Skip to content

Commit

Permalink
feat: Add new field "name" to User struct in dto_example.rs
Browse files Browse the repository at this point in the history
- Added a new field "name" of type String to the User struct.
- The value of the "name" field is computed by concatenating the values of the "firstname" and "lastname" fields using the `concat_str` function.
- Updated the mapper attributes for the User struct in dto_example.rs to include the new field.
- Removed commented out code related to checking if a field is required when it has an Option type.
- Refactored code in dto_builder.rs related to building initialization tokens for new fields.
- Removed the `required` attribute from NewField struct in mapper_entry.rs as it was not being used.
- Added support for multiple attributes on new fields in mapper_entry.rs.
- Fixed a bug where an error was not thrown when the `dto` property was missing or blank in mapper_entry.rs.
- Updated test_dto_creation.rs with correct syntax for specifying attributes on new fields.
  • Loading branch information
fatihaziz committed Oct 15, 2024
1 parent 6df0fc3 commit 98eb2f6
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 40 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,18 @@ It takes only those lines below to get this work done. And the conversion are be
#[mapper( dto="CustomDto" , no_builder=true , map=[ ("email",false) ] , derive=(Debug, Clone) ,
new_fields=[( "name: String", "concat_str( self.firstname.as_str(), self.lastname.as_str() )" )]
)]
#[mapper(
dto="CustomDtoWithAttribute" ,
no_builder=true ,
map=[ ("email",false) ],
derive=(Debug, Clone, Serialize, Deserialize),
new_fields=[(
"name: String",
"concat_str( self.firstname.as_str(), self.lastname.as_str() )",
["#[serde(rename = \"renamed_name\")]"], // attribute of fields
)],
macro_attr=["serde(rename_all = \"UPPERCASE\")"] // atriibute of struct
)]
struct User{
username: String,
password: String,
Expand Down
2 changes: 1 addition & 1 deletion examples/dto_example.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ fn concat_str(s1: &str, s2: &str) -> String {
#[mapper( dto="ProfileDto" , ignore=["password"] , derive=(Debug, Clone, PartialEq) )]
#[mapper( dto="PersonDto" , no_builder=true , map=[ ("firstname",true), ("lastname",true), ("email",false) ] )]
#[mapper( dto="CustomDto" , no_builder=true , map=[ ("email",false) ] , derive=(Debug, Clone) ,
new_fields=[( "name: String", "concat_str( self.firstname.as_str(), self.lastname.as_str() )" )]
new_fields=[( "name: String", "concat_str( self.firstname.as_str(), self.lastname.as_str() )" )]
)]
struct User {
username: String,
Expand Down
14 changes: 2 additions & 12 deletions src/dto_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,23 +260,13 @@ fn build_init_new_fields_token(mp_entry: &MapperEntry) -> Vec<TokenStream> {
.map(|new_field| {
let name = format_ident!("{}", new_field.field_name.as_str());
let expr = &new_field.expression_value;
let f_type = &new_field.field_type;
// let f_type = &new_field.field_type;

// eprintln!("required = {:#?}", new_field.required);
// eprintln!("expr = {:#?}", expr);
// eprintln!("f_type = {:#?}", f_type);

// assuming the `required` attribute is NONE then it want to set required=`false` when there is type `Option` in it
if new_field.required.unwrap_or(false) && f_type.contains("Option") {
panic!("field name: `{}` attribute `required` must set to `false` when type is `Option`", name);
}

// otherwise since its already either has Option or its set required=`true` then its just use as its
if new_field.required.unwrap_or(true) || f_type.contains("Option") {
quote! { #name: unstringify!(#expr) }
} else {
quote! { #name: Some(unstringify!(#expr)) }
}
quote! { #name: unstringify!(#expr) }
})
.collect()
}
Expand Down
37 changes: 12 additions & 25 deletions src/mapper_entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ pub struct NewField {
pub field_type: String,
//init_value is used compute this field value in the DTO during conversion with into()
pub expression_value: String,
pub required: Option<bool>,
pub attributes: Vec<String>,
}

Expand All @@ -44,14 +43,12 @@ impl NewField {
r#type: &str,
init_expression: &str,
attr: Option<Vec<String>>,
required: Option<bool>,
) -> Self {
Self {
field_name: name.to_string(),
field_type: r#type.to_string(),
expression_value: init_expression.to_string(),
attributes: attr.unwrap_or(vec![]),
required,
}
}
}
Expand Down Expand Up @@ -163,14 +160,18 @@ impl MapperEntry {

//dto property is required and must be checked
match dto_prop {
Some(val) if utils::isblank(&val) => Err(syn::Error::new(
attr.span(),
"`dto` property is blank. It must not have whitespace",
)),
None => Err(syn::Error::new(
attr.span(),
"`dto` property is missing.It is required for mapper",
)),
Some(val) if utils::isblank(&val) => {
Err(syn::Error::new(
attr.span(),
"`dto` property is blank. It must not have whitespace",
))
}
None => {
Err(syn::Error::new(
attr.span(),
"`dto` property is missing.It is required for mapper",
))
}
_ => syn::Result::Ok(mapper_entry),
}
}
Expand Down Expand Up @@ -349,7 +350,6 @@ impl MapperEntry {
fn process_new_fields(mut vec_tuple: &mut Vec<NewField>, elem: &Expr) {
if let Expr::Tuple(el_exp) = elem {
let mut field_data: [Option<String>; 2] = [None, None];
let mut is_required: Option<bool> = None;
let mut attributes: Vec<String> = Vec::new();
let total_passed_args = el_exp.elems.len();

Expand All @@ -376,15 +376,6 @@ impl MapperEntry {
}
}
2 => {
// Boolean value (is_optional)
if let Expr::Lit(content_lit) = content_expr {
if let Lit::Bool(bool_val) = &content_lit.lit {
// eprintln!("is_optional={}", bool_val.value);
is_required = Some(bool_val.value);
}
}
}
3 => {
// Attributes array
attributes = extract_attributes(content_expr);
// eprintln!("attributes={:#?}", attributes);
Expand All @@ -410,15 +401,13 @@ impl MapperEntry {
} else {
Some(attributes.clone())
},
is_required,
);
} else {
panic!("Missing `:` character for field declaration");
}
}
// Reset for next field
field_data = [None, None];
is_required = None;
attributes.clear();
}
}
Expand All @@ -433,7 +422,6 @@ impl MapperEntry {
field_decl: &String,
colon_position: &usize,
attributes: Option<Vec<String>>,
required: Option<bool>,
) {
if *colon_position == 0 {
panic!("`:` cannot be the first character. Need to specify new fieldname for struct");
Expand All @@ -450,7 +438,6 @@ impl MapperEntry {
field_type,
str_val.as_str(),
attributes,
required,
));
}

Expand Down
3 changes: 1 addition & 2 deletions tests/test_dto_creation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,10 @@ mod test_dto_creation {
new_fields=[(
"name: String",
"concat_str( self.firstname.as_str(), self.lastname.as_str() )",
true,
["#[serde(rename = \"renamed_name\")]"],
)],
macro_attr=["serde(rename_all = \"UPPERCASE\")"]
)]
)]
struct User {
username: String,
password: String,
Expand Down

0 comments on commit 98eb2f6

Please sign in to comment.