godot_binary_serialization/decoder/
dictionary.rs

1use byteorder::{ByteOrder, LittleEndian};
2use indexmap::IndexMap;
3
4use crate::types::{primitive::GodotNull, structures::GodotDictionary};
5
6use super::Decoder;
7
8impl Decoder {
9    /// Decodes bytes into a godot dictionary.
10    ///
11    /// # Example
12    ///
13    /// ```rust,ignore
14    /// // Typically you would get this from a network request
15    /// let bytes = /* Pretend we have valid bytes here */
16    ///
17    /// let Ok(dictionary) = Decoder::decode_dictionary(&bytes) else {
18    ///     panic!("Invalid bytes");
19    /// }
20    ///
21    /// // Assuming the dictionary has a key value pair that has a key of "position"
22    /// let key = Box::new(GodotString::new("position")) as Box<dyn GodotVariant>;
23    ///
24    /// // We can get the value now with this key
25    /// let value = dictionary.map.get(&key);
26    ///
27    /// ```
28    pub fn decode_dictionary(bytes: &[u8]) -> anyhow::Result<GodotDictionary> {
29        let mut dict = GodotDictionary {
30            map: IndexMap::new(),
31            byte_size: 0,
32        };
33
34        let dict_length = LittleEndian::read_u32(&bytes[4..8]);
35
36        let mut byte_pos = 8;
37        for _ in 0..dict_length {
38            let key = Self::decode_variant(&bytes[byte_pos..])?;
39            byte_pos += key.byte_length();
40
41            if key.as_any().is::<GodotNull>() {
42                continue;
43            }
44
45            let value = Self::decode_variant(&bytes[byte_pos..])?;
46            byte_pos += value.byte_length();
47
48            dict.map.insert(key, value);
49        }
50
51        dict.byte_size = byte_pos;
52
53        Ok(dict)
54    }
55}
56
57#[cfg(test)]
58mod tests {
59    use crate::{
60        decoder::Decoder,
61        types::{primitive::GodotString, structures::GodotVector2, variant::GodotVariant},
62    };
63
64    #[test]
65    fn decode_dictionary() {
66        let bytes = [
67            18, 0, 0, 0, 3, 0, 0, 0, 4, 0, 0, 0, 3, 0, 0, 0, 104, 101, 121, 0, 4, 0, 0, 0, 4, 0, 0,
68            0, 105, 32, 97, 109, 4, 0, 0, 0, 3, 0, 0, 0, 97, 103, 101, 0, 2, 0, 0, 0, 58, 0, 0, 0,
69            4, 0, 0, 0, 8, 0, 0, 0, 112, 111, 115, 105, 116, 105, 111, 110, 5, 0, 0, 0, 0, 96, 21,
70            70, 0, 184, 150, 69,
71        ];
72
73        let dict = Decoder::decode_dictionary(&bytes).unwrap();
74        let value = dict.get::<GodotVector2>(GodotString::new("position"));
75
76        println!("{:?}", value);
77        println!("{:?}", dict);
78    }
79
80    #[test]
81    fn decode_double_dictionary() {
82        let bytes = [
83            18, 0, 0, 0, 4, 0, 0, 0, 4, 0, 0, 0, 3, 0, 0, 0, 104, 101, 121, 0, 4, 0, 0, 0, 4, 0, 0,
84            0, 105, 32, 97, 109, 4, 0, 0, 0, 3, 0, 0, 0, 97, 103, 101, 0, 2, 0, 0, 0, 58, 0, 0, 0,
85            4, 0, 0, 0, 8, 0, 0, 0, 112, 111, 115, 105, 116, 105, 111, 110, 5, 0, 0, 0, 0, 96, 21,
86            70, 0, 184, 150, 69, 4, 0, 0, 0, 4, 0, 0, 0, 100, 97, 116, 97, 18, 0, 0, 0, 3, 0, 0, 0,
87            4, 0, 0, 0, 6, 0, 0, 0, 98, 97, 110, 97, 110, 97, 0, 0, 2, 0, 0, 0, 23, 0, 0, 0, 4, 0,
88            0, 0, 5, 0, 0, 0, 115, 119, 111, 114, 100, 0, 0, 0, 2, 0, 0, 0, 42, 0, 0, 0, 4, 0, 0,
89            0, 4, 0, 0, 0, 102, 105, 115, 104, 4, 0, 0, 0, 12, 0, 0, 0, 102, 105, 115, 104, 58, 58,
90            98, 97, 110, 97, 110, 97,
91        ];
92
93        let dict = Decoder::decode_dictionary(&bytes).unwrap();
94        let key = Box::new(GodotString::new("position")) as Box<dyn GodotVariant>;
95
96        let value = dict.map.get(&key);
97
98        println!("{:?}", value);
99        println!("{:?}", dict);
100    }
101}