diff --git a/README.md b/README.md index 7148a49..7a1e065 100644 --- a/README.md +++ b/README.md @@ -121,7 +121,7 @@ And here's the code that `o2o` generates (from here on, generated code is produc - [The (not so big) Problem](#the-not-so-big-problem) - [Inline expressions](#inline-expressions) - [Examples](#examples) - - [Different field name](#different-field-name) + - [Different member name](#different-member-name) - [Different field type](#different-field-type) - [Nested structs](#nested-structs) - [Nested collection](#nested-collection) @@ -313,7 +313,7 @@ So finally, let's look at some examples. ## Examples -### Different field name +### Different member name ``` rust use o2o::o2o; @@ -323,14 +323,29 @@ struct Entity { another_int: i16, } +enum EntityEnum { + Entity(Entity), + SomethingElse { field: i32 } +} + #[derive(o2o)] -#[from_ref(Entity)] -#[ref_into_existing(Entity)] +#[map_ref(Entity)] struct EntityDto { some_int: i32, #[map(another_int)] different_int: i16, } + +#[derive(o2o)] +#[map_ref(EntityEnum)] +enum EntityEnumDto { + #[map(Entity)] + EntityDto(#[map(~.into())]EntityDto), + SomethingElse { + #[map(field, *~)] + f: i32 + } +} ```
View generated code @@ -350,6 +365,23 @@ struct EntityDto { other.another_int = self.different_int; } } + + impl std::convert::From<&EntityEnum> for EntityEnumDto { + fn from(value: &EntityEnum) -> EntityEnumDto { + match value { + EntityEnum::Entity(f0) => EntityEnumDto::EntityDto(f0.into()), + EntityEnum::SomethingElse { field } => EntityEnumDto::SomethingElse { f: *field }, + } + } + } + impl std::convert::Into for &EntityEnumDto { + fn into(self) -> EntityEnum { + match self { + EntityEnumDto::EntityDto(f0) => EntityEnum::Entity(f0.into()), + EntityEnumDto::SomethingElse { f } => EntityEnum::SomethingElse { field: *f }, + } + } + } ```
@@ -485,9 +517,6 @@ struct Child { #[map_owned(Entity)] struct EntityDto { some_int: i32, - // Here field name as well as type are different, so we pass in field name and tilde inline expression. - // Also, it doesn't hurt to use member trait instruction #[map()], - // which is broader than trait instruction #[map_owned] #[map(children, ~.iter().map(|p|p.into()).collect())] children_vec: Vec } @@ -588,7 +617,7 @@ enum ZodiacSign {} ``` -In a reverse case, you need to use a struct level `#[ghost()]` instruction: +In a reverse case, you need to use a struct level `#[ghosts()]` instruction: ``` rust use o2o::o2o; @@ -805,16 +834,12 @@ impl Employee { #[derive(o2o)] #[map(Employee)] #[ghosts( - // o2o supports closures with one input parameter. - // This parameter represents instance on the other side of the conversion. first_name: {@.get_first_name()}, last_name: {@.get_last_name()} )] struct EmployeeDto { #[map(id)] employee_id: i32, - // '@.' is another flavor of 'inline expression'. - // @ also represents instance on the other side of the conversion. #[ghost(@.get_full_name())] full_name: String, diff --git a/o2o-impl/src/expand.rs b/o2o-impl/src/expand.rs index a9f7ffe..28bd521 100644 --- a/o2o-impl/src/expand.rs +++ b/o2o-impl/src/expand.rs @@ -20,7 +20,6 @@ pub fn derive(node: &DeriveInput) -> Result { let input = Enum::from_syn(node, data)?; let input = DataType::Enum(&input); validate(&input)?; - //Ok(TokenStream::new()) Ok(struct_impl(input)) }, _ => Err(Error::new_spanned( @@ -579,7 +578,7 @@ fn render_struct_line( let index2 = Member::Unnamed(Index { index: idx as u32, span: Span::call_site() }); quote!(obj.#index2 = #obj #index;) } else { - let index = if ctx.destructured_src { format_ident!("f{}", index).to_token_stream() } else { index.to_token_stream() }; + let index = if ctx.destructured_src { format_ident!("f{}", index.index).to_token_stream() } else { index.to_token_stream() }; quote!(#obj #index,) }, (syn::Member::Unnamed(index), None, Kind::OwnedIntoExisting | Kind::RefIntoExisting, StructKindHint::Tuple | StructKindHint::Unspecified) => { @@ -590,7 +589,7 @@ fn render_struct_line( if f.attrs.has_parent_attr(&ctx.struct_attr.ty) { if !ctx.kind.is_ref() { quote!((&value).into(),) } else { quote!(value.into(),) } } else { - let field_path = if ctx.destructured_src { get_field_path(&Member::Named(format_ident!("f{}", index))) } else { get_field_path(&f.member) }; + let field_path = if ctx.destructured_src { get_field_path(&Member::Named(format_ident!("f{}", index.index))) } else { get_field_path(&f.member) }; quote!(#obj #field_path,) }, (syn::Member::Unnamed(_), None, _, StructKindHint::Struct) => { @@ -624,7 +623,7 @@ fn render_struct_line( quote!(#ident: #right_side,) }, (syn::Member::Unnamed(index), Some(attr), Kind::OwnedInto | Kind::RefInto, StructKindHint::Tuple | StructKindHint::Unspecified) => { - let index = if ctx.destructured_src { Some(format_ident!("f{}", index).to_token_stream()) } else { Some(index.to_token_stream()) }; + let index = if ctx.destructured_src { Some(format_ident!("f{}", index.index).to_token_stream()) } else { Some(index.to_token_stream()) }; let right_side = attr.get_action_or(index.clone(), ctx, || quote!(#obj #index)); quote!(#right_side,) }, @@ -644,7 +643,7 @@ fn render_struct_line( quote!(other.#field_path = #right_side;) }, (syn::Member::Unnamed(index), Some(attr), Kind::FromOwned | Kind::FromRef, _) => { - let or = Member::Named(format_ident!("f{}", index)); + let or = Member::Named(format_ident!("f{}", index.index)); let right_side = attr.get_stuff(&obj, get_field_path, ctx, || if ctx.destructured_src { &or } else { &f.member}); quote!(#right_side,) } @@ -891,7 +890,7 @@ impl<'a> ApplicableAttr<'a> { (Some(ident), Some(action)) => { if let Member::Unnamed(index) = ident { if ctx.destructured_src { - let ident = Member::Named(format_ident!("f{}", index)); + let ident = Member::Named(format_ident!("f{}", index.index)); quote_action(action, Some(field_path(&ident)), ctx) } else { quote_action(action, Some(field_path(ident)), ctx)} } else {