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(data: &[u8], params: &[ParamInput]) -> Result<Vec<DynValue>> {
198 let mut ix_values = Vec::with_capacity(params.len());
199 let mut remaining_data = data;
200
201 for param in params {
202 let (value, new_data) = deserialize_value(¶m.param_type, remaining_data)?;
204 ix_values.push(value);
205 remaining_data = new_data;
206 }
207
208 if !remaining_data.is_empty() {
209 return Err(anyhow!(
210 "Remaining data after deserialization: {:?}",
211 remaining_data
212 ));
213 }
214
215 Ok(ix_values)
216}
217
218fn deserialize_value<'a>(param_type: &DynType, data: &'a [u8]) -> Result<(DynValue, &'a [u8])> {
234 match param_type {
235 DynType::Option(inner_type) => {
236 let value = data.first().context("Not enough data for option")?;
237 match value {
238 0 => Ok((DynValue::Option(None), &data[1..])),
239 1 => {
240 let (value, new_data) = deserialize_value(inner_type, &data[1..])?;
241 Ok((DynValue::Option(Some(Box::new(value))), new_data))
242 }
243 _ => Err(anyhow!("Invalid option value: {}", value)),
244 }
245 }
246 DynType::I8 => {
247 if data.is_empty() {
248 return Err(anyhow!(
249 "Not enough data for i8: expected 1 byte, got {}",
250 data.len()
251 ));
252 }
253 let value = i8::from_le_bytes(data[..1].try_into().unwrap());
254 Ok((DynValue::I8(value), &data[1..]))
255 }
256 DynType::I16 => {
257 if data.len() < 2 {
258 return Err(anyhow!(
259 "Not enough data for i16: expected 2 bytes, got {}",
260 data.len()
261 ));
262 }
263 let value = i16::from_le_bytes(data[..2].try_into().unwrap());
264 Ok((DynValue::I16(value), &data[2..]))
265 }
266 DynType::I32 => {
267 if data.len() < 4 {
268 return Err(anyhow!(
269 "Not enough data for i32: expected 4 bytes, got {}",
270 data.len()
271 ));
272 }
273 let value = i32::from_le_bytes(data[..4].try_into().unwrap());
274 Ok((DynValue::I32(value), &data[4..]))
275 }
276 DynType::I64 => {
277 if data.len() < 8 {
278 return Err(anyhow!(
279 "Not enough data for i64: expected 8 bytes, got {}",
280 data.len()
281 ));
282 }
283 let value = i64::from_le_bytes(data[..8].try_into().unwrap());
284 Ok((DynValue::I64(value), &data[8..]))
285 }
286 DynType::I128 => {
287 if data.len() < 16 {
288 return Err(anyhow!(
289 "Not enough data for i128: expected 16 bytes, got {}",
290 data.len()
291 ));
292 }
293 let value = i128::from_le_bytes(data[..16].try_into().unwrap());
294 Ok((DynValue::I128(value), &data[16..]))
295 }
296 DynType::U8 => {
297 if data.is_empty() {
298 return Err(anyhow!("Not enough data for u8: expected 1 byte, got 0"));
299 }
300 let value = data[0];
301 Ok((DynValue::U8(value), &data[1..]))
302 }
303 DynType::U16 => {
304 if data.len() < 2 {
305 return Err(anyhow!(
306 "Not enough data for u16: expected 2 bytes, got {}",
307 data.len()
308 ));
309 }
310 let value = u16::from_le_bytes(data[..2].try_into().unwrap());
311 Ok((DynValue::U16(value), &data[2..]))
312 }
313 DynType::U32 => {
314 if data.len() < 4 {
315 return Err(anyhow!(
316 "Not enough data for u32: expected 4 bytes, got {}",
317 data.len()
318 ));
319 }
320 let value = u32::from_le_bytes(data[..4].try_into().unwrap());
321 Ok((DynValue::U32(value), &data[4..]))
322 }
323 DynType::U64 => {
324 if data.len() < 8 {
325 return Err(anyhow!(
326 "Not enough data for u64: expected 8 bytes, got {}",
327 data.len()
328 ));
329 }
330 let value = u64::from_le_bytes(data[..8].try_into().unwrap());
331 Ok((DynValue::U64(value), &data[8..]))
332 }
333 DynType::U128 => {
334 if data.len() < 16 {
335 return Err(anyhow!(
336 "Not enough data for u128: expected 16 bytes, got {}",
337 data.len()
338 ));
339 }
340 let value = u128::from_le_bytes(data[..16].try_into().unwrap());
341 Ok((DynValue::U128(value), &data[16..]))
342 }
343 DynType::Bool => {
344 if data.is_empty() {
345 return Err(anyhow!("Not enough data for bool: expected 1 byte, got 0"));
346 }
347 let value = data[0] != 0;
348 Ok((DynValue::Bool(value), &data[1..]))
349 }
350 DynType::FixedArray(inner_type, size) => {
351 let inner_type_size = check_type_size(inner_type)?;
352 let total_size = inner_type_size * size;
353
354 if data.len() < total_size {
355 return Err(anyhow!(
356 "Not enough data for fixed array: expected {} bytes, got {}",
357 total_size,
358 data.len()
359 ));
360 }
361 let value = data[..total_size]
362 .to_vec()
363 .chunks(inner_type_size)
364 .map(|chunk| {
365 let (value, _) = deserialize_value(inner_type, chunk)?;
366 Ok(value)
367 })
368 .collect::<Result<Vec<DynValue>>>()?;
369 Ok((DynValue::Array(value), &data[total_size..]))
370 }
371 DynType::Array(inner_type) => {
372 if data.len() < 4 {
373 return Err(anyhow!(
374 "Not enough data for vector length: expected 4 bytes, got {}",
375 data.len()
376 ));
377 }
378 let length = u32::from_le_bytes(data[..4].try_into().unwrap()) as usize;
379 let mut remaining_data = &data[4..];
380
381 let mut values = Vec::with_capacity(length);
382 for _ in 0..length {
383 let (value, new_data) = deserialize_value(inner_type, remaining_data)?;
384 values.push(value);
385 remaining_data = new_data;
386 }
387
388 Ok((DynValue::Array(values), remaining_data))
389 }
390 DynType::Struct(fields) => {
391 let mut values = Vec::new();
392 let mut remaining_data = data;
393 for field in fields {
394 let (value, new_data) = deserialize_value(&field.1, remaining_data)?;
395 values.push((field.0.clone(), value));
396 remaining_data = new_data;
397 }
398 Ok((DynValue::Struct(values), remaining_data))
399 }
400 DynType::Enum(variants) => {
401 if data.is_empty() {
402 return Err(anyhow!(
403 "Not enough data for enum: expected at least 1 byte for variant index"
404 ));
405 }
406 let variant_index = data[0] as usize;
407 let remaining_data = &data[1..];
408
409 if variant_index >= variants.len() {
410 return Err(anyhow!("Invalid enum variant index: {}", variant_index));
411 }
412
413 let (variant_name, variant_type) = &variants[variant_index];
414
415 if let Some(variant_type) = variant_type {
416 let (variant_value, new_data) = deserialize_value(variant_type, remaining_data)?;
417 Ok((
418 DynValue::Enum(variant_name.clone(), Some(Box::new(variant_value))),
419 new_data,
420 ))
421 } else {
422 Ok((DynValue::Enum(variant_name.clone(), None), remaining_data))
423 }
424 }
425 }
426}
427
428fn check_type_size(param_type: &DynType) -> Result<usize> {
429 match param_type {
430 DynType::U8 => Ok(1),
431 DynType::U16 => Ok(2),
432 DynType::U32 => Ok(4),
433 DynType::U64 => Ok(8),
434 DynType::U128 => Ok(16),
435 DynType::I8 => Ok(1),
436 DynType::I16 => Ok(2),
437 DynType::I32 => Ok(4),
438 DynType::I64 => Ok(8),
439 DynType::I128 => Ok(16),
440 DynType::Bool => Ok(1),
441 _ => Err(anyhow!("Unsupported primitive type for fixed array")),
442 }
443}