mirror of
https://codeberg.org/icewind/bitbuffer.git
synced 2026-06-03 16:44:06 +02:00
basic serde support
This commit is contained in:
parent
cefc9c3500
commit
d08f92e11b
4 changed files with 137 additions and 1 deletions
|
|
@ -19,10 +19,12 @@ pub trait Endianness: private::Sealed {
|
|||
|
||||
/// Marks the buffer or stream as big endian
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct BigEndian;
|
||||
|
||||
/// Marks the buffer or stream as little endian
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct LittleEndian;
|
||||
|
||||
macro_rules! impl_endianness {
|
||||
|
|
|
|||
|
|
@ -764,6 +764,19 @@ where
|
|||
slice: self.slice,
|
||||
})
|
||||
}
|
||||
|
||||
/// Truncate the buffer to a given bit length
|
||||
pub fn truncate(&mut self, bit_len: usize) -> Result<()> {
|
||||
if bit_len > self.bit_len() {
|
||||
return Err(BitError::NotEnoughData {
|
||||
requested: bit_len,
|
||||
bits_left: self.bit_len(),
|
||||
});
|
||||
}
|
||||
|
||||
self.bit_len = bit_len;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, E: Endianness> From<&'a [u8]> for BitReadBuffer<'a, E> {
|
||||
|
|
|
|||
|
|
@ -743,3 +743,122 @@ impl<'a, E: Endianness> From<&'a [u8]> for BitReadStream<'a, E> {
|
|||
BitReadStream::new(BitReadBuffer::from(bytes))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{
|
||||
de::{self, MapAccess, SeqAccess, Visitor},
|
||||
ser::SerializeStruct,
|
||||
Deserialize, Deserializer, Serialize, Serializer,
|
||||
};
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl<'a, E: Endianness> Serialize for BitReadStream<'a, E> {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
let mut stream = self.clone();
|
||||
let mut data = stream.read_bytes(self.bits_left() / 8).unwrap().to_vec();
|
||||
if stream.bits_left() > 0 {
|
||||
data.push(stream.read_sized(stream.bits_left()).unwrap());
|
||||
}
|
||||
|
||||
let mut s = serializer.serialize_struct("BitReadStream", 3)?;
|
||||
s.serialize_field("data", &data)?;
|
||||
s.serialize_field("bit_length", &self.bit_len())?;
|
||||
s.end()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
impl<'de, E: Endianness> Deserialize<'de> for BitReadStream<'static, E> {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
#[derive(Deserialize)]
|
||||
#[serde(field_identifier, rename_all = "snake_case")]
|
||||
enum Field {
|
||||
Data,
|
||||
BitLength,
|
||||
}
|
||||
|
||||
use std::marker::PhantomData;
|
||||
struct ReadStreamVisitor<E>(PhantomData<E>);
|
||||
|
||||
impl<'de, E: Endianness> Visitor<'de> for ReadStreamVisitor<E> {
|
||||
type Value = BitReadStream<'static, E>;
|
||||
|
||||
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
formatter.write_str("struct BitReadStream")
|
||||
}
|
||||
|
||||
fn visit_seq<V>(self, mut seq: V) -> Result<Self::Value, V::Error>
|
||||
where
|
||||
V: SeqAccess<'de>,
|
||||
{
|
||||
let data = seq
|
||||
.next_element()?
|
||||
.ok_or_else(|| de::Error::invalid_length(0, &self))?;
|
||||
let bit_length = seq
|
||||
.next_element()?
|
||||
.ok_or_else(|| de::Error::invalid_length(1, &self))?;
|
||||
let mut buffer = BitReadBuffer::new_owned(data, E::endianness());
|
||||
buffer.truncate(bit_length).map_err(de::Error::custom)?;
|
||||
Ok(BitReadStream::new(buffer))
|
||||
}
|
||||
|
||||
fn visit_map<V>(self, mut map: V) -> Result<Self::Value, V::Error>
|
||||
where
|
||||
V: MapAccess<'de>,
|
||||
{
|
||||
let mut data = None;
|
||||
let mut bit_length = None;
|
||||
while let Some(key) = map.next_key()? {
|
||||
match key {
|
||||
Field::Data => {
|
||||
if data.is_some() {
|
||||
return Err(de::Error::duplicate_field("secs"));
|
||||
}
|
||||
data = Some(map.next_value()?);
|
||||
}
|
||||
Field::BitLength => {
|
||||
if bit_length.is_some() {
|
||||
return Err(de::Error::duplicate_field("nanos"));
|
||||
}
|
||||
bit_length = Some(map.next_value()?);
|
||||
}
|
||||
}
|
||||
}
|
||||
let data = data.ok_or_else(|| de::Error::missing_field("data"))?;
|
||||
let bit_length =
|
||||
bit_length.ok_or_else(|| de::Error::missing_field("bit_length"))?;
|
||||
let mut buffer = BitReadBuffer::new_owned(data, E::endianness());
|
||||
buffer.truncate(bit_length).map_err(de::Error::custom)?;
|
||||
Ok(BitReadStream::new(buffer))
|
||||
}
|
||||
}
|
||||
|
||||
const FIELDS: &'static [&'static str] = &["data", "bit_length"];
|
||||
deserializer.deserialize_struct("BitReadStream", FIELDS, ReadStreamVisitor(PhantomData))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
#[test]
|
||||
fn test_serde_roundtrip() {
|
||||
use crate::LittleEndian;
|
||||
|
||||
let mut buffer = BitReadBuffer::new_owned(vec![55; 8], LittleEndian);
|
||||
buffer.truncate(61).unwrap();
|
||||
let stream = BitReadStream::new(buffer);
|
||||
assert_eq!(61, stream.bit_len());
|
||||
|
||||
let json = serde_json::to_string(&stream).unwrap();
|
||||
|
||||
dbg!(&json);
|
||||
|
||||
let result: BitReadStream<LittleEndian> = serde_json::from_str(&json).unwrap();
|
||||
|
||||
assert_eq!(result, stream);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue