@@ -39,6 +39,7 @@ import {EnumerableSet} from "./EnumerableSet.sol";
39
39
* - `address -> address` (`AddressToAddressMap`) since v5.1.0
40
40
* - `address -> bytes32` (`AddressToBytes32Map`) since v5.1.0
41
41
* - `bytes32 -> address` (`Bytes32ToAddressMap`) since v5.1.0
42
+ * - `bytes -> bytes` (`BytesToBytesMap`) since v5.4.0
42
43
*
43
44
* [WARNING]
44
45
* ====
@@ -51,7 +52,7 @@ import {EnumerableSet} from "./EnumerableSet.sol";
51
52
* ====
52
53
*/
53
54
library EnumerableMap {
54
- using EnumerableSet for EnumerableSet.Bytes32Set ;
55
+ using EnumerableSet for * ;
55
56
56
57
// To implement this library for multiple types with as little code repetition as possible, we write it in
57
58
// terms of a generic Map type with bytes32 keys and values. The Map implementation uses private functions,
@@ -997,4 +998,122 @@ library EnumerableMap {
997
998
998
999
return result;
999
1000
}
1001
+
1002
+ /**
1003
+ * @dev Query for a nonexistent map key.
1004
+ */
1005
+ error EnumerableMapNonexistentBytesKey (bytes key );
1006
+
1007
+ struct BytesToBytesMap {
1008
+ // Storage of keys
1009
+ EnumerableSet.BytesSet _keys;
1010
+ mapping (bytes key = > bytes ) _values;
1011
+ }
1012
+
1013
+ /**
1014
+ * @dev Adds a key-value pair to a map, or updates the value for an existing
1015
+ * key. O(1).
1016
+ *
1017
+ * Returns true if the key was added to the map, that is if it was not
1018
+ * already present.
1019
+ */
1020
+ function set (BytesToBytesMap storage map , bytes memory key , bytes memory value ) internal returns (bool ) {
1021
+ map._values[key] = value;
1022
+ return map._keys.add (key);
1023
+ }
1024
+
1025
+ /**
1026
+ * @dev Removes a key-value pair from a map. O(1).
1027
+ *
1028
+ * Returns true if the key was removed from the map, that is if it was present.
1029
+ */
1030
+ function remove (BytesToBytesMap storage map , bytes memory key ) internal returns (bool ) {
1031
+ delete map._values[key];
1032
+ return map._keys.remove (key);
1033
+ }
1034
+
1035
+ /**
1036
+ * @dev Removes all the entries from a map. O(n).
1037
+ *
1038
+ * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
1039
+ * function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block.
1040
+ */
1041
+ function clear (BytesToBytesMap storage map ) internal {
1042
+ uint256 len = length (map);
1043
+ for (uint256 i = 0 ; i < len; ++ i) {
1044
+ delete map._values[map._keys.at (i)];
1045
+ }
1046
+ map._keys.clear ();
1047
+ }
1048
+
1049
+ /**
1050
+ * @dev Returns true if the key is in the map. O(1).
1051
+ */
1052
+ function contains (BytesToBytesMap storage map , bytes memory key ) internal view returns (bool ) {
1053
+ return map._keys.contains (key);
1054
+ }
1055
+
1056
+ /**
1057
+ * @dev Returns the number of key-value pairs in the map. O(1).
1058
+ */
1059
+ function length (BytesToBytesMap storage map ) internal view returns (uint256 ) {
1060
+ return map._keys.length ();
1061
+ }
1062
+
1063
+ /**
1064
+ * @dev Returns the key-value pair stored at position `index` in the map. O(1).
1065
+ *
1066
+ * Note that there are no guarantees on the ordering of entries inside the
1067
+ * array, and it may change when more entries are added or removed.
1068
+ *
1069
+ * Requirements:
1070
+ *
1071
+ * - `index` must be strictly less than {length}.
1072
+ */
1073
+ function at (
1074
+ BytesToBytesMap storage map ,
1075
+ uint256 index
1076
+ ) internal view returns (bytes memory key , bytes memory value ) {
1077
+ key = map._keys.at (index);
1078
+ value = map._values[key];
1079
+ }
1080
+
1081
+ /**
1082
+ * @dev Tries to returns the value associated with `key`. O(1).
1083
+ * Does not revert if `key` is not in the map.
1084
+ */
1085
+ function tryGet (
1086
+ BytesToBytesMap storage map ,
1087
+ bytes memory key
1088
+ ) internal view returns (bool exists , bytes memory value ) {
1089
+ value = map._values[key];
1090
+ exists = bytes (value).length != 0 || contains (map, key);
1091
+ }
1092
+
1093
+ /**
1094
+ * @dev Returns the value associated with `key`. O(1).
1095
+ *
1096
+ * Requirements:
1097
+ *
1098
+ * - `key` must be in the map.
1099
+ */
1100
+ function get (BytesToBytesMap storage map , bytes memory key ) internal view returns (bytes memory value ) {
1101
+ bool exists;
1102
+ (exists, value) = tryGet (map, key);
1103
+ if (! exists) {
1104
+ revert EnumerableMapNonexistentBytesKey (key);
1105
+ }
1106
+ }
1107
+
1108
+ /**
1109
+ * @dev Return the an array containing all the keys
1110
+ *
1111
+ * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
1112
+ * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
1113
+ * this function has an unbounded cost, and using it as part of a state-changing function may render the function
1114
+ * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block.
1115
+ */
1116
+ function keys (BytesToBytesMap storage map ) internal view returns (bytes [] memory ) {
1117
+ return map._keys.values ();
1118
+ }
1000
1119
}
0 commit comments