1use std::collections::{BTreeMap, BTreeSet, HashMap};
4
5use proc_macro2::{Punct, Spacing, TokenStream, TokenTree};
6use quote::{format_ident, quote, ToTokens};
7use schemars::schema::{Metadata, Schema};
8use syn::Path;
9use unicode_ident::is_xid_continue;
10
11use crate::{
12 enums::output_variant,
13 output::{OutputSpace, OutputSpaceMod},
14 sanitize,
15 structs::{generate_serde_attr, DefaultFunction},
16 util::{get_type_name, metadata_description, type_patch, unique},
17 Case, DefaultImpl, Name, Result, TypeId, TypeSpace, TypeSpaceImpl,
18};
19
20#[derive(Debug, Clone, PartialEq)]
21pub(crate) struct SchemaWrapper(Schema);
22
23impl Eq for SchemaWrapper {}
24
25impl Ord for SchemaWrapper {
26 fn cmp(&self, _other: &Self) -> std::cmp::Ordering {
27 std::cmp::Ordering::Equal
28 }
29}
30impl PartialOrd for SchemaWrapper {
31 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
32 Some(self.cmp(other))
33 }
34}
35
36#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
37pub(crate) struct TypeEntryEnum {
38 pub name: String,
39 pub rename: Option<String>,
40 pub description: Option<String>,
41 pub default: Option<WrappedValue>,
42 pub tag_type: EnumTagType,
43 pub variants: Vec<Variant>,
44 pub deny_unknown_fields: bool,
45 pub bespoke_impls: BTreeSet<TypeEntryEnumImpl>,
46 pub schema: SchemaWrapper,
47}
48
49#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
51pub(crate) enum TypeEntryEnumImpl {
52 AllSimpleVariants,
53 UntaggedFromStr,
54 UntaggedDisplay,
55 UntaggedFromStringIrrefutable,
59}
60
61#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
62pub(crate) struct TypeEntryStruct {
63 pub name: String,
64 pub rename: Option<String>,
65 pub description: Option<String>,
66 pub default: Option<WrappedValue>,
67 pub properties: Vec<StructProperty>,
68 pub deny_unknown_fields: bool,
69 pub schema: SchemaWrapper,
70}
71
72#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
73pub(crate) struct TypeEntryNewtype {
74 pub name: String,
75 pub rename: Option<String>,
76 pub description: Option<String>,
77 pub default: Option<WrappedValue>,
78 pub type_id: TypeId,
79 pub constraints: TypeEntryNewtypeConstraints,
80 pub schema: SchemaWrapper,
81}
82
83#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
84pub(crate) enum TypeEntryNewtypeConstraints {
85 None,
86 EnumValue(Vec<WrappedValue>),
87 DenyValue(Vec<WrappedValue>),
88 String {
89 max_length: Option<u32>,
90 min_length: Option<u32>,
91 pattern: Option<String>,
92 },
93}
94
95#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
96pub(crate) struct TypeEntryNative {
97 pub type_name: String,
98 impls: Vec<TypeSpaceImpl>,
99 pub parameters: Vec<TypeId>,
103}
104impl TypeEntryNative {
105 pub(crate) fn name_match(&self, type_name: &Name) -> bool {
106 let native_name = self.type_name.rsplit("::").next().unwrap();
107 !self.parameters.is_empty()
108 || matches!(type_name, Name::Required(req) if req == native_name)
109 }
110}
111
112#[derive(Debug, Clone, PartialEq, Eq)]
113pub(crate) struct WrappedValue(pub serde_json::Value);
114impl WrappedValue {
115 pub(crate) fn new(value: serde_json::Value) -> Self {
116 Self(value)
117 }
118}
119
120impl Ord for WrappedValue {
121 fn cmp(&self, _: &Self) -> std::cmp::Ordering {
122 std::cmp::Ordering::Equal
123 }
124}
125impl PartialOrd for WrappedValue {
126 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
127 Some(self.cmp(other))
128 }
129}
130
131#[derive(Debug, Clone, PartialEq, Eq)]
138pub(crate) struct TypeEntry {
139 pub details: TypeEntryDetails,
140 pub extra_derives: BTreeSet<String>,
141}
142
143#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
144pub(crate) enum TypeEntryDetails {
145 Enum(TypeEntryEnum),
146 Struct(TypeEntryStruct),
147 Newtype(TypeEntryNewtype),
148
149 Native(TypeEntryNative),
151
152 Option(TypeId),
154 Box(TypeId),
155 Vec(TypeId),
156 Map(TypeId, TypeId),
157 Set(TypeId),
158 Array(TypeId, usize),
159 Tuple(Vec<TypeId>),
160 Unit,
161 Boolean,
162 Integer(String),
164 Float(String),
166 String,
168 JsonValue,
170
171 Reference(TypeId),
175}
176
177#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
178pub(crate) enum EnumTagType {
179 External,
180 Internal { tag: String },
181 Adjacent { tag: String, content: String },
182 Untagged,
183}
184
185#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
186pub(crate) struct Variant {
187 pub raw_name: String,
188 pub ident_name: Option<String>,
189 pub description: Option<String>,
190 pub details: VariantDetails,
191}
192
193#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
194pub(crate) enum VariantDetails {
195 Simple,
196 Item(TypeId),
197 Tuple(Vec<TypeId>),
198 Struct(Vec<StructProperty>),
199}
200
201#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
202pub(crate) struct StructProperty {
203 pub name: String,
204 pub rename: StructPropertyRename,
205 pub state: StructPropertyState,
206 pub description: Option<String>,
207 pub type_id: TypeId,
208}
209
210#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
211pub(crate) enum StructPropertyRename {
212 None,
213 Rename(String),
214 Flatten,
215}
216
217#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
218pub(crate) enum StructPropertyState {
219 Required,
220 Optional,
221 Default(WrappedValue),
222}
223
224#[derive(Debug)]
225pub(crate) enum DefaultKind {
226 Intrinsic,
227 Specific,
228 Generic(DefaultImpl),
229}
230
231fn variants_unique(variants: &[Variant]) -> bool {
232 unique(
233 variants
234 .iter()
235 .map(|variant| variant.ident_name.as_ref().unwrap()),
236 )
237}
238
239impl TypeEntryEnum {
240 pub(crate) fn from_metadata(
241 type_space: &TypeSpace,
242 type_name: Name,
243 metadata: &Option<Box<Metadata>>,
244 tag_type: EnumTagType,
245 mut variants: Vec<Variant>,
246 deny_unknown_fields: bool,
247 schema: Schema,
248 ) -> TypeEntry {
249 variants.iter_mut().for_each(|variant| {
252 let ident_name = sanitize(&variant.raw_name, Case::Pascal);
253 variant.ident_name = Some(ident_name);
254 });
255
256 if !variants_unique(&variants) {
259 variants.iter_mut().for_each(|variant| {
260 let ident_name = sanitize(
261 &variant
262 .raw_name
263 .replace(|c| c == '_' || !is_xid_continue(c), "X"),
264 Case::Pascal,
265 );
266 variant.ident_name = Some(ident_name);
267 });
268 }
269
270 if !variants_unique(&variants) {
273 let mut counts = HashMap::new();
274 variants.iter().for_each(|variant| {
275 counts
276 .entry(variant.ident_name.as_ref().unwrap())
277 .and_modify(|xxx| *xxx += 1)
278 .or_insert(0);
279 });
280 let dups = variants
281 .iter()
282 .filter(|variant| *counts.get(variant.ident_name.as_ref().unwrap()).unwrap() > 0)
283 .map(|variant| variant.raw_name.as_str())
284 .collect::<Vec<_>>()
285 .join(",");
286 panic!("Failed to make unique variant names for [{}]", dups);
287 }
288
289 let name = get_type_name(&type_name, metadata).unwrap();
290 let rename = None;
291 let description = metadata_description(metadata);
292
293 let (name, extra_derives) = type_patch(type_space, name);
294
295 let details = TypeEntryDetails::Enum(Self {
296 name,
297 rename,
298 description,
299 default: None,
300 tag_type,
301 variants,
302 deny_unknown_fields,
303 bespoke_impls: Default::default(),
304 schema: SchemaWrapper(schema),
305 });
306
307 TypeEntry {
308 details,
309 extra_derives,
310 }
311 }
312
313 pub(crate) fn finalize(&mut self, type_space: &TypeSpace) {
314 self.bespoke_impls = [
315 (self.tag_type != EnumTagType::Untagged
317 && !self.variants.is_empty()
318 && self
319 .variants
320 .iter()
321 .all(|variant| matches!(variant.details, VariantDetails::Simple)))
322 .then_some(TypeEntryEnumImpl::AllSimpleVariants),
323 untagged_newtype_variants(
326 type_space,
327 &self.tag_type,
328 &self.variants,
329 TypeSpaceImpl::FromStr,
330 Some(TypeSpaceImpl::FromStringIrrefutable),
331 )
332 .then_some(TypeEntryEnumImpl::UntaggedFromStr),
333 untagged_newtype_variants(
335 type_space,
336 &self.tag_type,
337 &self.variants,
338 TypeSpaceImpl::Display,
339 None,
340 )
341 .then_some(TypeEntryEnumImpl::UntaggedDisplay),
342 untagged_newtype_string(type_space, &self.tag_type, &self.variants)
343 .then_some(TypeEntryEnumImpl::UntaggedFromStringIrrefutable),
344 ]
345 .into_iter()
346 .flatten()
347 .collect();
348 }
349}
350
351impl Variant {
352 pub(crate) fn new(
353 raw_name: String,
354 description: Option<String>,
355 details: VariantDetails,
356 ) -> Self {
357 Self {
358 raw_name,
359 ident_name: None,
360 description,
361 details,
362 }
363 }
364}
365
366impl TypeEntryStruct {
367 pub(crate) fn from_metadata(
368 type_space: &TypeSpace,
369 type_name: Name,
370 metadata: &Option<Box<Metadata>>,
371 properties: Vec<StructProperty>,
372 deny_unknown_fields: bool,
373 schema: Schema,
374 ) -> TypeEntry {
375 let name = get_type_name(&type_name, metadata).unwrap();
376 let rename = None;
377 let description = metadata_description(metadata);
378 let default = metadata
379 .as_ref()
380 .and_then(|m| m.default.as_ref())
381 .cloned()
382 .map(WrappedValue::new);
383
384 let (name, extra_derives) = type_patch(type_space, name);
385
386 let details = TypeEntryDetails::Struct(Self {
387 name,
388 rename,
389 description,
390 default,
391 properties,
392 deny_unknown_fields,
393 schema: SchemaWrapper(schema),
394 });
395
396 TypeEntry {
397 details,
398 extra_derives,
399 }
400 }
401}
402
403impl TypeEntryNewtype {
404 pub(crate) fn from_metadata(
405 type_space: &TypeSpace,
406 type_name: Name,
407 metadata: &Option<Box<Metadata>>,
408 type_id: TypeId,
409 schema: Schema,
410 ) -> TypeEntry {
411 let name = get_type_name(&type_name, metadata).unwrap();
412 let rename = None;
413 let description = metadata_description(metadata);
414
415 let (name, extra_derives) = type_patch(type_space, name);
416
417 let details = TypeEntryDetails::Newtype(Self {
418 name,
419 rename,
420 description,
421 default: None,
422 type_id,
423 constraints: TypeEntryNewtypeConstraints::None,
424 schema: SchemaWrapper(schema),
425 });
426
427 TypeEntry {
428 details,
429 extra_derives,
430 }
431 }
432
433 pub(crate) fn from_metadata_with_enum_values(
434 type_space: &TypeSpace,
435 type_name: Name,
436 metadata: &Option<Box<Metadata>>,
437 type_id: TypeId,
438 enum_values: &[serde_json::Value],
439 schema: Schema,
440 ) -> TypeEntry {
441 let name = get_type_name(&type_name, metadata).unwrap();
442 let rename = None;
443 let description = metadata_description(metadata);
444
445 let (name, extra_derives) = type_patch(type_space, name);
446
447 let details = TypeEntryDetails::Newtype(Self {
448 name,
449 rename,
450 description,
451 default: None,
452 type_id,
453 constraints: TypeEntryNewtypeConstraints::EnumValue(
454 enum_values.iter().cloned().map(WrappedValue::new).collect(),
455 ),
456 schema: SchemaWrapper(schema),
457 });
458
459 TypeEntry {
460 details,
461 extra_derives,
462 }
463 }
464
465 pub(crate) fn from_metadata_with_deny_values(
466 type_space: &TypeSpace,
467 type_name: Name,
468 metadata: &Option<Box<Metadata>>,
469 type_id: TypeId,
470 enum_values: &[serde_json::Value],
471 schema: Schema,
472 ) -> TypeEntry {
473 let name = get_type_name(&type_name, metadata).unwrap();
474 let rename = None;
475 let description = metadata_description(metadata);
476
477 let (name, extra_derives) = type_patch(type_space, name);
478
479 let details = TypeEntryDetails::Newtype(Self {
480 name,
481 rename,
482 description,
483 default: None,
484 type_id,
485 constraints: TypeEntryNewtypeConstraints::DenyValue(
486 enum_values.iter().cloned().map(WrappedValue::new).collect(),
487 ),
488 schema: SchemaWrapper(schema),
489 });
490
491 TypeEntry {
492 details,
493 extra_derives,
494 }
495 }
496
497 pub(crate) fn from_metadata_with_string_validation(
498 type_space: &TypeSpace,
499 type_name: Name,
500 metadata: &Option<Box<Metadata>>,
501 type_id: TypeId,
502 validation: &schemars::schema::StringValidation,
503 schema: Schema,
504 ) -> TypeEntry {
505 let name = get_type_name(&type_name, metadata).unwrap();
506 let rename = None;
507 let description = metadata_description(metadata);
508
509 let schemars::schema::StringValidation {
510 max_length,
511 min_length,
512 pattern,
513 } = validation.clone();
514
515 let (name, extra_derives) = type_patch(type_space, name);
516
517 let details = TypeEntryDetails::Newtype(Self {
518 name,
519 rename,
520 description,
521 default: None,
522 type_id,
523 constraints: TypeEntryNewtypeConstraints::String {
524 max_length,
525 min_length,
526 pattern,
527 },
528 schema: SchemaWrapper(schema),
529 });
530
531 TypeEntry {
532 details,
533 extra_derives,
534 }
535 }
536}
537
538impl From<TypeEntryDetails> for TypeEntry {
539 fn from(details: TypeEntryDetails) -> Self {
540 Self {
541 details,
542 extra_derives: Default::default(),
543 }
544 }
545}
546
547impl TypeEntry {
548 pub(crate) fn new_native<S: ToString>(type_name: S, impls: &[TypeSpaceImpl]) -> Self {
549 TypeEntry {
550 details: TypeEntryDetails::Native(TypeEntryNative {
551 type_name: type_name.to_string(),
552 impls: impls.to_vec(),
553 parameters: Default::default(),
554 }),
555 extra_derives: Default::default(),
556 }
557 }
558 pub(crate) fn new_native_params<S: ToString>(type_name: S, params: &[TypeId]) -> Self {
559 TypeEntry {
560 details: TypeEntryDetails::Native(TypeEntryNative {
561 type_name: type_name.to_string(),
562 impls: Default::default(),
563 parameters: params.to_vec(),
564 }),
565 extra_derives: Default::default(),
566 }
567 }
568 pub(crate) fn new_boolean() -> Self {
569 TypeEntry {
570 details: TypeEntryDetails::Boolean,
571 extra_derives: Default::default(),
572 }
573 }
574 pub(crate) fn new_integer<S: ToString>(type_name: S) -> Self {
575 TypeEntryDetails::Integer(type_name.to_string()).into()
576 }
577 pub(crate) fn new_float<S: ToString>(type_name: S) -> Self {
578 TypeEntry {
579 details: TypeEntryDetails::Float(type_name.to_string()),
580 extra_derives: Default::default(),
581 }
582 }
583
584 pub(crate) fn finalize(&mut self, type_space: &mut TypeSpace) -> Result<()> {
585 if let TypeEntryDetails::Enum(enum_details) = &mut self.details {
586 enum_details.finalize(type_space);
587 }
588
589 self.check_defaults(type_space)
590 }
591
592 pub(crate) fn name(&self) -> Option<&String> {
593 match &self.details {
594 TypeEntryDetails::Enum(TypeEntryEnum { name, .. })
595 | TypeEntryDetails::Struct(TypeEntryStruct { name, .. })
596 | TypeEntryDetails::Newtype(TypeEntryNewtype { name, .. }) => Some(name),
597
598 _ => None,
599 }
600 }
601
602 pub(crate) fn has_impl<'a>(
603 &'a self,
604 type_space: &'a TypeSpace,
605 impl_name: TypeSpaceImpl,
606 ) -> bool {
607 match &self.details {
608 TypeEntryDetails::Enum(details) => match impl_name {
609 TypeSpaceImpl::Default => details.default.is_some(),
610 TypeSpaceImpl::FromStr => {
611 details
612 .bespoke_impls
613 .contains(&TypeEntryEnumImpl::AllSimpleVariants)
614 || details
615 .bespoke_impls
616 .contains(&TypeEntryEnumImpl::UntaggedFromStr)
617 }
618 TypeSpaceImpl::Display => {
619 details
620 .bespoke_impls
621 .contains(&TypeEntryEnumImpl::AllSimpleVariants)
622 || details
623 .bespoke_impls
624 .contains(&TypeEntryEnumImpl::UntaggedDisplay)
625 }
626 TypeSpaceImpl::FromStringIrrefutable => details
627 .bespoke_impls
628 .contains(&TypeEntryEnumImpl::UntaggedFromStringIrrefutable),
629 },
630
631 TypeEntryDetails::Struct(details) => match impl_name {
632 TypeSpaceImpl::Default => details.default.is_some(),
633 _ => false,
634 },
635 TypeEntryDetails::Newtype(details) => match (&details.constraints, impl_name) {
636 (_, TypeSpaceImpl::Default) => details.default.is_some(),
637 (TypeEntryNewtypeConstraints::String { .. }, TypeSpaceImpl::FromStr) => true,
638 (TypeEntryNewtypeConstraints::String { .. }, TypeSpaceImpl::Display) => true,
639 (TypeEntryNewtypeConstraints::None, _) => {
640 let type_entry = type_space.id_to_entry.get(&details.type_id).unwrap();
656 type_entry.has_impl(type_space, impl_name)
657 }
658 _ => false,
659 },
660 TypeEntryDetails::Native(details) => details.impls.contains(&impl_name),
661 TypeEntryDetails::Box(type_id) => {
662 if impl_name == TypeSpaceImpl::Default {
663 let type_entry = type_space.id_to_entry.get(type_id).unwrap();
664 type_entry.has_impl(type_space, impl_name)
665 } else {
666 false
667 }
668 }
669
670 TypeEntryDetails::JsonValue => false,
671
672 TypeEntryDetails::Unit
673 | TypeEntryDetails::Option(_)
674 | TypeEntryDetails::Vec(_)
675 | TypeEntryDetails::Map(_, _)
676 | TypeEntryDetails::Set(_) => {
677 matches!(impl_name, TypeSpaceImpl::Default)
678 }
679
680 TypeEntryDetails::Tuple(type_ids) => {
681 matches!(impl_name, TypeSpaceImpl::Default)
683 && type_ids.len() <= 12
684 && type_ids.iter().all(|type_id| {
685 let type_entry = type_space.id_to_entry.get(type_id).unwrap();
686 type_entry.has_impl(type_space, TypeSpaceImpl::Default)
687 })
688 }
689
690 TypeEntryDetails::Array(item_id, length) => {
691 if *length <= 32 && impl_name == TypeSpaceImpl::Default {
693 let type_entry = type_space.id_to_entry.get(item_id).unwrap();
694 type_entry.has_impl(type_space, impl_name)
695 } else {
696 false
697 }
698 }
699
700 TypeEntryDetails::Boolean => match impl_name {
701 TypeSpaceImpl::Default | TypeSpaceImpl::FromStr | TypeSpaceImpl::Display => true,
702 TypeSpaceImpl::FromStringIrrefutable => false,
703 },
704 TypeEntryDetails::Integer(_) => match impl_name {
705 TypeSpaceImpl::Default | TypeSpaceImpl::FromStr | TypeSpaceImpl::Display => true,
706 TypeSpaceImpl::FromStringIrrefutable => false,
707 },
708
709 TypeEntryDetails::Float(_) => match impl_name {
710 TypeSpaceImpl::Default | TypeSpaceImpl::FromStr | TypeSpaceImpl::Display => true,
711 TypeSpaceImpl::FromStringIrrefutable => false,
712 },
713 TypeEntryDetails::String => match impl_name {
714 TypeSpaceImpl::Default
715 | TypeSpaceImpl::FromStr
716 | TypeSpaceImpl::Display
717 | TypeSpaceImpl::FromStringIrrefutable => true,
718 },
719
720 TypeEntryDetails::Reference(_) => unreachable!(),
721 }
722 }
723
724 pub(crate) fn output(&self, type_space: &TypeSpace, output: &mut OutputSpace) {
725 let derive_set = [
726 "::serde::Serialize",
727 "::serde::Deserialize",
728 "Debug",
729 "Clone",
730 ]
731 .into_iter()
732 .collect::<BTreeSet<_>>();
733
734 match &self.details {
735 TypeEntryDetails::Enum(enum_details) => {
736 self.output_enum(type_space, output, enum_details, derive_set)
737 }
738 TypeEntryDetails::Struct(struct_details) => {
739 self.output_struct(type_space, output, struct_details, derive_set)
740 }
741 TypeEntryDetails::Newtype(newtype_details) => {
742 self.output_newtype(type_space, output, newtype_details, derive_set)
743 }
744
745 TypeEntryDetails::Reference(_) => unreachable!(),
748
749 _ => (),
751 }
752 }
753
754 fn output_enum(
755 &self,
756 type_space: &TypeSpace,
757 output: &mut OutputSpace,
758 enum_details: &TypeEntryEnum,
759 mut derive_set: BTreeSet<&str>,
760 ) {
761 let TypeEntryEnum {
762 name,
763 rename,
764 description,
765 default,
766 tag_type,
767 variants,
768 deny_unknown_fields,
769 bespoke_impls,
770 schema: SchemaWrapper(schema),
771 } = enum_details;
772
773 let doc = make_doc(name, description.as_ref(), schema);
774
775 if variants
778 .iter()
779 .all(|variant| matches!(variant.details, VariantDetails::Simple))
780 {
781 derive_set.extend(["Copy", "PartialOrd", "Ord", "PartialEq", "Eq", "Hash"]);
782 }
783
784 let mut serde_options = Vec::new();
785 if let Some(old_name) = rename {
786 serde_options.push(quote! { rename = #old_name });
787 }
788 match tag_type {
789 EnumTagType::External => {}
790 EnumTagType::Internal { tag } => {
791 serde_options.push(quote! { tag = #tag });
792 }
793 EnumTagType::Adjacent { tag, content } => {
794 serde_options.push(quote! { tag = #tag });
795 serde_options.push(quote! { content = #content });
796 }
797 EnumTagType::Untagged => {
798 serde_options.push(quote! { untagged });
799 }
800 }
801 if *deny_unknown_fields {
802 serde_options.push(quote! { deny_unknown_fields });
803 }
804
805 let serde = (!serde_options.is_empty()).then(|| {
806 quote! { #[serde( #( #serde_options ),* )] }
807 });
808
809 let type_name = format_ident!("{}", name);
810
811 let variants_decl = variants
812 .iter()
813 .map(|variant| output_variant(variant, type_space, output, name))
814 .collect::<Vec<_>>();
815
816 if tag_type == &EnumTagType::Untagged {
819 assert!(
820 variants
821 .iter()
822 .filter(|variant| matches!(variant.details, VariantDetails::Simple))
823 .count()
824 <= 1
825 )
826 }
827
828 let simple_enum_impl = bespoke_impls
831 .contains(&TypeEntryEnumImpl::AllSimpleVariants)
832 .then(|| {
833 let (match_variants, match_strs): (Vec<_>, Vec<_>) = variants
834 .iter()
835 .map(|variant| {
836 let ident_name = variant.ident_name.as_ref().unwrap();
837 let variant_name = format_ident!("{}", ident_name);
838 (variant_name, &variant.raw_name)
839 })
840 .unzip();
841
842 quote! {
843 impl ::std::fmt::Display for #type_name {
844 fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
845 match *self {
846 #(Self::#match_variants => f.write_str(#match_strs),)*
847 }
848 }
849 }
850 impl ::std::str::FromStr for #type_name {
851 type Err = self::error::ConversionError;
852
853 fn from_str(value: &str) ->
854 ::std::result::Result<Self, self::error::ConversionError>
855 {
856 match value {
857 #(#match_strs => Ok(Self::#match_variants),)*
858 _ => Err("invalid value".into()),
859 }
860 }
861 }
862 impl ::std::convert::TryFrom<&str> for #type_name {
863 type Error = self::error::ConversionError;
864
865 fn try_from(value: &str) ->
866 ::std::result::Result<Self, self::error::ConversionError>
867 {
868 value.parse()
869 }
870 }
871 impl ::std::convert::TryFrom<&::std::string::String> for #type_name {
872 type Error = self::error::ConversionError;
873
874 fn try_from(value: &::std::string::String) ->
875 ::std::result::Result<Self, self::error::ConversionError>
876 {
877 value.parse()
878 }
879 }
880 impl ::std::convert::TryFrom<::std::string::String> for #type_name {
881 type Error = self::error::ConversionError;
882
883 fn try_from(value: ::std::string::String) ->
884 ::std::result::Result<Self, self::error::ConversionError>
885 {
886 value.parse()
887 }
888 }
889 }
890 });
891
892 let default_impl = default.as_ref().map(|value| {
893 let default_stream = self.output_value(type_space, &value.0, "e! {}).unwrap();
894 quote! {
895 impl ::std::default::Default for #type_name {
896 fn default() -> Self {
897 #default_stream
898 }
899 }
900 }
901 });
902
903 let untagged_newtype_from_string_impl = bespoke_impls
904 .contains(&TypeEntryEnumImpl::UntaggedFromStr)
905 .then(|| {
906 let variant_name = variants
907 .iter()
908 .map(|variant| format_ident!("{}", variant.ident_name.as_ref().unwrap()));
909
910 quote! {
911 impl ::std::str::FromStr for #type_name {
912 type Err = self::error::ConversionError;
913
914 fn from_str(value: &str) ->
915 ::std::result::Result<Self, self::error::ConversionError>
916 {
917 #(
918 if let Ok(v) = value.parse() {
920 Ok(Self::#variant_name(v))
921 } else
922 )*
923 {
924 Err("string conversion failed for all variants".into())
925 }
926 }
927 }
928 impl ::std::convert::TryFrom<&str> for #type_name {
929 type Error = self::error::ConversionError;
930
931 fn try_from(value: &str) ->
932 ::std::result::Result<Self, self::error::ConversionError>
933 {
934 value.parse()
935 }
936 }
937 impl ::std::convert::TryFrom<&::std::string::String> for #type_name {
938 type Error = self::error::ConversionError;
939
940 fn try_from(value: &::std::string::String) ->
941 ::std::result::Result<Self, self::error::ConversionError>
942 {
943 value.parse()
944 }
945 }
946 impl ::std::convert::TryFrom<::std::string::String> for #type_name {
947 type Error = self::error::ConversionError;
948
949 fn try_from(value: ::std::string::String) ->
950 ::std::result::Result<Self, self::error::ConversionError>
951 {
952 value.parse()
953 }
954 }
955 }
956 });
957
958 let untagged_newtype_to_string_impl = bespoke_impls
959 .contains(&TypeEntryEnumImpl::UntaggedDisplay)
960 .then(|| {
961 let variant_name = variants
962 .iter()
963 .map(|variant| format_ident!("{}", variant.ident_name.as_ref().unwrap()));
964
965 quote! {
966 impl ::std::fmt::Display for #type_name {
967 fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
968 match self {
969 #(Self::#variant_name(x) => x.fmt(f),)*
970 }
971 }
972 }
973 }
974 });
975
976 let convenience_from = {
977 let unique_variants =
984 variants
985 .iter()
986 .enumerate()
987 .fold(BTreeMap::new(), |mut map, (index, variant)| {
988 let key = match &variant.details {
989 VariantDetails::Item(type_id) => vec![type_id],
990 VariantDetails::Tuple(type_ids) => type_ids.iter().collect(),
991 _ => return map,
992 };
993
994 map.entry(key)
995 .and_modify(|v| *v = None)
996 .or_insert(Some((index, variant)));
997 map
998 });
999
1000 let ordered_variants = unique_variants
1006 .into_values()
1007 .flatten()
1008 .collect::<BTreeMap<_, _>>();
1009
1010 let variant_from = ordered_variants.into_values().map(|variant| {
1013 match &variant.details {
1014 VariantDetails::Item(type_id) => {
1015 let variant_type = type_space.id_to_entry.get(type_id).unwrap();
1016
1017 (variant_type.details != TypeEntryDetails::String).then(|| {
1020 let variant_type_ident = variant_type.type_ident(type_space, &None);
1021 let variant_name =
1022 format_ident!("{}", variant.ident_name.as_ref().unwrap());
1023 quote! {
1024 impl ::std::convert::From<#variant_type_ident> for #type_name {
1025 fn from(value: #variant_type_ident)
1026 -> Self
1027 {
1028 Self::#variant_name(value)
1029 }
1030 }
1031 }
1032 })
1033 }
1034 VariantDetails::Tuple(type_ids) => {
1035 let variant_type_idents = type_ids.iter().map(|type_id| {
1036 type_space
1037 .id_to_entry
1038 .get(type_id)
1039 .unwrap()
1040 .type_ident(type_space, &None)
1041 });
1042 let variant_type_ident = if type_ids.len() != 1 {
1043 quote! { ( #(#variant_type_idents),* ) }
1044 } else {
1045 quote! { ( #(#variant_type_idents,)* ) }
1048 };
1049 let variant_name =
1050 format_ident!("{}", variant.ident_name.as_ref().unwrap());
1051 let ii = (0..type_ids.len()).map(syn::Index::from);
1052 Some(quote! {
1053 impl ::std::convert::From<#variant_type_ident> for #type_name {
1054 fn from(value: #variant_type_ident) -> Self {
1055 Self::#variant_name(
1056 #( value.#ii, )*
1057 )
1058 }
1059 }
1060 })
1061 }
1062 _ => None,
1063 }
1064 });
1065
1066 quote! {
1067 #( #variant_from )*
1068 }
1069 };
1070
1071 let derives = strings_to_derives(
1072 derive_set,
1073 &self.extra_derives,
1074 &type_space.settings.extra_derives,
1075 );
1076
1077 let item = quote! {
1078 #doc
1079 #[derive(#(#derives),*)]
1080 #serde
1081 pub enum #type_name {
1082 #(#variants_decl)*
1083 }
1084
1085 impl ::std::convert::From<&Self> for #type_name {
1086 fn from(value: &#type_name) -> Self {
1087 value.clone()
1088 }
1089 }
1090
1091 #simple_enum_impl
1092 #default_impl
1093 #untagged_newtype_from_string_impl
1094 #untagged_newtype_to_string_impl
1095 #convenience_from
1096 };
1097 output.add_item(OutputSpaceMod::Crate, name, item);
1098 }
1099
1100 fn output_struct(
1101 &self,
1102 type_space: &TypeSpace,
1103 output: &mut OutputSpace,
1104 struct_details: &TypeEntryStruct,
1105 derive_set: BTreeSet<&str>,
1106 ) {
1107 enum PropDefault {
1108 None(String),
1109 Default(TokenStream),
1110 Custom(TokenStream),
1111 }
1112
1113 let TypeEntryStruct {
1114 name,
1115 rename,
1116 description,
1117 default,
1118 properties,
1119 deny_unknown_fields,
1120 schema: SchemaWrapper(schema),
1121 } = struct_details;
1122 let doc = make_doc(name, description.as_ref(), schema);
1123
1124 let mut serde_options = Vec::new();
1126 if let Some(old_name) = rename {
1127 serde_options.push(quote! { rename = #old_name });
1128 }
1129 if *deny_unknown_fields {
1130 serde_options.push(quote! { deny_unknown_fields });
1131 }
1132 let serde =
1133 (!serde_options.is_empty()).then(|| quote! { #[serde( #( #serde_options ),* )] });
1134
1135 let type_name = format_ident!("{}", name);
1136
1137 let mut prop_doc = Vec::new();
1139 let mut prop_serde = Vec::new();
1140 let mut prop_default = Vec::new();
1141 let mut prop_name = Vec::new();
1142 let mut prop_error = Vec::new();
1143 let mut prop_type = Vec::new();
1144 let mut prop_type_scoped = Vec::new();
1145
1146 properties.iter().for_each(|prop| {
1147 prop_doc.push(prop.description.as_ref().map(|d| quote! { #[doc = #d] }));
1148 prop_name.push(format_ident!("{}", prop.name));
1149 prop_error.push(format!(
1150 "error converting supplied value for {}: {{}}",
1151 prop.name,
1152 ));
1153
1154 let prop_type_entry = type_space.id_to_entry.get(&prop.type_id).unwrap();
1155 prop_type.push(prop_type_entry.type_ident(type_space, &None));
1156 prop_type_scoped
1157 .push(prop_type_entry.type_ident(type_space, &Some("super".to_string())));
1158
1159 let (serde, default_fn) = generate_serde_attr(
1160 name,
1161 &prop.name,
1162 &prop.rename,
1163 &prop.state,
1164 prop_type_entry,
1165 type_space,
1166 output,
1167 );
1168
1169 prop_serde.push(serde);
1170 prop_default.push(match default_fn {
1171 DefaultFunction::Default => PropDefault::Default(quote! {
1172 Default::default()
1173 }),
1174 DefaultFunction::Custom(fn_name) => {
1175 let default_fn = syn::parse_str::<Path>(&fn_name).unwrap();
1176 PropDefault::Custom(quote! {
1177 #default_fn()
1178 })
1179 }
1180 DefaultFunction::None => {
1181 let err_msg = format!("no value supplied for {}", prop.name);
1182 PropDefault::None(err_msg)
1183 }
1184 });
1185 });
1186
1187 let derives = strings_to_derives(
1188 derive_set,
1189 &self.extra_derives,
1190 &type_space.settings.extra_derives,
1191 );
1192
1193 output.add_item(
1194 OutputSpaceMod::Crate,
1195 name,
1196 quote! {
1197 #doc
1198 #[derive(#(#derives),*)]
1199 #serde
1200 pub struct #type_name {
1201 #(
1202 #prop_doc
1203 #prop_serde
1204 pub #prop_name: #prop_type,
1205 )*
1206 }
1207
1208 impl ::std::convert::From<&#type_name> for #type_name {
1209 fn from(value: &#type_name) -> Self {
1210 value.clone()
1211 }
1212 }
1213 },
1214 );
1215
1216 if let Some(value) = default {
1218 let default_stream = self.output_value(type_space, &value.0, "e! {}).unwrap();
1219 output.add_item(
1220 OutputSpaceMod::Crate,
1221 name,
1222 quote! {
1223 impl ::std::default::Default for #type_name {
1224 fn default() -> Self {
1225 #default_stream
1226 }
1227 }
1228 },
1229 );
1230 } else if let Some(prop_default) = prop_default
1231 .iter()
1232 .map(|pd| match pd {
1233 PropDefault::None(_) => None,
1234 PropDefault::Default(token_stream) | PropDefault::Custom(token_stream) => {
1235 Some(token_stream)
1236 }
1237 })
1238 .collect::<Option<Vec<_>>>()
1239 {
1240 output.add_item(
1242 OutputSpaceMod::Crate,
1243 name,
1244 quote! {
1245 impl ::std::default::Default for #type_name {
1246 fn default() -> Self {
1247 Self {
1248 #(
1249 #prop_name: #prop_default,
1250 )*
1251 }
1252 }
1253 }
1254 },
1255 )
1256 }
1257
1258 if type_space.settings.struct_builder {
1259 output.add_item(
1260 OutputSpaceMod::Crate,
1261 name,
1262 quote! {
1263 impl #type_name {
1264 pub fn builder() -> builder::#type_name {
1265 Default::default()
1266 }
1267 }
1268 },
1269 );
1270
1271 let value_ident = if prop_name.is_empty() {
1274 quote! { _value }
1275 } else {
1276 quote! { value }
1277 };
1278
1279 let prop_default = prop_default.iter().map(|pd| match pd {
1280 PropDefault::None(err_msg) => quote! { Err(#err_msg.to_string()) },
1281 PropDefault::Default(default_fn) => quote! { Ok(#default_fn) },
1282 PropDefault::Custom(custom_fn) => quote! { Ok(super::#custom_fn) },
1283 });
1284
1285 output.add_item(
1286 OutputSpaceMod::Builder,
1287 name,
1288 quote! {
1289 #[derive(Clone, Debug)]
1290 pub struct #type_name {
1291 #(
1292 #prop_name: ::std::result::Result<#prop_type_scoped, ::std::string::String>,
1293 )*
1294 }
1295
1296 impl ::std::default::Default for #type_name {
1297 fn default() -> Self {
1298 Self {
1299 #(
1300 #prop_name: #prop_default,
1301 )*
1302 }
1303 }
1304 }
1305
1306 impl #type_name {
1307 #(
1308 pub fn #prop_name<T>(mut self, value: T) -> Self
1309 where
1310 T: ::std::convert::TryInto<#prop_type_scoped>,
1311 T::Error: ::std::fmt::Display,
1312 {
1313 self.#prop_name = value.try_into()
1314 .map_err(|e| format!(#prop_error, e));
1315 self
1316 }
1317 )*
1318 }
1319
1320 impl ::std::convert::TryFrom<#type_name>
1322 for super::#type_name
1323 {
1324 type Error = super::error::ConversionError;
1325
1326 fn try_from(#value_ident: #type_name)
1327 -> ::std::result::Result<Self, super::error::ConversionError>
1328 {
1329 Ok(Self {
1330 #(
1331 #prop_name: value.#prop_name?,
1332 )*
1333 })
1334 }
1335 }
1336
1337 impl ::std::convert::From<super::#type_name> for #type_name {
1339 fn from(#value_ident: super::#type_name) -> Self {
1340 Self {
1341 #(
1342 #prop_name: Ok(value.#prop_name),
1343 )*
1344 }
1345 }
1346 }
1347 },
1348 );
1349 }
1350 }
1351
1352 fn output_newtype(
1353 &self,
1354 type_space: &TypeSpace,
1355 output: &mut OutputSpace,
1356 newtype_details: &TypeEntryNewtype,
1357 mut derive_set: BTreeSet<&str>,
1358 ) {
1359 let TypeEntryNewtype {
1360 name,
1361 rename: _,
1362 description,
1363 default,
1364 type_id,
1365 constraints,
1366 schema: SchemaWrapper(schema),
1367 } = newtype_details;
1368 let doc = make_doc(name, description.as_ref(), schema);
1369
1370 let type_name = format_ident!("{}", name);
1371 let inner_type = type_space.id_to_entry.get(type_id).unwrap();
1372 let inner_type_name = inner_type.type_ident(type_space, &None);
1373
1374 let is_str = matches!(inner_type.details, TypeEntryDetails::String);
1375
1376 if is_str {
1379 derive_set.extend(["PartialOrd", "Ord", "PartialEq", "Eq", "Hash"]);
1380 }
1381
1382 let constraint_impl = match constraints {
1383 TypeEntryNewtypeConstraints::None => {
1385 let str_impl = is_str.then(|| {
1386 quote! {
1387 impl ::std::str::FromStr for #type_name {
1388 type Err = ::std::convert::Infallible;
1389
1390 fn from_str(value: &str) ->
1391 ::std::result::Result<Self, Self::Err>
1392 {
1393 Ok(Self(value.to_string()))
1394 }
1395 }
1396 }
1397 });
1398
1399 let from_str_impl = (inner_type.has_impl(type_space, TypeSpaceImpl::FromStr)
1401 && !is_str)
1402 .then(|| {
1403 quote! {
1404 impl ::std::str::FromStr for #type_name {
1405 type Err = <#inner_type_name as
1406 ::std::str::FromStr>::Err;
1407
1408 fn from_str(value: &str) ->
1409 ::std::result::Result<Self, Self::Err>
1410 {
1411 Ok(Self(value.parse()?))
1412 }
1413 }
1414 impl ::std::convert::TryFrom<&str> for #type_name {
1415 type Error = <#inner_type_name as
1416 ::std::str::FromStr>::Err;
1417
1418 fn try_from(value: &str) ->
1419 ::std::result::Result<Self, Self::Error>
1420 {
1421 value.parse()
1422 }
1423 }
1424 impl ::std::convert::TryFrom<&String> for #type_name {
1425 type Error = <#inner_type_name as
1426 ::std::str::FromStr>::Err;
1427
1428 fn try_from(value: &String) ->
1429 ::std::result::Result<Self, Self::Error>
1430 {
1431 value.parse()
1432 }
1433 }
1434 impl ::std::convert::TryFrom<String> for #type_name {
1435 type Error = <#inner_type_name as
1436 ::std::str::FromStr>::Err;
1437
1438 fn try_from(value: String) ->
1439 ::std::result::Result<Self, Self::Error>
1440 {
1441 value.parse()
1442 }
1443 }
1444 }
1445 });
1446
1447 let display_impl = inner_type
1448 .has_impl(type_space, TypeSpaceImpl::Display)
1449 .then(|| {
1450 quote! {
1451 impl ::std::fmt::Display for #type_name {
1452 fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
1453 self.0.fmt(f)
1454 }
1455 }
1456 }
1457 });
1458
1459 quote! {
1460 impl ::std::convert::From<#inner_type_name> for #type_name {
1461 fn from(value: #inner_type_name) -> Self {
1462 Self(value)
1463 }
1464 }
1465
1466 #str_impl
1467 #from_str_impl
1468 #display_impl
1469 }
1470 }
1471
1472 TypeEntryNewtypeConstraints::DenyValue(enum_values)
1473 | TypeEntryNewtypeConstraints::EnumValue(enum_values) => {
1474 let not = matches!(constraints, TypeEntryNewtypeConstraints::EnumValue(_))
1475 .then(|| quote! { ! });
1476 assert!(
1480 matches!(constraints, TypeEntryNewtypeConstraints::DenyValue(_))
1481 || !matches!(&inner_type.details, TypeEntryDetails::String)
1482 );
1483
1484 derive_set.remove("::serde::Deserialize");
1487
1488 let value_output = enum_values
1492 .iter()
1493 .map(|value| inner_type.output_value(type_space, &value.0, "e! {}));
1494 quote! {
1498 impl ::std::convert::TryFrom<#inner_type_name> for #type_name {
1500 type Error = self::error::ConversionError;
1501
1502 fn try_from(
1503 value: #inner_type_name
1504 ) -> ::std::result::Result<Self, self::error::ConversionError>
1505 {
1506 if #not [
1507 #(#value_output,)*
1508 ].contains(&value) {
1509 Err("invalid value".into())
1510 } else {
1511 Ok(Self(value))
1512 }
1513 }
1514 }
1515
1516 impl<'de> ::serde::Deserialize<'de> for #type_name {
1517 fn deserialize<D>(
1518 deserializer: D,
1519 ) -> ::std::result::Result<Self, D::Error>
1520 where
1521 D: ::serde::Deserializer<'de>,
1522 {
1523 Self::try_from(
1524 <#inner_type_name>::deserialize(deserializer)?,
1525 )
1526 .map_err(|e| {
1527 <D::Error as ::serde::de::Error>::custom(
1528 e.to_string(),
1529 )
1530 })
1531 }
1532 }
1533 }
1534 }
1535
1536 TypeEntryNewtypeConstraints::String {
1537 max_length,
1538 min_length,
1539 pattern,
1540 } => {
1541 let max = max_length.map(|v| {
1542 let v = v as usize;
1543 let err = format!("longer than {} characters", v);
1544 quote! {
1545 if value.chars().count() > #v {
1546 return Err(#err.into());
1547 }
1548 }
1549 });
1550 let min = min_length.map(|v| {
1551 let v = v as usize;
1552 let err = format!("shorter than {} characters", v);
1553 quote! {
1554 if value.chars().count() < #v {
1555 return Err(#err.into());
1556 }
1557 }
1558 });
1559
1560 let pat = pattern.as_ref().map(|p| {
1561 let err = format!("doesn't match pattern \"{}\"", p);
1562 quote! {
1563 static PATTERN: ::std::sync::LazyLock<::regress::Regex> = ::std::sync::LazyLock::new(|| {
1564 ::regress::Regex::new(#p).unwrap()
1565 });
1566 if PATTERN.find(value).is_none() {
1567 return Err(#err.into());
1568 }
1569 }
1570 });
1571
1572 derive_set.remove("::serde::Deserialize");
1575
1576 quote! {
1579 impl ::std::str::FromStr for #type_name {
1580 type Err = self::error::ConversionError;
1581
1582 fn from_str(value: &str) -> ::std::result::Result<Self, self::error::ConversionError> {
1583 #max
1584 #min
1585 #pat
1586
1587 Ok(Self(value.to_string()))
1588 }
1589 }
1590 impl ::std::convert::TryFrom<&str> for #type_name {
1591 type Error = self::error::ConversionError;
1592
1593 fn try_from(value: &str) ->
1594 ::std::result::Result<Self, self::error::ConversionError>
1595 {
1596 value.parse()
1597 }
1598 }
1599 impl ::std::convert::TryFrom<&::std::string::String> for #type_name {
1600 type Error = self::error::ConversionError;
1601
1602 fn try_from(value: &::std::string::String) ->
1603 ::std::result::Result<Self, self::error::ConversionError>
1604 {
1605 value.parse()
1606 }
1607 }
1608 impl ::std::convert::TryFrom<::std::string::String> for #type_name {
1609 type Error = self::error::ConversionError;
1610
1611 fn try_from(value: ::std::string::String) ->
1612 ::std::result::Result<Self, self::error::ConversionError>
1613 {
1614 value.parse()
1615 }
1616 }
1617
1618 impl<'de> ::serde::Deserialize<'de> for #type_name {
1619 fn deserialize<D>(
1620 deserializer: D,
1621 ) -> ::std::result::Result<Self, D::Error>
1622 where
1623 D: ::serde::Deserializer<'de>,
1624 {
1625 ::std::string::String::deserialize(deserializer)?
1626 .parse()
1627 .map_err(|e: self::error::ConversionError| {
1628 <D::Error as ::serde::de::Error>::custom(
1629 e.to_string(),
1630 )
1631 })
1632 }
1633 }
1634 }
1635 }
1636 };
1637
1638 let vis = match constraints {
1640 TypeEntryNewtypeConstraints::None => Some(quote! {pub}),
1641 _ => None,
1642 };
1643
1644 let default_impl = default.as_ref().map(|value| {
1645 let default_stream = self.output_value(type_space, &value.0, "e! {}).unwrap();
1646 quote! {
1647 impl ::std::default::Default for #type_name {
1648 fn default() -> Self {
1649 #default_stream
1650 }
1651 }
1652 }
1653 });
1654
1655 let derives = strings_to_derives(
1656 derive_set,
1657 &self.extra_derives,
1658 &type_space.settings.extra_derives,
1659 );
1660
1661 let item = quote! {
1662 #doc
1663 #[derive(#(#derives),*)]
1664 #[serde(transparent)]
1665 pub struct #type_name(#vis #inner_type_name);
1666
1667 impl ::std::ops::Deref for #type_name {
1668 type Target = #inner_type_name;
1669 fn deref(&self) -> &#inner_type_name {
1670 &self.0
1671 }
1672 }
1673
1674 impl ::std::convert::From<#type_name> for #inner_type_name {
1675 fn from(value: #type_name) -> Self {
1676 value.0
1677 }
1678 }
1679
1680 impl ::std::convert::From<&#type_name> for #type_name {
1681 fn from(value: &#type_name) -> Self {
1682 value.clone()
1683 }
1684 }
1685
1686 #default_impl
1687 #constraint_impl
1688 };
1689 output.add_item(OutputSpaceMod::Crate, name, item);
1690 }
1691
1692 pub(crate) fn type_name(&self, type_space: &TypeSpace) -> String {
1693 self.type_ident(type_space, &None).to_string()
1694 }
1695
1696 pub(crate) fn type_ident(
1697 &self,
1698 type_space: &TypeSpace,
1699 type_mod: &Option<String>,
1700 ) -> TokenStream {
1701 match &self.details {
1702 TypeEntryDetails::Enum(TypeEntryEnum { name, .. })
1704 | TypeEntryDetails::Struct(TypeEntryStruct { name, .. })
1705 | TypeEntryDetails::Newtype(TypeEntryNewtype { name, .. }) => match &type_mod {
1706 Some(type_mod) => {
1707 let type_mod = format_ident!("{}", type_mod);
1708 let type_name = format_ident!("{}", name);
1709 quote! { #type_mod :: #type_name }
1710 }
1711 None => {
1712 let type_name = format_ident!("{}", name);
1713 quote! { #type_name }
1714 }
1715 },
1716
1717 TypeEntryDetails::Option(id) => {
1718 let inner_ty = type_space
1719 .id_to_entry
1720 .get(id)
1721 .expect("unresolved type id for option");
1722 let inner_ident = inner_ty.type_ident(type_space, type_mod);
1723
1724 match &inner_ty.details {
1727 TypeEntryDetails::Option(_) => inner_ident,
1728 _ => quote! { ::std::option::Option<#inner_ident> },
1729 }
1730 }
1731
1732 TypeEntryDetails::Box(id) => {
1733 let inner_ty = type_space
1734 .id_to_entry
1735 .get(id)
1736 .expect("unresolved type id for box");
1737
1738 let item = inner_ty.type_ident(type_space, type_mod);
1739
1740 quote! { ::std::boxed::Box<#item> }
1741 }
1742
1743 TypeEntryDetails::Vec(id) => {
1744 let inner_ty = type_space
1745 .id_to_entry
1746 .get(id)
1747 .expect("unresolved type id for array");
1748 let item = inner_ty.type_ident(type_space, type_mod);
1749
1750 quote! { ::std::vec::Vec<#item> }
1751 }
1752
1753 TypeEntryDetails::Map(key_id, value_id) => {
1754 let map_to_use = &type_space.settings.map_type;
1755 let key_ty = type_space
1756 .id_to_entry
1757 .get(key_id)
1758 .expect("unresolved type id for map key");
1759 let value_ty = type_space
1760 .id_to_entry
1761 .get(value_id)
1762 .expect("unresolved type id for map value");
1763
1764 if key_ty.details == TypeEntryDetails::String
1765 && value_ty.details == TypeEntryDetails::JsonValue
1766 {
1767 quote! { ::serde_json::Map<::std::string::String, ::serde_json::Value> }
1768 } else {
1769 let key_ident = key_ty.type_ident(type_space, type_mod);
1770 let value_ident = value_ty.type_ident(type_space, type_mod);
1771 let map_to_use = &map_to_use.0;
1772
1773 quote! { #map_to_use<#key_ident, #value_ident> }
1774 }
1775 }
1776
1777 TypeEntryDetails::Set(id) => {
1778 let inner_ty = type_space
1779 .id_to_entry
1780 .get(id)
1781 .expect("unresolved type id for set");
1782 let item = inner_ty.type_ident(type_space, type_mod);
1783 quote! { Vec<#item> }
1786 }
1787
1788 TypeEntryDetails::Tuple(items) => {
1789 let type_idents = items.iter().map(|item| {
1790 type_space
1791 .id_to_entry
1792 .get(item)
1793 .expect("unresolved type id for tuple")
1794 .type_ident(type_space, type_mod)
1795 });
1796
1797 if items.len() != 1 {
1798 quote! { ( #(#type_idents),* ) }
1799 } else {
1800 quote! { ( #(#type_idents,)* ) }
1802 }
1803 }
1804
1805 TypeEntryDetails::Array(item_id, length) => {
1806 let item_ty = type_space
1807 .id_to_entry
1808 .get(item_id)
1809 .expect("unresolved type id for array");
1810 let item_ident = item_ty.type_ident(type_space, type_mod);
1811
1812 quote! { [#item_ident; #length]}
1813 }
1814
1815 TypeEntryDetails::Native(TypeEntryNative {
1816 type_name,
1817 impls: _,
1818 parameters,
1819 }) => {
1820 let path =
1821 syn::parse_str::<syn::TypePath>(type_name).expect("type path wasn't valid");
1822
1823 let type_idents = (!parameters.is_empty()).then(|| {
1824 let type_idents = parameters.iter().map(|type_id| {
1825 type_space
1826 .id_to_entry
1827 .get(type_id)
1828 .expect("unresolved type id for tuple")
1829 .type_ident(type_space, type_mod)
1830 });
1831 quote! { < #(#type_idents,)* > }
1832 });
1833
1834 quote! {
1835 #path
1836 #type_idents
1837 }
1838 }
1839
1840 TypeEntryDetails::Unit => quote! { () },
1841 TypeEntryDetails::String => quote! { ::std::string::String },
1842 TypeEntryDetails::Boolean => quote! { bool },
1843 TypeEntryDetails::JsonValue => quote! { ::serde_json::Value },
1844 TypeEntryDetails::Integer(name) | TypeEntryDetails::Float(name) => {
1845 syn::parse_str::<syn::TypePath>(name)
1846 .unwrap()
1847 .to_token_stream()
1848 }
1849
1850 TypeEntryDetails::Reference(_) => panic!("references should be resolved by now"),
1851 }
1852 }
1853
1854 pub(crate) fn type_parameter_ident(
1855 &self,
1856 type_space: &TypeSpace,
1857 lifetime_name: Option<&str>,
1858 ) -> TokenStream {
1859 let lifetime = lifetime_name.map(|s| {
1860 vec![
1861 TokenTree::from(Punct::new('\'', Spacing::Joint)),
1862 TokenTree::from(format_ident!("{}", s)),
1863 ]
1864 .into_iter()
1865 .collect::<TokenStream>()
1866 });
1867 match &self.details {
1868 TypeEntryDetails::Enum(TypeEntryEnum { variants, .. })
1874 if variants
1875 .iter()
1876 .all(|variant| matches!(&variant.details, VariantDetails::Simple)) =>
1877 {
1878 self.type_ident(type_space, &type_space.settings.type_mod)
1879 }
1880 TypeEntryDetails::Enum(_)
1881 | TypeEntryDetails::Struct(_)
1882 | TypeEntryDetails::Newtype(_)
1883 | TypeEntryDetails::Vec(_)
1884 | TypeEntryDetails::Map(..)
1885 | TypeEntryDetails::Set(_)
1886 | TypeEntryDetails::Box(_)
1887 | TypeEntryDetails::Native(_)
1888 | TypeEntryDetails::Array(..)
1889 | TypeEntryDetails::JsonValue => {
1890 let ident = self.type_ident(type_space, &type_space.settings.type_mod);
1891 quote! {
1892 & #lifetime #ident
1893 }
1894 }
1895
1896 TypeEntryDetails::Option(id) => {
1897 let inner_ty = type_space
1898 .id_to_entry
1899 .get(id)
1900 .expect("unresolved type id for option");
1901 let inner_ident = inner_ty.type_parameter_ident(type_space, lifetime_name);
1902
1903 match &inner_ty.details {
1906 TypeEntryDetails::Option(_) => inner_ident,
1907 _ => quote! { Option<#inner_ident> },
1908 }
1909 }
1910
1911 TypeEntryDetails::Tuple(items) => {
1912 let type_streams = items.iter().map(|item| {
1913 type_space
1914 .id_to_entry
1915 .get(item)
1916 .expect("unresolved type id for tuple")
1917 .type_parameter_ident(type_space, lifetime_name)
1918 });
1919
1920 if items.len() != 1 {
1921 quote! { ( #(#type_streams),* ) }
1922 } else {
1923 quote! { ( #(#type_streams,)* ) }
1927 }
1928 }
1929
1930 TypeEntryDetails::Unit
1931 | TypeEntryDetails::Boolean
1932 | TypeEntryDetails::Integer(_)
1933 | TypeEntryDetails::Float(_) => {
1934 self.type_ident(type_space, &type_space.settings.type_mod)
1935 }
1936 TypeEntryDetails::String => quote! { & #lifetime str },
1937
1938 TypeEntryDetails::Reference(_) => panic!("references should be resolved by now"),
1939 }
1940 }
1941
1942 pub(crate) fn describe(&self) -> String {
1943 match &self.details {
1944 TypeEntryDetails::Enum(TypeEntryEnum { name, .. }) => format!("enum {}", name),
1945 TypeEntryDetails::Struct(TypeEntryStruct { name, .. }) => format!("struct {}", name),
1946 TypeEntryDetails::Newtype(TypeEntryNewtype { name, type_id, .. }) => {
1947 format!("newtype {} {}", name, type_id.0)
1948 }
1949
1950 TypeEntryDetails::Unit => "()".to_string(),
1951 TypeEntryDetails::Option(type_id) => format!("option {}", type_id.0),
1952 TypeEntryDetails::Vec(type_id) => format!("vec {}", type_id.0),
1953 TypeEntryDetails::Map(key_id, value_id) => {
1954 format!("map {} {}", key_id.0, value_id.0)
1955 }
1956 TypeEntryDetails::Set(type_id) => format!("set {}", type_id.0),
1957 TypeEntryDetails::Box(type_id) => format!("box {}", type_id.0),
1958 TypeEntryDetails::Tuple(type_ids) => {
1959 format!(
1960 "tuple ({})",
1961 type_ids
1962 .iter()
1963 .map(|type_id| type_id.0.to_string())
1964 .collect::<Vec<String>>()
1965 .join(", ")
1966 )
1967 }
1968 TypeEntryDetails::Array(type_id, length) => {
1969 format!("array {}; {}", type_id.0, length)
1970 }
1971 TypeEntryDetails::Boolean => "bool".to_string(),
1972 TypeEntryDetails::Native(TypeEntryNative {
1973 type_name: name, ..
1974 })
1975 | TypeEntryDetails::Integer(name)
1976 | TypeEntryDetails::Float(name) => name.clone(),
1977 TypeEntryDetails::String => "string".to_string(),
1978
1979 TypeEntryDetails::JsonValue => "json value".to_string(),
1980
1981 TypeEntryDetails::Reference(_) => unreachable!(),
1982 }
1983 }
1984}
1985
1986fn make_doc(name: &str, description: Option<&String>, schema: &Schema) -> TokenStream {
1987 let desc = match description {
1988 Some(desc) => desc,
1989 None => &format!("`{}`", name),
1990 };
1991 let schema_json = serde_json::to_string_pretty(schema).unwrap();
1992 let schema_lines = schema_json.lines();
1993 quote! {
1994 #[doc = #desc]
1995 #(
2000 #[doc = #schema_lines]
2001 )*
2002 }
2005}
2006
2007fn strings_to_derives<'a>(
2008 derive_set: BTreeSet<&'a str>,
2009 type_derives: &'a BTreeSet<String>,
2010 extra_derives: &'a [String],
2011) -> impl Iterator<Item = TokenStream> + 'a {
2012 let mut combined_derives = derive_set.clone();
2013 combined_derives.extend(extra_derives.iter().map(String::as_str));
2014 combined_derives.extend(type_derives.iter().map(String::as_str));
2015 combined_derives.into_iter().map(|derive| {
2016 syn::parse_str::<syn::Path>(derive)
2017 .unwrap()
2018 .into_token_stream()
2019 })
2020}
2021
2022fn untagged_newtype_variants(
2027 type_space: &TypeSpace,
2028 tag_type: &EnumTagType,
2029 variants: &[Variant],
2030 req_impl: TypeSpaceImpl,
2031 neg_impl: Option<TypeSpaceImpl>,
2032) -> bool {
2033 tag_type == &EnumTagType::Untagged
2034 && variants.iter().all(|variant| {
2035 match &variant.details {
2037 VariantDetails::Item(type_id) => Some(type_id),
2038 _ => None,
2039 }
2040 .map_or_else(
2041 || false,
2042 |type_id| {
2043 let type_entry = type_space.id_to_entry.get(type_id).unwrap();
2044 type_entry.has_impl(type_space, req_impl)
2046 && neg_impl
2047 .is_none_or(|neg_impl| !type_entry.has_impl(type_space, neg_impl))
2048 },
2049 )
2050 })
2051}
2052
2053fn untagged_newtype_string(
2057 type_space: &TypeSpace,
2058 tag_type: &EnumTagType,
2059 variants: &[Variant],
2060) -> bool {
2061 tag_type == &EnumTagType::Untagged
2062 && variants.iter().any(|variant| {
2063 match &variant.details {
2065 VariantDetails::Item(type_id) => Some(type_id),
2066 _ => None,
2067 }
2068 .map_or_else(
2069 || false,
2070 |type_id| {
2071 let type_entry = type_space.id_to_entry.get(type_id).unwrap();
2072 type_entry.has_impl(type_space, TypeSpaceImpl::FromStringIrrefutable)
2074 },
2075 )
2076 })
2077}
2078
2079#[cfg(test)]
2080mod tests {
2081 use crate::{
2082 type_entry::{SchemaWrapper, TypeEntry, TypeEntryStruct},
2083 TypeEntryDetails, TypeSpace,
2084 };
2085
2086 #[test]
2087 fn test_ident() {
2088 let ts = TypeSpace::default();
2089
2090 let type_mod = Some("the_mod".to_string());
2091
2092 let t = TypeEntry::new_integer("u32");
2093 let ident = t.type_ident(&ts, &type_mod);
2094 assert_eq!(ident.to_string(), "u32");
2095 let parameter = t.type_parameter_ident(&ts, None);
2096 assert_eq!(parameter.to_string(), "u32");
2097
2098 let t = TypeEntry::from(TypeEntryDetails::String);
2099 let ident = t.type_ident(&ts, &type_mod);
2100 assert_eq!(ident.to_string(), ":: std :: string :: String");
2101 let parameter = t.type_parameter_ident(&ts, None);
2102 assert_eq!(parameter.to_string(), "& str");
2103 let parameter = t.type_parameter_ident(&ts, Some("static"));
2104 assert_eq!(parameter.to_string(), "& 'static str");
2105
2106 let t = TypeEntry::from(TypeEntryDetails::Unit);
2107 let ident = t.type_ident(&ts, &type_mod);
2108 assert_eq!(ident.to_string(), "()");
2109 let parameter = t.type_parameter_ident(&ts, None);
2110 assert_eq!(parameter.to_string(), "()");
2111
2112 let t = TypeEntry::from(TypeEntryDetails::Struct(TypeEntryStruct {
2113 name: "SomeType".to_string(),
2114 rename: None,
2115 description: None,
2116 default: None,
2117 properties: vec![],
2118 deny_unknown_fields: false,
2119 schema: SchemaWrapper(schemars::schema::Schema::Bool(false)),
2120 }));
2121
2122 let ident = t.type_ident(&ts, &type_mod);
2123 assert_eq!(ident.to_string(), "the_mod :: SomeType");
2124 let parameter = t.type_parameter_ident(&ts, None);
2125 assert_eq!(parameter.to_string(), "& SomeType");
2126 let parameter = t.type_parameter_ident(&ts, Some("a"));
2127 assert_eq!(parameter.to_string(), "& 'a SomeType");
2128 }
2129}