inter_struct_codegen/generate/merge/
owned.rs1use proc_macro2::TokenStream;
2use quote::{quote, ToTokens};
3use syn::Field;
4
5use crate::error::*;
6use crate::generate::field::*;
7use crate::generate::types::*;
8use crate::generate::Parameters;
9
10pub(crate) fn impl_owned(params: &Parameters, fields: Vec<(Field, Field)>) -> TokenStream {
12 let mut functions_tokens = TokenStream::new();
13
14 let stream = merge(params, fields);
16 functions_tokens.extend(vec![stream]);
17
18 let src_ident = ¶ms.src_struct.ident;
20 let target_path = ¶ms.target_path;
21 quote! {
22 impl inter_struct::merge::StructMergeInto<#target_path> for #src_ident {
23 #functions_tokens
24 }
25 }
26}
27
28fn merge(params: &Parameters, fields: Vec<(Field, Field)>) -> TokenStream {
30 let mut merge_code = TokenStream::new();
31 for (src_field, target_field) in fields {
32 let src_field_ident = src_field.ident;
33 let target_field_ident = target_field.ident;
34
35 let src_field_type = match determine_field_type(src_field.ty) {
37 Ok(field) => field,
38 Err(err) => {
39 merge_code.extend(vec![err]);
40 continue;
41 }
42 };
43 let target_field_type = match determine_field_type(target_field.ty) {
44 Ok(field) => field,
45 Err(err) => {
46 merge_code.extend(vec![err]);
47 continue;
48 }
49 };
50
51 let snippet = match (src_field_type, target_field_type) {
52 (FieldType::Normal(src_type), FieldType::Normal(target_type)) => {
54 equal_type_or_err!(
55 src_type,
56 target_type,
57 quote! {
58 target.#target_field_ident = self.#src_field_ident;
59 }
60 )
61 }
62 (
64 FieldType::Optional {
65 inner: src_type, ..
66 },
67 FieldType::Normal(target_type),
68 ) => {
69 equal_type_or_err!(
70 src_type,
71 target_type,
72 quote! {
73 if let Some(value) = self.#src_field_ident {
74 target.#target_field_ident = value;
75 }
76 }
77 )
78 }
79 (
81 FieldType::Normal(src_type),
82 FieldType::Optional {
83 inner: target_type, ..
84 },
85 ) => {
86 equal_type_or_err!(
87 src_type,
88 target_type,
89 quote! {
90 target.#target_field_ident = Some(self.#src_field_ident);
91 }
92 )
93 }
94 (
99 FieldType::Optional {
100 inner: inner_src_type,
101 outer: outer_src_type,
102 },
103 FieldType::Optional {
104 inner: inner_target_type,
105 outer: outer_target_type,
106 },
107 ) => {
108 if is_equal_type(&inner_src_type, &inner_target_type) {
110 equal_type_or_err!(
111 inner_src_type,
112 inner_target_type,
113 quote! {
114 target.#target_field_ident = self.#src_field_ident;
115 }
116 )
117 } else if is_equal_type(&inner_src_type, &outer_target_type) {
119 equal_type_or_err!(
120 inner_src_type,
121 outer_target_type,
122 quote! {
123 if let Some(value) = self.#src_field_ident {
124 target.#target_field_ident = value;
125 }
126 }
127 )
128 } else {
130 equal_type_or_err!(
131 outer_src_type,
132 inner_target_type,
133 quote! {
134 target.#target_field_ident = Some(self.#src_field_ident);
135 }
136 )
137 }
138 }
139 (FieldType::Invalid, _) | (_, FieldType::Invalid) => continue,
141 };
142
143 merge_code.extend(vec![snippet]);
144 }
145
146 let merge_code = merge_code.to_token_stream();
147
148 let target_path = ¶ms.target_path;
149 quote! {
150 fn merge_into(self, target: &mut #target_path) {
151 #merge_code
152 }
153 }
154}