solidity-scale-codec 0.1.1 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +2 -0
  2. package/package.json +3 -1
  3. package/src/LittleEndian/LittleEndianU128.sol +49 -0
  4. package/src/LittleEndian/LittleEndianU16.sol +29 -0
  5. package/src/LittleEndian/LittleEndianU256.sol +101 -0
  6. package/src/LittleEndian/LittleEndianU32.sol +42 -0
  7. package/src/LittleEndian/LittleEndianU64.sol +45 -0
  8. package/src/LittleEndian/LittleEndianU8.sol +26 -0
  9. package/src/Scale/Array/BoolArr.sol +49 -35
  10. package/src/Scale/Array/I128Arr.sol +49 -35
  11. package/src/Scale/Array/I16Arr.sol +49 -35
  12. package/src/Scale/Array/I256Arr.sol +49 -35
  13. package/src/Scale/Array/I32Arr.sol +49 -35
  14. package/src/Scale/Array/I64Arr.sol +49 -35
  15. package/src/Scale/Array/I8Arr.sol +49 -35
  16. package/src/Scale/Array/U128Arr.sol +49 -35
  17. package/src/Scale/Array/U16Arr.sol +49 -35
  18. package/src/Scale/Array/U256Arr.sol +49 -35
  19. package/src/Scale/Array/U32Arr.sol +49 -35
  20. package/src/Scale/Array/U64Arr.sol +49 -35
  21. package/src/Scale/Array/U8Arr.sol +49 -35
  22. package/src/Scale/Array.sol +14 -15
  23. package/src/Scale/Bool/Bool.sol +1 -1
  24. package/src/Scale/Bool.sol +1 -1
  25. package/src/Scale/Compact/Compact.sol +89 -460
  26. package/src/Scale/Compact.sol +1 -1
  27. package/src/Scale/Signed/I128.sol +13 -6
  28. package/src/Scale/Signed/I16.sol +10 -5
  29. package/src/Scale/Signed/I256.sol +13 -6
  30. package/src/Scale/Signed/I32.sol +10 -5
  31. package/src/Scale/Signed/I64.sol +10 -5
  32. package/src/Scale/Signed/I8.sol +10 -5
  33. package/src/Scale/Signed.sol +7 -8
  34. package/src/Scale/Unsigned/U128.sol +15 -9
  35. package/src/Scale/Unsigned/U16.sol +15 -9
  36. package/src/Scale/Unsigned/U256.sol +15 -9
  37. package/src/Scale/Unsigned/U32.sol +15 -9
  38. package/src/Scale/Unsigned/U64.sol +15 -9
  39. package/src/Scale/Unsigned/U8.sol +13 -9
  40. package/src/Scale/Unsigned.sol +7 -8
  41. package/src/Utils/LittleEndian/LittleEndian.sol +0 -354
package/README.md CHANGED
@@ -20,6 +20,8 @@ This library provides a Highly-Modular implementation of SCALE in solidity.
20
20
  | `Compact` | A "compact" or general integer encoding is sufficient for encoding large integers (up to 2\*\*536) and is more efficient at encoding most values than the fixed-width version. (Though for single-byte values, the fixed-width integer is never worse.) | `0` | `0x00` |
21
21
  | `Arrays` | A collection of same-typed values is encoded, prefixed with a compact encoding of the number of items, followed by each item's encoding concatenated in turn. Currently `[uintN]`,`[intN]`, `[bool]` are supported. | `[1,0]` | `0x080100` |
22
22
 
23
+ See the [Definitions](definitions.md) for more details on the encoding of different types.
24
+
23
25
  ## Usage
24
26
 
