### Encode and Decode RLP Headers Source: https://context7.com/alloy-rs/rlp/llms.txt Demonstrates encoding a list header and decoding raw RLP bytes into a `Header` struct. Also shows using `decode_raw` to get a `PayloadView`. ```rust use alloy_rlp::{Header, PayloadView}; use bytes::BytesMut; // Encode a list header with a 3-byte payload let mut out = BytesMut::new(); Header { list: true, payload_length: 3 }.encode(&mut out); assert_eq!(&out[..], &[0xC3]); // 0xC0 + 3 // Decode a header from raw bytes let raw: &[u8] = &[0xC8, 0x83, 0xFF, 0xCC, 0xB5, 0x83, 0xFF, 0xC0, 0xB5]; let mut buf = raw; let header = Header::decode(&mut buf).unwrap(); assert!(header.list); assert_eq!(header.payload_length, 8); // decode_raw returns a PayloadView distinguishing strings from lists let encoded = alloy_rlp::encode(vec![0xBBCCB5_u64, 0xFFC0B5_u64]); let mut raw = encoded.as_slice(); match Header::decode_raw(&mut raw).unwrap() { PayloadView::List(items) => println!("got {} list items", items.len()), // prints 2 PayloadView::String(bytes) => println!("got string: {:?}", bytes), } ``` -------------------------------- ### Decode RLP Bytes into a Type Source: https://context7.com/alloy-rs/rlp/llms.txt Shows how to decode RLP encoded byte slices back into Rust types using the `Decodable` trait and `decode_exact`. Includes examples for primitive types, `String`, `Vec`, and error handling for invalid RLP data. ```rust use alloy_rlp::{Decodable, decode_exact, Error}; // Decode a u64 from a raw byte slice (buf is advanced past the item) let mut buf: &[u8] = &[0x85, 0xCE, 0x05, 0x05, 0x05, 0x05]; let val = u64::decode(&mut buf).unwrap(); assert_eq!(val, 0xCE05050505_u64); assert!(buf.is_empty()); // buffer fully consumed // decode_exact enforces no trailing bytes let encoded = alloy_rlp::encode("test1234"); let s: String = decode_exact(&encoded).unwrap(); assert_eq!(s, "test1234"); // decode_exact returns UnexpectedLength if trailing bytes remain let with_trailing = [encoded.clone(), vec![0x00]].concat(); assert_eq!(decode_exact::(with_trailing), Err(Error::UnexpectedLength)); // Decode a Vec list let mut list_buf: &[u8] = &[0xC8, 0x83, 0xBB, 0xCC, 0xB5, 0x83, 0xFF, 0xC0, 0xB5]; let vals = Vec::::decode(&mut list_buf).unwrap(); assert_eq!(vals, vec![0xBBCCB5_u64, 0xFFC0B5_u64]); // Error cases: leading zeros, overflow, unexpected list assert_eq!(u64::decode(&mut &[0x00u8][..]), Err(Error::LeadingZero)); assert_eq!(u64::decode(&mut &[0xC0u8][..]), Err(Error::UnexpectedList)); ``` -------------------------------- ### Top-level encode() Function Source: https://context7.com/alloy-rs/rlp/llms.txt Convenience function for encoding any `Encodable` value into a new `Vec`. Examples cover encoding strings, byte slices, and various integer types. ```rust use alloy_rlp::encode; // Strings assert_eq!(encode(""), vec![0x80]); assert_eq!(encode("{ "), vec![0x7b]); assert_eq!(encode("test str"), vec![0x88, 0x74, 0x65, 0x73, 0x74, 0x20, 0x73, 0x74, 0x72]); // Byte slices assert_eq!(encode(&b"\xAB\xBA"[..]), vec![0x82, 0xAB, 0xBA]); // Integers assert_eq!(encode(0u8), vec![0x80]); assert_eq!(encode(1u8), vec![0x01]); assert_eq!(encode(128u8), vec![0x81, 0x80]); assert_eq!(encode(1024u16), vec![0x82, 0x04, 0x00]); ``` -------------------------------- ### Encodable Trait Source: https://context7.com/alloy-rs/rlp/llms.txt The Encodable trait allows Rust types to be serialized into RLP byte sequences. It requires implementing `encode` and optionally `length`. The standalone `encode()` function is a convenient way to get the encoded `Vec`. ```APIDOC ## `Encodable` trait — Encode a type to RLP bytes The `Encodable` trait requires implementing `encode(&self, out: &mut dyn BufMut)` which writes the RLP representation into the provided buffer, and optionally `length(&self) -> usize` for a pre-computed byte count. The standalone `encode()` function is the simplest way to get the encoded `Vec` for any `Encodable` value. ```rust use alloy_rlp::{encode, Encodable}; use bytes::BytesMut; // Encoding primitives let n: u64 = 0xCE05050505; let encoded = encode(n); assert_eq!(encoded, vec![0x85, 0xCE, 0x05, 0x05, 0x05, 0x05]); // Encoding into an existing buffer let mut buf = BytesMut::new(); 42u64.encode(&mut buf); "hello".encode(&mut buf); true.encode(&mut buf); // Check computed length matches actual encode length let val: u32 = 0xFFCCB5; assert_eq!(val.length(), encode(val).len()); // Empty string and zero encode to the EMPTY_STRING_CODE (0x80) assert_eq!(encode(""), vec![0x80]); assert_eq!(encode(0u64), vec![0x80]); assert_eq!(encode(true), vec![0x01]); assert_eq!(encode(false), vec![0x80]); ``` ``` -------------------------------- ### RLP Length Calculation Utilities Source: https://context7.com/alloy-rs/rlp/llms.txt Shows how to use `length_of_length` for RLP prefix byte counts and `list_length` for total RLP-encoded list byte length. ```rust use alloy_rlp::{length_of_length, list_length, Encodable}; // Short payload (< 56 bytes) — 1-byte length prefix assert_eq!(length_of_length(0), 1); assert_eq!(length_of_length(55), 1); // Longer payload — multi-byte length prefix assert_eq!(length_of_length(56), 2); assert_eq!(length_of_length(256), 2); assert_eq!(length_of_length(65536), 3); // Total list length: header + all item encodings let items: &[u64] = &[0xFFCCB5, 0xFFC0B5]; let len = list_length(items); let mut buf = Vec::new(); alloy_rlp::encode_list(items, &mut buf); assert_eq!(len, buf.len()); ``` -------------------------------- ### Encode Primitive Types to RLP Bytes Source: https://context7.com/alloy-rs/rlp/llms.txt Demonstrates encoding primitive Rust types like u64 into RLP byte sequences using the `encode` function and the `Encodable` trait. Shows encoding into a new buffer and an existing `BytesMut` buffer. ```rust use alloy_rlp::{encode, Encodable}; use bytes::BytesMut; // Encoding primitives let n: u64 = 0xCE05050505; let encoded = encode(n); assert_eq!(encoded, vec![0x85, 0xCE, 0x05, 0x05, 0x05, 0x05]); // Encoding into an existing buffer let mut buf = BytesMut::new(); 42u64.encode(&mut buf); "hello".encode(&mut buf); true.encode(&mut buf); // Check computed length matches actual encode length let val: u32 = 0xFFCCB5; assert_eq!(val.length(), encode(val).len()); // Empty string and zero encode to the EMPTY_STRING_CODE (0x80) assert_eq!(encode(""), vec![0x80]); assert_eq!(encode(0u64), vec![0x80]); assert_eq!(encode(true), vec![0x01]); assert_eq!(encode(false), vec![0x80]); ``` -------------------------------- ### RLP Decode Error Types Source: https://context7.com/alloy-rs/rlp/llms.txt Demonstrates various RLP decoding errors such as Overflow, LeadingZero, NonCanonicalSingleByte, UnexpectedList, and InputTooShort. Also shows how to display error messages. ```rust use alloy_rlp::{Decodable, Error}; // Overflow: value does not fit in the target type assert_eq!(u8::decode(&mut &[0x82, 0x01, 0x00][..]), Err(Error::Overflow)); // LeadingZero: integer has a leading zero byte assert_eq!(u64::decode(&mut &[0x82, 0x00, 0xF4][..]), Err(Error::LeadingZero)); // NonCanonicalSingleByte: single byte < 0x80 should not use the 0x81 form assert_eq!(u8::decode(&mut &[0x81, 0x05][..]), Err(Error::NonCanonicalSingleByte)); // UnexpectedList: expected a string but got a list prefix assert_eq!(u64::decode(&mut &[0xC0][..]), Err(Error::UnexpectedList)); // InputTooShort: buffer ended before the declared payload was read assert_eq!(u64::decode(&mut &[0x82][..]), Err(Error::InputTooShort)); // Display output for logging/error reporting println!("{}", Error::Overflow); // "overflow" println!("{}", Error::LeadingZero); // "leading zero" println!("{}", Error::NonCanonicalSize); // "non-canonical size" println!("{}", Error::UnexpectedLength); // "unexpected length" println!("{}", Error::Custom("bad input")); // "bad input" ``` -------------------------------- ### Rlp struct (Streaming Decoder) Source: https://context7.com/alloy-rs/rlp/llms.txt Provides a streaming interface for decoding RLP list items one by one using `Rlp::new()` and `get_next::()`. ```APIDOC ## `Rlp` decoder — Streaming list item decoder The `Rlp` struct provides a streaming interface for decoding items one-by-one from an RLP list payload. Create it with `Rlp::new()` and call `get_next::()` repeatedly until it returns `None`. ```rust use alloy_rlp::{Rlp, Decodable}; // Build a list: [42u64, "hello", true] let mut buf = Vec::new(); use alloy_rlp::encode_list; use bytes::BufMut; // Manually build a heterogeneous list using encode_list with dyn Encodable use alloy_rlp::{Encodable, encode}; let a: u64 = 42; let b: &[u8] = b"hello"; let mut payload = Vec::new(); a.encode(&mut payload); b.encode(&mut payload); // Wrap payload in a list header use alloy_rlp::Header; let mut list_buf = Vec::new(); Header { list: true, payload_length: payload.len() }.encode(&mut list_buf); list_buf.extend_from_slice(&payload); // Stream-decode from the list let mut rlp = Rlp::new(&list_buf).unwrap(); let decoded_a: u64 = rlp.get_next().unwrap().unwrap(); let decoded_b: Vec = rlp.get_next().unwrap().unwrap(); assert_eq!(decoded_a, 42); assert_eq!(decoded_b, b"hello"); assert!(rlp.get_next::().unwrap().is_none()); // exhausted ``` ``` -------------------------------- ### Derive RLP Encodable/Decodable for Structs Source: https://context7.com/alloy-rs/rlp/llms.txt Shows how to automatically implement `Encodable` and `Decodable` for a struct using derive macros. Fields are encoded in declaration order. Supports roundtrip encoding and decoding. ```rust use alloy_rlp::{RlpEncodable, RlpDecodable, Encodable, Decodable, decode_exact}; #[derive(Debug, PartialEq, RlpEncodable, RlpDecodable)] pub struct Transaction { pub nonce: u64, pub gas_price: u128, pub gas_limit: u64, pub value: u128, pub data: Vec, } let tx = Transaction { nonce: 1, gas_price: 20_000_000_000, gas_limit: 21_000, value: 1_000_000_000_000_000_000, data: vec![0xde, 0xad, 0xbe, 0xef], }; // Encode let mut buf = Vec::new(); tx.encode(&mut buf); // Decode — roundtrip let decoded = Transaction::decode(&mut buf.as_slice()).unwrap(); assert_eq!(tx, decoded); // decode_exact for strict parsing let re_encoded = alloy_rlp::encode(&tx); let from_bytes: Transaction = decode_exact(&re_encoded).unwrap(); assert_eq!(tx, from_bytes); ``` -------------------------------- ### Derive RLP Traits and Encode/Decode Struct Source: https://github.com/alloy-rs/rlp/blob/main/crates/rlp/README.md Demonstrates how to derive `RlpEncodable` and `RlpDecodable` traits for a struct and then use the `encode` and `decode` methods. Ensure the `derive` feature is enabled. ```rust # #[cfg(feature = "derive")] { use alloy_rlp::{RlpEncodable, RlpDecodable, Decodable, Encodable}; #[derive(Debug, RlpEncodable, RlpDecodable, PartialEq)] pub struct MyStruct { pub a: u64, pub b: Vec, } let my_struct = MyStruct { a: 42, b: vec![1, 2, 3], }; let mut buffer = Vec::::new(); let encoded = my_struct.encode(&mut buffer); let decoded = MyStruct::decode(&mut buffer.as_slice()).unwrap(); assert_eq!(my_struct, decoded); # } ``` -------------------------------- ### RLP Streaming List Item Decoder Source: https://context7.com/alloy-rs/rlp/llms.txt Provides a streaming interface to decode RLP list items one by one using the Rlp struct. Call get_next::() repeatedly until it returns None. ```rust use alloy_rlp::{Rlp, Decodable}; // Build a list: [42u64, "hello", true] let mut buf = Vec::new(); use alloy_rlp::encode_list; use bytes::BufMut; // Manually build a heterogeneous list using encode_list with dyn Encodable use alloy_rlp::{Encodable, encode}; let a: u64 = 42; let b: &[u8] = b"hello"; let mut payload = Vec::new(); a.encode(&mut payload); b.encode(&mut payload); // Wrap payload in a list header use alloy_rlp::Header; let mut list_buf = Vec::new(); Header { list: true, payload_length: payload.len() }.encode(&mut list_buf); list_buf.extend_from_slice(&payload); // Stream-decode from the list let mut rlp = Rlp::new(&list_buf).unwrap(); let decoded_a: u64 = rlp.get_next().unwrap().unwrap(); let decoded_b: Vec = rlp.get_next().unwrap().unwrap(); assert_eq!(decoded_a, 42); assert_eq!(decoded_b, b"hello"); assert!(rlp.get_next::().unwrap().is_none()); // exhausted ``` -------------------------------- ### RlpMaxEncodedLen Derive Macro - Constant-Size Upper Bound Source: https://context7.com/alloy-rs/rlp/llms.txt This macro provides a statically known maximum encoded length for types. It derives `MaxEncodedLenAssoc` and `MaxEncodedLen`, enabling efficient, zero-heap-allocation encoding with `encode_fixed_size`. ```APIDOC ## `RlpMaxEncodedLen` derive macro — Constant-size upper bound For types whose maximum encoded length is statically known, `RlpMaxEncodedLen` derives `MaxEncodedLenAssoc` (and `MaxEncodedLen` for non-generic types), enabling use with `encode_fixed_size` for zero-heap-allocation encoding. ```rust use alloy_rlp::{RlpEncodable, RlpDecodable, RlpMaxEncodedLen, MaxEncodedLenAssoc, encode_fixed_size}; #[derive(Debug, PartialEq, RlpEncodable, RlpDecodable, RlpMaxEncodedLen)] struct NodeId { pub id: [u8; 32], pub port: u16, } // LEN is computed at compile time println!("Max encoded length: {}", NodeId::LEN); let node = NodeId { id: [0xAB; 32], port: 30303 }; // Stack-allocated encode — no Vec, no heap allocation let encoded = encode_fixed_size::(&node); let decoded = NodeId::decode(&mut &encoded[..]).unwrap(); assert_eq!(node, decoded); ``` ``` -------------------------------- ### decode_exact() Source: https://context7.com/alloy-rs/rlp/llms.txt Performs strict, whole-buffer RLP decoding, returning an error if any trailing bytes exist after the decoded item. Ideal for validating complete RLP blobs. ```APIDOC ## `decode_exact()` — Strict whole-buffer decoding Decodes a complete RLP-encoded byte sequence, returning an error if any trailing bytes remain after the item. Useful for validating that a complete and self-contained RLP blob is consumed. ```rust use alloy_rlp::{decode_exact, encode, Error}; // Successful roundtrip let encoded = encode(42u64); assert_eq!(decode_exact::(&encoded), Ok(42u64)); // Trailing bytes cause an error let mut with_garbage = encode(42u64); with_garbage.push(0xFF); assert_eq!(decode_exact::(&with_garbage), Err(Error::UnexpectedLength)); // Works for lists too let encoded_list = encode(vec![1u64, 2u64, 3u64]); assert_eq!(decode_exact::>(&encoded_list), Ok(vec![1, 2, 3])); ``` ``` -------------------------------- ### Derive RLP Encodable/Decodable for Newtype Wrappers Source: https://context7.com/alloy-rs/rlp/llms.txt Demonstrates using `RlpEncodableWrapper` and `RlpDecodableWrapper` for newtype structs. This makes the wrapper transparent at the RLP level, encoding/decoding the inner field directly. ```rust use alloy_rlp::{RlpEncodableWrapper, RlpDecodableWrapper, Encodable, Decodable, encode}; #[derive(Debug, PartialEq, RlpEncodableWrapper, RlpDecodableWrapper)] struct Hash([u8; 32]); let hash = Hash([0xAB; 32]); // Encodes as a plain byte string, NOT as a list let encoded = encode(&hash); let mut buf = encoded.as_slice(); let decoded = Hash::decode(&mut buf).unwrap(); assert_eq!(hash, decoded); // Transparent: same encoding as the inner [u8; 32] let inner_encoded = encode(&[0xABu8; 32]); assert_eq!(encode(&hash), inner_encoded); ``` -------------------------------- ### encode() Function Source: https://context7.com/alloy-rs/rlp/llms.txt A convenience function that allocates a `Vec` and encodes any `Encodable` value into it. This is the simplest way to encode a value to RLP bytes. ```APIDOC ## `encode()` — Top-level encode function Convenience function that allocates a `Vec` and encodes any `Encodable` value into it. Prefer `encode_fixed_size` when the type implements `MaxEncodedLen` and a stack-allocated result is desired. ```rust use alloy_rlp::encode; // Strings assert_eq!(encode(""), vec![0x80]); assert_eq!(encode("{}"), vec![0x7b]); assert_eq!(encode("test str"), vec![0x88, 0x74, 0x65, 0x73, 0x74, 0x20, 0x73, 0x74, 0x72]); // Byte slices assert_eq!(encode(&b"\xAB\xBA"[..]), vec![0x82, 0xAB, 0xBA]); // Integers assert_eq!(encode(0u8), vec![0x80]); assert_eq!(encode(1u8), vec![0x01]); assert_eq!(encode(128u8), vec![0x81, 0x80]); assert_eq!(encode(1024u16), vec![0x82, 0x04, 0x00]); ``` ``` -------------------------------- ### Manual RLP Encodable/Decodable Implementation for Enums Source: https://context7.com/alloy-rs/rlp/llms.txt Enums require manual `Encodable` and `Decodable` implementations. The standard pattern encodes an enum as a list with a discriminant byte followed by the variant's fields. Use `Header::decode_bytes` to unwrap the list header and decode the discriminant. ```rust use alloy_rlp::{encode, encode_list, Decodable, Encodable, Error, Header}; use bytes::BufMut; #[derive(Debug, PartialEq)] enum Message { Ping(u64), Pong(u16, u64), } impl Encodable for Message { fn encode(&self, out: &mut dyn BufMut) { match self { Self::Ping(nonce) => { let parts: [&dyn Encodable; 2] = [&0u8, nonce]; encode_list::<_, dyn Encodable>(&parts, out); } Self::Pong(id, ts) => { let parts: [&dyn Encodable; 3] = [&1u8, id, ts]; encode_list::<_, dyn Encodable>(&parts, out); } } } } impl Decodable for Message { fn decode(data: &mut &[u8]) -> Result { let mut payload = Header::decode_bytes(data, true)?; match u8::decode(&mut payload)? { 0 => Ok(Self::Ping(u64::decode(&mut payload)?)), 1 => Ok(Self::Pong(u16::decode(&mut payload)?, u64::decode(&mut payload)?)), _ => Err(Error::Custom("unknown message variant")), } } } // Roundtrip let msg = Message::Ping(12345); let bytes = encode(&msg); assert_eq!(Message::decode(&mut bytes.as_ref()), Ok(Message::Ping(12345))); let msg2 = Message::Pong(7, 9999999); let bytes2 = encode(&msg2); assert_eq!(Message::decode(&mut bytes2.as_ref()), Ok(Message::Pong(7, 9999999))); ``` -------------------------------- ### RlpEncodable / RlpDecodable Derive Macros Source: https://context7.com/alloy-rs/rlp/llms.txt These derive macros automatically implement the `Encodable` and `Decodable` traits for structs. They encode all fields as an RLP list in the order they are declared. ```APIDOC ## `RlpEncodable` / `RlpDecodable` derive macros The `RlpEncodable` and `RlpDecodable` derive macros (from `alloy-rlp-derive`, enabled via the `derive` feature) automatically implement `Encodable` and `Decodable` for structs by encoding all fields as an RLP list in field declaration order. ```rust use alloy_rlp::{RlpEncodable, RlpDecodable, Encodable, Decodable, decode_exact}; #[derive(Debug, PartialEq, RlpEncodable, RlpDecodable)] pub struct Transaction { pub nonce: u64, pub gas_price: u128, pub gas_limit: u64, pub value: u128, pub data: Vec, } let tx = Transaction { nonce: 1, gas_price: 20_000_000_000, gas_limit: 21_000, value: 1_000_000_000_000_000_000, data: vec![0xde, 0xad, 0xbe, 0xef], }; // Encode let mut buf = Vec::new(); tx.encode(&mut buf); // Decode — roundtrip let decoded = Transaction::decode(&mut buf.as_slice()).unwrap(); assert_eq!(tx, decoded); // decode_exact for strict parsing let re_encoded = alloy_rlp::encode(&tx); let from_bytes: Transaction = decode_exact(&re_encoded).unwrap(); assert_eq!(tx, from_bytes); ``` ``` -------------------------------- ### encode_list() Source: https://context7.com/alloy-rs/rlp/llms.txt Encodes a slice of Encodable items as an RLP list with a list header prefix. Vec also delegates to this function. ```APIDOC ## `encode_list()` — Encode a slice as an RLP list Encodes a `&[T]` as an RLP list (with list header prefix). The items must implement `Encodable`. `Vec` also implements `Encodable` and delegates to this function automatically. ```rust use alloy_rlp::{encode_list, encode}; use bytes::BytesMut; let mut out = BytesMut::new(); // Empty list → 0xC0 encode_list::(&[], &mut out); assert_eq!(&out[..], &[0xC0]); out.clear(); // List of two u64 values encode_list(&[0xFFCCB5_u64, 0xFFC0B5_u64], &mut out); assert_eq!(&out[..], &[0xC8, 0x83, 0xFF, 0xCC, 0xB5, 0x83, 0xFF, 0xC0, 0xB5]); // Equivalent via Vec's Encodable impl let v: Vec = vec![0xFFCCB5, 0xFFC0B5]; assert_eq!(encode(&v), &out[..]); ``` ``` -------------------------------- ### Header Struct - Low-level RLP Header Encode/Decode Source: https://context7.com/alloy-rs/rlp/llms.txt The `Header` struct allows direct manipulation of RLP prefixes, enabling custom codec implementations. It can encode and decode RLP headers, specifying whether a payload is a byte string or a list, and its length. ```APIDOC ## `Header` — Low-level RLP header encode/decode The `Header` struct represents the RLP prefix that identifies whether a payload is a byte string or a list, and carries the payload length. It can be encoded and decoded directly for building custom codecs. ```rust use alloy_rlp::{Header, PayloadView}; use bytes::BytesMut; // Encode a list header with a 3-byte payload let mut out = BytesMut::new(); Header { list: true, payload_length: 3 }.encode(&mut out); assert_eq!(&out[..], &[0xC3]); // 0xC0 + 3 // Decode a header from raw bytes let raw: &[u8] = &[0xC8, 0x83, 0xFF, 0xCC, 0xB5, 0x83, 0xFF, 0xC0, 0xB5]; let mut buf = raw; let header = Header::decode(&mut buf).unwrap(); assert!(header.list); assert_eq!(header.payload_length, 8); // decode_raw returns a PayloadView distinguishing strings from lists let encoded = alloy_rlp::encode(vec![0xBBCCB5_u64, 0xFFC0B5_u64]); let mut raw = encoded.as_slice(); match Header::decode_raw(&mut raw).unwrap() { PayloadView::List(items) => println!("got {} list items", items.len()), // prints 2 PayloadView::String(bytes) => println!("got string: {:?}", bytes), } ``` ``` -------------------------------- ### encode_iter() Source: https://context7.com/alloy-rs/rlp/llms.txt Encodes a cloneable iterator of Encodable items as an RLP list. It clones the iterator once for length calculation and then iterates again for encoding. ```APIDOC ## `encode_iter()` — Encode an iterator as an RLP list Encodes any cloneable iterator of `Encodable` items as an RLP list. The iterator is cloned once to compute the header length, then iterated again to encode each item. ```rust use alloy_rlp::encode_iter; use bytes::BytesMut; let mut out = BytesMut::new(); encode_iter([0xFFCCB5_u64, 0xFFC0B5_u64].iter(), &mut out); assert_eq!(&out[..], &[0xC8, 0x83, 0xFF, 0xCC, 0xB5, 0x83, 0xFF, 0xC0, 0xB5]); // Empty iterator let mut out2 = BytesMut::new(); encode_iter(core::iter::empty::(), &mut out2); assert_eq!(&out2[..], &[0xC0]); ``` ``` -------------------------------- ### RLP Field Attributes: `#[rlp(skip)]` and `#[rlp(default)]` Source: https://context7.com/alloy-rs/rlp/llms.txt Use `#[rlp(skip)]` to exclude a field from encoding and decoding. Use `#[rlp(default)]` to use the field's `Default` value when decoding fails. Both can be combined as `#[rlp(skip, default)]`. ```rust use alloy_rlp::{RlpEncodable, RlpDecodable, Encodable, Decodable}; #[derive(Debug, PartialEq, Default)] struct Cache(u64); #[derive(Debug, PartialEq, RlpEncodable, RlpDecodable)] struct Record { pub id: u64, pub value: u64, #[rlp(skip, default)] pub cache: Cache, } let rec = Record { id: 1, value: 100, cache: Cache(999) }; let mut buf = Vec::new(); rec.encode(&mut buf); // cache is not in the encoded bytes let decoded = Record::decode(&mut buf.as_slice()).unwrap(); assert_eq!(decoded.id, 1); assert_eq!(decoded.value, 100); assert_eq!(decoded.cache, Cache::default()); ``` -------------------------------- ### RLP Optional Trailing Fields with `#[rlp(trailing)]` Source: https://context7.com/alloy-rs/rlp/llms.txt Use `#[rlp(trailing)]` to allow `Option` fields at the end of a struct. Absent trailing fields decode as `None`, and trailing `None` values are omitted during encoding. Three modes are supported: `trailing` (default), `trailing(no_gaps)`, and `trailing(canonical)`. ```rust use alloy_rlp::{RlpEncodable, RlpDecodable, Encodable, Decodable}; #[derive(Debug, PartialEq, RlpEncodable, RlpDecodable)] #[rlp(trailing)] pub struct Receipt { pub status: u8, pub gas_used: u64, pub bloom: Option<[u8; 256]>, pub logs: Option>, } // Encoding with all fields let full = Receipt { status: 1, gas_used: 21000, bloom: Some([0xAA; 256]), logs: Some(vec![1, 2]) }; let mut buf = Vec::new(); full.encode(&mut buf); let decoded = Receipt::decode(&mut buf.as_slice()).unwrap(); assert_eq!(full, decoded); // Encoding without optional fields — trailing Nones are omitted let partial = Receipt { status: 1, gas_used: 21000, bloom: None, logs: None }; let mut buf2 = Vec::new(); partial.encode(&mut buf2); let decoded2 = Receipt::decode(&mut buf2.as_slice()).unwrap(); assert_eq!(partial, decoded2); ``` -------------------------------- ### Encode Iterator as RLP List Source: https://context7.com/alloy-rs/rlp/llms.txt Encodes any cloneable iterator of Encodable items as an RLP list. The iterator is cloned once for header length calculation and then iterated again for encoding. ```rust use alloy_rlp::encode_iter; use bytes::BytesMut; let mut out = BytesMut::new(); encode_iter([0xFFCCB5_u64, 0xFFC0B5_u64].iter(), &mut out); assert_eq!(&out[..], &[0xC8, 0x83, 0xFF, 0xCC, 0xB5, 0x83, 0xFF, 0xC0, 0xB5]); // Empty iterator let mut out2 = BytesMut::new(); encode_iter(core::iter::empty::(), &mut out2); assert_eq!(&out2[..], &[0xC0]); ``` -------------------------------- ### Derive Max RLP Encoded Length for Compile-Time Size Source: https://context7.com/alloy-rs/rlp/llms.txt Utilizes the `RlpMaxEncodedLen` derive macro to compute the maximum encoded length of a struct at compile time. This enables zero-heap-allocation encoding using `encode_fixed_size`. ```rust use alloy_rlp::{RlpEncodable, RlpDecodable, RlpMaxEncodedLen, MaxEncodedLenAssoc, encode_fixed_size}; #[derive(Debug, PartialEq, RlpEncodable, RlpDecodable, RlpMaxEncodedLen)] struct NodeId { pub id: [u8; 32], pub port: u16, } // LEN is computed at compile time println!("Max encoded length: {}", NodeId::LEN); let node = NodeId { id: [0xAB; 32], port: 30303 }; // Stack-allocated encode — no Vec, no heap allocation let encoded = encode_fixed_size::(&node); let decoded = NodeId::decode(&mut &encoded[..]).unwrap(); assert_eq!(node, decoded); ``` -------------------------------- ### Stack-allocated encoding with encode_fixed_size() Source: https://context7.com/alloy-rs/rlp/llms.txt Utilizes `encode_fixed_size` for stack-allocated RLP encoding when a type implements `MaxEncodedLen`. Requires the `arrayvec` feature to be enabled. ```rust // Cargo.toml: alloy-rlp = { version = "0.3", features = ["arrayvec"] } use alloy_rlp::{encode_fixed_size, MaxEncodedLenAssoc}; let val: u64 = 0xFFCCB5DDFFEE1483; let encoded = encode_fixed_size::(&val); // Returns ArrayVec, no heap allocation assert_eq!(&encoded[..], &[0x88, 0xFF, 0xCC, 0xB5, 0xDD, 0xFF, 0xEE, 0x14, 0x83]); ``` -------------------------------- ### Encode Slice as RLP List Source: https://context7.com/alloy-rs/rlp/llms.txt Encodes a slice of Encodable items into an RLP list. Vec also uses this function automatically. Ensure items implement Encodable. ```rust use alloy_rlp::{encode_list, encode}; use bytes::BytesMut; let mut out = BytesMut::new(); // Empty list → 0xC0 encode_list::(&[], &mut out); assert_eq!(&out[..], &[0xC0]); out.clear(); // List of two u64 values encode_list(&[0xFFCCB5_u64, 0xFFC0B5_u64], &mut out); assert_eq!(&out[..], &[0xC8, 0x83, 0xFF, 0xCC, 0xB5, 0x83, 0xFF, 0xC0, 0xB5]); // Equivalent via Vec's Encodable impl let v: Vec = vec![0xFFCCB5, 0xFFC0B5]; assert_eq!(encode(&v), &out[..]); ``` -------------------------------- ### Append Decoded RLP List Items to Vec Source: https://context7.com/alloy-rs/rlp/llms.txt Decodes an RLP-encoded list and appends each item to an existing Vec. This avoids new allocations when accumulating data. ```rust use alloy_rlp::{decode_append, encode}; let encoded_list: &[u8] = &[0xC8, 0x83, 0xBB, 0xCC, 0xB5, 0x83, 0xFF, 0xC0, 0xB5]; let mut buf = encoded_list; let mut values: Vec = vec![0x01]; // existing item let cap = values.capacity(); decode_append::(&mut buf, &mut values).unwrap(); assert!(buf.is_empty()); assert_eq!(values, vec![0x01, 0xBBCCB5_u64, 0xFFC0B5_u64]); assert_eq!(values.capacity(), cap); // no reallocation if capacity was sufficient ``` -------------------------------- ### decode_append() Source: https://context7.com/alloy-rs/rlp/llms.txt Decodes an RLP-encoded list and appends its items to an existing Vec, useful for accumulating data without new allocations. ```APIDOC ## `decode_append()` — Decode RLP list into an existing Vec Decodes an RLP-encoded list and appends each decoded item into an existing `Vec`. This avoids allocating a new vector when items need to be accumulated with pre-existing data. ```rust use alloy_rlp::{decode_append, encode}; let encoded_list: &[u8] = &[0xC8, 0x83, 0xBB, 0xCC, 0xB5, 0x83, 0xFF, 0xC0, 0xB5]; let mut buf = encoded_list; let mut values: Vec = vec![0x01]; // existing item let cap = values.capacity(); decode_append::(&mut buf, &mut values).unwrap(); assert!(buf.is_empty()); assert_eq!(values, vec![0x01, 0xBBCCB5_u64, 0xFFC0B5_u64]); assert_eq!(values.capacity(), cap); // no reallocation if capacity was sufficient ``` ``` -------------------------------- ### Decodable Trait Source: https://context7.com/alloy-rs/rlp/llms.txt The Decodable trait provides `decode(buf: &mut &[u8]) -> Result` for deserializing RLP bytes back into Rust types. It advances the input buffer past the decoded item. `decode_exact` enforces strict parsing with no trailing bytes. ```APIDOC ## `Decodable` trait — Decode RLP bytes into a type The `Decodable` trait provides `decode(buf: &mut &[u8]) -> Result`, which advances the input buffer past the decoded item. All built-in types implement this. For strict parsing of a complete buffer, use `decode_exact`. ```rust use alloy_rlp::{Decodable, decode_exact, Error}; // Decode a u64 from a raw byte slice (buf is advanced past the item) let mut buf: &[u8] = &[0x85, 0xCE, 0x05, 0x05, 0x05, 0x05]; let val = u64::decode(&mut buf).unwrap(); assert_eq!(val, 0xCE05050505_u64); assert!(buf.is_empty()); // buffer fully consumed // decode_exact enforces no trailing bytes let encoded = alloy_rlp::encode("test1234"); let s: String = decode_exact(&encoded).unwrap(); assert_eq!(s, "test1234"); // decode_exact returns UnexpectedLength if trailing bytes remain let with_trailing = [encoded.clone(), vec![0x00]].concat(); assert_eq!(decode_exact::(with_trailing), Err(Error::UnexpectedLength)); // Decode a Vec list let mut list_buf: &[u8] = &[0xC8, 0x83, 0xBB, 0xCC, 0xB5, 0x83, 0xFF, 0xC0, 0xB5]; let vals = Vec::::decode(&mut list_buf).unwrap(); assert_eq!(vals, vec![0xBBCCB5_u64, 0xFFC0B5_u64]); // Error cases: leading zeros, overflow, unexpected list assert_eq!(u64::decode(&mut &[0x00u8][..]), Err(Error::LeadingZero)); assert_eq!(u64::decode(&mut &[0xC0u8][..]), Err(Error::UnexpectedList)); ``` ``` -------------------------------- ### encode_fixed_size() Function Source: https://context7.com/alloy-rs/rlp/llms.txt Encodes a value into a stack-allocated `ArrayVec` when the type implements `MaxEncodedLen`, avoiding heap allocation. This function requires the `arrayvec` feature to be enabled. ```APIDOC ## `encode_fixed_size()` — Stack-allocated encoding (arrayvec feature) When a type implements `MaxEncodedLen`, this function encodes into a stack-allocated `ArrayVec`, avoiding heap allocation. Enabled by the `arrayvec` feature. ```rust // Cargo.toml: alloy-rlp = { version = "0.3", features = ["arrayvec"] } use alloy_rlp::{encode_fixed_size, MaxEncodedLenAssoc}; let val: u64 = 0xFFCCB5DDFFEE1483; let encoded = encode_fixed_size::(&val); // Returns ArrayVec, no heap allocation assert_eq!(&encoded[..], &[0x88, 0xFF, 0xCC, 0xB5, 0xDD, 0xFF, 0xEE, 0x14, 0x83]); ``` ``` -------------------------------- ### Strict RLP Decoding Source: https://context7.com/alloy-rs/rlp/llms.txt Decodes a complete RLP-encoded byte sequence, returning an error if any trailing bytes remain. This is useful for validating self-contained RLP blobs. ```rust use alloy_rlp::{decode_exact, encode, Error}; // Successful roundtrip let encoded = encode(42u64); assert_eq!(decode_exact::(&encoded), Ok(42u64)); // Trailing bytes cause an error let mut with_garbage = encode(42u64); with_garbage.push(0xFF); assert_eq!(decode_exact::(&with_garbage), Err(Error::UnexpectedLength)); // Works for lists too let encoded_list = encode(vec![1u64, 2u64, 3u64]); assert_eq!(decode_exact::>(&encoded_list), Ok(vec![1, 2, 3])); ``` -------------------------------- ### RlpEncodableWrapper / RlpDecodableWrapper - Newtype Wrapper Derives Source: https://context7.com/alloy-rs/rlp/llms.txt For newtype structs (single-field wrappers), these derives encode and decode the inner field directly. This makes the newtype transparent at the RLP level, avoiding an extra list header. ```APIDOC ## `RlpEncodableWrapper` / `RlpDecodableWrapper` — Newtype wrapper derives For newtype structs (single-field wrappers), `RlpEncodableWrapper` and `RlpDecodableWrapper` encode/decode the inner field directly without wrapping it in an additional list header, making the newtype transparent at the RLP level. ```rust use alloy_rlp::{RlpEncodableWrapper, RlpDecodableWrapper, Encodable, Decodable, encode}; #[derive(Debug, PartialEq, RlpEncodableWrapper, RlpDecodableWrapper)] struct Hash([u8; 32]); let hash = Hash([0xAB; 32]); // Encodes as a plain byte string, NOT as a list let encoded = encode(&hash); let mut buf = encoded.as_slice(); let decoded = Hash::decode(&mut buf).unwrap(); assert_eq!(hash, decoded); // Transparent: same encoding as the inner [u8; 32] let inner_encoded = encode(&[0xABu8; 32]); assert_eq!(encode(&hash), inner_encoded); ``` ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.