#![doc=include_str!("../../doc/serdes/array.md")]
use core::{
any,
fmt::{
self,
Formatter,
},
};
use serde::{
de::{
Deserialize,
Deserializer,
Error,
MapAccess,
SeqAccess,
Unexpected,
Visitor,
},
ser::{
Serialize,
SerializeStruct,
Serializer,
},
};
use super::{
utils::{
Array,
TypeName,
},
Field,
FIELDS,
};
use crate::{
array::BitArray,
index::BitIdx,
mem::bits_of,
order::BitOrder,
store::BitStore,
};
impl<T, O> Serialize for BitArray<T, O>
where
T: BitStore,
O: BitOrder,
T::Mem: Serialize,
{
#[inline]
fn serialize<S>(&self, serializer: S) -> super::Result<S>
where S: Serializer {
let mut state = serializer.serialize_struct("BitArr", FIELDS.len())?;
state.serialize_field("order", &any::type_name::<O>())?;
state.serialize_field("head", &BitIdx::<T::Mem>::MIN)?;
state.serialize_field("bits", &(self.len() as u64))?;
state.serialize_field(
"data",
Array::from_ref(core::array::from_ref(&self.data)),
)?;
state.end()
}
}
impl<T, O, const N: usize> Serialize for BitArray<[T; N], O>
where
T: BitStore,
O: BitOrder,
T::Mem: Serialize,
{
#[inline]
fn serialize<S>(&self, serializer: S) -> super::Result<S>
where S: Serializer {
let mut state = serializer.serialize_struct("BitArr", FIELDS.len())?;
state.serialize_field("order", &any::type_name::<O>())?;
state.serialize_field("head", &BitIdx::<T::Mem>::MIN)?;
state.serialize_field("bits", &(self.len() as u64))?;
state.serialize_field("data", Array::from_ref(&self.data))?;
state.end()
}
}
impl<'de, T, O> Deserialize<'de> for BitArray<T, O>
where
T: BitStore,
O: BitOrder,
T::Mem: Deserialize<'de>,
{
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'de> {
deserializer
.deserialize_struct("BitArr", FIELDS, BitArrVisitor::<T, O, 1>::THIS)
.map(|BitArray { data: [elem], .. }| BitArray::new(elem))
}
}
impl<'de, T, O, const N: usize> Deserialize<'de> for BitArray<[T; N], O>
where
T: BitStore,
O: BitOrder,
T::Mem: Deserialize<'de>,
{
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: Deserializer<'de> {
deserializer.deserialize_struct(
"BitArr",
FIELDS,
BitArrVisitor::<T, O, N>::THIS,
)
}
}
struct BitArrVisitor<T, O, const N: usize>
where
T: BitStore,
O: BitOrder,
{
order: Option<TypeName<O>>,
head: Option<BitIdx<T::Mem>>,
bits: Option<u64>,
data: Option<Array<T, N>>,
}
impl<'de, T, O, const N: usize> BitArrVisitor<T, O, N>
where
T: BitStore,
O: BitOrder,
Array<T, N>: Deserialize<'de>,
{
const THIS: Self = Self {
order: None,
head: None,
bits: None,
data: None,
};
#[inline]
fn assemble<E>(mut self) -> Result<BitArray<[T; N], O>, E>
where E: Error {
self.order.take().ok_or_else(|| E::missing_field("order"))?;
let head = self.head.take().ok_or_else(|| E::missing_field("head"))?;
let bits = self.bits.take().ok_or_else(|| E::missing_field("bits"))?;
let data = self.data.take().ok_or_else(|| E::missing_field("data"))?;
if head != BitIdx::MIN {
return Err(E::invalid_value(
Unexpected::Unsigned(head.into_inner() as u64),
&"`BitArray` must have a head-bit of `0`",
));
}
let bits = bits as usize;
if bits != bits_of::<[T; N]>() {
return Err(E::invalid_length(bits, &self));
}
Ok(BitArray::new(data.inner))
}
}
impl<'de, T, O, const N: usize> Visitor<'de> for BitArrVisitor<T, O, N>
where
T: BitStore,
O: BitOrder,
Array<T, N>: Deserialize<'de>,
{
type Value = BitArray<[T; N], O>;
#[inline]
fn expecting(&self, fmt: &mut Formatter) -> fmt::Result {
write!(
fmt,
"a `BitArray<[u{}; {}], {}>`",
bits_of::<T::Mem>(),
N,
any::type_name::<O>(),
)
}
#[inline]
fn visit_seq<V>(mut self, mut seq: V) -> Result<Self::Value, V::Error>
where V: SeqAccess<'de> {
self.order = Some(
seq.next_element()?
.ok_or_else(|| <V::Error>::invalid_length(0, &self))?,
);
self.head = Some(
seq.next_element()?
.ok_or_else(|| <V::Error>::invalid_length(1, &self))?,
);
self.bits = Some(
seq.next_element()?
.ok_or_else(|| <V::Error>::invalid_length(2, &self))?,
);
self.data = Some(
seq.next_element()?
.ok_or_else(|| <V::Error>::invalid_length(3, &self))?,
);
self.assemble()
}
#[inline]
fn visit_map<V>(mut self, mut map: V) -> Result<Self::Value, V::Error>
where V: MapAccess<'de> {
while let Some(key) = map.next_key()? {
match key {
Field::Order => {
if self.order.replace(map.next_value()?).is_some() {
return Err(<V::Error>::duplicate_field("order"));
}
},
Field::Head => {
if self.head.replace(map.next_value()?).is_some() {
return Err(<V::Error>::duplicate_field("head"));
}
},
Field::Bits => {
if self.bits.replace(map.next_value()?).is_some() {
return Err(<V::Error>::duplicate_field("bits"));
}
},
Field::Data => {
if self.data.replace(map.next_value()?).is_some() {
return Err(<V::Error>::duplicate_field("data"));
}
},
}
}
self.assemble()
}
}
#[cfg(test)]
mod tests {
#[cfg(all(feature = "alloc", not(feature = "std")))]
use alloc::format;
use core::any;
use serde_test::{
assert_de_tokens,
assert_de_tokens_error,
assert_ser_tokens,
Token,
};
use crate::prelude::*;
#[test]
#[cfg(feature = "std")]
fn roundtrip() -> Result<(), Box<dyn std::error::Error>> {
type BA = BitArr!(for 16, in u8, Msb0);
let array = [0x3Cu8, 0xA5].into_bitarray::<Msb0>();
let bytes = bincode::serialize(&array)?;
let array2 = bincode::deserialize::<BA>(&bytes)?;
assert_eq!(array, array2);
let json = serde_json::to_string(&array)?;
let array3 = serde_json::from_str::<BA>(&json)?;
assert_eq!(array, array3);
let json_value = serde_json::to_value(&array)?;
let array4 = serde_json::from_value::<BA>(json_value)?;
assert_eq!(array, array4);
type BA2 = BitArray<u16, Msb0>;
let array = BA2::new(44203);
let bytes = bincode::serialize(&array)?;
let array2 = bincode::deserialize::<BA2>(&bytes)?;
assert_eq!(array, array2);
let json = serde_json::to_string(&array)?;
let array3 = serde_json::from_str::<BA2>(&json)?;
assert_eq!(array, array3);
let json_value = serde_json::to_value(&array)?;
let array4 = serde_json::from_value::<BA2>(json_value)?;
assert_eq!(array, array4);
Ok(())
}
#[test]
fn tokens() {
let array = [0x3Cu8, 0xA5].into_bitarray::<Msb0>();
let tokens = &mut [
Token::Struct {
name: "BitArr",
len: 4,
},
Token::Str("order"),
Token::Str(any::type_name::<Msb0>()),
Token::Str("head"),
Token::Struct {
name: "BitIdx",
len: 2,
},
Token::Str("width"),
Token::U8(8),
Token::Str("index"),
Token::U8(0),
Token::StructEnd,
Token::Str("bits"),
Token::U64(16),
Token::Str("data"),
Token::Tuple { len: 2 },
Token::U8(0x3C),
Token::U8(0xA5),
Token::TupleEnd,
Token::StructEnd,
];
assert_ser_tokens(&array, tokens);
tokens[1 .. 4].copy_from_slice(&[
Token::BorrowedStr("order"),
Token::BorrowedStr(any::type_name::<Msb0>()),
Token::BorrowedStr("head"),
]);
tokens[5] = Token::BorrowedStr("width");
tokens[7] = Token::BorrowedStr("index");
tokens[10] = Token::BorrowedStr("bits");
tokens[12] = Token::BorrowedStr("data");
assert_de_tokens(&array, tokens);
}
#[test]
#[cfg(feature = "alloc")]
fn errors() {
type BA = BitArr!(for 8, in u8, Msb0);
let mut tokens = vec![
Token::Seq { len: Some(4) },
Token::BorrowedStr(any::type_name::<Msb0>()),
];
assert_de_tokens_error::<BitArr!(for 8, in u8, Lsb0)>(
&tokens,
&format!(
"invalid value: string \"{}\", expected the string \"{}\"",
any::type_name::<Msb0>(),
any::type_name::<Lsb0>(),
),
);
tokens.extend([
Token::Seq { len: Some(2) },
Token::U8(8),
Token::U8(0),
Token::SeqEnd,
Token::U64(8),
Token::Tuple { len: 1 },
Token::U8(0),
Token::TupleEnd,
Token::SeqEnd,
]);
tokens[6] = Token::U64(7);
assert_de_tokens_error::<BA>(
&tokens,
"invalid length 7, expected a `BitArray<[u8; 1], \
bitvec::order::Msb0>`",
);
tokens[4] = Token::U8(1);
assert_de_tokens_error::<BA>(
&tokens,
"invalid value: integer `1`, expected `BitArray` must have a \
head-bit of `0`",
);
assert_de_tokens_error::<BA>(
&[
Token::Struct {
name: "BitArr",
len: 2,
},
Token::BorrowedStr("placeholder"),
],
&format!(
"unknown field `placeholder`, expected one of `{}`",
super::FIELDS.join("`, `"),
),
);
assert_de_tokens_error::<BA>(
&[
Token::Struct {
name: "BitArr",
len: 2,
},
Token::BorrowedStr("order"),
Token::BorrowedStr(any::type_name::<Msb0>()),
Token::BorrowedStr("order"),
Token::BorrowedStr(any::type_name::<Msb0>()),
Token::StructEnd,
],
"duplicate field `order`",
);
assert_de_tokens_error::<BA>(
&[
Token::Struct {
name: "BitArr",
len: 2,
},
Token::BorrowedStr("head"),
Token::Seq { len: Some(2) },
Token::U8(8),
Token::U8(0),
Token::SeqEnd,
Token::BorrowedStr("head"),
Token::Seq { len: Some(2) },
Token::U8(8),
Token::U8(0),
Token::SeqEnd,
Token::StructEnd,
],
"duplicate field `head`",
);
assert_de_tokens_error::<BA>(
&[
Token::Struct {
name: "BitArr",
len: 2,
},
Token::BorrowedStr("bits"),
Token::U64(8),
Token::BorrowedStr("bits"),
Token::U64(8),
Token::StructEnd,
],
"duplicate field `bits`",
);
assert_de_tokens_error::<BA>(
&[
Token::Struct {
name: "BitArr",
len: 2,
},
Token::BorrowedStr("data"),
Token::Tuple { len: 1 },
Token::U8(0),
Token::TupleEnd,
Token::BorrowedStr("data"),
Token::Tuple { len: 1 },
Token::U8(1),
Token::TupleEnd,
Token::StructEnd,
],
"duplicate field `data`",
);
}
}