25
27
  ## Encode Structs
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "solidity-scale-codec",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Solidity implementation of scale-codec.",
5
5
  "keywords": [
6
6
  "solidity",
@@ -36,6 +36,8 @@
36
36
  "@types/node": "^22.19.1",
37
37
  "forge-std": "github:foundry-rs/forge-std#v1.9.4",
38
38
  "hardhat": "^3.0.15",
39
+ "prettier": "^3.8.1",
40
+ "prettier-plugin-solidity": "^2.2.1",
39
41
  "typescript": "~5.8.0",
40
42
  "viem": "^2.40.3"
41
43
  }
@@ -0,0 +1,49 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ pragma solidity ^0.8.28;
3
+
4
+ /// @title LittleEndianU128
5
+ /// @notice Gas-optimized library for converting U128 from big-endian to little-endian
6
+ library LittleEndianU128 {
7
+ /// @notice Converts a `uint128` to little-endian `bytes16`
8
+ /// @param value The `uint128` value to convert.
9
+ /// @return result The little-endian representation of the input `uint128` as a `bytes16`.
10
+ function toLE(uint128 value) internal pure returns (bytes16 result) {
11
+ assembly {
12
+ let v := value
13
+ v := or(
14
+ shl(8, and(v, 0x00FF00FF00FF00FF00FF00FF00FF00FF)),
15
+ shr(8, and(v, 0xFF00FF00FF00FF00FF00FF00FF00FF00))
16
+ )
17
+ v := or(
18
+ shl(16, and(v, 0x0000FFFF0000FFFF0000FFFF0000FFFF)),
19
+ shr(16, and(v, 0xFFFF0000FFFF0000FFFF0000FFFF0000))
20
+ )
21
+ v := or(
22
+ shl(32, and(v, 0x00000000FFFFFFFF00000000FFFFFFFF)),
23
+ shr(32, and(v, 0xFFFFFFFF00000000FFFFFFFF00000000))
24
+ )
25
+ v := or(shl(64, v), shr(64, v))
26
+ result := shl(128, v)
27
+ }
28
+ }
29
+
30
+ /// @notice Reads a uint128 from `data` at `offset` (little-endian, 16 bytes).
31
+ /// @param data Raw byte buffer.
32
+ /// @param offset Byte offset into `data`.
33
+ /// @return value Decoded uint128.
34
+ function fromLE(
35
+ bytes memory data,
36
+ uint256 offset
37
+ ) internal pure returns (uint128 value) {
38
+ assembly {
39
+ let ptr := add(add(data, 32), offset)
40
+ for {
41
+ let i := 0
42
+ } lt(i, 16) {
43
+ i := add(i, 1)
44
+ } {
45
+ value := or(value, shl(mul(i, 8), shr(248, mload(add(ptr, i)))))
46
+ }
47
+ }
48
+ }
49
+ }
@@ -0,0 +1,29 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ pragma solidity ^0.8.28;
3
+
4
+ /// @title LittleEndianU16
5
+ /// @notice Gas-optimized library for converting U16 from big-endian to little-endian
6
+ library LittleEndianU16 {
7
+ /// @notice Converts a `uint16` to little-endian `bytes2`
8
+ /// @param value The `uint16` value to convert
9
+ /// @return result The little-endian representation of the input `uint16` as a `bytes2`
10
+ function toLE(uint16 value) internal pure returns (bytes2) {
11
+ return bytes2(uint16((value >> 8) | (value << 8)));
12
+ }
13
+
14
+ /// @notice Reads a uint16 from `data` at `offset` (little-endian, 2 bytes).
15
+ /// @param data Raw byte buffer.
16
+ /// @param offset Byte offset into `data`.
17
+ /// @return value Decoded uint16.
18
+ function fromLE(
19
+ bytes memory data,
20
+ uint256 offset
21
+ ) internal pure returns (uint16 value) {
22
+ assembly {
23
+ let ptr := add(add(data, 32), offset)
24
+ let b0 := shr(248, mload(ptr))
25
+ let b1 := shr(248, mload(add(ptr, 1)))
26
+ value := or(b0, shl(8, b1))
27
+ }
28
+ }
29
+ }
@@ -0,0 +1,101 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ pragma solidity ^0.8.28;
3
+
4
+ /// @title LittleEndianU256
5
+ /// @notice Gas-optimized library for converting U256 from big-endian to little-endian
6
+ library LittleEndianU256 {
7
+ /// @notice Converts a `uint256` to little-endian `bytes32`
8
+ /// @param value The `uint256` value to convert.
9
+ /// @return result The little-endian representation of the input `uint256` as a `bytes32`.
10
+ function toLE(uint256 value) internal pure returns (bytes32 result) {
11
+ assembly {
12
+ let v := value
13
+ v := or(
14
+ shl(
15
+ 8,
16
+ and(
17
+ v,
18
+ 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF
19
+ )
20
+ ),
21
+ shr(
22
+ 8,
23
+ and(
24
+ v,
25
+ 0xFF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00
26
+ )
27
+ )
28
+ )
29
+ v := or(
30
+ shl(
31
+ 16,
32
+ and(
33
+ v,
34
+ 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF
35
+ )
36
+ ),
37
+ shr(
38
+ 16,
39
+ and(
40
+ v,
41
+ 0xFFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000
42
+ )
43
+ )
44
+ )
45
+ v := or(
46
+ shl(
47
+ 32,
48
+ and(
49
+ v,
50
+ 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF
51
+ )
52
+ ),
53
+ shr(
54
+ 32,
55
+ and(
56
+ v,
57
+ 0xFFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000
58
+ )
59
+ )
60
+ )
61
+ v := or(
62
+ shl(
63
+ 64,
64
+ and(
65
+ v,
66
+ 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF
67
+ )
68
+ ),
69
+ shr(
70
+ 64,
71
+ and(
72
+ v,
73
+ 0xFFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF0000000000000000
74
+ )
75
+ )
76
+ )
77
+ v := or(shl(128, v), shr(128, v))
78
+ result := v
79
+ }
80
+ }
81
+
82
+ /// @notice Reads a uint256 from `data` at `offset` (little-endian, 32 bytes).
83
+ /// @param data Raw byte buffer.
84
+ /// @param offset Byte offset into `data`.
85
+ /// @return value Decoded uint256.
86
+ function fromLE(
87
+ bytes memory data,
88
+ uint256 offset
89
+ ) internal pure returns (uint256 value) {
90
+ assembly {
91
+ let ptr := add(add(data, 32), offset)
92
+ for {
93
+ let i := 0
94
+ } lt(i, 32) {
95
+ i := add(i, 1)
96
+ } {
97
+ value := or(value, shl(mul(i, 8), shr(248, mload(add(ptr, i)))))
98
+ }
99
+ }
100
+ }
101
+ }
@@ -0,0 +1,42 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ pragma solidity ^0.8.28;
3
+
4
+ /// @title LittleEndianU32
5
+ /// @notice Gas-optimized library for converting U32 from big-endian to little-endian
6
+ library LittleEndianU32 {
7
+ /// @notice Converts a `uint32` to little-endian `bytes4`
8
+ /// @param value The `uint32` value to convert
9
+ /// @return result The little-endian representation of the input `uint32` as a `bytes4`
10
+ function toLE(uint32 value) internal pure returns (bytes4 result) {
11
+ assembly {
12
+ let v := or(
13
+ or(
14
+ shl(24, and(value, 0xff)),
15
+ shl(16, and(shr(8, value), 0xff))
16
+ ),
17
+ or(shl(8, and(shr(16, value), 0xff)), and(shr(24, value), 0xff))
18
+ )
19
+ result := shl(224, v) // Shift to bytes4 position (left-align in 256-bit word)
20
+ }
21
+ }
22
+
23
+ /// @notice Reads a uint32 from `data` at `offset` (little-endian, 4 bytes).
24
+ /// @param data Raw byte buffer.
25
+ /// @param offset Byte offset into `data`.
26
+ /// @return value Decoded uint32.
27
+ function fromLE(
28
+ bytes memory data,
29
+ uint256 offset
30
+ ) internal pure returns (uint32 value) {
31
+ assembly {
32
+ let ptr := add(add(data, 32), offset)
33
+ for {
34
+ let i := 0
35
+ } lt(i, 4) {
36
+ i := add(i, 1)
37
+ } {
38
+ value := or(value, shl(mul(i, 8), shr(248, mload(add(ptr, i)))))
39
+ }
40
+ }
41
+ }
42
+ }
@@ -0,0 +1,45 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ pragma solidity ^0.8.28;
3
+
4
+ /// @title LittleEndianU64
5
+ /// @notice Gas-optimized library for converting U64 from big-endian to little-endian
6
+ library LittleEndianU64 {
7
+ /// @notice Converts a `uint64` to little-endian `bytes8`
8
+ /// @param value The `uint64` value to convert.
9
+ /// @return result The little-endian representation of the input `uint64` as a `bytes8`.
10
+ function toLE(uint64 value) internal pure returns (bytes8 result) {
11
+ assembly {
12
+ let v := value
13
+ v := or(
14
+ shl(8, and(v, 0x00FF00FF00FF00FF)),
15
+ shr(8, and(v, 0xFF00FF00FF00FF00))
16
+ )
17
+ v := or(
18
+ shl(16, and(v, 0x0000FFFF0000FFFF)),
19
+ shr(16, and(v, 0xFFFF0000FFFF0000))
20
+ )
21
+ v := or(shl(32, v), shr(32, v))
22
+ result := shl(192, v)
23
+ }
24
+ }
25
+
26
+ /// @notice Reads a uint64 from `data` at `offset` (little-endian, 8 bytes).
27
+ /// @param data Raw byte buffer.
28
+ /// @param offset Byte offset into `data`.
29
+ /// @return value Decoded uint64.
30
+ function fromLE(
31
+ bytes memory data,
32
+ uint256 offset
33
+ ) internal pure returns (uint64 value) {
34
+ assembly {
35
+ let ptr := add(add(data, 32), offset)
36
+ for {
37
+ let i := 0
38
+ } lt(i, 8) {
39
+ i := add(i, 1)
40
+ } {
41
+ value := or(value, shl(mul(i, 8), shr(248, mload(add(ptr, i)))))
42
+ }
43
+ }
44
+ }
45
+ }
@@ -0,0 +1,26 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ pragma solidity ^0.8.28;
3
+
4
+ /// @title LittleEndianU8
5
+ /// @notice Gas-optimized library for converting U8 from big-endian to little-endian
6
+ library LittleEndianU8 {
7
+ /// @notice Converts a `uint8` to little-endian `bytes1`
8
+ /// @param value The `uint8` value to convert.
9
+ /// @return result The little-endian representation of the input `uint8` as a `bytes1`.
10
+ function toLE(uint8 value) internal pure returns (bytes1) {
11
+ return bytes1(value);
12
+ }
13
+
14
+ /// @notice Reads a uint8 from `data` at `offset`.
15
+ /// @param data Raw byte buffer.
16
+ /// @param offset Byte offset into `data`.
17
+ /// @return value Decoded uint8.
18
+ function fromLE(
19
+ bytes memory data,
20
+ uint256 offset
21
+ ) internal pure returns (uint8 value) {
22
+ assembly {
23
+ value := shr(248, mload(add(add(data, 32), offset)))
24
+ }
25
+ }
26
+ }
@@ -1,44 +1,58 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
- pragma solidity ^0.8.20;
2
+ pragma solidity ^0.8.28;
3
3
 
