1use codec::{Compact, Decode, Encode, Input, Output};
2use serde_json::{json, Map, Value};
3
4#[cfg(not(feature = "std"))]
5use alloc::{format, string::String};
6use sp_std::prelude::*;
7
8use crate::error::*;
9use crate::schema::*;
10use crate::type_def::*;
11
12pub mod de;
13
14#[derive(Clone)]
15pub struct TypeCodec {
16 type_lookup: TypeLookup,
17 ty: Type,
18 id: TypeId,
19}
20
21impl TypeCodec {
22 pub fn new(type_lookup: &TypeLookup, type_ref: TypeRef) -> Option<Self> {
23 type_ref.ty.map(|ty| Self {
24 type_lookup: type_lookup.clone(),
25 ty,
26 id: type_ref.id,
27 })
28 }
29
30 pub fn decode_value<I: Input>(&self, input: &mut I, is_compact: bool) -> Result<Value> {
31 self.ty.decode_value(&self.type_lookup, input, is_compact)
32 }
33
34 pub fn decode(&self, mut data: &[u8]) -> Result<Value> {
35 self.decode_value(&mut data, false)
36 }
37
38 pub fn encode_to<T: Output + ?Sized>(&self, value: &Value, dest: &mut T) -> Result<()> {
39 self.ty.encode_to(&self.type_lookup, value, dest, false)
40 }
41
42 pub fn encode(&self, value: &Value) -> Result<Vec<u8>> {
43 let mut buf = Vec::with_capacity(1024);
44 self.encode_to(value, &mut buf)?;
45 Ok(buf)
46 }
47
48 pub fn from_slice<'a, T>(&'a self, data: &'a [u8]) -> Result<T>
49 where
50 T: serde::de::Deserialize<'a>,
51 {
52 let mut deserializer = de::TypeDeserializer::from_slice(self, data);
53 Ok(T::deserialize(&mut deserializer)?)
54 }
55}
56
57impl TypeLookup {
58 pub fn type_codec(&self, name: &str) -> Option<TypeCodec> {
59 let type_ref = self.resolve(name);
60 TypeCodec::new(self, type_ref)
61 }
62
63 pub fn decode_value<I: Input>(
64 &self,
65 type_id: TypeId,
66 input: &mut I,
67 is_compact: bool,
68 ) -> Result<Value> {
69 let ty = self
70 .get_type(type_id)
71 .ok_or_else(|| Error::DecodeTypeFailed(format!("Missing type_id: {type_id:?}")))?;
72 if ty.path().is_empty() {
73 log::trace!("decode type[{type_id:?}]");
74 } else {
75 log::trace!("decode type[{type_id:?}]: {}", ty.path());
76 }
77 ty.decode_value(self, input, is_compact)
78 }
79
80 pub fn encode_to<T: Output + ?Sized>(
81 &self,
82 type_id: TypeId,
83 value: &Value,
84 dest: &mut T,
85 is_compact: bool,
86 ) -> Result<()> {
87 let ty = self
88 .get_type(type_id)
89 .ok_or_else(|| Error::DecodeTypeFailed(format!("Missing type_id: {type_id:?}")))?;
90 if ty.path().is_empty() {
91 log::trace!("encode type[{type_id:?}]");
92 } else {
93 log::trace!("encode type[{type_id:?}]: {}", ty.path());
94 }
95 ty.encode_to(self, value, dest, is_compact)
96 }
97}
98
99impl Type {
100 pub fn decode_value<I: Input>(
101 &self,
102 type_lookup: &TypeLookup,
103 input: &mut I,
104 is_compact: bool,
105 ) -> Result<Value> {
106 if !self.path().is_empty() {
107 log::trace!("decode type: {}", self.path());
108 }
109 self
110 .type_def
111 .decode_value(self, type_lookup, input, is_compact)
112 }
113
114 pub fn encode_to<T: Output + ?Sized>(
115 &self,
116 type_lookup: &TypeLookup,
117 value: &Value,
118 dest: &mut T,
119 is_compact: bool,
120 ) -> Result<()> {
121 if !self.path().is_empty() {
122 log::trace!("encode type: {}", self.path());
123 }
124 self
125 .type_def
126 .encode_to(self, type_lookup, value, dest, is_compact)
127 }
128}
129
130impl TypeDef {
131 pub fn decode_value<I: Input>(
132 &self,
133 ty: &Type,
134 type_lookup: &TypeLookup,
135 input: &mut I,
136 is_compact: bool,
137 ) -> Result<Value> {
138 match self {
139 TypeDef::Composite(def) => def.decode_value(type_lookup, input, is_compact),
140 TypeDef::Variant(def) => {
141 let is_option = ty.path().segments == &["Option"];
142 def.decode_value(type_lookup, input, is_compact, is_option)
143 }
144 TypeDef::Sequence(def) => def.decode_value(type_lookup, input, is_compact),
145 TypeDef::Array(def) => def.decode_value(type_lookup, input, is_compact),
146 TypeDef::Tuple(def) => def.decode_value(type_lookup, input, is_compact),
147 TypeDef::Primitive(prim) => {
148 log::trace!("decode Primitive: {prim:?}, is_compact: {is_compact}");
149 match prim {
150 TypeDefPrimitive::Bool => match input.read_byte()? {
151 0 => Ok(json!(false)),
152 1 => Ok(json!(true)),
153 num => Err(Error::DecodeTypeFailed(format!(
154 "Invalid bool byte: {num:?}"
155 ))),
156 },
157 TypeDefPrimitive::Char => {
158 let ch = input.read_byte()? as char;
159 Ok(json!(ch))
160 }
161 TypeDefPrimitive::Str => {
162 let s = String::decode(input)?;
163 Ok(json!(s))
164 }
165 TypeDefPrimitive::U8 => {
166 let num = u8::decode(input)?;
167 Ok(json!(num))
168 }
169 TypeDefPrimitive::U16 => {
170 let num = if is_compact {
171 Compact::<u16>::decode(input)?.0
172 } else {
173 u16::decode(input)?
174 };
175 Ok(json!(num))
176 }
177 TypeDefPrimitive::U32 => {
178 let num = if is_compact {
179 Compact::<u32>::decode(input)?.0
180 } else {
181 u32::decode(input)?
182 };
183 Ok(json!(num))
184 }
185 TypeDefPrimitive::U64 => {
186 let num = if is_compact {
187 Compact::<u64>::decode(input)?.0
188 } else {
189 u64::decode(input)?
190 };
191 Ok(json!(num))
192 }
193 TypeDefPrimitive::U128 => {
194 let num = if is_compact {
195 Compact::<u128>::decode(input)?.0
196 } else {
197 u128::decode(input)?
198 };
199 Ok(json!(num))
200 }
201 TypeDefPrimitive::U256 => {
202 unimplemented!();
203 }
204 TypeDefPrimitive::I8 => {
205 let num = i8::decode(input)?;
206 Ok(json!(num))
207 }
208 TypeDefPrimitive::I16 => {
209 let num = if is_compact {
210 Compact::<u16>::decode(input)?.0 as i16
211 } else {
212 i16::decode(input)?
213 };
214 Ok(json!(num))
215 }
216 TypeDefPrimitive::I32 => {
217 let num = if is_compact {
218 Compact::<u32>::decode(input)?.0 as i32
219 } else {
220 i32::decode(input)?
221 };
222 Ok(json!(num))
223 }
224 TypeDefPrimitive::I64 => {
225 let num = if is_compact {
226 Compact::<u64>::decode(input)?.0 as i64
227 } else {
228 i64::decode(input)?
229 };
230 Ok(json!(num))
231 }
232 TypeDefPrimitive::I128 => {
233 let num = if is_compact {
234 Compact::<u128>::decode(input)?.0 as i128
235 } else {
236 i128::decode(input)?
237 };
238 Ok(json!(num))
239 }
240 TypeDefPrimitive::I256 => {
241 unimplemented!();
242 }
243 }
244 }
245 TypeDef::Compact(def) => def.decode_value(type_lookup, input, is_compact),
246 }
247 }
248
249 pub fn encode_to<T: Output + ?Sized>(
250 &self,
251 ty: &Type,
252 type_lookup: &TypeLookup,
253 value: &Value,
254 dest: &mut T,
255 is_compact: bool,
256 ) -> Result<()> {
257 match self {
258 TypeDef::Composite(def) => def.encode_to(type_lookup, value, dest, is_compact),
259 TypeDef::Variant(def) => {
260 let is_option = ty.path().segments == &["Option"];
261 def.encode_to(type_lookup, value, dest, is_compact, is_option)
262 }
263 TypeDef::Sequence(def) => def.encode_to(type_lookup, value, dest, is_compact),
264 TypeDef::Array(def) => def.encode_to(type_lookup, value, dest, is_compact),
265 TypeDef::Tuple(def) => def.encode_to(type_lookup, value, dest, is_compact),
266 TypeDef::Primitive(prim) => {
267 log::trace!("encode Primitive: {prim:?}, is_compact: {is_compact}");
268 match prim {
269 TypeDefPrimitive::Bool => match value.as_bool() {
270 Some(v) => {
271 dest.push_byte(if v { 1 } else { 0 });
272 Ok(())
273 }
274 None => Err(Error::EncodeTypeFailed(format!(
275 "Expected a bool, got {:?}",
276 value
277 ))),
278 },
279 TypeDefPrimitive::Char => match value.as_str() {
280 Some(v) if v.len() == 1 => {
281 let ch = v.as_bytes()[0];
282 dest.push_byte(ch);
283 Ok(())
284 }
285 _ => Err(Error::EncodeTypeFailed(format!(
286 "Expected a char (string), got {:?}",
287 value
288 ))),
289 },
290 TypeDefPrimitive::Str => match value.as_str() {
291 Some(v) => {
292 v.encode_to(dest);
293 Ok(())
294 }
295 None => Err(Error::EncodeTypeFailed(format!(
296 "Expected a string, got {:?}",
297 value
298 ))),
299 },
300 TypeDefPrimitive::U8 => match value.as_u64() {
301 Some(num) => {
302 let num: u8 = num
303 .try_into()
304 .map_err(|e| Error::EncodeTypeFailed(format!("Not a u8 number: {e:?}")))?;
305 num.encode_to(dest);
306 Ok(())
307 }
308 None => Err(Error::EncodeTypeFailed(format!(
309 "Expected a number, got {:?}",
310 value
311 ))),
312 },
313 TypeDefPrimitive::U16 => match value.as_u64() {
314 Some(num) => {
315 let num: u16 = num
316 .try_into()
317 .map_err(|e| Error::EncodeTypeFailed(format!("Not a u16 number: {e:?}")))?;
318 if is_compact {
319 Compact(num).encode_to(dest);
320 } else {
321 num.encode_to(dest);
322 }
323 Ok(())
324 }
325 None => Err(Error::EncodeTypeFailed(format!(
326 "Expected a number, got {:?}",
327 value
328 ))),
329 },
330 TypeDefPrimitive::U32 => match value.as_u64() {
331 Some(num) => {
332 let num: u32 = num
333 .try_into()
334 .map_err(|e| Error::EncodeTypeFailed(format!("Not a u32 number: {e:?}")))?;
335 if is_compact {
336 Compact(num).encode_to(dest);
337 } else {
338 num.encode_to(dest);
339 }
340 Ok(())
341 }
342 None => Err(Error::EncodeTypeFailed(format!(
343 "Expected a number, got {:?}",
344 value
345 ))),
346 },
347 TypeDefPrimitive::U64 => match value.as_u64() {
348 Some(num) => {
349 if is_compact {
350 Compact(num).encode_to(dest);
351 } else {
352 num.encode_to(dest);
353 }
354 Ok(())
355 }
356 None => Err(Error::EncodeTypeFailed(format!(
357 "Expected a number, got {:?}",
358 value
359 ))),
360 },
361 TypeDefPrimitive::U128 => match value.as_u64() {
362 Some(num) => {
363 let num: u128 = num
364 .try_into()
365 .map_err(|e| Error::EncodeTypeFailed(format!("Not a u128 number: {e:?}")))?;
366 if is_compact {
367 Compact(num).encode_to(dest);
368 } else {
369 num.encode_to(dest);
370 }
371 Ok(())
372 }
373 None => Err(Error::EncodeTypeFailed(format!(
374 "Expected a number, got {:?}",
375 value
376 ))),
377 },
378 TypeDefPrimitive::U256 => {
379 unimplemented!();
380 }
381 TypeDefPrimitive::I8 => match value.as_i64() {
382 Some(num) => {
383 let num: i8 = num
384 .try_into()
385 .map_err(|e| Error::EncodeTypeFailed(format!("Not a i8 number: {e:?}")))?;
386 num.encode_to(dest);
387 Ok(())
388 }
389 None => Err(Error::EncodeTypeFailed(format!(
390 "Expected a number, got {:?}",
391 value
392 ))),
393 },
394 TypeDefPrimitive::I16 => match value.as_i64() {
395 Some(num) => {
396 let num: i16 = num
397 .try_into()
398 .map_err(|e| Error::EncodeTypeFailed(format!("Not a i16 number: {e:?}")))?;
399 if is_compact {
400 Compact(num as u128).encode_to(dest);
401 } else {
402 num.encode_to(dest);
403 }
404 Ok(())
405 }
406 None => Err(Error::EncodeTypeFailed(format!(
407 "Expected a number, got {:?}",
408 value
409 ))),
410 },
411 TypeDefPrimitive::I32 => match value.as_i64() {
412 Some(num) => {
413 let num: i32 = num
414 .try_into()
415 .map_err(|e| Error::EncodeTypeFailed(format!("Not a i32 number: {e:?}")))?;
416 if is_compact {
417 Compact(num as u128).encode_to(dest);
418 } else {
419 num.encode_to(dest);
420 }
421 Ok(())
422 }
423 None => Err(Error::EncodeTypeFailed(format!(
424 "Expected a number, got {:?}",
425 value
426 ))),
427 },
428 TypeDefPrimitive::I64 => match value.as_i64() {
429 Some(num) => {
430 if is_compact {
431 Compact(num as u128).encode_to(dest);
432 } else {
433 num.encode_to(dest);
434 }
435 Ok(())
436 }
437 None => Err(Error::EncodeTypeFailed(format!(
438 "Expected a number, got {:?}",
439 value
440 ))),
441 },
442 TypeDefPrimitive::I128 => match value.as_i64() {
443 Some(num) => {
444 let num: i128 = num
445 .try_into()
446 .map_err(|e| Error::EncodeTypeFailed(format!("Not a i128 number: {e:?}")))?;
447 if is_compact {
448 Compact(num as u128).encode_to(dest);
449 } else {
450 num.encode_to(dest);
451 }
452 Ok(())
453 }
454 None => Err(Error::EncodeTypeFailed(format!(
455 "Expected a number, got {:?}",
456 value
457 ))),
458 },
459 TypeDefPrimitive::I256 => {
460 unimplemented!();
461 }
462 }
463 }
464 TypeDef::Compact(def) => def.encode_to(type_lookup, value, dest, is_compact),
465 }
466 }
467}
468
469fn decode_fields<I: Input>(
470 fields: &Vec<Field>,
471 is_struct: bool,
472 type_lookup: &TypeLookup,
473 input: &mut I,
474 is_compact: bool,
475) -> Result<Value> {
476 let len = fields.len();
477 if len == 0 {
478 return Ok(Value::Null);
479 }
480 match fields.len() {
481 0 => Ok(Value::Null),
482 1 if fields[0].name.is_none() => {
483 Ok(type_lookup.decode_value(fields[0].ty, input, is_compact)?)
484 }
485 len if is_struct => {
486 let mut m = Map::with_capacity(len);
487 for (idx, field) in fields.iter().enumerate() {
488 let name = field
489 .name
490 .as_ref()
491 .cloned()
492 .unwrap_or_else(|| format!("{idx}"));
493 log::trace!("decode Composite field: {name}");
494 m.insert(name, type_lookup.decode_value(field.ty, input, is_compact)?);
495 }
496 Ok(m.into())
497 }
498 len => {
499 log::trace!("decode Composite tuple fields");
500 let mut arr = Vec::with_capacity(len);
501 for field in fields.iter() {
502 arr.push(type_lookup.decode_value(field.ty, input, is_compact)?);
503 }
504 Ok(arr.into())
505 }
506 }
507}
508
509fn encode_struct_fields<T: Output + ?Sized>(
510 fields: &Vec<Field>,
511 type_lookup: &TypeLookup,
512 value: &Value,
513 dest: &mut T,
514 is_compact: bool,
515) -> Result<()> {
516 let len = fields.len();
517 match value {
518 Value::Object(map) if map.len() == len => {
519 for field in fields {
520 let value = field.name.as_ref().and_then(|n| map.get(n));
521 match value {
522 Some(value) => {
523 log::trace!("encode Composite struct field: {:?}", field);
524 type_lookup.encode_to(field.ty, value, dest, is_compact)?;
525 }
526 None => {
527 return Err(Error::EncodeTypeFailed(format!(
528 "Encode struct missing field {:?}",
529 field.name
530 )));
531 }
532 }
533 }
534 Ok(())
535 }
536 Value::Object(map) => Err(Error::EncodeTypeFailed(format!(
537 "Encode struct expected {len} field, got {}",
538 map.len()
539 ))),
540 _ => Err(Error::EncodeTypeFailed(format!(
541 "Encode struct expect an object got {:?}",
542 value
543 ))),
544 }
545}
546
547fn encode_tuple_fields<T: Output + ?Sized>(
548 fields: &Vec<Field>,
549 type_lookup: &TypeLookup,
550 value: &Value,
551 dest: &mut T,
552 is_compact: bool,
553) -> Result<()> {
554 let len = fields.len();
555 if len == 1 {
556 return type_lookup.encode_to(fields[0].ty, value, dest, is_compact);
557 }
558 match value.as_array() {
559 Some(arr) if arr.len() == len => {
560 for (v, field) in arr.into_iter().zip(fields.iter()) {
561 log::trace!("encode Composite tuple field: {:?}", field);
562 type_lookup.encode_to(field.ty, v, dest, is_compact)?;
563 }
564 Ok(())
565 }
566 Some(arr) => Err(Error::EncodeTypeFailed(format!(
567 "Encode struct tuple expect array with length {len}, got {}",
568 arr.len()
569 ))),
570 None => Err(Error::EncodeTypeFailed(format!(
571 "Encode struct tuple expect array value got {:?}",
572 value
573 ))),
574 }
575}
576
577fn encode_fields<T: Output + ?Sized>(
578 fields: &Vec<Field>,
579 is_struct: bool,
580 type_lookup: &TypeLookup,
581 value: &Value,
582 dest: &mut T,
583 is_compact: bool,
584) -> Result<()> {
585 if is_struct {
586 encode_struct_fields(fields, type_lookup, value, dest, is_compact)
587 } else {
588 encode_tuple_fields(fields, type_lookup, value, dest, is_compact)
589 }
590}
591
592impl TypeDefComposite {
593 pub fn decode_value<I: Input>(
594 &self,
595 type_lookup: &TypeLookup,
596 input: &mut I,
597 is_compact: bool,
598 ) -> Result<Value> {
599 decode_fields(
600 &self.fields,
601 self.is_struct(),
602 type_lookup,
603 input,
604 is_compact,
605 )
606 }
607
608 pub fn encode_to<T: Output + ?Sized>(
609 &self,
610 type_lookup: &TypeLookup,
611 value: &Value,
612 dest: &mut T,
613 is_compact: bool,
614 ) -> Result<()> {
615 encode_fields(
616 &self.fields,
617 self.is_struct(),
618 type_lookup,
619 value,
620 dest,
621 is_compact,
622 )
623 }
624}
625
626impl TypeDefVariant {
627 pub fn decode_value<I: Input>(
628 &self,
629 type_lookup: &TypeLookup,
630 input: &mut I,
631 is_compact: bool,
632 is_option: bool,
633 ) -> Result<Value> {
634 let val = input.read_byte()?;
635 match (val, self.get_by_idx(val), is_option) {
636 (0, Some(_variant), true) => Ok(Value::Null),
637 (1, Some(variant), true) => decode_fields(
638 &variant.fields,
639 variant.is_struct(),
640 type_lookup,
641 input,
642 is_compact,
643 ),
644 (_, Some(variant), _) if variant.fields.len() == 0 => Ok(json!(variant.name)),
645 (_, Some(variant), _) => {
646 let mut m = Map::new();
647 let name = variant.name.clone();
648 m.insert(
649 name,
650 decode_fields(
651 &variant.fields,
652 variant.is_struct(),
653 type_lookup,
654 input,
655 is_compact,
656 )?,
657 );
658 Ok(m.into())
659 }
660 (_, None, _) if val == 0 => Ok(Value::Null),
661 (_, None, _) => {
662 log::debug!(
663 "Invalid variant: {}, bytes remaining: {:?}, variants: {:?}",
664 val,
665 input.remaining_len()?,
666 self.variants
667 );
668 Err(Error::DecodeTypeFailed(format!("Invalid variant: {val}")))
669 }
670 }
671 }
672
673 fn encode_option<T: Output + ?Sized>(
674 &self,
675 type_lookup: &TypeLookup,
676 value: &Value,
677 dest: &mut T,
678 is_compact: bool,
679 ) -> Result<()> {
680 if value.is_null() {
681 dest.push_byte(0);
682 return Ok(());
683 }
684 dest.push_byte(1);
685 let variant = self
686 .variants
687 .get(1)
688 .ok_or_else(|| Error::EncodeTypeFailed("Option type doesn't have a Some variant".into()))?;
689 encode_fields(
690 &variant.fields,
691 variant.is_struct(),
692 type_lookup,
693 value,
694 dest,
695 is_compact,
696 )
697 }
698
699 pub fn encode_to<T: Output + ?Sized>(
700 &self,
701 type_lookup: &TypeLookup,
702 value: &Value,
703 dest: &mut T,
704 is_compact: bool,
705 is_option: bool,
706 ) -> Result<()> {
707 if is_option {
708 return self.encode_option(type_lookup, value, dest, is_compact);
709 }
710 let len = self.variants.len();
711 match value {
712 Value::Null if len == 0 => {
713 dest.push_byte(0);
715 Ok(())
716 }
717 Value::String(s) => match self.get_by_name(&s) {
718 Some(v) if v.fields.len() == 0 => {
719 log::trace!("encode enum variant: {:?}", v);
720 dest.push_byte(v.index);
721 Ok(())
722 }
723 Some(v) => Err(Error::EncodeTypeFailed(format!(
724 "Variant {} has fields, got just the name.",
725 v.name
726 ))),
727 None => Err(Error::EncodeTypeFailed(format!("Unknown variant name {s}"))),
728 },
729 Value::Object(map) if map.len() == 1 => match map.iter().next() {
730 Some((key, value)) => match self.get_by_name(&key) {
731 Some(v) if v.fields.len() == 0 => {
732 log::trace!("encode enum variant: {:?}", v);
733 dest.push_byte(v.index);
734 Ok(())
735 }
736 Some(v) => {
737 log::trace!("encode enum variant: {:?}", v);
738 dest.push_byte(v.index);
739 if v.fields.len() > 0 {
740 encode_fields(
741 &v.fields,
742 v.is_struct(),
743 type_lookup,
744 value,
745 dest,
746 is_compact,
747 )
748 } else {
749 Ok(())
750 }
751 }
752 None => Err(Error::EncodeTypeFailed(format!(
753 "Unknown variant {:?}",
754 map
755 ))),
756 },
757 None => Err(Error::EncodeTypeFailed(format!(
758 "Unknown variant {:?}",
759 map
760 ))),
761 },
762 Value::Object(map) => Err(Error::EncodeTypeFailed(format!(
763 "Expect a variant, got a map with the wrong number of fields {}",
764 map.len()
765 ))),
766 value => Err(Error::EncodeTypeFailed(format!(
767 "Expect a variant, got {value:?}"
768 ))),
769 }
770 }
771}
772
773impl TypeDefSequence {
774 pub fn decode_value<I: Input>(
775 &self,
776 type_lookup: &TypeLookup,
777 input: &mut I,
778 is_compact: bool,
779 ) -> Result<Value> {
780 let len = Compact::<u64>::decode(input)?.0 as usize;
781 let ty = type_lookup
782 .get_type(self.type_param)
783 .ok_or_else(|| Error::DecodeTypeFailed(format!("Missing type_id: {:?}", self.type_param)))?;
784 if ty.is_u8() {
785 log::trace!("--- decode byte sequence[{len}]: {:?}", ty);
786 let mut vec = Vec::with_capacity(len);
787 for _ in 0..len {
789 vec.push(input.read_byte()?);
790 }
791 Ok(Value::String(hex::encode(vec)))
792 } else {
793 let mut vec = Vec::with_capacity(len.max(256));
794 for _ in 0..len {
795 vec.push(ty.decode_value(type_lookup, input, is_compact)?);
796 }
797 Ok(vec.into())
798 }
799 }
800
801 pub fn encode_to<T: Output + ?Sized>(
802 &self,
803 type_lookup: &TypeLookup,
804 value: &Value,
805 dest: &mut T,
806 is_compact: bool,
807 ) -> Result<()> {
808 let ty = type_lookup
809 .get_type(self.type_param)
810 .ok_or_else(|| Error::DecodeTypeFailed(format!("Missing type_id: {:?}", self.type_param)))?;
811 match value {
812 Value::Array(arr) => {
813 let len = Compact::<u64>(arr.len() as u64);
814 len.encode_to(dest);
815 log::trace!("encode sequence: len={}", arr.len());
816 for v in arr {
817 ty.encode_to(type_lookup, v, dest, is_compact)?;
818 }
819 Ok(())
820 }
821 Value::String(s) if ty.is_u8() => {
822 let off = if s.starts_with("0x") { 2 } else { 0 };
823 let arr = hex::decode(&s[off..])?;
824 log::trace!("--- encode byte sequence[{}]: {:?}", arr.len(), ty);
825 let len = Compact::<u64>(arr.len() as u64);
826 len.encode_to(dest);
827 dest.write(&arr[..]);
829 Ok(())
830 }
831 _ => Err(Error::EncodeTypeFailed(format!(
832 "Encode sequence expect array value got {:?}",
833 value
834 ))),
835 }
836 }
837}
838
839impl TypeDefArray {
840 pub fn decode_value<I: Input>(
841 &self,
842 type_lookup: &TypeLookup,
843 input: &mut I,
844 is_compact: bool,
845 ) -> Result<Value> {
846 let len = self.len as usize;
847 let ty = type_lookup
848 .get_type(self.type_param)
849 .ok_or_else(|| Error::DecodeTypeFailed(format!("Missing type_id: {:?}", self.type_param)))?;
850 if ty.is_u8() {
851 log::trace!("--- decode byte array[{len}]: {:?}", ty);
852 let mut vec = Vec::with_capacity(len);
853 for _ in 0..len {
855 vec.push(input.read_byte()?);
856 }
857 Ok(Value::String(hex::encode(vec)))
858 } else {
859 let mut vec = Vec::with_capacity(len);
860 for _ in 0..len {
861 vec.push(ty.decode_value(type_lookup, input, is_compact)?);
862 }
863 Ok(vec.into())
864 }
865 }
866
867 pub fn encode_to<T: Output + ?Sized>(
868 &self,
869 type_lookup: &TypeLookup,
870 value: &Value,
871 dest: &mut T,
872 is_compact: bool,
873 ) -> Result<()> {
874 let len = self.len as usize;
875 let ty = type_lookup
876 .get_type(self.type_param)
877 .ok_or_else(|| Error::DecodeTypeFailed(format!("Missing type_id: {:?}", self.type_param)))?;
878 match value {
879 Value::Array(arr) if arr.len() == len => {
880 log::trace!("encode array: len={len}");
881 for v in arr {
882 ty.encode_to(type_lookup, v, dest, is_compact)?;
883 }
884 Ok(())
885 }
886 Value::Array(arr) => Err(Error::EncodeTypeFailed(format!(
887 "Expect array with length {len}, got {}",
888 arr.len()
889 ))),
890 Value::String(s) if ty.is_u8() && s.len() >= 2 * len => {
891 log::trace!("--- encode byte array[{len}]: {:?}", ty);
892 let off = if s.starts_with("0x") { 2 } else { 0 };
894 let arr = hex::decode(&s[off..])?;
895 dest.write(&arr[..]);
896 Ok(())
897 }
898 _ => Err(Error::EncodeTypeFailed(format!(
899 "Expect array value got {:?}",
900 value
901 ))),
902 }
903 }
904}
905
906impl TypeDefTuple {
907 pub fn decode_value<I: Input>(
908 &self,
909 type_lookup: &TypeLookup,
910 input: &mut I,
911 is_compact: bool,
912 ) -> Result<Value> {
913 match self.fields.len() {
914 0 => Ok(Value::Null),
915 1 => Ok(type_lookup.decode_value(self.fields[0], input, is_compact)?),
916 len => {
917 let mut vec = Vec::with_capacity(len);
918 for field in &self.fields {
919 vec.push(type_lookup.decode_value(*field, input, is_compact)?);
920 }
921 Ok(vec.into())
922 }
923 }
924 }
925
926 pub fn encode_to<T: Output + ?Sized>(
927 &self,
928 type_lookup: &TypeLookup,
929 value: &Value,
930 dest: &mut T,
931 is_compact: bool,
932 ) -> Result<()> {
933 let len = self.fields.len();
934 log::trace!("encode tuple: len={len}");
935 if len == 1 {
936 return type_lookup.encode_to(self.fields[0], value, dest, is_compact);
937 }
938 match value.as_array() {
939 Some(arr) if arr.len() == len => {
940 for (v, field) in arr.into_iter().zip(self.fields.iter()) {
941 type_lookup.encode_to(*field, v, dest, is_compact)?;
942 }
943 Ok(())
944 }
945 Some(arr) => Err(Error::EncodeTypeFailed(format!(
946 "Encode tuple expect array with length {len}, got {}",
947 arr.len()
948 ))),
949 None => Err(Error::EncodeTypeFailed(format!(
950 "Encode tuple expect array value got {:?}",
951 value
952 ))),
953 }
954 }
955}
956
957impl TypeDefCompact {
958 pub fn decode_value<I: Input>(
959 &self,
960 type_lookup: &TypeLookup,
961 input: &mut I,
962 _is_compact: bool,
963 ) -> Result<Value> {
964 type_lookup.decode_value(self.type_param, input, true)
965 }
966
967 pub fn encode_to<T: Output + ?Sized>(
968 &self,
969 type_lookup: &TypeLookup,
970 value: &Value,
971 dest: &mut T,
972 _is_compact: bool,
973 ) -> Result<()> {
974 type_lookup.encode_to(self.type_param, value, dest, true)
975 }
976}