use crate::{de, io, Deserialize, Node, Serialize, Tape, Write};
use std::mem::MaybeUninit;
use std::ptr;
struct Guard<'a, T, const N: usize> {
pub array: &'a mut [MaybeUninit<T>; N], pub initialized: usize,
}
impl<T, const N: usize> Guard<'_, T, N> {
#[inline]
pub unsafe fn push_unchecked(&mut self, item: T) {
unsafe {
self.array.get_unchecked_mut(self.initialized).write(item);
self.initialized = self.initialized.wrapping_add(1); }
}
}
impl<T, const N: usize> Drop for Guard<'_, T, N> {
fn drop(&mut self) {
debug_assert!(self.initialized <= N);
unsafe {
let slice = ptr::slice_from_raw_parts_mut(
self.array.as_mut_ptr().cast::<T>(),
self.initialized,
);
ptr::drop_in_place(slice);
}
}
}
impl<'input, T, const N: usize> Deserialize<'input> for [T; N]
where
T: Deserialize<'input>,
{
#[inline]
fn from_tape(tape: &mut Tape<'input>) -> de::Result<Self>
where
Self: Sized + 'input,
{
if let Some(Node::Array { len, .. }) = tape.next() {
if len != N {
return Err(de::Error::custom(
"expected array of len {N} found array of len {len}",
));
}
if N == 0 {
#[allow(clippy::ref_as_ptr)]
return Ok(unsafe { ptr::read((&[]) as *const [T; N]) });
}
let mut array: [MaybeUninit<T>; N] = unsafe { MaybeUninit::uninit().assume_init() };
let mut guard = Guard {
array: &mut array,
initialized: 0,
};
while guard.initialized < N {
let item = T::from_tape(tape)?;
unsafe { guard.push_unchecked(item) };
}
core::mem::forget(guard);
Ok(unsafe { array.map(|x| x.assume_init()) })
} else {
Err(de::Error::expected_array())
}
}
}
impl<T, const N: usize> Serialize for [T; N]
where
T: Serialize,
{
#[inline]
fn json_write<W>(&self, writer: &mut W) -> io::Result<()>
where
W: Write,
{
if N == 0 {
return writer.write_all(b"[]");
}
let mut i = self.iter();
if let Some(first) = i.next() {
writer.write_all(b"[")?;
first.json_write(writer)?;
for e in i {
writer.write_all(b",")?;
e.json_write(writer)?;
}
writer.write_all(b"]")
} else {
unreachable!()
}
}
}
#[cfg(test)]
mod test {
use crate::*;
#[test]
fn arr() {
let s: [u8; 0] = [];
assert_eq!(s.json_string().expect("invalid "), "[]");
assert_eq!([1].json_string().expect("invalid "), "[1]");
assert_eq!([1, 2].json_string().expect("invalid "), "[1,2]");
assert_eq!([1, 2, 3].json_string().expect("invalid "), "[1,2,3]");
}
#[test]
fn arr2() {
assert_eq!(
<[u8; 0] as Deserialize<'_>>::from_slice(&mut b"[]".to_vec()),
Ok([])
);
assert_eq!(
<[u8; 1] as Deserialize<'_>>::from_slice(&mut b"[1]".to_vec()),
Ok([1])
);
assert_eq!(
<[u8; 2] as Deserialize<'_>>::from_slice(&mut b"[1, 2]".to_vec()),
Ok([1, 2])
);
assert_eq!(
<[u8; 3] as Deserialize<'_>>::from_slice(&mut b"[1, 2, 3]".to_vec()),
Ok([1, 2, 3])
);
}
#[test]
fn slice() {
let s: [u8; 0] = [];
assert_eq!(s.json_string().expect("invalid data"), "[]");
assert_eq!([1].json_string().expect("invalid data"), "[1]");
assert_eq!([1, 2].json_string().expect("invalid data"), "[1,2]");
assert_eq!([1, 2, 3].json_string().expect("invalid data"), "[1,2,3]");
}
}