4
4
  import {Compact} from "../Compact/Compact.sol";
5
- import { Bool } from "../Bool.sol";
5
+ import {Bool} from "../Bool.sol";
6
6
 
7
7
  /// @title Scale Codec for the `bool[]` type.
8
8
  /// @notice SCALE-compliant encoder/decoder for the `bool[]` type.
9
9
  /// @dev SCALE reference: https://docs.polkadot.com/polkadot-protocol/basics/data-encoding
10
10
  library BoolArr {
11
- using Bool for bool;
12
-
13
- /// @notice Encodes an `bool[]` into SCALE format.
14
- function encode(bool[] memory arr) internal pure returns (bytes memory) {
15
- bytes memory result = Compact.encode(arr.length);
16
- for (uint256 i = 0; i < arr.length; i++) {
17
- result = bytes.concat(result, arr[i].encode());
18
- }
19
- return result;
20
- }
21
-
22
- /// @notice Decodes an `bool[]` from SCALE format.
23
- function decode(bytes memory data)
24
- internal pure returns (bool[] memory arr, uint256 bytesRead)
25
- {
26
- return decodeAt(data, 0);
27
- }
28
-
29
- /// @notice Decodes an `bool[]` from SCALE format.
30
- function decodeAt(bytes memory data, uint256 offset)
31
- internal pure returns (bool[] memory arr, uint256 bytesRead)
32
- {
33
- (uint256 length, uint256 compactBytes) = Compact.decodeAt(data, offset);
34
- uint256 pos = offset + compactBytes;
35
-
36
- arr = new bool[](length);
37
- for (uint256 i = 0; i < length; i++) {
38
- arr[i] = Bool.decodeAt(data, pos);
39
- pos += 1;
40
- }
41
-
42
- bytesRead = pos - offset;
43
- }
11
+ error InvalidBoolArrLenght();
12
+
13
+ using Bool for bool;
14
+
15
+ /// @notice Encodes an `bool[]` into SCALE format.
16
+ /// @param arr The array of `bool` to encode.
17
+ /// @return SCALE-encoded byte sequence.
18
+ function encode(bool[] memory arr) internal pure returns (bytes memory) {
19
+ bytes memory result = Compact.encode(arr.length);
20
+ for (uint256 i = 0; i < arr.length; ++i) {
21
+ result = bytes.concat(result, arr[i].encode());
22
+ }
23
+ return result;
24
+ }
25
+
26
+ /// @notice Decodes an `bool[]` from SCALE format.
27
+ /// @param data The SCALE-encoded byte sequence.
28
+ /// @return arr The decoded array of `bool`.
29
+ /// @return bytesRead The total number of bytes read during decoding.
30
+ function decode(
31
+ bytes memory data
32
+ ) internal pure returns (bool[] memory arr, uint256 bytesRead) {
33
+ return decodeAt(data, 0);
34
+ }
35
+
36
+ /// @notice Decodes an `bool[]` from SCALE format at the specified offset.
37
+ /// @param data The SCALE-encoded byte sequence.
38
+ /// @param offset The byte offset to start decoding from.
39
+ /// @return arr The decoded array of `bool`.
40
+ /// @return bytesRead The total number of bytes read during decoding.
41
+ function decodeAt(
42
+ bytes memory data,
43
+ uint256 offset
44
+ ) internal pure returns (bool[] memory arr, uint256 bytesRead) {
45
+ (uint256 length, uint256 compactBytes) = Compact.decodeAt(data, offset);
46
+ uint256 pos = offset + compactBytes;
47
+
48
+ if (pos + (length * 1) > data.length) revert InvalidBoolArrLenght();
49
+
50
+ arr = new bool[](length);
51
+ for (uint256 i = 0; i < length; ++i) {
52
+ arr[i] = Bool.decodeAt(data, pos);
53
+ pos += 1;
54
+ }
55
+
56
+ bytesRead = pos - offset;
57
+ }
44
58
  }
