Exact Sizing

Dynamic messages expose schema-aware size APIs. Flat shapes get a direct checked helper; nested or ragged shapes get a staged *EncodedLength builder. Allocate or claim exactly that many bytes, then write groups and var-data in wire order:

#![allow(unused)]
fn main() {
pub fn demo_car_size_and_encode() -> Result<Vec<u8>, Box<dyn std::error::Error>> {
    // Fuel: 2 entries with usage ASCII lengths 5 and 7.
    // Performance: 1 entry with 2 nested acceleration rows (fixed-only entries).
    // Message var-data: manufacturer / model / activationCode lengths.
    let complete_len = CarEncoder::compute_length()
        .fuel_figures_ragged(2, |ff| {
            ff.add()?.usage_description(5)?; // "Urban"
            ff.add()?.usage_description(7)?; // "Highway"
            Ok(())
        })?
        .performance_figures_ragged(1, |pf| {
            pf.add()?.acceleration(|acc| {
                acc.uniform(2)?;
                Ok(())
            })?;
            Ok(())
        })?
        .manufacturer(5)? // "Honda"
        .model(9)? // "Civic VTi"
        .activation_code(6)? // "abcdef"
        .encoded_length_with_header();

    // Exact size from compute_length → stack pad (this demo fits well under 512).
    const CAR_PAD: usize = 512;
    assert!(
        complete_len <= CAR_PAD,
        "sample car length {complete_len} exceeds stack pad {CAR_PAD}"
    );
    let mut storage = [0u8; CAR_PAD];
    let written = encode_sample_car(&mut storage[..complete_len])?;
    assert_eq!(
        written, complete_len,
        "CarEncodedLength must equal encoder-produced length"
    );
    Ok(storage[..written].to_vec())
}
/// Encode the canonical sample car into `buf` (must be pre-sized).
pub fn encode_sample_car(buf: &mut [u8]) -> Result<usize, sbe_rt::EncodeError> {
    let mut extras = OptionalExtras::default();
    extras.cruise_control(true).sports_pack(true);

    // Buffer pre-sized from EncodedLength; try_* still validates extent.
    let len = CarEncoder::try_wrap_and_apply_header(buf, 0)
        .unwrap()
        .fixed(&CarFixedFields {
            serial_number: 1234,
            model_year: 2013,
            available: true.into(),
            code: Model::A,
            some_numbers: [10, 20, 30, 40],
            vehicle_code: [b'A', b'B', b'C', b'D', b'E', b'F'],
            extras,
            engine: Engine::new(
                2000,
                4,
                [b'1', b'2', b'3'],
                0i8,
                false.into(),
                Booster::new(BoostType::TURBO, 210),
            ),
        })
        .fuel_figures(2, |g| {
            g.add(|mut e| {
                e.speed(30).mpg(35.9);
                e.usage_description(b"Urban")
            })?;
            g.add(|mut e| {
                e.speed(60).mpg(25.0);
                e.usage_description(b"Highway")
            })?;
            Ok(())
        })?
        .performance_figures(1, |g| {
            g.add(|mut e| {
                e.octane_rating(95);
                e.acceleration(2, |a| {
                    a.add(|x| {
                        x.mph(30).seconds(4.0);
                        Ok(())
                    })?;
                    a.add(|x| {
                        x.mph(60).seconds(7.5);
                        Ok(())
                    })
                })
            })?;
            Ok(())
        })?
        .manufacturer(b"Honda")?
        .model(b"Civic VTi")?
        .activation_code(b"abcdef")?
        .encoded_length_with_header();

    Ok(len)
}
}

(This code comes from the sbe-feature-tour sample crate.)