arc-slice 0.1.0

Shared memory slices
Documentation
use alloc::{string::String, vec::Vec};
use core::{cmp, fmt, marker::PhantomData, ops::Deref};

use serde::{de, Deserialize, Deserializer, Serialize, Serializer};

use crate::{
    buffer::{Deserializable, Slice},
    layout::{ArcLayout, Layout, LayoutMut},
    utils::try_as_bytes,
    ArcSlice, ArcSliceMut,
};

const MAX_DESERIALIZE_SIZE: usize = 1 << 12;

fn serialize_slice<S: Serialize + Slice + ?Sized, Ser: Serializer>(
    slice: &S,
    serializer: Ser,
) -> Result<Ser::Ok, Ser::Error> {
    match try_as_bytes(slice) {
        Some(b) => serializer.serialize_bytes(b),
        None => slice.serialize(serializer),
    }
}

impl<S: Serialize + Slice + ?Sized, L: Layout> Serialize for ArcSlice<S, L> {
    fn serialize<Ser>(&self, serializer: Ser) -> Result<Ser::Ok, Ser::Error>
    where
        Ser: Serializer,
    {
        serialize_slice(self.deref(), serializer)
    }
}

impl<S: Serialize + Slice + ?Sized, L: LayoutMut, const UNIQUE: bool> Serialize
    for ArcSliceMut<S, L, UNIQUE>
{
    fn serialize<Ser>(&self, serializer: Ser) -> Result<Ser::Ok, Ser::Error>
    where
        Ser: Serializer,
    {
        serialize_slice(self.deref(), serializer)
    }
}

trait IntoArcSlice<S: Slice + ?Sized> {
    fn from_slice(slice: &S) -> Self;
    fn from_vec(vec: S::Vec) -> Self;
    fn from_arc_slice_mut(slice: ArcSliceMut<S, ArcLayout<false, false>>) -> Self;
}

impl<S: Slice + ?Sized, L: Layout> IntoArcSlice<S> for ArcSlice<S, L> {
    fn from_slice(slice: &S) -> Self {
        ArcSlice::new_bytes(slice)
    }
    fn from_vec(vec: S::Vec) -> Self {
        ArcSlice::new_byte_vec(vec)
    }
    fn from_arc_slice_mut(slice: ArcSliceMut<S, ArcLayout<false, false>>) -> Self {
        slice.freeze()
    }
}

impl<S: Slice + ?Sized, L: LayoutMut> IntoArcSlice<S> for ArcSliceMut<S, L> {
    fn from_slice(slice: &S) -> Self {
        ArcSliceMut::new_bytes(slice)
    }
    fn from_vec(vec: S::Vec) -> Self {
        ArcSliceMut::new_byte_vec(vec)
    }
    fn from_arc_slice_mut(slice: ArcSliceMut<S, ArcLayout<false, false>>) -> Self {
        slice.with_layout()
    }
}

struct ArcSliceVisitor<S: Slice + ?Sized, T>(PhantomData<(S::Vec, T)>);

impl<'de, S: Slice + Deserializable + ?Sized, T: IntoArcSlice<S>> de::Visitor<'de>
    for ArcSliceVisitor<S, T>
where
    S::Item: for<'a> Deserialize<'a>,
    S::TryFromSliceError: fmt::Display,
{
    type Value = T;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        S::expecting(formatter)
    }

    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        S::deserialize_from_str(v).map(T::from_slice)
    }

    fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        S::deserialize_from_string(v).map(T::from_vec)
    }

    fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        S::deserialize_from_bytes(v).map(T::from_slice)
    }

    fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<Self::Value, E>
    where
        E: de::Error,
    {
        S::deserialize_from_byte_buf(v).map(T::from_vec)
    }

    fn visit_seq<V>(self, mut seq: V) -> Result<Self::Value, V::Error>
    where
        V: de::SeqAccess<'de>,
    {
        if !S::try_deserialize_from_seq() {
            return Err(de::Error::invalid_type(de::Unexpected::Seq, &self));
        }
        let capacity = cmp::min(
            seq.size_hint().unwrap_or(0),
            MAX_DESERIALIZE_SIZE / core::mem::size_of::<S::Item>(),
        );
        let mut slice = ArcSliceMut::<[S::Item], ArcLayout<false, false>>::with_capacity(capacity);
        while let Some(item) = seq.next_element()? {
            slice.push(item);
        }
        Ok(T::from_arc_slice_mut(
            ArcSliceMut::try_from_arc_slice_mut(slice)
                .map_err(|(err, _)| de::Error::custom(err))?,
        ))
    }
}

impl<'de, S: Slice + Deserializable + ?Sized, L: Layout> Deserialize<'de> for ArcSlice<S, L>
where
    S::Item: for<'a> Deserialize<'a>,
    S::TryFromSliceError: fmt::Display,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        S::deserialize(deserializer, ArcSliceVisitor::<S, Self>(PhantomData))
    }
}

impl<'de, S: Slice + Deserializable + ?Sized, L: LayoutMut> Deserialize<'de> for ArcSliceMut<S, L>
where
    S::Item: for<'a> Deserialize<'a>,
    S::TryFromSliceError: fmt::Display,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        S::deserialize(deserializer, ArcSliceVisitor::<S, Self>(PhantomData))
    }
}

#[cfg(feature = "inlined")]
const _: () = {
    use crate::inlined::SmallArcSlice;

    impl<S: Serialize + Slice<Item = u8> + ?Sized, L: Layout> Serialize for SmallArcSlice<S, L> {
        fn serialize<Ser>(&self, serializer: Ser) -> Result<Ser::Ok, Ser::Error>
        where
            Ser: Serializer,
        {
            serialize_slice(self.deref(), serializer)
        }
    }

    impl<S: Slice<Item = u8> + ?Sized, L: Layout> IntoArcSlice<S> for SmallArcSlice<S, L> {
        fn from_slice(slice: &S) -> Self {
            SmallArcSlice::from_slice(slice)
        }
        fn from_vec(vec: S::Vec) -> Self {
            ArcSlice::<S, L>::from_vec(vec).into()
        }
        fn from_arc_slice_mut(slice: ArcSliceMut<S, ArcLayout<false, false>>) -> Self {
            slice.freeze().into()
        }
    }

    impl<'de, S: Slice<Item = u8> + Deserializable + ?Sized, L: LayoutMut> Deserialize<'de>
        for SmallArcSlice<S, L>
    where
        S::TryFromSliceError: fmt::Display,
    {
        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where
            D: Deserializer<'de>,
        {
            S::deserialize(deserializer, ArcSliceVisitor::<S, Self>(PhantomData))
        }
    }
};