Skip to main content

bincode_next/
lib.rs

1#![no_std]
2#![cfg_attr(docsrs, feature(doc_cfg))]
3#![allow(internal_features)]
4#![cfg_attr(is_nightly, feature(core_intrinsics))]
5
6//! Bincode-next is a crate for encoding and decoding using a tiny binary
7//! serialization strategy.  Using it, you can easily go from having
8//! an object in memory, quickly serialize it to bytes, and then
9//! deserialize it back just as fast!
10//!
11//! If you're coming from bincode 1, check out our [migration guide](migration_guide/index.html)
12//!
13//! # Serde
14//!
15//! Starting from bincode 2, serde is now an optional dependency. If you want to use serde, please enable the `serde` feature. See [Features](#features) for more information.
16//!
17//! # Features
18//!
19//! |Name  |Default?|Affects MSRV?|Supported types for Encode/Decode|Enabled methods                                                  |Other|
20//! |------|--------|-------------|-----------------------------------------|-----------------------------------------------------------------|-----|
21//! |std   | Yes    | No          |`HashMap` and `HashSet`|`decode_from_std_read` and `encode_into_std_write`|
22//! |alloc | Yes    | No          |All common containers in alloc, like `Vec`, `String`, `Box`|`encode_to_vec`|
23//! |derive| Yes    | No          |||Enables the `BorrowDecode`, `Decode`, `Encode`, `Fingerprint` and `BitPacked` derive macros|
24//! |serde | No     | Yes (MSRV reliant on serde)|`Compat` and `BorrowCompat`, which will work for all types that implement serde's traits|serde-specific encode/decode functions in the [`serde`\] module|Note: There are several [known issues](serde/index.html#known-issues) when using serde and bincode|
25//! |zero-copy| No    | No          |`RelativePtr`, `ZeroArray`, `ZeroSlice`, `ZeroStr`, `ZeroString`|Enables the `relative_ptr` module and the `ZeroCopy` derive macro|Zero-copy nested structures using offsets|
26//! |static-size| No    | No          |||Enables the `static_size` module, the `bounded` module and the `StaticSize` derive macro|Compile-time size verification|
27//! |async-fiber| No    | No          |||Enables the `async_fiber` module and async decoding|Async fiber-based encoding/decoding|
28//!
29//! # Which functions to use
30//!
31//! Bincode-next has a couple of pairs of functions that are used in different situations.
32//!
33//! |Situation|Encode|Decode|
34//! |---|---|---
35//! |You're working with [`fs::File`\] or [`net::TcpStream`\]|[`encode_into_std_write`\]|[`decode_from_std_read`\]|
36//! |you're working with in-memory buffers|[`encode_to_vec`\]|[`decode_from_slice`\]|
37//! |You want to use a custom [Reader] and [Writer]|[`encode_into_writer`\]|[`decode_from_reader`\]|
38//! |You're working with pre-allocated buffers or on embedded targets|[`encode_into_slice`\]|[`decode_from_slice`\]|
39//! |You're working with tokio| - |[`decode_async_tokio_with_context`\][`decode_async_tokio`\]|
40//! |You're working with futures-io| - |[`decode_async_with_context`\][`decode_async`\]|
41//!
42//! **Note:** If you're using `serde`, use `bincode_next::serde::...` instead of `bincode_next::...`
43//!
44//! ## Getting Started
45//!
46//! Add `bincode-next` to your `Cargo.toml`:
47//!
48//! ```toml
49//! [dependencies]
50//! bincode-next = "3.1.1"
51//! ```
52//!
53//! ### Basic Encode / Decode
54//!
55//! ```rust
56//! let mut slice = [0u8; 100];
57//!
58//! // You can encode any type that implements `Encode`.
59//! // You can automatically implement this trait on custom types with the `derive` feature.
60//! let input = (
61//!     0u8,
62//!     10u32,
63//!     10000i128,
64//!     'a',
65//!     [0u8, 1u8, 2u8, 3u8]
66//! );
67//!
68//! let length = bincode_next::encode_into_slice(
69//!     input,
70//!     &mut slice,
71//!     bincode_next::config::standard()
72//! ).unwrap();
73//!
74//! let slice = &slice[..length];
75//! println!("Bytes written: {:?}", slice);
76//!
77//! // Decoding works the same as encoding.
78//! // The trait used is `Decode`, and can also be automatically implemented with the `derive` feature.
79//! let decoded: (u8, u32, i128, char, [u8; 4]) = bincode_next::decode_from_slice(slice, bincode_next::config::standard()).unwrap().0;
80//!
81//! assert_eq!(decoded, input);
82//! ```
83//!
84//! ```rust
85//! use bincode_next::Decode;
86//! use bincode_next::Encode;
87//! use bincode_next::config;
88//!
89//! #[derive(Encode, Decode, PartialEq, Debug)]
90//! struct Entity {
91//!     x: f32,
92//!     y: f32,
93//! }
94//!
95//! #[derive(Encode, Decode, PartialEq, Debug)]
96//! struct World(Vec<Entity>);
97//!
98//! fn main() {
99//!     let config = config::standard();
100//!     let world = World(vec![Entity { x: 0.0, y: 4.0 }, Entity { x: 10.0, y: 20.5 }]);
101//!
102//!     let encoded: Vec<u8> = bincode_next::encode_to_vec(&world, config).unwrap();
103//!     let (decoded, len): (World, usize) =
104//!         bincode_next::decode_from_slice(&encoded[..], config).unwrap();
105//!
106//!     assert_eq!(world, decoded);
107//!     assert_eq!(len, encoded.len());
108//! }
109//! ```
110//!
111//! ---
112//!
113//! ### Serde Compatibility
114//!
115//! Bincode-Next works with any type that already derives `serde::Serialize` /
116//! `serde::Deserialize` — no need to re-derive `Encode`/`Decode` at all. Enable the
117//! `serde` feature and use the `bincode_next::serde::*` entry points.
118//!
119//! ```toml
120//! [dependencies]
121//! bincode-next = { version = "3.1.1", features = ["serde"] }
122//! serde = { version = "1", features = ["derive"] }
123//! ```
124//!
125//! ```rust
126//! # #[cfg(feature = "serde")] {
127//! use serde::Deserialize;
128//! use serde::Serialize;
129//!
130//! // Only serde derives — no Encode/Decode needed.
131//! #[derive(Serialize, Deserialize, PartialEq, Debug)]
132//! struct Config {
133//!     host: String,
134//!     port: u16,
135//!     #[serde(default)]
136//!     retries: u8,
137//! }
138//!
139//! fn main() {
140//!     let cfg = Config {
141//!         host: "localhost".into(),
142//!         port: 8080,
143//!         retries: 3,
144//!     };
145//!
146//!     // Encode via serde — honours all #[serde(...)] attributes
147//!     let bytes =
148//!         bincode_next::serde::encode_to_vec(&cfg, bincode_next::config::standard()).unwrap();
149//!
150//!     let (decoded, _): (Config, usize) =
151//!         bincode_next::serde::decode_from_slice(&bytes, bincode_next::config::standard())
152//!             .unwrap();
153//!     assert_eq!(cfg, decoded);
154//! }
155//! # }
156//! ```
157//!
158//! You can also mix: derive both `Serialize` and `Encode` on the same type, then use
159//! `#[bincode(with_serde)]` on individual fields to route specific fields through their
160//! serde impl (useful for types that only implement `Serialize`, not `Encode`).
161//!
162//! ---
163//!
164//! ### Bit-Packing
165//!
166//! Enable bit-packing in your configuration to pack fields at bit granularity. Consecutive
167//! `#[bincode(bits = N)]` fields share bytes — 3 bits + 5 bits = exactly 1 byte on the wire.
168//!
169//! ```rust
170//! use bincode_next::BitPacked;
171//! use bincode_next::config;
172//!
173//! #[derive(BitPacked, PartialEq, Debug)]
174//! struct Telemetry {
175//!     #[bincode(bits = 1)]
176//!     is_active: bool,
177//!     #[bincode(bits = 1)]
178//!     has_error: bool,
179//!     #[bincode(bits = 3)]
180//!     mode: u8,
181//!     // ↑ 5 bits total → 1 byte on the wire when bit-packing is enabled
182//! }
183//!
184//! fn main() {
185//!     let config = config::standard().with_bit_packing();
186//!     let t = Telemetry {
187//!         is_active: true,
188//!         has_error: false,
189//!         mode: 5,
190//!     };
191//!
192//!     let encoded = bincode_next::encode_to_vec(&t, config).unwrap();
193//!     assert_eq!(encoded.len(), 1); // 5 bits packed into 1 byte
194//!
195//!     let (decoded, _): (Telemetry, usize) =
196//!         bincode_next::decode_from_slice(&encoded, config).unwrap();
197//!     assert_eq!(decoded, t);
198//! }
199//! ```
200//!
201//! ---
202//!
203//! ### Zero-Copy Structures
204//!
205//! The `zero-copy` feature lets you build flat byte blobs that can be accessed as typed
206//! Rust references **without any deserialization step** — ideal for memory-mapped files,
207//! shared memory, and IPC.
208//!
209//! `#[derive(ZeroCopy)]` on a `#[repr(C, u8)]` enum generates a companion `*Builder`
210//! type that mirrors every variant. Use `ZeroBuilder` to accumulate bytes, `reserve::<T>()`
211//! to claim space, and `build_to_target()` to write and get back a live typed reference
212//! directly into the buffer.
213//!
214//! ```rust
215//! #[cfg(all(feature = "zero-copy", feature = "alloc"))]
216//! use bincode_next::DeepValidator;
217//! #[cfg(all(feature = "zero-copy", feature = "alloc"))]
218//! use bincode_next::ZeroBuilder;
219//! #[cfg(all(feature = "zero-copy", feature = "alloc"))]
220//! use bincode_next::ZeroCopyBuilder;
221//!
222//! /// Packet layout stored verbatim in the byte blob.
223//! #[derive(bincode_derive_next::ZeroCopy, Debug, PartialEq, Eq)]
224//! #[repr(C, u8)]
225//! enum Packet {
226//!     Ping,
227//!     Data { seq: u32, value: u64 },
228//!     Error(u32),
229//! }
230//!
231//! #[cfg(all(feature = "zero-copy", feature = "alloc"))]
232//! fn main() {
233//!     let mut builder = ZeroBuilder::new();
234//!
235//!     // — Ping ----------------------------------------------------------------
236//!     let ping_offset = builder.reserve::<Packet>();
237//!     let ping_view = PacketBuilder::Ping.build_to_target(&mut builder, ping_offset);
238//!     assert_eq!(ping_view, Packet::Ping);
239//!
240//!     // — Data ----------------------------------------------------------------
241//!     let data_offset = builder.reserve::<Packet>();
242//!     let data_view = PacketBuilder::Data {
243//!         seq: 7,
244//!         value: 0xDEAD_BEEF,
245//!     }
246//!     .build_to_target(&mut builder, data_offset);
247//!
248//!     match data_view {
249//!         | Packet::Data { seq, value } => {
250//!             assert_eq!(seq, 7);
251//!             assert_eq!(value, 0xDEAD_BEEF);
252//!         },
253//!         | _ => unreachable!(),
254//!     }
255//!
256//!     // — Error ---------------------------------------------------------------
257//!     let err_offset = builder.reserve::<Packet>();
258//!     let err_view = PacketBuilder::Error(404).build_to_target(&mut builder, err_offset);
259//!
260//!     match err_view {
261//!         | Packet::Error(code) => assert_eq!(code, 404),
262//!         | _ => unreachable!(),
263//!     }
264//!
265//!     // All three packets live in one contiguous allocation — no heap per variant.
266//!     let _bytes = builder.finish();
267//! }
268//! ```
269//!
270//! For lower-level use, `RelativePtr<T, OFFSET_SIZE>` lets you embed self-relative
271//! pointers inside any `#[repr(C)]` struct:
272//!
273//! ```rust
274//! #[cfg(feature = "zero-copy")]
275//! use bincode_next::DeepValidator;
276//! #[cfg(feature = "zero-copy")]
277//! use bincode_next::RelativePtr;
278//!
279//! #[repr(align(8))]
280//! struct AlignedBuf<const N: usize>(pub [u8; N]);
281//!
282//! #[cfg(feature = "zero-copy")]
283//! fn relative_ptr_example() {
284//!     let mut buf = AlignedBuf([0u8; 12]);
285//!     let b = &mut buf.0;
286//!
287//!     b[0..4].copy_from_slice(&8i32.to_ne_bytes()); // 4-byte signed offset stored at position 0
288//!     b[8..12].copy_from_slice(&42u32.to_ne_bytes()); // target value at position 8
289//!
290//!     let ptr = unsafe { &*(b.as_ptr() as *const RelativePtr<u32, 4>) };
291//!     // is_valid_deep also validates any nested relative pointers recursively
292//!     assert!(ptr.is_valid_deep(b));
293//!     assert_eq!(*ptr.get(b).unwrap(), 42);
294//! }
295//! ```
296//!
297//! ---
298//!
299//! ### Compile-time Memory Bounds (`StaticSize`)
300//!
301//! `StaticSize` gives a compile-time upper bound on encoded size — useful for stack
302//! allocation and `no_std` fixed-size buffers. Enable with the `static-size` feature.
303//!
304//! `MAX_SIZE` assumes worst-case varint encoding; `PACKED_MAX_SIZE` is tighter when
305//! bit-packing is active (consecutive `#[bincode(bits = N)]` fields share bytes).
306//!
307//! ```rust
308//! #[cfg(feature = "static-size")]
309//! use bincode_next::BitPacked;
310//! #[cfg(feature = "static-size")]
311//! use bincode_next::StaticSize;
312//!
313//! #[cfg(feature = "static-size")]
314//! #[derive(bincode_next::Encode, bincode_next::Decode, StaticSize, PartialEq, Debug)]
315//! struct Packet {
316//!     seq: u32,  // varint: up to 5 bytes
317//!     data: u64, // varint: up to 9 bytes
318//! }
319//!
320//! #[cfg(feature = "static-size")]
321//! #[derive(BitPacked, StaticSize, PartialEq, Debug)]
322//! struct Flags {
323//!     #[bincode(bits = 4)]
324//!     kind: u8,
325//!     #[bincode(bits = 4)]
326//!     priority: u8,
327//! }
328//!
329//! #[cfg(feature = "static-size")]
330//! fn main() {
331//!     // Packet: 5 (u32) + 9 (u64) = 14 bytes worst-case
332//!     assert_eq!(Packet::MAX_SIZE, 14);
333//!
334//!     // Flags without packing: two full u8s = 2 bytes
335//!     assert_eq!(Flags::MAX_SIZE, 2);
336//!     // Flags with packing: 4+4 bits = 1 byte
337//!     assert_eq!(Flags::PACKED_MAX_SIZE, 1);
338//!
339//!     // Use MAX_SIZE for a guaranteed-large-enough stack buffer
340//!     let val = Packet { seq: 1, data: 42 };
341//!     let mut buf = [0u8; Packet::MAX_SIZE];
342//!     let _ = bincode_next::encode_into_slice(&val, &mut buf, bincode_next::config::standard())
343//!         .unwrap();
344//!
345//!     // decode_from_slice_static takes &[u8; N] — pass the whole fixed-size array
346//!     let decoded: Packet =
347//!         bincode_next::decode_from_slice_static(&buf, bincode_next::config::standard()).unwrap();
348//!     assert_eq!(val, decoded);
349//! }
350//! ```
351//!
352//! ---
353//!
354//! ### Schema Fingerprinting
355//!
356//! Fingerprinting embeds a 64-bit schema hash into each encoded message. The hash covers
357//! field names, types, ordering, **and the full configuration** — including format
358//! (Bincode vs CBOR), endianness, integer encoding, and all CBOR options. Any mismatch
359//! between encoder and decoder returns a `DecodeError::SchemaHashMismatch`.
360//!
361//! ```rust
362//! use bincode_next::Decode;
363//! use bincode_next::Encode;
364//! use bincode_next::Fingerprint;
365//! use bincode_next::config;
366//!
367//! #[derive(Encode, Decode, Fingerprint, PartialEq, Debug, Clone)]
368//! struct PlayerV1 {
369//!     id: u32,
370//!     score: u64,
371//! }
372//!
373//! // Adding a field changes the schema hash → decode_from_slice returns an error
374//! #[derive(Encode, Decode, Fingerprint, PartialEq, Debug, Clone)]
375//! struct PlayerV2 {
376//!     id: u32,
377//!     score: u64,
378//!     level: u32, // new field
379//! }
380//!
381//! fn main() {
382//!     let config = config::standard().with_fingerprint();
383//!     let player = PlayerV1 { id: 1, score: 9001 };
384//!
385//!     let encoded = bincode_next::encode_to_vec(&player, config).unwrap();
386//!
387//!     // Decoding as V1 succeeds
388//!     let (decoded, _): (PlayerV1, usize) =
389//!         bincode_next::decode_from_slice(&encoded, config).unwrap();
390//!     assert_eq!(decoded, player);
391//!
392//!     // Decoding as V2 fails — schema hashes differ
393//!     let result = bincode_next::decode_from_slice::<PlayerV2, _>(&encoded, config);
394//!     assert!(result.is_err());
395//!
396//!     // Switching formats also changes the hash; cross-format decoding is caught too
397//!     let cbor_config = config::standard().with_fingerprint().with_cbor_format();
398//!     let result = bincode_next::decode_from_slice::<PlayerV1, _>(&encoded, cbor_config);
399//!     assert!(result.is_err());
400//! }
401//! ```
402//!
403//! ---
404//!
405//! ### CBOR Format
406//!
407//! Bincode-Next implements full RFC 8949 CBOR encoding. Switch formats with a single
408//! config call; all existing derives work unchanged.
409//!
410//! ```rust
411//! use bincode_next::Decode;
412//! use bincode_next::Encode;
413//! use bincode_next::config;
414//!
415//! #[derive(Encode, Decode, PartialEq, Debug)]
416//! struct Event {
417//!     timestamp: u64,
418//!     value: f32,
419//! }
420//!
421//! fn main() {
422//!     let config = config::standard().with_cbor_format();
423//!     let event = Event {
424//!         timestamp: 1_700_000_000,
425//!         value: 3.14,
426//!     };
427//!
428//!     let encoded = bincode_next::encode_to_vec(&event, config).unwrap();
429//!     let (decoded, _): (Event, usize) =
430//!         bincode_next::decode_from_slice(&encoded, config).unwrap();
431//!     assert_eq!(event, decoded);
432//!
433//!     // Deterministic (canonical) CBOR for hashing or signing
434//!     let det_config = config::standard().with_deterministic_cbor();
435//!     let det_encoded = bincode_next::encode_to_vec(&event, det_config).unwrap();
436//!     let (det_decoded, _): (Event, usize) =
437//!         bincode_next::decode_from_slice(&det_encoded, det_config).unwrap();
438//!     assert_eq!(event, det_decoded);
439//! }
440//! ```
441//!
442//! ---
443//!
444//! ### Async Fiber Decoding
445//!
446//! Bincode-Next supports true zero-cost asynchronous decoding using **Unified Fiber-backed
447//! Async (UFA)**. Synchronous `Decode` traits run on a dedicated lightweight fiber stack,
448//! avoiding state-machine code generation overhead entirely.
449//!
450//! ```rust
451//! use bincode_next::Decode;
452//! use bincode_next::Encode;
453//! use bincode_next::config;
454//! use bincode_next::decode_async;
455//! use bincode_next::encode_to_vec;
456//!
457//! #[derive(Encode, Decode, PartialEq, Debug)]
458//! struct Entity {
459//!     x: f32,
460//!     y: f32,
461//! }
462//!
463//! #[tokio::main]
464//! #[cfg_attr(miri, ignore)]
465//! async fn main() {
466//!     if cfg!(miri) {
467//!         return;
468//!     }
469//!
470//!     let entity = Entity { x: 1.0, y: 2.0 };
471//!     let encoded = encode_to_vec(&entity, config::standard()).unwrap();
472//!
473//!     // Any type implementing `futures_io::AsyncRead` works here.
474//!     let mut reader: &[u8] = &encoded;
475//!     let decoded: Entity = decode_async(config::standard(), &mut reader).await.unwrap();
476//!     assert_eq!(entity, decoded);
477//! }
478//! ```
479
480// =========================================================================
481// RUST LINT CONFIGURATION: bincode-next
482// =========================================================================
483
484// -------------------------------------------------------------------------
485// LEVEL 1: CRITICAL ERRORS (Deny)
486// -------------------------------------------------------------------------
487#![deny(
488    // Rust Compiler Errors
489    unreachable_code,
490    improper_ctypes_definitions,
491    future_incompatible,
492    nonstandard_style,
493    rust_2018_idioms,
494    clippy::perf,
495    clippy::correctness,
496    clippy::suspicious,
497    clippy::unwrap_used,
498    clippy::expect_used,
499    clippy::indexing_slicing,
500    clippy::arithmetic_side_effects,
501    clippy::missing_safety_doc,
502    clippy::same_item_push,
503    clippy::implicit_clone,
504    clippy::all,
505    clippy::pedantic,
506    missing_docs,
507    clippy::nursery,
508    clippy::single_call_fn,
509)]
510// -------------------------------------------------------------------------
511// LEVEL 2: STYLE WARNINGS (Warn)
512// -------------------------------------------------------------------------
513#![warn(
514    // For `no-std` Situation Issues
515    dead_code,
516    warnings,
517    unsafe_code,
518    clippy::dbg_macro,
519    clippy::todo,
520    clippy::unnecessary_safety_comment
521)]
522// -------------------------------------------------------------------------
523// LEVEL 3: ALLOW/IGNORABLE (Allow)
524// -------------------------------------------------------------------------
525#![allow(
526    clippy::restriction,
527    clippy::inline_always,
528    unused_doc_comments,
529    clippy::cast_possible_truncation,
530    clippy::cast_sign_loss,
531    clippy::cast_possible_wrap,
532    clippy::empty_line_after_doc_comments
533)]
534#![crate_name = "bincode_next"]
535#![crate_type = "rlib"]
536
537#[cfg(feature = "alloc")]
538extern crate alloc;
539#[cfg(any(feature = "std", test))]
540extern crate std;
541
542mod atomic;
543#[doc(hidden)]
544pub mod error_path;
545mod features;
546#[doc(hidden)]
547pub mod utils;
548pub(crate) mod varint;
549
550use de::Decoder;
551use de::read::Reader;
552use enc::write::Writer;
553
554#[cfg(any(
555    feature = "alloc",
556    feature = "std",
557    feature = "derive",
558    feature = "serde",
559    feature = "zero-copy",
560    feature = "static-size"
561))]
562pub use features::*;
563
564/// The major version of the bincode library.
565pub const BINCODE_MAJOR_VERSION: u64 = 3;
566
567#[doc(hidden)]
568pub use rapidhash;
569
570pub mod config;
571/// Fingerprinting support for schema verification.
572pub mod fingerprint;
573
574#[macro_use]
575pub mod de;
576pub mod enc;
577#[macro_use]
578pub mod error;
579
580#[cfg(feature = "static-size")]
581pub use static_size::StaticSize;
582
583pub use de::BorrowDecode;
584pub use de::Decode;
585pub use enc::Encode;
586pub use fingerprint::Fingerprint;
587/// Relative pointer system for zero-copy nested structures
588#[cfg(feature = "zero-copy")]
589pub mod zero_copy {
590    pub use crate::relative_ptr::*;
591}
592#[cfg(feature = "zero-copy")]
593#[doc(hidden)]
594pub use crate::relative_ptr::*;
595
596use config::Config;
597use config::internal::InternalFingerprintGuard;
598
599/// Encode the given value into the given slice. Returns the amount of bytes that have been written.
600///
601/// See the [config] module for more information on configurations.
602///
603/// # Errors
604///
605/// Returns an `EncodeError` if the slice is too small or the value cannot be encoded.
606///
607/// [config]: config/index.html
608#[inline]
609pub fn encode_into_slice<E: enc::Encode, C: Config>(
610    val: E,
611    dst: &mut [u8],
612    config: C,
613) -> Result<usize, error::EncodeError>
614where
615    C::Mode: config::InternalFingerprintGuard<E, C>,
616{
617    let mut writer = enc::write::SliceWriter::new(dst);
618    C::Mode::encode_check(&config, &mut writer)?;
619    let mut encoder = enc::EncoderImpl::<_, C>::new(writer, config);
620    val.encode(&mut encoder)?;
621    Ok(encoder.into_writer().bytes_written())
622}
623
624/// Encode the given value into a custom [`Writer`\].
625///
626/// See the [config] module for more information on configurations.
627///
628/// # Errors
629///
630/// Returns an `EncodeError` if the writer fails or the value cannot be encoded.
631///
632/// [config]: config/index.html
633#[inline]
634pub fn encode_into_writer<E: enc::Encode, W: Writer, C: Config>(
635    val: E,
636    mut writer: W,
637    config: C,
638) -> Result<(), error::EncodeError>
639where
640    C::Mode: config::InternalFingerprintGuard<E, C>,
641{
642    C::Mode::encode_check(&config, &mut writer)?;
643    let mut encoder = enc::EncoderImpl::<_, C>::new(writer, config);
644    val.encode(&mut encoder)?;
645    Ok(())
646}
647
648/// Attempt to decode a given type `D` from the given slice. Returns the decoded output and the amount of bytes read.
649///
650/// Note that this does not work with borrowed types like `&str` or `&[u8]`. For that use [`borrow_decode_from_slice`\].
651///
652/// See the [config] module for more information on configurations.
653///
654/// # Errors
655///
656/// Returns a `DecodeError` if the slice is too small or the data is invalid.
657///
658/// [config]: config/index.html
659#[inline(always)]
660pub fn decode_from_slice<D: de::Decode<()>, C: Config>(
661    src: &[u8],
662    config: C,
663) -> Result<(D, usize), error::DecodeError>
664where
665    C::Mode: config::InternalFingerprintGuard<D, C>,
666{
667    decode_from_slice_with_context(src, config, ())
668}
669
670/// Attempt to decode a given type `D` from the given slice with `Context`. Returns the decoded output and the amount of bytes read.
671///
672/// Note that this does not work with borrowed types like `&str` or `&[u8]`. For that use [`borrow_decode_from_slice`\].
673///
674/// See the [config] module for more information on configurations.
675///
676/// # Errors
677///
678/// Returns a `DecodeError` if the slice is too small or the data is invalid.
679///
680/// [config]: config/index.html
681#[inline]
682pub fn decode_from_slice_with_context<Context, D: de::Decode<Context>, C: Config>(
683    src: &[u8],
684    config: C,
685    context: Context,
686) -> Result<(D, usize), error::DecodeError>
687where
688    C::Mode: config::InternalFingerprintGuard<D, C>,
689{
690    let mut reader = de::read::SliceReader::new(src);
691    C::Mode::decode_check(&config, &mut reader)?;
692    let mut decoder = de::DecoderImpl::<_, C, Context>::new(reader, config, context);
693    let result = D::decode(&mut decoder)?;
694    let bytes_read = src.len() - decoder.reader().slice.len();
695    Ok((result, bytes_read))
696}
697
698/// Attempt to decode a given type `D` from the given slice. Returns the decoded output and the amount of bytes read.
699///
700/// See the [config] module for more information on configurations.
701///
702/// # Errors
703///
704/// Returns a `DecodeError` if the slice is too small or the data is invalid.
705///
706/// [config]: config/index.html
707#[inline(always)]
708pub fn borrow_decode_from_slice<'a, D: de::BorrowDecode<'a, ()>, C: Config>(
709    src: &'a [u8],
710    config: C,
711) -> Result<(D, usize), error::DecodeError>
712where
713    C::Mode: config::InternalFingerprintGuard<D, C>,
714{
715    borrow_decode_from_slice_with_context(src, config, ())
716}
717
718/// Attempt to decode a given type `D` from the given slice with `Context`. Returns the decoded output and the amount of bytes read.
719///
720/// See the [config] module for more information on configurations.
721///
722/// # Errors
723///
724/// Returns a `DecodeError` if the slice is too small or the data is invalid.
725///
726/// [config]: config/index.html
727#[inline]
728pub fn borrow_decode_from_slice_with_context<
729    'a,
730    Context,
731    D: de::BorrowDecode<'a, Context>,
732    C: Config,
733>(
734    src: &'a [u8],
735    config: C,
736    context: Context,
737) -> Result<(D, usize), error::DecodeError>
738where
739    C::Mode: config::InternalFingerprintGuard<D, C>,
740{
741    let mut reader = de::read::SliceReader::new(src);
742    C::Mode::decode_check(&config, &mut reader)?;
743    let mut decoder = de::DecoderImpl::<_, C, Context>::new(reader, config, context);
744    let result = D::borrow_decode(&mut decoder)?;
745    let bytes_read = src.len() - decoder.reader().slice.len();
746    Ok((result, bytes_read))
747}
748
749/// Attempt to decode a given type `D` from the given slice with a compile-time bound check.
750///
751/// This function ensures that the target type `D` cannot exceed the provided buffer capacity `CAP` at compile-time.
752///
753/// # Errors
754///
755/// Returns a `DecodeError` if the slice contains invalid data.
756#[cfg(feature = "static-size")]
757#[inline(always)]
758pub fn decode_from_slice_static<D, const CAP: usize, C>(
759    src: &[u8; CAP],
760    config: C,
761) -> Result<D, error::DecodeError>
762where
763    D: de::Decode<()> + static_size::StaticSize,
764    C: Config,
765    C::Mode: config::InternalFingerprintGuard<D, C>,
766{
767    const {
768        assert!(D::MAX_SIZE <= CAP, "Buffer too small for target type");
769    }
770    let (val, _) = decode_from_slice(src, config)?;
771    Ok(val)
772}
773
774/// Attempt to decode a given type `D` from the given slice with a compile-time bound check and a
775/// decoding context.
776///
777/// This function ensures that the target type `D` cannot exceed the provided buffer capacity `CAP`
778/// at compile-time.
779///
780/// # Errors
781///
782/// Returns a `DecodeError` if the slice contains invalid data.
783#[cfg(feature = "static-size")]
784#[inline(always)]
785pub fn decode_from_slice_static_with_context<Context, D, const CAP: usize, C>(
786    src: &[u8; CAP],
787    config: C,
788    context: Context,
789) -> Result<D, error::DecodeError>
790where
791    D: de::Decode<Context> + static_size::StaticSize,
792    C: Config,
793    C::Mode: config::InternalFingerprintGuard<D, C>,
794{
795    const {
796        assert!(D::MAX_SIZE <= CAP, "Buffer too small for target type");
797    }
798    let (val, _) = decode_from_slice_with_context(src, config, context)?;
799    Ok(val)
800}
801
802/// Attempt to decode a given type `D` from the given slice with a compile-time bound check.
803///
804/// This function ensures that the target type `D` cannot exceed the provided buffer capacity `CAP`
805/// at compile-time.
806///
807/// # Errors
808///
809/// Returns a `DecodeError` if the slice contains invalid data.
810#[cfg(feature = "static-size")]
811#[inline(always)]
812pub fn borrow_decode_from_slice_static<'a, D, const CAP: usize, C>(
813    src: &'a [u8; CAP],
814    config: C,
815) -> Result<D, error::DecodeError>
816where
817    D: de::BorrowDecode<'a, ()> + static_size::StaticSize,
818    C: Config,
819    C::Mode: config::InternalFingerprintGuard<D, C>,
820{
821    const {
822        assert!(D::MAX_SIZE <= CAP, "Buffer too small for target type");
823    }
824    let (val, _) = borrow_decode_from_slice(src, config)?;
825    Ok(val)
826}
827
828/// Attempt to borrow-decode a given type `D` from the given slice with a compile-time bound check
829/// and a decoding context.
830///
831/// This function ensures that the target type `D` cannot exceed the provided buffer capacity `CAP`
832/// at compile-time.
833///
834/// # Errors
835///
836/// Returns a `DecodeError` if the slice contains invalid data.
837#[cfg(feature = "static-size")]
838#[inline(always)]
839pub fn borrow_decode_from_slice_static_with_context<'a, Context, D, const CAP: usize, C>(
840    src: &'a [u8; CAP],
841    config: C,
842    context: Context,
843) -> Result<D, error::DecodeError>
844where
845    D: de::BorrowDecode<'a, Context> + static_size::StaticSize,
846    C: Config,
847    C::Mode: config::InternalFingerprintGuard<D, C>,
848{
849    const {
850        assert!(D::MAX_SIZE <= CAP, "Buffer too small for target type");
851    }
852    let (val, _) = borrow_decode_from_slice_with_context(src, config, context)?;
853    Ok(val)
854}
855
856/// Attempt to decode a given type `D` from the given [`Reader`\].
857///
858/// See the [config] module for more information on configurations.
859///
860/// # Errors
861///
862/// Returns a `DecodeError` if the reader fails or the data is invalid.
863///
864/// [config]: config/index.html
865#[inline]
866pub fn decode_from_reader<D: de::Decode<()>, R: Reader, C: Config>(
867    mut reader: R,
868    config: C,
869) -> Result<D, error::DecodeError>
870where
871    C::Mode: config::InternalFingerprintGuard<D, C>,
872{
873    C::Mode::decode_check(&config, &mut reader)?;
874    let mut decoder = de::DecoderImpl::<_, C, ()>::new(reader, config, ());
875    D::decode(&mut decoder)
876}
877
878/// Attempt to decode a given type `T` from the given async reader safely using a non-blocking fiber.
879///
880/// Requires the `async-fiber` feature.
881///
882/// # Errors
883///
884/// Returns a `DecodeError` if the reader fails or the data is invalid.
885///
886/// [config]: config/index.html
887#[cfg(feature = "async-fiber")]
888#[inline(always)]
889pub async fn decode_async<T, R, C>(
890    config: C,
891    reader: R,
892) -> Result<T, crate::error::DecodeError>
893where
894    T: crate::Decode<()>,
895    R: futures_io::AsyncRead + std::marker::Unpin,
896    C: crate::config::Config,
897    C::Mode: crate::config::InternalFingerprintGuard<T, C>,
898{
899    decode_async_with_context::<T, R, C, ()>(config, reader, ()).await
900}
901
902/// Attempt to decode a given type `T` from the given async reader using a non-blocking fiber and a context.
903///
904/// This is the primary implementation for runtimes that use the `futures-io` traits (e.g. `async-std`, `smol`).
905///
906/// Requires the `async-fiber` feature.
907///
908/// # Errors
909///
910/// Returns a `DecodeError` if the reader fails or the data is invalid.
911///
912/// [config]: config/index.html
913#[cfg(feature = "async-fiber")]
914#[inline]
915pub async fn decode_async_with_context<T, R, C, Context>(
916    config: C,
917    reader: R,
918    context: Context,
919) -> Result<T, crate::error::DecodeError>
920where
921    T: crate::Decode<Context>,
922    R: futures_io::AsyncRead + std::marker::Unpin,
923    C: crate::config::Config,
924    C::Mode: crate::config::InternalFingerprintGuard<T, C>,
925{
926    let bridge = crate::de::async_fiber::AsyncFiberBridge::new(reader);
927    bridge
928        .run(move |fiber_reader| {
929            C::Mode::decode_check(&config, fiber_reader)?;
930            let mut decoder =
931                crate::de::DecoderImpl::<_, C, Context>::new(fiber_reader, config, context);
932            T::decode(&mut decoder)
933        })
934        .await
935}
936
937/// Attempt to decode a given type `T` from the given tokio async reader safely using a non-blocking fiber.
938///
939/// Requires the `tokio` and `async-fiber` features.
940///
941/// # Errors
942///
943/// Returns a `DecodeError` if the reader fails or the data is invalid.
944///
945/// [config]: config/index.html
946#[cfg(all(feature = "tokio", feature = "async-fiber"))]
947#[inline(always)]
948pub async fn decode_async_tokio<T, R, C>(
949    config: C,
950    reader: R,
951) -> Result<T, crate::error::DecodeError>
952where
953    T: crate::Decode<()>,
954    R: tokio::io::AsyncRead + std::marker::Unpin,
955    C: crate::config::Config,
956    C::Mode: crate::config::InternalFingerprintGuard<T, C>,
957{
958    decode_async_tokio_with_context::<T, R, C, ()>(config, reader, ()).await
959}
960
961/// Attempt to decode a given type `T` from the given tokio async reader using a non-blocking fiber and a context.
962///
963/// Requires the `tokio` and `async-fiber` features.
964///
965/// # Errors
966///
967/// Returns a `DecodeError` if the reader fails or the data is invalid.
968///
969/// [config]: config/index.html
970#[cfg(all(feature = "tokio", feature = "async-fiber"))]
971#[inline(always)]
972pub async fn decode_async_tokio_with_context<T, R, C, Context>(
973    config: C,
974    reader: R,
975    context: Context,
976) -> Result<T, crate::error::DecodeError>
977where
978    T: crate::Decode<Context>,
979    R: tokio::io::AsyncRead + std::marker::Unpin,
980    C: crate::config::Config,
981    C::Mode: crate::config::InternalFingerprintGuard<T, C>,
982{
983    let reader = crate::de::async_fiber::TokioReader(reader);
984    decode_async_with_context::<T, _, C, Context>(config, reader, context).await
985}
986
987/// Attempt to decode a given serde-compatible type `T` from the given async reader safely using a non-blocking fiber.
988///
989/// Requires the `async-fiber` and `serde` features.
990///
991/// # Errors
992///
993/// Returns a `DecodeError` if the reader fails or the data is invalid.
994///
995/// [config]: config/index.html
996#[cfg(all(feature = "async-fiber", feature = "serde"))]
997#[inline(always)]
998#[doc(hidden)]
999pub async fn decode_serde_async<'de, T, R, C>(
1000    config: C,
1001    reader: R,
1002) -> Result<T, crate::error::DecodeError>
1003where
1004    T: ::serde::Deserialize<'de>,
1005    R: futures_io::AsyncRead + std::marker::Unpin,
1006    C: crate::config::Config,
1007{
1008    decode_serde_async_with_context::<'de, T, R, C, ()>(config, reader, ()).await
1009}
1010
1011/// Attempt to decode a given serde-compatible type `T` from the given async reader using a non-blocking fiber and a context.
1012///
1013/// Requires the `async-fiber` and `serde` features.
1014///
1015/// # Errors
1016///
1017/// Returns a `DecodeError` if the reader fails or the data is invalid.
1018///
1019/// [config]: config/index.html
1020#[cfg(all(feature = "async-fiber", feature = "serde"))]
1021#[inline]
1022#[doc(hidden)]
1023pub async fn decode_serde_async_with_context<'de, T, R, C, Context>(
1024    config: C,
1025    reader: R,
1026    context: Context,
1027) -> Result<T, crate::error::DecodeError>
1028where
1029    T: ::serde::Deserialize<'de>,
1030    R: futures_io::AsyncRead + std::marker::Unpin,
1031    C: crate::config::Config,
1032{
1033    let bridge = crate::de::async_fiber::AsyncFiberBridge::new(reader);
1034    bridge
1035        .run(move |fiber_reader| {
1036            let decoder =
1037                crate::de::DecoderImpl::<_, C, Context>::new(fiber_reader, config, context);
1038            let mut serde_decoder = crate::features::serde::OwnedSerdeDecoder { de: decoder };
1039            T::deserialize(serde_decoder.as_deserializer())
1040        })
1041        .await
1042}
1043
1044/// Attempt to decode a given serde-compatible type `T` from the given tokio async reader safely using a non-blocking fiber.
1045///
1046/// Requires the `tokio`, `async-fiber` and `serde` features.
1047///
1048/// # Errors
1049///
1050/// Returns a `DecodeError` if the reader fails or the data is invalid.
1051///
1052/// [config]: config/index.html
1053#[cfg(all(feature = "tokio", feature = "async-fiber", feature = "serde"))]
1054#[inline(always)]
1055#[doc(hidden)]
1056pub async fn decode_serde_tokio_async<'de, T, R, C>(
1057    config: C,
1058    reader: R,
1059) -> Result<T, crate::error::DecodeError>
1060where
1061    T: ::serde::Deserialize<'de>,
1062    R: tokio::io::AsyncRead + std::marker::Unpin,
1063    C: crate::config::Config,
1064{
1065    decode_serde_tokio_async_with_context::<'de, T, R, C, ()>(config, reader, ()).await
1066}
1067
1068/// Attempt to decode a given serde-compatible type `T` from the given tokio async reader using a non-blocking fiber and a context.
1069///
1070/// Requires the `tokio`, `async-fiber` and `serde` features.
1071///
1072/// # Errors
1073///
1074/// Returns a `DecodeError` if the reader fails or the data is invalid.
1075///
1076/// [config]: config/index.html
1077#[cfg(all(feature = "tokio", feature = "async-fiber", feature = "serde"))]
1078#[inline(always)]
1079#[doc(hidden)]
1080pub async fn decode_serde_tokio_async_with_context<'de, T, R, C, Context>(
1081    config: C,
1082    reader: R,
1083    context: Context,
1084) -> Result<T, crate::error::DecodeError>
1085where
1086    T: ::serde::Deserialize<'de>,
1087    R: tokio::io::AsyncRead + std::marker::Unpin,
1088    C: crate::config::Config,
1089{
1090    let reader = crate::de::async_fiber::TokioReader(reader);
1091    decode_serde_async_with_context::<'de, T, _, C, Context>(config, reader, context).await
1092}
1093
1094#[cfg(all(feature = "alloc", feature = "derive", doc))]
1095pub mod spec {
1096    #![doc = include_str!("../docs/spec.md")]
1097}
1098
1099#[cfg(doc)]
1100pub mod migration_guide {
1101    #![doc = include_str!("../docs/migration_guide.md")]
1102}
1103
1104// Test the examples in readme.md
1105#[cfg(all(
1106    feature = "std",
1107    feature = "derive",
1108    feature = "serde",
1109    feature = "async-fiber",
1110    feature = "zero-copy",
1111    feature = "static-size",
1112    doctest
1113))]
1114#[cfg_attr(miri, ignore)]
1115mod readme {
1116    #![doc = include_str!("../README.md")]
1117    #![doc = include_str!("../derive/readme.md")]
1118}