11use crate :: field:: { FieldArgs , FieldNestedArg } ;
2- use crate :: utils:: to_type_string;
3- use proc_macro2:: TokenStream ;
2+ use crate :: utils:: { ImplResult , to_type_string} ;
43use quote:: { ToTokens , format_ident, quote} ;
54use syn:: { Expr , GenericArgument , Ident , Lit , PathArguments , PathSegment , Type } ;
65
@@ -19,6 +18,7 @@ pub enum Layer {
1918
2019#[ derive( Debug ) ]
2120pub struct FieldValue {
21+ pub inner_ty : Option < Type > ,
2222 pub layers : Vec < Layer > ,
2323 pub nested : bool ,
2424 pub nested_ident : Option < Ident > ,
@@ -30,7 +30,6 @@ impl FieldValue {
3030 pub fn new ( ty : Type , nested_arg : Option < & FieldNestedArg > ) -> Self {
3131 let mut nested = false ;
3232 let mut nested_ident = None ;
33- let mut layers = vec ! [ ] ;
3433 let ty_string = to_type_string ( ty. to_token_stream ( ) ) ;
3534
3635 // Determine nested state
@@ -52,30 +51,37 @@ impl FieldValue {
5251 } ;
5352 }
5453
55- // Extract type information
56- if let Some ( custom_ident) =
57- extract_type_information ( & ty, & mut layers, nested && nested_ident. is_none ( ) )
58- {
59- nested_ident = Some ( custom_ident) ;
60- }
61-
62- if nested_ident. is_none ( ) && nested {
63- panic ! (
64- "Unable to extract the nested configuration identifier from `{ty_string}`. Try explicitly passing the identifier with `nested = ConfigName`."
65- )
66- }
67-
68- let value = Self {
54+ let mut value = FieldValue {
55+ inner_ty : None ,
6956 nested,
7057 nested_ident,
71- layers,
58+ layers : vec ! [ ] ,
7259 ty_string,
7360 ty,
7461 } ;
62+ value. extract_type_information ( ) ;
63+ value
64+ }
7565
76- // dbg!(&value);
66+ pub fn extract_type_information ( & mut self ) {
67+ extract_type_information ( & self . ty , & mut self . layers , |ty, segment| {
68+ self . inner_ty = Some ( ty. to_owned ( ) ) ;
7769
78- value
70+ if self . nested && self . nested_ident . is_none ( ) {
71+ self . nested_ident = Some ( segment. ident . clone ( ) ) ;
72+ }
73+ } ) ;
74+
75+ if self . nested && self . nested_ident . is_none ( ) {
76+ panic ! (
77+ "Unable to extract the nested configuration identifier from `{}`. Try explicitly passing the identifier with `nested = ConfigName`." ,
78+ self . ty_string
79+ )
80+ }
81+ }
82+
83+ pub fn get_inner_type ( & self ) -> & Type {
84+ self . inner_ty . as_ref ( ) . unwrap_or ( & self . ty )
7985 }
8086
8187 pub fn is_outer_option_wrapped ( & self ) -> bool {
@@ -84,11 +90,14 @@ impl FieldValue {
8490 . is_some_and ( |wrapper| * wrapper == Layer :: Option )
8591 }
8692
87- pub fn impl_partial_default_value ( & self , field_args : & FieldArgs ) -> Option < TokenStream > {
93+ pub fn impl_partial_default_value ( & self , field_args : & FieldArgs ) -> ImplResult {
8894 if self . is_outer_option_wrapped ( ) {
89- return None ;
95+ return ImplResult :: skipped ( ) ;
9096 } ;
9197
98+ let mut res = ImplResult :: default ( ) ;
99+ let mut wrap_with_some = false ;
100+
92101 // Extract the inner value first
93102 let mut value = if let Some ( nested_ident) = & self . nested_ident {
94103 if field_args. default . is_some ( ) {
@@ -99,18 +108,32 @@ impl FieldValue {
99108 <#nested_ident as schematic:: PartialConfig >:: default_values( content) ?
100109 }
101110 } else if let Some ( expr) = & field_args. default {
111+ let ty = self . get_inner_type ( ) ;
112+
102113 match expr {
103114 Expr :: Array ( _) | Expr :: Call ( _) | Expr :: Macro ( _) | Expr :: Tuple ( _) => {
115+ wrap_with_some = true ;
116+
104117 quote ! { #expr }
105118 }
106119 Expr :: Path ( func) => {
107- quote ! { schematic:: internal:: handle_default_result( #func( context) ) ? }
120+ res. requires_internal = true ;
121+
122+ quote ! { handle_default_result( #func( context) ) ? }
108123 }
109124 Expr :: Lit ( lit) => match & lit. lit {
110- Lit :: Str ( string) => quote ! {
111- schematic:: internal:: handle_default_result( std:: convert:: TryFrom :: try_from( #string) ) ?
112- } ,
113- other => quote ! { #other } ,
125+ Lit :: Str ( string) => {
126+ res. requires_internal = true ;
127+
128+ quote ! {
129+ handle_default_result( #ty:: try_from( #string) ) ?
130+ }
131+ }
132+ other => {
133+ wrap_with_some = true ;
134+
135+ quote ! { #other }
136+ }
114137 } ,
115138 invalid => {
116139 panic ! (
@@ -119,40 +142,52 @@ impl FieldValue {
119142 }
120143 }
121144 } else {
145+ wrap_with_some = true ;
146+
122147 quote ! {
123148 Default :: default ( )
124149 }
125150 } ;
126151
127152 // Then wrap with each layer
128- for layer in self . layers . iter ( ) . rev ( ) {
129- value = match layer {
130- Layer :: Arc => quote ! { Arc :: new( #value) } ,
131- Layer :: Box => quote ! { Box :: new( #value) } ,
132- Layer :: Option => quote ! { Some ( #value) } ,
133- Layer :: Rc => quote ! { Rc :: new( #value) } ,
134- Layer :: Map ( name) | Layer :: Set ( name) | Layer :: Vec ( name) | Layer :: Unknown ( name) => {
135- let collection = format_ident ! ( "{name}" ) ;
136-
137- quote ! { #collection:: default ( ) }
138- }
139- } ;
153+ if !self . layers . is_empty ( ) {
154+ wrap_with_some = true ;
155+
156+ for layer in self . layers . iter ( ) . rev ( ) {
157+ value = match layer {
158+ Layer :: Arc => quote ! { Arc :: new( #value) } ,
159+ Layer :: Box => quote ! { Box :: new( #value) } ,
160+ Layer :: Option => quote ! { Some ( #value) } ,
161+ Layer :: Rc => quote ! { Rc :: new( #value) } ,
162+ Layer :: Map ( name)
163+ | Layer :: Set ( name)
164+ | Layer :: Vec ( name)
165+ | Layer :: Unknown ( name) => {
166+ let collection = format_ident ! ( "{name}" ) ;
167+
168+ quote ! { #collection:: default ( ) }
169+ }
170+ } ;
171+ }
140172 }
141173
142- Some ( quote ! {
143- Some ( #value)
144- } )
174+ if wrap_with_some {
175+ value = quote ! { Some ( #value) } ;
176+ }
177+
178+ res. value = value;
179+ res
145180 }
146181}
147182
148183fn extract_type_information (
149184 ty : & Type ,
150185 layers : & mut Vec < Layer > ,
151- nested_ident : bool ,
152- ) -> Option < Ident > {
186+ mut on_last : impl FnMut ( & Type , & PathSegment ) ,
187+ ) {
153188 // We don't need to traverse other types, just paths
154189 let Type :: Path ( ty_path) = ty else {
155- return None ;
190+ return ;
156191 } ;
157192
158193 // Extract the last segment of the path, for example `Option`,
@@ -162,25 +197,22 @@ fn extract_type_information(
162197 match & last_segment. arguments {
163198 // We've reached the final segment
164199 PathArguments :: None => {
165- if nested_ident {
166- return Some ( last_segment. ident . clone ( ) ) ;
167- }
200+ on_last ( ty, last_segment) ;
168201 }
169202
170203 // Attempt to drill deeper down
171204 PathArguments :: AngleBracketed ( args) => {
172205 extract_layer ( last_segment, layers) ;
173206
174207 if let Some ( GenericArgument :: Type ( inner_ty) ) = args. args . last ( ) {
175- return extract_type_information ( inner_ty, layers, nested_ident) ;
208+ extract_type_information ( inner_ty, layers, on_last) ;
209+ return ;
176210 }
177211 }
178212
179213 // What to do here, anything?
180214 PathArguments :: Parenthesized ( _) => { }
181215 } ;
182-
183- None
184216}
185217
186218fn extract_layer ( last_segment : & PathSegment , layers : & mut Vec < Layer > ) {
0 commit comments