diff --git a/Cargo.toml b/Cargo.toml index 9c43dba..788bc68 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,8 @@ exclude = [".github/*", ".gitignore"] [lib] proc-macro = true +[features] +no-std = [] [dependencies] syn = { version = "2.0.*" } diff --git a/README.md b/README.md index a06d093..ea84a5d 100644 --- a/README.md +++ b/README.md @@ -8,10 +8,9 @@ - Customize the name and visibility of the auto-generated constructor using `#[ctor(visibility method_name)]`. - Provide a list of names to generate multiple constructors. - Customize field behavior in the constructor with the following attributes: - - `#[ctor(default)]` - Exclude the field from the generated method and use its default value. - - `#[ctor(value(EXPRESSION))]` - Exclude the field from the generated method and use the defined expression as its default value. - - `#[ctor(method(METHOD_NAME))]` - Exclude the field from the generated method and call the defined method for its default value. - - `#[ctor(impl)]` - Change the parameter type for the generated method to `impl Into`. + - `#[ctor(default)]` - Exclude the field from the generated method and use its default value. + - `#[ctor(expr(EXPRESSION))]` - Exclude the field from the generated method and use the defined expression as its default value. + - `#[ctor(impl)]` - Change the parameter type for the generated method to `impl Into`. ## Basic Usage @@ -30,6 +29,8 @@ use derive_ctor::ctor; Annotate your struct with `#[derive(ctor)]` to automatically generate a `new` constructor: ```rust +use derive_ctor::ctor; + #[derive(ctor)] struct MyStruct { field1: i32, @@ -48,6 +49,8 @@ In the following example, three constructor methods are created: `new`, `with_de These methods all inherit their respective visibilities defined within the `#[ctor]` attribute. ```rust +use derive_ctor::ctor; + #[derive(ctor)] #[ctor(pub new, pub(crate) with_defaults, internal)] struct MyStruct { @@ -63,6 +66,8 @@ The following are the available properties that can be used with the field-attri `#[ctor(default)]` - This property excludes the annotated field from the constructor and uses its default value. ```rust +use derive_ctor::ctor; + #[derive(ctor)] struct MyStruct { field1: i32, @@ -76,6 +81,8 @@ let my_struct = MyStruct::new(100); `#[ctor(impl)]` - This property modifies the parameter type of the annotated field for the generated method converting it from `Type` -> `impl Into`. ```rust +use derive_ctor::ctor; + #[derive(ctor)] struct MyStruct { field1: i32, @@ -86,34 +93,19 @@ struct MyStruct { let my_struct = MyStruct::new(100, "Foo"); ``` -`#[ctor(value(VALUE))]` - This property excludes the annotated field from the constructor and utilizes the defined expression +`#[ctor(expr(VALUE))]` - This property excludes the annotated field from the constructor and utilizes the defined expression to generate its value. ```rust -#[derive(ctor)] -struct MyStruct { - field1: i32, - #[ctor(value(String::from("Foo")))] - field2: String -} - -let my_struct = MyStruct::new(100); // generates MyStruct { field1: 100, field2: "foo" } -``` - -`#[ctor(method(METHOD_NAME)]` - This property exludes the annotated field from the constructor and invokes the provided -method to generate its value. -```rust -fn generate_struct_value() -> String { - String::from("Foo") -} +use derive_ctor::ctor; #[derive(ctor)] struct MyStruct { field1: i32, - #[ctor(method(generate_struct_value))] + #[ctor(expr(String::from("Foo")))] field2: String } -let my_struct = MyStruct::new(100); +let my_struct = MyStruct::new(100); // generates MyStruct { field1: 100, field2: "foo" } ``` ### Advanced Configuration @@ -122,23 +114,22 @@ Field attributes can additionally be configured with a list of indices correspon value for. This allows for the creation of multiple functions with different parameter requirements. ```rust +use derive_ctor::ctor; + #[derive(ctor)] #[ctor(new, with_defaults)] struct MyStruct { - field1: i32, - #[ctor(default) = [1]] - field2: String, - #[ctor(default) = 1] // brackets can be removed if specifying only 1 index - field3: bool, - #[ctor(default) = [0, 1]] - field4: u64, - #[ctor(default)] // this is the same as specifying all indices - field5: u64 + field1: i32, + #[ctor(default = [1])] + field2: String, + #[ctor(default = 1)] // brackets can be removed if specifying only 1 index + field3: bool, + #[ctor(default = [0, 1])] + field4: u64, + #[ctor(default)] // this is the same as specifying all indices + field5: u64 } let my_struct1 = MyStruct::new(100, "Foo".to_string(), true); let my_struct2 = MyStruct::with_defaults(100); -``` - - - +``` \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 6826d7c..8e68f0f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,27 @@ -use proc_macro::TokenStream; +#![cfg_attr(feature = "no-std", no_std, doc = "Test")] +#![doc = include_str!("../README.md")] + +#[cfg(feature = "no-std")] +extern crate alloc; +#[cfg(feature = "no-std")] +use alloc::vec; +#[cfg(feature = "no-std")] +use alloc::vec::Vec; +#[cfg(feature = "no-std")] +use alloc::collections::BTreeSet as HashSet; +#[cfg(feature = "no-std")] +use alloc::string::ToString; + +#[cfg(not(feature = "no-std"))] +use std::vec; +#[cfg(not(feature = "no-std"))] +use std::vec::Vec; +#[cfg(not(feature = "no-std"))] use std::collections::HashSet; + +use proc_macro::TokenStream; + use proc_macro2::{Delimiter, Punct, Span}; use proc_macro2::Spacing::Alone; use quote::{quote, TokenStreamExt, ToTokens}; @@ -10,9 +31,11 @@ use syn::parse::ParseStream; use syn::spanned::Spanned; use syn::token::{Comma, Impl, Pub}; + + static FIELD_CONFIG_ERR_MSG: &str = "Unexpected property: \"{prop}\" (must be one of the following:\ - \"default\", \"method\", \"value\", \"impl\")"; + \"default\", \"expr\", \"impl\")"; struct CtorTypeConfiguration { definitions: Vec<(Visibility, Ident)> @@ -37,6 +60,7 @@ impl Default for CtorTypeConfiguration { /// field: i16 /// } /// ``` + #[derive(Clone)] struct FieldConfig { property: FieldConfigProperty, @@ -47,8 +71,7 @@ struct FieldConfig { enum FieldConfigProperty { Default, Impl, - Method { ident: Ident }, - Value { expression: proc_macro2::TokenStream } + Expression { expression: proc_macro2::TokenStream } } struct RequiredStructField { @@ -126,27 +149,22 @@ impl Parse for FieldConfigProperty { let property_name = property.to_string(); match property_name.as_str() { "default" => Ok(FieldConfigProperty::Default), - "method" => { + "expr" => { let (delimiter, span, buffer) = input.parse_any_delimiter()?; if delimiter != Delimiter::Parenthesis { return Err(Error::new(span.span(), "Expected enclosing parenthesis")) } - Ok(FieldConfigProperty::Method { ident: buffer.parse()? }) - }, - "value" => { - let (delimiter, span, buffer) = input.parse_any_delimiter()?; - - if delimiter != Delimiter::Parenthesis { - return Err(Error::new(span.span(), "Expected enclosing parenthesis")) - } - - Ok(FieldConfigProperty::Value { + Ok(FieldConfigProperty::Expression { expression: proc_macro2::TokenStream::parse(&buffer) .expect("Unable to convert buffer back into TokenStream") }) }, + "method" => Err(Error::new( + property.span(), + "\"method\" property has been removed. Please refer to documentation for a list of valid properties." + )), _ => Err(Error::new( property.span(), FIELD_CONFIG_ERR_MSG.replace("{prop}", &property_name) @@ -175,8 +193,7 @@ impl ToTokens for GeneratedStructField { tokens.extend(match &self.configuration { FieldConfigProperty::Default => quote! { Default::default() }, - FieldConfigProperty::Method { ident } => quote! { #ident() }, - FieldConfigProperty::Value { expression } => expression.clone(), + FieldConfigProperty::Expression { expression } => expression.clone(), FieldConfigProperty::Impl => quote! { #ident.into() } }); diff --git a/tests/struct_base.rs b/tests/struct_base.rs new file mode 100644 index 0000000..1e04ad9 --- /dev/null +++ b/tests/struct_base.rs @@ -0,0 +1,42 @@ +use derive_ctor::ctor; + +#[derive(ctor, Debug, PartialEq)] +pub struct Unit; + +#[test] +fn test_unit_struct() { + let unit = Unit::new(); + assert_eq!(Unit, unit); +} + +#[derive(ctor, Debug, PartialEq)] +pub struct Empty {} + +#[test] +fn test_empty_struct_no_config() { + let empty = Empty::new(); + assert_eq!(Empty { }, empty) +} + +#[derive(ctor, Debug, PartialEq)] +pub struct OneFieldStruct { + value: u32 +} + +#[test] +fn test_struct_with_field() { + let ofs = OneFieldStruct::new(300); + assert_eq!(OneFieldStruct { value: 300 }, ofs) +} + +#[derive(ctor, Debug, PartialEq)] +pub struct ManyFieldStruct { + value1: u32, + value2: bool +} + +#[test] +fn test_struct_with_many_fields() { + let mfs = ManyFieldStruct::new(400, true); + assert_eq!(ManyFieldStruct { value1: 400, value2: true }, mfs); +} \ No newline at end of file diff --git a/tests/struct_field_all.rs b/tests/struct_field_all.rs new file mode 100644 index 0000000..0fa82e5 --- /dev/null +++ b/tests/struct_field_all.rs @@ -0,0 +1,19 @@ +use derive_ctor::ctor; + +#[derive(ctor, Debug, PartialEq)] +struct MixedStruct { + provided1: i16, + provided2: bool, + #[ctor(impl)] + provided3: String, + #[ctor(expr("Foo"))] + generated1: &'static str, + #[ctor(default)] + generated2: u32 +} + +#[test] +fn test_struct_with_multiple_generated_fields() { + let multi = MixedStruct::new(41, false, "Test"); + assert_eq!(MixedStruct { provided1: 41, provided2: false, provided3: String::from("Test"), generated1: "Foo", generated2: Default::default() }, multi) +} \ No newline at end of file diff --git a/tests/struct_field_default.rs b/tests/struct_field_default.rs new file mode 100644 index 0000000..abf5bcf --- /dev/null +++ b/tests/struct_field_default.rs @@ -0,0 +1,29 @@ +use derive_ctor::ctor; + +#[derive(ctor, Debug, PartialEq)] +struct StructDefault { + provided: String, + #[ctor(default)] + generated: u32 +} + +#[derive(ctor, Debug, PartialEq)] +struct StructManyDefault { + provided: String, + #[ctor(default)] + generated1: u32, + #[ctor(default)] + generated2: String +} + +#[test] +fn test_struct_with_default_field() { + let test = StructDefault::new(String::from("ABC")); + assert_eq!(StructDefault { provided: String::from("ABC"), generated: Default::default() }, test); +} + +#[test] +fn test_struct_with_multiple_default_fields() { + let test = StructManyDefault::new(String::from("ABC")); + assert_eq!(StructManyDefault { provided: String::from("ABC"), generated1: Default::default(), generated2: Default::default() }, test); +} \ No newline at end of file diff --git a/tests/struct_field_expr.rs b/tests/struct_field_expr.rs new file mode 100644 index 0000000..51682ac --- /dev/null +++ b/tests/struct_field_expr.rs @@ -0,0 +1,55 @@ +use derive_ctor::ctor; + +#[derive(ctor, Debug, PartialEq)] +struct StructExpr { + provided: u32, + #[ctor(expr(10))] + generated: u32 +} + +#[derive(ctor, Debug, PartialEq)] +struct StructManyExpr { + provided: u32, + #[ctor(expr(11))] + generated1: u32, + #[ctor(expr(false))] + generated2: bool +} + +#[derive(ctor, Debug, PartialEq)] +struct StructComplexExpr { + provided: u32, + #[ctor(expr(String::from("Foo")))] + generated: String +} + +#[derive(ctor, Debug, PartialEq)] +struct StructReliantExpr { + provided: u32, + #[ctor(expr(provided.to_string()))] + generated: String +} + +#[test] +fn test_struct_expr_field() { + let test = StructExpr::new(100); + assert_eq!(StructExpr { provided: 100, generated: 10 }, test); +} + +#[test] +fn test_struct_many_expr_fields() { + let test = StructManyExpr::new(101); + assert_eq!(StructManyExpr { provided: 101, generated1: 11, generated2: false }, test); +} + +#[test] +fn test_struct_complex_expr_field() { + let test = StructComplexExpr::new(102); + assert_eq!(StructComplexExpr { provided: 102, generated: String::from("Foo") }, test); +} + +#[test] +fn test_struct_reliant_expr_field() { + let test = StructReliantExpr::new(103); + assert_eq!(StructReliantExpr { provided: 103, generated: 103.to_string() }, test); +} \ No newline at end of file diff --git a/tests/struct_field_impl.rs b/tests/struct_field_impl.rs new file mode 100644 index 0000000..b298dc0 --- /dev/null +++ b/tests/struct_field_impl.rs @@ -0,0 +1,29 @@ +use derive_ctor::ctor; + +#[derive(ctor, Debug, PartialEq)] +struct StructImpl { + #[ctor(impl)] + provided: String, + other: bool +} + +#[derive(ctor, Debug, PartialEq)] +struct StructManyImpl { + provided: bool, + #[ctor(impl)] + one: String, + #[ctor(impl)] + two: String +} + +#[test] +fn test_struct_with_impl_value() { + let test = StructImpl::new("Foo", false); + assert_eq!(StructImpl { provided: String::from("Foo"), other: false }, test); +} + +#[test] +fn test_struct_with_many_impl() { + let test = StructManyImpl::new(false, "One", "Two"); + assert_eq!(StructManyImpl { provided: false, one: String::from("One"), two: String::from("Two") }, test) +} \ No newline at end of file diff --git a/tests/struct_field_specific_ctor.rs b/tests/struct_field_specific_ctor.rs new file mode 100644 index 0000000..e7b50bd --- /dev/null +++ b/tests/struct_field_specific_ctor.rs @@ -0,0 +1,60 @@ +use derive_ctor::ctor; + +#[derive(ctor, Debug, PartialEq)] +#[ctor(new, new2)] +struct TargetedGenerationStruct { + arg1: u32, + #[ctor(default = [0])] + arg2: u32 +} + +#[test] +fn test_struct_with_targeted_generation() { + let targeted = TargetedGenerationStruct::new(100); + assert_eq!(TargetedGenerationStruct { arg1: 100, arg2: Default::default() }, targeted); + let targeted2 = TargetedGenerationStruct::new2(50, 41); + assert_eq!(TargetedGenerationStruct { arg1: 50, arg2: 41 }, targeted2); +} + +fn test_method_2() -> String { + String::from("FooBar") +} + +#[derive(ctor, Debug, PartialEq)] +#[ctor(new, new2)] +struct TargetedGenerationStruct2 { + #[ctor(expr(test_method_2()) = [1])] + arg1: String, + #[ctor(expr(33) = 0)] + arg2: u32 +} + +#[test] +fn test_struct_with_multiple_targeted_generations() { + let tgs1 = TargetedGenerationStruct2::new(String::from("one")); + assert_eq!(TargetedGenerationStruct2 { arg1: String::from("one"), arg2: 33 }, tgs1); + + let tgs2 = TargetedGenerationStruct2::new2(95); + assert_eq!(TargetedGenerationStruct2 { arg1: String::from("FooBar"), arg2: 95}, tgs2); +} + +#[derive(ctor, Debug, PartialEq)] +#[ctor(m1, m2, m3)] +struct TestStructWithFieldWithMultipleTargets { + #[ctor(impl)] + arg1: String, + #[ctor(expr(5) = [0, 1])] + arg2: u32 +} + +#[test] +fn test_struct_multiple_targeted_generations_single_field() { + let tswfwmt1 = TestStructWithFieldWithMultipleTargets::m1("One"); + assert_eq!(TestStructWithFieldWithMultipleTargets { arg1: String::from("One"), arg2: 5 }, tswfwmt1); + + let tswfwmt1 = TestStructWithFieldWithMultipleTargets::m2("Two"); + assert_eq!(TestStructWithFieldWithMultipleTargets { arg1: String::from("Two"), arg2: 5 }, tswfwmt1); + + let tswfwmt1 = TestStructWithFieldWithMultipleTargets::m3("Three", 77); + assert_eq!(TestStructWithFieldWithMultipleTargets { arg1: String::from("Three"), arg2: 77 }, tswfwmt1); +} \ No newline at end of file diff --git a/tests/struct_method_config.rs b/tests/struct_method_config.rs new file mode 100644 index 0000000..c431145 --- /dev/null +++ b/tests/struct_method_config.rs @@ -0,0 +1,58 @@ +use derive_ctor::ctor; +#[derive(ctor, Debug, PartialEq)] +#[ctor(init)] +struct Empty2 {} + +#[test] +fn test_empty_struct_config_name() { + let empty = Empty2::init(); + assert_eq!(Empty2 { }, empty) +} + +#[derive(ctor, Debug, PartialEq)] +#[ctor(pub(crate) new)] +struct VisibilityStruct {} + +#[test] +fn test_method_visibility() { + let visibility = VisibilityStruct::new(); + assert_eq!(VisibilityStruct {}, visibility) +} + +#[derive(ctor, Debug, PartialEq)] +#[ctor(m1, m2)] +struct ManyMethodStruct {} + +#[test] +fn test_empty_struct_many_methods() { + let many1 = ManyMethodStruct::m1(); + assert_eq!(ManyMethodStruct {}, many1); + let many2 = ManyMethodStruct::m2(); + assert_eq!(ManyMethodStruct {}, many2); +} + +#[derive(ctor, Debug, PartialEq)] +#[ctor(pub m1, pub(crate) m2, m3)] +struct ManyVisibleMethodStruct {} + +#[test] +fn test_empty_struct_many_methods_with_visibility() { + let m1 = ManyVisibleMethodStruct::m1(); + assert_eq!(ManyVisibleMethodStruct {}, m1); + let m2 = ManyVisibleMethodStruct::m2(); + assert_eq!(ManyVisibleMethodStruct {}, m2); + let m3 = ManyVisibleMethodStruct::m3(); + assert_eq!(ManyVisibleMethodStruct {}, m3); +} + +#[derive(ctor, Debug, PartialEq)] +#[ctor(init)] +struct FieldStructCustomCtor { + value: u32 +} + +#[test] +fn test_field_struct_with_custom_ctor_name() { + let field_struct = FieldStructCustomCtor::init(15); + assert_eq!(FieldStructCustomCtor { value: 15 }, field_struct); +} \ No newline at end of file diff --git a/tests/struct_mixed_method_field.rs b/tests/struct_mixed_method_field.rs new file mode 100644 index 0000000..669bcf3 --- /dev/null +++ b/tests/struct_mixed_method_field.rs @@ -0,0 +1,15 @@ +use derive_ctor::ctor; + +#[derive(ctor, Debug, PartialEq)] +#[ctor(a)] +struct MixedCtorFieldStruct { + provided: u32, + #[ctor(default)] + generated: bool +} + +#[test] +fn test_struct_with_custom_ctor_and_generated_field() { + let test = MixedCtorFieldStruct::a(100); + assert_eq!(MixedCtorFieldStruct { provided: 100, generated: false }, test) +} \ No newline at end of file diff --git a/tests/test.rs b/tests/test.rs deleted file mode 100644 index f14c8aa..0000000 --- a/tests/test.rs +++ /dev/null @@ -1,232 +0,0 @@ -#[macro_use] -extern crate derive_ctor; - -#[derive(ctor, Debug, PartialEq)] -pub struct Empty {} - -#[test] -fn test_empty_struct_no_config() { - let empty = Empty::new(); - assert_eq!(Empty { }, empty) -} - -#[derive(ctor, Debug, PartialEq)] -#[ctor(init)] -pub struct Empty2 {} - -#[test] -fn test_empty_struct_config_name() { - let empty = Empty2::init(); - assert_eq!(Empty2 { }, empty) -} - -#[derive(ctor, Debug, PartialEq)] -pub struct Unit; - -#[test] -fn test_unit_struct() { - let unit = Unit::new(); - assert_eq!(Unit, unit); -} - -#[derive(ctor, Debug, PartialEq)] -#[ctor(pub(crate) new)] -pub struct VisibilityStruct {} - -#[test] -fn test_method_visibility() { - let visibility = VisibilityStruct::new(); - assert_eq!(VisibilityStruct {}, visibility) -} - -#[derive(ctor, Debug, PartialEq)] -#[ctor(m1, m2)] -pub struct ManyMethodStruct {} - -#[test] -fn test_empty_struct_many_methods() { - let many1 = ManyMethodStruct::m1(); - assert_eq!(ManyMethodStruct {}, many1); - let many2 = ManyMethodStruct::m2(); - assert_eq!(ManyMethodStruct {}, many2); -} - -#[derive(ctor, Debug, PartialEq)] -#[ctor(pub m1, pub(crate) m2, m3)] -pub struct ManyVisibleMethodStruct {} - -#[test] -fn test_empty_struct_many_methods_with_visibility() { - let m1 = ManyVisibleMethodStruct::m1(); - assert_eq!(ManyVisibleMethodStruct {}, m1); - let m2 = ManyVisibleMethodStruct::m2(); - assert_eq!(ManyVisibleMethodStruct {}, m2); - let m3 = ManyVisibleMethodStruct::m3(); - assert_eq!(ManyVisibleMethodStruct {}, m3); -} - -#[derive(ctor, Debug, PartialEq)] -pub struct OneFieldStruct { - value: u32 -} - -#[test] -fn test_struct_with_field() { - let ofs = OneFieldStruct::new(300); - assert_eq!(OneFieldStruct { value: 300 }, ofs) -} - -#[derive(ctor, Debug, PartialEq)] -pub struct ManyFieldStruct { - value1: u32, - value2: bool -} - -#[test] -fn test_struct_with_many_fields() { - let mfs = ManyFieldStruct::new(400, true); - assert_eq!(ManyFieldStruct { value1: 400, value2: true }, mfs); -} - -#[derive(ctor, Debug, PartialEq)] -#[ctor(init)] -pub struct FieldStructCustomCtor { - value: u32 -} - -#[test] -fn test_field_struct_with_custom_ctor_name() { - let field_struct = FieldStructCustomCtor::init(15); - assert_eq!(FieldStructCustomCtor { value: 15 }, field_struct); -} - -#[derive(ctor, Debug, PartialEq)] -pub struct DefaultValueStruct { - provided: String, - #[ctor(default)] - generated: u32 -} - -#[test] -fn test_struct_with_default_field() { - let test = DefaultValueStruct::new(String::from("ABC")); - assert_eq!(DefaultValueStruct { provided: String::from("ABC"), generated: Default::default() }, test); -} - -#[derive(ctor, Debug, PartialEq)] -pub struct ValueValueStruct { - provided: u32, - #[ctor(value(10))] - generated: u32 -} - -#[test] -fn test_struct_with_value_field() { - let test = ValueValueStruct::new(100); - assert_eq!(ValueValueStruct { provided: 100, generated: 10 }, test); -} - -fn generation_method() -> Option> { - Some(Some(4123)) -} - -#[derive(ctor, Debug, PartialEq)] -pub struct MethodValueStruct { - provided: bool, - #[ctor(method(generation_method))] - generated: Option> -} - -#[test] -fn test_struct_with_method_field() { - let test = MethodValueStruct::new(false); - assert_eq!(MethodValueStruct { provided: false, generated: Some(Some(4123))}, test) -} - -#[derive(ctor, Debug, PartialEq)] -pub struct ImplValueStruct { - #[ctor(impl)] - provided: String, - other: bool -} - -#[test] -fn test_struct_with_impl_value() { - let test = ImplValueStruct::new("Foo", false); - assert_eq!(ImplValueStruct { provided: String::from("Foo"), other: false }, test); -} - -#[derive(ctor, Debug, PartialEq)] -pub struct MultipleGenerated { - provided1: i16, - provided2: bool, - #[ctor(value("Foo"))] - generated1: &'static str, - #[ctor(default)] - generated2: u32 -} - -#[test] -fn test_struct_with_multiple_generated_fields() { - let multi = MultipleGenerated::new(41, false); - assert_eq!(MultipleGenerated { provided1: 41, provided2: false, generated1: "Foo", generated2: Default::default() }, multi) -} - -#[derive(ctor, Debug, PartialEq)] -#[ctor(new, new2)] -pub struct TargetedGenerationStruct { - arg1: u32, - #[ctor(default = [0])] - arg2: u32 -} - -#[test] -fn test_struct_with_targeted_generation() { - let targeted = TargetedGenerationStruct::new(100); - assert_eq!(TargetedGenerationStruct { arg1: 100, arg2: Default::default() }, targeted); - let targeted2 = TargetedGenerationStruct::new2(50, 41); - assert_eq!(TargetedGenerationStruct { arg1: 50, arg2: 41 }, targeted2); -} - -fn test_method_2() -> String { - String::from("FooBar") -} - -#[derive(ctor, Debug, PartialEq)] -#[ctor(new, new2)] -pub struct TargetedGenerationStruct2 { - #[ctor(method(test_method_2) = [1])] - arg1: String, - #[ctor(value(33) = 0)] - arg2: u32 -} - -#[test] -fn test_struct_with_multiple_targeted_generations() { - let tgs1 = TargetedGenerationStruct2::new(String::from("one")); - assert_eq!(TargetedGenerationStruct2 { arg1: String::from("one"), arg2: 33 }, tgs1); - - let tgs2 = TargetedGenerationStruct2::new2(95); - assert_eq!(TargetedGenerationStruct2 { arg1: String::from("FooBar"), arg2: 95}, tgs2); -} - -#[derive(ctor, Debug, PartialEq)] -#[ctor(m1, m2, m3)] -pub struct TestStructWithFieldWithMultipleTargets { - #[ctor(impl)] - arg1: String, - #[ctor(value(5) = [0, 1])] - arg2: u32 -} - -#[test] -fn test_struct_multiple_targeted_generations_single_field() { - let tswfwmt1 = TestStructWithFieldWithMultipleTargets::m1("One"); - assert_eq!(TestStructWithFieldWithMultipleTargets { arg1: String::from("One"), arg2: 5 }, tswfwmt1); - - let tswfwmt1 = TestStructWithFieldWithMultipleTargets::m2("Two"); - assert_eq!(TestStructWithFieldWithMultipleTargets { arg1: String::from("Two"), arg2: 5 }, tswfwmt1); - - let tswfwmt1 = TestStructWithFieldWithMultipleTargets::m3("Three", 77); - assert_eq!(TestStructWithFieldWithMultipleTargets { arg1: String::from("Three"), arg2: 77 }, tswfwmt1); -} \ No newline at end of file