@@ -6,7 +6,6 @@ const header = `\
66pragma solidity ^0.8.20;
77
88import {Arrays} from "../Arrays.sol";
9- import {Hashes} from "../cryptography/Hashes.sol";
109
1110/**
1211 * @dev Library for managing
@@ -261,149 +260,14 @@ function values(${name} storage set) internal view returns (${type}[] memory) {
261260}
262261` ;
263262
264- const memorySet = ( { name, type } ) => `\
265- struct ${ name } {
266- // Storage of set values
267- ${ type } [] _values;
268- // Position is the index of the value in the \`values\` array plus 1.
269- // Position 0 is used to mean a value is not in the self.
270- mapping(bytes32 valueHash => uint256) _positions;
271- }
272-
273- /**
274- * @dev Add a value to a self. O(1).
275- *
276- * Returns true if the value was added to the set, that is if it was not
277- * already present.
278- */
279- function add(${ name } storage self, ${ type } memory value) internal returns (bool) {
280- if (!contains(self, value)) {
281- self._values.push(value);
282- // The value is stored at length-1, but we add 1 to all indexes
283- // and use 0 as a sentinel value
284- self._positions[_hash(value)] = self._values.length;
285- return true;
286- } else {
287- return false;
288- }
289- }
290-
291- /**
292- * @dev Removes a value from a self. O(1).
293- *
294- * Returns true if the value was removed from the set, that is if it was
295- * present.
296- */
297- function remove(${ name } storage self, ${ type } memory value) internal returns (bool) {
298- // We cache the value's position to prevent multiple reads from the same storage slot
299- bytes32 valueHash = _hash(value);
300- uint256 position = self._positions[valueHash];
301-
302- if (position != 0) {
303- // Equivalent to contains(self, value)
304- // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
305- // the array, and then remove the last element (sometimes called as 'swap and pop').
306- // This modifies the order of the array, as noted in {at}.
307-
308- uint256 valueIndex = position - 1;
309- uint256 lastIndex = self._values.length - 1;
310-
311- if (valueIndex != lastIndex) {
312- ${ type } memory lastValue = self._values[lastIndex];
313-
314- // Move the lastValue to the index where the value to delete is
315- self._values[valueIndex] = lastValue;
316- // Update the tracked position of the lastValue (that was just moved)
317- self._positions[_hash(lastValue)] = position;
318- }
319-
320- // Delete the slot where the moved value was stored
321- self._values.pop();
322-
323- // Delete the tracked position for the deleted slot
324- delete self._positions[valueHash];
325-
326- return true;
327- } else {
328- return false;
329- }
330- }
331-
332- /**
333- * @dev Removes all the values from a set. O(n).
334- *
335- * WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
336- * function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.
337- */
338- function clear(${ name } storage self) internal {
339- ${ type } [] storage v = self._values;
340-
341- uint256 len = length(self);
342- for (uint256 i = 0; i < len; ++i) {
343- delete self._positions[_hash(v[i])];
344- }
345- assembly ("memory-safe") {
346- sstore(v.slot, 0)
347- }
348- }
349-
350- /**
351- * @dev Returns true if the value is in the self. O(1).
352- */
353- function contains(${ name } storage self, ${ type } memory value) internal view returns (bool) {
354- return self._positions[_hash(value)] != 0;
355- }
356-
357- /**
358- * @dev Returns the number of values on the self. O(1).
359- */
360- function length(${ name } storage self) internal view returns (uint256) {
361- return self._values.length;
362- }
363-
364- /**
365- * @dev Returns the value stored at position \`index\` in the self. O(1).
366- *
367- * Note that there are no guarantees on the ordering of values inside the
368- * array, and it may change when more values are added or removed.
369- *
370- * Requirements:
371- *
372- * - \`index\` must be strictly less than {length}.
373- */
374- function at(${ name } storage self, uint256 index) internal view returns (${ type } memory) {
375- return self._values[index];
376- }
377-
378- /**
379- * @dev Return the entire set in an array
380- *
381- * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
382- * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
383- * this function has an unbounded cost, and using it as part of a state-changing function may render the function
384- * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
385- */
386- function values(${ name } storage self) internal view returns (${ type } [] memory) {
387- return self._values;
388- }
389- ` ;
390-
391- const hashes = `\
392- function _hash(bytes32[2] memory value) private pure returns (bytes32) {
393- return Hashes.efficientKeccak256(value[0], value[1]);
394- }
395- ` ;
396-
397263// GENERATE
398264module . exports = format (
399265 header . trimEnd ( ) ,
400266 'library EnumerableSet {' ,
401267 format (
402268 [ ] . concat (
403269 defaultSet ,
404- TYPES . filter ( ( { size } ) => size == undefined ) . map ( details => customSet ( details ) ) ,
405- TYPES . filter ( ( { size } ) => size != undefined ) . map ( details => memorySet ( details ) ) ,
406- hashes ,
270+ TYPES . map ( details => customSet ( details ) ) ,
407271 ) ,
408272 ) . trimEnd ( ) ,
409273 '}' ,
0 commit comments