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//! |atomic| Yes    | No          |All `Atomic*` integer types, e.g. `AtomicUsize`, and `AtomicBool`||
24//! |derive| Yes    | No          |||Enables the `BorrowDecode`, `Decode`, `Encode`, `Fingerprint` and `BitPacked` derive macros|
25//! |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|
26//! |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|
27//! |static-size| No    | No          |||Enables the `static_size` module, the `bounded` module and the `StaticSize` derive macro|Compile-time size verification|
28//!
29//! # Which functions to use
30//!
31//! Bincode 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//!
40//! **Note:** If you're using `serde`, use `bincode_next::serde::...` instead of `bincode_next::...`
41//!
42//! # Example
43//!
44//! ```rust
45//! let mut slice = [0u8; 100];
46//!
47//! // You can encode any type that implements `Encode`.
48//! // You can automatically implement this trait on custom types with the `derive` feature.
49//! let input = (
50//!     0u8,
51//!     10u32,
52//!     10000i128,
53//!     'a',
54//!     [0u8, 1u8, 2u8, 3u8]
55//! );
56//!
57//! let length = bincode_next::encode_into_slice(
58//!     input,
59//!     &mut slice,
60//!     bincode_next::config::standard()
61//! ).unwrap();
62//!
63//! let slice = &slice[..length];
64//! println!("Bytes written: {:?}", slice);
65//!
66//! // Decoding works the same as encoding.
67//! // The trait used is `Decode`, and can also be automatically implemented with the `derive` feature.
68//! let decoded: (u8, u32, i128, char, [u8; 4]) = bincode_next::decode_from_slice(slice, bincode_next::config::standard()).unwrap().0;
69//!
70//! assert_eq!(decoded, input);
71//! ```
72//!
73//! [`fs::File`\]: `std::fs::File`
74//! [`net::TcpStream`\]: `std::net::TcpStream`
75
76// =========================================================================
77// RUST LINT CONFIGURATION: bincode-next
78// =========================================================================
79
80// -------------------------------------------------------------------------
81// LEVEL 1: CRITICAL ERRORS (Deny)
82// -------------------------------------------------------------------------
83#![deny(
84    // Rust Compiler Errors
85    unreachable_code,
86    improper_ctypes_definitions,
87    future_incompatible,
88    nonstandard_style,
89    rust_2018_idioms,
90    clippy::perf,
91    clippy::correctness,
92    clippy::suspicious,
93    clippy::unwrap_used,
94    clippy::expect_used,
95    clippy::indexing_slicing,
96    clippy::arithmetic_side_effects,
97    clippy::missing_safety_doc,
98    clippy::same_item_push,
99    clippy::implicit_clone,
100    clippy::all,
101    clippy::pedantic,
102    missing_docs,
103    clippy::nursery,
104    clippy::single_call_fn,
105)]
106// -------------------------------------------------------------------------
107// LEVEL 2: STYLE WARNINGS (Warn)
108// -------------------------------------------------------------------------
109#![warn(
110    // For `no-std` Situation Issues
111    dead_code,
112    warnings,
113    unsafe_code,
114    clippy::dbg_macro,
115    clippy::todo,
116    clippy::cast_possible_truncation,
117    clippy::cast_sign_loss,
118    clippy::cast_possible_wrap,
119    clippy::unnecessary_safety_comment
120)]
121// -------------------------------------------------------------------------
122// LEVEL 3: ALLOW/IGNORABLE (Allow)
123// -------------------------------------------------------------------------
124#![allow(
125    clippy::restriction,
126    clippy::inline_always,
127    unused_doc_comments,
128    clippy::empty_line_after_doc_comments
129)]
130#![crate_name = "bincode_next"]
131#![crate_type = "rlib"]
132
133#[cfg(feature = "alloc")]
134extern crate alloc;
135#[cfg(any(feature = "std", test))]
136extern crate std;
137
138mod atomic;
139#[doc(hidden)]
140pub mod error_path;
141mod features;
142#[doc(hidden)]
143pub mod utils;
144pub(crate) mod varint;
145
146use de::Decoder;
147use de::read::Reader;
148use enc::write::Writer;
149
150#[cfg(any(
151    feature = "alloc",
152    feature = "std",
153    feature = "derive",
154    feature = "serde",
155    feature = "zero-copy",
156    feature = "static-size"
157))]
158pub use features::*;
159
160/// The major version of the bincode library.
161pub const BINCODE_MAJOR_VERSION: u64 = 3;
162
163#[doc(hidden)]
164pub use rapidhash;
165
166pub mod config;
167/// Fingerprinting support for schema verification.
168pub mod fingerprint;
169
170#[macro_use]
171pub mod de;
172pub mod enc;
173pub mod error;
174
175#[cfg(feature = "static-size")]
176pub use static_size::StaticSize;
177
178pub use de::BorrowDecode;
179pub use de::Decode;
180pub use enc::Encode;
181pub use fingerprint::Fingerprint;
182#[cfg(feature = "zero-copy")]
183pub use relative_ptr::ZeroCopy;
184#[cfg(feature = "zero-copy")]
185pub use relative_ptr::ZeroCopyType;
186
187#[cfg(not(any(feature = "std", feature = "serde")))]
188#[cfg(feature = "no-std")]
189use panic_halt as _;
190
191use config::Config;
192use config::internal::InternalFingerprintGuard;
193
194/// Encode the given value into the given slice. Returns the amount of bytes that have been written.
195///
196/// See the [config] module for more information on configurations.
197///
198/// # Errors
199///
200/// Returns an `EncodeError` if the slice is too small or the value cannot be encoded.
201///
202/// [config]: config/index.html
203#[inline]
204pub fn encode_into_slice<E: enc::Encode, C: Config>(
205    val: E,
206    dst: &mut [u8],
207    config: C,
208) -> Result<usize, error::EncodeError>
209where
210    C::Mode: config::InternalFingerprintGuard<E, C>,
211{
212    let mut writer = enc::write::SliceWriter::new(dst);
213    C::Mode::encode_check(&config, &mut writer)?;
214    let mut encoder = enc::EncoderImpl::<_, C>::new(writer, config);
215    val.encode(&mut encoder)?;
216    Ok(encoder.into_writer().bytes_written())
217}
218
219/// Encode the given value into a custom [`Writer`\].
220///
221/// See the [config] module for more information on configurations.
222///
223/// # Errors
224///
225/// Returns an `EncodeError` if the writer fails or the value cannot be encoded.
226///
227/// [config]: config/index.html
228#[inline]
229pub fn encode_into_writer<E: enc::Encode, W: Writer, C: Config>(
230    val: E,
231    mut writer: W,
232    config: C,
233) -> Result<(), error::EncodeError>
234where
235    C::Mode: config::InternalFingerprintGuard<E, C>,
236{
237    C::Mode::encode_check(&config, &mut writer)?;
238    let mut encoder = enc::EncoderImpl::<_, C>::new(writer, config);
239    val.encode(&mut encoder)?;
240    Ok(())
241}
242
243/// Attempt to decode a given type `D` from the given slice. Returns the decoded output and the amount of bytes read.
244///
245/// Note that this does not work with borrowed types like `&str` or `&[u8]`. For that use [`borrow_decode_from_slice`\].
246///
247/// See the [config] module for more information on configurations.
248///
249/// # Errors
250///
251/// Returns a `DecodeError` if the slice is too small or the data is invalid.
252///
253/// [config]: config/index.html
254#[inline(always)]
255pub fn decode_from_slice<D: de::Decode<()>, C: Config>(
256    src: &[u8],
257    config: C,
258) -> Result<(D, usize), error::DecodeError>
259where
260    C::Mode: config::InternalFingerprintGuard<D, C>,
261{
262    decode_from_slice_with_context(src, config, ())
263}
264
265/// Attempt to decode a given type `D` from the given slice with `Context`. Returns the decoded output and the amount of bytes read.
266///
267/// Note that this does not work with borrowed types like `&str` or `&[u8]`. For that use [`borrow_decode_from_slice`\].
268///
269/// See the [config] module for more information on configurations.
270///
271/// # Errors
272///
273/// Returns a `DecodeError` if the slice is too small or the data is invalid.
274///
275/// [config]: config/index.html
276#[inline]
277pub fn decode_from_slice_with_context<Context, D: de::Decode<Context>, C: Config>(
278    src: &[u8],
279    config: C,
280    context: Context,
281) -> Result<(D, usize), error::DecodeError>
282where
283    C::Mode: config::InternalFingerprintGuard<D, C>,
284{
285    let mut reader = de::read::SliceReader::new(src);
286    C::Mode::decode_check(&config, &mut reader)?;
287    let mut decoder = de::DecoderImpl::<_, C, Context>::new(reader, config, context);
288    let result = D::decode(&mut decoder)?;
289    let bytes_read = src.len() - decoder.reader().slice.len();
290    Ok((result, bytes_read))
291}
292
293/// Attempt to decode a given type `D` from the given slice. Returns the decoded output and the amount of bytes read.
294///
295/// See the [config] module for more information on configurations.
296///
297/// # Errors
298///
299/// Returns a `DecodeError` if the slice is too small or the data is invalid.
300///
301/// [config]: config/index.html
302#[inline(always)]
303pub fn borrow_decode_from_slice<'a, D: de::BorrowDecode<'a, ()>, C: Config>(
304    src: &'a [u8],
305    config: C,
306) -> Result<(D, usize), error::DecodeError>
307where
308    C::Mode: config::InternalFingerprintGuard<D, C>,
309{
310    borrow_decode_from_slice_with_context(src, config, ())
311}
312
313/// Attempt to decode a given type `D` from the given slice with `Context`. Returns the decoded output and the amount of bytes read.
314///
315/// See the [config] module for more information on configurations.
316///
317/// # Errors
318///
319/// Returns a `DecodeError` if the slice is too small or the data is invalid.
320///
321/// [config]: config/index.html
322#[inline]
323pub fn borrow_decode_from_slice_with_context<
324    'a,
325    Context,
326    D: de::BorrowDecode<'a, Context>,
327    C: Config,
328>(
329    src: &'a [u8],
330    config: C,
331    context: Context,
332) -> Result<(D, usize), error::DecodeError>
333where
334    C::Mode: config::InternalFingerprintGuard<D, C>,
335{
336    let mut reader = de::read::SliceReader::new(src);
337    C::Mode::decode_check(&config, &mut reader)?;
338    let mut decoder = de::DecoderImpl::<_, C, Context>::new(reader, config, context);
339    let result = D::borrow_decode(&mut decoder)?;
340    let bytes_read = src.len() - decoder.reader().slice.len();
341    Ok((result, bytes_read))
342}
343
344/// Attempt to decode a given type `D` from the given slice with a compile-time bound check.
345///
346/// This function ensures that the target type `D` cannot exceed the provided buffer capacity `CAP` at compile-time.
347///
348/// # Errors
349///
350/// Returns a `DecodeError` if the slice contains invalid data.
351#[cfg(feature = "static-size")]
352#[inline(always)]
353pub fn decode_from_slice_static<D, const CAP: usize, C>(
354    src: &[u8; CAP],
355    config: C,
356) -> Result<D, error::DecodeError>
357where
358    D: de::Decode<()> + static_size::StaticSize,
359    C: Config,
360    C::Mode: config::InternalFingerprintGuard<D, C>,
361{
362    const {
363        assert!(D::MAX_SIZE <= CAP, "Buffer too small for target type");
364    }
365    let (val, _) = decode_from_slice(src, config)?;
366    Ok(val)
367}
368
369/// Attempt to decode a given type `D` from the given slice with a compile-time bound check and a
370/// decoding context.
371///
372/// This function ensures that the target type `D` cannot exceed the provided buffer capacity `CAP`
373/// at compile-time.
374///
375/// # Errors
376///
377/// Returns a `DecodeError` if the slice contains invalid data.
378#[cfg(feature = "static-size")]
379#[inline(always)]
380pub fn decode_from_slice_static_with_context<Context, D, const CAP: usize, C>(
381    src: &[u8; CAP],
382    config: C,
383    context: Context,
384) -> Result<D, error::DecodeError>
385where
386    D: de::Decode<Context> + static_size::StaticSize,
387    C: Config,
388    C::Mode: config::InternalFingerprintGuard<D, C>,
389{
390    const {
391        assert!(D::MAX_SIZE <= CAP, "Buffer too small for target type");
392    }
393    let (val, _) = decode_from_slice_with_context(src, config, context)?;
394    Ok(val)
395}
396
397/// Attempt to decode a given type `D` from the given slice with a compile-time bound check.
398///
399/// This function ensures that the target type `D` cannot exceed the provided buffer capacity `CAP`
400/// at compile-time.
401///
402/// # Errors
403///
404/// Returns a `DecodeError` if the slice contains invalid data.
405#[cfg(feature = "static-size")]
406#[inline(always)]
407pub fn borrow_decode_from_slice_static<'a, D, const CAP: usize, C>(
408    src: &'a [u8; CAP],
409    config: C,
410) -> Result<D, error::DecodeError>
411where
412    D: de::BorrowDecode<'a, ()> + static_size::StaticSize,
413    C: Config,
414    C::Mode: config::InternalFingerprintGuard<D, C>,
415{
416    const {
417        assert!(D::MAX_SIZE <= CAP, "Buffer too small for target type");
418    }
419    let (val, _) = borrow_decode_from_slice(src, config)?;
420    Ok(val)
421}
422
423/// Attempt to borrow-decode a given type `D` from the given slice with a compile-time bound check
424/// and a decoding context.
425///
426/// This function ensures that the target type `D` cannot exceed the provided buffer capacity `CAP`
427/// at compile-time.
428///
429/// # Errors
430///
431/// Returns a `DecodeError` if the slice contains invalid data.
432#[cfg(feature = "static-size")]
433#[inline(always)]
434pub fn borrow_decode_from_slice_static_with_context<'a, Context, D, const CAP: usize, C>(
435    src: &'a [u8; CAP],
436    config: C,
437    context: Context,
438) -> Result<D, error::DecodeError>
439where
440    D: de::BorrowDecode<'a, Context> + static_size::StaticSize,
441    C: Config,
442    C::Mode: config::InternalFingerprintGuard<D, C>,
443{
444    const {
445        assert!(D::MAX_SIZE <= CAP, "Buffer too small for target type");
446    }
447    let (val, _) = borrow_decode_from_slice_with_context(src, config, context)?;
448    Ok(val)
449}
450
451/// Attempt to decode a given type `D` from the given [`Reader`\].
452///
453/// See the [config] module for more information on configurations.
454///
455/// # Errors
456///
457/// Returns a `DecodeError` if the reader fails or the data is invalid.
458///
459/// [config]: config/index.html
460#[inline]
461pub fn decode_from_reader<D: de::Decode<()>, R: Reader, C: Config>(
462    mut reader: R,
463    config: C,
464) -> Result<D, error::DecodeError>
465where
466    C::Mode: config::InternalFingerprintGuard<D, C>,
467{
468    C::Mode::decode_check(&config, &mut reader)?;
469    let mut decoder = de::DecoderImpl::<_, C, ()>::new(reader, config, ());
470    D::decode(&mut decoder)
471}
472
473/// Attempt to decode a given type `T` from the given async reader safely using a non-blocking fiber.
474///
475/// Requires the `async-fiber` feature.
476///
477/// # Errors
478///
479/// Returns a `DecodeError` if the reader fails or the data is invalid.
480///
481/// [config]: config/index.html
482#[cfg(feature = "async-fiber")]
483#[inline(always)]
484pub async fn decode_async<T, R, C>(
485    config: C,
486    reader: R,
487) -> Result<T, crate::error::DecodeError>
488where
489    T: crate::Decode<()>,
490    R: futures_io::AsyncRead + std::marker::Unpin,
491    C: crate::config::Config,
492    C::Mode: crate::config::InternalFingerprintGuard<T, C>,
493{
494    decode_async_with_context::<T, R, C, ()>(config, reader, ()).await
495}
496
497/// Attempt to decode a given type `T` from the given async reader using a non-blocking fiber and a context.
498///
499/// This is the primary implementation for runtimes that use the `futures-io` traits (e.g. `async-std`, `smol`).
500///
501/// Requires the `async-fiber` feature.
502///
503/// # Errors
504///
505/// Returns a `DecodeError` if the reader fails or the data is invalid.
506///
507/// [config]: config/index.html
508#[cfg(feature = "async-fiber")]
509#[inline]
510pub async fn decode_async_with_context<T, R, C, Context>(
511    config: C,
512    reader: R,
513    context: Context,
514) -> Result<T, crate::error::DecodeError>
515where
516    T: crate::Decode<Context>,
517    R: futures_io::AsyncRead + std::marker::Unpin,
518    C: crate::config::Config,
519    C::Mode: crate::config::InternalFingerprintGuard<T, C>,
520{
521    let bridge = crate::de::async_fiber::AsyncFiberBridge::new(reader);
522    bridge
523        .run(move |fiber_reader| {
524            C::Mode::decode_check(&config, fiber_reader)?;
525            let mut decoder =
526                crate::de::DecoderImpl::<_, C, Context>::new(fiber_reader, config, context);
527            T::decode(&mut decoder)
528        })
529        .await
530}
531
532/// Attempt to decode a given type `T` from an `async-std` reader.
533///
534/// Requires the `async-fiber` feature.
535///
536/// # Errors
537///
538/// Returns a `DecodeError` if the reader fails or the data is invalid.
539///
540/// [config]: config/index.html
541#[cfg(feature = "async-fiber")]
542#[inline(always)]
543pub async fn decode_async_std<T, R, C>(
544    config: C,
545    reader: R,
546) -> Result<T, crate::error::DecodeError>
547where
548    T: crate::Decode<()>,
549    R: futures_io::AsyncRead + std::marker::Unpin,
550    C: crate::config::Config,
551    C::Mode: crate::config::InternalFingerprintGuard<T, C>,
552{
553    decode_async_with_context::<T, R, C, ()>(config, reader, ()).await
554}
555
556/// Attempt to decode a given type `T` from an `async-std` reader.
557///
558/// Requires the `async-fiber` feature.
559///
560/// # Errors
561///
562/// Returns a `DecodeError` if the reader fails or the data is invalid.
563///
564/// [config]: config/index.html
565#[cfg(feature = "async-fiber")]
566#[inline(always)]
567pub async fn decode_async_std_with_context<T, R, C, Context>(
568    config: C,
569    reader: R,
570    context: Context,
571) -> Result<T, crate::error::DecodeError>
572where
573    T: crate::Decode<Context>,
574    R: futures_io::AsyncRead + std::marker::Unpin,
575    C: crate::config::Config,
576    C::Mode: crate::config::InternalFingerprintGuard<T, C>,
577{
578    decode_async_with_context::<T, R, C, Context>(config, reader, context).await
579}
580
581/// Attempt to decode a given type `T` from a `smol` reader.
582///
583/// Requires the `async-fiber` feature.
584///
585/// # Errors
586///
587/// Returns a `DecodeError` if the reader fails or the data is invalid.
588///
589/// [config]: config/index.html
590#[cfg(feature = "async-fiber")]
591#[inline(always)]
592pub async fn decode_async_smol<T, R, C>(
593    config: C,
594    reader: R,
595) -> Result<T, crate::error::DecodeError>
596where
597    T: crate::Decode<()>,
598    R: futures_io::AsyncRead + std::marker::Unpin,
599    C: crate::config::Config,
600    C::Mode: crate::config::InternalFingerprintGuard<T, C>,
601{
602    decode_async_with_context::<T, R, C, ()>(config, reader, ()).await
603}
604
605/// Attempt to decode a given type `T` from a `smol` reader.
606///
607/// Requires the `async-fiber` feature.
608///
609/// # Errors
610///
611/// Returns a `DecodeError` if the reader fails or the data is invalid.
612///
613/// [config]: config/index.html
614#[cfg(feature = "async-fiber")]
615#[inline(always)]
616pub async fn decode_async_smol_with_context<T, R, C, Context>(
617    config: C,
618    reader: R,
619    context: Context,
620) -> Result<T, crate::error::DecodeError>
621where
622    T: crate::Decode<Context>,
623    R: futures_io::AsyncRead + std::marker::Unpin,
624    C: crate::config::Config,
625    C::Mode: crate::config::InternalFingerprintGuard<T, C>,
626{
627    decode_async_with_context::<T, R, C, Context>(config, reader, context).await
628}
629
630/// Attempt to decode a given type `T` from the given tokio async reader safely using a non-blocking fiber.
631///
632/// Requires the `tokio` and `async-fiber` features.
633///
634/// # Errors
635///
636/// Returns a `DecodeError` if the reader fails or the data is invalid.
637///
638/// [config]: config/index.html
639#[cfg(all(feature = "tokio", feature = "async-fiber"))]
640#[inline(always)]
641pub async fn decode_async_tokio<T, R, C>(
642    config: C,
643    reader: R,
644) -> Result<T, crate::error::DecodeError>
645where
646    T: crate::Decode<()>,
647    R: tokio::io::AsyncRead + std::marker::Unpin,
648    C: crate::config::Config,
649    C::Mode: crate::config::InternalFingerprintGuard<T, C>,
650{
651    decode_async_tokio_with_context::<T, R, C, ()>(config, reader, ()).await
652}
653
654/// Attempt to decode a given type `T` from the given tokio async reader using a non-blocking fiber and a context.
655///
656/// Requires the `tokio` and `async-fiber` features.
657///
658/// # Errors
659///
660/// Returns a `DecodeError` if the reader fails or the data is invalid.
661///
662/// [config]: config/index.html
663#[cfg(all(feature = "tokio", feature = "async-fiber"))]
664#[inline(always)]
665pub async fn decode_async_tokio_with_context<T, R, C, Context>(
666    config: C,
667    reader: R,
668    context: Context,
669) -> Result<T, crate::error::DecodeError>
670where
671    T: crate::Decode<Context>,
672    R: tokio::io::AsyncRead + std::marker::Unpin,
673    C: crate::config::Config,
674    C::Mode: crate::config::InternalFingerprintGuard<T, C>,
675{
676    let reader = crate::de::async_fiber::TokioReader(reader);
677    decode_async_with_context::<T, _, C, Context>(config, reader, context).await
678}
679
680/// Attempt to decode a given serde-compatible type `T` from the given async reader safely using a non-blocking fiber.
681///
682/// Requires the `async-fiber` and `serde` features.
683///
684/// # Errors
685///
686/// Returns a `DecodeError` if the reader fails or the data is invalid.
687///
688/// [config]: config/index.html
689#[cfg(all(feature = "async-fiber", feature = "serde"))]
690#[inline(always)]
691pub async fn decode_serde_async<'de, T, R, C>(
692    config: C,
693    reader: R,
694) -> Result<T, crate::error::DecodeError>
695where
696    T: ::serde::Deserialize<'de>,
697    R: futures_io::AsyncRead + std::marker::Unpin,
698    C: crate::config::Config,
699{
700    decode_serde_async_with_context::<'de, T, R, C, ()>(config, reader, ()).await
701}
702
703/// Attempt to decode a given serde-compatible type `T` from an `async-std` reader.
704///
705/// Requires the `async-fiber` and `serde` features.
706///
707/// # Errors
708///
709/// Returns a `DecodeError` if the reader fails or the data is invalid.
710///
711/// [config]: config/index.html
712#[cfg(all(feature = "async-fiber", feature = "serde"))]
713#[inline(always)]
714pub async fn decode_serde_async_std<'de, T, R, C>(
715    config: C,
716    reader: R,
717) -> Result<T, crate::error::DecodeError>
718where
719    T: ::serde::Deserialize<'de>,
720    R: futures_io::AsyncRead + std::marker::Unpin,
721    C: crate::config::Config,
722{
723    decode_serde_async_with_context::<'de, T, R, C, ()>(config, reader, ()).await
724}
725
726/// Attempt to decode a given serde-compatible type `T` from an `async-std` reader.
727///
728/// Requires the `async-fiber` and `serde` features.
729///
730/// # Errors
731///
732/// Returns a `DecodeError` if the reader fails or the data is invalid.
733///
734/// [config]: config/index.html
735#[cfg(all(feature = "async-fiber", feature = "serde"))]
736#[inline(always)]
737pub async fn decode_serde_async_std_with_context<'de, T, R, C, Context>(
738    config: C,
739    reader: R,
740    context: Context,
741) -> Result<T, crate::error::DecodeError>
742where
743    T: ::serde::Deserialize<'de>,
744    R: futures_io::AsyncRead + std::marker::Unpin,
745    C: crate::config::Config,
746{
747    decode_serde_async_with_context::<'de, T, R, C, Context>(config, reader, context).await
748}
749
750/// Attempt to decode a given serde-compatible type `T` from a `smol` reader.
751///
752/// Requires the `async-fiber` and `serde` features.
753///
754/// # Errors
755///
756/// Returns a `DecodeError` if the reader fails or the data is invalid.
757///
758/// [config]: config/index.html
759#[cfg(all(feature = "async-fiber", feature = "serde"))]
760#[inline(always)]
761pub async fn decode_serde_async_smol<'de, T, R, C>(
762    config: C,
763    reader: R,
764) -> Result<T, crate::error::DecodeError>
765where
766    T: ::serde::Deserialize<'de>,
767    R: futures_io::AsyncRead + std::marker::Unpin,
768    C: crate::config::Config,
769{
770    decode_serde_async_with_context::<'de, T, R, C, ()>(config, reader, ()).await
771}
772
773/// Attempt to decode a given serde-compatible type `T` from a `smol` reader.
774///
775/// Requires the `async-fiber` and `serde` features.
776///
777/// # Errors
778///
779/// Returns a `DecodeError` if the reader fails or the data is invalid.
780///
781/// [config]: config/index.html
782#[cfg(all(feature = "async-fiber", feature = "serde"))]
783#[inline(always)]
784pub async fn decode_serde_async_smol_with_context<'de, T, R, C, Context>(
785    config: C,
786    reader: R,
787    context: Context,
788) -> Result<T, crate::error::DecodeError>
789where
790    T: ::serde::Deserialize<'de>,
791    R: futures_io::AsyncRead + std::marker::Unpin,
792    C: crate::config::Config,
793{
794    decode_serde_async_with_context::<'de, T, R, C, Context>(config, reader, context).await
795}
796
797/// Attempt to decode a given serde-compatible type `T` from the given async reader using a non-blocking fiber and a context.
798///
799/// Requires the `async-fiber` and `serde` features.
800///
801/// # Errors
802///
803/// Returns a `DecodeError` if the reader fails or the data is invalid.
804///
805/// [config]: config/index.html
806#[cfg(all(feature = "async-fiber", feature = "serde"))]
807#[inline]
808pub async fn decode_serde_async_with_context<'de, T, R, C, Context>(
809    config: C,
810    reader: R,
811    context: Context,
812) -> Result<T, crate::error::DecodeError>
813where
814    T: ::serde::Deserialize<'de>,
815    R: futures_io::AsyncRead + std::marker::Unpin,
816    C: crate::config::Config,
817{
818    let bridge = crate::de::async_fiber::AsyncFiberBridge::new(reader);
819    bridge
820        .run(move |fiber_reader| {
821            let decoder =
822                crate::de::DecoderImpl::<_, C, Context>::new(fiber_reader, config, context);
823            let mut serde_decoder = crate::features::serde::OwnedSerdeDecoder { de: decoder };
824            T::deserialize(serde_decoder.as_deserializer())
825        })
826        .await
827}
828
829/// Attempt to decode a given serde-compatible type `T` from the given tokio async reader safely using a non-blocking fiber.
830///
831/// Requires the `tokio`, `async-fiber` and `serde` features.
832///
833/// # Errors
834///
835/// Returns a `DecodeError` if the reader fails or the data is invalid.
836///
837/// [config]: config/index.html
838#[cfg(all(feature = "tokio", feature = "async-fiber", feature = "serde"))]
839#[inline(always)]
840pub async fn decode_serde_tokio_async<'de, T, R, C>(
841    config: C,
842    reader: R,
843) -> Result<T, crate::error::DecodeError>
844where
845    T: ::serde::Deserialize<'de>,
846    R: tokio::io::AsyncRead + std::marker::Unpin,
847    C: crate::config::Config,
848{
849    decode_serde_tokio_async_with_context::<'de, T, R, C, ()>(config, reader, ()).await
850}
851
852/// Attempt to decode a given serde-compatible type `T` from the given tokio async reader using a non-blocking fiber and a context.
853///
854/// Requires the `tokio`, `async-fiber` and `serde` features.
855///
856/// # Errors
857///
858/// Returns a `DecodeError` if the reader fails or the data is invalid.
859///
860/// [config]: config/index.html
861#[cfg(all(feature = "tokio", feature = "async-fiber", feature = "serde"))]
862#[inline(always)]
863pub async fn decode_serde_tokio_async_with_context<'de, T, R, C, Context>(
864    config: C,
865    reader: R,
866    context: Context,
867) -> Result<T, crate::error::DecodeError>
868where
869    T: ::serde::Deserialize<'de>,
870    R: tokio::io::AsyncRead + std::marker::Unpin,
871    C: crate::config::Config,
872{
873    let reader = crate::de::async_fiber::TokioReader(reader);
874    decode_serde_async_with_context::<'de, T, _, C, Context>(config, reader, context).await
875}
876
877#[cfg(all(feature = "alloc", feature = "derive", doc))]
878pub mod spec {
879    #![doc = include_str!("../docs/spec.md")]
880}
881
882#[cfg(doc)]
883pub mod migration_guide {
884    #![doc = include_str!("../docs/migration_guide.md")]
885}
886
887// Test the examples in readme.md
888#[cfg(all(
889    feature = "std",
890    feature = "derive",
891    feature = "serde",
892    feature = "async-fiber",
893    doctest
894))]
895#[cfg_attr(miri, ignore)]
896mod readme {
897    #![doc = include_str!("../README.md")]
898}