feagi_serialization/implementations/
cortical_mapped_xyzp_neuron_data.rs1use crate::{FeagiByteContainer, FeagiByteStructureType, FeagiSerializable};
4use byteorder::{ByteOrder, LittleEndian};
5use feagi_structures::genomic::cortical_area::CorticalID;
6use feagi_structures::neuron_voxels::xyzp::{
7 CorticalMappedXYZPNeuronVoxels, NeuronVoxelXYZP, NeuronVoxelXYZPArrays,
8};
9use feagi_structures::FeagiDataError;
10use std::any::Any;
11
12const BYTE_STRUCT_VERSION: u8 = 1;
14
15const NUMBER_BYTES_PER_CORTICAL_ID_HEADER: usize =
17 CorticalID::NUMBER_OF_BYTES + size_of::<u32>() + size_of::<u32>();
18
19const NUMBER_BYTES_CORTICAL_COUNT_HEADER: usize = size_of::<u16>();
21
22impl FeagiSerializable for CorticalMappedXYZPNeuronVoxels {
23 fn get_type(&self) -> FeagiByteStructureType {
24 FeagiByteStructureType::NeuronCategoricalXYZP
25 }
26
27 fn get_version(&self) -> u8 {
28 BYTE_STRUCT_VERSION
29 }
30
31 fn get_number_of_bytes_needed(&self) -> usize {
32 let mut number_bytes_needed: usize =
33 FeagiByteContainer::STRUCT_HEADER_BYTE_COUNT + NUMBER_BYTES_CORTICAL_COUNT_HEADER;
34 for neuron_data in self.iter() {
35 number_bytes_needed +=
36 neuron_data.get_size_in_number_of_bytes() + NUMBER_BYTES_PER_CORTICAL_ID_HEADER;
37 }
38 number_bytes_needed
39 }
40
41 fn try_serialize_struct_to_byte_slice(
42 &self,
43 byte_destination: &mut [u8],
44 ) -> Result<(), FeagiDataError> {
45 byte_destination[0] = self.get_type() as u8;
47 byte_destination[1] = self.get_version();
48
49 let number_cortical_areas: usize = self.mappings.len();
51 const NUMBER_BYTES_INITIAL_SECTION_HEADER: usize = size_of::<u16>();
52 LittleEndian::write_u16(
53 &mut byte_destination[FeagiByteContainer::STRUCT_HEADER_BYTE_COUNT
54 ..FeagiByteContainer::STRUCT_HEADER_BYTE_COUNT
55 + NUMBER_BYTES_INITIAL_SECTION_HEADER],
56 number_cortical_areas as u16,
57 );
58
59 let mut subheader_write_index: usize =
61 FeagiByteContainer::STRUCT_HEADER_BYTE_COUNT + NUMBER_BYTES_INITIAL_SECTION_HEADER;
62 let mut neuron_data_write_index: usize =
63 subheader_write_index + (number_cortical_areas * NUMBER_BYTES_PER_CORTICAL_ID_HEADER);
64
65 for (cortical_id, neuron_data) in &self.mappings {
66 let cortical_area_lookup_header_slice = &mut byte_destination
68 [subheader_write_index..subheader_write_index + CorticalID::NUMBER_OF_BYTES];
69 let cortical_area_lookup_header_slice: &mut [u8; CorticalID::NUMBER_OF_BYTES] =
70 cortical_area_lookup_header_slice.try_into().unwrap();
71 cortical_id.write_id_to_bytes(cortical_area_lookup_header_slice);
72
73 let reading_length: u32 = neuron_data.get_size_in_number_of_bytes() as u32;
74 LittleEndian::write_u32(
75 &mut byte_destination[subheader_write_index + CorticalID::NUMBER_OF_BYTES
76 ..subheader_write_index + CorticalID::NUMBER_OF_BYTES + size_of::<u32>()],
77 neuron_data_write_index as u32,
78 );
79 LittleEndian::write_u32(
80 &mut byte_destination[subheader_write_index
81 + CorticalID::NUMBER_OF_BYTES
82 + size_of::<u32>()
83 ..subheader_write_index
84 + CorticalID::NUMBER_OF_BYTES
85 + size_of::<u32>()
86 + size_of::<u32>()],
87 reading_length,
88 );
89
90 write_neuron_array_to_bytes(
92 neuron_data,
93 &mut byte_destination
94 [neuron_data_write_index..(neuron_data_write_index + reading_length as usize)],
95 )?;
96
97 subheader_write_index += NUMBER_BYTES_PER_CORTICAL_ID_HEADER;
99 neuron_data_write_index += reading_length as usize;
100 }
101
102 Ok(())
103 }
104
105 fn try_deserialize_and_update_self_from_byte_slice(
106 &mut self,
107 byte_reading: &[u8],
108 ) -> Result<(), FeagiDataError> {
109 self.verify_byte_slice_is_of_correct_version(byte_reading)?;
111 self.clear_neurons_only(); let number_cortical_areas: usize = LittleEndian::read_u16(&byte_reading[2..4]) as usize;
114 let mut reading_header_byte_index: usize =
115 FeagiByteContainer::STRUCT_HEADER_BYTE_COUNT + NUMBER_BYTES_CORTICAL_COUNT_HEADER;
116
117 for _cortical_index in 0..number_cortical_areas {
118 let cortical_id = CorticalID::try_from_bytes(
119 <&[u8; CorticalID::NUMBER_OF_BYTES]>::try_from(
120 &byte_reading[reading_header_byte_index
121 ..reading_header_byte_index + CorticalID::NUMBER_OF_BYTES],
122 )
123 .unwrap(),
124 )?;
125
126 const CORTICAL_ID_AND_U32_OFFSET: usize =
127 size_of::<u32>() + CorticalID::NUMBER_OF_BYTES;
128 const CORTICAL_ID_AND_U32_AND_U32_OFFSET: usize =
129 size_of::<u32>() + size_of::<u32>() + CorticalID::NUMBER_OF_BYTES;
130
131 let data_start_reading: usize = LittleEndian::read_u32(
132 &byte_reading[reading_header_byte_index + CorticalID::NUMBER_OF_BYTES
133 ..reading_header_byte_index + CORTICAL_ID_AND_U32_OFFSET],
134 ) as usize;
135 let number_bytes_to_read: usize = LittleEndian::read_u32(
136 &byte_reading[reading_header_byte_index + CORTICAL_ID_AND_U32_OFFSET
137 ..reading_header_byte_index + CORTICAL_ID_AND_U32_AND_U32_OFFSET],
138 ) as usize;
139
140 if byte_reading.len() < data_start_reading + number_bytes_to_read {
141 return Err(FeagiDataError::SerializationError("Byte structure for NeuronCategoricalXYZP is too short to fit the data the header says it contains!".into()));
142 }
143
144 let neuron_bytes =
145 &byte_reading[data_start_reading..data_start_reading + number_bytes_to_read];
146 let bytes_length = neuron_bytes.len();
147
148 #[allow(clippy::manual_is_multiple_of)] if bytes_length % NeuronVoxelXYZP::NUMBER_BYTES_PER_NEURON != 0 {
150 return Err(FeagiDataError::SerializationError("As NeuronXYCPArrays contains 4 internal arrays of equal length, each of elements of 4 bytes each (uint32 and float), the input bytes array must be divisible by 16!".into()));
151 }
152
153 let x_end = bytes_length / 4; let y_end = bytes_length / 2; let z_end = x_end * 3; let num_neurons = bytes_length / NeuronVoxelXYZP::NUMBER_BYTES_PER_NEURON;
158 let neuron_array = self.ensure_clear_and_borrow_mut(&cortical_id);
159 neuron_array.ensure_capacity(num_neurons);
160
161 for i in 0..num_neurons {
163 let x_start = i * 4;
164 let y_start = x_end + x_start;
165 let z_start = y_end + x_start;
166 let p_start = z_end + x_start;
167
168 neuron_array.push_raw(
169 LittleEndian::read_u32(&neuron_bytes[x_start..x_start + 4]),
170 LittleEndian::read_u32(&neuron_bytes[y_start..y_start + 4]),
171 LittleEndian::read_u32(&neuron_bytes[z_start..z_start + 4]),
172 LittleEndian::read_f32(&neuron_bytes[p_start..p_start + 4]),
173 )
174 }
175 reading_header_byte_index += NUMBER_BYTES_PER_CORTICAL_ID_HEADER;
176 }
177
178 Ok(())
179 }
180
181 fn as_any(&self) -> &dyn Any {
182 self
183 }
184}
185
186#[inline]
191fn write_neuron_array_to_bytes(
192 neuron_array: &NeuronVoxelXYZPArrays,
193 bytes_to_write_to: &mut [u8],
194) -> Result<(), FeagiDataError> {
195 const U32_F32_LENGTH: usize = 4;
196 let number_of_neurons_to_write: usize = neuron_array.len();
197 let number_bytes_needed = neuron_array.get_size_in_number_of_bytes();
198 if bytes_to_write_to.len() != number_bytes_needed {
199 return Err(FeagiDataError::SerializationError(format!(
200 "Need exactly {} bytes to write xyzp neuron data, but given a space of {} bytes!",
201 bytes_to_write_to.len(),
202 number_bytes_needed
203 )));
204 }
205
206 let x_offset: usize = 0;
207 let y_offset = number_of_neurons_to_write * U32_F32_LENGTH; let z_offset = number_of_neurons_to_write * U32_F32_LENGTH * 2; let p_offset = number_of_neurons_to_write * U32_F32_LENGTH * 3; let (x, y, z, p) = neuron_array.borrow_xyzp_vectors();
212
213 #[cfg(target_endian = "little")]
215 {
216 let x_len = x.len() * U32_F32_LENGTH;
217 let y_len = y.len() * U32_F32_LENGTH;
218 let z_len = z.len() * U32_F32_LENGTH;
219 let p_len = p.len() * U32_F32_LENGTH;
220
221 unsafe {
224 std::ptr::copy_nonoverlapping(
225 x.as_ptr() as *const u8,
226 bytes_to_write_to.as_mut_ptr().add(x_offset),
227 x_len,
228 );
229 std::ptr::copy_nonoverlapping(
230 y.as_ptr() as *const u8,
231 bytes_to_write_to.as_mut_ptr().add(y_offset),
232 y_len,
233 );
234 std::ptr::copy_nonoverlapping(
235 z.as_ptr() as *const u8,
236 bytes_to_write_to.as_mut_ptr().add(z_offset),
237 z_len,
238 );
239 std::ptr::copy_nonoverlapping(
240 p.as_ptr() as *const u8,
241 bytes_to_write_to.as_mut_ptr().add(p_offset),
242 p_len,
243 );
244 }
245 }
246
247 #[cfg(not(target_endian = "little"))]
248 {
249 let mut x_off = x_offset;
251 let mut y_off = y_offset;
252 let mut z_off = z_offset;
253 let mut p_off = p_offset;
254
255 for i in 0..number_of_neurons_to_write {
256 LittleEndian::write_u32(&mut bytes_to_write_to[x_off..x_off + U32_F32_LENGTH], x[i]);
257 LittleEndian::write_u32(&mut bytes_to_write_to[y_off..y_off + U32_F32_LENGTH], y[i]);
258 LittleEndian::write_u32(&mut bytes_to_write_to[z_off..z_off + U32_F32_LENGTH], z[i]);
259 LittleEndian::write_f32(&mut bytes_to_write_to[p_off..p_off + U32_F32_LENGTH], p[i]);
260
261 x_off += U32_F32_LENGTH;
262 y_off += U32_F32_LENGTH;
263 z_off += U32_F32_LENGTH;
264 p_off += U32_F32_LENGTH;
265 }
266 }
267
268 Ok(())
269}