@@ -1,44 +1,58 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
- pragma solidity ^0.8.20;
2
+ pragma solidity ^0.8.28;
3
3
 
4
4
  import {Compact} from "../Compact/Compact.sol";
5
- import { I128 } from "../Signed.sol";
5
+ import {I128} from "../Signed.sol";
6
6
 
7
7
  /// @title Scale Codec for the `int128[]` type.
8
8
  /// @notice SCALE-compliant encoder/decoder for the `int128[]` type.
9
9
  /// @dev SCALE reference: https://docs.polkadot.com/polkadot-protocol/basics/data-encoding
10
10
  library I128Arr {
11
- using I128 for int128;
12
-
13
- /// @notice Encodes an `int128[]` into SCALE format.
14
- function encode(int128[] memory arr) internal pure returns (bytes memory) {
15
- bytes memory result = Compact.encode(arr.length);
16
- for (uint256 i = 0; i < arr.length; i++) {
17
- result = bytes.concat(result, arr[i].encode());
18
- }
19
- return result;
20
- }
21
-
22
- /// @notice Decodes an `int128[]` from SCALE format.
23
- function decode(bytes memory data)
24
- internal pure returns (int128[] memory arr, uint256 bytesRead)
25
- {
26
- return decodeAt(data, 0);
27
- }
28
-
29
- /// @notice Decodes an `int128[]` from SCALE format.
30
- function decodeAt(bytes memory data, uint256 offset)
31
- internal pure returns (int128[] memory arr, uint256 bytesRead)
32
- {
33
- (uint256 length, uint256 compactBytes) = Compact.decodeAt(data, offset);
34
- uint256 pos = offset + compactBytes;
35
-
36
- arr = new int128[](length);
37
- for (uint256 i = 0; i < length; i++) {
38
- arr[i] = I128.decodeAt(data, pos);
39
- pos += 16;
40
- }
41
-
42
- bytesRead = pos - offset;
43
- }
11
+ error InvalidI128ArrLenght();
12
+
13
+ using I128 for int128;
14
+
15
+ /// @notice Encodes an `int128[]` into SCALE format.
16
+ /// @param arr The array of `int128` to encode.
17
+ /// @return SCALE-encoded byte sequence.
18
+ function encode(int128[] memory arr) internal pure returns (bytes memory) {
19
+ bytes memory result = Compact.encode(arr.length);
20
+ for (uint256 i = 0; i < arr.length; ++i) {
21
+ result = bytes.concat(result, arr[i].encode());
22
+ }
23
+ return result;
24
+ }
25
+
26
+ /// @notice Decodes an `int128[]` from SCALE format.
27
+ /// @param data The SCALE-encoded byte sequence.
28
+ /// @return arr The decoded array of `int128`.
29
+ /// @return bytesRead The total number of bytes read during decoding.
30
+ function decode(
31
+ bytes memory data
32
+ ) internal pure returns (int128[] memory arr, uint256 bytesRead) {
33
+ return decodeAt(data, 0);
34
+ }
35
+
36
+ /// @notice Decodes an `int128[]` from SCALE format at the specified offset.
37
+ /// @param data The SCALE-encoded byte sequence.
38
+ /// @param offset The byte offset to start decoding from.
39
+ /// @return arr The decoded array of `int128`.
40
+ /// @return bytesRead The total number of bytes read during decoding.
41
+ function decodeAt(
42
+ bytes memory data,
43
+ uint256 offset
44
+ ) internal pure returns (int128[] memory arr, uint256 bytesRead) {
45
+ (uint256 length, uint256 compactBytes) = Compact.decodeAt(data, offset);
46
+ uint256 pos = offset + compactBytes;
47
+
48
+ if (pos + (length * 16) > data.length) revert InvalidI128ArrLenght();
49
+
50
+ arr = new int128[](length);
51
+ for (uint256 i = 0; i < length; ++i) {
52
+ arr[i] = I128.decodeAt(data, pos);
53
+ pos += 16;
54
+ }
55
+
56
+ bytesRead = pos - offset;
57
+ }
44
58
  }
