zusi_protocol/de/
mod.rs

1mod num;
2use std::io::Read;
3
4use log::warn;
5
6use crate::{ProtocolError, Result};
7
8pub trait Deserialize: Sized {
9    fn deserialize<R>(reader: &mut R, length: u32) -> Result<Self>
10    where
11        R: Read;
12
13    fn deserialize_in_place<R>(reader: &mut R, length: u32, place: &mut Self) -> Result<()>
14    where
15        R: Read,
16    {
17        *place = Deserialize::deserialize(reader, length)?;
18
19        Ok(())
20    }
21}
22
23impl Deserialize for String {
24    fn deserialize<R>(reader: &mut R, length: u32) -> Result<Self>
25    where
26        R: Read,
27    {
28        let mut bts = vec![0; length as usize];
29        reader.read_exact(&mut bts)?;
30
31        Ok(String::from_utf8(bts).unwrap())
32    }
33}
34
35impl<T> Deserialize for Option<T>
36where
37    T: Deserialize,
38{
39    fn deserialize<R>(reader: &mut R, length: u32) -> Result<Self>
40    where
41        R: Read,
42    {
43        Ok(Some(Deserialize::deserialize(reader, length)?))
44    }
45}
46
47impl<T> Deserialize for Vec<T>
48where
49    T: Deserialize,
50{
51    /// # Warning
52    /// This function is a bit funky to use for a Vec.
53    /// By the nature of this TCP protocol, we don't know if a read value is the first or a
54    /// consecutive following value of the `Vec<T>`.
55    ///
56    /// The caller of this function has to handle the case of a `Vec<T>` with more than one value
57    /// and has to merge the returned `Vec<T>` with a single value with the values deserialized
58    /// before.
59    ///
60    /// When possible `deserialize_in_place` should be used instead, as that function has access
61    /// to the underlying object and can append the deserialized element.
62    fn deserialize<R>(reader: &mut R, length: u32) -> Result<Self>
63    where
64        R: Read,
65    {
66        let vec: Vec<T> = vec![Deserialize::deserialize(reader, length)?];
67
68        Ok(vec)
69    }
70
71    /// Deserializes an element of `Vec<T>` and appends it to the current object.
72    fn deserialize_in_place<R>(reader: &mut R, length: u32, place: &mut Self) -> Result<()>
73    where
74        R: Read,
75    {
76        place.push(Deserialize::deserialize(reader, length)?);
77
78        Ok(())
79    }
80}
81
82#[derive(PartialEq, Debug)]
83pub enum Header {
84    StructEnd,
85    Field {
86        id: u16,
87        /// When `len == 0` a struct follows.
88        len: u32,
89    },
90}
91
92/// Reads a Node or Attribute header
93///
94/// Header is composed of u32 length and u8 id.
95///
96/// When `len == 0` a struct follows and if `len == 0xFFFFFFFF` we are at the end of a struct.
97pub fn read_header<R>(reader: &mut R) -> Result<Header>
98where
99    R: Read,
100{
101    let mut buf = [0; 4];
102    reader.read_exact(&mut buf)?;
103
104    let mut len = u32::from_le_bytes(buf);
105    if len == 0xFFFFFFFF {
106        return Ok(Header::StructEnd);
107    } else if len > 2 {
108        len -= 2;
109    }
110
111    let mut buf = [0; 2];
112    reader.read_exact(&mut buf)?;
113    let id = u16::from_le_bytes(buf);
114
115    Ok(Header::Field { id, len })
116}
117
118pub fn read_unknown_field<R>(reader: &mut R, header: Header) -> Result<()>
119where
120    R: Read,
121{
122    if let Header::Field { id, len } = header {
123        warn!("reading unknown field {} with len={}", id, len);
124
125        if len == 0 {
126            // we found an unknown struct and go recursive through it
127            while let Header::Field { id, len } = read_header(reader)? {
128                read_unknown_field(reader, Header::Field { id, len })?
129            }
130        } else {
131            let mut buf = vec![0; len as usize];
132            reader.read_exact(&mut buf)?;
133        }
134    } else {
135        return Err(ProtocolError::Deserialization(
136            "calling read_unknown_field is not supported nor useful".to_string(),
137        ));
138    }
139
140    Ok(())
141}
142
143#[cfg(test)]
144mod tests {
145    use crate::de::{read_header, Header};
146
147    #[test]
148    fn test_read_header() {
149        let bts: Vec<u8> = vec![10, 0, 0, 0, 5, 0];
150
151        let result = read_header(&mut &bts[..]).unwrap();
152
153        if let Header::Field { id, len } = result {
154            assert_eq!(id, 5);
155            // we subtract 2 from 10, as id is counted towards the size
156            assert_eq!(len, 8);
157        } else {
158            panic!("Header should be of type Attribute")
159        }
160    }
161}