#![no_std]
#![cfg_attr(docsrs, feature(doc_cfg))]
#![allow(internal_features)]
#![cfg_attr(is_nightly, feature(core_intrinsics))]
#![deny(
// Rust Compiler Errors
unreachable_code,
improper_ctypes_definitions,
future_incompatible,
nonstandard_style,
rust_2018_idioms,
clippy::perf,
clippy::correctness,
clippy::suspicious,
clippy::unwrap_used,
clippy::expect_used,
clippy::indexing_slicing,
clippy::arithmetic_side_effects,
clippy::missing_safety_doc,
clippy::same_item_push,
clippy::implicit_clone,
clippy::all,
clippy::pedantic,
missing_docs,
clippy::nursery,
clippy::single_call_fn,
)]
#![warn(
// For `no-std` Situation Issues
dead_code,
warnings,
unsafe_code,
clippy::dbg_macro,
clippy::todo,
clippy::cast_possible_truncation,
clippy::cast_sign_loss,
clippy::cast_possible_wrap,
clippy::unnecessary_safety_comment
)]
#![allow(
clippy::restriction,
clippy::inline_always,
unused_doc_comments,
clippy::empty_line_after_doc_comments
)]
#![crate_name = "bincode_next"]
#![crate_type = "rlib"]
#[cfg(feature = "alloc")]
extern crate alloc;
#[cfg(any(feature = "std", test))]
extern crate std;
mod atomic;
#[doc(hidden)]
pub mod error_path;
mod features;
#[doc(hidden)]
pub mod utils;
pub(crate) mod varint;
use de::Decoder;
use de::read::Reader;
use enc::write::Writer;
#[cfg(any(
feature = "alloc",
feature = "std",
feature = "derive",
feature = "serde",
feature = "zero-copy",
feature = "static-size"
))]
pub use features::*;
pub const BINCODE_MAJOR_VERSION: u64 = 3;
#[doc(hidden)]
pub use rapidhash;
pub mod config;
pub mod fingerprint;
#[macro_use]
pub mod de;
pub mod enc;
pub mod error;
#[cfg(feature = "static-size")]
pub use static_size::StaticSize;
pub use de::BorrowDecode;
pub use de::Decode;
pub use enc::Encode;
pub use fingerprint::Fingerprint;
#[cfg(feature = "zero-copy")]
pub use relative_ptr::ZeroCopy;
#[cfg(feature = "zero-copy")]
pub use relative_ptr::ZeroCopyType;
#[cfg(not(any(feature = "std", feature = "serde")))]
#[cfg(feature = "no-std")]
use panic_halt as _;
use config::Config;
use config::internal::InternalFingerprintGuard;
#[inline]
pub fn encode_into_slice<E: enc::Encode, C: Config>(
val: E,
dst: &mut [u8],
config: C,
) -> Result<usize, error::EncodeError>
where
C::Mode: config::InternalFingerprintGuard<E, C>,
{
let mut writer = enc::write::SliceWriter::new(dst);
C::Mode::encode_check(&config, &mut writer)?;
let mut encoder = enc::EncoderImpl::<_, C>::new(writer, config);
val.encode(&mut encoder)?;
Ok(encoder.into_writer().bytes_written())
}
#[inline]
pub fn encode_into_writer<E: enc::Encode, W: Writer, C: Config>(
val: E,
mut writer: W,
config: C,
) -> Result<(), error::EncodeError>
where
C::Mode: config::InternalFingerprintGuard<E, C>,
{
C::Mode::encode_check(&config, &mut writer)?;
let mut encoder = enc::EncoderImpl::<_, C>::new(writer, config);
val.encode(&mut encoder)?;
Ok(())
}
#[inline(always)]
pub fn decode_from_slice<D: de::Decode<()>, C: Config>(
src: &[u8],
config: C,
) -> Result<(D, usize), error::DecodeError>
where
C::Mode: config::InternalFingerprintGuard<D, C>,
{
decode_from_slice_with_context(src, config, ())
}
#[inline]
pub fn decode_from_slice_with_context<Context, D: de::Decode<Context>, C: Config>(
src: &[u8],
config: C,
context: Context,
) -> Result<(D, usize), error::DecodeError>
where
C::Mode: config::InternalFingerprintGuard<D, C>,
{
let mut reader = de::read::SliceReader::new(src);
C::Mode::decode_check(&config, &mut reader)?;
let mut decoder = de::DecoderImpl::<_, C, Context>::new(reader, config, context);
let result = D::decode(&mut decoder)?;
let bytes_read = src.len() - decoder.reader().slice.len();
Ok((result, bytes_read))
}
#[inline(always)]
pub fn borrow_decode_from_slice<'a, D: de::BorrowDecode<'a, ()>, C: Config>(
src: &'a [u8],
config: C,
) -> Result<(D, usize), error::DecodeError>
where
C::Mode: config::InternalFingerprintGuard<D, C>,
{
borrow_decode_from_slice_with_context(src, config, ())
}
#[inline]
pub fn borrow_decode_from_slice_with_context<
'a,
Context,
D: de::BorrowDecode<'a, Context>,
C: Config,
>(
src: &'a [u8],
config: C,
context: Context,
) -> Result<(D, usize), error::DecodeError>
where
C::Mode: config::InternalFingerprintGuard<D, C>,
{
let mut reader = de::read::SliceReader::new(src);
C::Mode::decode_check(&config, &mut reader)?;
let mut decoder = de::DecoderImpl::<_, C, Context>::new(reader, config, context);
let result = D::borrow_decode(&mut decoder)?;
let bytes_read = src.len() - decoder.reader().slice.len();
Ok((result, bytes_read))
}
#[cfg(feature = "static-size")]
#[inline(always)]
pub fn decode_from_slice_static<D, const CAP: usize, C>(
src: &[u8; CAP],
config: C,
) -> Result<D, error::DecodeError>
where
D: de::Decode<()> + static_size::StaticSize,
C: Config,
C::Mode: config::InternalFingerprintGuard<D, C>,
{
const {
assert!(D::MAX_SIZE <= CAP, "Buffer too small for target type");
}
let (val, _) = decode_from_slice(src, config)?;
Ok(val)
}
#[cfg(feature = "static-size")]
#[inline(always)]
pub fn decode_from_slice_static_with_context<Context, D, const CAP: usize, C>(
src: &[u8; CAP],
config: C,
context: Context,
) -> Result<D, error::DecodeError>
where
D: de::Decode<Context> + static_size::StaticSize,
C: Config,
C::Mode: config::InternalFingerprintGuard<D, C>,
{
const {
assert!(D::MAX_SIZE <= CAP, "Buffer too small for target type");
}
let (val, _) = decode_from_slice_with_context(src, config, context)?;
Ok(val)
}
#[cfg(feature = "static-size")]
#[inline(always)]
pub fn borrow_decode_from_slice_static<'a, D, const CAP: usize, C>(
src: &'a [u8; CAP],
config: C,
) -> Result<D, error::DecodeError>
where
D: de::BorrowDecode<'a, ()> + static_size::StaticSize,
C: Config,
C::Mode: config::InternalFingerprintGuard<D, C>,
{
const {
assert!(D::MAX_SIZE <= CAP, "Buffer too small for target type");
}
let (val, _) = borrow_decode_from_slice(src, config)?;
Ok(val)
}
#[cfg(feature = "static-size")]
#[inline(always)]
pub fn borrow_decode_from_slice_static_with_context<'a, Context, D, const CAP: usize, C>(
src: &'a [u8; CAP],
config: C,
context: Context,
) -> Result<D, error::DecodeError>
where
D: de::BorrowDecode<'a, Context> + static_size::StaticSize,
C: Config,
C::Mode: config::InternalFingerprintGuard<D, C>,
{
const {
assert!(D::MAX_SIZE <= CAP, "Buffer too small for target type");
}
let (val, _) = borrow_decode_from_slice_with_context(src, config, context)?;
Ok(val)
}
#[inline]
pub fn decode_from_reader<D: de::Decode<()>, R: Reader, C: Config>(
mut reader: R,
config: C,
) -> Result<D, error::DecodeError>
where
C::Mode: config::InternalFingerprintGuard<D, C>,
{
C::Mode::decode_check(&config, &mut reader)?;
let mut decoder = de::DecoderImpl::<_, C, ()>::new(reader, config, ());
D::decode(&mut decoder)
}
#[cfg(feature = "async-fiber")]
#[inline(always)]
pub async fn decode_async<T, R, C>(
config: C,
reader: R,
) -> Result<T, crate::error::DecodeError>
where
T: crate::Decode<()>,
R: futures_io::AsyncRead + std::marker::Unpin,
C: crate::config::Config,
C::Mode: crate::config::InternalFingerprintGuard<T, C>,
{
decode_async_with_context::<T, R, C, ()>(config, reader, ()).await
}
#[cfg(feature = "async-fiber")]
#[inline]
pub async fn decode_async_with_context<T, R, C, Context>(
config: C,
reader: R,
context: Context,
) -> Result<T, crate::error::DecodeError>
where
T: crate::Decode<Context>,
R: futures_io::AsyncRead + std::marker::Unpin,
C: crate::config::Config,
C::Mode: crate::config::InternalFingerprintGuard<T, C>,
{
let bridge = crate::de::async_fiber::AsyncFiberBridge::new(reader);
bridge
.run(move |fiber_reader| {
C::Mode::decode_check(&config, fiber_reader)?;
let mut decoder =
crate::de::DecoderImpl::<_, C, Context>::new(fiber_reader, config, context);
T::decode(&mut decoder)
})
.await
}
#[cfg(feature = "async-fiber")]
#[inline(always)]
pub async fn decode_async_std<T, R, C>(
config: C,
reader: R,
) -> Result<T, crate::error::DecodeError>
where
T: crate::Decode<()>,
R: futures_io::AsyncRead + std::marker::Unpin,
C: crate::config::Config,
C::Mode: crate::config::InternalFingerprintGuard<T, C>,
{
decode_async_with_context::<T, R, C, ()>(config, reader, ()).await
}
#[cfg(feature = "async-fiber")]
#[inline(always)]
pub async fn decode_async_std_with_context<T, R, C, Context>(
config: C,
reader: R,
context: Context,
) -> Result<T, crate::error::DecodeError>
where
T: crate::Decode<Context>,
R: futures_io::AsyncRead + std::marker::Unpin,
C: crate::config::Config,
C::Mode: crate::config::InternalFingerprintGuard<T, C>,
{
decode_async_with_context::<T, R, C, Context>(config, reader, context).await
}
#[cfg(feature = "async-fiber")]
#[inline(always)]
pub async fn decode_async_smol<T, R, C>(
config: C,
reader: R,
) -> Result<T, crate::error::DecodeError>
where
T: crate::Decode<()>,
R: futures_io::AsyncRead + std::marker::Unpin,
C: crate::config::Config,
C::Mode: crate::config::InternalFingerprintGuard<T, C>,
{
decode_async_with_context::<T, R, C, ()>(config, reader, ()).await
}
#[cfg(feature = "async-fiber")]
#[inline(always)]
pub async fn decode_async_smol_with_context<T, R, C, Context>(
config: C,
reader: R,
context: Context,
) -> Result<T, crate::error::DecodeError>
where
T: crate::Decode<Context>,
R: futures_io::AsyncRead + std::marker::Unpin,
C: crate::config::Config,
C::Mode: crate::config::InternalFingerprintGuard<T, C>,
{
decode_async_with_context::<T, R, C, Context>(config, reader, context).await
}
#[cfg(all(feature = "tokio", feature = "async-fiber"))]
#[inline(always)]
pub async fn decode_tokio_async<T, R, C>(
config: C,
reader: R,
) -> Result<T, crate::error::DecodeError>
where
T: crate::Decode<()>,
R: tokio::io::AsyncRead + std::marker::Unpin,
C: crate::config::Config,
C::Mode: crate::config::InternalFingerprintGuard<T, C>,
{
decode_async_tokio_with_context::<T, R, C, ()>(config, reader, ()).await
}
#[cfg(all(feature = "tokio", feature = "async-fiber"))]
#[inline(always)]
pub async fn decode_async_tokio_with_context<T, R, C, Context>(
config: C,
reader: R,
context: Context,
) -> Result<T, crate::error::DecodeError>
where
T: crate::Decode<Context>,
R: tokio::io::AsyncRead + std::marker::Unpin,
C: crate::config::Config,
C::Mode: crate::config::InternalFingerprintGuard<T, C>,
{
let reader = crate::de::async_fiber::TokioReader(reader);
decode_async_with_context::<T, _, C, Context>(config, reader, context).await
}
#[cfg(all(feature = "async-fiber", feature = "serde"))]
#[inline(always)]
pub async fn decode_serde_async<'de, T, R, C>(
config: C,
reader: R,
) -> Result<T, crate::error::DecodeError>
where
T: ::serde::Deserialize<'de>,
R: futures_io::AsyncRead + std::marker::Unpin,
C: crate::config::Config,
{
decode_serde_async_with_context::<'de, T, R, C, ()>(config, reader, ()).await
}
#[cfg(all(feature = "async-fiber", feature = "serde"))]
#[inline(always)]
pub async fn decode_serde_async_std<'de, T, R, C>(
config: C,
reader: R,
) -> Result<T, crate::error::DecodeError>
where
T: ::serde::Deserialize<'de>,
R: futures_io::AsyncRead + std::marker::Unpin,
C: crate::config::Config,
{
decode_serde_async_with_context::<'de, T, R, C, ()>(config, reader, ()).await
}
#[cfg(all(feature = "async-fiber", feature = "serde"))]
#[inline(always)]
pub async fn decode_serde_async_std_with_context<'de, T, R, C, Context>(
config: C,
reader: R,
context: Context,
) -> Result<T, crate::error::DecodeError>
where
T: ::serde::Deserialize<'de>,
R: futures_io::AsyncRead + std::marker::Unpin,
C: crate::config::Config,
{
decode_serde_async_with_context::<'de, T, R, C, Context>(config, reader, context).await
}
#[cfg(all(feature = "async-fiber", feature = "serde"))]
#[inline(always)]
pub async fn decode_serde_async_smol<'de, T, R, C>(
config: C,
reader: R,
) -> Result<T, crate::error::DecodeError>
where
T: ::serde::Deserialize<'de>,
R: futures_io::AsyncRead + std::marker::Unpin,
C: crate::config::Config,
{
decode_serde_async_with_context::<'de, T, R, C, ()>(config, reader, ()).await
}
#[cfg(all(feature = "async-fiber", feature = "serde"))]
#[inline(always)]
pub async fn decode_serde_async_smol_with_context<'de, T, R, C, Context>(
config: C,
reader: R,
context: Context,
) -> Result<T, crate::error::DecodeError>
where
T: ::serde::Deserialize<'de>,
R: futures_io::AsyncRead + std::marker::Unpin,
C: crate::config::Config,
{
decode_serde_async_with_context::<'de, T, R, C, Context>(config, reader, context).await
}
#[cfg(all(feature = "async-fiber", feature = "serde"))]
#[inline]
pub async fn decode_serde_async_with_context<'de, T, R, C, Context>(
config: C,
reader: R,
context: Context,
) -> Result<T, crate::error::DecodeError>
where
T: ::serde::Deserialize<'de>,
R: futures_io::AsyncRead + std::marker::Unpin,
C: crate::config::Config,
{
let bridge = crate::de::async_fiber::AsyncFiberBridge::new(reader);
bridge
.run(move |fiber_reader| {
let decoder =
crate::de::DecoderImpl::<_, C, Context>::new(fiber_reader, config, context);
let mut serde_decoder = crate::features::serde::OwnedSerdeDecoder { de: decoder };
T::deserialize(serde_decoder.as_deserializer())
})
.await
}
#[cfg(all(feature = "tokio", feature = "async-fiber", feature = "serde"))]
#[inline(always)]
pub async fn decode_serde_tokio_async<'de, T, R, C>(
config: C,
reader: R,
) -> Result<T, crate::error::DecodeError>
where
T: ::serde::Deserialize<'de>,
R: tokio::io::AsyncRead + std::marker::Unpin,
C: crate::config::Config,
{
decode_serde_tokio_async_with_context::<'de, T, R, C, ()>(config, reader, ()).await
}
#[cfg(all(feature = "tokio", feature = "async-fiber", feature = "serde"))]
#[inline(always)]
pub async fn decode_serde_tokio_async_with_context<'de, T, R, C, Context>(
config: C,
reader: R,
context: Context,
) -> Result<T, crate::error::DecodeError>
where
T: ::serde::Deserialize<'de>,
R: tokio::io::AsyncRead + std::marker::Unpin,
C: crate::config::Config,
{
let reader = crate::de::async_fiber::TokioReader(reader);
decode_serde_async_with_context::<'de, T, _, C, Context>(config, reader, context).await
}
#[cfg(all(feature = "alloc", feature = "derive", doc))]
pub mod spec {
#![doc = include_str!("../docs/spec.md")]
}
#[cfg(doc)]
pub mod migration_guide {
#![doc = include_str!("../docs/migration_guide.md")]
}
#[cfg(all(
feature = "std",
feature = "derive",
feature = "serde",
feature = "async-fiber",
doctest
))]
#[cfg_attr(miri, ignore)]
mod readme {
#![doc = include_str!("../README.md")]
}