use bytemuck::AnyBitPattern;
use serde::de::{self, Visitor};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use crate::ext::{Complex, ComplexElement, ComplexSlice, serialize_typed_slice};
use crate::fast::BeveTypedSlice;
fn bytes_to_vec<E: AnyBitPattern>(payload: &[u8], scalar_size: usize) -> Vec<E> {
let elem = core::mem::size_of::<E>();
debug_assert!(elem != 0 && payload.len().is_multiple_of(elem));
let n = payload.len() / elem.max(1);
let mut out: Vec<E> = Vec::with_capacity(n);
if n != 0 {
let nbytes = n * elem;
unsafe {
core::ptr::copy_nonoverlapping(payload.as_ptr(), out.as_mut_ptr() as *mut u8, nbytes);
out.set_len(n);
}
#[cfg(not(target_endian = "little"))]
{
let bytes =
unsafe { core::slice::from_raw_parts_mut(out.as_mut_ptr() as *mut u8, nbytes) };
for s in bytes.chunks_exact_mut(scalar_size) {
s.reverse();
}
}
}
#[cfg(target_endian = "little")]
let _ = scalar_size;
out
}
fn reserve_from_hint<E>(hint: Option<usize>) -> usize {
let elem = core::mem::size_of::<E>().max(1);
hint.unwrap_or(0).min(crate::de::MAX_PREALLOC_BYTES / elem)
}
struct TypedArrayVisitor<S>(core::marker::PhantomData<S>);
impl<'de, S> Visitor<'de> for TypedArrayVisitor<S>
where
S: BeveTypedSlice + AnyBitPattern + Deserialize<'de>,
{
type Value = Vec<S>;
fn expecting(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "a beve typed numeric array")
}
fn visit_borrowed_bytes<E: de::Error>(self, v: &'de [u8]) -> Result<Self::Value, E> {
Ok(bytes_to_vec::<S>(v, S::ELEM_SIZE))
}
fn visit_bytes<E: de::Error>(self, v: &[u8]) -> Result<Self::Value, E> {
Ok(bytes_to_vec::<S>(v, S::ELEM_SIZE))
}
fn visit_byte_buf<E: de::Error>(self, v: Vec<u8>) -> Result<Self::Value, E> {
Ok(bytes_to_vec::<S>(&v, S::ELEM_SIZE))
}
fn visit_seq<A: de::SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
let mut out = Vec::with_capacity(reserve_from_hint::<S>(seq.size_hint()));
while let Some(x) = seq.next_element::<S>()? {
out.push(x);
}
Ok(out)
}
fn visit_newtype_struct<D: Deserializer<'de>>(self, d: D) -> Result<Self::Value, D::Error> {
Vec::<S>::deserialize(d)
}
}
struct ComplexArrayVisitor<S, T>(core::marker::PhantomData<(S, T)>);
impl<'de, S, T> Visitor<'de> for ComplexArrayVisitor<S, T>
where
S: BeveTypedSlice,
T: AnyBitPattern + Deserialize<'de>,
{
type Value = Vec<T>;
fn expecting(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
write!(f, "a beve complex array")
}
fn visit_borrowed_bytes<E: de::Error>(self, v: &'de [u8]) -> Result<Self::Value, E> {
Ok(bytes_to_vec::<T>(v, S::ELEM_SIZE))
}
fn visit_bytes<E: de::Error>(self, v: &[u8]) -> Result<Self::Value, E> {
Ok(bytes_to_vec::<T>(v, S::ELEM_SIZE))
}
fn visit_byte_buf<E: de::Error>(self, v: Vec<u8>) -> Result<Self::Value, E> {
Ok(bytes_to_vec::<T>(&v, S::ELEM_SIZE))
}
fn visit_seq<A: de::SeqAccess<'de>>(self, mut seq: A) -> Result<Self::Value, A::Error> {
let mut out = Vec::with_capacity(reserve_from_hint::<T>(seq.size_hint()));
while let Some(x) = seq.next_element::<T>()? {
out.push(x);
}
Ok(out)
}
fn visit_newtype_struct<D: Deserializer<'de>>(self, d: D) -> Result<Self::Value, D::Error> {
Vec::<T>::deserialize(d)
}
}
fn assert_complex_layout<S, T>() {
assert_eq!(
core::mem::align_of::<T>(),
core::mem::align_of::<Complex<S>>(),
"beve complex array: ComplexElement impl has the wrong element alignment"
);
assert_eq!(
core::mem::size_of::<T>(),
core::mem::size_of::<Complex<S>>(),
"beve complex array: ComplexElement impl has the wrong element size"
);
}
pub mod typed {
use super::*;
macro_rules! typed_with {
($module:ident, $scalar:ty, $nt:expr) => {
#[doc = concat!("Bulk `Vec<", stringify!($scalar), ">` codec for `#[serde(with = ...)]`.")]
pub mod $module {
use super::*;
pub fn serialize<S: Serializer>(
value: &[$scalar],
serializer: S,
) -> Result<S::Ok, S::Error> {
serialize_typed_slice(value, $nt, serializer)
}
pub fn deserialize<'de, D: Deserializer<'de>>(
deserializer: D,
) -> Result<Vec<$scalar>, D::Error> {
deserializer.deserialize_newtype_struct(
$nt,
TypedArrayVisitor::<$scalar>(core::marker::PhantomData),
)
}
}
};
}
typed_with!(i8, i8, crate::ext::NT_TYPED_ARRAY_I8);
typed_with!(i16, i16, crate::ext::NT_TYPED_ARRAY_I16);
typed_with!(i32, i32, crate::ext::NT_TYPED_ARRAY_I32);
typed_with!(i64, i64, crate::ext::NT_TYPED_ARRAY_I64);
typed_with!(i128, i128, crate::ext::NT_TYPED_ARRAY_I128);
typed_with!(u8, u8, crate::ext::NT_TYPED_ARRAY_U8);
typed_with!(u16, u16, crate::ext::NT_TYPED_ARRAY_U16);
typed_with!(u32, u32, crate::ext::NT_TYPED_ARRAY_U32);
typed_with!(u64, u64, crate::ext::NT_TYPED_ARRAY_U64);
typed_with!(u128, u128, crate::ext::NT_TYPED_ARRAY_U128);
typed_with!(f32, f32, crate::ext::NT_TYPED_ARRAY_F32);
typed_with!(f64, f64, crate::ext::NT_TYPED_ARRAY_F64);
}
pub mod complex_array {
use super::*;
macro_rules! complex_with {
($module:ident, $scalar:ty, $nt:expr) => {
#[doc = concat!("Bulk `Vec<Complex<", stringify!($scalar), ">>` codec for `#[serde(with = ...)]`.")]
pub mod $module {
use super::*;
pub fn serialize<S, T>(value: &[T], serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
T: ComplexElement<Component = $scalar> + Serialize,
{
if serializer.is_human_readable() {
use serde::ser::SerializeSeq;
let mut seq = serializer.serialize_seq(Some(value.len()))?;
for v in value {
seq.serialize_element(v)?;
}
return seq.end();
}
assert_complex_layout::<$scalar, T>();
let slice: &[Complex<$scalar>] = unsafe {
core::slice::from_raw_parts(
value.as_ptr() as *const Complex<$scalar>,
value.len(),
)
};
ComplexSlice(slice).serialize(serializer)
}
pub fn deserialize<'de, D, T>(deserializer: D) -> Result<Vec<T>, D::Error>
where
D: Deserializer<'de>,
T: ComplexElement<Component = $scalar> + AnyBitPattern + Deserialize<'de>,
{
assert_complex_layout::<$scalar, T>();
deserializer.deserialize_newtype_struct(
$nt,
ComplexArrayVisitor::<$scalar, T>(core::marker::PhantomData),
)
}
}
};
}
complex_with!(f32, f32, crate::ext::NT_COMPLEX_ARRAY_F32);
complex_with!(f64, f64, crate::ext::NT_COMPLEX_ARRAY_F64);
complex_with!(i8, i8, crate::ext::NT_COMPLEX_ARRAY_I8);
complex_with!(i16, i16, crate::ext::NT_COMPLEX_ARRAY_I16);
complex_with!(i32, i32, crate::ext::NT_COMPLEX_ARRAY_I32);
complex_with!(i64, i64, crate::ext::NT_COMPLEX_ARRAY_I64);
complex_with!(i128, i128, crate::ext::NT_COMPLEX_ARRAY_I128);
complex_with!(u8, u8, crate::ext::NT_COMPLEX_ARRAY_U8);
complex_with!(u16, u16, crate::ext::NT_COMPLEX_ARRAY_U16);
complex_with!(u32, u32, crate::ext::NT_COMPLEX_ARRAY_U32);
complex_with!(u64, u64, crate::ext::NT_COMPLEX_ARRAY_U64);
complex_with!(u128, u128, crate::ext::NT_COMPLEX_ARRAY_U128);
}
#[cfg(test)]
mod marker_tests {
use super::*;
use core::cell::Cell;
use core::fmt;
struct NameSpy<'a>(&'a Cell<&'static str>);
#[derive(Debug)]
struct Stop;
impl fmt::Display for Stop {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("stop")
}
}
impl std::error::Error for Stop {}
impl de::Error for Stop {
fn custom<T: fmt::Display>(_: T) -> Self {
Stop
}
}
impl<'de> Deserializer<'de> for NameSpy<'_> {
type Error = Stop;
fn deserialize_newtype_struct<V: Visitor<'de>>(
self,
name: &'static str,
_visitor: V,
) -> Result<V::Value, Stop> {
self.0.set(name);
Err(Stop)
}
fn deserialize_any<V: Visitor<'de>>(self, _visitor: V) -> Result<V::Value, Stop> {
Err(Stop)
}
serde::forward_to_deserialize_any! {
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
bytes byte_buf option unit unit_struct seq tuple tuple_struct map
struct enum identifier ignored_any
}
}
#[test]
fn each_complex_array_module_asks_for_its_own_marker() {
macro_rules! check {
($module:ident, $scalar:ty, $nt:expr) => {{
let seen = Cell::new("");
let _ = complex_array::$module::deserialize::<_, Complex<$scalar>>(NameSpy(&seen));
assert_eq!(
seen.get(),
$nt,
concat!(
"complex_array::",
stringify!($module),
" must request its own marker"
)
);
}};
}
check!(f32, f32, crate::ext::NT_COMPLEX_ARRAY_F32);
check!(f64, f64, crate::ext::NT_COMPLEX_ARRAY_F64);
check!(i8, i8, crate::ext::NT_COMPLEX_ARRAY_I8);
check!(i16, i16, crate::ext::NT_COMPLEX_ARRAY_I16);
check!(i32, i32, crate::ext::NT_COMPLEX_ARRAY_I32);
check!(i64, i64, crate::ext::NT_COMPLEX_ARRAY_I64);
check!(i128, i128, crate::ext::NT_COMPLEX_ARRAY_I128);
check!(u8, u8, crate::ext::NT_COMPLEX_ARRAY_U8);
check!(u16, u16, crate::ext::NT_COMPLEX_ARRAY_U16);
check!(u32, u32, crate::ext::NT_COMPLEX_ARRAY_U32);
check!(u64, u64, crate::ext::NT_COMPLEX_ARRAY_U64);
check!(u128, u128, crate::ext::NT_COMPLEX_ARRAY_U128);
}
#[test]
fn complex_array_markers_are_all_distinct() {
let names = [
crate::ext::NT_COMPLEX_ARRAY_F32,
crate::ext::NT_COMPLEX_ARRAY_F64,
crate::ext::NT_COMPLEX_ARRAY_I8,
crate::ext::NT_COMPLEX_ARRAY_I16,
crate::ext::NT_COMPLEX_ARRAY_I32,
crate::ext::NT_COMPLEX_ARRAY_I64,
crate::ext::NT_COMPLEX_ARRAY_I128,
crate::ext::NT_COMPLEX_ARRAY_U8,
crate::ext::NT_COMPLEX_ARRAY_U16,
crate::ext::NT_COMPLEX_ARRAY_U32,
crate::ext::NT_COMPLEX_ARRAY_U64,
crate::ext::NT_COMPLEX_ARRAY_U128,
];
let mut sorted = names.to_vec();
sorted.sort_unstable();
sorted.dedup();
assert_eq!(sorted.len(), names.len(), "markers must be distinct");
}
}