feagi_data_serialization/implementations/
feagi_json.rs

1use feagi_data_structures::data::FeagiJSON;
2use feagi_data_structures::FeagiDataError;
3use crate::byte_structure::{FeagiByteStructureCompatible, FeagiByteStructure, FeagiByteStructureType};
4
5const BYTE_STRUCT_VERSION: u8 = 1;
6
7impl FeagiByteStructureCompatible for FeagiJSON {
8    fn get_type(&self) -> FeagiByteStructureType { FeagiByteStructureType::JSON }
9
10    fn get_version(&self) -> u8 {BYTE_STRUCT_VERSION}
11
12    fn overwrite_feagi_byte_structure_slice(&self, slice: &mut [u8]) -> Result<usize, FeagiDataError> {
13
14        // doing this here instead of using the max_number_bytes_needed func so we can double-dip on data usage
15        let json_string = self.borrow_json_value().to_string();
16        let json_bytes = json_string.as_bytes();
17
18        let num_bytes_needed: usize = FeagiByteStructure::GLOBAL_BYTE_HEADER_BYTE_SIZE_IN_BYTES + json_bytes.len();
19        if slice.len() < num_bytes_needed {
20            return Err(FeagiDataError::SerializationError(format!("Not enough space given to store JSON data! Need {} bytes but given {}!", num_bytes_needed, slice.len())));
21        }
22
23        // Write the global header
24        slice[0] = self.get_type() as u8;
25        slice[1] = self.get_version();
26
27        // Write the JSON data as UTF-8 bytes
28        slice[FeagiByteStructure::GLOBAL_BYTE_HEADER_BYTE_SIZE_IN_BYTES..FeagiByteStructure::GLOBAL_BYTE_HEADER_BYTE_SIZE_IN_BYTES + json_bytes.len()].copy_from_slice(json_bytes);
29
30        let wasted_space = slice.len() - num_bytes_needed;
31        Ok(wasted_space)
32    }
33
34    fn max_number_bytes_needed(&self) -> usize {
35        // Global header (2 bytes) + JSON data as UTF-8 bytes
36        // TODO this is pretty slow, any faster way to do this?
37        FeagiByteStructure::GLOBAL_BYTE_HEADER_BYTE_SIZE_IN_BYTES + self.borrow_json_value().to_string().as_bytes().len()
38    }
39
40    fn new_from_feagi_byte_structure(feagi_byte_structure: &FeagiByteStructure) -> Result<Self, FeagiDataError>
41    where
42        Self: Sized
43    {
44        FeagiByteStructure::verify_matching_structure_type_and_version(
45            feagi_byte_structure,
46            FeagiByteStructureType::JSON,
47            BYTE_STRUCT_VERSION
48        )?;
49
50        let bytes = feagi_byte_structure.borrow_data_as_slice();
51
52        if bytes.len() < FeagiByteStructure::GLOBAL_BYTE_HEADER_BYTE_SIZE_IN_BYTES {
53            return Err(FeagiDataError::DeserializationError("JSON bytes structure too short to contain global header".into()));
54        }
55
56        // Extract JSON data (everything after the global header)
57        let json_bytes = &bytes[FeagiByteStructure::GLOBAL_BYTE_HEADER_BYTE_SIZE_IN_BYTES..];
58
59        // Parse JSON string
60        let json_value = match serde_json::from_slice(json_bytes) {
61            Ok(value) => value,
62            Err(e) => return Err(FeagiDataError::DeserializationError(format!("Invalid JSON data: {}", e))),
63        };
64
65        Ok(FeagiJSON::from_json_value(json_value))
66    }
67}