> Aztec.nr API reference, v6.0.0 (mainnet and testnet). Index: https://docs.aztec.network/aztec-nr-api/mainnet/llms.txt

# Trait Packable

Module: `noir_aztec::protocol::traits`

```rust
pub trait Packable {
    let N: u32;

    // Required methods
    pub fn pack(self) -> [Field; N];
    pub fn unpack(packed: [Field; N]) -> Self;
}
```

Space-efficient value packing and unpacking.

Like [`Serialize`](/aztec-nr-api/mainnet/serde/serialization/trait.Serialize.md) and [`Deserialize`](/aztec-nr-api/mainnet/serde/serialization/trait.Deserialize.md), this trait is used to convert to a from `Field` array representations. `Packable` is used instead of those whenever *the length* of the resulting array needs to be minimized, for example in order to reduce the number of amount storage access operations, or the number of values that will be hashed together.

The associated constant `N` is the length of the `Field` array.

## Automatic Derivation

The `#[derive]` macro can be used on any type that holds primitive values, or types that themselves also derive `Packable`. The resulting implementation does not attempt to tightly-pack values at all, and instead simply assigns a full `Field` to each value. This makes it suitable for types that are composed solely of `Field`-sized elements.

```rust
#[derive(Packable)]
struct FieldGrouping {
    a: Field,
    b: Field,
    c: Field,
}

#[derive(Packable)]
struct NestedStructs {
    fg: FieldGrouping,
    x: Field,
}

// Inefficient: there are gains to be had by manually implementing the trait instead of using `derive`
#[derive(Packable)]
struct SubFieldGrouping {
    a: bool,
    b: u32,
    c: u64,
}
```

## Manual Implementation

If a type holds at least two elements smaller than a `Field`, then manually implementing `Packable` can result in reduced costs (assuming the sub-`Field` elements are small enough to be packed together).

The nature of cost reduction will depend on what the value is used for. For public storage, it will typically decrease both L2 gas (in the form of fewer `SLOAD` and `SSTORE` opcodes) and DA costs (due to there being fewer slots accessed). For notes, it will typically decrease proving times (due to fewer hash operations).

Note that packing and unpacking must also be runtime efficient for the previously mentioned gains to not be offset by this overhead. Bit-packing by multiplying and dividing by powers of 2 is often a good strategy, as this maps well to both AVM opcodes (for public contract functions) and proving backend primitives (for private contract functions).

```rust
struct TwoBooleans {
    a: bool,
    b: bool,
}

impl Packable for TwoBooleans {
    let N: u32 = 1;

    fn pack(self) -> [Field; Self::N] {
        // a in bit 1, b in bit 0
        [(self.a as Field) * 2.pow_32(1) + (self.b as Field)]
    }

    fn unpack(packed: [Field; Self::N]) -> Self {
        let b = (packed[0] as u8) % 2 != 0;
        let a = ((packed[0] - b as Field) / 2.pow_32(1)) != 0;

        Self { a, b }
    }
}
```

## Required methods

```rust
pub fn pack(self) -> [Field; N]
```

Packs the value into a compact `Field` array.

The original value can be reconstructed by calling [`Packable::unpack`](/aztec-nr-api/mainnet/protocol_types/traits/trait.Packable.md#unpack).

```rust
pub fn unpack(packed: [Field; N]) -> Self
```

Unpacks the value from a compact `Field` array.

`packed` must be the value returned by [`Packable::pack`](/aztec-nr-api/mainnet/protocol_types/traits/trait.Packable.md#pack).

## Implementors

```rust
impl Packable for AddressNote
```

```rust
impl Packable for AztecAddress
```

```rust
impl<let M: u32, let N: u32> Packable for CompressedString<N, M>
```

```rust
impl Packable for ContractClassId
```

```rust
impl<let INITIAL_DELAY: u64, T> Packable for DelayedPublicMutableValues<T, INITIAL_DELAY>
where
    T: Packable
```

```rust
impl Packable for EcdsaPublicKeyNote
```

```rust
impl Packable for EmbeddedCurvePoint
```

```rust
impl Packable for Empty
```

```rust
impl Packable for EthAddress
```

```rust
impl Packable for Field
```

```rust
impl Packable for FieldCompressedString
```

```rust
impl Packable for FieldNote
```

```rust
impl<let N: u32, T> Packable for HasArrayWithGenerics<T, N>
where
    T: Packable
```

```rust
impl<Note> Packable for HintedNote<Note>
where
    Note: Packable
```

```rust
impl Packable for MockStruct
```

```rust
impl Packable for MockStruct
```

```rust
impl Packable for NoteMetadata
```

```rust
impl Packable for PartialUintNote
```

```rust
impl Packable for Smol
```

```rust
impl Packable for TwoBooleans
```

```rust
impl Packable for UintNote
```

```rust
impl<let M: u32, T> Packable for WithHash<T, M>
where
    T: Packable<N = M>
```

```rust
impl<let M: u32, T> Packable for [T; M]
where
    T: Packable
```

```rust
impl Packable for bool
```

```rust
impl Packable for i16
```

```rust
impl Packable for i32
```

```rust
impl Packable for i64
```

```rust
impl Packable for i8
```

```rust
impl Packable for u128
```

```rust
impl Packable for u16
```

```rust
impl Packable for u32
```

```rust
impl Packable for u64
```

```rust
impl Packable for u8
```
