123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- // SPDX-License-Identifier: MIT
- // OpenZeppelin Contracts (last updated v5.2.0-rc.0) (utils/Bytes.sol)
- pragma solidity ^0.8.24;
- import {Math} from "./math/Math.sol";
- /**
- * @dev Bytes operations.
- */
- library Bytes {
- /**
- * @dev Forward search for `s` in `buffer`
- * * If `s` is present in the buffer, returns the index of the first instance
- * * If `s` is not present in the buffer, returns type(uint256).max
- *
- * NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf[Javascript's `Array.indexOf`]
- */
- function indexOf(bytes memory buffer, bytes1 s) internal pure returns (uint256) {
- return indexOf(buffer, s, 0);
- }
- /**
- * @dev Forward search for `s` in `buffer` starting at position `pos`
- * * If `s` is present in the buffer (at or after `pos`), returns the index of the next instance
- * * If `s` is not present in the buffer (at or after `pos`), returns type(uint256).max
- *
- * NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf[Javascript's `Array.indexOf`]
- */
- function indexOf(bytes memory buffer, bytes1 s, uint256 pos) internal pure returns (uint256) {
- uint256 length = buffer.length;
- for (uint256 i = pos; i < length; ++i) {
- if (bytes1(_unsafeReadBytesOffset(buffer, i)) == s) {
- return i;
- }
- }
- return type(uint256).max;
- }
- /**
- * @dev Backward search for `s` in `buffer`
- * * If `s` is present in the buffer, returns the index of the last instance
- * * If `s` is not present in the buffer, returns type(uint256).max
- *
- * NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/lastIndexOf[Javascript's `Array.lastIndexOf`]
- */
- function lastIndexOf(bytes memory buffer, bytes1 s) internal pure returns (uint256) {
- return lastIndexOf(buffer, s, type(uint256).max);
- }
- /**
- * @dev Backward search for `s` in `buffer` starting at position `pos`
- * * If `s` is present in the buffer (at or before `pos`), returns the index of the previous instance
- * * If `s` is not present in the buffer (at or before `pos`), returns type(uint256).max
- *
- * NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/lastIndexOf[Javascript's `Array.lastIndexOf`]
- */
- function lastIndexOf(bytes memory buffer, bytes1 s, uint256 pos) internal pure returns (uint256) {
- unchecked {
- uint256 length = buffer.length;
- // NOTE here we cannot do `i = Math.min(pos + 1, length)` because `pos + 1` could overflow
- for (uint256 i = Math.min(pos, length - 1) + 1; i > 0; --i) {
- if (bytes1(_unsafeReadBytesOffset(buffer, i - 1)) == s) {
- return i - 1;
- }
- }
- return type(uint256).max;
- }
- }
- /**
- * @dev Copies the content of `buffer`, from `start` (included) to the end of `buffer` into a new bytes object in
- * memory.
- *
- * NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice[Javascript's `Array.slice`]
- */
- function slice(bytes memory buffer, uint256 start) internal pure returns (bytes memory) {
- return slice(buffer, start, buffer.length);
- }
- /**
- * @dev Copies the content of `buffer`, from `start` (included) to `end` (excluded) into a new bytes object in
- * memory.
- *
- * NOTE: replicates the behavior of https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice[Javascript's `Array.slice`]
- */
- function slice(bytes memory buffer, uint256 start, uint256 end) internal pure returns (bytes memory) {
- // sanitize
- uint256 length = buffer.length;
- end = Math.min(end, length);
- start = Math.min(start, end);
- // allocate and copy
- bytes memory result = new bytes(end - start);
- assembly ("memory-safe") {
- mcopy(add(result, 0x20), add(buffer, add(start, 0x20)), sub(end, start))
- }
- return result;
- }
- /**
- * @dev Reads a bytes32 from a bytes array without bounds checking.
- *
- * NOTE: making this function internal would mean it could be used with memory unsafe offset, and marking the
- * assembly block as such would prevent some optimizations.
- */
- function _unsafeReadBytesOffset(bytes memory buffer, uint256 offset) private pure returns (bytes32 value) {
- // This is not memory safe in the general case, but all calls to this private function are within bounds.
- assembly ("memory-safe") {
- value := mload(add(buffer, add(0x20, offset)))
- }
- }
- }
|