1use anyhow::{anyhow, Context, Result};
2
3#[derive(Debug, Clone)]
5pub struct ParamInput {
6 pub name: String,
7 pub param_type: DynType,
8}
9
10#[cfg(feature = "pyo3")]
11impl<'py> pyo3::FromPyObject<'py> for ParamInput {
12 fn extract_bound(ob: &pyo3::Bound<'py, pyo3::PyAny>) -> pyo3::PyResult<Self> {
13 use pyo3::types::PyAnyMethods;
14
15 let name = ob.getattr("name")?.extract::<String>()?;
16 let param_type = ob.getattr("param_type")?.extract::<DynType>()?;
17 Ok(ParamInput { name, param_type })
18 }
19}
20
21#[derive(Debug, Clone, PartialEq)]
23pub enum DynType {
24 I8,
25 I16,
26 I32,
27 I64,
28 I128,
29 U8,
30 U16,
31 U32,
32 U64,
33 U128,
34 Bool,
35 FixedArray(Box<DynType>, usize),
37 Array(Box<DynType>),
38 Struct(Vec<(String, DynType)>),
39 Enum(Vec<(String, Option<DynType>)>),
40 Option(Box<DynType>),
41}
42
43#[cfg(feature = "pyo3")]
44impl<'py> pyo3::FromPyObject<'py> for DynType {
45 fn extract_bound(ob: &pyo3::Bound<'py, pyo3::PyAny>) -> pyo3::PyResult<Self> {
46 use pyo3::types::PyAnyMethods;
47 use pyo3::types::PyTypeMethods;
48
49 let variant_str: String = ob.get_type().name()?.to_string();
50 let variant_str = if variant_str == "str" {
52 ob.to_string()
53 } else {
54 variant_str
55 };
56
57 match variant_str.as_str() {
58 "i8" => Ok(DynType::I8),
59 "i16" => Ok(DynType::I16),
60 "i32" => Ok(DynType::I32),
61 "i64" => Ok(DynType::I64),
62 "i128" => Ok(DynType::I128),
63 "u8" => Ok(DynType::U8),
64 "u16" => Ok(DynType::U16),
65 "u32" => Ok(DynType::U32),
66 "u64" => Ok(DynType::U64),
67 "u128" => Ok(DynType::U128),
68 "bool" => Ok(DynType::Bool),
69 "FixedArray" => {
70 let inner_bound = ob
71 .getattr("element_type")
72 .context("Failed to retrieve FixedArray element type")?;
73 let size: usize = ob
74 .getattr("size")
75 .context("Failed to retrieve size")?
76 .extract::<usize>()?;
77 let inner_type = inner_bound.extract::<DynType>()?;
78 Ok(DynType::FixedArray(Box::new(inner_type), size))
79 }
80 "Array" => {
81 let inner_bound = ob
82 .getattr("element_type")
83 .context("Failed to retrieve Array element type")?;
84 let inner_type = inner_bound.extract::<DynType>()?;
85 Ok(DynType::Array(Box::new(inner_type)))
86 }
87 "Struct" => {
88 let py_fields = ob
89 .getattr("fields")
90 .context("Failed to retrieve Struct fields")?;
91 let mut fields: Vec<(String, DynType)> = Vec::new();
92 for field in py_fields.try_iter()? {
93 match field {
94 Ok(field) => {
95 let name = field
96 .getattr("name")
97 .context("Failed to retrieve Struct field name")?
98 .to_string();
99 let param_type = field
100 .getattr("element_type")
101 .context("Failed to retrieve Struct field type")?
102 .extract::<DynType>()?;
103 fields.push((name, param_type));
104 }
105 Err(e) => {
106 return Err(anyhow!(
107 "Could not convert Struct fields into an iterator. Error: {:?}",
108 e
109 )
110 .into())
111 }
112 }
113 }
114 Ok(DynType::Struct(fields))
115 }
116 "Enum" => {
117 let py_variants = ob
118 .getattr("variants")
119 .context("Failed to retrieve Enum variants")?;
120 let mut variants: Vec<(String, Option<DynType>)> = Vec::new();
121 for variant in py_variants.try_iter()? {
122 match variant {
123 Ok(variant) => {
124 let name = variant
125 .getattr("name")
126 .context("Failed to retrieve Enum variant name")?
127 .to_string();
128 let param_type = variant
129 .getattr("element_type")
130 .context("Failed to retrieve Enum variant type")?;
131 match param_type.to_string().as_str() {
132 "None" => variants.push((name, None)),
133 _ => {
134 let param_type = param_type.extract::<DynType>()?;
135 variants.push((name, Some(param_type)));
136 }
137 }
138 }
139 Err(e) => {
140 return Err(anyhow!(
141 "Could not convert Enum variants into an iterator. Error: {:?}",
142 e
143 )
144 .into())
145 }
146 }
147 }
148 Ok(DynType::Enum(variants))
149 }
150 "Option" => {
151 let inner_bound = ob
152 .getattr("element_type")
153 .context("Failed to retrieve Option element type")?;
154 let inner_type = inner_bound.extract::<DynType>()?;
155 Ok(DynType::Option(Box::new(inner_type)))
156 }
157 _ => Err(anyhow!("Not yet implemented type: {}", variant_str).into()),
158 }
159 }
160}
161
162#[derive(Debug, Clone)]
164pub enum DynValue {
165 I8(i8),
166 I16(i16),
167 I32(i32),
168 I64(i64),
169 I128(i128),
170 U8(u8),
171 U16(u16),
172 U32(u32),
173 U64(u64),
174 U128(u128),
175 Bool(bool),
176 Array(Vec<DynValue>),
178 Struct(Vec<(String, DynValue)>),
179 Enum(String, Option<Box<DynValue>>),
180 Option(Option<Box<DynValue>>),
181}
182
183pub fn deserialize_data(
200 data: &[u8],
201 params: &[ParamInput],
202 error_on_remaining: bool,
203) -> Result<Vec<DynValue>> {
204 let mut ix_values = Vec::with_capacity(params.len());
205 let mut remaining_data = data;
206
207 for param in params {
208 let (value, new_data) = deserialize_value(¶m.param_type, remaining_data)?;
210 ix_values.push(value);
211 remaining_data = new_data;
212 }
213
214 if error_on_remaining && !remaining_data.is_empty() {
215 return Err(anyhow!(
216 "Remaining data after deserialization: {:?}",
217 remaining_data
218 ));
219 }
220
221 Ok(ix_values)
222}
223
224fn deserialize_value<'a>(param_type: &DynType, data: &'a [u8]) -> Result<(DynValue, &'a [u8])> {
240 match param_type {
241 DynType::Option(inner_type) => {
242 let value = data.first().context("Not enough data for option")?;
243 match value {
244 0 => Ok((DynValue::Option(None), &data[1..])),
245 1 => {
246 let (value, new_data) = deserialize_value(inner_type, &data[1..])?;
247 Ok((DynValue::Option(Some(Box::new(value))), new_data))
248 }
249 _ => Err(anyhow!("Invalid option value: {}", value)),
250 }
251 }
252 DynType::I8 => {
253 if data.is_empty() {
254 return Err(anyhow!(
255 "Not enough data for i8: expected 1 byte, got {}",
256 data.len()
257 ));
258 }
259 let value = i8::from_le_bytes(data[..1].try_into().unwrap());
260 Ok((DynValue::I8(value), &data[1..]))
261 }
262 DynType::I16 => {
263 if data.len() < 2 {
264 return Err(anyhow!(
265 "Not enough data for i16: expected 2 bytes, got {}",
266 data.len()
267 ));
268 }
269 let value = i16::from_le_bytes(data[..2].try_into().unwrap());
270 Ok((DynValue::I16(value), &data[2..]))
271 }
272 DynType::I32 => {
273 if data.len() < 4 {
274 return Err(anyhow!(
275 "Not enough data for i32: expected 4 bytes, got {}",
276 data.len()
277 ));
278 }
279 let value = i32::from_le_bytes(data[..4].try_into().unwrap());
280 Ok((DynValue::I32(value), &data[4..]))
281 }
282 DynType::I64 => {
283 if data.len() < 8 {
284 return Err(anyhow!(
285 "Not enough data for i64: expected 8 bytes, got {}",
286 data.len()
287 ));
288 }
289 let value = i64::from_le_bytes(data[..8].try_into().unwrap());
290 Ok((DynValue::I64(value), &data[8..]))
291 }
292 DynType::I128 => {
293 if data.len() < 16 {
294 return Err(anyhow!(
295 "Not enough data for i128: expected 16 bytes, got {}",
296 data.len()
297 ));
298 }
299 let value = i128::from_le_bytes(data[..16].try_into().unwrap());
300 Ok((DynValue::I128(value), &data[16..]))
301 }
302 DynType::U8 => {
303 if data.is_empty() {
304 return Err(anyhow!("Not enough data for u8: expected 1 byte, got 0"));
305 }
306 let value = data[0];
307 Ok((DynValue::U8(value), &data[1..]))
308 }
309 DynType::U16 => {
310 if data.len() < 2 {
311 return Err(anyhow!(
312 "Not enough data for u16: expected 2 bytes, got {}",
313 data.len()
314 ));
315 }
316 let value = u16::from_le_bytes(data[..2].try_into().unwrap());
317 Ok((DynValue::U16(value), &data[2..]))
318 }
319 DynType::U32 => {
320 if data.len() < 4 {
321 return Err(anyhow!(
322 "Not enough data for u32: expected 4 bytes, got {}",
323 data.len()
324 ));
325 }
326 let value = u32::from_le_bytes(data[..4].try_into().unwrap());
327 Ok((DynValue::U32(value), &data[4..]))
328 }
329 DynType::U64 => {
330 if data.len() < 8 {
331 return Err(anyhow!(
332 "Not enough data for u64: expected 8 bytes, got {}",
333 data.len()
334 ));
335 }
336 let value = u64::from_le_bytes(data[..8].try_into().unwrap());
337 Ok((DynValue::U64(value), &data[8..]))
338 }
339 DynType::U128 => {
340 if data.len() < 16 {
341 return Err(anyhow!(
342 "Not enough data for u128: expected 16 bytes, got {}",
343 data.len()
344 ));
345 }
346 let value = u128::from_le_bytes(data[..16].try_into().unwrap());
347 Ok((DynValue::U128(value), &data[16..]))
348 }
349 DynType::Bool => {
350 if data.is_empty() {
351 return Err(anyhow!("Not enough data for bool: expected 1 byte, got 0"));
352 }
353 let value = data[0] != 0;
354 Ok((DynValue::Bool(value), &data[1..]))
355 }
356 DynType::FixedArray(inner_type, size) => {
357 let inner_type_size = check_type_size(inner_type)?;
358 let total_size = inner_type_size * size;
359
360 if data.len() < total_size {
361 return Err(anyhow!(
362 "Not enough data for fixed array: expected {} bytes, got {}",
363 total_size,
364 data.len()
365 ));
366 }
367 let value = data[..total_size]
368 .to_vec()
369 .chunks(inner_type_size)
370 .map(|chunk| {
371 let (value, _) = deserialize_value(inner_type, chunk)?;
372 Ok(value)
373 })
374 .collect::<Result<Vec<DynValue>>>()?;
375 Ok((DynValue::Array(value), &data[total_size..]))
376 }
377 DynType::Array(inner_type) => {
378 if data.len() < 4 {
379 return Err(anyhow!(
380 "Not enough data for vector length: expected 4 bytes, got {}",
381 data.len()
382 ));
383 }
384 let length = u32::from_le_bytes(data[..4].try_into().unwrap()) as usize;
385 let mut remaining_data = &data[4..];
386
387 let mut values = Vec::with_capacity(length);
388 for _ in 0..length {
389 let (value, new_data) = deserialize_value(inner_type, remaining_data)?;
390 values.push(value);
391 remaining_data = new_data;
392 }
393
394 Ok((DynValue::Array(values), remaining_data))
395 }
396 DynType::Struct(fields) => {
397 let mut values = Vec::new();
398 let mut remaining_data = data;
399 for field in fields {
400 let (value, new_data) = deserialize_value(&field.1, remaining_data)?;
401 values.push((field.0.clone(), value));
402 remaining_data = new_data;
403 }
404 Ok((DynValue::Struct(values), remaining_data))
405 }
406 DynType::Enum(variants) => {
407 if data.is_empty() {
408 return Err(anyhow!(
409 "Not enough data for enum: expected at least 1 byte for variant index"
410 ));
411 }
412 let variant_index = data[0] as usize;
413 let remaining_data = &data[1..];
414
415 if variant_index >= variants.len() {
416 return Err(anyhow!("Invalid enum variant index: {}", variant_index));
417 }
418
419 let (variant_name, variant_type) = &variants[variant_index];
420
421 if let Some(variant_type) = variant_type {
422 let (variant_value, new_data) = deserialize_value(variant_type, remaining_data)?;
423 Ok((
424 DynValue::Enum(variant_name.clone(), Some(Box::new(variant_value))),
425 new_data,
426 ))
427 } else {
428 Ok((DynValue::Enum(variant_name.clone(), None), remaining_data))
429 }
430 }
431 }
432}
433
434fn check_type_size(param_type: &DynType) -> Result<usize> {
435 match param_type {
436 DynType::U8 => Ok(1),
437 DynType::U16 => Ok(2),
438 DynType::U32 => Ok(4),
439 DynType::U64 => Ok(8),
440 DynType::U128 => Ok(16),
441 DynType::I8 => Ok(1),
442 DynType::I16 => Ok(2),
443 DynType::I32 => Ok(4),
444 DynType::I64 => Ok(8),
445 DynType::I128 => Ok(16),
446 DynType::Bool => Ok(1),
447 _ => Err(anyhow!("Unsupported primitive type for fixed array")),
448 }
449}