From a4daaccacb1c6e2f93ddec37451fbf781a178000 Mon Sep 17 00:00:00 2001 From: Novus Nota <68142933+novusnota@users.noreply.github.com> Date: Mon, 22 Jul 2024 15:01:24 +0200 Subject: [PATCH] feat: explanation of `remaining` serialization format --- pages/book/cells.mdx | 43 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 4 deletions(-) diff --git a/pages/book/cells.mdx b/pages/book/cells.mdx index 1db35995..498f47fc 100644 --- a/pages/book/cells.mdx +++ b/pages/book/cells.mdx @@ -126,8 +126,7 @@ While you may use them for [manual parsing](#cnp-manually) of the cells, it's st Similar to serialization options of [`Int{:tact}`](/book/integers) type, `Cell{:tact}`, `Builder{:tact}` and `Slice{:tact}` also have various representations for encoding their values in the following cases: * as fields of [contracts](/book/contracts) and [traits](/book/types#traits), -* as fields of [Structs](/book/structs-and-messages#structs) and [Messages](/book/structs-and-messages#messages), -* and as key/value types of [maps](/book/maps). +* and as fields of [Structs](/book/structs-and-messages#structs) and [Messages](/book/structs-and-messages#messages). ```tact contract SerializationExample { @@ -136,11 +135,47 @@ contract SerializationExample { } ``` -### `remaining` [#serialization-bytes64] +### `remaining` [#serialization-remaining] + +By default, when it comes to storing values of [`Cell{:tact}`](#cells), [`Builder{:tact}`](#builders) and [`Slice{:tact}`](#slices) types in persistent storage of loading them from the received messages or assigned values, Tact's auto-layout algorithm uses references (refs): + +```tact +contract ReReReF { + c: Cell; // ^cell in TL-B notation + b: Builder; // ^builder in TL-B notation + s: Slice; // ^slice in TL-B notation +} +``` + +However, using `remaining{:tact}` makes values assigned to those fields to be stored directly as a [`Slice{:tact}`](#slices): + +```tact +contract RemRemRem { + c: Cell as remaining; // remainder in TL-B notation, + // storing and loading Slices directly in this Cell + + b: Builder as remaining; // remainder in TL-B notation, + // storing and loading Slices directly in this Builder + + s: Slice as remaining; // remainder in TL-B notation, + // storing and loading Slices directly +} +``` + +That's like using [`Builder.storeSlice(){:tact}`][b-5] and [`Slice.loadSlice(){:tact}`][s-5] over [`Builder.storeRef(){:tact}`][b-8] and [`Slice.loadRef(){:tact}`][s-8], which are to be used by default. In practice, this makes using `Slice as remaining{:tact}` the most [gas](https://docs.ton.org/develop/smart-contracts/fees#gas)-efficient option for working with [`Slice{:tact}`](#slices) values, since it uses the least amount of operations and bits. - To be resolved by [#26](https://github.com/tact-lang/tact-docs/issues/26). + Note, that the field serialized `as remaining{:tact}` cannot be [optional](/book/optional). That is, specifying something like `Cell? as remaining{:tact}` would cause a compilation error. + + Also note, that as of now, specifying `remaining{:tact}` for `Cell{:tact}` as the [map](/book/maps) value type doesn't do anything — the cell would still be stored as a reference: + + ```tact + struct Nope { + m: map; // dict in TL-B notation, + // despite the `remaining` + } + ```