Skip to main content

rydantic_derive/
lib.rs

1use proc_macro::TokenStream;
2use proc_macro2::TokenStream as Tokens;
3use quote::{format_ident, quote};
4use syn::{
5    parse_macro_input, parse_quote, spanned::Spanned, Data, DeriveInput, Expr, Fields, Ident,
6    Member, Type,
7};
8mod attrs;
9#[cfg(feature = "capnp")]
10mod auto_protocol;
11mod native;
12mod sql_model;
13
14/// Derive SQL schema metadata, SQLx row decoding and validated CRUD operations.
15#[proc_macro_derive(SqlModel, attributes(sql, model))]
16pub fn derive_sql_model(input: TokenStream) -> TokenStream {
17    sql_model::expand(parse_macro_input!(input as DeriveInput))
18        .unwrap_or_else(syn::Error::into_compile_error)
19        .into()
20}
21
22/// Derive a complete Cap'n Proto protocol and its bindings from an inline model module.
23#[cfg(feature = "capnp")]
24#[proc_macro_attribute]
25pub fn capnp_models(args: TokenStream, input: TokenStream) -> TokenStream {
26    auto_protocol::expand(args.into(), input.into())
27        .unwrap_or_else(syn::Error::into_compile_error)
28        .into()
29}
30
31#[proc_macro_derive(Model, attributes(model))]
32pub fn derive_model(input: TokenStream) -> TokenStream {
33    expand(parse_macro_input!(input as DeriveInput))
34        .unwrap_or_else(syn::Error::into_compile_error)
35        .into()
36}
37
38struct Field {
39    ident: Ident,
40    member: Member,
41    ty: Type,
42    attr: attrs::Field,
43    input: String,
44    output: String,
45    doc: ::core::option::Option<String>,
46}
47#[derive(Clone, Copy, PartialEq)]
48enum Shape {
49    Named,
50    Tuple,
51    Unit,
52}
53fn shape(fields: &Fields) -> Shape {
54    match fields {
55        Fields::Named(_) => Shape::Named,
56        Fields::Unnamed(_) => Shape::Tuple,
57        Fields::Unit => Shape::Unit,
58    }
59}
60fn fields(
61    source: &Fields,
62    tag: ::core::option::Option<&str>,
63    container: &attrs::Container,
64) -> syn::Result<Vec<Field>> {
65    let mut inputs = std::collections::HashSet::new();
66    let mut outputs = std::collections::HashSet::new();
67    let mut extras = 0;
68    let result=source.iter().enumerate().map(|(i,field)|{
69        let ident=field.ident.clone().unwrap_or_else(||format_ident!("__tuple_{i}"));
70        let member=field.ident.clone().map(Member::Named).unwrap_or_else(||Member::Unnamed(i.into()));
71        let attr=attrs::field(&field.attrs)?;
72        if attr.extra{extras+=1;}
73        if matches!(source,Fields::Unnamed(_)) && (attr.flatten||attr.extra||attr.rename.is_some()||attr.validation_alias.is_some()||attr.serialization_alias.is_some()||attr.exclude||attr.has_default()){
74            return Err(syn::Error::new(field.span(),"tuple fields support validation and transformations; names, flatten, extra, exclude and defaults require named fields"));
75        }
76        if (attr.flatten||attr.extra)&&(attr.rename.is_some()||attr.validation_alias.is_some()||attr.serialization_alias.is_some()||attr.before.is_some()||attr.coerce||attr.has_rules()){
77            return Err(syn::Error::new(field.span(),"flatten and extra fields use their inner model's names, transformations and constraints"));
78        }
79        let base=attr.rename.clone().unwrap_or_else(||if field.ident.is_some(){ident.to_string().trim_start_matches("r#").to_owned()}else{i.to_string()});
80        let input=attr.validation_alias.clone().unwrap_or_else(||base.clone());let output=attr.serialization_alias.clone().unwrap_or(base);
81        if !attr.flatten&&!attr.extra{
82            if !inputs.insert(input.clone())||tag==Some(input.as_str()){return Err(syn::Error::new(ident.span(),"duplicate input field name or collision with enum tag"));}
83            if !attr.exclude&&(!outputs.insert(output.clone())||tag==Some(output.as_str())){return Err(syn::Error::new(ident.span(),"duplicate output field name or collision with enum tag"));}
84        }
85        let doc=attr.description.clone().or_else(||{
86            let text=field.attrs.iter().filter_map(|attr|{if !attr.path().is_ident("doc"){return None;}let syn::Meta::NameValue(v)=&attr.meta else{return None;};let Expr::Lit(v)=&v.value else{return None;};let syn::Lit::Str(v)=&v.lit else{return None;};Some(v.value().trim().to_owned())}).collect::<Vec<_>>();(!text.is_empty()).then(||text.join("\n"))
87        });
88        Ok(Field{ident,member,ty:field.ty.clone(),attr,input,output,doc})
89    }).collect::<syn::Result<Vec<_>>>()?;
90    if extras > 1 {
91        return Err(syn::Error::new(
92            source.span(),
93            "a model may have only one extra field",
94        ));
95    }
96    if container.allow_extra && extras != 1 {
97        return Err(syn::Error::new(
98            source.span(),
99            "extra = \"allow\" requires one #[model(extra)] map field",
100        ));
101    }
102    if !container.allow_extra && extras != 0 {
103        return Err(syn::Error::new(
104            source.span(),
105            "#[model(extra)] requires #[model(extra = \"allow\")]",
106        ));
107    }
108    Ok(result)
109}
110fn option<T: quote::ToTokens>(value: &::core::option::Option<T>) -> Tokens {
111    match value {
112        Some(v) => quote!(Some(#v)),
113        None => quote!(None),
114    }
115}
116fn rules(field: &Field, rd: &Tokens) -> Tokens {
117    let a = &field.attr;
118    let trim = a.trim;
119    let lower = a.lowercase;
120    let upper = a.uppercase;
121    let email = a.email;
122    let min = option(&a.min_length);
123    let max = option(&a.max_length);
124    let number = |v: &::core::option::Option<String>| match v {
125        Some(v) => quote!(Some(#rd::__private::number(#v))),
126        None => quote!(None),
127    };
128    let ge = number(&a.ge);
129    let gt = number(&a.gt);
130    let le = number(&a.le);
131    let lt = number(&a.lt);
132    let pattern = match &a.pattern {
133        Some(v) => {
134            quote!(Some(#rd::__private::regex::Regex::new(#v).expect("regex checked by Model derive")))
135        }
136        None => quote!(None),
137    };
138    quote!({static RULES: ::std::sync::OnceLock<#rd::rules::Rules>=::std::sync::OnceLock::new();RULES.get_or_init(||#rd::rules::Rules{trim:#trim,lowercase:#lower,uppercase:#upper,min_length:#min,max_length:#max,ge:#ge,gt:#gt,le:#le,lt:#lt,pattern:#pattern,email:#email})})
139}
140struct Mode<'a> {
141    rd: &'a Tokens,
142    borrow: bool,
143}
144impl Mode<'_> {
145    fn tr(&self) -> Tokens {
146        let rd = self.rd;
147        if self.borrow {
148            quote!(#rd::BorrowType<'__rydantic_de>)
149        } else {
150            quote!(#rd::JsonType)
151        }
152    }
153    fn decode(&self, ty: &Type, raw: Tokens, coerce: bool) -> Tokens {
154        let tr = self.tr();
155        if self.borrow {
156            quote!(<#ty as #tr>::decode(#raw,__rydantic_ctx,#coerce))
157        } else {
158            quote!(<#ty as #tr>::decode_input(#raw,__rydantic_ctx,#coerce))
159        }
160    }
161}
162fn default_expr(field: &Field, borrow: bool) -> ::core::option::Option<Tokens> {
163    let ty = &field.ty;
164    let a = &field.attr;
165    if a.default_trait {
166        Some(quote!(<#ty as ::core::default::Default>::default()))
167    } else if let Some(expr) = &a.default {
168        Some(
169            if matches!(
170                expr,
171                Expr::Lit(syn::ExprLit {
172                    lit: syn::Lit::Str(_),
173                    ..
174                })
175            ) {
176                if borrow {
177                    quote!(::core::convert::From::from(#expr))
178                } else {
179                    quote!((#expr).to_owned())
180                }
181            } else {
182                quote!(#expr)
183            },
184        )
185    } else {
186        a.default_factory.as_ref().map(|path| quote!(#path()))
187    }
188}
189fn field_value(field: &Field, raw: Tokens, mode: &Mode) -> Tokens {
190    let rd = mode.rd;
191    let tr = mode.tr();
192    let ty = &field.ty;
193    let rule = rules(field, rd);
194    let missing_error = quote!({__rydantic_ctx.push(#rd::ValidationError::new("missing","field is required").with_stage(#rd::Stage::Parse));None});
195    let default = default_expr(field, mode.borrow);
196    let missing = if let Some(value) = default {
197        quote!(Some({let value:#ty=#value;value}))
198    } else if field.attr.required {
199        missing_error.clone()
200    } else {
201        quote!(match <#ty as #tr>::missing(){Some(value)=>Some(value),None=>#missing_error})
202    };
203    let before=field.attr.before.as_ref().map(|path|quote!{
204        let value=__rydantic_raw.into_value(__rydantic_ctx)?;
205        __rydantic_raw=match #path(value){Ok(value)=>#rd::Input::Owned(value),Err(error)=>{__rydantic_ctx.push(error.with_stage(#rd::Stage::Parse));return None;}};
206    });
207    let decoded = mode.decode(ty, quote!(__rydantic_raw), field.attr.coerce);
208    let default_flow = if field.attr.before.is_some() {
209        quote! {let value:#ty=#missing?;let value=<#ty as #tr>::encode_input(&value,__rydantic_ctx);let mut __rydantic_raw=#rd::Input::Owned(value);#before #decoded?}
210    } else {
211        quote! {let value:#ty=#missing?;<#ty as #tr>::prepare_default(value,__rydantic_ctx)?}
212    };
213    let custom=field.attr.validate.as_ref().map(|path|quote!{if __rydantic_ctx.error_count()==__rydantic_start{if let Err(error)=#path(&__rydantic_value){__rydantic_ctx.push(error);}}});
214    let builtin=field.attr.has_rules().then(||quote!{let rules=#rule;__rydantic_value=<#ty as #tr>::normalize(__rydantic_value,rules,__rydantic_ctx)?;<#ty as #tr>::validate_rules(&__rydantic_value,rules,__rydantic_ctx);});
215    quote! {
216        let __rydantic_start=__rydantic_ctx.error_count();
217        let mut __rydantic_value=match #raw{Some(mut __rydantic_raw)=>{#before #decoded?},None=>{#default_flow}};
218        #builtin #custom Some(__rydantic_value)
219    }
220}
221fn with_location(field: &Field, index: usize, shape: Shape, body: Tokens, _rd: &Tokens) -> Tokens {
222    if field.attr.flatten || field.attr.extra || (shape == Shape::Tuple && index == usize::MAX) {
223        quote! {(||{#body})()}
224    } else if shape == Shape::Tuple {
225        quote! {__rydantic_ctx.at(#index,|__rydantic_ctx|{#body})}
226    } else {
227        let input = &field.input;
228        quote! {__rydantic_ctx.at(#input,|__rydantic_ctx|{#body})}
229    }
230}
231fn object_names(fields: &[Field], rd: &Tokens, tag: ::core::option::Option<&str>) -> Tokens {
232    let names=fields.iter().filter(|f|!f.attr.extra).map(|f|{let ty=&f.ty;let input=&f.input;let output=&f.output;let exclude=f.attr.exclude;
233        if f.attr.flatten{quote!{if !(mode==#rd::SchemaMode::Output&&#exclude){names.extend(<#ty as #rd::ObjectType>::field_names(mode,seen));}}}
234        else{quote!{if !(mode==#rd::SchemaMode::Output&&#exclude){names.push(if mode==#rd::SchemaMode::Input{#input}else{#output}.to_owned());}}}
235    });
236    let tag = tag.map(|tag| quote!(names.push(#tag.to_owned());));
237    quote! {let mut names=::std::vec::Vec::<::std::string::String>::new();#tag #(#names)* names}
238}
239fn collision_checks(
240    fields: &[Field],
241    values: &[Tokens],
242    rd: &Tokens,
243    tag: ::core::option::Option<&str>,
244) -> Tokens {
245    let tag = tag.map(|key| quote!(names.push(#key.to_owned());));
246    let entries = fields.iter().zip(values).map(|(field, value)| {
247        let ty=&field.ty; let input=&field.input; let output=&field.output; let exclude=field.attr.exclude;
248        if field.attr.flatten || field.attr.extra {
249            quote! { if !(mode==#rd::SchemaMode::Output && #exclude) { names.extend(<#ty as #rd::ObjectType>::reserved_names(#value,mode)); } }
250        } else {
251            quote! { if !(mode==#rd::SchemaMode::Output && #exclude) { names.push(if mode==#rd::SchemaMode::Input { #input } else { #output }.to_owned()); } }
252        }
253    });
254    let captures=fields.iter().filter(|f|f.attr.flatten||f.attr.extra).map(|f|{let ty=&f.ty;quote!(usize::from(<#ty as #rd::ObjectType>::captures_extra(&mut ::std::collections::HashSet::new())))});
255    quote! {
256        if 0usize #(+ #captures)* > 1 { __rydantic_ctx.push(#rd::ValidationError::new("flatten_ambiguous","only one flattened field may capture unknown keys")); }
257        for mode in [#rd::SchemaMode::Input,#rd::SchemaMode::Output] {
258            let mut names=::std::vec::Vec::new(); #tag #(#entries)*
259            #rd::__private::check_names(names,__rydantic_ctx);
260        }
261    }
262}
263fn layout_check(fields: &[Field], rd: &Tokens, tag: ::core::option::Option<&str>) -> Tokens {
264    let names = object_names(fields, rd, tag);
265    let catches=fields.iter().filter(|f|f.attr.extra||f.attr.flatten).map(|f|{let ty=&f.ty;quote!(usize::from(<#ty as #rd::ObjectType>::captures_extra(&mut ::std::collections::HashSet::new())))});
266    quote! {
267        for mode in [#rd::SchemaMode::Input,#rd::SchemaMode::Output]{let seen=&mut ::std::collections::HashSet::<&'static str>::new();let names={#names};#rd::__private::check_names(names,__rydantic_ctx);}
268        if 0usize #(+ #catches)*>1{__rydantic_ctx.push(#rd::ValidationError::new("flatten_ambiguous","only one flattened field may capture unknown keys"));return None;}
269    }
270}
271fn parse_shape(
272    fields: &[Field],
273    shape: Shape,
274    constructor: Tokens,
275    container: &attrs::Container,
276    mode: &Mode,
277    tag: ::core::option::Option<&str>,
278) -> Tokens {
279    let rd = mode.rd;
280    let tr = mode.tr();
281    let count = fields.len();
282    let newtype = shape == Shape::Tuple && count == 1;
283    let mut parses = vec![];
284    let locals = (0..count)
285        .map(|i| format_ident!("__rydantic_field_{i}"))
286        .collect::<Vec<_>>();
287    // Declared fields are consumed before flattened maps, independently of Rust field order.
288    let mut order = (0..count).collect::<Vec<_>>();
289    order.sort_by_key(|i| fields[*i].attr.flatten || fields[*i].attr.extra);
290    for i in order {
291        let field = &fields[i];
292        let local = &locals[i];
293        let ty = &field.ty;
294        let input = &field.input;
295        let has_default = field.attr.has_default();
296        let raw = if shape == Shape::Named {
297            if field.attr.flatten || field.attr.extra {
298                quote! {{let names=<#ty as #rd::ObjectType>::field_names(#rd::SchemaMode::Input,&mut ::std::collections::HashSet::new());
299                    let capture=<#ty as #rd::ObjectType>::captures_extra(&mut ::std::collections::HashSet::new());
300                    let mut object=::std::collections::BTreeMap::new();
301                    for name in names{if let Some(value)=__rydantic_object.remove(&name){object.insert(name,value);}}
302                    if capture{object.extend(::core::mem::take(&mut __rydantic_object));}
303                    if object.is_empty()&&(<#ty as #tr>::allows_missing()||#has_default){None}else{Some(#rd::Input::Object(object))}
304                }}
305            } else {
306                quote!(__rydantic_object.remove(#input))
307            }
308        } else if newtype {
309            quote!(Some(__rydantic_raw))
310        } else {
311            quote!(__rydantic_items.next())
312        };
313        let body = field_value(field, raw, mode);
314        let body = with_location(field, if newtype { usize::MAX } else { i }, shape, body, rd);
315        if field.attr.flatten || field.attr.extra {
316            let capture = quote!(<#ty as #rd::ObjectType>::captures_extra(&mut ::std::collections::HashSet::new()));
317            parses.push((
318                i,
319                quote! {if !#capture{#local= #body;}},
320                quote! {if #capture{#local= #body;}},
321            ));
322        } else {
323            parses.push((i, quote! {#local= #body;}, quote!()));
324        }
325    }
326    let first = parses.iter().map(|(_, a, _)| a);
327    let last = parses.iter().map(|(_, _, b)| b);
328    let unknown=(!container.ignore_extra&&shape==Shape::Named).then(||quote!{for (key,_) in __rydantic_object{__rydantic_ctx.at(key,|ctx|ctx.push(#rd::ValidationError::new("extra_forbidden","unknown field").with_stage(#rd::Stage::Parse)));}});
329    let setup = match shape {
330        Shape::Named => {
331            let check = layout_check(fields, rd, tag);
332            quote! {let mut __rydantic_object=__rydantic_raw.object(__rydantic_ctx)?;#check}
333        }
334        Shape::Tuple if !newtype => {
335            quote! {let items=__rydantic_raw.array(__rydantic_ctx)?;if items.len()!=#count{__rydantic_ctx.push(#rd::ValidationError::new("tuple_length",concat!("expected ",stringify!(#count)," tuple items")).with_param("expected",#count).with_param("actual",items.len()));return None;}let mut __rydantic_items=items.into_iter();}
336        }
337        Shape::Unit => {
338            quote! {if !__rydantic_raw.is_null(){__rydantic_ctx.push(#rd::ValidationError::new("type_error","expected null").with_stage(#rd::Stage::Parse));return None;}}
339        }
340        _ => quote!(),
341    };
342    let collision = if shape == Shape::Named {
343        let values = locals
344            .iter()
345            .map(|local| quote!(&#local))
346            .collect::<Vec<_>>();
347        collision_checks(fields, &values, rd, tag)
348    } else {
349        quote!()
350    };
351    let done = if count == 0 {
352        quote!({#collision Some(#constructor)})
353    } else {
354        quote! {match (#(#locals,)*){(#(Some(#locals),)*)=>{#collision Some(#constructor)},_=>None}}
355    };
356    quote! {#setup #(let mut #locals=None;)* #(#first)* #(#last)* #unknown #done}
357}
358fn encode_shape(
359    fields: &[Field],
360    values: &[Tokens],
361    shape: Shape,
362    mode: &Mode,
363    input: bool,
364    tag: ::core::option::Option<(&str, &str)>,
365) -> Tokens {
366    let rd = mode.rd;
367    let tr = mode.tr();
368    let method = if input {
369        format_ident!("encode_input")
370    } else {
371        format_ident!("encode")
372    };
373    let newtype = shape == Shape::Tuple && fields.len() == 1;
374    if shape == Shape::Unit {
375        return quote!(#rd::Value::Null);
376    }
377    let mut entries = vec![];
378    for (i, (field, value)) in fields.iter().zip(values).enumerate() {
379        if !input && field.attr.exclude {
380            continue;
381        }
382        let ty = &field.ty;
383        let key = if input { &field.input } else { &field.output };
384        let encoded = quote!(<#ty as #tr>::#method(#value,__rydantic_ctx));
385        if newtype {
386            return encoded;
387        }
388        if shape == Shape::Tuple {
389            entries.push(
390                quote! {__rydantic_items.push(__rydantic_ctx.at(#i,|__rydantic_ctx|#encoded));},
391            );
392        } else if field.attr.flatten || field.attr.extra {
393            entries.push(quote!{let value=#encoded;#rd::__private::merge(&mut __rydantic_object,value,__rydantic_ctx);});
394        } else {
395            entries.push(quote!{let value=__rydantic_ctx.at(#key,|__rydantic_ctx|#encoded);#rd::__private::merge(&mut __rydantic_object,#rd::__private::serde_json::json!({#key:value}),__rydantic_ctx);});
396        }
397    }
398    if shape == Shape::Tuple {
399        quote! {let mut __rydantic_items=::std::vec::Vec::new();#(#entries)* #rd::Value::Array(__rydantic_items)}
400    } else {
401        let tag=tag.map(|(tag,wire)|quote!{__rydantic_object.insert(#tag.to_owned(),#rd::__private::serde_json::json!(#wire));});
402        quote! {let mut __rydantic_object=#rd::__private::serde_json::Map::new();#tag #(#entries)* #rd::Value::Object(__rydantic_object)}
403    }
404}
405fn validate_fields(fields: &[Field], values: &[Tokens], shape: Shape, mode: &Mode) -> Tokens {
406    let rd = mode.rd;
407    let tr = mode.tr();
408    let checks=fields.iter().zip(values).enumerate().map(|(i,(field,value))|{
409        let ty=&field.ty;let rule=rules(field,rd);
410        let builtin=field.attr.has_rules().then(||quote!(<#ty as #tr>::validate_rules(#value,#rule,__rydantic_ctx);));
411        let custom=field.attr.validate.as_ref().map(|path|quote!(if let Err(error)=#path(#value){__rydantic_ctx.push(error);}));
412        let body=quote!{let start=__rydantic_ctx.error_count();<#ty as #tr>::validate_into(#value,__rydantic_ctx);if start==__rydantic_ctx.error_count(){#builtin #custom}};
413        with_location(field,if shape==Shape::Tuple&&fields.len()==1{usize::MAX}else{i},shape,body,rd)
414    });
415    let collision = if shape == Shape::Named {
416        collision_checks(fields, values, rd, None)
417    } else {
418        quote!()
419    };
420    quote!(#(#checks;)* #collision)
421}
422fn async_fields(fields: &[Field], values: &[Tokens], shape: Shape, rd: &Tokens) -> Tokens {
423    let checks=fields.iter().zip(values).enumerate().map(|(i,(field,value))|{
424        let ty=&field.ty;let input=&field.input;
425        let segment=if field.attr.flatten||field.attr.extra||(shape==Shape::Tuple&&fields.len()==1){quote!(None)}else if shape==Shape::Tuple{quote!(Some(#rd::PathSegment::from(#i)))}else{quote!(Some(#rd::PathSegment::from(#input)))};
426        let custom=field.attr.async_validate.as_ref().map(|path|quote!{if child.error_count()==start{if let Err(error)=#path(#value).await{child.push(error);}}});
427        quote!{let mut child=__rydantic_ctx.child(#segment);let start=child.error_count();<#ty as #rd::AsyncCheck>::check_async(#value,&mut child).await;#custom __rydantic_ctx.absorb(child);}
428    });
429    quote!(#(#checks)*)
430}
431fn property_schema(field: &Field, mode: &Mode) -> Tokens {
432    let rd = mode.rd;
433    let tr = mode.tr();
434    let ty = &field.ty;
435    let coerce = field.attr.coerce;
436    let rule = rules(field, rd);
437    let before=field.attr.before.as_ref().map(|path|quote!{if __rydantic_ctx.mode==#rd::SchemaMode::Input{property=#rd::__private::serde_json::json!({});#rd::schema::annotate_local(&mut property,concat!("before:",stringify!(#path)));}});
438    let condition = if field.attr.before.is_some() {
439        quote!(__rydantic_ctx.mode==#rd::SchemaMode::Output)
440    } else {
441        quote!(true)
442    };
443    let custom=field.attr.validate.iter().map(|path|quote!(#rd::schema::annotate_local(&mut property,concat!("validate:",stringify!(#path)));));
444    let asynchronous=field.attr.async_validate.iter().map(|path|quote!(#rd::schema::annotate_local(&mut property,concat!("async_validate:",stringify!(#path)));));
445    let desc = field
446        .doc
447        .as_ref()
448        .map(|text| quote!(property["description"]=#rd::__private::serde_json::json!(#text);));
449    let literal = field.attr.default.as_ref().and_then(|expr| match expr {
450        Expr::Lit(v) => match &v.lit {
451            syn::Lit::Str(v) => Some(serde_json::json!(v.value())),
452            syn::Lit::Bool(v) => Some(serde_json::json!(v.value)),
453            syn::Lit::Int(v) => v
454                .base10_digits()
455                .parse()
456                .ok()
457                .map(serde_json::Value::Number),
458            syn::Lit::Float(v) => v
459                .base10_digits()
460                .parse()
461                .ok()
462                .map(serde_json::Value::Number),
463            _ => None,
464        },
465        _ => None,
466    });
467    let annotation=literal.map(|v|{let text=v.to_string();quote!(if __rydantic_ctx.mode==#rd::SchemaMode::Input{property["default"]=#rd::__private::serde_json::from_str::<#rd::Value>(#text).expect("literal default");})});
468    quote! {{let mut property=<#ty as #tr>::schema(__rydantic_ctx,#coerce);#before if #condition{#rule.apply_schema(&mut property,__rydantic_ctx.mode,#coerce,<#ty as #tr>::kind());}#(#custom)* #(#asynchronous)* #desc #annotation property}}
469}
470fn schema_shape(
471    fields: &[Field],
472    shape: Shape,
473    container: &attrs::Container,
474    mode: &Mode,
475    tag: ::core::option::Option<(&str, &str)>,
476) -> Tokens {
477    let rd = mode.rd;
478    let tr = mode.tr();
479    if shape == Shape::Unit {
480        return quote!(#rd::__private::serde_json::json!({"type":"null"}));
481    }
482    if shape == Shape::Tuple {
483        let props = fields.iter().map(|f| property_schema(f, mode));
484        let count = fields.len();
485        if count == 0 {
486            return quote!(#rd::__private::serde_json::json!({"type":"array","items":false,"maxItems":0}));
487        }
488        if count == 1 {
489            return props.into_iter().next().expect("one field");
490        }
491        return quote!(#rd::__private::serde_json::json!({"type":"array","prefixItems":[#((#props)),*],"items":false,"minItems":#count,"maxItems":#count}));
492    }
493    let ignore = container.ignore_extra;
494    let known_names = object_names(fields, rd, tag.map(|(key, _)| key));
495    let captures=fields.iter().filter(|f|f.attr.flatten||f.attr.extra).map(|f|{let ty=&f.ty;quote!(usize::from(<#ty as #rd::ObjectType>::captures_extra(&mut ::std::collections::HashSet::new())))});
496    let tag=tag.map(|(key,value)|quote!{schema["properties"][#key]=#rd::__private::serde_json::json!({"type":"string","const":#value});schema["required"].as_array_mut().expect("required").push(#rd::__private::serde_json::json!(#key));});
497    let inserts=fields.iter().map(|f|{let ty=&f.ty;let input=&f.input;let output=&f.output;let exclude=f.attr.exclude;let required=f.attr.required;let default=f.attr.has_default();let property=property_schema(f,mode);
498        let insert=if f.attr.flatten||f.attr.extra{
499            let optional=quote!((__rydantic_ctx.mode==#rd::SchemaMode::Input&&#default)||((!#required||__rydantic_ctx.mode==#rd::SchemaMode::Output)&&<#ty as #tr>::allows_missing()));
500            quote!{let child=#property;#rd::__private::flatten_schema(&mut schema,child,(#optional),<#ty as #rd::ObjectType>::captures_extra(&mut ::std::collections::HashSet::new()),__rydantic_ctx);}
501        }else{quote!{let key=if __rydantic_ctx.mode==#rd::SchemaMode::Input{#input}else{#output};let property=#property;schema["properties"].as_object_mut().expect("properties").insert(key.to_owned(),property);if __rydantic_ctx.mode==#rd::SchemaMode::Output||#required||(!#default&&!<#ty as #tr>::allows_missing()){schema["required"].as_array_mut().expect("required").push(#rd::__private::serde_json::json!(key));}}};
502        quote!{if !(__rydantic_ctx.mode==#rd::SchemaMode::Output&&#exclude){#insert}}
503    });
504    quote! {{let mut schema=#rd::__private::serde_json::json!({"type":"object","properties":{},"required":[],"allOf":[],"additionalProperties":(#ignore&&__rydantic_ctx.mode==#rd::SchemaMode::Input)});#tag #(#inserts)*
505    let captures=0usize #(+ #captures)*;
506    if captures>1 { schema["allOf"].as_array_mut().expect("allOf").push(#rd::Value::Bool(false)); }
507    let mut views=::std::vec::Vec::new();
508    for mode in [#rd::SchemaMode::Input,#rd::SchemaMode::Output] {
509        let seen=&mut ::std::collections::HashSet::<&'static str>::new(); let names={#known_names};
510        let mut unique=::std::collections::HashSet::new();
511        if names.iter().any(|name|!unique.insert(name)) { schema["allOf"].as_array_mut().expect("allOf").push(#rd::Value::Bool(false)); }
512        views.push(names);
513    }
514    let mut required=::std::collections::HashSet::new();
515    schema["required"].as_array_mut().expect("required").retain(|key|required.insert(key.as_str().expect("key").to_owned()));
516    if captures>0 && views[0]!=views[1] && __rydantic_ctx.mode==#rd::SchemaMode::Input {#rd::schema::annotate_local(&mut schema,"extra_alias_collision");}
517    if schema["allOf"].as_array().is_some_and(|v|v.is_empty()){schema.as_object_mut().expect("schema").remove("allOf");}schema}}
518}
519fn constructor(fields: &[Field], shape: Shape, path: Tokens) -> Tokens {
520    let locals = (0..fields.len())
521        .map(|i| format_ident!("__rydantic_field_{i}"))
522        .collect::<Vec<_>>();
523    let names = fields.iter().map(|f| &f.ident);
524    match shape {
525        Shape::Named => quote!(#path{#(#names:#locals,)*}),
526        Shape::Tuple => quote!(#path(#(#locals,)*)),
527        Shape::Unit => path,
528    }
529}
530fn pattern(fields: &[Field], shape: Shape, path: Tokens) -> (Tokens, Vec<Tokens>) {
531    let locals = (0..fields.len())
532        .map(|i| format_ident!("__rydantic_field_{i}"))
533        .collect::<Vec<_>>();
534    let names = fields.iter().map(|f| &f.ident);
535    let values = locals.iter().map(|l| quote!(#l)).collect();
536    let pat = match shape {
537        Shape::Named => quote!(#path{#(#names:#locals,)*}),
538        Shape::Tuple => quote!(#path(#(#locals,)*)),
539        Shape::Unit => path,
540    };
541    (pat, values)
542}
543fn prepare_fields(fields: &[Field], shape: Shape, mode: &Mode, path: Tokens) -> Tokens {
544    let rd = mode.rd;
545    let tr = mode.tr();
546    let (pat, _) = pattern(fields, shape, path.clone());
547    let constructor = constructor(fields, shape, path);
548    let locals = (0..fields.len())
549        .map(|i| format_ident!("__rydantic_field_{i}"))
550        .collect::<Vec<_>>();
551    let prepare=fields.iter().enumerate().map(|(i,f)|{let ty=&f.ty;let local=&locals[i];let rule=rules(f,rd);
552        let raw=if let Some(path)=&f.attr.before{let decoded=mode.decode(ty,quote!(#rd::Input::Owned(raw)),f.attr.coerce);quote!{let raw=<#ty as #tr>::encode_input(&#local,__rydantic_ctx);let raw=match #path(raw){Ok(v)=>v,Err(e)=>{__rydantic_ctx.push(e.with_stage(#rd::Stage::Parse));return None;}};let mut value=#decoded?;}}
553        else{quote!(let mut value=<#ty as #tr>::prepare_default(#local,__rydantic_ctx)?;)};
554        let builtin=f.attr.has_rules().then(||quote!{value=<#ty as #tr>::normalize(value,#rule,__rydantic_ctx)?;<#ty as #tr>::validate_rules(&value,#rule,__rydantic_ctx);});
555        let custom=f.attr.validate.as_ref().map(|path|quote!{if start==__rydantic_ctx.error_count(){if let Err(error)=#path(&value){__rydantic_ctx.push(error);}}});
556        let body=quote!{let start=__rydantic_ctx.error_count();#raw #builtin #custom Some(value)};
557        let body=with_location(f,if shape==Shape::Tuple&&fields.len()==1{usize::MAX}else{i},shape,body,rd);quote!(let #local=#body;)
558    });
559    let done = if fields.is_empty() {
560        quote!(Some(#constructor))
561    } else {
562        quote!(match (#(#locals,)*){(#(Some(#locals),)*)=>Some(#constructor),_=>None})
563    };
564    quote!(#pat=>{#(#prepare)* #done})
565}
566fn expand(input: DeriveInput) -> syn::Result<Tokens> {
567    let rd = match proc_macro_crate::crate_name("rydantic")
568        .map_err(|e| syn::Error::new(input.ident.span(), e))?
569    {
570        proc_macro_crate::FoundCrate::Itself => quote!(::rydantic),
571        proc_macro_crate::FoundCrate::Name(name) => {
572            let name = format_ident!("{name}");
573            quote!(::#name)
574        }
575    };
576    let container = attrs::container(&input.attrs)?;
577    let native_capnp = native::expand(&input, &container, &rd)?;
578    let name = &input.ident;
579    let title = container.title.clone().unwrap_or_else(|| name.to_string());
580    let borrowed = input.generics.lifetimes().next().is_some();
581    let mode = Mode {
582        rd: &rd,
583        borrow: borrowed,
584    };
585    let tr = mode.tr();
586    let mut all_fields = Vec::new();
587    let mut object_impl = None;
588    let (decode, encode, encode_input, validate, schema, asynchronous, kind) = match &input.data {
589        Data::Struct(data) => {
590            if container.tag.is_some() || container.untagged {
591                return Err(syn::Error::new(
592                    name.span(),
593                    "tag and untagged are supported on enums",
594                ));
595            }
596            let fields = fields(&data.fields, None, &container)?;
597            let shape = shape(&data.fields);
598            let ctor = constructor(&fields, shape, quote!(Self));
599            let decode = parse_shape(&fields, shape, ctor, &container, &mode, None);
600            let values = fields
601                .iter()
602                .map(|f| {
603                    let m = &f.member;
604                    quote!(&self.#m)
605                })
606                .collect::<Vec<_>>();
607            let encode = encode_shape(&fields, &values, shape, &mode, false, None);
608            let encode_input = encode_shape(&fields, &values, shape, &mode, true, None);
609            let validate = validate_fields(&fields, &values, shape, &mode);
610            let schema = schema_shape(&fields, shape, &container, &mode, None);
611            let asynchronous = async_fields(&fields, &values, shape, &rd);
612            let kind = match shape {
613                Shape::Named => quote!(#rd::TypeKind::Object),
614                Shape::Tuple if fields.len() == 1 => {
615                    let ty = &fields[0].ty;
616                    quote!(<#ty as #tr>::kind())
617                }
618                Shape::Tuple => quote!(#rd::TypeKind::Array),
619                Shape::Unit => quote!(#rd::TypeKind::Any),
620            };
621            if shape == Shape::Named {
622                let names = object_names(&fields, &rd, None);
623                let present=fields.iter().map(|f|{let ty=&f.ty;let member=&f.member;let input=&f.input;let output=&f.output;let exclude=f.attr.exclude;
624                    if f.attr.flatten||f.attr.extra{quote!{if !(mode==#rd::SchemaMode::Output&&#exclude){names.extend(<#ty as #rd::ObjectType>::reserved_names(&self.#member,mode));}}}
625                    else{quote!{if !(mode==#rd::SchemaMode::Output&&#exclude){names.push(if mode==#rd::SchemaMode::Input{#input}else{#output}.to_owned());}}}
626                });
627                let extra = fields
628                    .iter()
629                    .filter(|f| f.attr.flatten || f.attr.extra)
630                    .map(|f| {
631                        let ty = &f.ty;
632                        quote!(<#ty as #rd::ObjectType>::captures_extra(seen))
633                    });
634                object_impl = Some(quote! {
635                    fn reserved_names(&self,mode:#rd::SchemaMode)->::std::vec::Vec<::std::string::String>{let mut names=::std::vec::Vec::new();#(#present)* names}
636                    fn field_names(mode:#rd::SchemaMode,seen:&mut ::std::collections::HashSet<&'static str>)->::std::vec::Vec<::std::string::String>{if !seen.insert(::core::any::type_name::<Self>()){return ::std::vec::Vec::new();}let names={#names};seen.remove(::core::any::type_name::<Self>());names}
637                    fn captures_extra(seen:&mut ::std::collections::HashSet<&'static str>)->bool{if !seen.insert(::core::any::type_name::<Self>()){return false;}let captures=false #(|| #extra)*;seen.remove(::core::any::type_name::<Self>());captures}
638                });
639            }
640            all_fields.extend(fields);
641            (
642                decode,
643                encode,
644                encode_input,
645                validate,
646                schema,
647                asynchronous,
648                kind,
649            )
650        }
651        Data::Enum(data) => {
652            if data.variants.is_empty() {
653                return Err(syn::Error::new(
654                    name.span(),
655                    "Model requires at least one enum variant",
656                ));
657            }
658            let mut variants = vec![];
659            let mut seen = std::collections::HashSet::new();
660            for v in &data.variants {
661                let wire = attrs::variant_name(&v.attrs, &v.ident.to_string())?;
662                if !seen.insert(wire.clone()) {
663                    return Err(syn::Error::new(
664                        v.ident.span(),
665                        "duplicate enum variant name",
666                    ));
667                }
668                let shape = shape(&v.fields);
669                if container.tag.is_some() && shape == Shape::Tuple {
670                    return Err(syn::Error::new(v.ident.span(),"internally tagged enums require named fields or unit variants; use untagged for tuple variants"));
671                }
672                if container.tag.is_none() && !container.untagged && shape != Shape::Unit {
673                    return Err(syn::Error::new(
674                        v.ident.span(),
675                        "enums with fields require #[model(tag = \"...\")] or #[model(untagged)]",
676                    ));
677                }
678                variants.push((
679                    &v.ident,
680                    wire,
681                    shape,
682                    fields(&v.fields, container.tag.as_deref(), &container)?,
683                ));
684            }
685            let mut decodes = vec![];
686            let mut encodes = vec![];
687            let mut input_encodes = vec![];
688            let mut validates = vec![];
689            let mut asyncs = vec![];
690            let mut schemas = vec![];
691            let wires = variants.iter().map(|(_, w, _, _)| w).collect::<Vec<_>>();
692            for (variant, wire, shape, fields) in &variants {
693                let (pat, values) = pattern(fields, *shape, quote!(Self::#variant));
694                let ctor = constructor(fields, *shape, quote!(Self::#variant));
695                let wire_shape = if container.tag.is_some() {
696                    Shape::Named
697                } else {
698                    *shape
699                };
700                let tag = container.tag.as_deref().map(|t| (t, wire.as_str()));
701                let (encode, encode_input, schema) =
702                    if !container.untagged && container.tag.is_none() {
703                        (
704                            quote!(#rd::__private::serde_json::json!(#wire)),
705                            quote!(#rd::__private::serde_json::json!(#wire)),
706                            quote!(),
707                        )
708                    } else {
709                        (
710                            encode_shape(fields, &values, wire_shape, &mode, false, tag),
711                            encode_shape(fields, &values, wire_shape, &mode, true, tag),
712                            schema_shape(fields, wire_shape, &container, &mode, tag),
713                        )
714                    };
715                encodes.push(quote!(#pat=>{#encode}));
716                input_encodes.push(quote!(#pat=>{#encode_input}));
717                let checks = validate_fields(fields, &values, *shape, &mode);
718                validates.push(quote!(#pat=>{#checks}));
719                let checks = async_fields(fields, &values, *shape, &rd);
720                asyncs.push(quote!(#pat=>{#checks}));
721                schemas.push(schema);
722                if container.untagged {
723                    let body = parse_shape(fields, *shape, ctor, &container, &mode, None);
724                    decodes.push(quote!{
725                        {let mut trial=#rd::Context::new();let result={let __rydantic_ctx=&mut trial;let __rydantic_raw=__rydantic_raw.clone();(||{#body})()};
726                        match trial.finish(result){Ok(value)=>return Some(value),Err(errors)=>__rydantic_branches.push(#rd::__private::serde_json::json!({"variant":#wire,"errors":errors.to_json()}))}}
727                    });
728                } else if container.tag.is_some() {
729                    let body = parse_shape(
730                        fields,
731                        wire_shape,
732                        ctor,
733                        &container,
734                        &mode,
735                        container.tag.as_deref(),
736                    );
737                    decodes.push(quote!(#wire=>{let __rydantic_raw=#rd::Input::Object(__rydantic_object);#body}));
738                } else {
739                    decodes.push(quote!(#wire=>Some(#ctor)));
740                }
741            }
742            let (decode, schema, kind) = if container.untagged {
743                (
744                    quote! {let mut __rydantic_branches=::std::vec::Vec::<#rd::Value>::new();#(#decodes)* __rydantic_ctx.push(#rd::ValidationError::new("union_no_match","no untagged variant accepted the value").with_stage(#rd::Stage::Parse).with_param("branches",#rd::Value::Array(__rydantic_branches)));None},
745                    quote!(#rd::__private::serde_json::json!({"anyOf":[#((#schemas)),*]})),
746                    quote!(#rd::TypeKind::Any),
747                )
748            } else if let Some(tag) = &container.tag {
749                (
750                    quote! {let mut __rydantic_object=__rydantic_raw.object(__rydantic_ctx)?;let tag=match __rydantic_object.remove(#tag){Some(raw)=>{let value=raw.into_value(__rydantic_ctx)?;match value{#rd::Value::String(value)=>value,_=>{__rydantic_ctx.at(#tag,|ctx|ctx.push(#rd::ValidationError::new("union_tag_type","discriminator must be a string").with_stage(#rd::Stage::Parse)));return None;}}},None=>{__rydantic_ctx.at(#tag,|ctx|ctx.push(#rd::ValidationError::new("union_tag_missing","discriminator is required").with_stage(#rd::Stage::Parse)));return None;}};
751                    match tag.as_str(){#(#decodes,)* _=>{__rydantic_ctx.at(#tag,|ctx|ctx.push(#rd::ValidationError::new("union_tag_invalid","unknown discriminator").with_stage(#rd::Stage::Parse).with_param("expected",#rd::__private::serde_json::json!([#(#wires),*]))));None}}},
752                    quote!(#rd::__private::serde_json::json!({"oneOf":[#((#schemas)),*],"discriminator":{"propertyName":#tag}})),
753                    quote!(#rd::TypeKind::Object),
754                )
755            } else {
756                (
757                    quote! {let raw=__rydantic_raw.into_value(__rydantic_ctx)?;match raw.as_str(){Some(wire)=>match wire{#(#decodes,)* _=>{__rydantic_ctx.push(#rd::ValidationError::new("enum","unknown enum value").with_stage(#rd::Stage::Parse).with_param("expected",#rd::__private::serde_json::json!([#(#wires),*])));None}},None=>{__rydantic_ctx.push(#rd::ValidationError::new("type_error","expected enum string").with_stage(#rd::Stage::Parse));None}}},
758                    quote!(#rd::__private::serde_json::json!({"type":"string","enum":[#(#wires),*]})),
759                    quote!(#rd::TypeKind::String),
760                )
761            };
762            for (_, _, _, fields) in variants {
763                all_fields.extend(fields);
764            }
765            (
766                decode,
767                quote!(match self{#(#encodes,)*}),
768                quote!(match self{#(#input_encodes,)*}),
769                quote!(match self{#(#validates,)*}),
770                schema,
771                quote!(match self{#(#asyncs,)*}),
772                kind,
773            )
774        }
775        Data::Union(_) => {
776            return Err(syn::Error::new(
777                name.span(),
778                "Model cannot be derived for unions",
779            ))
780        }
781    };
782    let prepare_default = {
783        let arms = match &input.data {
784            Data::Struct(data) => {
785                let fields = fields(&data.fields, None, &container)?;
786                let arm = prepare_fields(&fields, shape(&data.fields), &mode, quote!(Self));
787                quote!(#arm)
788            }
789            Data::Enum(data) => {
790                let mut arms = vec![];
791                for v in &data.variants {
792                    let variant = &v.ident;
793                    let fields = fields(&v.fields, container.tag.as_deref(), &container)?;
794                    arms.push(prepare_fields(
795                        &fields,
796                        shape(&v.fields),
797                        &mode,
798                        quote!(Self::#variant),
799                    ));
800                }
801                quote!(#(#arms,)*)
802            }
803            _ => unreachable!(),
804        };
805        let custom=container.validate.as_ref().map(|path|quote!{if start==ctx.error_count(){if let Some(value)=&value{if let Err(errors)=#path(value){ctx.extend(errors);}}}});
806        quote! {fn prepare_default(self,ctx:&mut #rd::Context)->::core::option::Option<Self>{let start=ctx.error_count();let value={let __rydantic_ctx=&mut *ctx;match self{#arms}};#custom value}}
807    };
808    let mut generics = input.generics.clone();
809    if borrowed {
810        generics.params.insert(0, parse_quote!('__rydantic_de));
811        for lt in input.generics.lifetimes() {
812            let lt = &lt.lifetime;
813            generics
814                .make_where_clause()
815                .predicates
816                .push(parse_quote!('__rydantic_de:#lt));
817        }
818    }
819    for p in generics.type_params_mut() {
820        p.bounds.push(parse_quote!(#tr));
821    }
822    fn contains_generic(ty: &Type, ident: &Ident) -> bool {
823        match ty{Type::Path(p)=>p.path.segments.iter().any(|s|s.ident==*ident||matches!(&s.arguments,syn::PathArguments::AngleBracketed(a) if a.args.iter().any(|arg|matches!(arg,syn::GenericArgument::Type(t)if contains_generic(t,ident))))),Type::Array(a)=>contains_generic(&a.elem,ident),Type::Reference(r)=>contains_generic(&r.elem,ident),Type::Tuple(t)=>t.elems.iter().any(|t|contains_generic(t,ident)),_=>false}
824    }
825    let mut assertions = vec![];
826    for f in &all_fields {
827        let ty = &f.ty;
828        let a = &f.attr;
829        let generic = input
830            .generics
831            .type_params()
832            .any(|p| contains_generic(ty, &p.ident));
833        let mut bounds = vec![];
834        if a.trim || a.lowercase || a.uppercase || a.email || a.pattern.is_some() {
835            assertions.push(quote!(__rydantic_assert_string::<#ty>();));
836            bounds.push(quote!(#rd::StringType));
837        }
838        if a.min_length.is_some() || a.max_length.is_some() {
839            assertions.push(quote!(__rydantic_assert_length::<#ty>();));
840            bounds.push(quote!(#rd::LengthType));
841        }
842        if a.ge.is_some() || a.gt.is_some() || a.le.is_some() || a.lt.is_some() {
843            assertions.push(quote!(__rydantic_assert_number::<#ty>();));
844            bounds.push(quote!(#rd::NumericType));
845        }
846        if a.flatten {
847            bounds.push(quote!(#rd::ObjectType));
848        }
849        if a.extra {
850            bounds.push(quote!(#rd::ExtraFields));
851            assertions.push(quote!(__rydantic_assert_extra::<#ty>();));
852        }
853        if a.default_trait {
854            bounds.push(quote!(::core::default::Default));
855        }
856        if generic {
857            for bound in bounds {
858                generics
859                    .make_where_clause()
860                    .predicates
861                    .push(parse_quote!(#ty:#bound));
862            }
863        }
864    }
865    let (_, ty_generics, _) = input.generics.split_for_impl();
866    let (impl_generics, _, where_clause) = generics.split_for_impl();
867    let mut de_generics = generics.clone();
868    if !borrowed {
869        de_generics.params.insert(0, parse_quote!('__rydantic_de));
870    }
871    let (de_impl_generics, _, de_where_clause) = de_generics.split_for_impl();
872    let custom_parse=container.validate.as_ref().map(|path|quote!{if __rydantic_ctx.error_count()==start{if let Some(value)=&value{if let Err(errors)=#path(value){__rydantic_ctx.extend(errors);}}}});
873    let custom_validate=container.validate.as_ref().map(|path|quote!{if __rydantic_ctx.error_count()==start{if let Err(errors)=#path(self){__rydantic_ctx.extend(errors);}}});
874    let schema_custom=container.validate.as_ref().map(|path|quote!(#rd::schema::annotate_local(&mut schema,concat!("validate:",stringify!(#path)));));
875    let schema_async=container.async_validate.as_ref().map(|path|quote!(#rd::schema::annotate_local(&mut schema,concat!("async_validate:",stringify!(#path)));));
876    let direct_async = container.async_validate.is_some()
877        || all_fields.iter().any(|f| f.attr.async_validate.is_some());
878    let nested_async = all_fields.iter().map(|f| {
879        let ty = &f.ty;
880        quote!(<#ty as #tr>::async_required(seen))
881    });
882    let model_impl = if borrowed {
883        quote!(impl #impl_generics #rd::BorrowModel<'__rydantic_de> for #name #ty_generics #where_clause {})
884    } else {
885        quote!(impl #impl_generics #rd::Model for #name #ty_generics #where_clause {})
886    };
887    let dump = if borrowed {
888        quote!(<Self as #rd::BorrowModel<'__rydantic_de>>::dump(self))
889    } else {
890        quote!(<Self as #rd::Model>::dump(self))
891    };
892    let deserialize = if borrowed {
893        quote! {let raw=<&'__rydantic_de #rd::__private::serde_json::value::RawValue as #rd::__private::serde::Deserialize>::deserialize(deserializer)?;<Self as #rd::BorrowModel<'__rydantic_de>>::parse_raw(raw).map_err(#rd::__private::serde::de::Error::custom)}
894    } else {
895        quote! {let raw=<::std::boxed::Box<#rd::RawValue> as #rd::__private::serde::Deserialize>::deserialize(deserializer)?;<Self as #rd::Model>::parse_raw(&raw).map_err(#rd::__private::serde::de::Error::custom)}
896    };
897    let object_impl=object_impl.map(|body|quote!(impl #impl_generics #rd::ObjectType for #name #ty_generics #where_clause{#body}));
898    let bridge=(!borrowed).then(||quote!{
899        impl #de_impl_generics #rd::BorrowType<'__rydantic_de> for #name #ty_generics #de_where_clause{
900            fn decode(raw:#rd::Input<'__rydantic_de>,ctx:&mut #rd::Context,coerce:bool)->::core::option::Option<Self>{<Self as #rd::JsonType>::decode_input(raw,ctx,coerce)}
901            fn prepare_default(self,ctx:&mut #rd::Context)->::core::option::Option<Self>{<Self as #rd::JsonType>::prepare_default(self,ctx)}
902            fn encode(&self,ctx:&mut #rd::Context)->#rd::Value{<Self as #rd::JsonType>::encode(self,ctx)}
903            fn encode_input(&self,ctx:&mut #rd::Context)->#rd::Value{<Self as #rd::JsonType>::encode_input(self,ctx)}
904            fn schema(ctx:&mut #rd::SchemaContext,coerce:bool)->#rd::Value{<Self as #rd::JsonType>::schema(ctx,coerce)}
905            fn validate_into(&self,ctx:&mut #rd::Context){<Self as #rd::JsonType>::validate_into(self,ctx)}
906            fn normalize(self,rules:&#rd::rules::Rules,ctx:&mut #rd::Context)->::core::option::Option<Self>{<Self as #rd::JsonType>::normalize(self,rules,ctx)}
907            fn validate_rules(&self,rules:&#rd::rules::Rules,ctx:&mut #rd::Context){<Self as #rd::JsonType>::validate_rules(self,rules,ctx)}
908            fn async_required(seen:&mut ::std::collections::HashSet<&'static str>)->bool{<Self as #rd::JsonType>::async_required(seen)}
909            fn kind()->#rd::TypeKind{<Self as #rd::JsonType>::kind()}
910        }
911    });
912    let mut async_generics = input.generics.clone();
913    for p in async_generics.type_params_mut() {
914        p.bounds.push(parse_quote!(#rd::AsyncCheck));
915    }
916    let (async_impl_generics, _, async_where_clause) = async_generics.split_for_impl();
917    let custom_async=container.async_validate.as_ref().map(|path|quote!{if start==__rydantic_ctx.error_count(){if let Err(errors)=#path(self).await{__rydantic_ctx.extend(errors);}}});
918    let body = quote! {
919        fn __rydantic_assert_string<T:#rd::StringType>(){}fn __rydantic_assert_length<T:#rd::LengthType>(){}fn __rydantic_assert_number<T:#rd::NumericType>(){}fn __rydantic_assert_extra<T:#rd::ExtraFields>(){}
920        #(#assertions)* let start=__rydantic_ctx.error_count();let value=(||{#decode})();#custom_parse value
921    };
922    let decode_methods = if borrowed {
923        quote! {fn decode(__rydantic_raw:#rd::Input<'__rydantic_de>,__rydantic_ctx:&mut #rd::Context,_coerce:bool)->::core::option::Option<Self>{#body}}
924    } else {
925        quote! {
926            fn decode(raw:#rd::Value,ctx:&mut #rd::Context,coerce:bool)->::core::option::Option<Self>{<Self as #rd::JsonType>::decode_input(#rd::Input::Owned(raw),ctx,coerce)}
927            fn decode_input(__rydantic_raw:#rd::Input<'_>,__rydantic_ctx:&mut #rd::Context,_coerce:bool)->::core::option::Option<Self>{#body}
928        }
929    };
930    Ok(quote! {
931        impl #impl_generics #tr for #name #ty_generics #where_clause{
932            #decode_methods
933            #prepare_default
934            fn encode(&self,__rydantic_ctx:&mut #rd::Context)->#rd::Value{#encode}
935            fn encode_input(&self,__rydantic_ctx:&mut #rd::Context)->#rd::Value{#encode_input}
936            fn validate_into(&self,__rydantic_ctx:&mut #rd::Context){let start=__rydantic_ctx.error_count();#validate #custom_validate}
937            fn schema(__rydantic_ctx:&mut #rd::SchemaContext,_coerce:bool)->#rd::Value{__rydantic_ctx.reference(::core::any::type_name::<Self>(),|__rydantic_ctx|{let mut schema=#schema;schema["title"]=#rd::__private::serde_json::json!(#title);#schema_custom #schema_async schema})}
938            fn kind()->#rd::TypeKind{#kind}
939            fn async_required(seen:&mut ::std::collections::HashSet<&'static str>)->bool{if !seen.insert(::core::any::type_name::<Self>()){return false;}#direct_async #(|| #nested_async)*}
940        }
941        #model_impl #object_impl #bridge #native_capnp
942        impl #async_impl_generics #rd::AsyncCheck for #name #ty_generics #async_where_clause{
943            fn check_async<'__rydantic_future>(&'__rydantic_future self,__rydantic_ctx:&'__rydantic_future mut #rd::Context)->#rd::BoxFuture<'__rydantic_future,()>{
944                ::std::boxed::Box::pin(async move{let start=__rydantic_ctx.error_count();#asynchronous #custom_async})
945            }
946        }
947        impl #impl_generics #rd::__private::serde::Serialize for #name #ty_generics #where_clause{
948            fn serialize<S:#rd::__private::serde::Serializer>(&self,serializer:S)->::core::result::Result<S::Ok,S::Error>{let value=#dump.map_err(#rd::__private::serde::ser::Error::custom)?;#rd::__private::serde::Serialize::serialize(&value,serializer)}
949        }
950        impl #de_impl_generics #rd::__private::serde::Deserialize<'__rydantic_de> for #name #ty_generics #de_where_clause{
951            fn deserialize<D:#rd::__private::serde::Deserializer<'__rydantic_de>>(deserializer:D)->::core::result::Result<Self,D::Error>{#deserialize}
952        }
953    })
954}