godot_binary_serialization/decoder/
dictionary.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
use byteorder::{ByteOrder, LittleEndian};
use indexmap::IndexMap;

use crate::types::{primitive::GodotNull, structures::GodotDictionary};

use super::Decoder;

impl Decoder {
    /// Decodes bytes into a godot dictionary.
    ///
    /// # Example
    ///
    /// ```rust,ignore
    /// // Typically you would get this from a network request
    /// let bytes = /* Pretend we have valid bytes here */
    ///
    /// let Ok(dictionary) = Decoder::decode_dictionary(&bytes) else {
    ///     panic!("Invalid bytes");
    /// }
    ///
    /// // Assuming the dictionary has a key value pair that has a key of "position"
    /// let key = Box::new(GodotString::new("position")) as Box<dyn GodotVariant>;
    ///
    /// // We can get the value now with this key
    /// let value = dictionary.map.get(&key);
    ///
    /// ```
    pub fn decode_dictionary(bytes: &[u8]) -> anyhow::Result<GodotDictionary> {
        let mut dict = GodotDictionary {
            map: IndexMap::new(),
            byte_size: 0,
        };

        let dict_length = LittleEndian::read_u32(&bytes[4..8]);

        let mut byte_pos = 8;
        for _ in 0..dict_length {
            let key = Self::decode_variant(&bytes[byte_pos..])?;
            byte_pos += key.byte_length();

            if key.as_any().is::<GodotNull>() {
                continue;
            }

            let value = Self::decode_variant(&bytes[byte_pos..])?;
            byte_pos += value.byte_length();

            dict.map.insert(key, value);
        }

        dict.byte_size = byte_pos;

        Ok(dict)
    }
}

#[cfg(test)]
mod tests {
    use crate::{
        decoder::Decoder,
        types::{primitive::GodotString, structures::GodotVector2, variant::GodotVariant},
    };

    #[test]
    fn decode_dictionary() {
        let bytes = [
            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,
            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,
            4, 0, 0, 0, 8, 0, 0, 0, 112, 111, 115, 105, 116, 105, 111, 110, 5, 0, 0, 0, 0, 96, 21,
            70, 0, 184, 150, 69,
        ];

        let dict = Decoder::decode_dictionary(&bytes).unwrap();
        let value = dict.get::<GodotVector2>(GodotString::new("position"));

        println!("{:?}", value);
        println!("{:?}", dict);
    }

    #[test]
    fn decode_double_dictionary() {
        let bytes = [
            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,
            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,
            4, 0, 0, 0, 8, 0, 0, 0, 112, 111, 115, 105, 116, 105, 111, 110, 5, 0, 0, 0, 0, 96, 21,
            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,
            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,
            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,
            0, 4, 0, 0, 0, 102, 105, 115, 104, 4, 0, 0, 0, 12, 0, 0, 0, 102, 105, 115, 104, 58, 58,
            98, 97, 110, 97, 110, 97,
        ];

        let dict = Decoder::decode_dictionary(&bytes).unwrap();
        let key = Box::new(GodotString::new("position")) as Box<dyn GodotVariant>;

        let value = dict.map.get(&key);

        println!("{:?}", value);
        println!("{:?}", dict);
    }
}