#[cfg(feature = "alloc")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
mod alloc;
#[cfg(feature = "std")]
#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
mod net;
mod range;
mod tuples;
#[cfg(feature = "std")]
use core::any::TypeId;
use core::ffi::CStr;
use core::num::{
NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroIsize, NonZeroU8,
NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, NonZeroUsize, Saturating, Wrapping,
};
use core::{fmt, marker};
use crate::de::{
Decode, DecodeBytes, DecodePacked, DecodeUnsized, DecodeUnsizedBytes, Decoder, SequenceDecoder,
UnsizedVisitor, VariantDecoder,
};
use crate::en::{Encode, EncodeBytes, EncodePacked, Encoder, SequenceEncoder, VariantEncoder};
#[cfg(feature = "std")]
use crate::mode::Text;
use crate::{Allocator, Context};
#[cfg(feature = "std")]
enum PlatformTag {
Unix,
Windows,
}
#[cfg(feature = "std")]
impl<M> Encode<M> for PlatformTag
where
M: 'static,
{
type Encode = Self;
const IS_BITWISE_ENCODE: bool = false;
#[inline]
fn encode<E>(&self, encoder: E) -> Result<(), E::Error>
where
E: Encoder<Mode = M>,
{
if TypeId::of::<M>() == TypeId::of::<Text>() {
match self {
PlatformTag::Unix => encoder.encode("unix"),
PlatformTag::Windows => encoder.encode("windows"),
}
} else {
let tag = match self {
PlatformTag::Unix => 0,
PlatformTag::Windows => 1,
};
encoder.encode_u8(tag)
}
}
#[inline]
fn as_encode(&self) -> &Self::Encode {
self
}
}
#[cfg(feature = "std")]
impl<'de, M, A> Decode<'de, M, A> for PlatformTag
where
M: 'static,
A: Allocator,
{
const IS_BITWISE_DECODE: bool = true;
#[inline]
fn decode<D>(decoder: D) -> Result<Self, D::Error>
where
D: Decoder<'de, Allocator = A>,
{
let cx = decoder.cx();
if TypeId::of::<M>() == TypeId::of::<Text>() {
decoder.decode_unsized(|value: &str| match value {
"unix" => Ok(PlatformTag::Unix),
"windows" => Ok(PlatformTag::Windows),
_ => Err(cx.message(format_args!("Unsupported platform tag `{value}`",))),
})
} else {
match decoder.decode_u8()? {
0 => Ok(PlatformTag::Unix),
1 => Ok(PlatformTag::Windows),
_ => Err(cx.message("Unsupported platform tag")),
}
}
}
}
impl<M> Encode<M> for () {
type Encode = Self;
const IS_BITWISE_ENCODE: bool = true;
#[inline]
fn encode<E>(&self, encoder: E) -> Result<(), E::Error>
where
E: Encoder,
{
encoder.encode_empty()
}
#[inline]
fn as_encode(&self) -> &Self::Encode {
self
}
}
impl<'de, M, A> Decode<'de, M, A> for ()
where
A: Allocator,
{
const IS_BITWISE_DECODE: bool = true;
#[inline]
fn decode<D>(decoder: D) -> Result<Self, D::Error>
where
D: Decoder<'de, Allocator = A>,
{
decoder.decode_empty()
}
}
impl<T, M> Encode<M> for marker::PhantomData<T> {
type Encode = Self;
const IS_BITWISE_ENCODE: bool = true;
#[inline]
fn encode<E>(&self, encoder: E) -> Result<(), E::Error>
where
E: Encoder,
{
encoder.encode_empty()
}
#[inline]
fn as_encode(&self) -> &Self::Encode {
self
}
}
impl<'de, M, A, T> Decode<'de, M, A> for marker::PhantomData<T>
where
A: Allocator,
{
const IS_BITWISE_DECODE: bool = true;
#[inline]
fn decode<D>(decoder: D) -> Result<Self, D::Error>
where
D: Decoder<'de>,
{
decoder.decode_empty()?;
Ok(marker::PhantomData)
}
}
macro_rules! atomic_impl {
($size:literal $(, $ty:ident)*) => {
$(
#[cfg(target_has_atomic = $size)]
impl<'de, M, A> Decode<'de, M, A> for core::sync::atomic::$ty
where
A: Allocator
{
const IS_BITWISE_DECODE: bool = true;
fn decode<D>(decoder: D) -> Result<Self, D::Error>
where
D: Decoder<'de>,
{
decoder.decode().map(Self::new)
}
}
#[cfg(target_has_atomic = $size)]
impl<M> Encode<M> for core::sync::atomic::$ty {
const IS_BITWISE_ENCODE: bool = false;
type Encode = Self;
#[inline]
fn encode<E>(&self, encoder: E) -> Result<(), E::Error>
where
E: Encoder,
{
use core::sync::atomic::Ordering::Relaxed;
self.load(Relaxed).encode(encoder)
}
#[inline]
fn as_encode(&self) -> &Self::Encode {
self
}
}
)*
};
}
atomic_impl!("8", AtomicBool, AtomicI8, AtomicU8);
atomic_impl!("16", AtomicI16, AtomicU16);
atomic_impl!("32", AtomicI32, AtomicU32);
atomic_impl!("64", AtomicI64, AtomicU64);
atomic_impl!("ptr", AtomicIsize, AtomicUsize);
macro_rules! non_zero {
($ty:ty) => {
impl<M> Encode<M> for $ty {
const IS_BITWISE_ENCODE: bool = true;
type Encode = Self;
#[inline]
fn encode<E>(&self, encoder: E) -> Result<(), E::Error>
where
E: Encoder,
{
self.get().encode(encoder)
}
#[inline]
fn as_encode(&self) -> &Self::Encode {
self
}
}
impl<'de, M, A> Decode<'de, M, A> for $ty
where
A: Allocator,
{
const IS_BITWISE_DECODE: bool = false;
fn decode<D>(decoder: D) -> Result<Self, D::Error>
where
D: Decoder<'de, Allocator = A>,
{
let cx = decoder.cx();
let value = decoder.decode()?;
match Self::new(value) {
Some(value) => Ok(value),
None => Err(cx.message(NonZeroUnsupportedValue {
type_name: stringify!($ty),
value,
})),
}
}
}
};
}
non_zero!(NonZeroI128);
non_zero!(NonZeroI16);
non_zero!(NonZeroI32);
non_zero!(NonZeroI64);
non_zero!(NonZeroI8);
non_zero!(NonZeroIsize);
non_zero!(NonZeroU128);
non_zero!(NonZeroU16);
non_zero!(NonZeroU32);
non_zero!(NonZeroU64);
non_zero!(NonZeroU8);
non_zero!(NonZeroUsize);
struct NonZeroUnsupportedValue<T> {
type_name: &'static str,
value: T,
}
impl<T> fmt::Display for NonZeroUnsupportedValue<T>
where
T: fmt::Display,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}: unsupported non-zero value `{}`",
self.type_name, self.value
)
}
}
impl<M, T, const N: usize> Encode<M> for [T; N]
where
T: Encode<M>,
{
const IS_BITWISE_ENCODE: bool =
T::IS_BITWISE_ENCODE && core::mem::size_of::<T>() % core::mem::align_of::<T>() == 0;
type Encode = [T; N];
#[inline]
fn encode<E>(&self, encoder: E) -> Result<(), E::Error>
where
E: Encoder<Mode = M>,
{
encoder.encode_slice(self)
}
#[inline]
fn as_encode(&self) -> &Self::Encode {
self
}
}
impl<'de, M, T, A, const N: usize> Decode<'de, M, A> for [T; N]
where
T: Decode<'de, M, A>,
A: Allocator,
{
const IS_BITWISE_DECODE: bool =
T::IS_BITWISE_DECODE && core::mem::size_of::<T>() % core::mem::align_of::<T>() == 0;
#[inline]
fn decode<D>(decoder: D) -> Result<Self, D::Error>
where
D: Decoder<'de, Mode = M, Allocator = A>,
{
let cx = decoder.cx();
let mark = cx.mark();
decoder.decode_sequence(|seq| {
let mut array = crate::internal::FixedVec::new();
while let Some(item) = seq.try_decode_next()? {
array.try_push(item.decode()?).map_err(cx.map())?;
}
if array.len() != N {
return Err(cx.message_at(
&mark,
format_args!(
"Array with length {} does not have the expected {N} number of elements",
array.len()
),
));
}
Ok(array.into_inner())
})
}
}
impl<M, T, const N: usize> EncodePacked<M> for [T; N]
where
T: Encode<M>,
{
#[inline]
fn encode_packed<E>(&self, encoder: E) -> Result<(), E::Error>
where
E: Encoder<Mode = M>,
{
encoder.encode_pack_fn(|seq| {
for value in self.iter() {
seq.push(value)?;
}
Ok(())
})
}
}
impl<'de, M, A, T, const N: usize> DecodePacked<'de, M, A> for [T; N]
where
A: Allocator,
T: Decode<'de, M, A>,
{
#[inline]
fn decode_packed<D>(decoder: D) -> Result<Self, D::Error>
where
D: Decoder<'de, Mode = M, Allocator = A>,
{
let cx = decoder.cx();
decoder.decode_pack(|pack| {
let mut array = crate::internal::FixedVec::new();
while array.len() < N {
let item = pack.decode_next()?;
array.try_push(item.decode()?).map_err(cx.map())?;
}
Ok(array.into_inner())
})
}
}
macro_rules! impl_number {
($ty:ty, $read:ident, $write:ident) => {
impl<M> Encode<M> for $ty {
const IS_BITWISE_ENCODE: bool = true;
#[inline]
fn encode<E>(&self, encoder: E) -> Result<(), E::Error>
where
E: Encoder,
{
encoder.$write(*self)
}
type Encode = Self;
#[inline]
fn as_encode(&self) -> &Self::Encode {
self
}
}
impl<'de, M, A> Decode<'de, M, A> for $ty
where
A: Allocator,
{
const IS_BITWISE_DECODE: bool = true;
#[inline]
fn decode<D>(decoder: D) -> Result<Self, D::Error>
where
D: Decoder<'de>,
{
decoder.$read()
}
}
};
}
impl<M> Encode<M> for bool {
type Encode = Self;
const IS_BITWISE_ENCODE: bool = true;
#[inline]
fn encode<E>(&self, encoder: E) -> Result<(), E::Error>
where
E: Encoder,
{
encoder.encode_bool(*self)
}
#[inline]
fn as_encode(&self) -> &Self::Encode {
self
}
}
impl<'de, M, A> Decode<'de, M, A> for bool
where
A: Allocator,
{
const IS_BITWISE_DECODE: bool = false;
#[inline]
fn decode<D>(decoder: D) -> Result<Self, D::Error>
where
D: Decoder<'de>,
{
decoder.decode_bool()
}
}
impl<M> Encode<M> for char {
type Encode = Self;
const IS_BITWISE_ENCODE: bool = true;
#[inline]
fn encode<E>(&self, encoder: E) -> Result<(), E::Error>
where
E: Encoder,
{
encoder.encode_char(*self)
}
#[inline]
fn as_encode(&self) -> &Self::Encode {
self
}
}
impl<'de, M, A> Decode<'de, M, A> for char
where
A: Allocator,
{
const IS_BITWISE_DECODE: bool = false;
#[inline]
fn decode<D>(decoder: D) -> Result<Self, D::Error>
where
D: Decoder<'de>,
{
decoder.decode_char()
}
}
impl_number!(usize, decode_usize, encode_usize);
impl_number!(isize, decode_isize, encode_isize);
impl_number!(u8, decode_u8, encode_u8);
impl_number!(u16, decode_u16, encode_u16);
impl_number!(u32, decode_u32, encode_u32);
impl_number!(u64, decode_u64, encode_u64);
impl_number!(u128, decode_u128, encode_u128);
impl_number!(i8, decode_i8, encode_i8);
impl_number!(i16, decode_i16, encode_i16);
impl_number!(i32, decode_i32, encode_i32);
impl_number!(i64, decode_i64, encode_i64);
impl_number!(i128, decode_i128, encode_i128);
impl_number!(f32, decode_f32, encode_f32);
impl_number!(f64, decode_f64, encode_f64);
impl<M> Encode<M> for str {
const IS_BITWISE_ENCODE: bool = false;
#[inline]
fn encode<E>(&self, encoder: E) -> Result<(), E::Error>
where
E: Encoder,
{
encoder.encode_string(self)
}
type Encode = Self;
#[inline]
fn as_encode(&self) -> &Self::Encode {
self
}
}
impl<'de, M, A> Decode<'de, M, A> for &'de str
where
A: Allocator,
{
const IS_BITWISE_DECODE: bool = false;
#[inline]
fn decode<D>(decoder: D) -> Result<Self, D::Error>
where
D: Decoder<'de>,
{
struct Visitor;
#[crate::trait_defaults(crate)]
impl<'de, C> UnsizedVisitor<'de, C, str> for Visitor
where
C: Context,
{
type Ok = &'de str;
#[inline]
fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "string borrowed from source")
}
#[inline]
fn visit_borrowed(self, _: C, string: &'de str) -> Result<Self::Ok, Self::Error> {
Ok(string)
}
}
decoder.decode_string(Visitor)
}
}
impl<'de, M> DecodeUnsized<'de, M> for str {
#[inline]
fn decode_unsized<D, F, O>(decoder: D, f: F) -> Result<O, D::Error>
where
D: Decoder<'de>,
F: FnOnce(&Self) -> Result<O, D::Error>,
{
struct Visitor<F>(F);
#[crate::trait_defaults(crate)]
impl<C, F, O> UnsizedVisitor<'_, C, str> for Visitor<F>
where
C: Context,
F: FnOnce(&str) -> Result<O, C::Error>,
{
type Ok = O;
#[inline]
fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "string visited from source")
}
#[inline]
fn visit_ref(self, _: C, string: &str) -> Result<Self::Ok, C::Error> {
(self.0)(string)
}
}
decoder.decode_string(Visitor(f))
}
}
impl<'de, M> DecodeUnsized<'de, M> for [u8] {
#[inline]
fn decode_unsized<D, F, O>(decoder: D, f: F) -> Result<O, D::Error>
where
D: Decoder<'de>,
F: FnOnce(&Self) -> Result<O, D::Error>,
{
struct Visitor<F>(F);
#[crate::trait_defaults(crate)]
impl<C, F, O> UnsizedVisitor<'_, C, [u8]> for Visitor<F>
where
C: Context,
F: FnOnce(&[u8]) -> Result<O, C::Error>,
{
type Ok = O;
#[inline]
fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "bytes visited from source")
}
#[inline]
fn visit_ref(self, _: C, bytes: &[u8]) -> Result<Self::Ok, C::Error> {
(self.0)(bytes)
}
}
decoder.decode_bytes(Visitor(f))
}
}
impl<M, T> Encode<M> for [T]
where
T: Encode<M>,
{
type Encode = Self;
const IS_BITWISE_ENCODE: bool = false;
#[inline]
fn encode<E>(&self, encoder: E) -> Result<(), E::Error>
where
E: Encoder<Mode = M>,
{
encoder.encode_slice(self)
}
#[inline]
fn as_encode(&self) -> &Self::Encode {
self
}
}
impl<'de, M, A> Decode<'de, M, A> for &'de [u8]
where
A: Allocator,
{
const IS_BITWISE_DECODE: bool = false;
#[inline]
fn decode<D>(decoder: D) -> Result<Self, D::Error>
where
D: Decoder<'de>,
{
struct Visitor;
#[crate::trait_defaults(crate)]
impl<'de, C> UnsizedVisitor<'de, C, [u8]> for Visitor
where
C: Context,
{
type Ok = &'de [u8];
#[inline]
fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "bytes borrowed from source")
}
#[inline]
fn visit_borrowed(self, _: C, bytes: &'de [u8]) -> Result<Self::Ok, Self::Error> {
Ok(bytes)
}
}
decoder.decode_bytes(Visitor)
}
}
impl<'de, M> DecodeUnsizedBytes<'de, M> for [u8] {
#[inline]
fn decode_unsized_bytes<D, F, O>(decoder: D, f: F) -> Result<O, D::Error>
where
D: Decoder<'de>,
F: FnOnce(&Self) -> Result<O, D::Error>,
{
struct Visitor<F>(F);
#[crate::trait_defaults(crate)]
impl<C, F, O> UnsizedVisitor<'_, C, [u8]> for Visitor<F>
where
C: Context,
F: FnOnce(&[u8]) -> Result<O, C::Error>,
{
type Ok = O;
#[inline]
fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "bytes visited from source")
}
#[inline]
fn visit_ref(self, _: C, bytes: &[u8]) -> Result<Self::Ok, C::Error> {
(self.0)(bytes)
}
}
decoder.decode_bytes(Visitor(f))
}
}
impl<T, M> Encode<M> for Option<T>
where
T: Encode<M>,
{
type Encode = Self;
const IS_BITWISE_ENCODE: bool = false;
#[inline]
fn encode<E>(&self, encoder: E) -> Result<(), E::Error>
where
E: Encoder<Mode = M>,
{
match self {
Some(value) => encoder.encode_some()?.encode(value),
None => encoder.encode_none(),
}
}
#[inline]
fn as_encode(&self) -> &Self::Encode {
self
}
}
impl<'de, M, A, T> Decode<'de, M, A> for Option<T>
where
A: Allocator,
T: Decode<'de, M, A>,
{
const IS_BITWISE_DECODE: bool = false;
#[inline]
fn decode<D>(decoder: D) -> Result<Self, D::Error>
where
D: Decoder<'de, Mode = M, Allocator = A>,
{
if let Some(decoder) = decoder.decode_option()? {
Ok(Some(decoder.decode()?))
} else {
Ok(None)
}
}
}
#[derive(Encode, Decode)]
#[musli(crate)]
enum ResultTag {
Ok,
Err,
}
impl<T, U, M> Encode<M> for Result<T, U>
where
T: Encode<M>,
U: Encode<M>,
ResultTag: Encode<M>,
{
type Encode = Self;
const IS_BITWISE_ENCODE: bool = false;
#[inline]
fn encode<E>(&self, encoder: E) -> Result<(), E::Error>
where
E: Encoder<Mode = M>,
{
let variant = encoder.encode_variant()?;
match self {
Ok(ok) => variant.insert_variant(&ResultTag::Ok, ok),
Err(err) => variant.insert_variant(&ResultTag::Err, err),
}
}
#[inline]
fn as_encode(&self) -> &Self::Encode {
self
}
}
impl<'de, M, A, T, U> Decode<'de, M, A> for Result<T, U>
where
A: Allocator,
T: Decode<'de, M, A>,
U: Decode<'de, M, A>,
ResultTag: Decode<'de, M, A>,
{
const IS_BITWISE_DECODE: bool = false;
#[inline]
fn decode<D>(decoder: D) -> Result<Self, D::Error>
where
D: Decoder<'de, Mode = M, Allocator = A>,
{
decoder.decode_variant(|variant| {
let tag = variant.decode_tag()?.decode()?;
Ok(match tag {
ResultTag::Ok => Ok(variant.decode_value()?.decode()?),
ResultTag::Err => Err(variant.decode_value()?.decode()?),
})
})
}
}
impl<T, M> Encode<M> for Wrapping<T>
where
T: Encode<M>,
{
const IS_BITWISE_ENCODE: bool = T::IS_BITWISE_ENCODE;
type Encode = Self;
#[inline]
fn encode<E>(&self, encoder: E) -> Result<(), E::Error>
where
E: Encoder<Mode = M>,
{
self.0.encode(encoder)
}
#[inline]
fn as_encode(&self) -> &Self::Encode {
self
}
}
impl<'de, M, T, A> Decode<'de, M, A> for Wrapping<T>
where
T: Decode<'de, M, A>,
A: Allocator,
{
const IS_BITWISE_DECODE: bool = T::IS_BITWISE_DECODE;
#[inline]
fn decode<D>(decoder: D) -> Result<Self, D::Error>
where
D: Decoder<'de, Mode = M, Allocator = A>,
{
Ok(Wrapping(decoder.decode()?))
}
}
impl<T, M> Encode<M> for Saturating<T>
where
T: Encode<M>,
{
const IS_BITWISE_ENCODE: bool = T::IS_BITWISE_ENCODE;
type Encode = Self;
#[inline]
fn encode<E>(&self, encoder: E) -> Result<(), E::Error>
where
E: Encoder<Mode = M>,
{
self.0.encode(encoder)
}
#[inline]
fn as_encode(&self) -> &Self::Encode {
self
}
}
impl<'de, M, T, A> Decode<'de, M, A> for Saturating<T>
where
T: Decode<'de, M, A>,
A: Allocator,
{
const IS_BITWISE_DECODE: bool = T::IS_BITWISE_DECODE;
#[inline]
fn decode<D>(decoder: D) -> Result<Self, D::Error>
where
D: Decoder<'de, Mode = M, Allocator = A>,
{
Ok(Saturating(decoder.decode()?))
}
}
impl<M> Encode<M> for CStr {
type Encode = Self;
const IS_BITWISE_ENCODE: bool = false;
#[inline]
fn encode<E>(&self, encoder: E) -> Result<(), E::Error>
where
E: Encoder,
{
encoder.encode_bytes(self.to_bytes_with_nul())
}
#[inline]
fn as_encode(&self) -> &Self::Encode {
self
}
}
impl<'de, M, A> Decode<'de, M, A> for &'de CStr
where
A: Allocator,
{
const IS_BITWISE_DECODE: bool = false;
#[inline]
fn decode<D>(decoder: D) -> Result<Self, D::Error>
where
D: Decoder<'de>,
{
let cx = decoder.cx();
let bytes = decoder.decode()?;
CStr::from_bytes_with_nul(bytes).map_err(cx.map())
}
}
impl<'de, M> DecodeUnsized<'de, M> for CStr {
#[inline]
fn decode_unsized<D, F, O>(decoder: D, f: F) -> Result<O, D::Error>
where
D: Decoder<'de, Mode = M>,
F: FnOnce(&Self) -> Result<O, D::Error>,
{
let cx = decoder.cx();
DecodeUnsizedBytes::decode_unsized_bytes(decoder, |bytes: &[u8]| {
let cstr = CStr::from_bytes_with_nul(bytes).map_err(cx.map())?;
f(cstr)
})
}
}
impl<M> EncodeBytes<M> for [u8] {
const ENCODE_BYTES_PACKED: bool = false;
type EncodeBytes = [u8];
#[inline]
fn encode_bytes<E>(&self, encoder: E) -> Result<(), E::Error>
where
E: Encoder<Mode = M>,
{
encoder.encode_bytes(self)
}
#[inline]
fn as_encode_bytes(&self) -> &Self::EncodeBytes {
self
}
}
impl<const N: usize, M> EncodeBytes<M> for [u8; N] {
const ENCODE_BYTES_PACKED: bool = true;
type EncodeBytes = [u8; N];
#[inline]
fn encode_bytes<E>(&self, encoder: E) -> Result<(), E::Error>
where
E: Encoder<Mode = M>,
{
encoder.encode_array(self)
}
#[inline]
fn as_encode_bytes(&self) -> &Self::EncodeBytes {
self
}
}
impl<'de, M, A> DecodeBytes<'de, M, A> for &'de [u8]
where
A: Allocator,
{
const DECODE_BYTES_PACKED: bool = false;
#[inline]
fn decode_bytes<D>(decoder: D) -> Result<Self, D::Error>
where
D: Decoder<'de, Allocator = A>,
{
Decode::decode(decoder)
}
}
impl<'de, M, A, const N: usize> DecodeBytes<'de, M, A> for [u8; N]
where
A: Allocator,
{
const DECODE_BYTES_PACKED: bool = true;
#[inline]
fn decode_bytes<D>(decoder: D) -> Result<Self, D::Error>
where
D: Decoder<'de, Allocator = A>,
{
decoder.decode_array()
}
}