diff --git a/e2e/packages/contracts/src/codegen/tables/Multi.sol b/e2e/packages/contracts/src/codegen/tables/Multi.sol index fd30c691ef..abab8c9590 100644 --- a/e2e/packages/contracts/src/codegen/tables/Multi.sol +++ b/e2e/packages/contracts/src/codegen/tables/Multi.sol @@ -233,8 +233,12 @@ library Multi { _keyTuple[2] = bytes32(uint256(c)); _keyTuple[3] = bytes32(uint256(int256(d))); - bytes memory _blob = StoreSwitch.getRecord(_tableId, _keyTuple, _fieldLayout); - return decode(_blob); + (bytes memory _staticData, PackedCounter _encodedLengths, bytes memory _dynamicData) = StoreSwitch.getRecord( + _tableId, + _keyTuple, + _fieldLayout + ); + return decode(_staticData, _encodedLengths, _dynamicData); } /** Get the full data */ @@ -245,8 +249,12 @@ library Multi { _keyTuple[2] = bytes32(uint256(c)); _keyTuple[3] = bytes32(uint256(int256(d))); - bytes memory _blob = StoreCore.getRecord(_tableId, _keyTuple, _fieldLayout); - return decode(_blob); + (bytes memory _staticData, PackedCounter _encodedLengths, bytes memory _dynamicData) = StoreCore.getRecord( + _tableId, + _keyTuple, + _fieldLayout + ); + return decode(_staticData, _encodedLengths, _dynamicData); } /** Get the full data (using the specified store) */ @@ -257,8 +265,12 @@ library Multi { _keyTuple[2] = bytes32(uint256(c)); _keyTuple[3] = bytes32(uint256(int256(d))); - bytes memory _blob = _store.getRecord(_tableId, _keyTuple, _fieldLayout); - return decode(_blob); + (bytes memory _staticData, PackedCounter _encodedLengths, bytes memory _dynamicData) = _store.getRecord( + _tableId, + _keyTuple, + _fieldLayout + ); + return decode(_staticData, _encodedLengths, _dynamicData); } /** Set the full data using individual values */ @@ -324,11 +336,26 @@ library Multi { set(_store, a, b, c, d, _table.num, _table.value); } - /** Decode the tightly packed blob using this table's field layout */ - function decode(bytes memory _blob) internal pure returns (MultiData memory _table) { - _table.num = (int256(uint256(Bytes.slice32(_blob, 0)))); + /** + * Decode the tightly packed blob of static data using this table's field layout + * Undefined behaviour for invalid blobs + */ + function decodeStatic(bytes memory _blob) internal pure returns (int256 num, bool value) { + num = (int256(uint256(Bytes.slice32(_blob, 0)))); - _table.value = (_toBool(uint8(Bytes.slice1(_blob, 32)))); + value = (_toBool(uint8(Bytes.slice1(_blob, 32)))); + } + + /** + * Decode the tightly packed blob using this table's field layout. + * Undefined behaviour for invalid blobs. + */ + function decode( + bytes memory _staticData, + PackedCounter, + bytes memory + ) internal pure returns (MultiData memory _table) { + (_table.num, _table.value) = decodeStatic(_staticData); } /** Tightly pack static data using this table's schema */ @@ -337,13 +364,13 @@ library Multi { } /** Tightly pack full data using this table's field layout */ - function encode(int256 num, bool value) internal pure returns (bytes memory) { + function encode(int256 num, bool value) internal pure returns (bytes memory, PackedCounter, bytes memory) { bytes memory _staticData = encodeStatic(num, value); PackedCounter _encodedLengths; bytes memory _dynamicData; - return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); + return (_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/e2e/packages/contracts/src/codegen/tables/Number.sol b/e2e/packages/contracts/src/codegen/tables/Number.sol index 77dcf598c3..b75e730224 100644 --- a/e2e/packages/contracts/src/codegen/tables/Number.sol +++ b/e2e/packages/contracts/src/codegen/tables/Number.sol @@ -131,13 +131,13 @@ library Number { } /** Tightly pack full data using this table's field layout */ - function encode(uint32 value) internal pure returns (bytes memory) { + function encode(uint32 value) internal pure returns (bytes memory, PackedCounter, bytes memory) { bytes memory _staticData = encodeStatic(value); PackedCounter _encodedLengths; bytes memory _dynamicData; - return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); + return (_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/e2e/packages/contracts/src/codegen/tables/NumberList.sol b/e2e/packages/contracts/src/codegen/tables/NumberList.sol index 2703550074..7b03f525db 100644 --- a/e2e/packages/contracts/src/codegen/tables/NumberList.sol +++ b/e2e/packages/contracts/src/codegen/tables/NumberList.sol @@ -285,12 +285,12 @@ library NumberList { } /** Tightly pack full data using this table's field layout */ - function encode(uint32[] memory value) internal pure returns (bytes memory) { + function encode(uint32[] memory value) internal pure returns (bytes memory, PackedCounter, bytes memory) { bytes memory _staticData; PackedCounter _encodedLengths = encodeLengths(value); bytes memory _dynamicData = encodeDynamic(value); - return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); + return (_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/e2e/packages/contracts/src/codegen/tables/Vector.sol b/e2e/packages/contracts/src/codegen/tables/Vector.sol index 380f222702..ee5dd92631 100644 --- a/e2e/packages/contracts/src/codegen/tables/Vector.sol +++ b/e2e/packages/contracts/src/codegen/tables/Vector.sol @@ -188,8 +188,12 @@ library Vector { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(key)); - bytes memory _blob = StoreSwitch.getRecord(_tableId, _keyTuple, _fieldLayout); - return decode(_blob); + (bytes memory _staticData, PackedCounter _encodedLengths, bytes memory _dynamicData) = StoreSwitch.getRecord( + _tableId, + _keyTuple, + _fieldLayout + ); + return decode(_staticData, _encodedLengths, _dynamicData); } /** Get the full data */ @@ -197,8 +201,12 @@ library Vector { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(key)); - bytes memory _blob = StoreCore.getRecord(_tableId, _keyTuple, _fieldLayout); - return decode(_blob); + (bytes memory _staticData, PackedCounter _encodedLengths, bytes memory _dynamicData) = StoreCore.getRecord( + _tableId, + _keyTuple, + _fieldLayout + ); + return decode(_staticData, _encodedLengths, _dynamicData); } /** Get the full data (using the specified store) */ @@ -206,8 +214,12 @@ library Vector { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = bytes32(uint256(key)); - bytes memory _blob = _store.getRecord(_tableId, _keyTuple, _fieldLayout); - return decode(_blob); + (bytes memory _staticData, PackedCounter _encodedLengths, bytes memory _dynamicData) = _store.getRecord( + _tableId, + _keyTuple, + _fieldLayout + ); + return decode(_staticData, _encodedLengths, _dynamicData); } /** Set the full data using individual values */ @@ -264,11 +276,26 @@ library Vector { set(_store, key, _table.x, _table.y); } - /** Decode the tightly packed blob using this table's field layout */ - function decode(bytes memory _blob) internal pure returns (VectorData memory _table) { - _table.x = (int32(uint32(Bytes.slice4(_blob, 0)))); + /** + * Decode the tightly packed blob of static data using this table's field layout + * Undefined behaviour for invalid blobs + */ + function decodeStatic(bytes memory _blob) internal pure returns (int32 x, int32 y) { + x = (int32(uint32(Bytes.slice4(_blob, 0)))); - _table.y = (int32(uint32(Bytes.slice4(_blob, 4)))); + y = (int32(uint32(Bytes.slice4(_blob, 4)))); + } + + /** + * Decode the tightly packed blob using this table's field layout. + * Undefined behaviour for invalid blobs. + */ + function decode( + bytes memory _staticData, + PackedCounter, + bytes memory + ) internal pure returns (VectorData memory _table) { + (_table.x, _table.y) = decodeStatic(_staticData); } /** Tightly pack static data using this table's schema */ @@ -277,13 +304,13 @@ library Vector { } /** Tightly pack full data using this table's field layout */ - function encode(int32 x, int32 y) internal pure returns (bytes memory) { + function encode(int32 x, int32 y) internal pure returns (bytes memory, PackedCounter, bytes memory) { bytes memory _staticData = encodeStatic(x, y); PackedCounter _encodedLengths; bytes memory _dynamicData; - return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); + return (_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/examples/minimal/packages/contracts/src/codegen/tables/CounterTable.sol b/examples/minimal/packages/contracts/src/codegen/tables/CounterTable.sol index 8cff969735..21056806b4 100644 --- a/examples/minimal/packages/contracts/src/codegen/tables/CounterTable.sol +++ b/examples/minimal/packages/contracts/src/codegen/tables/CounterTable.sol @@ -123,13 +123,13 @@ library CounterTable { } /** Tightly pack full data using this table's field layout */ - function encode(uint32 value) internal pure returns (bytes memory) { + function encode(uint32 value) internal pure returns (bytes memory, PackedCounter, bytes memory) { bytes memory _staticData = encodeStatic(value); PackedCounter _encodedLengths; bytes memory _dynamicData; - return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); + return (_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/examples/minimal/packages/contracts/src/codegen/tables/Inventory.sol b/examples/minimal/packages/contracts/src/codegen/tables/Inventory.sol index 8344c02274..38f67b2815 100644 --- a/examples/minimal/packages/contracts/src/codegen/tables/Inventory.sol +++ b/examples/minimal/packages/contracts/src/codegen/tables/Inventory.sol @@ -147,13 +147,13 @@ library Inventory { } /** Tightly pack full data using this table's field layout */ - function encode(uint32 amount) internal pure returns (bytes memory) { + function encode(uint32 amount) internal pure returns (bytes memory, PackedCounter, bytes memory) { bytes memory _staticData = encodeStatic(amount); PackedCounter _encodedLengths; bytes memory _dynamicData; - return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); + return (_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/examples/minimal/packages/contracts/src/codegen/tables/MessageTable.sol b/examples/minimal/packages/contracts/src/codegen/tables/MessageTable.sol index 9bcba034c6..48d6426ca7 100644 --- a/examples/minimal/packages/contracts/src/codegen/tables/MessageTable.sol +++ b/examples/minimal/packages/contracts/src/codegen/tables/MessageTable.sol @@ -119,12 +119,12 @@ library MessageTable { } /** Tightly pack full data using this table's field layout */ - function encode(string memory value) internal pure returns (bytes memory) { + function encode(string memory value) internal pure returns (bytes memory, PackedCounter, bytes memory) { bytes memory _staticData; PackedCounter _encodedLengths = encodeLengths(value); bytes memory _dynamicData = encodeDynamic(value); - return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); + return (_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/packages/cli/contracts/src/codegen/tables/Dynamics1.sol b/packages/cli/contracts/src/codegen/tables/Dynamics1.sol index 1b7dee5110..e2482100cd 100644 --- a/packages/cli/contracts/src/codegen/tables/Dynamics1.sol +++ b/packages/cli/contracts/src/codegen/tables/Dynamics1.sol @@ -1240,8 +1240,12 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getRecord(_tableId, _keyTuple, _fieldLayout); - return decode(_blob); + (bytes memory _staticData, PackedCounter _encodedLengths, bytes memory _dynamicData) = StoreSwitch.getRecord( + _tableId, + _keyTuple, + _fieldLayout + ); + return decode(_staticData, _encodedLengths, _dynamicData); } /** Get the full data */ @@ -1249,8 +1253,12 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreCore.getRecord(_tableId, _keyTuple, _fieldLayout); - return decode(_blob); + (bytes memory _staticData, PackedCounter _encodedLengths, bytes memory _dynamicData) = StoreCore.getRecord( + _tableId, + _keyTuple, + _fieldLayout + ); + return decode(_staticData, _encodedLengths, _dynamicData); } /** Get the full data (using the specified store) */ @@ -1258,8 +1266,12 @@ library Dynamics1 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getRecord(_tableId, _keyTuple, _fieldLayout); - return decode(_blob); + (bytes memory _staticData, PackedCounter _encodedLengths, bytes memory _dynamicData) = _store.getRecord( + _tableId, + _keyTuple, + _fieldLayout + ); + return decode(_staticData, _encodedLengths, _dynamicData); } /** Set the full data using individual values */ @@ -1335,48 +1347,69 @@ library Dynamics1 { set(_store, key, _table.staticB32, _table.staticI32, _table.staticU128, _table.staticAddrs, _table.staticBools); } + /** + * Decode the tightly packed blob of static data using this table's field layout + * Undefined behaviour for invalid blobs + */ + function decodeDynamic( + PackedCounter _encodedLengths, + bytes memory _blob + ) + internal + pure + returns ( + bytes32[1] memory staticB32, + int32[2] memory staticI32, + uint128[3] memory staticU128, + address[4] memory staticAddrs, + bool[5] memory staticBools + ) + { + uint256 _start; + uint256 _end; + unchecked { + _end = _encodedLengths.atIndex(0); + } + staticB32 = toStaticArray_bytes32_1(SliceLib.getSubslice(_blob, _start, _end).decodeArray_bytes32()); + + _start = _end; + unchecked { + _end += _encodedLengths.atIndex(1); + } + staticI32 = toStaticArray_int32_2(SliceLib.getSubslice(_blob, _start, _end).decodeArray_int32()); + + _start = _end; + unchecked { + _end += _encodedLengths.atIndex(2); + } + staticU128 = toStaticArray_uint128_3(SliceLib.getSubslice(_blob, _start, _end).decodeArray_uint128()); + + _start = _end; + unchecked { + _end += _encodedLengths.atIndex(3); + } + staticAddrs = toStaticArray_address_4(SliceLib.getSubslice(_blob, _start, _end).decodeArray_address()); + + _start = _end; + unchecked { + _end += _encodedLengths.atIndex(4); + } + staticBools = toStaticArray_bool_5(SliceLib.getSubslice(_blob, _start, _end).decodeArray_bool()); + } + /** * Decode the tightly packed blob using this table's field layout. * Undefined behaviour for invalid blobs. */ - function decode(bytes memory _blob) internal pure returns (Dynamics1Data memory _table) { - // 0 is the total byte length of static data - PackedCounter _encodedLengths = PackedCounter.wrap(Bytes.slice32(_blob, 0)); - - // Store trims the blob if dynamic fields are all empty - if (_blob.length > 0) { - // skip static data length + dynamic lengths word - uint256 _start = 32; - uint256 _end; - unchecked { - _end = 32 + _encodedLengths.atIndex(0); - } - _table.staticB32 = toStaticArray_bytes32_1(SliceLib.getSubslice(_blob, _start, _end).decodeArray_bytes32()); - - _start = _end; - unchecked { - _end += _encodedLengths.atIndex(1); - } - _table.staticI32 = toStaticArray_int32_2(SliceLib.getSubslice(_blob, _start, _end).decodeArray_int32()); - - _start = _end; - unchecked { - _end += _encodedLengths.atIndex(2); - } - _table.staticU128 = toStaticArray_uint128_3(SliceLib.getSubslice(_blob, _start, _end).decodeArray_uint128()); - - _start = _end; - unchecked { - _end += _encodedLengths.atIndex(3); - } - _table.staticAddrs = toStaticArray_address_4(SliceLib.getSubslice(_blob, _start, _end).decodeArray_address()); - - _start = _end; - unchecked { - _end += _encodedLengths.atIndex(4); - } - _table.staticBools = toStaticArray_bool_5(SliceLib.getSubslice(_blob, _start, _end).decodeArray_bool()); - } + function decode( + bytes memory, + PackedCounter _encodedLengths, + bytes memory _dynamicData + ) internal pure returns (Dynamics1Data memory _table) { + (_table.staticB32, _table.staticI32, _table.staticU128, _table.staticAddrs, _table.staticBools) = decodeDynamic( + _encodedLengths, + _dynamicData + ); } /** Tightly pack dynamic data using this table's schema */ @@ -1424,12 +1457,12 @@ library Dynamics1 { uint128[3] memory staticU128, address[4] memory staticAddrs, bool[5] memory staticBools - ) internal pure returns (bytes memory) { + ) internal pure returns (bytes memory, PackedCounter, bytes memory) { bytes memory _staticData; PackedCounter _encodedLengths = encodeLengths(staticB32, staticI32, staticU128, staticAddrs, staticBools); bytes memory _dynamicData = encodeDynamic(staticB32, staticI32, staticU128, staticAddrs, staticBools); - return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); + return (_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/packages/cli/contracts/src/codegen/tables/Dynamics2.sol b/packages/cli/contracts/src/codegen/tables/Dynamics2.sol index 77371f92a7..c587e088ea 100644 --- a/packages/cli/contracts/src/codegen/tables/Dynamics2.sol +++ b/packages/cli/contracts/src/codegen/tables/Dynamics2.sol @@ -749,8 +749,12 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getRecord(_tableId, _keyTuple, _fieldLayout); - return decode(_blob); + (bytes memory _staticData, PackedCounter _encodedLengths, bytes memory _dynamicData) = StoreSwitch.getRecord( + _tableId, + _keyTuple, + _fieldLayout + ); + return decode(_staticData, _encodedLengths, _dynamicData); } /** Get the full data */ @@ -758,8 +762,12 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreCore.getRecord(_tableId, _keyTuple, _fieldLayout); - return decode(_blob); + (bytes memory _staticData, PackedCounter _encodedLengths, bytes memory _dynamicData) = StoreCore.getRecord( + _tableId, + _keyTuple, + _fieldLayout + ); + return decode(_staticData, _encodedLengths, _dynamicData); } /** Get the full data (using the specified store) */ @@ -767,8 +775,12 @@ library Dynamics2 { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getRecord(_tableId, _keyTuple, _fieldLayout); - return decode(_blob); + (bytes memory _staticData, PackedCounter _encodedLengths, bytes memory _dynamicData) = _store.getRecord( + _tableId, + _keyTuple, + _fieldLayout + ); + return decode(_staticData, _encodedLengths, _dynamicData); } /** Set the full data using individual values */ @@ -822,36 +834,44 @@ library Dynamics2 { set(_store, key, _table.u64, _table.str, _table.b); } + /** + * Decode the tightly packed blob of static data using this table's field layout + * Undefined behaviour for invalid blobs + */ + function decodeDynamic( + PackedCounter _encodedLengths, + bytes memory _blob + ) internal pure returns (uint64[] memory u64, string memory str, bytes memory b) { + uint256 _start; + uint256 _end; + unchecked { + _end = _encodedLengths.atIndex(0); + } + u64 = (SliceLib.getSubslice(_blob, _start, _end).decodeArray_uint64()); + + _start = _end; + unchecked { + _end += _encodedLengths.atIndex(1); + } + str = (string(SliceLib.getSubslice(_blob, _start, _end).toBytes())); + + _start = _end; + unchecked { + _end += _encodedLengths.atIndex(2); + } + b = (bytes(SliceLib.getSubslice(_blob, _start, _end).toBytes())); + } + /** * Decode the tightly packed blob using this table's field layout. * Undefined behaviour for invalid blobs. */ - function decode(bytes memory _blob) internal pure returns (Dynamics2Data memory _table) { - // 0 is the total byte length of static data - PackedCounter _encodedLengths = PackedCounter.wrap(Bytes.slice32(_blob, 0)); - - // Store trims the blob if dynamic fields are all empty - if (_blob.length > 0) { - // skip static data length + dynamic lengths word - uint256 _start = 32; - uint256 _end; - unchecked { - _end = 32 + _encodedLengths.atIndex(0); - } - _table.u64 = (SliceLib.getSubslice(_blob, _start, _end).decodeArray_uint64()); - - _start = _end; - unchecked { - _end += _encodedLengths.atIndex(1); - } - _table.str = (string(SliceLib.getSubslice(_blob, _start, _end).toBytes())); - - _start = _end; - unchecked { - _end += _encodedLengths.atIndex(2); - } - _table.b = (bytes(SliceLib.getSubslice(_blob, _start, _end).toBytes())); - } + function decode( + bytes memory, + PackedCounter _encodedLengths, + bytes memory _dynamicData + ) internal pure returns (Dynamics2Data memory _table) { + (_table.u64, _table.str, _table.b) = decodeDynamic(_encodedLengths, _dynamicData); } /** Tightly pack dynamic data using this table's schema */ @@ -872,12 +892,16 @@ library Dynamics2 { } /** Tightly pack full data using this table's field layout */ - function encode(uint64[] memory u64, string memory str, bytes memory b) internal pure returns (bytes memory) { + function encode( + uint64[] memory u64, + string memory str, + bytes memory b + ) internal pure returns (bytes memory, PackedCounter, bytes memory) { bytes memory _staticData; PackedCounter _encodedLengths = encodeLengths(u64, str, b); bytes memory _dynamicData = encodeDynamic(u64, str, b); - return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); + return (_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/packages/cli/contracts/src/codegen/tables/Ephemeral.sol b/packages/cli/contracts/src/codegen/tables/Ephemeral.sol index 04e78e2503..dae46bfb71 100644 --- a/packages/cli/contracts/src/codegen/tables/Ephemeral.sol +++ b/packages/cli/contracts/src/codegen/tables/Ephemeral.sol @@ -119,13 +119,13 @@ library Ephemeral { } /** Tightly pack full data using this table's field layout */ - function encode(uint256 value) internal pure returns (bytes memory) { + function encode(uint256 value) internal pure returns (bytes memory, PackedCounter, bytes memory) { bytes memory _staticData = encodeStatic(value); PackedCounter _encodedLengths; bytes memory _dynamicData; - return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); + return (_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/packages/cli/contracts/src/codegen/tables/Singleton.sol b/packages/cli/contracts/src/codegen/tables/Singleton.sol index 3db7f72067..5d8d466a6c 100644 --- a/packages/cli/contracts/src/codegen/tables/Singleton.sol +++ b/packages/cli/contracts/src/codegen/tables/Singleton.sol @@ -724,16 +724,24 @@ library Singleton { function get() internal view returns (int256 v1, uint32[2] memory v2, uint32[2] memory v3, uint32[1] memory v4) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = StoreSwitch.getRecord(_tableId, _keyTuple, _fieldLayout); - return decode(_blob); + (bytes memory _staticData, PackedCounter _encodedLengths, bytes memory _dynamicData) = StoreSwitch.getRecord( + _tableId, + _keyTuple, + _fieldLayout + ); + return decode(_staticData, _encodedLengths, _dynamicData); } /** Get the full data */ function _get() internal view returns (int256 v1, uint32[2] memory v2, uint32[2] memory v3, uint32[1] memory v4) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = StoreCore.getRecord(_tableId, _keyTuple, _fieldLayout); - return decode(_blob); + (bytes memory _staticData, PackedCounter _encodedLengths, bytes memory _dynamicData) = StoreCore.getRecord( + _tableId, + _keyTuple, + _fieldLayout + ); + return decode(_staticData, _encodedLengths, _dynamicData); } /** Get the full data (using the specified store) */ @@ -742,8 +750,12 @@ library Singleton { ) internal view returns (int256 v1, uint32[2] memory v2, uint32[2] memory v3, uint32[1] memory v4) { bytes32[] memory _keyTuple = new bytes32[](0); - bytes memory _blob = _store.getRecord(_tableId, _keyTuple, _fieldLayout); - return decode(_blob); + (bytes memory _staticData, PackedCounter _encodedLengths, bytes memory _dynamicData) = _store.getRecord( + _tableId, + _keyTuple, + _fieldLayout + ); + return decode(_staticData, _encodedLengths, _dynamicData); } /** Set the full data using individual values */ @@ -782,40 +794,54 @@ library Singleton { _store.setRecord(_tableId, _keyTuple, _staticData, _encodedLengths, _dynamicData, _fieldLayout); } + /** + * Decode the tightly packed blob of static data using this table's field layout + * Undefined behaviour for invalid blobs + */ + function decodeStatic(bytes memory _blob) internal pure returns (int256 v1) { + v1 = (int256(uint256(Bytes.slice32(_blob, 0)))); + } + + /** + * Decode the tightly packed blob of static data using this table's field layout + * Undefined behaviour for invalid blobs + */ + function decodeDynamic( + PackedCounter _encodedLengths, + bytes memory _blob + ) internal pure returns (uint32[2] memory v2, uint32[2] memory v3, uint32[1] memory v4) { + uint256 _start; + uint256 _end; + unchecked { + _end = _encodedLengths.atIndex(0); + } + v2 = toStaticArray_uint32_2(SliceLib.getSubslice(_blob, _start, _end).decodeArray_uint32()); + + _start = _end; + unchecked { + _end += _encodedLengths.atIndex(1); + } + v3 = toStaticArray_uint32_2(SliceLib.getSubslice(_blob, _start, _end).decodeArray_uint32()); + + _start = _end; + unchecked { + _end += _encodedLengths.atIndex(2); + } + v4 = toStaticArray_uint32_1(SliceLib.getSubslice(_blob, _start, _end).decodeArray_uint32()); + } + /** * Decode the tightly packed blob using this table's field layout. * Undefined behaviour for invalid blobs. */ function decode( - bytes memory _blob + bytes memory _staticData, + PackedCounter _encodedLengths, + bytes memory _dynamicData ) internal pure returns (int256 v1, uint32[2] memory v2, uint32[2] memory v3, uint32[1] memory v4) { - // 32 is the total byte length of static data - PackedCounter _encodedLengths = PackedCounter.wrap(Bytes.slice32(_blob, 32)); - - v1 = (int256(uint256(Bytes.slice32(_blob, 0)))); + (v1) = decodeStatic(_staticData); - // Store trims the blob if dynamic fields are all empty - if (_blob.length > 32) { - // skip static data length + dynamic lengths word - uint256 _start = 64; - uint256 _end; - unchecked { - _end = 64 + _encodedLengths.atIndex(0); - } - v2 = toStaticArray_uint32_2(SliceLib.getSubslice(_blob, _start, _end).decodeArray_uint32()); - - _start = _end; - unchecked { - _end += _encodedLengths.atIndex(1); - } - v3 = toStaticArray_uint32_2(SliceLib.getSubslice(_blob, _start, _end).decodeArray_uint32()); - - _start = _end; - unchecked { - _end += _encodedLengths.atIndex(2); - } - v4 = toStaticArray_uint32_1(SliceLib.getSubslice(_blob, _start, _end).decodeArray_uint32()); - } + (v2, v3, v4) = decodeDynamic(_encodedLengths, _dynamicData); } /** Tightly pack static data using this table's schema */ @@ -855,13 +881,13 @@ library Singleton { uint32[2] memory v2, uint32[2] memory v3, uint32[1] memory v4 - ) internal pure returns (bytes memory) { + ) internal pure returns (bytes memory, PackedCounter, bytes memory) { bytes memory _staticData = encodeStatic(v1); PackedCounter _encodedLengths = encodeLengths(v2, v3, v4); bytes memory _dynamicData = encodeDynamic(v2, v3, v4); - return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); + return (_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/packages/cli/contracts/src/codegen/tables/Statics.sol b/packages/cli/contracts/src/codegen/tables/Statics.sol index b65c03db2f..8a911d7d46 100644 --- a/packages/cli/contracts/src/codegen/tables/Statics.sol +++ b/packages/cli/contracts/src/codegen/tables/Statics.sol @@ -657,8 +657,12 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - bytes memory _blob = StoreSwitch.getRecord(_tableId, _keyTuple, _fieldLayout); - return decode(_blob); + (bytes memory _staticData, PackedCounter _encodedLengths, bytes memory _dynamicData) = StoreSwitch.getRecord( + _tableId, + _keyTuple, + _fieldLayout + ); + return decode(_staticData, _encodedLengths, _dynamicData); } /** Get the full data */ @@ -678,8 +682,12 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - bytes memory _blob = StoreCore.getRecord(_tableId, _keyTuple, _fieldLayout); - return decode(_blob); + (bytes memory _staticData, PackedCounter _encodedLengths, bytes memory _dynamicData) = StoreCore.getRecord( + _tableId, + _keyTuple, + _fieldLayout + ); + return decode(_staticData, _encodedLengths, _dynamicData); } /** Get the full data (using the specified store) */ @@ -700,8 +708,12 @@ library Statics { _keyTuple[4] = _boolToBytes32(k5); _keyTuple[5] = bytes32(uint256(uint8(k6))); - bytes memory _blob = _store.getRecord(_tableId, _keyTuple, _fieldLayout); - return decode(_blob); + (bytes memory _staticData, PackedCounter _encodedLengths, bytes memory _dynamicData) = _store.getRecord( + _tableId, + _keyTuple, + _fieldLayout + ); + return decode(_staticData, _encodedLengths, _dynamicData); } /** Set the full data using individual values */ @@ -822,19 +834,36 @@ library Statics { set(_store, k1, k2, k3, k4, k5, k6, _table.v1, _table.v2, _table.v3, _table.v4, _table.v5, _table.v6); } - /** Decode the tightly packed blob using this table's field layout */ - function decode(bytes memory _blob) internal pure returns (StaticsData memory _table) { - _table.v1 = (uint256(Bytes.slice32(_blob, 0))); + /** + * Decode the tightly packed blob of static data using this table's field layout + * Undefined behaviour for invalid blobs + */ + function decodeStatic( + bytes memory _blob + ) internal pure returns (uint256 v1, int32 v2, bytes16 v3, address v4, bool v5, Enum1 v6) { + v1 = (uint256(Bytes.slice32(_blob, 0))); - _table.v2 = (int32(uint32(Bytes.slice4(_blob, 32)))); + v2 = (int32(uint32(Bytes.slice4(_blob, 32)))); - _table.v3 = (Bytes.slice16(_blob, 36)); + v3 = (Bytes.slice16(_blob, 36)); - _table.v4 = (address(Bytes.slice20(_blob, 52))); + v4 = (address(Bytes.slice20(_blob, 52))); - _table.v5 = (_toBool(uint8(Bytes.slice1(_blob, 72)))); + v5 = (_toBool(uint8(Bytes.slice1(_blob, 72)))); - _table.v6 = Enum1(uint8(Bytes.slice1(_blob, 73))); + v6 = Enum1(uint8(Bytes.slice1(_blob, 73))); + } + + /** + * Decode the tightly packed blob using this table's field layout. + * Undefined behaviour for invalid blobs. + */ + function decode( + bytes memory _staticData, + PackedCounter, + bytes memory + ) internal pure returns (StaticsData memory _table) { + (_table.v1, _table.v2, _table.v3, _table.v4, _table.v5, _table.v6) = decodeStatic(_staticData); } /** Tightly pack static data using this table's schema */ @@ -857,13 +886,13 @@ library Statics { address v4, bool v5, Enum1 v6 - ) internal pure returns (bytes memory) { + ) internal pure returns (bytes memory, PackedCounter, bytes memory) { bytes memory _staticData = encodeStatic(v1, v2, v3, v4, v5, v6); PackedCounter _encodedLengths; bytes memory _dynamicData; - return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); + return (_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/templates/phaser/packages/contracts/src/codegen/tables/Counter.sol b/templates/phaser/packages/contracts/src/codegen/tables/Counter.sol index 24ba4c5d0f..e6ebcd912f 100644 --- a/templates/phaser/packages/contracts/src/codegen/tables/Counter.sol +++ b/templates/phaser/packages/contracts/src/codegen/tables/Counter.sol @@ -123,13 +123,13 @@ library Counter { } /** Tightly pack full data using this table's field layout */ - function encode(uint32 value) internal pure returns (bytes memory) { + function encode(uint32 value) internal pure returns (bytes memory, PackedCounter, bytes memory) { bytes memory _staticData = encodeStatic(value); PackedCounter _encodedLengths; bytes memory _dynamicData; - return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); + return (_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/templates/react/packages/contracts/src/codegen/tables/Counter.sol b/templates/react/packages/contracts/src/codegen/tables/Counter.sol index 24ba4c5d0f..e6ebcd912f 100644 --- a/templates/react/packages/contracts/src/codegen/tables/Counter.sol +++ b/templates/react/packages/contracts/src/codegen/tables/Counter.sol @@ -123,13 +123,13 @@ library Counter { } /** Tightly pack full data using this table's field layout */ - function encode(uint32 value) internal pure returns (bytes memory) { + function encode(uint32 value) internal pure returns (bytes memory, PackedCounter, bytes memory) { bytes memory _staticData = encodeStatic(value); PackedCounter _encodedLengths; bytes memory _dynamicData; - return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); + return (_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/templates/threejs/packages/contracts/src/codegen/tables/Position.sol b/templates/threejs/packages/contracts/src/codegen/tables/Position.sol index 1ea72f6f0b..b747e01351 100644 --- a/templates/threejs/packages/contracts/src/codegen/tables/Position.sol +++ b/templates/threejs/packages/contracts/src/codegen/tables/Position.sol @@ -242,8 +242,12 @@ library Position { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreSwitch.getRecord(_tableId, _keyTuple, _fieldLayout); - return decode(_blob); + (bytes memory _staticData, PackedCounter _encodedLengths, bytes memory _dynamicData) = StoreSwitch.getRecord( + _tableId, + _keyTuple, + _fieldLayout + ); + return decode(_staticData, _encodedLengths, _dynamicData); } /** Get the full data */ @@ -251,8 +255,12 @@ library Position { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = StoreCore.getRecord(_tableId, _keyTuple, _fieldLayout); - return decode(_blob); + (bytes memory _staticData, PackedCounter _encodedLengths, bytes memory _dynamicData) = StoreCore.getRecord( + _tableId, + _keyTuple, + _fieldLayout + ); + return decode(_staticData, _encodedLengths, _dynamicData); } /** Get the full data (using the specified store) */ @@ -260,8 +268,12 @@ library Position { bytes32[] memory _keyTuple = new bytes32[](1); _keyTuple[0] = key; - bytes memory _blob = _store.getRecord(_tableId, _keyTuple, _fieldLayout); - return decode(_blob); + (bytes memory _staticData, PackedCounter _encodedLengths, bytes memory _dynamicData) = _store.getRecord( + _tableId, + _keyTuple, + _fieldLayout + ); + return decode(_staticData, _encodedLengths, _dynamicData); } /** Set the full data using individual values */ @@ -318,13 +330,28 @@ library Position { set(_store, key, _table.x, _table.y, _table.z); } - /** Decode the tightly packed blob using this table's field layout */ - function decode(bytes memory _blob) internal pure returns (PositionData memory _table) { - _table.x = (int32(uint32(Bytes.slice4(_blob, 0)))); + /** + * Decode the tightly packed blob of static data using this table's field layout + * Undefined behaviour for invalid blobs + */ + function decodeStatic(bytes memory _blob) internal pure returns (int32 x, int32 y, int32 z) { + x = (int32(uint32(Bytes.slice4(_blob, 0)))); - _table.y = (int32(uint32(Bytes.slice4(_blob, 4)))); + y = (int32(uint32(Bytes.slice4(_blob, 4)))); - _table.z = (int32(uint32(Bytes.slice4(_blob, 8)))); + z = (int32(uint32(Bytes.slice4(_blob, 8)))); + } + + /** + * Decode the tightly packed blob using this table's field layout. + * Undefined behaviour for invalid blobs. + */ + function decode( + bytes memory _staticData, + PackedCounter, + bytes memory + ) internal pure returns (PositionData memory _table) { + (_table.x, _table.y, _table.z) = decodeStatic(_staticData); } /** Tightly pack static data using this table's schema */ @@ -333,13 +360,13 @@ library Position { } /** Tightly pack full data using this table's field layout */ - function encode(int32 x, int32 y, int32 z) internal pure returns (bytes memory) { + function encode(int32 x, int32 y, int32 z) internal pure returns (bytes memory, PackedCounter, bytes memory) { bytes memory _staticData = encodeStatic(x, y, z); PackedCounter _encodedLengths; bytes memory _dynamicData; - return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); + return (_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */ diff --git a/templates/vanilla/packages/contracts/src/codegen/tables/Counter.sol b/templates/vanilla/packages/contracts/src/codegen/tables/Counter.sol index 24ba4c5d0f..e6ebcd912f 100644 --- a/templates/vanilla/packages/contracts/src/codegen/tables/Counter.sol +++ b/templates/vanilla/packages/contracts/src/codegen/tables/Counter.sol @@ -123,13 +123,13 @@ library Counter { } /** Tightly pack full data using this table's field layout */ - function encode(uint32 value) internal pure returns (bytes memory) { + function encode(uint32 value) internal pure returns (bytes memory, PackedCounter, bytes memory) { bytes memory _staticData = encodeStatic(value); PackedCounter _encodedLengths; bytes memory _dynamicData; - return abi.encodePacked(_staticData, _encodedLengths, _dynamicData); + return (_staticData, _encodedLengths, _dynamicData); } /** Encode keys as a bytes32 array using this table's field layout */