@@ -1,44 +1,58 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
- pragma solidity ^0.8.20;
2
+ pragma solidity ^0.8.28;
3
3
 
4
4
  import {Compact} from "../Compact/Compact.sol";
5
- import { I16 } from "../Signed.sol";
5
+ import {I16} from "../Signed.sol";
6
6
 
7
7
  /// @title Scale Codec for the `int16[]` type.
8
8
  /// @notice SCALE-compliant encoder/decoder for the `int16[]` type.
9
9
  /// @dev SCALE reference: https://docs.polkadot.com/polkadot-protocol/basics/data-encoding
10
10
  library I16Arr {
11
- using I16 for int16;
12
-
13
- /// @notice Encodes an `int16[]` into SCALE format.
14
- function encode(int16[] memory arr) internal pure returns (bytes memory) {
15
- bytes memory result = Compact.encode(arr.length);
16
- for (uint256 i = 0; i < arr.length; i++) {
17
- result = bytes.concat(result, arr[i].encode());
18
- }
19
- return result;
20
- }
21
-
22
- /// @notice Decodes an `int16[]` from SCALE format.
23
- function decode(bytes memory data)
24
- internal pure returns (int16[] memory arr, uint256 bytesRead)
25
- {
26
- return decodeAt(data, 0);
27
- }
28
-
29
- /// @notice Decodes an `int16[]` from SCALE format.
30
- function decodeAt(bytes memory data, uint256 offset)
31
- internal pure returns (int16[] memory arr, uint256 bytesRead)
32
- {
33
- (uint256 length, uint256 compactBytes) = Compact.decodeAt(data, offset);
34
- uint256 pos = offset + compactBytes;
35
-
36
- arr = new int16[](length);
37
- for (uint256 i = 0; i < length; i++) {
38
- arr[i] = I16.decodeAt(data, pos);
39
- pos += 2;
40
- }
41
-
42
- bytesRead = pos - offset;
43
- }
11
+ error InvalidI16ArrLenght();
12
+
13
+ using I16 for int16;
14
+
15
+ /// @notice Encodes an `int16[]` into SCALE format.
16
+ /// @param arr The array of `int16` to encode.
17
+ /// @return SCALE-encoded byte sequence.
18
+ function encode(int16[] memory arr) internal pure returns (bytes memory) {
19
+ bytes memory result = Compact.encode(arr.length);
20
+ for (uint256 i = 0; i < arr.length; ++i) {
21
+ result = bytes.concat(result, arr[i].encode());
22
+ }
23
+ return result;
24
+ }
25
+
26
+ /// @notice Decodes an `int16[]` from SCALE format.
27
+ /// @param data The SCALE-encoded byte sequence.
28
+ /// @return arr The decoded array of `int16`.
29
+ /// @return bytesRead The total number of bytes read during decoding.
30
+ function decode(
31
+ bytes memory data
32
+ ) internal pure returns (int16[] memory arr, uint256 bytesRead) {
33
+ return decodeAt(data, 0);
34
+ }
35
+
36
+ /// @notice Decodes an `int16[]` from SCALE format at the specified offset.
37
+ /// @param data The SCALE-encoded byte sequence.
38
+ /// @param offset The byte offset to start decoding from.
39
+ /// @return arr The decoded array of `int16`.
40
+ /// @return bytesRead The total number of bytes read during decoding.
41
+ function decodeAt(
42
+ bytes memory data,
43
+ uint256 offset
44
+ ) internal pure returns (int16[] memory arr, uint256 bytesRead) {
45
+ (uint256 length, uint256 compactBytes) = Compact.decodeAt(data, offset);
46
+ uint256 pos = offset + compactBytes;
47
+
48
+ if (pos + (length * 2) > data.length) revert InvalidI16ArrLenght();
49
+
50
+ arr = new int16[](length);
51
+ for (uint256 i = 0; i < length; ++i) {
52
+ arr[i] = I16.decodeAt(data, pos);
53
+ pos += 2;
54
+ }
55
+
56
+ bytesRead = pos - offset;
57
+ }
44
58
  }