feagi_data_serialization/
feagi_byte_container.rs1use byteorder::{ByteOrder, LittleEndian};
2use feagi_data_structures::FeagiDataError;
3use crate::feagi_serializable::FeagiSerializable;
4use crate::FeagiByteStructureType;
5
6const MAX_NUMBER_OF_STRUCTS: usize = u8::MAX as usize;
7
8type StructureIndex = u8;
9type ByteIndexReadingStart = u32;
10type NumberBytesToRead = u32;
11
12#[derive(Debug, Clone)]
34pub struct FeagiByteContainer {
35 bytes: Vec<u8>,
37 is_data_valid: bool,
39 contained_struct_references: Vec<ContainedStructReference>,
41}
42
43impl FeagiByteContainer{
44 pub const CURRENT_FBS_VERSION: u8 = 2;
45
46 pub const GLOBAL_BYTE_HEADER_BYTE_COUNT: usize = 4; pub const STRUCTURE_LOOKUP_HEADER_BYTE_COUNT_PER_STRUCTURE: usize = 4; pub const STRUCT_HEADER_BYTE_COUNT: usize = 2; pub fn new_empty() -> Self {
69 Self { bytes: vec![Self::CURRENT_FBS_VERSION, 0, 0, 0], is_data_valid: true, contained_struct_references: Vec::new() }
70 }
71
72 pub fn get_byte_ref(&self) -> &[u8] {
91 &self.bytes
92 }
93
94 pub fn try_write_data_to_container_and_verify<F>(&mut self, byte_writer: &mut F) -> Result<(), FeagiDataError>
113 where F: FnMut(&mut Vec<u8>) -> Result<(), FeagiDataError> {
114 byte_writer(&mut self.bytes)?;
115 self.verify_container_valid_and_populate()
116 }
117
118 pub fn is_valid(&self) -> bool {
135 self.is_data_valid
136 }
137
138 pub fn try_get_number_contained_structures(&self) -> Result<usize, FeagiDataError> {
151 if self.is_data_valid {
152 return Ok(self.contained_struct_references.len())
153 }
154 Err(FeagiDataError::DeserializationError("Given Byte Container is invalid and thus cannot be read!".into()))
155 }
156
157 pub fn get_number_of_bytes_used(&self) -> usize {
169 self.bytes.len()
170 }
171
172 pub fn get_number_of_bytes_allocated(&self) -> usize {
184 self.bytes.capacity()
185 }
186
187 pub fn get_increment_counter(&self) -> Result<u16, FeagiDataError> {
200 if self.is_data_valid {
201 return Ok(LittleEndian::read_u16(&self.bytes[1..3]))
202 }
203 Err(FeagiDataError::DeserializationError("Given Byte Container is invalid and thus cannot be read!".into()))
204 }
205
206 pub fn try_create_new_struct_from_index(&self, index: StructureIndex) -> Result<Box<dyn FeagiSerializable>, FeagiDataError> {
224 self.verify_structure_index_valid(index)?;
225 let relevant_slice = self.contained_struct_references[index as usize].get_as_byte_slice(&self.bytes);
226 let mut boxed_struct: Box<dyn FeagiSerializable> = self.contained_struct_references[index as usize].structure_type.create_new_struct_of_type();
227 boxed_struct.try_deserialize_and_update_self_from_byte_slice(relevant_slice)?;
228 Ok(boxed_struct)
229 }
230
231 pub fn try_create_struct_from_first_found_struct_of_type(&self, structure_type: FeagiByteStructureType) -> Result<Option<Box<dyn FeagiSerializable>>, FeagiDataError> {
236 let getting_slice = self.try_get_first_structure_slice_of_type(structure_type);
237 if getting_slice.is_none() {
238 return Ok(None);
239 }
240 let mut boxed_struct: Box<dyn FeagiSerializable> = structure_type.create_new_struct_of_type();
241 boxed_struct.try_deserialize_and_update_self_from_byte_slice(getting_slice.unwrap())?;
242 Ok(Some(boxed_struct))
243 }
244
245 pub fn try_update_struct_from_index(&self, index: StructureIndex, updating_boxed_struct: &mut dyn FeagiSerializable) -> Result<(), FeagiDataError> {
249 self.verify_structure_index_valid(index)?;
250 let relevant_slice = self.contained_struct_references[index as usize].get_as_byte_slice(&self.bytes);
251 updating_boxed_struct.verify_byte_slice_is_of_correct_type(relevant_slice)?;
252 updating_boxed_struct.try_deserialize_and_update_self_from_byte_slice(relevant_slice)?;
253 Ok(())
254 }
255
256 pub fn try_update_struct_from_first_found_struct_of_type(&self, updating_boxed_struct: &mut dyn FeagiSerializable) -> Result<bool, FeagiDataError> {
260 let structure_type: FeagiByteStructureType = updating_boxed_struct.get_type();
261 let getting_slice = self.try_get_first_structure_slice_of_type(structure_type);
262 if getting_slice.is_none() {
263 return Ok(false);
264 }
265 updating_boxed_struct.try_deserialize_and_update_self_from_byte_slice(getting_slice.unwrap())?;
266 Ok(true)
267 }
268
269 pub fn get_contained_struct_types(&self) -> Vec<FeagiByteStructureType> {
283 let mut output: Vec<FeagiByteStructureType> = Vec::with_capacity(self.contained_struct_references.len());
284 for contained_struct_reference in &self.contained_struct_references {
285 output.push(contained_struct_reference.structure_type);
286 };
287 output
288 }
289
290 pub fn overwrite_byte_data_with_multiple_struct_data(&mut self, incoming_structs: Vec<&dyn FeagiSerializable>, new_increment_value: u16) -> Result<(), FeagiDataError> {
299
300 if incoming_structs.len() > MAX_NUMBER_OF_STRUCTS {
301 return Err(FeagiDataError::BadParameters(format!("FeagiByteContainers only support a max of {} contained structs, {} were given!", MAX_NUMBER_OF_STRUCTS, incoming_structs.len())))
302 }
303
304 self.bytes.clear();
305 self.contained_struct_references.clear();
306 self.is_data_valid = false;
307
308 let header_total_number_of_bytes: usize = Self::GLOBAL_BYTE_HEADER_BYTE_COUNT +
309 Self::STRUCTURE_LOOKUP_HEADER_BYTE_COUNT_PER_STRUCTURE * incoming_structs.len();
310
311
312 let total_number_of_bytes = {
314 let mut data_start_index = header_total_number_of_bytes;
315 for incoming_struct in &incoming_structs {
316 let per_struct_number_bytes = incoming_struct.get_number_of_bytes_needed();
317 self.contained_struct_references.push(
318 ContainedStructReference{
319 structure_type: incoming_struct.get_type(),
320 byte_start_index: data_start_index as u32,
321 number_bytes_to_read: per_struct_number_bytes as u32,
322 }
323 );
324 data_start_index += per_struct_number_bytes;
325 }
326 data_start_index
327 };
328
329 if total_number_of_bytes > self.bytes.capacity() {
330 self.bytes.resize(total_number_of_bytes, 0);
331 }
332
333 self.bytes[0] = Self::CURRENT_FBS_VERSION;
335 LittleEndian::write_u16(&mut self.bytes[1..3], new_increment_value); self.bytes[3] = incoming_structs.len() as u8; let mut structure_lookup_header_byte_index = Self::GLOBAL_BYTE_HEADER_BYTE_COUNT;
340 for struct_index in 0..incoming_structs.len() {
341 let incoming_struct = &incoming_structs[struct_index];
342 let contained_struct_reference = &self.contained_struct_references[struct_index];
343
344 LittleEndian::write_u32(&mut self.bytes[structure_lookup_header_byte_index..structure_lookup_header_byte_index + 4], contained_struct_reference.number_bytes_to_read as u32);
345 incoming_struct.try_serialize_struct_to_byte_slice(contained_struct_reference.get_as_byte_slice_mut(&mut self.bytes))?;
346
347 structure_lookup_header_byte_index += Self::STRUCTURE_LOOKUP_HEADER_BYTE_COUNT_PER_STRUCTURE;
348 };
349
350 self.is_data_valid = true;
351 Ok(())
352
353 }
354
355 pub fn overwrite_byte_data_with_single_struct_data(&mut self, incoming_struct: &dyn FeagiSerializable, new_increment_value: u16) -> Result<(), FeagiDataError> {
360
361 self.bytes.clear();
362 self.contained_struct_references.clear();
363 self.is_data_valid = false;
364
365 let number_of_bytes_used_by_struct = incoming_struct.get_number_of_bytes_needed();
366 let total_number_of_bytes = Self::GLOBAL_BYTE_HEADER_BYTE_COUNT + (1 * Self::STRUCTURE_LOOKUP_HEADER_BYTE_COUNT_PER_STRUCTURE) + number_of_bytes_used_by_struct;
367
368 self.contained_struct_references.push(
369 ContainedStructReference {
370 structure_type: incoming_struct.get_type(),
371 byte_start_index: (Self::GLOBAL_BYTE_HEADER_BYTE_COUNT + Self::STRUCTURE_LOOKUP_HEADER_BYTE_COUNT_PER_STRUCTURE) as u32, number_bytes_to_read: number_of_bytes_used_by_struct as u32
373 }
374 );
375
376
377 if total_number_of_bytes > self.bytes.capacity() {
378 self.bytes.resize(total_number_of_bytes, 0);
379 }
380
381 self.bytes[0] = Self::CURRENT_FBS_VERSION;
383 LittleEndian::write_u16(&mut self.bytes[1..3], new_increment_value); self.bytes[3] = 1u8; let data_read_index: u32 = (Self::GLOBAL_BYTE_HEADER_BYTE_COUNT + Self::STRUCTURE_LOOKUP_HEADER_BYTE_COUNT_PER_STRUCTURE) as u32;
388 LittleEndian::write_u32(&mut self.bytes[Self::GLOBAL_BYTE_HEADER_BYTE_COUNT..Self::GLOBAL_BYTE_HEADER_BYTE_COUNT + 4], data_read_index);
389
390 let data_byte_slice = &mut self.bytes[data_read_index as usize..]; incoming_struct.try_serialize_struct_to_byte_slice(data_byte_slice)?;
393
394 self.is_data_valid = true;
395 Ok(())
396
397 }
398
399 pub fn set_increment_counter_state(&mut self, new_increment_value: u16) -> Result<(), FeagiDataError> {
412 if !self.is_data_valid {
413 return Err(FeagiDataError::DeserializationError("Given Byte Container is invalid and thus cannot have its increment counter changed!".into()))
414 };
415 LittleEndian::write_u16(&mut self.bytes[1..3], new_increment_value);
416 Ok(())
417 }
418
419 pub fn free_unused_allocation(&mut self) {
433 self.bytes.shrink_to_fit()
434 }
435
436 fn verify_container_valid_and_populate(&mut self) -> Result<(), FeagiDataError> {
444 self.is_data_valid = false;
445 self.contained_struct_references.clear();
446 let byte_length = self.bytes.len();
447
448 if byte_length < Self::GLOBAL_BYTE_HEADER_BYTE_COUNT { return Err(FeagiDataError::DeserializationError("Given Feagi Byte Structure byte length is too short! (Less than 4!)".into()));
451 }
452 if self.bytes[0] != Self::CURRENT_FBS_VERSION {
453 return Err(FeagiDataError::DeserializationError(format!("Given FEAGI Byte Structure is using version {} when this application only supports version {}!", self.bytes[0], Self::CURRENT_FBS_VERSION)));
454 }
455 let number_contained_structs = self.bytes[3] as usize;
456 if number_contained_structs == 0 {
457 self.is_data_valid = true; return Ok(())
459 }
461
462 let minimum_count_header_size = Self::STRUCTURE_LOOKUP_HEADER_BYTE_COUNT_PER_STRUCTURE * number_contained_structs;
463 let total_header_size = Self::GLOBAL_BYTE_HEADER_BYTE_COUNT + minimum_count_header_size;
464 if byte_length < total_header_size {
465 return Err(FeagiDataError::DeserializationError(format!("Feagi Byte Data specifies the existence of {} structures, but the given byte array is under the required {} byte length!", minimum_count_header_size, Self::GLOBAL_BYTE_HEADER_BYTE_COUNT + minimum_count_header_size)));
466 }
467
468 let mut structure_header_byte_index: usize = Self::GLOBAL_BYTE_HEADER_BYTE_COUNT;
469 let mut structure_data_byte_index: usize = total_header_size;
470 for contained_structure_index in 0..number_contained_structs {
471 let structure_length = LittleEndian::read_u32(&self.bytes[structure_header_byte_index..structure_header_byte_index + 4]);
472
473 if structure_data_byte_index + structure_length as usize > byte_length {
474 return Err(FeagiDataError::DeserializationError(
475 format!("Structure of index {} goes out of bound reaching position {} when given byte length is only {} long!", contained_structure_index, structure_data_byte_index + structure_length as usize, byte_length)));
476 }
477
478 let structure_type = FeagiByteStructureType::try_from(self.bytes[structure_data_byte_index])?;
479 self.contained_struct_references.push( ContainedStructReference {
480 structure_type,
481 byte_start_index: structure_data_byte_index as u32,
482 number_bytes_to_read: structure_length
483 });
484
485 structure_header_byte_index += 4; structure_data_byte_index += structure_length as usize;
487 }
488 Ok(())
489 }
490
491 fn verify_structure_index_valid(&self, structure_index: StructureIndex) -> Result<(), FeagiDataError> {
493 if structure_index as usize >= self.contained_struct_references.len() {
494 return Err(FeagiDataError::BadParameters(format!("Structure index {} out of bounds! Feagi Byte Container only contains {} structures!", structure_index, self.contained_struct_references.len())));
495 }
496 Ok(())
497 }
498
499 fn try_get_first_structure_slice_of_type(&self, structure_type: FeagiByteStructureType) -> Option<&[u8]> {
501 for index in 0..self.contained_struct_references.len() {
502 if self.contained_struct_references[index].structure_type == structure_type {
503 return Some(self.contained_struct_references[index].get_as_byte_slice(&self.bytes));
504 }
505 };
506 None
507 }
508
509 }
512
513#[derive(Debug, Clone, Hash, PartialEq, Eq)]
519struct ContainedStructReference {
520 structure_type: FeagiByteStructureType,
522 byte_start_index: ByteIndexReadingStart,
524 number_bytes_to_read: NumberBytesToRead
526}
527
528impl ContainedStructReference {
529 pub fn get_as_byte_slice<'a>(&self, byte_source: &'a Vec<u8>) -> &'a [u8] {
531 &byte_source[self.byte_start_index as usize ..self.byte_start_index as usize + self.number_bytes_to_read as usize]
532 }
533
534 pub fn get_as_byte_slice_mut<'a>(&self, byte_source: &'a mut Vec<u8>) -> &'a mut [u8] {
536 &mut byte_source[self.byte_start_index as usize ..self.byte_start_index as usize + self.number_bytes_to_read as usize]
537 }
538}
539
540