/// Macro for generating pub enum IdentityField /// E.g. /// /// /// The fields that we use to identify the owner of an account with. Each corresponds to a field /// in the `IdentityInfo` struct. /// #[bitflags] /// #[repr(u64)] /// #[derive(Clone, Copy, PartialEq, Eq, RuntimeDebug)] /// pub enum IdentityField { /// Display, /// FirstName, /// LastName, /// Email, /// Address, /// TelephoneNumber, /// Bio, /// } #[macro_export] macro_rules! generate_identity_field_enum { ($($variant:ident),* $(,)?) => { #[bitflags] #[repr(u64)] #[derive(Clone, Copy, PartialEq, Eq, RuntimeDebug)] pub enum IdentityField { $( $variant, )* } } } /// Macro for generating impl TypeInfo for IdentityField /// E.g. /// /// use scale_info::{build::Variants, Path, Type, TypeInfo}; /// /// impl TypeInfo for IdentityField { /// type Identity = Self; /// /// fn type_info() -> scale_info::Type { /// Type::builder() /// .path(Path::new("IdentityField", module_path!())) /// .variant( /// Variants::new() /// .variant("Display", |v| v.index(0)) /// .variant("FirstName", |v| v.index(1)) /// .variant("LastName", |v| v.index(2)) /// .variant("Email", |v| v.index(3)) /// .variant("Address", |v| v.index(4)) /// .variant("TelephoneNumber", |v| v.index(5)) /// .variant("Bio", |v| v.index(6)), /// ) /// } /// } #[macro_export] macro_rules! generate_type_info { ($name:ident, $variants:expr) => { impl TypeInfo for $name { type Identity = Self; fn type_info() -> scale_info::Type { scale_info::Type::builder() .path(scale_info::Path::new(stringify!($name), module_path!())) .type_params(vec![]) .variant($variants.iter().enumerate().fold( scale_info::build::Variants::new(), |variants, (index, variant)| { variants.variant(*variant, |v| v.index(index as u8)) }, )) } } }; } /// Macro to generate the `impl` block for `IdentityInformationProvider` for `IdentityInfo`. /// /// Parameters: /// - `$type_name`: The name of the struct (e.g., `IdentityInfo`). /// - `$field_limit`: The generic parameter for field limit (e.g., `FieldLimit`). /// - `$fields`: A list of tuples containing field names and their associated data lengths. /// /// Usage: /// ```rust /// generate_identity_information_provider_impl!( /// IdentityInfo, /// FieldLimit, /// (display, DEFAULT_DATA_MAX_LENGTH), /// (first_name, DEFAULT_DATA_MAX_LENGTH), /// (last_name, DEFAULT_DATA_MAX_LENGTH), /// (email, DEFAULT_DATA_MAX_LENGTH), /// (address, DEFAULT_DATA_MAX_LENGTH), /// (telephone_number, DEFAULT_DATA_MAX_LENGTH), /// (bio, BIO_DATA_MAX_LENGTH) /// ); /// ``` /// E.g. /// /// /// impl + 'static> IdentityInformationProvider for IdentityInfo { /// type FieldsIdentifier = u64; /// /// fn has_identity(&self, fields: Self::FieldsIdentifier) -> bool { /// self.fields().bits() & fields == fields /// } /// /// #[cfg(feature = "runtime-benchmarks")] /// fn create_identity_info() -> Self { /// let data = Data::Raw(vec![0; DEFAULT_DATA_MAX_LENGTH].try_into().unwrap()); /// let bio_data = Data::Raw(vec![0; BIO_DATA_MAX_LENGTH].try_into().unwrap()); /// /// IdentityInfo { /// additional: vec![(data.clone(), data.clone()); FieldLimit::get().try_into().unwrap()] /// .try_into() /// .unwrap(), /// display: data.clone(), /// first_name: data.clone(), /// last_name: data.clone(), /// email: data.clone(), /// address: data.clone(), /// telephone_number: data.clone(), /// bio: bio_data.clone(), /// } /// } /// /// #[cfg(feature = "runtime-benchmarks")] /// fn all_fields() -> Self::FieldsIdentifier { /// IdentityField::all().bits() /// } /// } #[macro_export] macro_rules! generate_identity_information_provider_impl { ($type_name:ident, $field_limit:ident, $(($field_name:ident, $data_length:expr)),* $(,)?) => { impl<$field_limit: Get + 'static> IdentityInformationProvider for $type_name<$field_limit> { type FieldsIdentifier = u64; fn has_identity(&self, fields: Self::FieldsIdentifier) -> bool { self.fields().bits() & fields == fields } #[cfg(feature = "runtime-benchmarks")] fn create_identity_info() -> Self { $( let $field_name = { let data_length = $data_length; Data::Raw(vec![0; data_length].try_into().unwrap()) }; )* $type_name { additional: vec![ ( Data::Raw(vec![0; DEFAULT_DATA_MAX_LENGTH].try_into().unwrap()), Data::Raw(vec![0; DEFAULT_DATA_MAX_LENGTH].try_into().unwrap()) ); $field_limit::get() as usize ] .try_into() .unwrap(), $( $field_name: $field_name.clone(), )* } } #[cfg(feature = "runtime-benchmarks")] fn all_fields() -> Self::FieldsIdentifier { IdentityField::all().bits() } } }; } /// Macro for generating impl> Default for IdentityInfo /// E.g. /// /// impl> Default for IdentityInfo { /// fn default() -> Self { /// IdentityInfo { /// additional: BoundedVec::default(), /// display: Data::None, /// first_name: Data::None, /// last_name: Data::None, /// email: Data::None, /// address: Data::None, /// telephone_number: Data::None, /// bio: Data::None, /// } /// } /// } #[macro_export] macro_rules! generate_identity_info_default_impl { ($(($field_name:ident, $default_value:expr)),*) => { impl> Default for IdentityInfo { fn default() -> Self { IdentityInfo { $( $field_name: $default_value, )* } } } }; } /// Macro for generating impl> IdentityInfo /// E.g. /// /// impl> IdentityInfo { /// pub(crate) fn fields(&self) -> BitFlags { /// let mut res = >::empty(); /// if !self.display.is_none() { /// res.insert(IdentityField::Display); /// } /// if !self.first_name.is_none() { /// res.insert(IdentityField::FirstName); /// } /// if !self.last_name.is_none() { /// res.insert(IdentityField::LastName); /// } /// if !self.email.is_none() { /// res.insert(IdentityField::Email); /// } /// if !self.address.is_none() { /// res.insert(IdentityField::Address); /// } /// if !self.telephone_number.is_none() { /// res.insert(IdentityField::TelephoneNumber); /// } /// if !self.bio.is_none() { /// res.insert(IdentityField::Bio); /// } /// res /// } /// } #[macro_export] macro_rules! generate_identity_info_impl { ($(($field_name:ident, $variant_name:ident)),*) => { impl> IdentityInfo { pub(crate) fn fields(&self) -> BitFlags { let mut res = >::empty(); $( if !self.$field_name.is_none() { res.insert(IdentityField::$variant_name); } )* res } } }; } // combined #[macro_export] macro_rules! generate_identity_field_enum_and_type_info { ($($variant:ident),+ $(,)?) => { generate_identity_field_enum!( $($variant),+ ); generate_type_info!( IdentityField, vec![ $(stringify!($variant)),+ ] ); } } #[macro_export] macro_rules! generate_identity_info_impls { ( $struct_name:ident, $field_limit:ident, $(($variant_name:ident, $field_name:ident, $max_length:expr)),+ $(,)? ) => { generate_identity_information_provider_impl!( $struct_name, $field_limit, $(($field_name, $max_length)),+ ); generate_identity_info_default_impl!( (additional, BoundedVec::default()), $(($field_name, Data::None)),+ ); generate_identity_info_impl!( $(($field_name, $variant_name)),+ ); } }