EnumerableSet.sol 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. pragma solidity ^0.6.0;
  2. /**
  3. * @dev Library for managing
  4. * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
  5. * types.
  6. *
  7. * Sets have the following properties:
  8. *
  9. * - Elements are added, removed, and checked for existence in constant time
  10. * (O(1)).
  11. * - Elements are enumerated in O(n). No guarantees are made on the ordering.
  12. *
  13. * As of v2.5.0, only `address` sets are supported.
  14. *
  15. * Include with `using EnumerableSet for EnumerableSet.AddressSet;`.
  16. *
  17. * _Available since v2.5.0._
  18. *
  19. * @author Alberto Cuesta Cañada
  20. */
  21. library EnumerableSet {
  22. struct AddressSet {
  23. // Position of the value in the `values` array, plus 1 because index 0
  24. // means a value is not in the set.
  25. mapping (address => uint256) index;
  26. address[] values;
  27. }
  28. /**
  29. * @dev Add a value to a set. O(1).
  30. * Returns false if the value was already in the set.
  31. */
  32. function add(AddressSet storage set, address value)
  33. internal
  34. returns (bool)
  35. {
  36. if (!contains(set, value)) {
  37. set.values.push(value);
  38. // The element is stored at length-1, but we add 1 to all indexes
  39. // and use 0 as a sentinel value
  40. set.index[value] = set.values.length;
  41. return true;
  42. } else {
  43. return false;
  44. }
  45. }
  46. /**
  47. * @dev Removes a value from a set. O(1).
  48. * Returns false if the value was not present in the set.
  49. */
  50. function remove(AddressSet storage set, address value)
  51. internal
  52. returns (bool)
  53. {
  54. if (contains(set, value)){
  55. uint256 toDeleteIndex = set.index[value] - 1;
  56. uint256 lastIndex = set.values.length - 1;
  57. // If the element we're deleting is the last one, we can just remove it without doing a swap
  58. if (lastIndex != toDeleteIndex) {
  59. address lastValue = set.values[lastIndex];
  60. // Move the last value to the index where the deleted value is
  61. set.values[toDeleteIndex] = lastValue;
  62. // Update the index for the moved value
  63. set.index[lastValue] = toDeleteIndex + 1; // All indexes are 1-based
  64. }
  65. // Delete the index entry for the deleted value
  66. delete set.index[value];
  67. // Delete the old entry for the moved value
  68. set.values.pop();
  69. return true;
  70. } else {
  71. return false;
  72. }
  73. }
  74. /**
  75. * @dev Returns true if the value is in the set. O(1).
  76. */
  77. function contains(AddressSet storage set, address value)
  78. internal
  79. view
  80. returns (bool)
  81. {
  82. return set.index[value] != 0;
  83. }
  84. /**
  85. * @dev Returns an array with all values in the set. O(N).
  86. * Note that there are no guarantees on the ordering of values inside the
  87. * array, and it may change when more values are added or removed.
  88. * WARNING: This function may run out of gas on large sets: use {length} and
  89. * {get} instead in these cases.
  90. */
  91. function enumerate(AddressSet storage set)
  92. internal
  93. view
  94. returns (address[] memory)
  95. {
  96. address[] memory output = new address[](set.values.length);
  97. for (uint256 i; i < set.values.length; i++){
  98. output[i] = set.values[i];
  99. }
  100. return output;
  101. }
  102. /**
  103. * @dev Returns the number of elements on the set. O(1).
  104. */
  105. function length(AddressSet storage set)
  106. internal
  107. view
  108. returns (uint256)
  109. {
  110. return set.values.length;
  111. }
  112. /** @dev Returns the element stored at position `index` in the set. O(1).
  113. * Note that there are no guarantees on the ordering of values inside the
  114. * array, and it may change when more values are added or removed.
  115. *
  116. * Requirements:
  117. *
  118. * - `index` must be strictly less than {length}.
  119. */
  120. function get(AddressSet storage set, uint256 index)
  121. internal
  122. view
  123. returns (address)
  124. {
  125. return set.values[index];
  126. }
  127. }