A VALUE frame and its CRC trailer (Rust)¶
The smallest whole frame the Rust core produces: a VALUE with the opt-in CRC-32C trailer.
encode computes the trailer from opt.CR; decode recomputes it and refuses a mismatch.
What to notice¶
The trailer is opt-in, and so is the protection. The same one-bit flip that
decoderefuses asFrameCrcFailwith the trailer decodes silently without it. Integrity is a per-frame choice the sender makes, not a property of the codec (reference 01).Twelve bytes: 4 + 4 + 4. Header, payload, CRC. The C++ and TypeScript cores produce the same bytes, and the shared conformance vectors keep all three in step.
The error names are the wire names.
Error::FrameCrcFail.name()printsFRAME_CRC_FAIL, the spelling the C++ and TypeScript cores use.
Source¶
1// SPDX-License-Identifier: Apache-2.0
2// SPDX-FileCopyrightText: Copyright 2026 avatarsd LLC
3
4/*!
5 * @brief One concept: a VALUE frame with a CRC trailer, and what `decode` says when a
6 * byte flips in transit.
7 *
8 * Run: `cargo run --example value_crc` (from `bindings/rust/`).
9 */
10
11use libtracer::{decode, encode, value_opts, CrcWidth, Error, ValueOptions};
12
13fn main() {
14 // A 4-byte reading, with the opt-in CRC-32C trailer (opt.CR = 1).
15 let reading = 21_500u32.to_le_bytes();
16 let opts = ValueOptions {
17 crc: true,
18 ..ValueOptions::default()
19 };
20 let frame = encode(&value_opts(&reading, &opts));
21
22 // 4-byte header + 4 payload bytes + 4 CRC bytes.
23 println!("frame ({} bytes): {:02x?}", frame.len(), frame);
24 assert_eq!(frame.len(), 4 + 4 + 4);
25
26 // Decoding checks the trailer and hands back the payload unchanged.
27 let tlv = decode(&frame).expect("an intact frame decodes");
28 assert_eq!(tlv.payload, reading);
29 let crc = tlv
30 .trailer
31 .and_then(|t| t.crc)
32 .expect("the trailer carries the CRC");
33 assert_eq!(crc.width, CrcWidth::Crc32c);
34 println!(
35 "decoded payload {:02x?}, crc32c {:#010x}",
36 tlv.payload, crc.value
37 );
38
39 // Flip one payload bit: the frame still parses, but the CRC no longer matches.
40 let mut damaged = frame.clone();
41 damaged[4] ^= 0x01;
42 assert_eq!(decode(&damaged), Err(Error::FrameCrcFail));
43 println!("one flipped bit -> {}", Error::FrameCrcFail.name());
44
45 // Without the trailer the same damage is invisible to the codec.
46 let mut bare = encode(&value_opts(&reading, &ValueOptions::default()));
47 bare[4] ^= 0x01;
48 assert!(decode(&bare).is_ok());
49 println!("same flip without a CRC -> decodes silently");
50}
Run it from bindings/rust/:
$ cargo run --example value_crc
See also: the trailer (C++) · data format reference.