@@ -2,7 +2,7 @@ use crate::parsing::*;
22use convert_case:: { Case , Casing } ;
33use proc_macro_crate:: FoundCrate ;
44use proc_macro2:: TokenStream as TokenStream2 ;
5- use quote:: { format_ident, quote} ;
5+ use quote:: { format_ident, quote, quote_spanned } ;
66use std:: sync:: atomic:: AtomicU64 ;
77use syn:: punctuated:: Punctuated ;
88use syn:: spanned:: Spanned ;
@@ -134,14 +134,22 @@ pub(crate) fn generate_node_code(parsed: &ParsedNodeFn) -> syn::Result<TokenStre
134134 let number_min_values: Vec < _ > = fields
135135 . iter ( )
136136 . map ( |field| match field {
137- ParsedField :: Regular { number_min : Some ( number_min) , .. } => quote ! ( Some ( #number_min) ) ,
137+ ParsedField :: Regular { number_soft_min, number_hard_min, .. } => match ( number_soft_min, number_hard_min) {
138+ ( Some ( soft_min) , _) => quote ! ( Some ( #soft_min) ) ,
139+ ( None , Some ( hard_min) ) => quote ! ( Some ( #hard_min) ) ,
140+ ( None , None ) => quote ! ( None ) ,
141+ } ,
138142 _ => quote ! ( None ) ,
139143 } )
140144 . collect ( ) ;
141145 let number_max_values: Vec < _ > = fields
142146 . iter ( )
143147 . map ( |field| match field {
144- ParsedField :: Regular { number_max : Some ( number_max) , .. } => quote ! ( Some ( #number_max) ) ,
148+ ParsedField :: Regular { number_soft_max, number_hard_max, .. } => match ( number_soft_max, number_hard_max) {
149+ ( Some ( soft_max) , _) => quote ! ( Some ( #soft_max) ) ,
150+ ( None , Some ( hard_max) ) => quote ! ( Some ( #hard_max) ) ,
151+ ( None , None ) => quote ! ( None ) ,
152+ } ,
145153 _ => quote ! ( None ) ,
146154 } )
147155 . collect ( ) ;
@@ -175,6 +183,33 @@ pub(crate) fn generate_node_code(parsed: &ParsedNodeFn) -> syn::Result<TokenStre
175183 }
176184 } ) ;
177185
186+ let min_max_args = fields. iter ( ) . map ( |field| match field {
187+ ParsedField :: Regular {
188+ pat_ident,
189+ number_hard_min,
190+ number_hard_max,
191+ ..
192+ } => {
193+ let name = & pat_ident. ident ;
194+ let mut tokens = quote ! ( ) ;
195+ if let Some ( min) = number_hard_min {
196+ tokens. extend ( quote_spanned ! { min. span( ) =>
197+ let #name = #graphene_core:: misc:: Clampable :: clamp_hard_min( #name, #min) ;
198+ } ) ;
199+ }
200+
201+ if let Some ( max) = number_hard_max {
202+ tokens. extend ( quote_spanned ! { max. span( ) =>
203+ let #name = #graphene_core:: misc:: Clampable :: clamp_hard_max( #name, #max) ;
204+ } ) ;
205+ }
206+ tokens
207+ }
208+ ParsedField :: Node { .. } => {
209+ quote ! ( )
210+ }
211+ } ) ;
212+
178213 let all_implementation_types = fields. iter ( ) . flat_map ( |field| match field {
179214 ParsedField :: Regular { implementations, .. } => implementations. into_iter ( ) . cloned ( ) . collect :: < Vec < _ > > ( ) ,
180215 ParsedField :: Node { implementations, .. } => implementations
@@ -186,13 +221,27 @@ pub(crate) fn generate_node_code(parsed: &ParsedNodeFn) -> syn::Result<TokenStre
186221
187222 let input_type = & parsed. input . ty ;
188223 let mut clauses = Vec :: new ( ) ;
224+ let mut clampable_clauses = Vec :: new ( ) ;
225+
189226 for ( field, name) in fields. iter ( ) . zip ( struct_generics. iter ( ) ) {
190227 clauses. push ( match ( field, * is_async) {
191- ( ParsedField :: Regular { ty, .. } , _) => {
228+ (
229+ ParsedField :: Regular {
230+ ty, number_hard_min, number_hard_max, ..
231+ } ,
232+ _,
233+ ) => {
192234 let all_lifetime_ty = substitute_lifetimes ( ty. clone ( ) , "all" ) ;
193235 let id = future_idents. len ( ) ;
194236 let fut_ident = format_ident ! ( "F{}" , id) ;
195237 future_idents. push ( fut_ident. clone ( ) ) ;
238+
239+ // Add Clampable bound if this field uses hard_min or hard_max
240+ if number_hard_min. is_some ( ) || number_hard_max. is_some ( ) {
241+ // The bound applies to the Output type of the future, which is #ty
242+ clampable_clauses. push ( quote ! ( #ty: #graphene_core:: misc:: Clampable ) ) ;
243+ }
244+
196245 quote ! (
197246 #fut_ident: core:: future:: Future <Output = #ty> + #graphene_core:: WasmNotSend + ' n,
198247 for <' all> #all_lifetime_ty: #graphene_core:: WasmNotSend ,
@@ -220,6 +269,7 @@ pub(crate) fn generate_node_code(parsed: &ParsedNodeFn) -> syn::Result<TokenStre
220269 let mut struct_where_clause = where_clause. clone ( ) ;
221270 let extra_where: Punctuated < WherePredicate , Comma > = parse_quote ! (
222271 #( #clauses, ) *
272+ #( #clampable_clauses, ) *
223273 #output_type: ' n,
224274 ) ;
225275 struct_where_clause. predicates . extend ( extra_where) ;
@@ -236,7 +286,10 @@ pub(crate) fn generate_node_code(parsed: &ParsedNodeFn) -> syn::Result<TokenStre
236286 #[ inline]
237287 fn eval( & ' n self , __input: #input_type) -> Self :: Output {
238288 Box :: pin( async move {
289+ use #graphene_core:: misc:: Clampable ;
290+
239291 #( #eval_args) *
292+ #( #min_max_args) *
240293 self :: #fn_name( __input #( , #field_names) * ) #await_keyword
241294 } )
242295 }
0 commit comments