diff --git a/module/core/former/tests/inc/former_tests/a_containers_with_runtime_manual.rs b/module/core/former/tests/inc/former_tests/a_containers_with_runtime_manual.rs index 0e2f2a2704..3cb0bfa769 100644 --- a/module/core/former/tests/inc/former_tests/a_containers_with_runtime_manual.rs +++ b/module/core/former/tests/inc/former_tests/a_containers_with_runtime_manual.rs @@ -9,7 +9,7 @@ pub struct Struct1 hashset_strings_1 : std::collections::HashSet< String >, } -// +// = formed impl Struct1 { @@ -19,6 +19,8 @@ impl Struct1 } } +// = storage + // generated by former pub struct Struct1FormerStorage { @@ -43,7 +45,7 @@ impl Default for Struct1FormerStorage } -// +// = former pub struct Struct1Former < diff --git a/module/core/former/tests/inc/former_tests/a_primitives_expanded.rs b/module/core/former/tests/inc/former_tests/a_primitives_expanded.rs index 1f1a5f72c4..a31c9475cd 100644 --- a/module/core/former/tests/inc/former_tests/a_primitives_expanded.rs +++ b/module/core/former/tests/inc/former_tests/a_primitives_expanded.rs @@ -1,8 +1,9 @@ #[ allow( unused_imports ) ] use super::*; -#[ derive( Debug, PartialEq, the_module::Former ) ] -#[ debug ] +#[ derive( Debug, PartialEq ) ] +// #[ derive( Debug, PartialEq, the_module::Former ) ] +// #[ debug ] pub struct Struct1 { pub int_1 : i32, @@ -11,7 +12,265 @@ pub struct Struct1 string_optional_1 : Option< String >, } -// +// = formed + +impl Struct1 +{ + #[doc = r""] + #[doc = r" Make former, variation of builder pattern to form structure defining values of fields step by step."] + #[doc = r""] + #[inline(always)] + pub fn former() -> Struct1Former<(), former::ReturnStorage> + { + Struct1Former::new() + } +} + +// = descriptor + +#[ derive( Debug ) ] +pub struct Struct1FormerDescriptor; + +impl Struct1FormerDescriptor +{ + pub fn new() -> Self + { + Self + } +} + +impl former::FormerDescriptor +for Struct1FormerDescriptor +{ + type Storage = Struct1FormerStorage; + type Formed = Struct1; +} + +// = storage + +pub struct Struct1FormerStorage +{ + #[doc = r" A field"] + pub int_1 : ::core::option::Option, + #[doc = r" A field"] + pub string_1 : ::core::option::Option, + #[doc = r" A field"] + pub int_optional_1 : core::option::Option, + #[doc = r" A field"] + pub string_optional_1 : Option, +} + +impl ::core::default::Default for Struct1FormerStorage +{ + #[inline(always)] + fn default() -> Self + { + Self + { + int_1 : ::core::option::Option::None, + string_1 : ::core::option::Option::None, + int_optional_1 : ::core::option::Option::None, + string_optional_1 : ::core::option::Option::None, + } + } +} + +impl former::Storage +for Struct1FormerStorage +{ + type Descriptor = Struct1FormerDescriptor; +} + +impl former::StoragePerform +for Struct1FormerStorage +{ + + fn preform( mut self ) -> Struct1 + { + + let int_1 = if self.int_1.is_some() + { + self.int_1.take().unwrap() + } + else + { + let val : i32 = Default::default(); + val + }; + + let string_1 = if self.string_1.is_some() + { + self.string_1.take().unwrap() + } + else + { + let val : String = Default::default(); + val + }; + + let int_optional_1 = if self.int_optional_1.is_some() + { + Some( self.int_optional_1.take().unwrap() ) + } + else + { + None + }; + + let string_optional_1 = if self.string_optional_1.is_some() + { + Some( self.string_optional_1.take().unwrap() ) + } + else + { + None + }; + + // xxx : Rust failt to use parameter here + // < < Self as former::Storage >::Descriptor as former::FormerDescriptor >::Formed + Struct1 + { + int_1, + string_1, + int_optional_1, + string_optional_1, + } + + } + +} + +// = former + +#[automatically_derived] +pub struct Struct1Former +where FormerEnd : former::FormingEnd, +{ + storage : Struct1FormerStorage, + context : core::option::Option, + on_end : core::option::Option, +} + +#[automatically_derived] +impl Struct1Former +where FormerEnd : former::FormingEnd, +{ + #[doc = r""] + #[doc = r" Finish setting options and return formed entity."] + #[doc = r""] + #[doc = r" `perform` has no effect on method `form`, but change behavior and returned type of method `perform`."] + #[doc = r""] + #[inline(always)] + pub fn preform(self) -> < Struct1FormerDescriptor as former::FormerDescriptor >::Formed + { + < Struct1FormerStorage as former::StoragePerform >::preform( self.storage ) + } + + #[doc = r""] + #[doc = r" Finish setting options and call perform on formed entity."] + #[doc = r""] + #[doc = r" If `perform` defined then associated method is called and its result returned instead of entity."] + #[doc = r" For example `perform()` of structure with : `#[ perform( fn after1() -> &str > )` returns `&str`."] + #[doc = r""] + #[inline(always)] + pub fn perform( self ) -> < Struct1FormerDescriptor as former::FormerDescriptor >::Formed + { + let result = self.form(); + return result; + } + + #[doc = r""] + #[doc = r" Begin the process of forming. Expects context of forming to return it after forming."] + #[doc = r""] + #[inline(always)] + pub fn begin(mut storage : core::option::Option, context : core::option::Option, on_end : FormerEnd,) -> Self + { + if storage.is_none() + { + storage = Some(::core::default::Default::default()); + } + Self + { + storage: storage.unwrap(), + context: context, + on_end: ::core::option::Option::Some(on_end), + } + } + + #[doc = r""] + #[doc = r" End the process of forming returning original context of forming."] + #[doc = r""] + #[inline(always)] + pub fn form( self ) -> < Struct1FormerDescriptor as former::FormerDescriptor >::Formed + { + self.end() + } + + #[doc = r""] + #[doc = r" End the process of forming returning original context of forming."] + #[doc = r""] + #[inline(always)] + pub fn end(mut self) -> < Struct1FormerDescriptor as former::FormerDescriptor >::Formed + { + let on_end = self.on_end.take().unwrap(); + let context = self.context.take(); + // let storage = self.form(); + on_end.call(self.storage, context) + } + + #[doc = "Setter for the 'int_1' field."] + #[inline] + pub fn int_1(mut self, src: Src) -> Self + where Src: ::core::convert::Into, + { + debug_assert!(self.storage.int_1.is_none()); + self.storage.int_1 = ::core::option::Option::Some(src.into()); + self + } + + #[doc = "Setter for the 'string_1' field."] + #[inline] + pub fn string_1(mut self, src: Src) -> Self + where Src: ::core::convert::Into, + { + debug_assert!(self.storage.string_1.is_none()); + self.storage.string_1 = ::core::option::Option::Some(src.into()); + self + } + + #[doc = "Setter for the 'int_optional_1' field."] + #[inline] + pub fn int_optional_1(mut self, src: Src) -> Self + where Src: ::core::convert::Into, + { + debug_assert!(self.storage.int_optional_1.is_none()); + self.storage.int_optional_1 = ::core::option::Option::Some(src.into()); + self + } + + #[doc = "Setter for the 'string_optional_1' field."] + #[inline] + pub fn string_optional_1(mut self, src: Src) -> Self + where Src: ::core::convert::Into, + { + debug_assert!(self.storage.string_optional_1.is_none()); + self.storage.string_optional_1 = ::core::option::Option::Some(src.into()); + self + } +} + +#[automatically_derived] +impl Struct1Former<(), former::ReturnStorage> +{ + #[doc = r""] + #[doc = r" Construct new instance of former with default parameters."] + #[doc = r""] + #[inline(always)] + pub fn new() -> Self + { + Self::begin(None, None, former::ReturnStorage,) + } +} // diff --git a/module/core/former/tests/inc/former_tests/a_primitives_manual.rs b/module/core/former/tests/inc/former_tests/a_primitives_manual.rs index 071c6d5aef..7462251a80 100644 --- a/module/core/former/tests/inc/former_tests/a_primitives_manual.rs +++ b/module/core/former/tests/inc/former_tests/a_primitives_manual.rs @@ -32,6 +32,7 @@ pub struct Struct1FormerStorage pub string_optional_1 : core::option::Option< String >, } +// xxx : cover by test impl Default for Struct1FormerStorage { diff --git a/module/core/former/tests/inc/mod.rs b/module/core/former/tests/inc/mod.rs index 63cd87eede..8d654b850d 100644 --- a/module/core/former/tests/inc/mod.rs +++ b/module/core/former/tests/inc/mod.rs @@ -9,7 +9,7 @@ mod former_tests mod a_primitives_manual; // mod a_primitives; - // mod a_primitives_expanded; + mod a_primitives_expanded; // mod a_containers_without_runtime_manual; // mod a_containers_without_runtime; // #[ cfg( not( feature = "no_std" ) ) ] diff --git a/module/core/former_meta/src/derive/former.rs b/module/core/former_meta/src/derive/former.rs index 38dd6c8d7d..3159903ea5 100644 --- a/module/core/former_meta/src/derive/former.rs +++ b/module/core/former_meta/src/derive/former.rs @@ -824,11 +824,14 @@ pub fn former( input : proc_macro::TokenStream ) -> Result< TokenStream > let former_name_ident = syn::Ident::new( &former_name, name_ident.span() ); let former_storage_name = format!( "{}FormerStorage", name_ident ); let former_storage_name_ident = syn::Ident::new( &former_storage_name, name_ident.span() ); + let former_descriptor_name = format!( "{}FormerDescriptor", name_ident ); + let former_descriptor_name_ident = syn::Ident::new( &former_descriptor_name, name_ident.span() ); /* generic parameters */ let generics = &ast.generics; let ( generics_impl, generics_ty, generics_where ) = generics.split_for_impl(); + // xxx : eliminate generics_params maybe let _generics_params = generics::params_names( generics ).params; let generics_params = if _generics_params.len() == 0 { @@ -847,7 +850,7 @@ pub fn former( input : proc_macro::TokenStream ) -> Result< TokenStream > extra_generics.where_clause = parse_quote! { where - __FormerEnd : former::FormingEnd< #name_ident #generics_ty, __FormerContext >, + __FormerEnd : former::FormingEnd< #former_descriptor_name_ident #generics_ty, __FormerContext >, }; // xxx : write helper to fix bug with where let generics_of_former = generics::merge( &generics, &extra_generics ); @@ -915,6 +918,8 @@ pub fn former( input : proc_macro::TokenStream ) -> Result< TokenStream > let result = qt! { + // = formed + #[ automatically_derived ] impl #generics_impl #name_ident #generics_ty #generics_where @@ -923,12 +928,34 @@ pub fn former( input : proc_macro::TokenStream ) -> Result< TokenStream > /// Make former, variation of builder pattern to form structure defining values of fields step by step. /// #[ inline( always ) ] - pub fn former() -> #former_name_ident < #generics_params #name_ident #generics_ty, former::ReturnStorage > + pub fn former() -> #former_name_ident < #generics_params (), former::ReturnStorage > { - #former_name_ident :: < #generics_params #name_ident #generics_ty, former::ReturnStorage > :: new() + #former_name_ident :: new() } } + // = descriptor + + #[ derive( Debug ) ] + pub struct #former_descriptor_name_ident #generics_impl; + + impl #generics_impl #former_descriptor_name_ident #generics_ty + { + pub fn new() -> Self + { + Self + } + } + + impl #generics_impl former::FormerDescriptor + for #former_descriptor_name_ident #generics_ty + { + type Storage = #former_storage_name_ident #generics_ty; + type Formed = #name_ident #generics_ty; + } + + // = storage + // xxx : rename to storage #[ doc = "Container of a corresponding former." ] pub struct #former_storage_name_ident #generics_ty @@ -955,6 +982,37 @@ pub fn former( input : proc_macro::TokenStream ) -> Result< TokenStream > } + impl #generics_impl former::Storage + for #former_storage_name_ident #generics_ty + #generics_where + { + // type Descriptor = Struct1FormerDescriptor; + type Descriptor = #former_descriptor_name_ident #generics_ty; + } + // generics_impl, generics_ty, generics_where + + impl former::StoragePerform + for #former_storage_name_ident #generics_ty + #generics_where + { + + fn preform( mut self ) -> #former_storage_name_ident #generics_ty + { + Self + { + #( #fields_form )* + let result = #name_ident + { + #( #fields_names, )* + }; + return result; + } + } + + } + + // = former + #[ doc = #doc_former_struct ] #[ automatically_derived ] pub struct #former_name_ident < #generics_of_former_with_defaults > @@ -974,17 +1032,17 @@ pub fn former( input : proc_macro::TokenStream ) -> Result< TokenStream > /// /// Finish setting options and return formed entity. /// - /// `perform` has no effect on method `form`, but change behavior and returned type of method `perform`. - /// #[ inline( always ) ] - pub fn preform( mut self ) -> #name_ident #generics_ty + pub fn preform( self ) -> < former_descriptor_name_ident #generics_impl as former::FormerDescriptor >::Formed + // #name_ident #generics_ty { - #( #fields_form )* - let result = #name_ident - { - #( #fields_names, )* - }; - return result; + < #former_storage_name_ident #generics_ty as former::StoragePerform >::preform( self.storage ) + // #( #fields_form )* + // let result = #name_ident + // { + // #( #fields_names, )* + // }; + // return result; } /// @@ -1027,7 +1085,7 @@ pub fn former( input : proc_macro::TokenStream ) -> Result< TokenStream > /// End the process of forming returning original context of forming. /// #[ inline( always ) ] - pub fn form( self ) -> __FormerContext + pub fn form( self ) -> < former_descriptor_name_ident #generics_impl as former::FormerDescriptor >::Formed { self.end() } @@ -1036,12 +1094,12 @@ pub fn former( input : proc_macro::TokenStream ) -> Result< TokenStream > /// End the process of forming returning original context of forming. /// #[ inline( always ) ] - pub fn end( mut self ) -> __FormerContext + pub fn end( mut self ) -> < former_descriptor_name_ident #generics_impl as former::FormerDescriptor >::Formed { let on_end = self.on_end.take().unwrap(); let context = self.context.take(); - let storage = self.form(); - on_end.call( storage, context ) + // let storage = self.form(); + on_end.call( self.storage, context ) } #( @@ -1051,7 +1109,7 @@ pub fn former( input : proc_macro::TokenStream ) -> Result< TokenStream > } #[ automatically_derived ] - impl #generics_impl #former_name_ident < #generics_params #name_ident #generics_ty, former::ReturnStorage > + impl #generics_impl #former_name_ident < #generics_params (), former::ReturnStorage > #generics_where {