Skip to main content

reflectapi_schema/
lib.rs

1mod codegen;
2mod ids;
3mod internal;
4mod normalize;
5mod rename;
6mod semantic;
7mod subst;
8mod symbol;
9mod visit;
10
11pub use self::codegen::*;
12pub use self::ids::ensure_symbol_ids;
13pub use self::normalize::{
14    CircularDependencyResolutionStage, Consolidation, Naming, NamingResolutionStage,
15    NormalizationError, NormalizationPipeline, NormalizationStage, Normalizer, PipelineBuilder,
16    ResolutionStrategy, TypeConsolidationStage,
17};
18pub use self::semantic::*;
19pub use self::subst::{mk_subst, Instantiate, Substitute};
20pub use self::symbol::{SymbolId, SymbolKind, STDLIB_TYPES, STDLIB_TYPE_PREFIXES};
21pub use self::visit::{VisitMut, Visitor};
22
23#[cfg(feature = "glob")]
24pub use self::rename::Glob;
25
26#[cfg(feature = "glob")]
27pub use glob::PatternError;
28
29pub use self::rename::*;
30use core::fmt;
31use std::collections::BTreeSet;
32use std::{
33    collections::HashMap,
34    ops::{ControlFlow, Index},
35};
36
37#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
38pub struct Schema {
39    #[serde(skip_serializing, default)]
40    pub id: SymbolId,
41
42    pub name: String,
43
44    #[serde(skip_serializing_if = "String::is_empty", default)]
45    pub description: String,
46
47    #[serde(skip_serializing_if = "Vec::is_empty", default)]
48    pub functions: Vec<Function>,
49
50    #[serde(skip_serializing_if = "Typespace::is_empty", default)]
51    pub input_types: Typespace,
52
53    #[serde(skip_serializing_if = "Typespace::is_empty", default)]
54    pub output_types: Typespace,
55}
56
57impl Default for Schema {
58    fn default() -> Self {
59        Self::new()
60    }
61}
62
63impl Schema {
64    pub fn new() -> Self {
65        Schema {
66            id: SymbolId::default(),
67            name: String::new(),
68            description: String::new(),
69            functions: Vec::new(),
70            input_types: Typespace::new(),
71            output_types: Typespace::new(),
72        }
73    }
74
75    pub fn name(&self) -> &str {
76        self.name.as_str()
77    }
78
79    pub fn description(&self) -> &str {
80        self.description.as_str()
81    }
82
83    pub fn functions(&self) -> std::slice::Iter<'_, Function> {
84        self.functions.iter()
85    }
86
87    pub fn input_types(&self) -> &Typespace {
88        &self.input_types
89    }
90
91    pub fn is_input_type(&self, name: &str) -> bool {
92        self.input_types.has_type(name)
93    }
94
95    pub fn output_types(&self) -> &Typespace {
96        &self.output_types
97    }
98
99    pub fn is_output_type(&self, name: &str) -> bool {
100        self.output_types.has_type(name)
101    }
102
103    pub fn extend(&mut self, other: Self) {
104        let Self {
105            id: _,
106            functions,
107            input_types,
108            output_types,
109            name: _,
110            description: _,
111        } = other;
112        self.functions.extend(functions);
113        self.input_types.extend(input_types);
114        self.output_types.extend(output_types);
115    }
116
117    pub fn prepend_path(&mut self, path: &str) {
118        if path.is_empty() {
119            return;
120        }
121        for function in self.functions.iter_mut() {
122            function.path = format!("{}{}", path, function.path);
123        }
124    }
125
126    pub fn consolidate_types(&mut self) -> Vec<String> {
127        // this is probably very inefficient approach to deduplicate types
128        // but is simple enough and will work for foreseeable future
129        loop {
130            let mut all_types = std::collections::HashSet::new();
131            let mut colliding_types = std::collections::HashSet::new();
132            let mut colliging_non_equal_types = std::collections::HashSet::new();
133
134            for input_type in self.input_types.types() {
135                all_types.insert(input_type.name().to_string());
136                if let Some(output_type) = self.output_types.get_type(input_type.name()) {
137                    colliding_types.insert(input_type.name().to_string());
138                    if input_type != output_type {
139                        colliging_non_equal_types.insert(input_type.name().to_string());
140                    }
141                }
142            }
143            for output_type in self.output_types.types() {
144                all_types.insert(output_type.name().to_string());
145                if let Some(input_type) = self.input_types.get_type(output_type.name()) {
146                    colliding_types.insert(output_type.name().to_string());
147                    if input_type != output_type {
148                        colliging_non_equal_types.insert(output_type.name().to_string());
149                    }
150                }
151            }
152
153            if colliging_non_equal_types.is_empty() {
154                let mut r: Vec<_> = all_types.into_iter().collect();
155                r.sort();
156                return r;
157            }
158
159            for type_name in colliging_non_equal_types.iter() {
160                // we assume for now that there is not collision with input / output submodule
161
162                let mut type_name_parts = type_name.split("::").collect::<Vec<_>>();
163                type_name_parts.insert(type_name_parts.len() - 1, "input");
164                self.rename_input_types(type_name.as_str(), &type_name_parts.join("::"));
165
166                let mut type_name_parts = type_name.split("::").collect::<Vec<_>>();
167                type_name_parts.insert(type_name_parts.len() - 1, "output");
168                self.rename_output_types(type_name.as_str(), &type_name_parts.join("::"));
169            }
170        }
171    }
172
173    pub fn get_type(&self, name: &str) -> Option<&Type> {
174        if let Some(t) = self.input_types.get_type(name) {
175            return Some(t);
176        }
177        if let Some(t) = self.output_types.get_type(name) {
178            return Some(t);
179        }
180        None
181    }
182
183    pub fn get_type_mut(&mut self, name: &str) -> Option<&mut Type> {
184        if let Some(t) = self.input_types.get_type_mut(name) {
185            return Some(t);
186        }
187        if let Some(t) = self.output_types.get_type_mut(name) {
188            return Some(t);
189        }
190        None
191    }
192
193    #[cfg(feature = "glob")]
194    pub fn glob_rename_types(
195        &mut self,
196        glob: &str,
197        replacer: &str,
198    ) -> Result<(), glob::PatternError> {
199        let pattern = glob.parse::<Glob>()?;
200        self.rename_types(&pattern, replacer);
201        Ok(())
202    }
203
204    pub fn rename_types(&mut self, pattern: impl Pattern, replacer: &str) -> usize {
205        self.rename_input_types(pattern, replacer) + self.rename_output_types(pattern, replacer)
206    }
207
208    fn rename_input_types(&mut self, pattern: impl Pattern, replacer: &str) -> usize {
209        match Renamer::new(pattern, replacer).visit_schema_inputs(self) {
210            ControlFlow::Continue(c) | ControlFlow::Break(c) => c,
211        }
212    }
213
214    fn rename_output_types(&mut self, pattern: impl Pattern, replacer: &str) -> usize {
215        match Renamer::new(pattern, replacer).visit_schema_outputs(self) {
216            ControlFlow::Continue(c) | ControlFlow::Break(c) => c,
217        }
218    }
219
220    pub fn fold_transparent_types(&mut self) {
221        // Replace the transparent struct `strukt` with it's single field.
222        #[derive(Debug)]
223        struct SubstVisitor {
224            strukt: Struct,
225            to: TypeReference,
226        }
227
228        impl SubstVisitor {
229            fn new(strukt: Struct) -> Self {
230                assert!(strukt.transparent && strukt.fields.len() == 1);
231                Self {
232                    to: strukt.fields[0].type_ref.clone(),
233                    strukt,
234                }
235            }
236        }
237
238        impl Visitor for SubstVisitor {
239            type Output = ();
240
241            fn visit_type_ref(
242                &mut self,
243                type_ref: &mut TypeReference,
244            ) -> ControlFlow<Self::Output, Self::Output> {
245                if type_ref.name == self.strukt.name {
246                    let subst = subst::mk_subst(&self.strukt.parameters, &type_ref.arguments);
247                    *type_ref = self.to.clone().subst(&subst);
248                }
249
250                type_ref.visit_mut(self)?;
251
252                ControlFlow::Continue(())
253            }
254        }
255
256        let transparent_types = self
257            .input_types()
258            .types()
259            .filter_map(|t| {
260                t.as_struct()
261                    .filter(|i| i.transparent && i.fields.len() == 1)
262                    .cloned()
263            })
264            .collect::<Vec<_>>();
265
266        for strukt in transparent_types {
267            self.input_types.remove_type(strukt.name());
268            let _ = SubstVisitor::new(strukt).visit_schema_inputs(self);
269        }
270
271        let transparent_types = self
272            .output_types()
273            .types()
274            .filter_map(|t| {
275                t.as_struct()
276                    .filter(|i| i.transparent && i.fields.len() == 1)
277                    .cloned()
278            })
279            .collect::<Vec<_>>();
280
281        for strukt in transparent_types {
282            self.output_types.remove_type(strukt.name());
283            let _ = SubstVisitor::new(strukt).visit_schema_outputs(self);
284        }
285    }
286}
287
288#[derive(Clone, serde::Serialize, serde::Deserialize, Default)]
289pub struct Typespace {
290    #[serde(skip_serializing_if = "Vec::is_empty", default)]
291    types: Vec<Type>,
292
293    #[serde(skip_serializing, default)]
294    types_map: std::cell::RefCell<HashMap<String, usize>>,
295}
296
297impl fmt::Debug for Typespace {
298    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
299        f.debug_map()
300            .entries(self.types.iter().map(|t| (t.name().to_string(), t)))
301            .finish()
302    }
303}
304
305impl Typespace {
306    pub fn new() -> Self {
307        Typespace {
308            types: Vec::new(),
309            types_map: std::cell::RefCell::new(HashMap::new()),
310        }
311    }
312
313    pub fn is_empty(&self) -> bool {
314        self.types.is_empty()
315    }
316
317    pub fn types(&self) -> std::slice::Iter<'_, Type> {
318        self.types.iter()
319    }
320
321    pub fn get_type(&self, name: &str) -> Option<&Type> {
322        self.ensure_types_map();
323        let index = {
324            let b = self.types_map.borrow();
325            b.get(name).copied().unwrap_or(usize::MAX)
326        };
327        if index == usize::MAX {
328            return None;
329        }
330        self.types.get(index)
331    }
332
333    pub fn get_type_mut(&mut self, name: &str) -> Option<&mut Type> {
334        self.ensure_types_map();
335        let index = {
336            let b = self.types_map.borrow();
337            b.get(name).copied().unwrap_or(usize::MAX)
338        };
339        if index == usize::MAX {
340            return None;
341        }
342        self.types.get_mut(index)
343    }
344
345    pub fn reserve_type(&mut self, name: &str) -> bool {
346        self.ensure_types_map();
347        if self.types_map.borrow().contains_key(name) {
348            return false;
349        }
350        self.types_map.borrow_mut().insert(name.into(), usize::MAX);
351        true
352    }
353
354    pub fn insert_type(&mut self, ty: Type) {
355        self.ensure_types_map();
356        if let Some(index) = self.types_map.borrow().get(ty.name()) {
357            if index != &usize::MAX {
358                return;
359            }
360        }
361        self.types_map
362            .borrow_mut()
363            .insert(ty.name().into(), self.types.len());
364        self.types.push(ty);
365    }
366
367    pub fn remove_type(&mut self, ty: &str) -> Option<Type> {
368        self.ensure_types_map();
369        let index = self
370            .types_map
371            .borrow()
372            .get(ty)
373            .copied()
374            .unwrap_or(usize::MAX);
375        if index == usize::MAX {
376            return None;
377        }
378
379        self.types_map.borrow_mut().remove(ty);
380        Some(self.types.remove(index))
381    }
382
383    pub fn sort_types(&mut self) {
384        self.types.sort_by(|a, b| a.name().cmp(b.name()));
385        self.build_types_map();
386    }
387
388    pub fn has_type(&self, name: &str) -> bool {
389        self.ensure_types_map();
390        self.types_map.borrow().contains_key(name)
391    }
392
393    pub fn extend(&mut self, other: Self) {
394        self.ensure_types_map();
395        for ty in other.types {
396            if self.has_type(ty.name()) {
397                continue;
398            }
399            self.insert_type(ty);
400        }
401    }
402
403    fn invalidate_types_map(&self) {
404        self.types_map.borrow_mut().clear()
405    }
406
407    fn ensure_types_map(&self) {
408        if self.types_map.borrow().is_empty() && !self.types.is_empty() {
409            self.build_types_map();
410        }
411    }
412
413    fn build_types_map(&self) {
414        let mut types_map = HashMap::new();
415        for (i, ty) in self.types.iter().enumerate() {
416            types_map.insert(ty.name().into(), i);
417        }
418        *(self.types_map.borrow_mut()) = types_map;
419    }
420}
421
422#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
423pub struct Function {
424    #[serde(skip_serializing, default)]
425    pub id: SymbolId,
426
427    /// Includes entity and action, for example: users.login
428    pub name: String,
429    /// URL mounting path, for example: /api/v1
430    pub path: String,
431    /// Description of the call
432    #[serde(skip_serializing_if = "String::is_empty", default)]
433    pub description: String,
434    /// Deprecation note. If none, function is not deprecated.
435    /// If present as empty string, function is deprecated without a note.
436    #[serde(skip_serializing_if = "Option::is_none", default)]
437    pub deprecation_note: Option<String>,
438
439    #[serde(skip_serializing_if = "Option::is_none", default)]
440    pub input_type: Option<TypeReference>,
441    #[serde(skip_serializing_if = "Option::is_none", default)]
442    pub input_headers: Option<TypeReference>,
443
444    #[serde(skip_serializing_if = "Option::is_none", default)]
445    pub output_type: Option<TypeReference>,
446
447    #[serde(skip_serializing_if = "Option::is_none", default)]
448    pub error_type: Option<TypeReference>,
449
450    ///
451    /// Supported content types for request and response bodies.
452    ///
453    /// Note: serialization for header values is not affected by this field.
454    /// For displayable types of fields, it is encoded in plain strings.
455    /// For non-displayable types, it is encoded as json.
456    ///
457    /// Default: only json if empty
458    ///
459    #[serde(skip_serializing_if = "Vec::is_empty", default)]
460    pub serialization: Vec<SerializationMode>,
461
462    /// If a function is readonly, it means it does not modify the state of an application
463    #[serde(skip_serializing_if = "is_false", default)]
464    pub readonly: bool,
465
466    #[serde(skip_serializing_if = "BTreeSet::is_empty", default)]
467    pub tags: BTreeSet<String>,
468}
469
470impl Function {
471    pub fn new(name: String) -> Self {
472        let id = SymbolId::endpoint_id(vec![name.clone()]);
473        Function {
474            id,
475            name,
476            deprecation_note: Default::default(),
477            path: Default::default(),
478            description: Default::default(),
479            input_type: None,
480            input_headers: None,
481            output_type: None,
482            error_type: None,
483            serialization: Default::default(),
484            readonly: Default::default(),
485            tags: Default::default(),
486        }
487    }
488
489    pub fn name(&self) -> &str {
490        self.name.as_str()
491    }
492
493    pub fn path(&self) -> &str {
494        self.path.as_str()
495    }
496
497    pub fn description(&self) -> &str {
498        self.description.as_str()
499    }
500
501    pub fn deprecated(&self) -> bool {
502        self.deprecation_note.is_some()
503    }
504
505    pub fn input_type(&self) -> Option<&TypeReference> {
506        self.input_type.as_ref()
507    }
508
509    pub fn input_headers(&self) -> Option<&TypeReference> {
510        self.input_headers.as_ref()
511    }
512
513    pub fn output_type(&self) -> Option<&TypeReference> {
514        self.output_type.as_ref()
515    }
516
517    pub fn error_type(&self) -> Option<&TypeReference> {
518        self.error_type.as_ref()
519    }
520
521    pub fn serialization(&self) -> std::slice::Iter<'_, SerializationMode> {
522        self.serialization.iter()
523    }
524
525    pub fn readonly(&self) -> bool {
526        self.readonly
527    }
528}
529
530#[derive(Debug, Default, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
531#[serde(rename_all = "snake_case")]
532pub enum SerializationMode {
533    #[default]
534    Json,
535    Msgpack,
536}
537
538#[derive(
539    Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq, Hash, PartialOrd, Ord,
540)]
541pub struct TypeReference {
542    pub name: String,
543    /**
544     * References to actual types to use instead of the type parameters
545     * declared on the referred generic type
546     */
547    #[serde(skip_serializing_if = "Vec::is_empty", default)]
548    pub arguments: Vec<TypeReference>,
549}
550
551impl TypeReference {
552    pub fn new(name: impl Into<String>, arguments: Vec<TypeReference>) -> Self {
553        TypeReference {
554            name: name.into(),
555            arguments,
556        }
557    }
558
559    pub fn name(&self) -> &str {
560        self.name.as_str()
561    }
562
563    pub fn arguments(&self) -> std::slice::Iter<'_, TypeReference> {
564        self.arguments.iter()
565    }
566
567    pub fn fallback_recursively(&mut self, schema: &Typespace) {
568        loop {
569            let Some(type_def) = schema.get_type(self.name()) else {
570                return;
571            };
572            let Some(fallback_type_ref) = type_def.fallback_internal(self) else {
573                return;
574            };
575            *self = fallback_type_ref;
576        }
577    }
578
579    pub fn fallback_once(&self, schema: &Typespace) -> Option<TypeReference> {
580        let type_def = schema.get_type(self.name())?;
581        type_def.fallback_internal(self)
582    }
583}
584
585impl From<&str> for TypeReference {
586    fn from(name: &str) -> Self {
587        TypeReference::new(name, Vec::new())
588    }
589}
590
591impl From<String> for TypeReference {
592    fn from(name: String) -> Self {
593        TypeReference::new(name, Vec::new())
594    }
595}
596
597#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
598pub struct TypeParameter {
599    pub name: String,
600    #[serde(skip_serializing_if = "String::is_empty", default)]
601    pub description: String,
602}
603
604impl TypeParameter {
605    pub fn new(name: String, description: String) -> Self {
606        TypeParameter { name, description }
607    }
608
609    pub fn name(&self) -> &str {
610        self.name.as_str()
611    }
612
613    pub fn description(&self) -> &str {
614        self.description.as_str()
615    }
616}
617
618impl From<&str> for TypeParameter {
619    fn from(name: &str) -> Self {
620        TypeParameter {
621            name: name.into(),
622            description: String::new(),
623        }
624    }
625}
626
627impl From<String> for TypeParameter {
628    fn from(name: String) -> Self {
629        TypeParameter {
630            name,
631            description: String::new(),
632        }
633    }
634}
635
636impl PartialEq for TypeParameter {
637    fn eq(&self, other: &Self) -> bool {
638        self.name == other.name
639    }
640}
641
642impl Eq for TypeParameter {}
643
644impl std::hash::Hash for TypeParameter {
645    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
646        self.name.hash(state);
647    }
648}
649
650#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Eq, PartialEq)]
651#[serde(rename_all = "snake_case", tag = "kind")]
652pub enum Type {
653    Primitive(Primitive),
654    Struct(Struct),
655    Enum(Enum),
656}
657
658impl Type {
659    pub fn name(&self) -> &str {
660        match self {
661            Type::Primitive(p) => &p.name,
662            Type::Struct(s) => &s.name,
663            Type::Enum(e) => &e.name,
664        }
665    }
666
667    pub fn serde_name(&self) -> &str {
668        match self {
669            Type::Primitive(_) => self.name(),
670            Type::Struct(s) => s.serde_name(),
671            Type::Enum(e) => e.serde_name(),
672        }
673    }
674
675    pub fn description(&self) -> &str {
676        match self {
677            Type::Primitive(p) => &p.description,
678            Type::Struct(s) => &s.description,
679            Type::Enum(e) => &e.description,
680        }
681    }
682
683    pub fn parameters(&self) -> std::slice::Iter<'_, TypeParameter> {
684        match self {
685            Type::Primitive(p) => p.parameters(),
686            Type::Struct(s) => s.parameters(),
687            Type::Enum(e) => e.parameters(),
688        }
689    }
690
691    pub fn as_struct(&self) -> Option<&Struct> {
692        match self {
693            Type::Struct(s) => Some(s),
694            _ => None,
695        }
696    }
697
698    pub fn is_struct(&self) -> bool {
699        matches!(self, Type::Struct(_))
700    }
701
702    pub fn as_enum(&self) -> Option<&Enum> {
703        match self {
704            Type::Enum(e) => Some(e),
705            _ => None,
706        }
707    }
708
709    pub fn is_enum(&self) -> bool {
710        matches!(self, Type::Enum(_))
711    }
712
713    pub fn as_primitive(&self) -> Option<&Primitive> {
714        match self {
715            Type::Primitive(p) => Some(p),
716            _ => None,
717        }
718    }
719
720    pub fn is_primitive(&self) -> bool {
721        matches!(self, Type::Primitive(_))
722    }
723
724    fn fallback_internal(&self, origin: &TypeReference) -> Option<TypeReference> {
725        match self {
726            Type::Primitive(p) => p.fallback_internal(origin),
727            Type::Struct(_) => None,
728            Type::Enum(_) => None,
729        }
730    }
731
732    pub fn __internal_rename_current(&mut self, new_name: String) {
733        match self {
734            Type::Primitive(p) => p.name = new_name,
735            Type::Struct(s) => s.name = new_name,
736            Type::Enum(e) => e.name = new_name,
737        }
738    }
739
740    pub fn __internal_rebind_generic_parameters(
741        &mut self,
742        unresolved_to_resolved_map: &std::collections::HashMap<TypeReference, TypeReference>,
743        schema: &Typespace,
744    ) {
745        internal::replace_type_references_for_type(self, unresolved_to_resolved_map, schema)
746    }
747}
748
749#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Eq)]
750pub struct Primitive {
751    #[serde(skip_serializing, default)]
752    pub id: SymbolId,
753
754    pub name: String,
755    #[serde(skip_serializing_if = "String::is_empty", default)]
756    pub description: String,
757
758    /// Generic type parameters, if any
759    #[serde(skip_serializing_if = "Vec::is_empty", default)]
760    pub parameters: Vec<TypeParameter>,
761
762    /// Fallback type to use when the type is not supported by the target language
763    #[serde(skip_serializing_if = "Option::is_none", default)]
764    pub fallback: Option<TypeReference>,
765}
766
767impl Primitive {
768    pub fn new(
769        name: String,
770        description: String,
771        parameters: Vec<TypeParameter>,
772        fallback: Option<TypeReference>,
773    ) -> Self {
774        let id = SymbolId::new(SymbolKind::Primitive, vec![name.clone()]);
775        Primitive {
776            id,
777            name,
778            description,
779            parameters,
780            fallback,
781        }
782    }
783
784    pub fn name(&self) -> &str {
785        self.name.as_str()
786    }
787
788    pub fn description(&self) -> &str {
789        self.description.as_str()
790    }
791
792    pub fn parameters(&self) -> std::slice::Iter<'_, TypeParameter> {
793        self.parameters.iter()
794    }
795
796    pub fn fallback(&self) -> Option<&TypeReference> {
797        self.fallback.as_ref()
798    }
799
800    fn fallback_internal(&self, origin: &TypeReference) -> Option<TypeReference> {
801        // example:
802        // Self is DashMap<K, V>
803        // fallback is HashSet<V> (stupid example, but it demos generic param discard)
804        // origin is DashMap<String, u8>
805        // It should transform origin to HashSet<u8>
806        let fallback = self.fallback.as_ref()?;
807
808        if let Some((type_def_param_index, _)) = self
809            .parameters()
810            .enumerate()
811            .find(|(_, type_def_param)| type_def_param.name() == fallback.name())
812        {
813            // this is the case when fallback is to one of the generic parameters
814            // for example, Arc<T> to T
815            let Some(origin_type_ref_param) = origin.arguments.get(type_def_param_index) else {
816                // It means the origin type reference does no provide correct number of generic parameters
817                // required by the type definition
818                // It is invalid schema
819                return None;
820            };
821            return Some(TypeReference {
822                name: origin_type_ref_param.name.clone(),
823                arguments: origin_type_ref_param.arguments.clone(),
824            });
825        }
826
827        let mut new_arguments_for_origin = Vec::new();
828        for fallback_type_ref_param in fallback.arguments() {
829            let Some((type_def_param_index, _)) =
830                self.parameters().enumerate().find(|(_, type_def_param)| {
831                    type_def_param.name() == fallback_type_ref_param.name()
832                })
833            else {
834                // It means fallback type does not have
835                // as much generic parameters as this type definition
836                // in our example, it would be index 0
837                continue;
838            };
839
840            // in our example type_def_param_index would be index 1 for V
841            let Some(origin_type_ref_param) = origin.arguments.get(type_def_param_index) else {
842                // It means the origin type reference does no provide correct number of generic parameters
843                // required by the type definition
844                // It is invalid schema
845                return None;
846            };
847            new_arguments_for_origin.push(origin_type_ref_param.clone());
848        }
849
850        Some(TypeReference {
851            name: fallback.name.clone(),
852            arguments: new_arguments_for_origin,
853        })
854    }
855}
856
857impl PartialEq for Primitive {
858    fn eq(&self, other: &Self) -> bool {
859        self.name == other.name
860            && self.description == other.description
861            && self.parameters == other.parameters
862            && self.fallback == other.fallback
863    }
864}
865
866impl std::hash::Hash for Primitive {
867    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
868        self.name.hash(state);
869        self.description.hash(state);
870        self.parameters.hash(state);
871        self.fallback.hash(state);
872    }
873}
874
875impl From<Primitive> for Type {
876    fn from(val: Primitive) -> Self {
877        Type::Primitive(val)
878    }
879}
880
881#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Eq)]
882pub struct Struct {
883    #[serde(skip_serializing, default)]
884    pub id: SymbolId,
885
886    /// Name of a struct, should be a valid Rust struct name identifier
887    pub name: String,
888
889    /// If a serialized name is not a valid Rust struct name identifier
890    /// then this defines the name of a struct to be used in serialization
891    #[serde(skip_serializing_if = "String::is_empty", default)]
892    pub serde_name: String,
893
894    /// Markdown docs for the struct
895    #[serde(skip_serializing_if = "String::is_empty", default)]
896    pub description: String,
897
898    /// Generic type parameters, if any
899    #[serde(skip_serializing_if = "Vec::is_empty", default)]
900    pub parameters: Vec<TypeParameter>,
901
902    pub fields: Fields,
903
904    /// If serde transparent attribute is set on a struct
905    #[serde(skip_serializing_if = "is_false", default)]
906    pub transparent: bool,
907
908    #[serde(skip_serializing_if = "is_default", default)]
909    pub codegen_config: LanguageSpecificTypeCodegenConfig,
910}
911
912impl Struct {
913    pub fn new(name: impl Into<String>) -> Self {
914        let name = name.into();
915        let id = SymbolId::struct_id(vec![name.clone()]);
916        Struct {
917            id,
918            name,
919            serde_name: Default::default(),
920            description: Default::default(),
921            parameters: Default::default(),
922            fields: Default::default(),
923            transparent: Default::default(),
924            codegen_config: Default::default(),
925        }
926    }
927
928    /// Returns the name of a struct, should be a valid Rust struct name identifier
929    pub fn name(&self) -> &str {
930        self.name.as_str()
931    }
932
933    /// Returns the name of a struct to be used in serialization
934    pub fn serde_name(&self) -> &str {
935        if self.serde_name.is_empty() {
936            self.name.as_str()
937        } else {
938            self.serde_name.as_str()
939        }
940    }
941
942    pub fn description(&self) -> &str {
943        self.description.as_str()
944    }
945
946    pub fn parameters(&self) -> std::slice::Iter<'_, TypeParameter> {
947        self.parameters.iter()
948    }
949
950    pub fn fields(&self) -> std::slice::Iter<'_, Field> {
951        self.fields.iter()
952    }
953
954    pub fn transparent(&self) -> bool {
955        self.transparent
956    }
957
958    /// Returns true if a struct has 1 field and it is either named "0"
959    /// or is transparent in the serialized form
960    pub fn is_alias(&self) -> bool {
961        self.fields.len() == 1 && (self.fields[0].name() == "0" || self.transparent)
962    }
963
964    /// Returns true is a struct is a Rust unit struct.
965    /// Please note, that a unit struct is also an alias
966    // NOTE(andy): does this function make sense? A unit struct is a struct with no fields.
967    pub fn is_unit(&self) -> bool {
968        let Some(first_field) = self.fields.iter().next() else {
969            return false;
970        };
971
972        self.fields.len() == 1
973            && first_field.name() == "0"
974            && first_field.type_ref.name == "std::tuple::Tuple0"
975            && !first_field.required
976    }
977
978    /// Returns true if a struct is a Rust tuple struct.
979    pub fn is_tuple(&self) -> bool {
980        !self.fields.is_empty()
981            && self
982                .fields
983                .iter()
984                .all(|f| f.name().parse::<usize>().is_ok())
985    }
986}
987
988impl PartialEq for Struct {
989    fn eq(&self, other: &Self) -> bool {
990        self.name == other.name
991            && self.serde_name == other.serde_name
992            && self.description == other.description
993            && self.parameters == other.parameters
994            && self.fields == other.fields
995            && self.transparent == other.transparent
996            && self.codegen_config == other.codegen_config
997    }
998}
999
1000impl From<Struct> for Type {
1001    fn from(val: Struct) -> Self {
1002        Type::Struct(val)
1003    }
1004}
1005
1006#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Eq, PartialEq, Default)]
1007#[serde(rename_all = "snake_case")]
1008pub enum Fields {
1009    /// Named struct or variant:
1010    /// struct S { a: u8, b: u8 }
1011    /// enum S { T { a: u8, b: u8 } }
1012    Named(Vec<Field>),
1013    /// Tuple struct or variant:
1014    /// struct S(u8, u8);
1015    /// enum S { T(u8, u8) }
1016    Unnamed(Vec<Field>),
1017    /// Unit struct or variant:
1018    ///
1019    /// struct S;
1020    /// enum S { U }
1021    #[default]
1022    None,
1023}
1024
1025impl Fields {
1026    pub fn is_empty(&self) -> bool {
1027        match self {
1028            Fields::Named(fields) | Fields::Unnamed(fields) => fields.is_empty(),
1029            Fields::None => true,
1030        }
1031    }
1032
1033    pub fn len(&self) -> usize {
1034        match self {
1035            Fields::Named(fields) | Fields::Unnamed(fields) => fields.len(),
1036            Fields::None => 0,
1037        }
1038    }
1039
1040    pub fn iter(&self) -> std::slice::Iter<'_, Field> {
1041        match self {
1042            Fields::Named(fields) | Fields::Unnamed(fields) => fields.iter(),
1043            Fields::None => [].iter(),
1044        }
1045    }
1046
1047    pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, Field> {
1048        match self {
1049            Fields::Named(fields) | Fields::Unnamed(fields) => fields.iter_mut(),
1050            Fields::None => [].iter_mut(),
1051        }
1052    }
1053}
1054
1055impl Index<usize> for Fields {
1056    type Output = Field;
1057
1058    fn index(&self, index: usize) -> &Self::Output {
1059        match self {
1060            Fields::Named(fields) | Fields::Unnamed(fields) => &fields[index],
1061            Fields::None => panic!("index out of bounds"),
1062        }
1063    }
1064}
1065
1066impl IntoIterator for Fields {
1067    type Item = Field;
1068    type IntoIter = std::vec::IntoIter<Field>;
1069
1070    fn into_iter(self) -> Self::IntoIter {
1071        match self {
1072            Fields::Named(fields) => fields.into_iter(),
1073            Fields::Unnamed(fields) => fields.into_iter(),
1074            Fields::None => vec![].into_iter(),
1075        }
1076    }
1077}
1078
1079#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Eq)]
1080pub struct Field {
1081    #[serde(skip_serializing, default)]
1082    pub id: SymbolId,
1083
1084    /// Field name, should be a valid Rust field name identifier
1085    pub name: String,
1086    /// If a serialized name is not a valid Rust field name identifier
1087    /// then this defines the name of a field to be used in serialization
1088    #[serde(skip_serializing_if = "String::is_empty", default)]
1089    pub serde_name: String,
1090    /// Rust docs for the field
1091    #[serde(skip_serializing_if = "String::is_empty", default)]
1092    pub description: String,
1093
1094    /// Deprecation note. If none, field is not deprecated.
1095    /// If present as empty string, field is deprecated without a note.
1096    #[serde(skip_serializing_if = "Option::is_none", default)]
1097    pub deprecation_note: Option<String>,
1098
1099    /// Type of a field
1100    #[serde(rename = "type")]
1101    pub type_ref: TypeReference,
1102    /// required and not nullable:
1103    /// - field always present and not null / none
1104    ///
1105    /// required and nullable:
1106    /// - Rust: `Option<T>`, do not skip serializing if None
1107    /// - TypeScript: T | null, do not skip serializing if null
1108    ///
1109    /// not required and not nullable:
1110    /// - Rust: `Option<T>`, skip serializing if None
1111    /// - TypeScript: T | undefined, skip serializing if undefined
1112    ///
1113    /// not required and nullable:
1114    ///   serializers and deserializers are required to differentiate between
1115    ///   missing fields and null / none fields
1116    /// - Rust: `reflectapi::Option<T>` is enum with Undefined, None and Some variants
1117    /// - TypeScript: T | null | undefined
1118    ///
1119    /// Default is false
1120    #[serde(skip_serializing_if = "is_false", default)]
1121    pub required: bool,
1122    /// If serde flatten attribute is set on a field
1123    /// Default is false
1124    #[serde(skip_serializing_if = "is_false", default)]
1125    pub flattened: bool,
1126
1127    #[serde(skip, default)]
1128    pub transform_callback: String,
1129    #[serde(skip, default)]
1130    pub transform_callback_fn: Option<fn(&mut TypeReference, &Typespace) -> ()>,
1131}
1132
1133impl PartialEq for Field {
1134    fn eq(
1135        &self,
1136        Self {
1137            id: _,
1138            name,
1139            serde_name,
1140            description,
1141            deprecation_note,
1142            type_ref,
1143            required,
1144            flattened,
1145            transform_callback,
1146            transform_callback_fn: _,
1147        }: &Self,
1148    ) -> bool {
1149        self.name == *name
1150            && self.serde_name == *serde_name
1151            && self.description == *description
1152            && self.deprecation_note == *deprecation_note
1153            && self.type_ref == *type_ref
1154            && self.required == *required
1155            && self.flattened == *flattened
1156            && self.transform_callback == *transform_callback
1157    }
1158}
1159
1160impl std::hash::Hash for Field {
1161    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1162        self.name.hash(state);
1163        self.serde_name.hash(state);
1164        self.description.hash(state);
1165        self.deprecation_note.hash(state);
1166        self.type_ref.hash(state);
1167        self.required.hash(state);
1168        self.flattened.hash(state);
1169        self.transform_callback.hash(state);
1170    }
1171}
1172
1173impl Field {
1174    pub fn new(name: String, type_ref: TypeReference) -> Self {
1175        Field {
1176            id: SymbolId::default(),
1177            name,
1178            type_ref,
1179            serde_name: Default::default(),
1180            description: Default::default(),
1181            deprecation_note: Default::default(),
1182            required: Default::default(),
1183            flattened: Default::default(),
1184            transform_callback: Default::default(),
1185            transform_callback_fn: Default::default(),
1186        }
1187    }
1188
1189    pub fn with_required(mut self, required: bool) -> Self {
1190        self.required = required;
1191        self
1192    }
1193
1194    pub fn name(&self) -> &str {
1195        self.name.as_str()
1196    }
1197
1198    pub fn is_named(&self) -> bool {
1199        !self.is_unnamed()
1200    }
1201
1202    pub fn is_unnamed(&self) -> bool {
1203        self.name.parse::<u64>().is_ok()
1204    }
1205
1206    pub fn serde_name(&self) -> &str {
1207        if self.serde_name.is_empty() {
1208            self.name.as_str()
1209        } else {
1210            self.serde_name.as_str()
1211        }
1212    }
1213
1214    pub fn description(&self) -> &str {
1215        self.description.as_str()
1216    }
1217
1218    pub fn deprecated(&self) -> bool {
1219        self.deprecation_note.is_some()
1220    }
1221
1222    pub fn type_ref(&self) -> &TypeReference {
1223        &self.type_ref
1224    }
1225
1226    pub fn required(&self) -> bool {
1227        self.required
1228    }
1229
1230    pub fn flattened(&self) -> bool {
1231        self.flattened
1232    }
1233
1234    pub fn transform_callback(&self) -> &str {
1235        self.transform_callback.as_str()
1236    }
1237
1238    pub fn transform_callback_fn(&self) -> Option<fn(&mut TypeReference, &Typespace)> {
1239        self.transform_callback_fn
1240    }
1241}
1242
1243fn is_false(b: &bool) -> bool {
1244    !*b
1245}
1246
1247fn is_default<T: Default + PartialEq>(t: &T) -> bool {
1248    *t == Default::default()
1249}
1250
1251#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Eq)]
1252pub struct Enum {
1253    #[serde(skip_serializing, default)]
1254    pub id: SymbolId,
1255
1256    pub name: String,
1257    #[serde(skip_serializing_if = "String::is_empty", default)]
1258    pub serde_name: String,
1259    #[serde(skip_serializing_if = "String::is_empty", default)]
1260    pub description: String,
1261
1262    /// Generic type parameters, if any
1263    #[serde(skip_serializing_if = "Vec::is_empty", default)]
1264    pub parameters: Vec<TypeParameter>,
1265
1266    #[serde(skip_serializing_if = "Representation::is_default", default)]
1267    pub representation: Representation,
1268
1269    #[serde(skip_serializing_if = "Vec::is_empty", default)]
1270    pub variants: Vec<Variant>,
1271
1272    #[serde(skip_serializing_if = "is_default", default)]
1273    pub codegen_config: LanguageSpecificTypeCodegenConfig,
1274}
1275
1276impl Enum {
1277    pub fn new(name: String) -> Self {
1278        let id = SymbolId::enum_id(vec![name.clone()]);
1279        Enum {
1280            id,
1281            name,
1282            serde_name: Default::default(),
1283            description: Default::default(),
1284            parameters: Default::default(),
1285            representation: Default::default(),
1286            variants: Default::default(),
1287            codegen_config: Default::default(),
1288        }
1289    }
1290
1291    pub fn name(&self) -> &str {
1292        self.name.as_str()
1293    }
1294
1295    pub fn serde_name(&self) -> &str {
1296        if self.serde_name.is_empty() {
1297            self.name.as_str()
1298        } else {
1299            self.serde_name.as_str()
1300        }
1301    }
1302
1303    pub fn description(&self) -> &str {
1304        self.description.as_str()
1305    }
1306
1307    pub fn parameters(&self) -> std::slice::Iter<'_, TypeParameter> {
1308        self.parameters.iter()
1309    }
1310
1311    pub fn representation(&self) -> &Representation {
1312        &self.representation
1313    }
1314
1315    pub fn variants(&self) -> std::slice::Iter<'_, Variant> {
1316        self.variants.iter()
1317    }
1318}
1319
1320impl PartialEq for Enum {
1321    fn eq(&self, other: &Self) -> bool {
1322        self.name == other.name
1323            && self.serde_name == other.serde_name
1324            && self.description == other.description
1325            && self.parameters == other.parameters
1326            && self.representation == other.representation
1327            && self.variants == other.variants
1328            && self.codegen_config == other.codegen_config
1329    }
1330}
1331
1332impl From<Enum> for Type {
1333    fn from(val: Enum) -> Self {
1334        Type::Enum(val)
1335    }
1336}
1337
1338#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Eq)]
1339pub struct Variant {
1340    #[serde(skip_serializing, default)]
1341    pub id: SymbolId,
1342
1343    pub name: String,
1344    #[serde(skip_serializing_if = "String::is_empty", default)]
1345    pub serde_name: String,
1346    #[serde(skip_serializing_if = "String::is_empty", default)]
1347    pub description: String,
1348
1349    pub fields: Fields,
1350    #[serde(skip_serializing_if = "Option::is_none", default)]
1351    pub discriminant: Option<isize>,
1352
1353    /// If serde `untagged` attribute is set on a variant
1354    #[serde(skip_serializing_if = "is_false", default)]
1355    pub untagged: bool,
1356}
1357
1358impl Variant {
1359    pub fn new(name: String) -> Self {
1360        Variant {
1361            id: SymbolId::default(),
1362            name,
1363            serde_name: String::new(),
1364            description: String::new(),
1365            fields: Fields::None,
1366            discriminant: None,
1367            untagged: false,
1368        }
1369    }
1370
1371    pub fn name(&self) -> &str {
1372        self.name.as_str()
1373    }
1374
1375    pub fn serde_name(&self) -> &str {
1376        if self.serde_name.is_empty() {
1377            self.name.as_str()
1378        } else {
1379            self.serde_name.as_str()
1380        }
1381    }
1382
1383    pub fn description(&self) -> &str {
1384        self.description.as_str()
1385    }
1386
1387    pub fn fields(&self) -> std::slice::Iter<'_, Field> {
1388        self.fields.iter()
1389    }
1390
1391    pub fn discriminant(&self) -> Option<isize> {
1392        self.discriminant
1393    }
1394
1395    pub fn untagged(&self) -> bool {
1396        self.untagged
1397    }
1398}
1399
1400impl PartialEq for Variant {
1401    fn eq(&self, other: &Self) -> bool {
1402        self.name == other.name
1403            && self.serde_name == other.serde_name
1404            && self.description == other.description
1405            && self.fields == other.fields
1406            && self.discriminant == other.discriminant
1407            && self.untagged == other.untagged
1408    }
1409}
1410
1411#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Eq, PartialEq, Hash, Default)]
1412#[serde(rename_all = "snake_case")]
1413pub enum Representation {
1414    /// The default.
1415    ///
1416    /// ```json
1417    /// {"variant1": {"key1": "value1", "key2": "value2"}}
1418    /// ```
1419    #[default]
1420    External,
1421
1422    /// `#[serde(tag = "type")]`
1423    ///
1424    /// ```json
1425    /// {"type": "variant1", "key1": "value1", "key2": "value2"}
1426    /// ```
1427    Internal { tag: String },
1428
1429    /// `#[serde(tag = "t", content = "c")]`
1430    ///
1431    /// ```json
1432    /// {"t": "variant1", "c": {"key1": "value1", "key2": "value2"}}
1433    /// ```
1434    Adjacent { tag: String, content: String },
1435
1436    /// `#[serde(untagged)]`
1437    ///
1438    /// ```json
1439    /// {"key1": "value1", "key2": "value2"}
1440    /// ```
1441    None,
1442}
1443
1444impl Representation {
1445    pub fn new() -> Self {
1446        Default::default()
1447    }
1448
1449    pub fn is_default(&self) -> bool {
1450        matches!(self, Representation::External)
1451    }
1452
1453    pub fn is_external(&self) -> bool {
1454        matches!(self, Representation::External)
1455    }
1456
1457    pub fn is_internal(&self) -> bool {
1458        matches!(self, Representation::Internal { .. })
1459    }
1460
1461    pub fn is_adjacent(&self) -> bool {
1462        matches!(self, Representation::Adjacent { .. })
1463    }
1464
1465    pub fn is_none(&self) -> bool {
1466        matches!(self, Representation::None)
1467    }
1468}