devela/data/serde/utils/
array_wrapper.rsuse crate::{MaybeUninit, PhantomData};
use core::{fmt, mem};
use serde::{
de::{self, Deserialize, Deserializer, SeqAccess, Visitor},
ser::{Serialize, SerializeTuple, Serializer},
};
#[cfg(feature = "alloc")]
use {crate::Vec, serde::ser::SerializeSeq};
struct ArrayWrap<'a, T: Serialize, const N: usize> {
item: &'a [T; N],
}
impl<T: Serialize, const N: usize> Serialize for ArrayWrap<'_, T, N> {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
super::serialize(self.item, serializer)
}
}
mod _private {
pub trait SerializableArray<T: super::Serialize, const N: usize> {
fn serialize<S: super::Serializer>(&self, ser: S) -> Result<S::Ok, S::Error>;
}
}
pub fn serialize<A, S, T, const N: usize>(data: &A, ser: S) -> Result<S::Ok, S::Error>
where
A: _private::SerializableArray<T, N>,
S: Serializer,
T: Serialize,
{
data.serialize(ser)
}
pub fn deserialize<'de, D, T, const N: usize>(deserialize: D) -> Result<[T; N], D::Error>
where
D: Deserializer<'de>,
T: Deserialize<'de>,
{
deserialize.deserialize_tuple(N, ArrayVisitor(PhantomData))
}
impl<T: Serialize, const N: usize, const M: usize> _private::SerializableArray<T, N>
for [[T; N]; M]
{
fn serialize<S>(&self, ser: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut s = ser.serialize_tuple(N)?;
for item in self {
let wrapped = ArrayWrap { item };
s.serialize_element(&wrapped)?;
}
s.end()
}
}
#[cfg(feature = "alloc")]
#[cfg_attr(feature = "nightly_doc", doc(cfg(feature = "alloc")))]
impl<T: Serialize, const N: usize> _private::SerializableArray<T, N> for Vec<[T; N]> {
fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
let mut s = ser.serialize_seq(Some(self.len()))?;
for item in self {
let wrapped = ArrayWrap { item };
s.serialize_element(&wrapped)?;
}
s.end()
}
}
impl<T: Serialize, const N: usize> _private::SerializableArray<T, N> for [T; N] {
fn serialize<S: Serializer>(&self, ser: S) -> Result<S::Ok, S::Error> {
serialize_as_tuple(self, ser)
}
}
fn serialize_as_tuple<S, T, const N: usize>(data: &[T; N], ser: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
T: Serialize,
{
let mut s = ser.serialize_tuple(N)?;
for item in data {
s.serialize_element(item)?;
}
s.end()
}
struct ArrayVisitor<T, const N: usize>(PhantomData<T>);
impl<'de, T: Deserialize<'de>, const N: usize> Visitor<'de> for ArrayVisitor<T, N> {
type Value = [T; N];
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
write!(formatter, "an array of size {}", N)
}
fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
let mut arr: [MaybeUninit<T>; N] = unsafe { MaybeUninit::uninit().assume_init() };
let mut place_iter = arr.iter_mut();
let mut cnt_filled = 0;
let err = loop {
match (seq.next_element(), place_iter.next()) {
(Ok(Some(val)), Some(place)) => *place = MaybeUninit::new(val),
(Ok(None), None) => break None,
(Err(e), _) => break Some(e),
(Ok(None), Some(_)) | (Ok(Some(_)), None) => {
break Some(de::Error::invalid_length(cnt_filled, &self))
}
}
cnt_filled += 1;
};
if let Some(err) = err {
if mem::needs_drop::<T>() {
for elem in IntoIterator::into_iter(arr).take(cnt_filled) {
unsafe {
elem.assume_init();
}
}
}
return Err(err);
}
let ret = unsafe { mem::transmute_copy(&arr) };
Ok(ret)
}
}