Skip to main content

feagi_serialization/
feagi_serializable.rs

1use crate::{FeagiByteContainer, FeagiByteStructureType};
2use feagi_structures::neuron_voxels::xyzp::CorticalMappedXYZPNeuronVoxels;
3use feagi_structures::{FeagiDataError, FeagiJSON};
4use std::any::Any;
5use std::fmt::Debug;
6
7/// Trait for structures that can be serialized to and from FEAGI byte format.
8///
9/// Implementations must provide methods for determining their type, version,
10/// size requirements, and serialization/deserialization logic. The trait includes
11/// default validation methods for type and version checking.
12pub trait FeagiSerializable: Debug + Any {
13    /// Returns the structure type identifier.
14    fn get_type(&self) -> FeagiByteStructureType;
15
16    /// Returns the version number of this structure format.
17    fn get_version(&self) -> u8;
18
19    /// Returns the total number of bytes needed for serialization.
20    fn get_number_of_bytes_needed(&self) -> usize;
21
22    /// Serializes this structure into the provided byte slice.
23    ///
24    /// The slice must be exactly the size returned by `get_number_of_bytes_needed`.
25    fn try_serialize_struct_to_byte_slice(
26        &self,
27        byte_destination: &mut [u8],
28    ) -> Result<(), FeagiDataError>;
29
30    /// Deserializes data from a byte slice and updates this structure.
31    fn try_deserialize_and_update_self_from_byte_slice(
32        &mut self,
33        byte_reading: &[u8],
34    ) -> Result<(), FeagiDataError>;
35
36    /// Provide access to `Any` trait for downcasting
37    fn as_any(&self) -> &dyn Any;
38
39    /// Verifies that a byte slice contains data of the correct type.
40    fn verify_byte_slice_is_of_correct_type(
41        &self,
42        byte_source: &[u8],
43    ) -> Result<(), FeagiDataError> {
44        if byte_source.len() <= FeagiByteContainer::STRUCT_HEADER_BYTE_COUNT {
45            return Err(FeagiDataError::DeserializationError(
46                format!("Byte slice needs to be at least {} bytes long to be considered valid! Given slice is {} elements long!", FeagiByteContainer::STRUCT_HEADER_BYTE_COUNT, byte_source.len())
47            ));
48        }
49        if byte_source[0] != self.get_type() as u8 {
50            return Err(FeagiDataError::DeserializationError(format!("Attempted to process byte slice as structure type {} when given slice seems to be type {}!", self.get_type(), byte_source[0])));
51        }
52        Ok(())
53    }
54
55    /// Verifies that a byte slice contains data of the correct version.
56    fn verify_byte_slice_is_of_correct_version(
57        &self,
58        byte_source: &[u8],
59    ) -> Result<(), FeagiDataError> {
60        if byte_source.len() < FeagiByteContainer::STRUCT_HEADER_BYTE_COUNT {
61            return Err(FeagiDataError::DeserializationError(
62                format!("Byte slice needs to be at least {} bytes long to be considered valid! Given slice is {} elements long!", FeagiByteContainer::STRUCT_HEADER_BYTE_COUNT, byte_source.len())
63            ));
64        }
65        if byte_source[1] != self.get_version() {
66            return Err(FeagiDataError::DeserializationError(format!("Current implementation of Feagi Data Serialization supports structure ID {} of version {}, however version {} was given!!", self.get_type(), self.get_version(), byte_source[1])));
67        }
68        Ok(())
69    }
70
71    // TODO universal method to export as a new FBS
72}
73
74// TODO there is cloning here, can it be avoided?
75
76impl TryFrom<Box<dyn FeagiSerializable>> for FeagiJSON {
77    type Error = FeagiDataError;
78    fn try_from(value: Box<dyn FeagiSerializable>) -> Result<Self, Self::Error> {
79        let option = value.as_any().downcast_ref::<FeagiJSON>();
80        match option {
81            Some(value) => Ok(value.clone()),
82            None => Err(FeagiDataError::DeserializationError(
83                "This struct is not a FeagiJSON struct and cannot be deserialized as such!".into(),
84            )),
85        }
86    }
87}
88
89impl TryFrom<Box<dyn FeagiSerializable>> for CorticalMappedXYZPNeuronVoxels {
90    type Error = FeagiDataError;
91    fn try_from(value: Box<dyn FeagiSerializable>) -> Result<Self, Self::Error> {
92        let option = value
93            .as_any()
94            .downcast_ref::<CorticalMappedXYZPNeuronVoxels>();
95        match option {
96            Some(value) => Ok(value.clone()),
97            None => Err(FeagiDataError::DeserializationError("This struct is not a CorticalMappedXYZPNeuronVoxels struct and cannot be deserialized as such!".into()))
98        }
99    }
100}