### Complete Custom Configuration Example Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/04-configuration.md Demonstrates how to build and use a completely custom configuration for Wincode serialization. This example shows how to specify alignment checks, preallocation limits, integer lengths, endianness, and encoding types. ```rust use wincode::{ config::Configuration, len::UseIntLen, schema::int_encoding::VarInt, SchemaRead, SchemaWrite, }; // Build a completely custom configuration type CustomConfig = wincode::config::Configuration< false, // No alignment checks { 16 * 1024 * 1024 }, // 16 MiB preallocation limit UseIntLen, // Use u32 for sequence lengths wincode::schema::int_encoding::BigEndian, // Big-endian integers VarInt, // Variable-width encoding u16, // u16 enum tags >; #[derive(SchemaRead, SchemaWrite)] struct MyData { id: u32, items: Vec, } // Serialize with custom config let data = MyData { id: 42, items: vec![1, 2, 3] }; let bytes = >::write(&mut writer, &data)?; ``` -------------------------------- ### Example: Using UseIntLen for Vector Lengths Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/08-sequence-length-encoding.md Illustrates how to use `UseIntLen` to define the integer type and preallocation limits for vector lengths in a struct. Examples include `u16` length, `u32` length with a 512 KiB limit, and default `u64` length. ```rust use wincode::{ containers, len::UseIntLen, }; use wincode::{SchemaRead, SchemaWrite}; #[derive(SchemaRead, SchemaWrite)] struct MyData { // Length as u16 (up to 65,535 elements) #[wincode(with = "containers::Vec>")] small_vec: Vec, // Length as u32 with 512 KiB limit #[wincode(with = "containers::Vec>")] medium_vec: Vec, // Length as u64 (default) #[wincode(with = "containers::Vec>")] large_vec: Vec, } ``` -------------------------------- ### TypeMeta Examples Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/01-core-traits.md Demonstrates creating TypeMeta instances for static types with zero-copy enabled and combining metadata from multiple types. ```rust use wincode::TypeMeta; // Static type with zero-copy let tm = TypeMeta::Static { size: 32, zero_copy: true }; // Combining multiple types let combined = TypeMeta::join_types([ TypeMeta::Static { size: 4, zero_copy: true }, TypeMeta::Static { size: 8, zero_copy: true }, TypeMeta::Static { size: 2, zero_copy: false }, ]); assert_eq!(combined, TypeMeta::Static { size: 14, zero_copy: false }); ``` -------------------------------- ### Serialize Example: Vec Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/03-serialization-api.md Demonstrates serializing a Vec into bytes and checking its size. Requires the 'alloc' feature. ```rust use wincode::Serialize; let vec: Vec = vec![1, 2, 3]; let bytes = vec.serialize()?; assert_eq!(bytes.len(), 8 + 3); // 8 bytes for length + 3 bytes for data let size = vec.serialized_size()?; assert_eq!(size as usize, bytes.len()); ``` -------------------------------- ### SchemaWrite Size Calculation Example Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/10-implementation-guide.md The size_of method must return the exact number of bytes that the write method will produce. This example shows calculating size for two fields. ```rust use wincode::{SchemaWrite, WriteResult, config::ConfigCore}; unsafe impl SchemaWrite for MyStruct { type Src = MyStruct; fn size_of(src: &Self::Src) -> WriteResult { let field1_size = 4; // u32 let field2_size = 8; // u64 Ok(field1_size + field2_size) } fn write(mut writer: impl wincode::io::Writer, src: &Self::Src) -> WriteResult<()> { writer.write(&src.field1.to_le_bytes())?; writer.write(&src.field2.to_le_bytes())?; Ok(()) } } ``` -------------------------------- ### Custom Configuration Example Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/04-configuration.md Demonstrates how to create a custom Wincode configuration with variable-width integers and a specific length encoding. This custom configuration can then be used with schema traits for writing data. ```rust use wincode::config::Configuration; use wincode::len::UseIntLen; use wincode::schema::int_encoding::VarInt; // Create config with variable-width integers and custom length encoding let config = Configuration::default() .with_var_int_encoding() .with_length_encoding::>(); // Use with schema traits let bytes = >::write(&mut writer, &value)?; ``` -------------------------------- ### Deserialize Example: Vec Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/03-serialization-api.md Demonstrates deserializing a Vec from a byte slice. ```rust use wincode::Deserialize; let bytes = vec![3, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3]; let vec: Vec = Deserialize::deserialize(&bytes)?; assert_eq!(vec, vec![1, 2, 3]); ``` -------------------------------- ### Cursor Usage Example Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/02-io-module.md Demonstrates the use of the Cursor for tracking position within a slice. Supports call-site scoped borrowing and advances the position after reading bytes. ```rust use wincode::io::Cursor; let data = [1, 2, 3, 4, 5]; let mut cursor = Cursor::new(&data[..]); let pos = cursor.position(); // 0 let byte = cursor.take_byte()?; assert_eq!(cursor.position(), 1); // Advanced ``` -------------------------------- ### Regular Deserialization Example Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/09-zero-copy-deserialization.md Demonstrates standard deserialization which involves memory allocation and byte copying. This is slower than zero-copy but necessary when owned or mutable data structures are required. ```rust // Fast but slower than zero-copy: allocates and initializes let data: Data = wincode::deserialize(&bytes)?; ``` -------------------------------- ### Example: Per-Sequence Preallocation Overrides Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/08-sequence-length-encoding.md Demonstrates using `wincode` attributes to apply different preallocation limits to vector fields within a struct. Shows how to use global config, a custom limit (1 MiB), and no limit. ```rust use wincode::{ containers, len::BincodeLen, PREALLOCATION_SIZE_LIMIT_DISABLED, }; use wincode::{SchemaRead, SchemaWrite}; #[derive(SchemaRead, SchemaWrite)] struct DataContainer { // Use global config limit #[wincode(with = "containers::Vec")] normal_vec: Vec, // 1 MiB limit for this field only #[wincode(with = "containers::Vec>")] limited_vec: Vec, // No limit for this field #[wincode(with = "containers::Vec>")] unlimited_vec: Vec, } ``` -------------------------------- ### Immutable Zero-Copy Deserialization Example Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/09-zero-copy-deserialization.md Demonstrates how to get an immutable reference to a struct directly from serialized bytes using `ZeroCopy::from_bytes`. Ensure the struct derives `SchemaRead` and `SchemaWrite` and meets zero-copy eligibility criteria. ```rust use wincode::{SchemaRead, SchemaWrite, ZeroCopy}; #[derive(SchemaRead, SchemaWrite)] #[repr(C)] struct Data { bytes: [u8; 7], value: u8, } let data = Data { bytes: *b"wincode", value: 42 }; let serialized = wincode::serialize(&data)?; // Get reference to data directly from bytes let data_ref = Data::from_bytes(&serialized)?; assert_eq!(data_ref.bytes, *b"wincode"); assert_eq!(data_ref.value, 42); ``` -------------------------------- ### Example: Using Slice Reader with Backing Borrows Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/02-io-module.md Demonstrates how a slice reader supports 'Backing' borrows, allowing borrowed data to remain valid even after the reader is dropped. Ensure the reader supports the required borrow kind before attempting to borrow. ```rust use wincode::io::{Reader, BorrowKind}; let data = [1, 2, 3, 4, 5]; let mut reader = data.as_slice(); // Slice readers support Backing borrows if reader.supports_borrow(BorrowKind::Backing) { let borrowed = reader.take_borrowed(3)?; // borrowed is valid even after reader is dropped } ``` -------------------------------- ### Vec with Preallocation Size Limits Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/05-containers-and-collections.md Illustrates setting per-collection preallocation limits using const generics with `UseIntLen`. This example shows an 8 KiB limit and an unlimited Vec. ```rust use wincode::{containers, len::{UseIntLen, PREALLOCATION_SIZE_LIMIT_DISABLED}, SchemaRead, SchemaWrite}; #[derive(SchemaRead, SchemaWrite)] struct MyStruct { // 8 KiB limit #[wincode(with = "containers::Vec>")] small: Vec, // No limit #[wincode(with = "containers::Vec>")] unlimited: Vec, } ``` -------------------------------- ### Handling Variable-Length Data with SeqLen Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/10-implementation-guide.md Coordinate with `SeqLen` implementations for writing variable-length data, such as vectors. This example shows how to calculate the total size and write the length prefix followed by the items. ```rust use wincode::{SchemaWrite, io::Writer, WriteResult, len::SeqLen, config::ConfigCore}; unsafe impl SchemaWrite for VecWrapper where C: ConfigCore, T: SchemaWrite, Len: SeqLen, { type Src = Vec; fn size_of(src: &Self::Src) -> WriteResult { let len_size = Len::write_bytes_needed(src.len())?; let item_size = src.iter() .try_fold(0usize, |acc, item| T::size_of(item).map(|s| acc + s))?; Ok(len_size + item_size) } fn write(mut writer: impl Writer, src: &Self::Src) -> WriteResult<()> { Len::write(writer.by_ref(), src.len())?; for item in src { T::write(writer.by_ref(), item)?; } Ok(()) } } ``` -------------------------------- ### Handle Wincode Read Errors Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/07-error-types.md Demonstrates how to match against various `ReadError` variants when deserializing data. This example specifically handles `PreallocationSizeLimit`, `InvalidValue`, and `TrailingBytes` errors. ```rust use wincode::{ReadError, Deserialize}; let bytes = vec![255, 255, 255]; match >::deserialize(&bytes) { Ok(vec) => println!("Deserialized: {:?}", vec), Err(ReadError::PreallocationSizeLimit { needed, limit }) => { eprintln!("Collection too large: needed {} bytes, limit is {} bytes", needed, limit); } Err(ReadError::InvalidValue(msg)) => { eprintln!("Invalid value: {}", msg); } Err(ReadError::TrailingBytes) => { eprintln!("Extra bytes after deserialization"); } Err(e) => eprintln!("Read error: {}", e), } ``` -------------------------------- ### Correct Deserialization Initialization Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/10-implementation-guide.md Ensure `dst` is initialized if and only if `Ok(())` is returned to prevent undefined behavior. This example shows the correct pattern for initializing `dst` before returning `Ok`. ```rust unsafe impl<'de, C: ConfigCore> SchemaRead<'de, C> for MyType { type Dst = MyType; fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit) -> ReadResult<()> { // ✅ Correct: Initialize dst before returning Ok let value = read_value(&mut reader)?; dst.write(value); Ok(()) // ❌ Wrong: Return Ok without initializing dst // Ok(()) // Would cause undefined behavior! } } ``` -------------------------------- ### Vec with UseIntLen Length Encoding Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/05-containers-and-collections.md Example of using `UseIntLen` for specifying the integer type used to encode the length of a Vec. This example uses `u16` for the length. ```rust use wincode::{containers, len::UseIntLen, SchemaRead, SchemaWrite}; #[derive(SchemaRead, SchemaWrite)] struct MyStruct { #[wincode(with = "containers::Vec>")] vec: Vec, } ``` -------------------------------- ### DeserializeOwned Example: Vec Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/03-serialization-api.md Demonstrates deserializing a Vec from a Cursor using DeserializeOwned. ```rust use wincode::DeserializeOwned; use wincode::io::Cursor; let bytes = vec![3, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3]; let mut cursor = Cursor::new(&bytes[..]); let vec: Vec = Vec::deserialize_from(&mut cursor)?; assert_eq!(vec, vec![1, 2, 3]); ``` -------------------------------- ### Handling Wincode Errors Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/07-error-types.md Example of how to match and handle the top-level Wincode Error enum, distinguishing between write and read failures. ```rust use wincode::Error; match some_operation() { Ok(value) => println!("Success: {:?}", value), Err(Error::WriteError(we)) => eprintln!("Write failed: {}", we), Err(Error::ReadError(re)) => eprintln!("Read failed: {}", re), } ``` -------------------------------- ### Vec with FixIntLen Length Encoding Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/05-containers-and-collections.md Example of using `FixIntLen` for fixed-width length encoding of a Vec. This example specifies `u32` as the integer type for the length. ```rust use wincode::{containers, len::FixIntLen, SchemaRead, SchemaWrite}; #[derive(SchemaRead, SchemaWrite)] struct MyStruct { #[wincode(with = "containers::Vec>")] vec: Vec, } ``` -------------------------------- ### Using UninitBuilder for Complex Initialization Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/10-implementation-guide.md For types with many fields or complex dependencies, leverage the generated `UninitBuilder`. This example shows how to use the builder to read and initialize fields of a `Header` struct within a `CustomMessage`. ```rust use wincode::{SchemaRead, io::Reader, ReadResult, config::ConfigCore, UninitBuilder}; use core::mem::MaybeUninit; #[derive(SchemaRead, SchemaWrite, UninitBuilder)] struct Header { version: u8, flags: u8, reserved: u16, } unsafe impl<'de, C: ConfigCore> SchemaRead<'de, C> for CustomMessage { type Dst = CustomMessage; fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit) -> ReadResult<()> { let mut builder = HeaderUninitBuilder::::from_maybe_uninit_mut( unsafe { &mut *(&raw mut (*dst.as_mut_ptr()).header).cast::>() } ); builder.read_version(&mut reader)?; builder.read_flags(&mut reader)?; builder.read_reserved(&mut reader)?; builder.finish(); Ok(()) } } ``` -------------------------------- ### Integrate SmallVec with Wincode Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/11-features-and-build.md When the `smallvec` feature is enabled, Wincode supports `smallvec::SmallVec`. This example demonstrates its usage, which avoids heap allocation for small collections by using inline storage. ```rust use smallvec::SmallVec; #[derive(SchemaRead, SchemaWrite)] struct Batch { #[wincode(with = "containers::Vec")] small: SmallVec<[u32; 4]>, } ``` -------------------------------- ### Zero-Copy Deserialization Example Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/09-zero-copy-deserialization.md Illustrates ultra-fast zero-copy deserialization using a simple pointer cast. This method avoids allocations and copying, making it ideal for read-only access to large data structures. ```rust // Ultra-fast: just pointer cast, no allocation or copying let data_ref = Data::from_bytes(&bytes)?; ``` -------------------------------- ### Mutable Zero-Copy Deserialization Example Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/09-zero-copy-deserialization.md Shows how to obtain a mutable reference to a struct from serialized bytes using `ZeroCopy::from_bytes_mut` for in-place mutation. The modified data can then be re-serialized. ```rust use wincode::{SchemaRead, SchemaWrite, ZeroCopy}; #[derive(SchemaRead, SchemaWrite)] #[repr(C)] struct Config { name: [u8; 8], version: u32, } let mut serialized = wincode::serialize(&Config { name: *b"app00000", version: 1, })?; // Mutate the data in-place let config = Config::from_bytes_mut(&mut serialized)?; config.name = *b"myapp000"; config.version = 2; // Serialize the modified data let modified = wincode::serialize(config)?; ``` -------------------------------- ### Reader Trait Example Usage Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/02-io-module.md Demonstrates reading data from a byte slice using the Reader trait's methods like take_array, take_byte, and take_borrowed. ```rust use wincode::io::Reader; let slice = [1, 2, 3, 4, 5]; let mut reader = slice.as_slice(); // Read array let arr: [u8; 2] = reader.take_array()?; assert_eq!(arr, [1, 2]); // Read byte let b: u8 = reader.take_byte()?; assert_eq!(b, 3); // Borrow remaining let borrowed = reader.take_borrowed(2)?; assert_eq!(borrowed, [4, 5]); ``` -------------------------------- ### Configure Strict Linting with Clippy Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/11-features-and-build.md Enable strict linting rules using Clippy by configuring the `[lints.clippy]` section in Cargo.toml. This example denies specific lint rules to enforce code quality. ```toml [lints.clippy] default_trait_access = "deny" manual_let_else = "deny" used_underscore_binding = "deny" arithmetic_side_effects = "deny" ``` -------------------------------- ### Implement SchemaWrite for Custom Type Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/01-core-traits.md Example of implementing the SchemaWrite trait for a custom struct to enable serialization. Ensure TYPE_META is correctly set if using static sizing or zero-copy. ```rust use wincode::{SchemaWrite, io::Writer, WriteResult}; struct MyType(u32, u16); unsafe impl SchemaWrite for MyType { type Src = MyType; fn size_of(_: &Self::Src) -> WriteResult { Ok(std::mem::size_of::() + std::mem::size_of::()) } fn write(mut writer: impl Writer, src: &Self::Src) -> WriteResult<()> { let mut buf = [0u8; 6]; buf[..4].copy_from_slice(&src.0.to_le_bytes()); buf[4..].copy_from_slice(&src.1.to_le_bytes()); writer.write(&buf) } } ``` -------------------------------- ### Integrate Bytes Crate with Wincode Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/11-features-and-build.md When the `bytes` feature is enabled, Wincode allows integration with `bytes::Bytes`. This example shows how to use `#[wincode(with = "containers::Vec")]` to serialize `Bytes` efficiently. ```rust use bytes::Bytes; use wincode::{containers, len::BincodeLen}; #[derive(SchemaRead, SchemaWrite)] struct Data { #[wincode(with = "containers::Vec")] payload: Bytes, } ``` -------------------------------- ### Implement SchemaRead for Custom Type Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/01-core-traits.md Example of implementing the SchemaRead trait for a custom struct to enable deserialization with in-place initialization. Ensure the safety requirements regarding initialization on success and no initialization on error are met. ```rust use wincode::{SchemaRead, io::Reader, ReadResult, config::Config}; use core::mem::MaybeUninit; struct MyType(u32, u16); unsafe impl<'de, C: Config> SchemaRead<'de, C> for MyType { type Dst = MyType; fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit) -> ReadResult<()> { let mut buf = [0u8; 6]; reader.copy_into_slice(&mut buf.iter_mut().map(|b| MaybeUninit::new(*b)).collect::>())?; dst.write(MyType( u32::from_le_bytes([buf[0], buf[1], buf[2], buf[3]]), u16::from_le_bytes([buf[4], buf[5]]), )); Ok(()) } } ``` -------------------------------- ### Configure Documentation Build for Docs.rs Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/11-features-and-build.md Configure the documentation build for docs.rs by enabling all features and passing specific rustdoc arguments. This ensures comprehensive documentation is published and warnings are treated as errors. ```toml [package.metadata.docs.rs] all-features = true rustdoc-args = ["--cfg", "docsrs", "-D", "warnings"] ``` -------------------------------- ### Minimal Wincode Configuration (No-Std) Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/11-features-and-build.md This configuration enables serialization/deserialization with heap allocations but without relying on the standard library. It requires explicitly disabling default features and enabling the `alloc` feature. ```toml [dependencies] wincode = { version = "0.5.5", default-features = false, features = ["alloc"] } ``` -------------------------------- ### Run wincode Benchmarks Source: https://github.com/anza-xyz/wincode/blob/master/README.md Execute benchmarks to compare the performance of wincode against bincode. Ensure the 'derive' feature is enabled for accurate comparison. ```bash cargo bench --features derive ``` -------------------------------- ### Custom Serialization Configuration Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/03-serialization-api.md Demonstrates creating a custom serialization configuration with a preallocation size limit. This is useful when you need to control memory allocation during serialization. ```rust use wincode::config::{Configuration, Serialize as _}; use wincode::len::BincodeLen; // Create custom config with different settings let config = Configuration::default() .with_preallocation_size_limit(8192); let data = vec![1, 2, 3]; let bytes = as wincode::config::Serialize<_>>::serialize(&data, config)?; ``` -------------------------------- ### Running Cargo Benchmarks Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/11-features-and-build.md Execute benchmarks, including comparison against 'bincode' and specifying a particular benchmark suite and baseline. ```bash # Benchmark against bincode cargo bench --features derive # Specific benchmark cargo bench --features derive --bench benchmarks -- --baseline=default ``` -------------------------------- ### Borrowed Deserialization for Types with Lifetimes Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/10-implementation-guide.md For types with lifetime parameters, use reader borrowing to read data directly into the type. This example demonstrates reading a borrowed slice from the reader. ```rust unsafe impl<'de, C: ConfigCore> SchemaRead<'de, C> for BytesRef<'de> { type Dst = BytesRef<'de>; fn read(mut reader: impl Reader<'de>, dst: &mut MaybeUninit) -> ReadResult<()> { // Read length let len = >::get(&mut reader)?; // Borrow slice from reader let bytes = reader.take_borrowed(len as usize)?; dst.write(BytesRef { bytes }); Ok(()) } } #[derive(SchemaRead, SchemaWrite)] struct BytesRef<'a> { bytes: &'a [u8], } ``` -------------------------------- ### Override Collection Length Encoding with Custom Type Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/00-index.md Customize the length encoding for a specific field within a struct. This example uses a u16 for the length of a Vec payload. ```rust use wincode::{containers, len::UseIntLen, SchemaRead, SchemaWrite}; #[derive(SchemaRead, SchemaWrite)] struct Message { // Length as u16 (max 65,535 items) #[wincode(with = "containers::Vec>")] payload: Vec, } ``` -------------------------------- ### Release Profile Configuration Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/11-features-and-build.md Optimize production builds by enabling level 3 optimizations, link-time optimization (LTO), and reducing codegen units. ```toml [profile.release] opt-level = 3 lto = true codegen-units = 1 ``` -------------------------------- ### VecDeque Container with Custom Length Encoding Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/05-containers-and-collections.md Wrap `std::collections::VecDeque` using `containers::VecDeque` and specify the length encoding, for example, `UseIntLen` for a 4-byte length. ```rust use wincode::{containers, len::UseIntLen, SchemaRead, SchemaWrite}; use std::collections::VecDeque; #[derive(SchemaRead, SchemaWrite)] struct MyStruct { #[wincode(with = "containers::VecDeque>")] deque: VecDeque, } ``` -------------------------------- ### Running Fuzz Testing Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/11-features-and-build.md Execute the fuzzing harness for roundtrip correctness by navigating to the fuzz directory and running the 'roundtrip' fuzz target. ```bash cd fuzz cargo +nightly fuzz run roundtrip ``` -------------------------------- ### Running Cargo Tests Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/11-features-and-build.md Execute tests with default features, all features, or specific features like 'derive'. Includes command for property-based tests with release optimization. ```bash # All tests with default features cargo test # Tests with all features cargo test --all-features # Tests with derive macros cargo test --features derive # Property-based tests cargo test --all-features --release ``` -------------------------------- ### Wrapping Foreign Types with POD Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/05-containers-and-collections.md Demonstrates how to create Plain Old Data (POD) wrappers for foreign types to use them with Wincode's derived schema types and collections. Ensure the foreign type meets Wincode's safety requirements. ```rust use wincode::containers; use wincode_derive::{SchemaRead, SchemaWrite}; use serde::{Serialize, Deserialize}; // Foreign type from another crate #[derive(Serialize, Deserialize, Clone, Copy)] #[repr(transparent)] pub struct Address([u8; 32]); #[derive(Serialize, Deserialize, Clone, Copy)] #[repr(transparent)] pub struct Hash([u8; 32]); // Create POD wrappers wincode::pod_wrapper! { unsafe struct PodAddress(Address); unsafe struct PodHash(Hash); } // Use in derived schema types #[derive(SchemaRead, SchemaWrite)] struct MyStruct { #[wincode(with = "PodAddress")] address: Address, #[wincode(with = "containers::Vec>")] addresses: Vec
, } ``` -------------------------------- ### Basic SchemaWrite Implementation Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/10-implementation-guide.md Implement SchemaWrite for a custom type. Provide size_of for exact byte count and write to serialize the data. ```rust use wincode::{SchemaWrite, io::Writer, WriteResult, TypeMeta, config::ConfigCore}; unsafe impl SchemaWrite for MyType { type Src = MyType; // Optional: provide metadata for optimizations const TYPE_META: TypeMeta = TypeMeta::Dynamic; fn size_of(src: &Self::Src) -> WriteResult { // Calculate exact size of serialized form Ok(std::mem::size_of_val(src)) } fn write(mut writer: impl Writer, src: &Self::Src) -> WriteResult<()> { // Write bytes to writer writer.write(&[/* bytes */])?; Ok(()) } } ``` -------------------------------- ### Testing Wincode Implementations Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/10-implementation-guide.md Implement comprehensive tests for Wincode schemas, including roundtrip serialization/deserialization, size verification, and compatibility checks. ```rust #[cfg(test)] mod tests { use super::*; use wincode::{Serialize, Deserialize}; #[test] fn roundtrip() { let original = MyType { /* ... */ }; let bytes = MyType::serialize(&original).unwrap(); let deserialized: MyType = wincode::deserialize(&bytes).unwrap(); assert_eq!(original, deserialized); } #[test] fn size_matches_bytes() { let value = MyType { /* ... */ }; let size = >::size_of(&value).unwrap(); let bytes = >::write(&mut Vec::new(), &value).unwrap(); assert_eq!(size, bytes.len()); } #[test] fn bincode_compatible() { let value = MyType { /* ... */ }; let wincode_bytes = wincode::serialize(&value).unwrap(); let bincode_bytes = bincode::serialize(&value).unwrap(); assert_eq!(wincode_bytes, bincode_bytes); } } ``` -------------------------------- ### Standard Wincode Serialization Configuration Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/11-features-and-build.md This is the default configuration for Wincode, providing serialization and deserialization capabilities with both the standard library and heap allocations enabled. ```toml [dependencies] wincode = { version = "0.5.5" } ``` -------------------------------- ### ZeroCopy Trait Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/01-core-traits.md Marker trait for types that can be directly referenced from serialized data without copying or validation, using the default configuration. It provides methods to get immutable or mutable references directly from byte slices. ```APIDOC ## ZeroCopy Trait ### Purpose Marker trait for types that can be directly referenced from serialized data without copying or validation, using the default configuration. ### Methods | Method | Signature | Description | |--------|-----------|-------------| | `from_bytes` | `fn(bytes: &'de [u8]) -> ReadResult<&'de Self>` | Get immutable reference to type from bytes | | `from_bytes_mut` | `fn(bytes: &'de mut [u8]) -> ReadResult<&'de mut Self>` | Get mutable reference to type from bytes | ### Example ```rust use wincode::{SchemaRead, SchemaWrite, ZeroCopy}; #[derive(SchemaRead, SchemaWrite)] #[repr(C)] struct Data { bytes: [u8; 7], the_answer: u8, } let serialized = vec![1, 2, 3, 4, 5, 6, 7, 42]; let data_ref = Data::from_bytes(&serialized)?; assert_eq!(data_ref.bytes, [1, 2, 3, 4, 5, 6, 7]); assert_eq!(data_ref.the_answer, 42); ``` ``` -------------------------------- ### Configuration-Aware Schema Implementation Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/10-implementation-guide.md Implement `SchemaWrite` using configuration types to dynamically adjust behavior, such as preallocation limits and byte order. ```rust use wincode::{SchemaWrite, config::ConfigCore, io::Writer, WriteResult}; unsafe impl SchemaWrite for ConfigAware { type Src = ConfigAware; fn write(writer: impl Writer, src: &Self::Src) -> WriteResult<()> { // Use configuration to determine encoding if let Some(limit) = C::PREALLOCATION_SIZE_LIMIT { // Config has preallocation limit validate_size(src, limit)?; } // Dispatch to byte order let bytes = match C::ByteOrder::ENDIAN { Endian::Little => src.to_le_bytes(), Endian::Big => src.to_be_bytes(), }; writer.write(&bytes)?; Ok(()) } } ``` -------------------------------- ### Handle Preallocation Size Limit Error Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/07-error-types.md Shows how to specifically catch and handle the `PreallocationSizeLimit` error during deserialization. This is useful when dealing with potentially large data structures. ```rust use wincode::ReadError; match deserialize(&bytes) { Ok(data) => process(data), Err(ReadError::PreallocationSizeLimit { needed, limit }) => { eprintln!("Data too large: needs {} bytes, but limit is {} bytes", needed, limit); // Increase limit, split data, or error } Err(e) => return Err(e), } ``` -------------------------------- ### Full Featured Wincode Configuration Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/11-features-and-build.md Enables all available type support, derive macros, and comprehensive ecosystem integrations for Wincode. This configuration includes features for uuid, bytes, indexmap, smallvec, and ecow. ```toml [dependencies] wincode = { version = "0.5.5", features = [ "derive", "uuid", "bytes", "indexmap", "smallvec", "ecow", ] } ``` -------------------------------- ### Handling Wincode Write Errors Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/07-error-types.md Demonstrates handling specific write errors, such as `PreallocationSizeLimit` and `LengthEncodingOverflow`, during serialization. Ensure necessary imports are present. ```rust use wincode::{WriteError, Serialize}; let large_vec = vec![0u8; 100_000_000]; // 100 MB match large_vec.serialize() { Ok(bytes) => println!("Serialized {} bytes", bytes.len()), Err(WriteError::PreallocationSizeLimit { needed, limit }) => { eprintln!("Collection too large: needed {} bytes, limit is {}", needed, limit); } Err(WriteError::LengthEncodingOverflow(encoding)) => { eprintln!("Length {} exceeds capacity of {}", large_vec.len(), encoding); } Err(e) => eprintln!("Other error: {}", e), } ``` -------------------------------- ### Create Zero-Copy Wrapper with pod_wrapper! Macro Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/06-derive-macros.md The pod_wrapper! macro creates a zero-copy wrapper for Plain Old Data (POD) types, enabling optimized SchemaRead and SchemaWrite via memcpy. The wrapped type must meet specific safety requirements for raw byte copying. ```rust use serde::{Serialize, Deserialize}; #[derive(Serialize, Deserialize, Clone, Copy)] #[repr(transparent)] struct Signature([u8; 64]); wincode::pod_wrapper! { unsafe struct PodSignature(Signature); } // Now use PodSignature in schema types #[derive(wincode_derive::SchemaRead, wincode_derive::SchemaWrite)] struct Transaction { #[wincode(with = "PodSignature")] signature: Signature, } ``` -------------------------------- ### Vec with BincodeLen Length Encoding Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/05-containers-and-collections.md Demonstrates using `BincodeLen` for Vec length encoding, which defaults to `u64` with the configuration's integer encoding, mimicking bincode's default behavior. ```rust use wincode::{containers, len::BincodeLen, SchemaRead, SchemaWrite}; #[derive(SchemaRead, SchemaWrite)] struct MyStruct { #[wincode(with = "containers::Vec")] vec: Vec, } ``` -------------------------------- ### Bincode Compatibility Verification Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/11-features-and-build.md Verify that Wincode produces identical byte output to bincode for the same data structure. This is crucial for ensuring compatibility. ```rust let val = MyType { /* ... */ }; // Both produce identical bytes let wincode_bytes = wincode::serialize(&val)?; let bincode_bytes = bincode::serialize(&val)?; assert_eq!(wincode_bytes, bincode_bytes); ``` -------------------------------- ### Struct Layout for Zero-Copy Safety Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/09-zero-copy-deserialization.md Demonstrates how to reorder struct fields to eliminate alignment padding, ensuring zero-copy safety. Use this when the order of fields can be changed without affecting external compatibility. ```rust use wincode_derive::{SchemaRead, SchemaWrite}; // ❌ Has padding (alignment hole) #[derive(SchemaRead, SchemaWrite)] #[repr(C)] struct BadLayout { a: u8, // 1 byte // 3 bytes padding b: u32, // 4 bytes c: u16, // 2 bytes d: u8, // 1 byte // 1 byte padding } // ✅ No padding (zero-copy safe) #[derive(SchemaRead, SchemaWrite)] #[repr(C)] struct GoodLayout { b: u32, // 4 bytes (offset 0) c: u16, // 2 bytes (offset 4) a: u8, // 1 byte (offset 6) d: u8, // 1 byte (offset 7) } ``` -------------------------------- ### Feature-Based Build Optimization Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/11-features-and-build.md Reduce compile time by disabling default features and explicitly enabling only necessary features like 'derive'. ```toml [dependencies] wincode = { version = "0.5.5", features = ["derive"], default-features = false } ``` -------------------------------- ### Set Default Preallocation Size Limit Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/04-configuration.md Configures the default preallocation size limit for collections during deserialization to prevent denial-of-service attacks. A secure default of 4 MiB is provided, or the limit can be disabled using `usize::MAX` (not recommended). ```rust use wincode::config::Configuration; let config = Configuration::default() .with_preallocation_size_limit::<{ 1024 * 1024 }>(); // 1 MiB // Or disable it (not recommended) let config = Configuration::default() .with_preallocation_size_limit::<{ usize::MAX }>(); ``` -------------------------------- ### Enable Derive Macros for Wincode Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/11-features-and-build.md To use the `#[derive(SchemaRead, SchemaWrite, UninitBuilder)]` macros, enable the `derive` feature in your Cargo.toml. This is not enabled by default. ```toml [dependencies] wincode = { version = "0.5.5", features = ["derive"] } ``` -------------------------------- ### Default Configuration Type Alias Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/04-configuration.md Provides a convenient alias for the default configuration settings of the Wincode Configuration struct. ```rust pub type DefaultConfig = Configuration; ``` -------------------------------- ### Set Minimum Supported Rust Version Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/11-features-and-build.md Configure the minimum supported Rust version for your project in Cargo.toml. Wincode requires Rust 1.89.0 or later. ```toml [package] rust-version = "1.89.0" ``` -------------------------------- ### Configuring Zero-Copy Alignment Checks Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/09-zero-copy-deserialization.md Demonstrates how to enable or disable alignment checks for zero-copy deserialization using `wincode::config::Configuration`. Alignment checks are enabled by default for safety. ```rust use wincode::config::Configuration; // Alignment checks enabled (default, safe) let config = Configuration::default(); // Disable alignment checks (only if you know what you're doing!) let config = Configuration::default() .with_zero_copy_align_check::(); ``` -------------------------------- ### Direct SeqLen Implementation for Primitive Integers Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/08-sequence-length-encoding.md Allows using primitive integer types directly as length encodings. The configuration's integer encoding is used for variable-width types. ```rust // All primitive integers implement SeqLen directly unsafe impl SeqLen for u8 { ... } unsafe impl SeqLen for u16 { ... } unsafe impl SeqLen for u32 { ... } // ... and others ``` ```rust use wincode::{containers, SchemaRead, SchemaWrite}; #[derive(SchemaRead, SchemaWrite)] struct Data { // u16 as length (configuration's integer encoding) #[wincode(with = "containers::Vec")] vec: Vec, } ``` -------------------------------- ### Set Project Edition Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/11-features-and-build.md Specify the Rust edition for your project in Cargo.toml. Wincode uses the Rust Edition 2024. ```toml [package] edition = "2024" ``` -------------------------------- ### Integrate IndexMap with Wincode Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/11-features-and-build.md When the `indexmap` feature is enabled, Wincode supports `indexmap::IndexMap`. This integration preserves the insertion order of key-value pairs during serialization and deserialization, unlike `HashMap`. ```rust use indexmap::IndexMap; #[derive(SchemaRead, SchemaWrite)] struct Config { settings: IndexMap, } ``` -------------------------------- ### SchemaWrite TypeMeta::Static for Optimization Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/10-implementation-guide.md Use TypeMeta::Static for fixed-size types to inform readers and writers about the exact size upfront. Ensure size_of matches the static size. ```rust unsafe impl SchemaWrite for FixedSize { type Src = FixedSize; // Tell readers/writers the exact size upfront const TYPE_META: TypeMeta = TypeMeta::Static { size: 12, // This type is always 12 bytes zero_copy: true, // And it's zero-copy safe }; fn size_of(_: &Self::Src) -> WriteResult { Ok(12) // Must match TYPE_META::Static { size: 12, ... } } fn write(mut writer: impl Writer, src: &Self::Src) -> WriteResult<()> { // Write exactly 12 bytes let mut buf = [0u8; 12]; // ... fill buf ... writer.write(&buf)?; Ok(()) } } ``` -------------------------------- ### In-Place Configuration Updates with Zero-Copy Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/09-zero-copy-deserialization.md Updates configuration values directly within a mutable byte slice using zero-copy deserialization. This avoids copying the configuration data and allows for efficient in-place modifications. ```rust use wincode::{SchemaRead, SchemaWrite, ZeroCopy}; #[derive(SchemaRead, SchemaWrite)] #[repr(C)] pub struct Config { pub feature_flags: u32, pub timeout_ms: u32, pub max_connections: u16, } pub fn update_config(data: &mut [u8]) -> wincode::ReadResult<()> { let config = Config::from_bytes_mut(data)?; config.timeout_ms = 5000; config.feature_flags |= 0x0001; Ok(()) } ``` -------------------------------- ### Wincode Configuration Struct Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/04-configuration.md Defines the structure for compile-time configuration of Wincode's serialization behavior. It uses const generics and phantom data for zero runtime overhead. ```rust pub struct Configuration< const ZERO_COPY_ALIGN_CHECK: bool = true, const PREALLOCATION_SIZE_LIMIT: usize = DEFAULT_PREALLOCATION_SIZE_LIMIT, LengthEncoding = BincodeLen, ByteOrder = LittleEndian, IntEncoding = FixInt, TagEncoding = u32, > { _l: PhantomData, _b: PhantomData, _i: PhantomData, _t: PhantomData, } ``` -------------------------------- ### Integrate EcoString and EcoVec with Wincode Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/11-features-and-build.md When the `ecow` feature is enabled, Wincode supports `ecow::EcoString` and `ecow::EcoVec`. These types provide copy-on-write semantics for strings and vectors, enhancing efficiency. ```rust use ecow::{EcoString, EcoVec}; #[derive(SchemaRead, SchemaWrite)] struct Message { text: EcoString, items: EcoVec, } ``` -------------------------------- ### Basic SchemaRead Implementation Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/10-implementation-guide.md Implement SchemaRead for a custom type. The read method must initialize the destination `MaybeUninit` if it returns Ok(()), and must not initialize it if it returns Err. ```rust use wincode::{SchemaRead, io::Reader, ReadResult, config::ConfigCore}; use core::mem::MaybeUninit; unsafe impl<'de, C: ConfigCore> SchemaRead<'de, C> for MyType { type Dst = MyType; // Optional: provide metadata for optimizations const TYPE_META: TypeMeta = TypeMeta::Dynamic; fn read(reader: impl Reader<'de>, dst: &mut MaybeUninit) -> ReadResult<()> { // Read bytes from reader and initialize dst // MUST initialize dst if returning Ok(()) // MUST NOT initialize dst if returning Err let value = MyType { /* ... */ }; dst.write(value); Ok(()) } } ``` -------------------------------- ### Module Function: serialize() Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/03-serialization-api.md Serializes a type into a new Vec using the default configuration. ```rust let data = vec![1, 2, 3, 4, 5]; let bytes = wincode::serialize(&data)?; ``` -------------------------------- ### Derive SchemaRead and SchemaWrite for Basic Struct Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/06-derive-macros.md Automatically generates serialization and deserialization implementations for a struct. Use this for standard data structures. ```rust use wincode_derive::{SchemaRead, SchemaWrite}; #[derive(SchemaRead, SchemaWrite)] struct Person { id: u32, name: String, age: u8, } let bytes = wincode::serialize(&Person { id: 1, name: "Alice".to_string(), age: 30, })?; let person: Person = wincode::deserialize(&bytes)?; ``` -------------------------------- ### Handle Serialization Write Errors Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/00-index.md Catch specific write errors like PreallocationSizeLimit, which indicates the data exceeds the configured limit. Other general write errors are also handled. ```Rust use wincode::{WriteError, ReadError, Serialize, Deserialize}; match data.serialize() { Ok(bytes) => println!("Serialized: {} bytes", bytes.len()), Err(WriteError::PreallocationSizeLimit { needed, limit }) => { eprintln!("Data too large: needs {}, limit {}", needed, limit); } Err(e) => eprintln!("Error: {}", e), } ``` -------------------------------- ### SchemaWrite Delegating to Field Schemas Source: https://github.com/anza-xyz/wincode/blob/master/_autodocs/10-implementation-guide.md For composite types, implement SchemaWrite by delegating to the SchemaWrite implementations of its fields. Ensure size_of and write calls correctly handle each field. ```rust use wincode::{SchemaWrite, io::Writer, WriteResult, config::ConfigCore}; struct Composite { id: u32, data: Vec, } unsafe impl SchemaWrite for Composite { type Src = Composite; fn size_of(src: &Self::Src) -> WriteResult { let id_size = >::size_of(&src.id)?; let data_size = as SchemaWrite>::size_of(&src.data)?; Ok(id_size + data_size) } fn write(mut writer: impl Writer, src: &Self::Src) -> WriteResult<()> { >::write(writer.by_ref(), &src.id)?; as SchemaWrite>::write(writer, &src.data)?; Ok(()) } } ```