binary_codec/
variable.rs

1use crate::{
2    DeserializationError, SerializationError, SerializerConfig,
3    utils::{ensure_size, get_read_size, slice, write_size},
4};
5
6pub fn read_string<T: Clone>(
7    bytes: &[u8],
8    size_key: Option<&str>,
9    config: &mut SerializerConfig<T>,
10) -> Result<String, DeserializationError> {
11    let len = get_read_size(bytes, size_key, config)?;
12    config.reset_bits(true);
13    let slice = slice(config, bytes, len, true)?;
14    let string = String::from_utf8(slice.to_vec()).expect("Not valid UTF-8 bytes to create string");
15
16    Ok(string)
17}
18
19pub fn write_string<T: Clone>(
20    value: &str,
21    size_key: Option<&str>,
22    buffer: &mut Vec<u8>,
23    config: &mut SerializerConfig<T>,
24) -> Result<(), SerializationError> {
25    config.reset_bits(false);
26    write_size(value.len(), size_key, buffer, config)?;
27
28    buffer.extend_from_slice(&value.as_bytes());
29    config.pos += value.len();
30    Ok(())
31}
32
33pub fn read_object<T, U>(
34    bytes: &[u8],
35    size_key: Option<&str>,
36    config: &mut SerializerConfig<U>,
37) -> Result<T, DeserializationError>
38where
39    T: crate::BinaryDeserializer<U>,
40    U: Clone,
41{
42    let len = get_read_size(bytes, size_key, config)?;
43
44    // If exact size of buffer is available, don't slice
45    if ensure_size(config, bytes, len)? {
46        T::deserialize_bytes(bytes, Some(config))
47    } else {
48        // Create an isolated slice like we do for a String, but with its own config
49        config.reset_bits(true);
50        let mut temp_config = config.clone();
51        temp_config.reset();
52
53        let slice = slice(config, bytes, len, true)?;
54        T::deserialize_bytes(&slice, Some(&mut temp_config))
55    }
56}
57
58pub fn write_object<T, U>(
59    value: &T,
60    size_key: Option<&str>,
61    buffer: &mut Vec<u8>,
62    config: &mut SerializerConfig<U>,
63) -> Result<(), SerializationError>
64where
65    T: crate::BinarySerializer<U>,
66    U: Clone,
67{
68    // If length name is provided, we need to ensure the length matches
69    // So we write it to a different buffer
70    if size_key.is_some() {
71        let mut temp_buffer = Vec::new();
72        config.reset_bits(false);
73        value.write_bytes(&mut temp_buffer, Some(config))?;
74        write_size(temp_buffer.len(), size_key, buffer, config)?;
75        buffer.extend_from_slice(&temp_buffer);
76        Ok(())
77    } else {
78        value.write_bytes(buffer, Some(config))
79    }
80}
81
82#[cfg(test)]
83mod tests {
84    use crate::{BinaryDeserializer, dynamics::read_small_dynamic_unsigned, fixed_int::FixedInt};
85
86    use super::*;
87
88    struct TestObj {
89        nr: u16,
90    }
91
92    impl<T: Clone> BinaryDeserializer<T> for TestObj {
93        fn deserialize_bytes(
94            bytes: &[u8],
95            config: Option<&mut SerializerConfig<T>>,
96        ) -> Result<Self, DeserializationError> {
97            let config = config.unwrap();
98            let nr = FixedInt::read(bytes, config)?;
99            Ok(TestObj { nr })
100        }
101    }
102
103    #[test]
104    fn test_read_number_object_after_reading_few_bits() {
105        let bytes = vec![0b0000_0011, 0, 7];
106        let mut config = SerializerConfig::new(None);
107
108        let small_nr = read_small_dynamic_unsigned(&bytes, &mut config, 2).unwrap();
109        assert_eq!(small_nr, 3);
110        assert_eq!(config.bits, 2);
111        assert_eq!(config.pos, 0);
112
113        let obj = read_object::<TestObj, ()>(&bytes, None, &mut config).unwrap();
114        assert_eq!(obj.nr, 7);
115        assert_eq!(config.bits, 0);
116        assert_eq!(config.pos, 3);
117    }
118}