mod num;
use std::io::Read;
use log::warn;
use crate::{ProtocolError, Result};
pub trait Deserialize: Sized {
fn deserialize<R>(reader: &mut R, length: u32) -> Result<Self>
where
R: Read;
fn deserialize_in_place<R>(reader: &mut R, length: u32, place: &mut Self) -> Result<()>
where
R: Read,
{
*place = Deserialize::deserialize(reader, length)?;
Ok(())
}
}
impl Deserialize for String {
fn deserialize<R>(reader: &mut R, length: u32) -> Result<Self>
where
R: Read,
{
let mut bts = vec![0; length as usize];
reader.read_exact(&mut bts)?;
Ok(String::from_utf8(bts).unwrap())
}
}
impl<T> Deserialize for Option<T>
where
T: Deserialize,
{
fn deserialize<R>(reader: &mut R, length: u32) -> Result<Self>
where
R: Read,
{
Ok(Some(Deserialize::deserialize(reader, length)?))
}
}
impl<T> Deserialize for Vec<T>
where
T: Deserialize,
{
fn deserialize<R>(reader: &mut R, length: u32) -> Result<Self>
where
R: Read,
{
let vec: Vec<T> = vec![Deserialize::deserialize(reader, length)?];
Ok(vec)
}
fn deserialize_in_place<R>(reader: &mut R, length: u32, place: &mut Self) -> Result<()>
where
R: Read,
{
place.push(Deserialize::deserialize(reader, length)?);
Ok(())
}
}
#[derive(PartialEq, Debug)]
pub enum Header {
StructEnd,
Field {
id: u16,
len: u32,
},
}
pub fn read_header<R>(reader: &mut R) -> Result<Header>
where
R: Read,
{
let mut buf = [0; 4];
reader.read_exact(&mut buf)?;
let mut len = u32::from_le_bytes(buf);
if len == 0xFFFFFFFF {
return Ok(Header::StructEnd);
} else if len > 2 {
len -= 2;
}
let mut buf = [0; 2];
reader.read_exact(&mut buf)?;
let id = u16::from_le_bytes(buf);
Ok(Header::Field { id, len })
}
pub fn read_unknown_field<R>(reader: &mut R, header: Header) -> Result<()>
where
R: Read,
{
if let Header::Field { id, len } = header {
warn!("reading unknown field {} with len={}", id, len);
if len == 0 {
while let Header::Field { id, len } = read_header(reader)? {
read_unknown_field(reader, Header::Field { id, len })?
}
} else {
let mut buf = vec![0; len as usize];
reader.read_exact(&mut buf)?;
}
} else {
return Err(ProtocolError::Deserialization(
"calling read_unknown_field is not supported nor useful".to_string(),
));
}
Ok(())
}
#[cfg(test)]
mod tests {
use crate::de::{read_header, Deserialize, Header};
#[test]
fn test_read_header() {
let bts: Vec<u8> = vec![10, 0, 0, 0, 5, 0];
let result = read_header(&mut &bts[..]).unwrap();
if let Header::Field { id, len } = result {
assert_eq!(id, 5);
assert_eq!(len, 8);
} else {
panic!("Header should be of type Attribute")
}
}
#[test]
fn u8() {
let bts: Vec<u8> = vec![0x05];
let result: u8 = u8::deserialize(&mut &bts[..], 1).unwrap();
assert_eq!(result, 5)
}
#[test]
fn u8_wrong_length() {
let bts: Vec<u8> = vec![0x05];
let _result = u8::deserialize(&mut &bts[..], 2)
.expect_err("memory size (1) of type u8 differs from reported length 2");
}
}