# Cells, slices, builders (https://docs-dmpho5eos-ton-core-docs.vercel.app/llms/tolk/types/cells/content.md)



In TON, all data is stored in and represented as *cells*.

Tolk provides low-level functions for constructing and parsing cells manually, as well as [automatic serialization](/llms/languages/tolk/features/auto-serialization/content.md) of structures to and from cells.

## Cells [#cells]

[Cells](/llms/foundations/serialization/cells/content.md) are a data structure that can hold up to 1023 bits of data and up to 4 references to other cells. They are read-only and immutable once created.

### Untyped cells [#untyped-cells]

The basic type `cell` describes an untyped cell:

```tolk
struct SomeMessage {
    // ...
    customPayload: cell
}
```

### Typed cells [#typed-cells]

`Cell<T>` represents a cell with known internal structure. Since a single cell stores at most 1023 bits, larger data is split across multiple cells that sequentially reference each other. Circular references are not allowed.

```tolk
struct Demo {
    ref1: cell //          untyped reference
    ref2: Cell<Inner> //   typed ref
    ref3: Cell<int256>? // maybe ref
}
```

The `toCell()` method on struct instances produces values of type `Cell<STRUCT_NAME>`. However, any typed cell can be assigned to an untyped `cell` directly.

## Slices [#slices]

A cell opened for reading is called a *slice*. They allow loading data from cells.

To read data from a cell manually, call `beginParse()` to get a slice:

```tolk
var s = cell.beginParse();
```

Then load data incrementally: integers, coins, sub-slices, references, etc.

```tolk
val mode = s.loadUint(8);
val dest = s.loadAddress();
val firstRef = s.loadRef();   // cell

if (s.remainingBitsCount()) {
   // ...
}
```

### Prefer distinct slice types [#prefer-distinct-slice-types]

Builders and slices are low-level primitives for constructing and parsing cells. The values of `builder` and `slice` types contain raw binary data.

As such, reading an arbitrary `slice` or `builder` from another `slice` is impossible:

```tolk
struct CantBeRead {
    before: int8
    s: slice
    after: int8
}
```

An attempt to call `CantBeRead.fromCell(c)` fires an error: "Can not be deserialized, because `CantBeRead.s` is `slice`".

Express the shape of data using the type system and fixed-size slices to make serialization distinct. For example, use `s: bits100` to hold a slice containing at most 100 bits.

### Fixed-size slices [#fixed-size-slices]

The `slice` type cannot be serialized, but the `bitsN` types, such as `bits32` or `bytes8`, can. At runtime, `bitsN` is a regular slice, just how `int32` are regular TVM integers.

```tolk
struct OkayToRead {
    before: int8
    s: bits100
    after: int8
}

fun read(c: cell) {
    // a cell `c` is expected to be 116 bits
    val r = OkayToRead.fromCell(c);
    // on the stack: INT, SLICE, INT
}
```

To cast `slice` to `bitsN`, use the unsafe `as` operator. This is intentional: slices may have refs, so explicit casting forces consideration of whether the transformation is valid.

At runtime, this is a no-op:

```tolk
fun calcHash(raw: bits512) {
    // ...
}

fun demo() {
    calcHash(someSlice);                   // error
    calcHash(someSlice as bits512);        // ok

    someBytes.loadAddress();               // error
    (someBytes as slice).loadAddress();    // ok
}
```

### Embed constant slices into a contract [#embed-constant-slices-into-a-contract]

<Callout type="note">
  Tolk has a dedicated [`string`](/llms/languages/tolk/types/strings/content.md) type backed by snake-encoded cells. The examples below show how to embed constant slices with low-level binary data.
</Callout>

Use `"...".literalSlice()` to create a constant slice from a string literal:

```tolk
// a slice with 4 bytes: 97,98,99,100 (0x61626364)
const SLICE1 = "abcd".literalSlice()
```

Use `"<HEX_BYTES>".hexToSlice()` to embed hexadecimal binary data:

```tolk
// a slice with 2 bytes: 16,32 (0x1020)
const SLICE2 = "1020".hexToSlice()
```

## Builders [#builders]

A cell under construction is called a *builder*. They allow composing new cells.

To construct a cell manually, create a builder, write data to it, then finalize:

```tolk
var b = beginCell();
b.storeUint(123, 8);
b.storeAddress(dest);
val c = b.endCell();
```

Methods named `storeXYZ` return `self`, which is a builder, so calls can be chained:

```tolk
val c = beginCell()
    .storeUint(123, 8)
    .storeAddress(dest)
    .endCell();
```

### Read from a builder [#read-from-a-builder]

The only way to access bits already written to a builder is to convert it into a slice:

```tolk
var s = b.toSlice();
// or (exactly the same)
var s = b.endCell().beginParse();
```

Constructing a cell is generally expensive in terms of gas, but `b.endCell().beginParse()` is optimized and does not create intermediate cells.

## Automatic construction and parsing [#automatic-construction-and-parsing]

Structures are [auto-serializable](/llms/languages/tolk/features/auto-serialization/content.md) to and from cells when their fields are well-typed. Prefer using structures over manual work with builders and slices.

### Marshall to and from cells [#marshall-to-and-from-cells]

```tolk
struct Something {
    // ...
}

fun parseAndModify(c: cell): cell {
    var smth = Something.fromCell(c)
    // ...
    return smth.toCell()
}
```

For `Cell<T>`, call `load()` to get a value of type `T`:

```tolk
fun parsePoint(c: Cell<Point>) {
    // same as `Point.fromCell(c)`
    var p = c.load();
}
```

Internally, `fromCell()` calls `beginParse()` and reads data from a slice.

### Marshall to and from builders and slices [#marshall-to-and-from-builders-and-slices]

A struct can be parsed not only from a cell but also from a slice:

```tolk
val smth = Something.fromSlice(s);
```

In addition to `loadUint()` and similar methods, there is `loadAny<T>()`:

```tolk
val smth = s.loadAny<Something>();
// or
val smth: Something = s.loadAny(); // with T deduced as Something
```

<Callout type="note">
  Notice that `T.fromSlice(s)` does not mutate a slice `s`, while `s.loadAny<T>()` does. This is due to how Tolk handles [mutability](/llms/languages/tolk/syntax/mutability/content.md): all `s.loadXYZ()` methods mutate a slice, but functions in the form `doSomething(s)` do not.
</Callout>

Similarly, `storeAny<T>()` for a builder accepts any serializable value:

```tolk
beginCell()
    .storeAddress(dest)
    .storeAny(smth)         // T=Something deduced
    .storeUint(123, 8);
```

Both `loadAny<T>()` and `storeAny<T>()` work with arbitrary types, not only with structures:

```tolk
s.loadAny<int32>();           // same as loadInt(32)
s.loadAny<(coins, bool?)>();  // read a pair (a tensor)

b.storeAny(someAddress);      // same as storeAddress
b.storeAny(0xFF as uint8);    // same as storeUint(0xFF, 8)
```

## Remaining slice when reading [#remaining-slice-when-reading]

A common pattern is to read a portion of data and then retrieve the remainder. With manual parsing, this happens naturally:

```tolk
val ownerId = s.loadUint(32);
val dest = s.loadAddress();
// `s` contains all bits/refs still unread
val payload = s;
```

To express the same with structures, use the special type `RemainingBitsAndRefs`:

```tolk
struct WithPayload {
    ownerId: uint32
    dest: address
    payload: RemainingBitsAndRefs
}
```

Then, `obj = WithPayload.fromSlice(s)` is a structure instance where `obj.payload` contains all bits and refs left as a `slice`.

A field with this type must appear last in a struct: no more data exists after reading it.

## Stack layout and serialization [#stack-layout-and-serialization]

Structure fields of `cell` and `Cell<T>` types which are [serialized](/llms/languages/tolk/types/overall-serialization/content.md) as references to corresponding [TVM](/llms/languages/tolk/types/overall-tvm-stack/content.md) cells, with nullable types `?` serialized as 0 when the value is `null` and 1, followed by the cell reference otherwise.

The primitive types `builder` and `slice` cannot be serialized. Use `bitsN` and `RemainingBitsAndRefs` types instead.
