1use crate::{
27 form::PortableForm,
28 interner::Interner,
29 prelude::{collections::BTreeMap, fmt::Debug, mem, vec::Vec},
30 Path, Registry, Type, TypeDef, TypeDefPrimitive,
31};
32use scale::Encode;
33
34#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
36#[cfg_attr(feature = "serde", derive(serde::Serialize))]
37#[cfg_attr(all(feature = "serde", feature = "decode"), derive(serde::Deserialize))]
38#[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))]
39#[derive(Clone, Debug, PartialEq, Eq, Encode)]
40pub struct PortableRegistry {
41 pub types: Vec<PortableType>,
43}
44
45impl From<Registry> for PortableRegistry {
46 fn from(registry: Registry) -> Self {
47 PortableRegistry {
48 types: registry
49 .types()
50 .map(|(k, v)| PortableType {
51 id: k.id,
52 ty: v.clone(),
53 })
54 .collect::<Vec<_>>(),
55 }
56 }
57}
58
59impl PortableRegistry {
60 pub fn resolve(&self, id: u32) -> Option<&Type<PortableForm>> {
62 self.types.get(id as usize).map(|ty| &ty.ty)
63 }
64
65 #[deprecated(
67 since = "2.5.0",
68 note = "Prefer to access the fields directly; this getter will be removed in the next major version"
69 )]
70 pub fn types(&self) -> &[PortableType] {
71 &self.types
72 }
73
74 pub fn retain<F>(&mut self, mut filter: F) -> BTreeMap<u32, u32>
86 where
87 F: FnMut(u32) -> bool,
88 {
89 let mut retained_mappings = BTreeMap::new();
90 let mut new_types = crate::prelude::vec![];
91
92 fn placeholder_type() -> PortableType {
93 PortableType {
94 id: u32::MAX,
95 ty: Type {
96 type_def: TypeDef::Primitive(TypeDefPrimitive::Bool),
97 path: Path::default(),
98 type_params: crate::prelude::vec![],
99 docs: crate::prelude::vec![],
100 },
101 }
102 }
103
104 fn retain_type(
105 id: u32,
106 types: &mut [PortableType],
107 new_types: &mut Vec<PortableType>,
108 retained_mappings: &mut BTreeMap<u32, u32>,
109 ) -> u32 {
110 if let Some(id) = retained_mappings.get(&id) {
112 return *id;
113 }
114
115 let new_id = new_types.len() as u32;
120 new_types.push(placeholder_type());
121 retained_mappings.insert(id, new_id);
122
123 let mut ty = mem::replace(&mut types[id as usize], placeholder_type());
127 ty.id = new_id;
128
129 for param in ty.ty.type_params.iter_mut() {
132 let Some(param_ty) = ¶m.ty else { continue };
133 let new_id = retain_type(param_ty.id, types, new_types, retained_mappings);
134 param.ty = Some(Into::into(new_id));
135 }
136
137 match &mut ty.ty.type_def {
140 TypeDef::Composite(composite) => {
141 for field in composite.fields.iter_mut() {
142 let new_id = retain_type(field.ty.id, types, new_types, retained_mappings);
143 field.ty = new_id.into();
144 }
145 }
146 TypeDef::Variant(variant) => {
147 for var in variant.variants.iter_mut() {
148 for field in var.fields.iter_mut() {
149 let new_id =
150 retain_type(field.ty.id, types, new_types, retained_mappings);
151 field.ty = new_id.into();
152 }
153 }
154 }
155 TypeDef::Sequence(sequence) => {
156 let new_id =
157 retain_type(sequence.type_param.id, types, new_types, retained_mappings);
158 sequence.type_param = new_id.into();
159 }
160 TypeDef::Array(array) => {
161 let new_id =
162 retain_type(array.type_param.id, types, new_types, retained_mappings);
163 array.type_param = new_id.into();
164 }
165 TypeDef::Tuple(tuple) => {
166 for ty in tuple.fields.iter_mut() {
167 let new_id = retain_type(ty.id, types, new_types, retained_mappings);
168 *ty = new_id.into();
169 }
170 }
171 TypeDef::Primitive(_) => (),
172 TypeDef::Compact(compact) => {
173 let new_id =
174 retain_type(compact.type_param.id, types, new_types, retained_mappings);
175 compact.type_param = new_id.into();
176 }
177 TypeDef::BitSequence(bit_seq) => {
178 let bit_store_id = retain_type(
179 bit_seq.bit_store_type.id,
180 types,
181 new_types,
182 retained_mappings,
183 );
184 let bit_order_id = retain_type(
185 bit_seq.bit_order_type.id,
186 types,
187 new_types,
188 retained_mappings,
189 );
190
191 bit_seq.bit_store_type = bit_store_id.into();
192 bit_seq.bit_order_type = bit_order_id.into();
193 }
194 }
195
196 new_types[new_id as usize] = ty;
199 new_id
200 }
201
202 for id in 0..self.types.len() as u32 {
203 if !filter(id) {
205 continue;
206 }
207
208 retain_type(id, &mut self.types, &mut new_types, &mut retained_mappings);
209 }
210
211 self.types = new_types;
212 retained_mappings
213 }
214}
215
216#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
218#[cfg_attr(feature = "serde", derive(serde::Serialize))]
219#[cfg_attr(all(feature = "serde", feature = "decode"), derive(serde::Deserialize))]
220#[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))]
221#[derive(Clone, Debug, PartialEq, Eq, Encode)]
222pub struct PortableType {
223 #[codec(compact)]
225 pub id: u32,
226 #[cfg_attr(feature = "serde", serde(rename = "type"))]
228 pub ty: Type<PortableForm>,
229}
230
231impl PortableType {
232 pub fn new(id: u32, ty: Type<PortableForm>) -> Self {
234 Self { id, ty }
235 }
236
237 #[deprecated(
239 since = "2.5.0",
240 note = "Prefer to access the fields directly; this getter will be removed in the next major version"
241 )]
242 pub fn id(&self) -> u32 {
243 self.id
244 }
245
246 #[deprecated(
248 since = "2.5.0",
249 note = "Prefer to access the fields directly; this getter will be removed in the next major version"
250 )]
251 pub fn ty(&self) -> &Type<PortableForm> {
252 &self.ty
253 }
254}
255
256#[derive(Debug, Default)]
262pub struct PortableRegistryBuilder {
263 types: Interner<Type<PortableForm>>,
264}
265
266impl PortableRegistryBuilder {
267 pub fn new() -> Self {
269 Default::default()
270 }
271
272 pub fn register_type(&mut self, ty: Type<PortableForm>) -> u32 {
276 self.types.intern_or_get(ty).1.into_untracked().id
277 }
278
279 pub fn next_type_id(&self) -> u32 {
281 self.types.elements().len() as u32
282 }
283
284 pub fn get(&self, id: u32) -> Option<&Type<PortableForm>> {
286 self.types.elements().get(id as usize)
287 }
288
289 pub fn finish(&self) -> PortableRegistry {
291 let types = self
292 .types
293 .elements()
294 .iter()
295 .enumerate()
296 .map(|(i, ty)| PortableType {
297 id: i as u32,
298 ty: ty.clone(),
299 })
300 .collect();
301 PortableRegistry { types }
302 }
303}
304
305#[cfg(test)]
306mod tests {
307 use scale::Compact;
308
309 use super::*;
310 use crate::ty::TypeDefPrimitive;
311 use crate::{build::*, prelude::vec, *};
312
313 fn ty<T: TypeInfo + 'static>() -> MetaType {
314 MetaType::new::<T>()
315 }
316
317 fn make_registry(tys: impl IntoIterator<Item = MetaType>) -> (Vec<u32>, PortableRegistry) {
318 let mut types = Registry::new();
320 let mut ids = vec![];
321 for ty in tys.into_iter() {
322 let id = types.register_type(&ty);
323 ids.push(id.id);
324 }
325
326 let registry = types.into();
327 (ids, registry)
328 }
329
330 #[test]
331 fn retain_seq_type() {
332 let (ids, mut registry) = make_registry([ty::<bool>(), ty::<Vec<u32>>(), ty::<String>()]);
333
334 assert_eq!(registry.types.len(), 4);
335
336 let vec_id = ids[1];
338 let retained_ids = registry.retain(|id| id == vec_id);
339
340 assert_eq!(retained_ids.len(), 2);
341 assert_eq!(registry.types.len(), 2);
342
343 let new_vec_id = *retained_ids
345 .get(&vec_id)
346 .expect("vec should have been retained");
347 let registry_ty = registry
348 .types
349 .get(new_vec_id as usize)
350 .expect("vec should exist");
351
352 assert_eq!(registry_ty.id, new_vec_id);
353
354 let seq = match ®istry_ty.ty.type_def {
356 TypeDef::Sequence(s) => s,
357 def => panic!("Expected a sequence type, got {def:?}"),
358 };
359
360 let vec_param = registry
361 .resolve(seq.type_param.id)
362 .expect("vec param should be exist");
363 assert!(matches!(
364 vec_param.type_def,
365 TypeDef::Primitive(TypeDefPrimitive::U32)
366 ));
367 }
368
369 #[test]
370 fn retain_array_type() {
371 let (ids, mut registry) = make_registry([ty::<bool>(), ty::<[u32; 16]>(), ty::<String>()]);
372
373 assert_eq!(registry.types.len(), 4);
374
375 let arr_id = ids[1];
377 let retained_ids = registry.retain(|id| id == arr_id);
378
379 assert_eq!(retained_ids.len(), 2);
380 assert_eq!(registry.types.len(), 2);
381
382 let new_arr_id = *retained_ids
384 .get(&arr_id)
385 .expect("array should have been retained");
386 let registry_ty = registry
387 .types
388 .get(new_arr_id as usize)
389 .expect("array should exist");
390
391 assert_eq!(registry_ty.id, new_arr_id);
392
393 let arr = match ®istry_ty.ty.type_def {
395 TypeDef::Array(a) => a,
396 def => panic!("Expected an array type, got {def:?}"),
397 };
398
399 let array_param = registry
400 .resolve(arr.type_param.id)
401 .expect("array param should be exist");
402 assert!(matches!(
403 array_param.type_def,
404 TypeDef::Primitive(TypeDefPrimitive::U32)
405 ));
406 }
407
408 #[test]
409 fn retain_tuple_type() {
410 let (ids, mut registry) =
411 make_registry([ty::<bool>(), ty::<(u32, [u8; 32], bool)>(), ty::<String>()]);
412
413 assert_eq!(registry.types.len(), 6);
414
415 let tuple_id = ids[1];
417 let retained_ids = registry.retain(|id| id == tuple_id);
418
419 assert_eq!(retained_ids.len(), 5);
421 assert_eq!(registry.types.len(), 5);
422
423 let new_tuple_id = *retained_ids
425 .get(&tuple_id)
426 .expect("tuple should have been retained");
427 let registry_ty = registry
428 .types
429 .get(new_tuple_id as usize)
430 .expect("tuple should exist");
431
432 assert_eq!(registry_ty.id, new_tuple_id);
433
434 let tup = match ®istry_ty.ty.type_def {
436 TypeDef::Tuple(t) => t,
437 def => panic!("Expected an tuple type, got {def:?}"),
438 };
439
440 assert!(matches!(
442 registry.resolve(tup.fields[0].id).unwrap().type_def,
443 TypeDef::Primitive(TypeDefPrimitive::U32)
444 ));
445 assert!(matches!(
446 registry.resolve(tup.fields[1].id).unwrap().type_def,
447 TypeDef::Array(_)
448 ));
449 assert!(matches!(
450 registry.resolve(tup.fields[2].id).unwrap().type_def,
451 TypeDef::Primitive(TypeDefPrimitive::Bool)
452 ));
453 }
454
455 #[test]
456 fn retain_composite_type() {
457 #[derive(scale_info_derive::TypeInfo)]
458 #[allow(dead_code)]
459 struct Foo {
460 a: u32,
461 b: [u8; 32],
462 c: bool,
463 }
464
465 let (ids, mut registry) = make_registry([ty::<bool>(), ty::<Foo>(), ty::<String>()]);
466
467 assert_eq!(registry.types.len(), 6);
468
469 let struct_id = ids[1];
471 let retained_ids = registry.retain(|id| id == struct_id);
472
473 assert_eq!(retained_ids.len(), 5);
475 assert_eq!(registry.types.len(), 5);
476
477 let struct_id = *retained_ids
479 .get(&struct_id)
480 .expect("struct should have been retained");
481 let registry_ty = registry
482 .types
483 .get(struct_id as usize)
484 .expect("struct should exist");
485
486 assert_eq!(registry_ty.id, struct_id);
487
488 let struc = match ®istry_ty.ty.type_def {
490 TypeDef::Composite(s) => s,
491 def => panic!("Expected an struct type, got {def:?}"),
492 };
493
494 assert_eq!(struc.fields.len(), 3);
496 assert_eq!(struc.fields[0].name, Some("a".to_owned()));
497 assert!(matches!(
498 registry.resolve(struc.fields[0].ty.id).unwrap().type_def,
499 TypeDef::Primitive(TypeDefPrimitive::U32)
500 ));
501 assert_eq!(struc.fields[1].name, Some("b".to_owned()));
502 assert!(matches!(
503 registry.resolve(struc.fields[1].ty.id).unwrap().type_def,
504 TypeDef::Array(_)
505 ));
506 assert_eq!(struc.fields[2].name, Some("c".to_owned()));
507 assert!(matches!(
508 registry.resolve(struc.fields[2].ty.id).unwrap().type_def,
509 TypeDef::Primitive(TypeDefPrimitive::Bool)
510 ));
511 }
512
513 #[test]
514 fn retain_variant_type() {
515 #[derive(scale_info_derive::TypeInfo)]
516 #[allow(dead_code)]
517 enum Foo {
518 A(u32),
519 B(bool),
520 }
521
522 let (ids, mut registry) = make_registry([ty::<bool>(), ty::<Foo>(), ty::<String>()]);
523
524 assert_eq!(registry.types.len(), 4);
525
526 let variant_id = ids[1];
528 let retained_ids = registry.retain(|id| id == variant_id);
529
530 assert_eq!(retained_ids.len(), 3);
532 assert_eq!(registry.types.len(), 3);
533
534 let variant_id = *retained_ids
536 .get(&variant_id)
537 .expect("variant should have been retained");
538 let registry_ty = registry
539 .types
540 .get(variant_id as usize)
541 .expect("variant should exist");
542
543 assert_eq!(registry_ty.id, variant_id);
544
545 let var = match ®istry_ty.ty.type_def {
547 TypeDef::Variant(v) => v,
548 def => panic!("Expected a variant type, got {def:?}"),
549 };
550
551 assert_eq!(var.variants.len(), 2);
552 assert_eq!(var.variants[0].name, "A".to_owned());
553 assert_eq!(var.variants[0].fields.len(), 1);
554 assert!(matches!(
555 registry
556 .resolve(var.variants[0].fields[0].ty.id)
557 .unwrap()
558 .type_def,
559 TypeDef::Primitive(TypeDefPrimitive::U32)
560 ));
561
562 assert_eq!(var.variants[1].name, "B".to_owned());
563 assert_eq!(var.variants[1].fields.len(), 1);
564 assert!(matches!(
565 registry
566 .resolve(var.variants[1].fields[0].ty.id)
567 .unwrap()
568 .type_def,
569 TypeDef::Primitive(TypeDefPrimitive::Bool)
570 ));
571 }
572
573 #[test]
574 fn retain_compact_type() {
575 let (ids, mut registry) =
576 make_registry([ty::<bool>(), ty::<String>(), ty::<Compact<u32>>()]);
577
578 assert_eq!(registry.types.len(), 4);
579
580 let compact_id = ids[2];
582 let retained_ids = registry.retain(|id| id == compact_id);
583
584 assert_eq!(retained_ids.len(), 2);
585 assert_eq!(registry.types.len(), 2);
586
587 let compact_id = *retained_ids
589 .get(&compact_id)
590 .expect("compact should have been retained");
591 let registry_ty = registry
592 .types
593 .get(compact_id as usize)
594 .expect("compact should exist");
595
596 assert_eq!(registry_ty.id, compact_id);
597
598 let compact = match ®istry_ty.ty.type_def {
600 TypeDef::Compact(c) => c,
601 def => panic!("Expected a compact type, got {def:?}"),
602 };
603
604 assert!(matches!(
606 registry.resolve(compact.type_param.id).unwrap().type_def,
607 TypeDef::Primitive(TypeDefPrimitive::U32)
608 ));
609 }
610
611 #[test]
612 fn retain_bitsequence_type() {
613 let mut builder = PortableRegistryBuilder::new();
616
617 let bool_type = Type::new(Path::default(), vec![], TypeDefPrimitive::Bool, vec![]);
619 let _bool_type_id = builder.register_type(bool_type);
620
621 let u32_type = Type::new(Path::default(), vec![], TypeDefPrimitive::U32, vec![]);
622 let u32_type_id = builder.register_type(u32_type);
623
624 let u64_type = Type::new(Path::default(), vec![], TypeDefPrimitive::U64, vec![]);
625 let u64_type_id = builder.register_type(u64_type);
626
627 let bit_seq_type = Type::new(
629 Path::default(),
630 vec![],
631 TypeDefBitSequence::new_portable(u32_type_id.into(), u64_type_id.into()),
632 vec![],
633 );
634 let bit_seq_type_id = builder.register_type(bit_seq_type);
635
636 let mut registry = builder.finish();
638
639 assert_eq!(registry.types.len(), 4);
640
641 let retained_ids = registry.retain(|id| id == bit_seq_type_id);
643
644 assert_eq!(retained_ids.len(), 3);
646 assert_eq!(registry.types.len(), 3);
647
648 let bitseq_id = *retained_ids
650 .get(&bit_seq_type_id)
651 .expect("bitseq should have been retained");
652 let registry_ty = registry
653 .types
654 .get(bitseq_id as usize)
655 .expect("bitseq should exist");
656
657 assert_eq!(registry_ty.id, bitseq_id);
658
659 let bitseq = match ®istry_ty.ty.type_def {
661 TypeDef::BitSequence(b) => b,
662 def => panic!("Expected a bit sequence type, got {def:?}"),
663 };
664 assert!(matches!(
665 registry.resolve(bitseq.bit_store_type.id).unwrap().type_def,
666 TypeDef::Primitive(TypeDefPrimitive::U32)
667 ));
668 assert!(matches!(
669 registry.resolve(bitseq.bit_order_type.id).unwrap().type_def,
670 TypeDef::Primitive(TypeDefPrimitive::U64)
671 ));
672 }
673
674 #[test]
675 fn retain_recursive_type() {
676 #[derive(scale_info_derive::TypeInfo)]
677 #[allow(dead_code)]
678 enum Recursive {
679 Value(Box<Recursive>),
680 Empty,
681 }
682
683 let (ids, mut registry) = make_registry([ty::<bool>(), ty::<Recursive>(), ty::<String>()]);
684
685 assert_eq!(registry.types.len(), 3);
686
687 let variant_id = ids[1];
689 let retained_ids = registry.retain(|id| id == variant_id);
690
691 assert_eq!(retained_ids.len(), 1);
692 assert_eq!(registry.types.len(), 1);
693
694 let variant_id = *retained_ids
696 .get(&variant_id)
697 .expect("variant should have been retained");
698 let registry_ty = registry
699 .types
700 .get(variant_id as usize)
701 .expect("variant should exist");
702
703 assert_eq!(registry_ty.id, variant_id);
704
705 let var = match ®istry_ty.ty.type_def {
707 TypeDef::Variant(v) => v,
708 def => panic!("Expected a variant type, got {def:?}"),
709 };
710
711 assert_eq!(var.variants.len(), 2);
712 assert_eq!(var.variants[0].name, "Value".to_owned());
713 assert_eq!(var.variants[0].fields.len(), 1);
714 assert!(matches!(
715 registry
716 .resolve(var.variants[0].fields[0].ty.id)
717 .unwrap()
718 .type_def,
719 TypeDef::Variant(_)
720 ));
721
722 assert_eq!(var.variants[1].name, "Empty".to_owned());
723 assert_eq!(var.variants[1].fields.len(), 0);
724 }
725
726 #[test]
727 fn type_ids_are_sequential() {
728 let mut registry = Registry::new();
729 registry.register_type(&MetaType::new::<u32>());
730 registry.register_type(&MetaType::new::<bool>());
731 registry.register_type(&MetaType::new::<Option<(u32, bool)>>());
732
733 let readonly: PortableRegistry = registry.into();
734
735 assert_eq!(4, readonly.types.len());
736
737 for (expected, ty) in readonly.types.iter().enumerate() {
738 assert_eq!(expected as u32, ty.id);
739 }
740 }
741
742 #[test]
743 fn construct_portable_registry() {
744 let mut builder = PortableRegistryBuilder::new();
745 let u32_type = Type::new(Path::default(), vec![], TypeDefPrimitive::U32, vec![]);
746 let u32_type_id = builder.register_type(u32_type.clone());
747
748 let vec_u32_type = Type::new(
749 Path::default(),
750 vec![],
751 TypeDefSequence::new(u32_type_id.into()),
752 vec![],
753 );
754 let vec_u32_type_id = builder.register_type(vec_u32_type.clone());
755
756 let self_referential_type_id = builder.next_type_id();
757
758 let composite_type = Type::builder_portable()
759 .path(Path::from_segments_unchecked(["MyStruct".into()]))
760 .composite(
761 Fields::named()
762 .field_portable(|f| f.name("primitive".into()).ty(u32_type_id))
763 .field_portable(|f| f.name("vec_of_u32".into()).ty(vec_u32_type_id))
764 .field_portable(|f| {
765 f.name("self_referential".into())
766 .ty(self_referential_type_id)
767 }),
768 );
769 let composite_type_id = builder.register_type(composite_type.clone());
770
771 assert_eq!(self_referential_type_id, composite_type_id);
772
773 assert_eq!(builder.get(u32_type_id).unwrap(), &u32_type);
774 assert_eq!(builder.get(vec_u32_type_id).unwrap(), &vec_u32_type);
775 assert_eq!(builder.get(composite_type_id).unwrap(), &composite_type);
776
777 let registry = builder.finish();
778
779 assert_eq!(Some(&u32_type), registry.resolve(u32_type_id));
780 assert_eq!(Some(&vec_u32_type), registry.resolve(vec_u32_type_id));
781 assert_eq!(Some(&composite_type), registry.resolve(composite_type_id));
782 }
783}