From ce21de5ef09c413161293422738172887e9ec639 Mon Sep 17 00:00:00 2001 From: Alexandru Vasile <60601340+lexnv@users.noreply.github.com> Date: Tue, 21 Mar 2023 16:50:03 +0200 Subject: [PATCH] portable: Retain the provided type IDs (#174) * ty: Make type fields public Signed-off-by: Alexandru Vasile * portable: Add recursive type ID resolver Signed-off-by: Alexandru Vasile * tests: Check recursive type ID correctness Signed-off-by: Alexandru Vasile * portable: Implement `retain` on the `PortableRegistry` Signed-off-by: Alexandru Vasile * tests: Check `retain` method Signed-off-by: Alexandru Vasile * portable: Add error type Signed-off-by: Alexandru Vasile * derive: Fix clippy and improve documentation Signed-off-by: Alexandru Vasile * Fix clippy Signed-off-by: Alexandru Vasile * rustfmt: Change deprecated fmt Signed-off-by: Alexandru Vasile * portable: Ensure no-std works Signed-off-by: Alexandru Vasile * test_suite: Adjust UI tests to latest Signed-off-by: Alexandru Vasile * Adjust UI tests with nightly Signed-off-by: Alexandru Vasile * portable: Remove AtomicU32 Signed-off-by: Alexandru Vasile * portable: Use DFS for recursive ID assignment Signed-off-by: Alexandru Vasile * ty: Implement zero-alloc Default::default() for Type Signed-off-by: Alexandru Vasile * portable: Change `retain` signature with FnMut Signed-off-by: Alexandru Vasile * portable/tests: Apply clippy Signed-off-by: Alexandru Vasile * git: Use clippy with `--all-targets` Signed-off-by: Alexandru Vasile * ty: Make fields public to this crate `pub(crate)` only Signed-off-by: Alexandru Vasile * portable: Use `mem` from `prelude` and not from `std` Signed-off-by: Alexandru Vasile * retain * portable: Modify docs and apply fmt Signed-off-by: Alexandru Vasile * portable/test: Check result BTreeMap Signed-off-by: Alexandru Vasile * Fix cargo check Signed-off-by: Alexandru Vasile * tests: Recursive retain for all type-def types Signed-off-by: Alexandru Vasile * ty: Use placeholder instead of implementing dummy Default::default() Signed-off-by: Alexandru Vasile * portable: use crate::prelude::vec![] insted of vec![] Signed-off-by: Alexandru Vasile * Update src/portable.rs Co-authored-by: James Wilson * portable: Fix clippy Signed-off-by: Alexandru Vasile * Update src/portable.rs Co-authored-by: Andrew Jones --------- Signed-off-by: Alexandru Vasile Co-authored-by: James Wilson Co-authored-by: Andrew Jones --- .github/workflows/rust.yml | 2 +- .rustfmt.toml | 2 +- derive/src/trait_bounds.rs | 2 +- src/portable.rs | 559 ++++++++++++++++++ src/ty/composite.rs | 2 +- src/ty/fields.rs | 8 +- src/ty/mod.rs | 26 +- src/ty/variant.rs | 2 +- src/utils.rs | 11 +- .../tests/ui/fail_missing_derive.stderr | 4 +- 10 files changed, 588 insertions(+), 30 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index d88de063..b875a59a 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -31,7 +31,7 @@ jobs: - name: clippy run: | cargo clippy --version - cargo clippy --all -- -D warnings + cargo clippy --all-targets -- -D warnings - name: check-all-features run: | diff --git a/.rustfmt.toml b/.rustfmt.toml index 536703e6..33407627 100644 --- a/.rustfmt.toml +++ b/.rustfmt.toml @@ -34,7 +34,7 @@ struct_field_align_threshold = 0 enum_discrim_align_threshold = 0 match_arm_blocks = true force_multiline_blocks = true # changed -fn_args_layout = "Tall" +fn_params_layout = "Tall" brace_style = "SameLineWhere" control_brace_style = "AlwaysSameLine" trailing_semicolon = false # changed diff --git a/derive/src/trait_bounds.rs b/derive/src/trait_bounds.rs index 08fb1ec0..da28f486 100644 --- a/derive/src/trait_bounds.rs +++ b/derive/src/trait_bounds.rs @@ -104,7 +104,7 @@ pub fn make_where_clause<'a>( } }); - generics.type_params().into_iter().for_each(|type_param| { + generics.type_params().for_each(|type_param| { let ident = type_param.ident.clone(); let mut bounds = type_param.bounds.clone(); if attrs diff --git a/src/portable.rs b/src/portable.rs index 96978bf2..74aae9e0 100644 --- a/src/portable.rs +++ b/src/portable.rs @@ -27,11 +27,16 @@ use crate::{ form::PortableForm, interner::Interner, prelude::{ + collections::BTreeMap, fmt::Debug, + mem, vec::Vec, }, + Path, Registry, Type, + TypeDef, + TypeDefPrimitive, }; use scale::Encode; @@ -70,6 +75,158 @@ impl PortableRegistry { pub fn types(&self) -> &[PortableType] { &self.types } + + /// Retains only the portable types needed to express the provided ids. + /// + /// The type IDs retained are returned as key to the [`BTreeMap`]. + /// The value of the map represents the new ID of that type. + /// + /// # Note + /// + /// A given type ID can be defined by nesting type IDs, such as the case + /// of a [`TypeDef::Composite`] and others. To retain a valid [`PortableRegistry`] + /// all the types needed to express an ID are included. Therefore, the number of + /// elements defined by the result equals or exceeds the number of provided IDs. + pub fn retain(&mut self, mut filter: F) -> BTreeMap + where + F: FnMut(u32) -> bool, + { + let mut retained_mappings = BTreeMap::new(); + let mut new_types = crate::prelude::vec![]; + + fn retain_type( + id: u32, + types: &mut [PortableType], + new_types: &mut Vec, + retained_mappings: &mut BTreeMap, + ) -> u32 { + // Type already retained; just return the new ID for it: + if let Some(id) = retained_mappings.get(&id) { + return *id + } + + // Zero-allocation default implementation that is used as + // a placeholder and never accessed. + let placeholder = PortableType { + id: 0, + ty: Type { + type_def: TypeDef::Primitive(TypeDefPrimitive::Bool), + path: Path::default(), + type_params: crate::prelude::vec![], + docs: crate::prelude::vec![], + }, + }; + // Take the type out of the registry that we'll be retaining: + let mut ty = mem::replace(&mut types[id as usize], placeholder); + + // Make sure any type params are also retained: + for param in ty.ty.type_params.iter_mut() { + let Some(ty) = param.ty() else { + continue + }; + let new_id = retain_type(ty.id(), types, new_types, retained_mappings); + param.ty = Some(new_id).map(Into::into); + } + + // make sure any types inside this type are also retained and update the IDs: + match &mut ty.ty.type_def { + TypeDef::Composite(composite) => { + for field in composite.fields.iter_mut() { + let new_id = retain_type( + field.ty.id(), + types, + new_types, + retained_mappings, + ); + field.ty = new_id.into(); + } + } + TypeDef::Variant(variant) => { + for var in variant.variants.iter_mut() { + for field in var.fields.iter_mut() { + let new_id = retain_type( + field.ty.id(), + types, + new_types, + retained_mappings, + ); + field.ty = new_id.into(); + } + } + } + TypeDef::Sequence(sequence) => { + let new_id = retain_type( + sequence.type_param.id(), + types, + new_types, + retained_mappings, + ); + sequence.type_param = new_id.into(); + } + TypeDef::Array(array) => { + let new_id = retain_type( + array.type_param.id(), + types, + new_types, + retained_mappings, + ); + array.type_param = new_id.into(); + } + TypeDef::Tuple(tuple) => { + for ty in tuple.fields.iter_mut() { + let new_id = + retain_type(ty.id(), types, new_types, retained_mappings); + *ty = new_id.into(); + } + } + TypeDef::Primitive(_) => (), + TypeDef::Compact(compact) => { + let new_id = retain_type( + compact.type_param().id(), + types, + new_types, + retained_mappings, + ); + compact.type_param = new_id.into(); + } + TypeDef::BitSequence(bit_seq) => { + let bit_store_id = retain_type( + bit_seq.bit_store_type().id(), + types, + new_types, + retained_mappings, + ); + let bit_order_id = retain_type( + bit_seq.bit_order_type().id(), + types, + new_types, + retained_mappings, + ); + + bit_seq.bit_store_type = bit_store_id.into(); + bit_seq.bit_order_type = bit_order_id.into(); + } + } + + // Retain this type, having updated any inner IDs: + let new_id = new_types.len() as u32; + new_types.push(ty); + retained_mappings.insert(id, new_id); + new_id + } + + for id in 0..self.types.len() as u32 { + // We don't care about the type; move on: + if !filter(id) { + continue + } + + retain_type(id, &mut self.types, &mut new_types, &mut retained_mappings); + } + + self.types = new_types; + retained_mappings + } } /// Represent a type in it's portable form. @@ -161,6 +318,311 @@ mod tests { *, }; + // Type IDs generated by `build_registry`. + const U32_TY_ID: u32 = 0; + const U64_TY_ID: u32 = 1; + const VEC_U32_TY_ID: u32 = 2; + const ARRAY_U32_TY_ID: u32 = 3; + const TUPLE_TY_ID: u32 = 4; + const COMPACT_TY_ID: u32 = 5; + const BIT_SEQ_TY_ID: u32 = 6; + const COMPOSITE_TY_ID: u32 = 7; + const VARIANT_TY_ID: u32 = 8; + + fn build_registry() -> PortableRegistry { + let mut builder = PortableRegistryBuilder::new(); + // Primitives + let u32_type = Type::new(Path::default(), vec![], TypeDefPrimitive::U32, vec![]); + let u32_type_id = builder.register_type(u32_type); + assert_eq!(U32_TY_ID, u32_type_id); + + let u64_type = Type::new(Path::default(), vec![], TypeDefPrimitive::U64, vec![]); + let u64_type_id = builder.register_type(u64_type); + assert_eq!(U64_TY_ID, u64_type_id); + + // Sequence + let vec_u32_type = Type::new( + Path::default(), + vec![], + TypeDefSequence::new(u32_type_id.into()), + vec![], + ); + let vec_u32_type_id = builder.register_type(vec_u32_type); + assert_eq!(VEC_U32_TY_ID, vec_u32_type_id); + + // Array + let array_u32_type = Type::new( + Path::default(), + vec![], + TypeDefArray::new(3, u32_type_id.into()), + vec![], + ); + let array_u32_type_id = builder.register_type(array_u32_type); + assert_eq!(ARRAY_U32_TY_ID, array_u32_type_id); + + // Tuple + let tuple_type = Type::new( + Path::default(), + vec![], + TypeDefTuple::new_portable(vec![u32_type_id.into(), u64_type_id.into()]), + vec![], + ); + let tuple_type_id = builder.register_type(tuple_type); + assert_eq!(TUPLE_TY_ID, tuple_type_id); + + // Compact + let compact_type = Type::new( + Path::default(), + vec![], + TypeDefCompact::new(tuple_type_id.into()), + vec![], + ); + let compact_type_id = builder.register_type(compact_type); + assert_eq!(COMPACT_TY_ID, compact_type_id); + + // BitSequence + let bit_seq_type = Type::new( + Path::default(), + vec![], + TypeDefBitSequence::new_portable(u32_type_id.into(), u64_type_id.into()), + vec![], + ); + let bit_seq_type_id = builder.register_type(bit_seq_type); + assert_eq!(BIT_SEQ_TY_ID, bit_seq_type_id); + + // Composite + let composite_type = Type::builder_portable() + .path(Path::from_segments_unchecked(["MyStruct".into()])) + .composite( + Fields::named() + .field_portable(|f| f.name("primitive".into()).ty(u32_type_id)) + .field_portable(|f| f.name("vec_of_u32".into()).ty(vec_u32_type_id)), + ); + let composite_type_id = builder.register_type(composite_type); + assert_eq!(COMPOSITE_TY_ID, composite_type_id); + + // Variant + let enum_type = Type::builder_portable() + .path(Path::from_segments_unchecked(["MyEnum".into()])) + .variant( + Variants::new() + .variant("A".into(), |v| { + v.index(0).fields( + Fields::::named() + .field_portable(|f| { + f.name("primitive".into()).ty(u32_type_id) + }) + .field_portable(|f| { + f.name("vec_of_u32".into()).ty(vec_u32_type_id) + }), + ) + }) + .variant_unit("B".into(), 1), + ); + let enum_type_id = builder.register_type(enum_type); + assert_eq!(VARIANT_TY_ID, enum_type_id); + + builder.finish() + } + + #[test] + fn retain_recursive_seq() { + let mut registry = build_registry(); + + let ids_result = registry.retain(|id| id == VEC_U32_TY_ID); + assert_eq!(ids_result.len(), 2); + assert_eq!(ids_result.get(&U32_TY_ID), Some(&0)); + assert_eq!(ids_result.get(&VEC_U32_TY_ID), Some(&1)); + + assert_eq!(registry.types.len(), 2); + let expected_ty = + Type::new(Path::default(), vec![], TypeDefPrimitive::U32, vec![]); + assert_eq!(registry.resolve(0).unwrap(), &expected_ty); + let expected_ty = Type::new( + Path::default(), + vec![], + TypeDefSequence::new(0.into()), + vec![], + ); + assert_eq!(registry.resolve(1).unwrap(), &expected_ty); + } + + #[test] + fn retain_recursive_array() { + let mut registry = build_registry(); + + let ids_result = registry.retain(|id| id == ARRAY_U32_TY_ID); + assert_eq!(ids_result.len(), 2); + assert_eq!(ids_result.get(&U32_TY_ID), Some(&0)); + assert_eq!(ids_result.get(&ARRAY_U32_TY_ID), Some(&1)); + + assert_eq!(registry.types.len(), 2); + let expected_ty = + Type::new(Path::default(), vec![], TypeDefPrimitive::U32, vec![]); + assert_eq!(registry.resolve(0).unwrap(), &expected_ty); + let expected_ty = Type::new( + Path::default(), + vec![], + TypeDefArray::new(3, 0.into()), + vec![], + ); + assert_eq!(registry.resolve(1).unwrap(), &expected_ty); + } + + #[test] + fn retain_recursive_tuple() { + let mut registry = build_registry(); + + let ids_result = registry.retain(|id| id == TUPLE_TY_ID); + assert_eq!(ids_result.len(), 3); + assert_eq!(ids_result.get(&U32_TY_ID), Some(&0)); + assert_eq!(ids_result.get(&U64_TY_ID), Some(&1)); + assert_eq!(ids_result.get(&TUPLE_TY_ID), Some(&2)); + + assert_eq!(registry.types.len(), 3); + let expected_ty = + Type::new(Path::default(), vec![], TypeDefPrimitive::U32, vec![]); + assert_eq!(registry.resolve(0).unwrap(), &expected_ty); + let expected_ty = + Type::new(Path::default(), vec![], TypeDefPrimitive::U64, vec![]); + assert_eq!(registry.resolve(1).unwrap(), &expected_ty); + let expected_ty = Type::new( + Path::default(), + vec![], + TypeDefTuple::new_portable(vec![0.into(), 1.into()]), + vec![], + ); + assert_eq!(registry.resolve(2).unwrap(), &expected_ty); + } + + #[test] + fn retain_recursive_compact() { + let mut registry = build_registry(); + + let ids_result = registry.retain(|id| id == COMPACT_TY_ID); + assert_eq!(ids_result.len(), 4); + assert_eq!(ids_result.get(&U32_TY_ID), Some(&0)); + assert_eq!(ids_result.get(&U64_TY_ID), Some(&1)); + assert_eq!(ids_result.get(&TUPLE_TY_ID), Some(&2)); + assert_eq!(ids_result.get(&COMPACT_TY_ID), Some(&3)); + + assert_eq!(registry.types.len(), 4); + let expected_ty = + Type::new(Path::default(), vec![], TypeDefPrimitive::U32, vec![]); + assert_eq!(registry.resolve(0).unwrap(), &expected_ty); + let expected_ty = + Type::new(Path::default(), vec![], TypeDefPrimitive::U64, vec![]); + assert_eq!(registry.resolve(1).unwrap(), &expected_ty); + let expected_ty = Type::new( + Path::default(), + vec![], + TypeDefTuple::new_portable(vec![0.into(), 1.into()]), + vec![], + ); + assert_eq!(registry.resolve(2).unwrap(), &expected_ty); + let expected_ty = Type::new( + Path::default(), + vec![], + TypeDefCompact::new(2.into()), + vec![], + ); + assert_eq!(registry.resolve(3).unwrap(), &expected_ty); + } + + #[test] + fn retain_recursive_bit_seq() { + let mut registry = build_registry(); + + let ids_result = registry.retain(|id| id == BIT_SEQ_TY_ID); + assert_eq!(ids_result.len(), 3); + assert_eq!(ids_result.get(&U32_TY_ID), Some(&0)); + assert_eq!(ids_result.get(&U64_TY_ID), Some(&1)); + assert_eq!(ids_result.get(&BIT_SEQ_TY_ID), Some(&2)); + + assert_eq!(registry.types.len(), 3); + let expected_ty = + Type::new(Path::default(), vec![], TypeDefPrimitive::U32, vec![]); + assert_eq!(registry.resolve(0).unwrap(), &expected_ty); + let expected_ty = + Type::new(Path::default(), vec![], TypeDefPrimitive::U64, vec![]); + assert_eq!(registry.resolve(1).unwrap(), &expected_ty); + let expected_ty = Type::new( + Path::default(), + vec![], + TypeDefBitSequence::new_portable(0.into(), 1.into()), + vec![], + ); + assert_eq!(registry.resolve(2).unwrap(), &expected_ty); + } + + #[test] + fn retain_recursive_composite() { + let mut registry = build_registry(); + + let ids_result = registry.retain(|id| id == COMPOSITE_TY_ID); + assert_eq!(ids_result.len(), 3); + assert_eq!(ids_result.get(&U32_TY_ID), Some(&0)); + assert_eq!(ids_result.get(&VEC_U32_TY_ID), Some(&1)); + assert_eq!(ids_result.get(&COMPOSITE_TY_ID), Some(&2)); + + assert_eq!(registry.types.len(), 3); + let expected_ty = + Type::new(Path::default(), vec![], TypeDefPrimitive::U32, vec![]); + assert_eq!(registry.resolve(0).unwrap(), &expected_ty); + let expected_ty = Type::new( + Path::default(), + vec![], + TypeDefSequence::new(0.into()), + vec![], + ); + assert_eq!(registry.resolve(1).unwrap(), &expected_ty); + let expected_ty = Type::builder_portable() + .path(Path::from_segments_unchecked(["MyStruct".into()])) + .composite( + Fields::named() + .field_portable(|f| f.name("primitive".into()).ty(0)) + .field_portable(|f| f.name("vec_of_u32".into()).ty(1)), + ); + assert_eq!(registry.resolve(2).unwrap(), &expected_ty); + } + + #[test] + fn retain_recursive_variant() { + let mut registry = build_registry(); + + let ids_result = registry.retain(|id| id == VARIANT_TY_ID); + assert_eq!(ids_result.len(), 3); + assert_eq!(ids_result.get(&U32_TY_ID), Some(&0)); + assert_eq!(ids_result.get(&VEC_U32_TY_ID), Some(&1)); + assert_eq!(ids_result.get(&VARIANT_TY_ID), Some(&2)); + + assert_eq!(registry.types.len(), 3); + let expected_ty = + Type::new(Path::default(), vec![], TypeDefPrimitive::U32, vec![]); + assert_eq!(registry.resolve(0).unwrap(), &expected_ty); + let expected_ty = Type::new( + Path::default(), + vec![], + TypeDefSequence::new(0.into()), + vec![], + ); + assert_eq!(registry.resolve(1).unwrap(), &expected_ty); + let expected_ty = Type::builder_portable() + .path(Path::from_segments_unchecked(["MyEnum".into()])) + .variant( + Variants::new() + .variant("A".into(), |v| { + v.index(0).fields( + Fields::::named() + .field_portable(|f| f.name("primitive".into()).ty(0)) + .field_portable(|f| f.name("vec_of_u32".into()).ty(1)), + ) + }) + .variant_unit("B".into(), 1), + ); + assert_eq!(registry.resolve(2).unwrap(), &expected_ty); + } + #[test] fn type_ids_are_sequential() { let mut registry = Registry::new(); @@ -218,4 +680,101 @@ mod tests { assert_eq!(Some(&vec_u32_type), registry.resolve(vec_u32_type_id)); assert_eq!(Some(&composite_type), registry.resolve(composite_type_id)); } + + #[test] + fn retain_ids() { + let mut builder = PortableRegistryBuilder::new(); + let u32_type = Type::new(Path::default(), vec![], TypeDefPrimitive::U32, vec![]); + let _u32_type_id = builder.register_type(u32_type); + + let u64_type = Type::new(Path::default(), vec![], TypeDefPrimitive::U64, vec![]); + let u64_type_id = builder.register_type(u64_type.clone()); + + let mut registry = builder.finish(); + assert_eq!(registry.types.len(), 2); + + let ids_result = registry.retain(|id| id == u64_type_id); + assert_eq!(ids_result.len(), 1); + assert_eq!(ids_result.get(&u64_type_id), Some(&0)); + + assert_eq!(registry.types.len(), 1); + assert_eq!(registry.resolve(0).unwrap(), &u64_type); + } + + #[test] + fn retain_recursive_ids() { + let mut builder = PortableRegistryBuilder::new(); + let u32_type = Type::new(Path::default(), vec![], TypeDefPrimitive::U32, vec![]); + let u32_type_id = builder.register_type(u32_type.clone()); + + let u64_type = Type::new(Path::default(), vec![], TypeDefPrimitive::U64, vec![]); + let _u64_type_id = builder.register_type(u64_type); + + let vec_u32_type = Type::new( + Path::default(), + vec![], + TypeDefSequence::new(u32_type_id.into()), + vec![], + ); + let vec_u32_type_id = builder.register_type(vec_u32_type); + + let composite_type = Type::builder_portable() + .path(Path::from_segments_unchecked(["MyStruct".into()])) + .composite( + Fields::named() + .field_portable(|f| f.name("primitive".into()).ty(u32_type_id)) + .field_portable(|f| f.name("vec_of_u32".into()).ty(vec_u32_type_id)), + ); + let composite_type_id = builder.register_type(composite_type); + + let composite_type_second = Type::builder_portable() + .path(Path::from_segments_unchecked(["MyStructSecond".into()])) + .composite( + Fields::named() + .field_portable(|f| f.name("vec_of_u32".into()).ty(vec_u32_type_id)) + .field_portable(|f| f.name("second".into()).ty(composite_type_id)), + ); + let composite_type_second_id = builder.register_type(composite_type_second); + + let mut registry = builder.finish(); + assert_eq!(registry.types.len(), 5); + + let ids_result = registry.retain(|id| id == composite_type_second_id); + assert_eq!(ids_result.len(), 4); + assert_eq!(ids_result.get(&u32_type_id), Some(&0)); + assert_eq!(ids_result.get(&vec_u32_type_id), Some(&1)); + assert_eq!(ids_result.get(&composite_type_id), Some(&2)); + assert_eq!(ids_result.get(&composite_type_second_id), Some(&3)); + + assert_eq!(registry.types.len(), 4); + + // New type IDs are generated in DFS manner. + assert_eq!(registry.resolve(0).unwrap(), &u32_type); + + let expected_type = Type::new( + Path::default(), + vec![], + TypeDefSequence::new(0.into()), + vec![], + ); + assert_eq!(registry.resolve(1).unwrap(), &expected_type); + + let expected_type = Type::builder_portable() + .path(Path::from_segments_unchecked(["MyStruct".into()])) + .composite( + Fields::named() + .field_portable(|f| f.name("primitive".into()).ty(0)) + .field_portable(|f| f.name("vec_of_u32".into()).ty(1)), + ); + assert_eq!(registry.resolve(2).unwrap(), &expected_type); + + let expected_type = Type::builder_portable() + .path(Path::from_segments_unchecked(["MyStructSecond".into()])) + .composite( + Fields::named() + .field_portable(|f| f.name("vec_of_u32".into()).ty(1)) + .field_portable(|f| f.name("second".into()).ty(2)), + ); + assert_eq!(registry.resolve(3).unwrap(), &expected_type); + } } diff --git a/src/ty/composite.rs b/src/ty/composite.rs index faeaef68..26d8852a 100644 --- a/src/ty/composite.rs +++ b/src/ty/composite.rs @@ -76,7 +76,7 @@ pub struct TypeDefComposite { feature = "serde", serde(skip_serializing_if = "Vec::is_empty", default) )] - fields: Vec>, + pub(crate) fields: Vec>, } impl IntoPortable for TypeDefComposite { diff --git a/src/ty/fields.rs b/src/ty/fields.rs index e024a421..5d8d0029 100644 --- a/src/ty/fields.rs +++ b/src/ty/fields.rs @@ -78,22 +78,22 @@ pub struct Field { feature = "serde", serde(skip_serializing_if = "Option::is_none", default) )] - name: Option, + pub(crate) name: Option, /// The type of the field. #[cfg_attr(feature = "serde", serde(rename = "type"))] - ty: T::Type, + pub(crate) ty: T::Type, /// The name of the type of the field as it appears in the source code. #[cfg_attr( feature = "serde", serde(skip_serializing_if = "Option::is_none", default) )] - type_name: Option, + pub(crate) type_name: Option, /// Documentation #[cfg_attr( feature = "serde", serde(skip_serializing_if = "Vec::is_empty", default) )] - docs: Vec, + pub(crate) docs: Vec, } impl IntoPortable for Field { diff --git a/src/ty/mod.rs b/src/ty/mod.rs index 20215a22..56bf4c71 100644 --- a/src/ty/mod.rs +++ b/src/ty/mod.rs @@ -68,22 +68,22 @@ pub struct Type { feature = "serde", serde(skip_serializing_if = "Path::is_empty", default) )] - path: Path, + pub(crate) path: Path, /// The generic type parameters of the type in use. Empty for non generic types #[cfg_attr( feature = "serde", serde(rename = "params", skip_serializing_if = "Vec::is_empty", default) )] - type_params: Vec>, + pub(crate) type_params: Vec>, /// The actual type definition #[cfg_attr(feature = "serde", serde(rename = "def"))] - type_def: TypeDef, + pub(crate) type_def: TypeDef, /// Documentation #[cfg_attr( feature = "serde", serde(skip_serializing_if = "Vec::is_empty", default) )] - docs: Vec, + pub(crate) docs: Vec, } impl IntoPortable for Type { @@ -194,12 +194,12 @@ where #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, From, Debug, Encode)] pub struct TypeParameter { /// The name of the generic type parameter e.g. "T". - name: T::String, + pub(crate) name: T::String, /// The concrete type for the type parameter. /// /// `None` if the type parameter is skipped. #[cfg_attr(feature = "serde", serde(rename = "type"))] - ty: Option, + pub(crate) ty: Option, } impl IntoPortable for TypeParameter { @@ -400,10 +400,10 @@ pub enum TypeDefPrimitive { #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Debug)] pub struct TypeDefArray { /// The length of the array type. - len: u32, + pub(crate) len: u32, /// The element type of the array type. #[cfg_attr(feature = "serde", serde(rename = "type"))] - type_param: T::Type, + pub(crate) type_param: T::Type, } impl IntoPortable for TypeDefArray { @@ -452,7 +452,7 @@ where #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Debug)] pub struct TypeDefTuple { /// The types of the tuple fields. - fields: Vec, + pub(crate) fields: Vec, } impl IntoPortable for TypeDefTuple { @@ -514,7 +514,7 @@ where pub struct TypeDefSequence { /// The element type of the sequence type. #[cfg_attr(feature = "serde", serde(rename = "type"))] - type_param: T::Type, + pub(crate) type_param: T::Type, } impl IntoPortable for TypeDefSequence { @@ -564,7 +564,7 @@ where pub struct TypeDefCompact { /// The type wrapped in [`Compact`], i.e. the `T` in `Compact`. #[cfg_attr(feature = "serde", serde(rename = "type"))] - type_param: T::Type, + pub(crate) type_param: T::Type, } impl IntoPortable for TypeDefCompact { @@ -603,9 +603,9 @@ where #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Debug)] pub struct TypeDefBitSequence { /// The type implementing [`bitvec::store::BitStore`]. - bit_store_type: T::Type, + pub(crate) bit_store_type: T::Type, /// The type implementing [`bitvec::order::BitOrder`]. - bit_order_type: T::Type, + pub(crate) bit_order_type: T::Type, } impl IntoPortable for TypeDefBitSequence { diff --git a/src/ty/variant.rs b/src/ty/variant.rs index eb791b24..fb4944c2 100644 --- a/src/ty/variant.rs +++ b/src/ty/variant.rs @@ -88,7 +88,7 @@ pub struct TypeDefVariant { feature = "serde", serde(skip_serializing_if = "Vec::is_empty", default) )] - variants: Vec>, + pub(crate) variants: Vec>, } impl IntoPortable for TypeDefVariant { diff --git a/src/utils.rs b/src/utils.rs index 88f76cf2..ba3d54e0 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -23,14 +23,13 @@ pub fn is_rust_identifier(s: &str) -> bool { let trimmed = s.trim_start_matches("r#"); if let Some((&head, tail)) = trimmed.as_bytes().split_first() { // Check if head and tail make up a proper Rust identifier. - let head_ok = head == b'_' - || (b'a'..=b'z').contains(&head) - || (b'A'..=b'Z').contains(&head); + let head_ok = + head == b'_' || head.is_ascii_lowercase() || head.is_ascii_uppercase(); let tail_ok = tail.iter().all(|&ch| { ch == b'_' - || (b'a'..=b'z').contains(&ch) - || (b'A'..=b'Z').contains(&ch) - || (b'0'..=b'9').contains(&ch) + || ch.is_ascii_lowercase() + || ch.is_ascii_uppercase() + || ch.is_ascii_digit() }); head_ok && tail_ok } else { diff --git a/test_suite/tests/ui/fail_missing_derive.stderr b/test_suite/tests/ui/fail_missing_derive.stderr index 9207cb25..4183c20e 100644 --- a/test_suite/tests/ui/fail_missing_derive.stderr +++ b/test_suite/tests/ui/fail_missing_derive.stderr @@ -13,12 +13,12 @@ error[E0277]: the trait bound `PawType: TypeInfo` is not satisfied (A, B, C, D) (A, B, C, D, E) (A, B, C, D, E, F) - and 54 others + and $N others note: required for `Cat` to implement `TypeInfo` --> tests/ui/fail_missing_derive.rs:8:10 | 8 | #[derive(TypeInfo)] - | ^^^^^^^^ + | ^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro 9 | #[scale_info(crate = info)] 10 | struct Cat { | ^^^^^^^^^^^^^^^^^^^