Add paginated version of EnumerableSet.values() and EnumerableMap.keys() (#5713)
Co-authored-by: ernestognw <ernestognw@gmail.com>
This commit is contained in:
@ -5,6 +5,7 @@
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
import {Arrays} from "../Arrays.sol";
|
||||
import {Math} from "../math/Math.sol";
|
||||
|
||||
/**
|
||||
* @dev Library for managing
|
||||
@ -176,6 +177,28 @@ library EnumerableSet {
|
||||
return set._values;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Return a slice of the set in an array
|
||||
*
|
||||
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
|
||||
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
|
||||
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
|
||||
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
|
||||
*/
|
||||
function _values(Set storage set, uint256 start, uint256 end) private view returns (bytes32[] memory) {
|
||||
unchecked {
|
||||
end = Math.min(end, _length(set));
|
||||
start = Math.min(start, end);
|
||||
|
||||
uint256 len = end - start;
|
||||
bytes32[] memory result = new bytes32[](len);
|
||||
for (uint256 i = 0; i < len; ++i) {
|
||||
result[i] = Arrays.unsafeAccess(set._values, start + i).value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// Bytes32Set
|
||||
|
||||
struct Bytes32Set {
|
||||
@ -259,6 +282,25 @@ library EnumerableSet {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Return a slice of the set in an array
|
||||
*
|
||||
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
|
||||
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
|
||||
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
|
||||
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
|
||||
*/
|
||||
function values(Bytes32Set storage set, uint256 start, uint256 end) internal view returns (bytes32[] memory) {
|
||||
bytes32[] memory store = _values(set._inner, start, end);
|
||||
bytes32[] memory result;
|
||||
|
||||
assembly ("memory-safe") {
|
||||
result := store
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// AddressSet
|
||||
|
||||
struct AddressSet {
|
||||
@ -342,6 +384,25 @@ library EnumerableSet {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Return a slice of the set in an array
|
||||
*
|
||||
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
|
||||
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
|
||||
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
|
||||
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
|
||||
*/
|
||||
function values(AddressSet storage set, uint256 start, uint256 end) internal view returns (address[] memory) {
|
||||
bytes32[] memory store = _values(set._inner, start, end);
|
||||
address[] memory result;
|
||||
|
||||
assembly ("memory-safe") {
|
||||
result := store
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// UintSet
|
||||
|
||||
struct UintSet {
|
||||
@ -425,6 +486,25 @@ library EnumerableSet {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Return a slice of the set in an array
|
||||
*
|
||||
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
|
||||
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
|
||||
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
|
||||
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
|
||||
*/
|
||||
function values(UintSet storage set, uint256 start, uint256 end) internal view returns (uint256[] memory) {
|
||||
bytes32[] memory store = _values(set._inner, start, end);
|
||||
uint256[] memory result;
|
||||
|
||||
assembly ("memory-safe") {
|
||||
result := store
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
struct StringSet {
|
||||
// Storage of set values
|
||||
string[] _values;
|
||||
@ -545,6 +625,28 @@ library EnumerableSet {
|
||||
return self._values;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Return a slice of the set in an array
|
||||
*
|
||||
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
|
||||
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
|
||||
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
|
||||
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
|
||||
*/
|
||||
function values(StringSet storage set, uint256 start, uint256 end) internal view returns (string[] memory) {
|
||||
unchecked {
|
||||
end = Math.min(end, length(set));
|
||||
start = Math.min(start, end);
|
||||
|
||||
uint256 len = end - start;
|
||||
string[] memory result = new string[](len);
|
||||
for (uint256 i = 0; i < len; ++i) {
|
||||
result[i] = Arrays.unsafeAccess(set._values, start + i).value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
struct BytesSet {
|
||||
// Storage of set values
|
||||
bytes[] _values;
|
||||
@ -664,4 +766,26 @@ library EnumerableSet {
|
||||
function values(BytesSet storage self) internal view returns (bytes[] memory) {
|
||||
return self._values;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Return a slice of the set in an array
|
||||
*
|
||||
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
|
||||
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
|
||||
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
|
||||
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
|
||||
*/
|
||||
function values(BytesSet storage set, uint256 start, uint256 end) internal view returns (bytes[] memory) {
|
||||
unchecked {
|
||||
end = Math.min(end, length(set));
|
||||
start = Math.min(start, end);
|
||||
|
||||
uint256 len = end - start;
|
||||
bytes[] memory result = new bytes[](len);
|
||||
for (uint256 i = 0; i < len; ++i) {
|
||||
result[i] = Arrays.unsafeAccess(set._values, start + i).value;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user