godot_binary_serialization/decoder/
mod.rs

1pub mod dictionary;
2pub mod float;
3pub mod int;
4pub mod string;
5pub mod vector;
6pub mod bool;
7
8use anyhow::anyhow;
9use byteorder::{ByteOrder, LittleEndian};
10
11use crate::types::{primitive::GodotNull, variant::GodotVariant, SerializeFlag, GodotTypeIndex};
12
13pub struct Decoder;
14
15impl Decoder {
16    /// Gets the type and flags of the bytes passed. The type determines which type we should try
17    /// and decode it as, and the flag shows how we will decode the type
18    pub fn get_type_and_flags(bytes: &[u8]) -> anyhow::Result<(GodotTypeIndex, SerializeFlag)> {
19        let Ok(type_idx) = GodotTypeIndex::try_from(LittleEndian::read_u16(&bytes[0..2])) else {
20            return Err(anyhow!("Unsupported type index"));
21        };
22        let flag =
23            SerializeFlag::try_from(LittleEndian::read_u16(&bytes[2..4])).unwrap_or(SerializeFlag::None);
24
25        Ok((type_idx, flag))
26    }
27
28    /// Decodes bytes into it's respective Godot variant. This can fail if the bytes does not match
29    /// Godot's serialization rules or it's an unsupported type.
30    pub fn decode_variant(bytes: &[u8]) -> anyhow::Result<Box<dyn GodotVariant + 'static>> {
31        if bytes.is_empty() {
32            return Err(anyhow!("Empty bytes"));
33        }
34
35        let (type_idx, flag) = Self::get_type_and_flags(bytes)?;
36
37        let variant: Box<dyn GodotVariant> = match type_idx {
38            GodotTypeIndex::Nil => Box::new(GodotNull),
39            GodotTypeIndex::Bool => Box::new(Self::decode_bool(bytes, &flag)?),
40            GodotTypeIndex::Integer => Box::new(Self::decode_int(bytes, &flag)?),
41            GodotTypeIndex::Float => Box::new(Self::decode_float(bytes, &flag)?),
42            GodotTypeIndex::String => Box::new(Self::decode_string(bytes)?),
43            GodotTypeIndex::Vector2 => Box::new(Self::decode_vector2(bytes)?),
44            GodotTypeIndex::Vector3 => Box::new(Self::decode_vector3(bytes)?),
45            GodotTypeIndex::Dictionary => Box::new(Self::decode_dictionary(bytes)?),
46            _ => return Err(anyhow!("Unsupported godot variant of type {:?}", type_idx)),
47        };
48
49        Ok(variant)
50    }
51}