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 error_type: Option<TypeReference>,
446
447    #[serde(flatten)]
448    pub output_type: OutputType,
449
450    /// Supported content types for request and response bodies.
451    ///
452    /// Note: serialization for header values is not affected by this field.
453    /// For displayable types of fields, it is encoded in plain strings.
454    /// For non-displayable types, it is encoded as json.
455    ///
456    /// Default: only json if empty
457    ///
458    #[serde(skip_serializing_if = "Vec::is_empty", default)]
459    pub serialization: Vec<SerializationMode>,
460
461    /// If a function is readonly, it means it does not modify the state of an application
462    #[serde(skip_serializing_if = "is_false", default)]
463    pub readonly: bool,
464
465    #[serde(skip_serializing_if = "BTreeSet::is_empty", default)]
466    pub tags: BTreeSet<String>,
467}
468
469impl Function {
470    pub fn new(name: String) -> Self {
471        let id = SymbolId::endpoint_id(vec![name.clone()]);
472        Function {
473            id,
474            name,
475            deprecation_note: Default::default(),
476            path: Default::default(),
477            description: Default::default(),
478            input_type: None,
479            input_headers: None,
480            error_type: None,
481            output_type: OutputType::Complete { output_type: None },
482            serialization: Default::default(),
483            readonly: Default::default(),
484            tags: Default::default(),
485        }
486    }
487
488    pub fn name(&self) -> &str {
489        self.name.as_str()
490    }
491
492    pub fn path(&self) -> &str {
493        self.path.as_str()
494    }
495
496    pub fn description(&self) -> &str {
497        self.description.as_str()
498    }
499
500    pub fn deprecated(&self) -> bool {
501        self.deprecation_note.is_some()
502    }
503
504    pub fn input_type(&self) -> Option<&TypeReference> {
505        self.input_type.as_ref()
506    }
507
508    pub fn input_headers(&self) -> Option<&TypeReference> {
509        self.input_headers.as_ref()
510    }
511
512    pub fn output_type(&self) -> &OutputType {
513        &self.output_type
514    }
515
516    pub fn serialization(&self) -> std::slice::Iter<'_, SerializationMode> {
517        self.serialization.iter()
518    }
519
520    pub fn readonly(&self) -> bool {
521        self.readonly
522    }
523}
524
525#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
526#[serde(tag = "output_kind", rename_all = "snake_case")]
527pub enum OutputType {
528    Complete {
529        #[serde(skip_serializing_if = "Option::is_none", default)]
530        output_type: Option<TypeReference>,
531    },
532    Stream {
533        item_type: TypeReference,
534    },
535}
536
537impl OutputType {
538    pub fn type_refs(&self) -> Vec<&TypeReference> {
539        match self {
540            OutputType::Complete {
541                output_type: Some(output_type),
542            } => vec![output_type],
543            OutputType::Complete { output_type: None } => vec![],
544            OutputType::Stream { item_type } => vec![item_type],
545        }
546    }
547}
548
549#[derive(Debug, Default, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
550#[serde(rename_all = "snake_case")]
551pub enum SerializationMode {
552    #[default]
553    Json,
554    Msgpack,
555}
556
557#[derive(
558    Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq, Hash, PartialOrd, Ord,
559)]
560pub struct TypeReference {
561    pub name: String,
562    /**
563     * References to actual types to use instead of the type parameters
564     * declared on the referred generic type
565     */
566    #[serde(skip_serializing_if = "Vec::is_empty", default)]
567    pub arguments: Vec<TypeReference>,
568}
569
570impl TypeReference {
571    pub fn new(name: impl Into<String>, arguments: Vec<TypeReference>) -> Self {
572        TypeReference {
573            name: name.into(),
574            arguments,
575        }
576    }
577
578    pub fn name(&self) -> &str {
579        self.name.as_str()
580    }
581
582    pub fn arguments(&self) -> std::slice::Iter<'_, TypeReference> {
583        self.arguments.iter()
584    }
585
586    pub fn fallback_recursively(&mut self, schema: &Typespace) {
587        loop {
588            let Some(type_def) = schema.get_type(self.name()) else {
589                return;
590            };
591            let Some(fallback_type_ref) = type_def.fallback_internal(self) else {
592                return;
593            };
594            *self = fallback_type_ref;
595        }
596    }
597
598    pub fn fallback_once(&self, schema: &Typespace) -> Option<TypeReference> {
599        let type_def = schema.get_type(self.name())?;
600        type_def.fallback_internal(self)
601    }
602}
603
604impl From<&str> for TypeReference {
605    fn from(name: &str) -> Self {
606        TypeReference::new(name, Vec::new())
607    }
608}
609
610impl From<String> for TypeReference {
611    fn from(name: String) -> Self {
612        TypeReference::new(name, Vec::new())
613    }
614}
615
616#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
617pub struct TypeParameter {
618    pub name: String,
619    #[serde(skip_serializing_if = "String::is_empty", default)]
620    pub description: String,
621}
622
623impl TypeParameter {
624    pub fn new(name: String, description: String) -> Self {
625        TypeParameter { name, description }
626    }
627
628    pub fn name(&self) -> &str {
629        self.name.as_str()
630    }
631
632    pub fn description(&self) -> &str {
633        self.description.as_str()
634    }
635}
636
637impl From<&str> for TypeParameter {
638    fn from(name: &str) -> Self {
639        TypeParameter {
640            name: name.into(),
641            description: String::new(),
642        }
643    }
644}
645
646impl From<String> for TypeParameter {
647    fn from(name: String) -> Self {
648        TypeParameter {
649            name,
650            description: String::new(),
651        }
652    }
653}
654
655impl PartialEq for TypeParameter {
656    fn eq(&self, other: &Self) -> bool {
657        self.name == other.name
658    }
659}
660
661impl Eq for TypeParameter {}
662
663impl std::hash::Hash for TypeParameter {
664    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
665        self.name.hash(state);
666    }
667}
668
669#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Eq, PartialEq)]
670#[serde(rename_all = "snake_case", tag = "kind")]
671pub enum Type {
672    Primitive(Primitive),
673    Struct(Struct),
674    Enum(Enum),
675}
676
677impl Type {
678    pub fn name(&self) -> &str {
679        match self {
680            Type::Primitive(p) => &p.name,
681            Type::Struct(s) => &s.name,
682            Type::Enum(e) => &e.name,
683        }
684    }
685
686    pub fn serde_name(&self) -> &str {
687        match self {
688            Type::Primitive(_) => self.name(),
689            Type::Struct(s) => s.serde_name(),
690            Type::Enum(e) => e.serde_name(),
691        }
692    }
693
694    pub fn description(&self) -> &str {
695        match self {
696            Type::Primitive(p) => &p.description,
697            Type::Struct(s) => &s.description,
698            Type::Enum(e) => &e.description,
699        }
700    }
701
702    pub fn parameters(&self) -> std::slice::Iter<'_, TypeParameter> {
703        match self {
704            Type::Primitive(p) => p.parameters(),
705            Type::Struct(s) => s.parameters(),
706            Type::Enum(e) => e.parameters(),
707        }
708    }
709
710    pub fn as_struct(&self) -> Option<&Struct> {
711        match self {
712            Type::Struct(s) => Some(s),
713            _ => None,
714        }
715    }
716
717    pub fn is_struct(&self) -> bool {
718        matches!(self, Type::Struct(_))
719    }
720
721    pub fn as_enum(&self) -> Option<&Enum> {
722        match self {
723            Type::Enum(e) => Some(e),
724            _ => None,
725        }
726    }
727
728    pub fn is_enum(&self) -> bool {
729        matches!(self, Type::Enum(_))
730    }
731
732    pub fn as_primitive(&self) -> Option<&Primitive> {
733        match self {
734            Type::Primitive(p) => Some(p),
735            _ => None,
736        }
737    }
738
739    pub fn is_primitive(&self) -> bool {
740        matches!(self, Type::Primitive(_))
741    }
742
743    fn fallback_internal(&self, origin: &TypeReference) -> Option<TypeReference> {
744        match self {
745            Type::Primitive(p) => p.fallback_internal(origin),
746            Type::Struct(_) => None,
747            Type::Enum(_) => None,
748        }
749    }
750
751    pub fn __internal_rename_current(&mut self, new_name: String) {
752        match self {
753            Type::Primitive(p) => p.name = new_name,
754            Type::Struct(s) => s.name = new_name,
755            Type::Enum(e) => e.name = new_name,
756        }
757    }
758
759    pub fn __internal_rebind_generic_parameters(
760        &mut self,
761        unresolved_to_resolved_map: &std::collections::HashMap<TypeReference, TypeReference>,
762        schema: &Typespace,
763    ) {
764        internal::replace_type_references_for_type(self, unresolved_to_resolved_map, schema)
765    }
766}
767
768#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Eq)]
769pub struct Primitive {
770    #[serde(skip_serializing, default)]
771    pub id: SymbolId,
772
773    pub name: String,
774    #[serde(skip_serializing_if = "String::is_empty", default)]
775    pub description: String,
776
777    /// Generic type parameters, if any
778    #[serde(skip_serializing_if = "Vec::is_empty", default)]
779    pub parameters: Vec<TypeParameter>,
780
781    /// Fallback type to use when the type is not supported by the target language
782    #[serde(skip_serializing_if = "Option::is_none", default)]
783    pub fallback: Option<TypeReference>,
784}
785
786impl Primitive {
787    pub fn new(
788        name: String,
789        description: String,
790        parameters: Vec<TypeParameter>,
791        fallback: Option<TypeReference>,
792    ) -> Self {
793        let id = SymbolId::new(SymbolKind::Primitive, vec![name.clone()]);
794        Primitive {
795            id,
796            name,
797            description,
798            parameters,
799            fallback,
800        }
801    }
802
803    pub fn name(&self) -> &str {
804        self.name.as_str()
805    }
806
807    pub fn description(&self) -> &str {
808        self.description.as_str()
809    }
810
811    pub fn parameters(&self) -> std::slice::Iter<'_, TypeParameter> {
812        self.parameters.iter()
813    }
814
815    pub fn fallback(&self) -> Option<&TypeReference> {
816        self.fallback.as_ref()
817    }
818
819    fn fallback_internal(&self, origin: &TypeReference) -> Option<TypeReference> {
820        // example:
821        // Self is DashMap<K, V>
822        // fallback is HashSet<V> (stupid example, but it demos generic param discard)
823        // origin is DashMap<String, u8>
824        // It should transform origin to HashSet<u8>
825        let fallback = self.fallback.as_ref()?;
826
827        if let Some((type_def_param_index, _)) = self
828            .parameters()
829            .enumerate()
830            .find(|(_, type_def_param)| type_def_param.name() == fallback.name())
831        {
832            // this is the case when fallback is to one of the generic parameters
833            // for example, Arc<T> to T
834            let Some(origin_type_ref_param) = origin.arguments.get(type_def_param_index) else {
835                // It means the origin type reference does no provide correct number of generic parameters
836                // required by the type definition
837                // It is invalid schema
838                return None;
839            };
840            return Some(TypeReference {
841                name: origin_type_ref_param.name.clone(),
842                arguments: origin_type_ref_param.arguments.clone(),
843            });
844        }
845
846        let mut new_arguments_for_origin = Vec::new();
847        for fallback_type_ref_param in fallback.arguments() {
848            let Some((type_def_param_index, _)) =
849                self.parameters().enumerate().find(|(_, type_def_param)| {
850                    type_def_param.name() == fallback_type_ref_param.name()
851                })
852            else {
853                // It means fallback type does not have
854                // as much generic parameters as this type definition
855                // in our example, it would be index 0
856                continue;
857            };
858
859            // in our example type_def_param_index would be index 1 for V
860            let Some(origin_type_ref_param) = origin.arguments.get(type_def_param_index) else {
861                // It means the origin type reference does no provide correct number of generic parameters
862                // required by the type definition
863                // It is invalid schema
864                return None;
865            };
866            new_arguments_for_origin.push(origin_type_ref_param.clone());
867        }
868
869        Some(TypeReference {
870            name: fallback.name.clone(),
871            arguments: new_arguments_for_origin,
872        })
873    }
874}
875
876impl PartialEq for Primitive {
877    fn eq(&self, other: &Self) -> bool {
878        self.name == other.name
879            && self.description == other.description
880            && self.parameters == other.parameters
881            && self.fallback == other.fallback
882    }
883}
884
885impl std::hash::Hash for Primitive {
886    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
887        self.name.hash(state);
888        self.description.hash(state);
889        self.parameters.hash(state);
890        self.fallback.hash(state);
891    }
892}
893
894impl From<Primitive> for Type {
895    fn from(val: Primitive) -> Self {
896        Type::Primitive(val)
897    }
898}
899
900#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Eq)]
901pub struct Struct {
902    #[serde(skip_serializing, default)]
903    pub id: SymbolId,
904
905    /// Name of a struct, should be a valid Rust struct name identifier
906    pub name: String,
907
908    /// If a serialized name is not a valid Rust struct name identifier
909    /// then this defines the name of a struct to be used in serialization
910    #[serde(skip_serializing_if = "String::is_empty", default)]
911    pub serde_name: String,
912
913    /// Markdown docs for the struct
914    #[serde(skip_serializing_if = "String::is_empty", default)]
915    pub description: String,
916
917    /// Generic type parameters, if any
918    #[serde(skip_serializing_if = "Vec::is_empty", default)]
919    pub parameters: Vec<TypeParameter>,
920
921    pub fields: Fields,
922
923    /// If serde transparent attribute is set on a struct
924    #[serde(skip_serializing_if = "is_false", default)]
925    pub transparent: bool,
926
927    #[serde(skip_serializing_if = "is_default", default)]
928    pub codegen_config: LanguageSpecificTypeCodegenConfig,
929}
930
931impl Struct {
932    pub fn new(name: impl Into<String>) -> Self {
933        let name = name.into();
934        let id = SymbolId::struct_id(vec![name.clone()]);
935        Struct {
936            id,
937            name,
938            serde_name: Default::default(),
939            description: Default::default(),
940            parameters: Default::default(),
941            fields: Default::default(),
942            transparent: Default::default(),
943            codegen_config: Default::default(),
944        }
945    }
946
947    /// Returns the name of a struct, should be a valid Rust struct name identifier
948    pub fn name(&self) -> &str {
949        self.name.as_str()
950    }
951
952    /// Returns the name of a struct to be used in serialization
953    pub fn serde_name(&self) -> &str {
954        if self.serde_name.is_empty() {
955            self.name.as_str()
956        } else {
957            self.serde_name.as_str()
958        }
959    }
960
961    pub fn description(&self) -> &str {
962        self.description.as_str()
963    }
964
965    pub fn parameters(&self) -> std::slice::Iter<'_, TypeParameter> {
966        self.parameters.iter()
967    }
968
969    pub fn fields(&self) -> std::slice::Iter<'_, Field> {
970        self.fields.iter()
971    }
972
973    pub fn transparent(&self) -> bool {
974        self.transparent
975    }
976
977    /// Returns true if a struct has 1 field and it is either named "0"
978    /// or is transparent in the serialized form
979    pub fn is_alias(&self) -> bool {
980        self.fields.len() == 1 && (self.fields[0].name() == "0" || self.transparent)
981    }
982
983    /// Returns true is a struct is a Rust unit struct.
984    /// Please note, that a unit struct is also an alias
985    // NOTE(andy): does this function make sense? A unit struct is a struct with no fields.
986    pub fn is_unit(&self) -> bool {
987        let Some(first_field) = self.fields.iter().next() else {
988            return false;
989        };
990
991        self.fields.len() == 1
992            && first_field.name() == "0"
993            && first_field.type_ref.name == "std::tuple::Tuple0"
994            && !first_field.required
995    }
996
997    /// Returns true if a struct is a Rust tuple struct.
998    pub fn is_tuple(&self) -> bool {
999        !self.fields.is_empty()
1000            && self
1001                .fields
1002                .iter()
1003                .all(|f| f.name().parse::<usize>().is_ok())
1004    }
1005}
1006
1007impl PartialEq for Struct {
1008    fn eq(&self, other: &Self) -> bool {
1009        self.name == other.name
1010            && self.serde_name == other.serde_name
1011            && self.description == other.description
1012            && self.parameters == other.parameters
1013            && self.fields == other.fields
1014            && self.transparent == other.transparent
1015            && self.codegen_config == other.codegen_config
1016    }
1017}
1018
1019impl From<Struct> for Type {
1020    fn from(val: Struct) -> Self {
1021        Type::Struct(val)
1022    }
1023}
1024
1025#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Eq, PartialEq, Default)]
1026#[serde(rename_all = "snake_case")]
1027pub enum Fields {
1028    /// Named struct or variant:
1029    /// struct S { a: u8, b: u8 }
1030    /// enum S { T { a: u8, b: u8 } }
1031    Named(Vec<Field>),
1032    /// Tuple struct or variant:
1033    /// struct S(u8, u8);
1034    /// enum S { T(u8, u8) }
1035    Unnamed(Vec<Field>),
1036    /// Unit struct or variant:
1037    ///
1038    /// struct S;
1039    /// enum S { U }
1040    #[default]
1041    None,
1042}
1043
1044impl Fields {
1045    pub fn is_empty(&self) -> bool {
1046        match self {
1047            Fields::Named(fields) | Fields::Unnamed(fields) => fields.is_empty(),
1048            Fields::None => true,
1049        }
1050    }
1051
1052    pub fn len(&self) -> usize {
1053        match self {
1054            Fields::Named(fields) | Fields::Unnamed(fields) => fields.len(),
1055            Fields::None => 0,
1056        }
1057    }
1058
1059    pub fn iter(&self) -> std::slice::Iter<'_, Field> {
1060        match self {
1061            Fields::Named(fields) | Fields::Unnamed(fields) => fields.iter(),
1062            Fields::None => [].iter(),
1063        }
1064    }
1065
1066    pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, Field> {
1067        match self {
1068            Fields::Named(fields) | Fields::Unnamed(fields) => fields.iter_mut(),
1069            Fields::None => [].iter_mut(),
1070        }
1071    }
1072}
1073
1074impl Index<usize> for Fields {
1075    type Output = Field;
1076
1077    fn index(&self, index: usize) -> &Self::Output {
1078        match self {
1079            Fields::Named(fields) | Fields::Unnamed(fields) => &fields[index],
1080            Fields::None => panic!("index out of bounds"),
1081        }
1082    }
1083}
1084
1085impl IntoIterator for Fields {
1086    type Item = Field;
1087    type IntoIter = std::vec::IntoIter<Field>;
1088
1089    fn into_iter(self) -> Self::IntoIter {
1090        match self {
1091            Fields::Named(fields) => fields.into_iter(),
1092            Fields::Unnamed(fields) => fields.into_iter(),
1093            Fields::None => vec![].into_iter(),
1094        }
1095    }
1096}
1097
1098#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Eq)]
1099pub struct Field {
1100    #[serde(skip_serializing, default)]
1101    pub id: SymbolId,
1102
1103    /// Field name, should be a valid Rust field name identifier
1104    pub name: String,
1105    /// If a serialized name is not a valid Rust field name identifier
1106    /// then this defines the name of a field to be used in serialization
1107    #[serde(skip_serializing_if = "String::is_empty", default)]
1108    pub serde_name: String,
1109    /// Rust docs for the field
1110    #[serde(skip_serializing_if = "String::is_empty", default)]
1111    pub description: String,
1112
1113    /// Deprecation note. If none, field is not deprecated.
1114    /// If present as empty string, field is deprecated without a note.
1115    #[serde(skip_serializing_if = "Option::is_none", default)]
1116    pub deprecation_note: Option<String>,
1117
1118    /// Type of a field
1119    #[serde(rename = "type")]
1120    pub type_ref: TypeReference,
1121    /// required and not nullable:
1122    /// - field always present and not null / none
1123    ///
1124    /// required and nullable:
1125    /// - Rust: `Option<T>`, do not skip serializing if None
1126    /// - TypeScript: T | null, do not skip serializing if null
1127    ///
1128    /// not required and not nullable:
1129    /// - Rust: `Option<T>`, skip serializing if None
1130    /// - TypeScript: T | undefined, skip serializing if undefined
1131    ///
1132    /// not required and nullable:
1133    ///   serializers and deserializers are required to differentiate between
1134    ///   missing fields and null / none fields
1135    /// - Rust: `reflectapi::Option<T>` is enum with Undefined, None and Some variants
1136    /// - TypeScript: T | null | undefined
1137    ///
1138    /// Default is false
1139    #[serde(skip_serializing_if = "is_false", default)]
1140    pub required: bool,
1141    /// If serde flatten attribute is set on a field
1142    /// Default is false
1143    #[serde(skip_serializing_if = "is_false", default)]
1144    pub flattened: bool,
1145
1146    #[serde(skip, default)]
1147    pub transform_callback: String,
1148    #[serde(skip, default)]
1149    pub transform_callback_fn: Option<fn(&mut TypeReference, &Typespace) -> ()>,
1150}
1151
1152impl PartialEq for Field {
1153    fn eq(
1154        &self,
1155        Self {
1156            id: _,
1157            name,
1158            serde_name,
1159            description,
1160            deprecation_note,
1161            type_ref,
1162            required,
1163            flattened,
1164            transform_callback,
1165            transform_callback_fn: _,
1166        }: &Self,
1167    ) -> bool {
1168        self.name == *name
1169            && self.serde_name == *serde_name
1170            && self.description == *description
1171            && self.deprecation_note == *deprecation_note
1172            && self.type_ref == *type_ref
1173            && self.required == *required
1174            && self.flattened == *flattened
1175            && self.transform_callback == *transform_callback
1176    }
1177}
1178
1179impl std::hash::Hash for Field {
1180    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1181        self.name.hash(state);
1182        self.serde_name.hash(state);
1183        self.description.hash(state);
1184        self.deprecation_note.hash(state);
1185        self.type_ref.hash(state);
1186        self.required.hash(state);
1187        self.flattened.hash(state);
1188        self.transform_callback.hash(state);
1189    }
1190}
1191
1192impl Field {
1193    pub fn new(name: String, type_ref: TypeReference) -> Self {
1194        Field {
1195            id: SymbolId::default(),
1196            name,
1197            type_ref,
1198            serde_name: Default::default(),
1199            description: Default::default(),
1200            deprecation_note: Default::default(),
1201            required: Default::default(),
1202            flattened: Default::default(),
1203            transform_callback: Default::default(),
1204            transform_callback_fn: Default::default(),
1205        }
1206    }
1207
1208    pub fn with_required(mut self, required: bool) -> Self {
1209        self.required = required;
1210        self
1211    }
1212
1213    pub fn name(&self) -> &str {
1214        self.name.as_str()
1215    }
1216
1217    pub fn is_named(&self) -> bool {
1218        !self.is_unnamed()
1219    }
1220
1221    pub fn is_unnamed(&self) -> bool {
1222        self.name.parse::<u64>().is_ok()
1223    }
1224
1225    pub fn serde_name(&self) -> &str {
1226        if self.serde_name.is_empty() {
1227            self.name.as_str()
1228        } else {
1229            self.serde_name.as_str()
1230        }
1231    }
1232
1233    pub fn description(&self) -> &str {
1234        self.description.as_str()
1235    }
1236
1237    pub fn deprecated(&self) -> bool {
1238        self.deprecation_note.is_some()
1239    }
1240
1241    pub fn type_ref(&self) -> &TypeReference {
1242        &self.type_ref
1243    }
1244
1245    pub fn required(&self) -> bool {
1246        self.required
1247    }
1248
1249    pub fn flattened(&self) -> bool {
1250        self.flattened
1251    }
1252
1253    pub fn transform_callback(&self) -> &str {
1254        self.transform_callback.as_str()
1255    }
1256
1257    pub fn transform_callback_fn(&self) -> Option<fn(&mut TypeReference, &Typespace)> {
1258        self.transform_callback_fn
1259    }
1260}
1261
1262fn is_false(b: &bool) -> bool {
1263    !*b
1264}
1265
1266fn is_default<T: Default + PartialEq>(t: &T) -> bool {
1267    *t == Default::default()
1268}
1269
1270#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Eq)]
1271pub struct Enum {
1272    #[serde(skip_serializing, default)]
1273    pub id: SymbolId,
1274
1275    pub name: String,
1276    #[serde(skip_serializing_if = "String::is_empty", default)]
1277    pub serde_name: String,
1278    #[serde(skip_serializing_if = "String::is_empty", default)]
1279    pub description: String,
1280
1281    /// Generic type parameters, if any
1282    #[serde(skip_serializing_if = "Vec::is_empty", default)]
1283    pub parameters: Vec<TypeParameter>,
1284
1285    #[serde(skip_serializing_if = "Representation::is_default", default)]
1286    pub representation: Representation,
1287
1288    #[serde(skip_serializing_if = "Vec::is_empty", default)]
1289    pub variants: Vec<Variant>,
1290
1291    #[serde(skip_serializing_if = "is_default", default)]
1292    pub codegen_config: LanguageSpecificTypeCodegenConfig,
1293}
1294
1295impl Enum {
1296    pub fn new(name: String) -> Self {
1297        let id = SymbolId::enum_id(vec![name.clone()]);
1298        Enum {
1299            id,
1300            name,
1301            serde_name: Default::default(),
1302            description: Default::default(),
1303            parameters: Default::default(),
1304            representation: Default::default(),
1305            variants: Default::default(),
1306            codegen_config: Default::default(),
1307        }
1308    }
1309
1310    pub fn name(&self) -> &str {
1311        self.name.as_str()
1312    }
1313
1314    pub fn serde_name(&self) -> &str {
1315        if self.serde_name.is_empty() {
1316            self.name.as_str()
1317        } else {
1318            self.serde_name.as_str()
1319        }
1320    }
1321
1322    pub fn description(&self) -> &str {
1323        self.description.as_str()
1324    }
1325
1326    pub fn parameters(&self) -> std::slice::Iter<'_, TypeParameter> {
1327        self.parameters.iter()
1328    }
1329
1330    pub fn representation(&self) -> &Representation {
1331        &self.representation
1332    }
1333
1334    pub fn variants(&self) -> std::slice::Iter<'_, Variant> {
1335        self.variants.iter()
1336    }
1337}
1338
1339impl PartialEq for Enum {
1340    fn eq(&self, other: &Self) -> bool {
1341        self.name == other.name
1342            && self.serde_name == other.serde_name
1343            && self.description == other.description
1344            && self.parameters == other.parameters
1345            && self.representation == other.representation
1346            && self.variants == other.variants
1347            && self.codegen_config == other.codegen_config
1348    }
1349}
1350
1351impl From<Enum> for Type {
1352    fn from(val: Enum) -> Self {
1353        Type::Enum(val)
1354    }
1355}
1356
1357#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Eq)]
1358pub struct Variant {
1359    #[serde(skip_serializing, default)]
1360    pub id: SymbolId,
1361
1362    pub name: String,
1363    #[serde(skip_serializing_if = "String::is_empty", default)]
1364    pub serde_name: String,
1365    #[serde(skip_serializing_if = "String::is_empty", default)]
1366    pub description: String,
1367
1368    pub fields: Fields,
1369    #[serde(skip_serializing_if = "Option::is_none", default)]
1370    pub discriminant: Option<isize>,
1371
1372    /// If serde `untagged` attribute is set on a variant
1373    #[serde(skip_serializing_if = "is_false", default)]
1374    pub untagged: bool,
1375}
1376
1377impl Variant {
1378    pub fn new(name: String) -> Self {
1379        Variant {
1380            id: SymbolId::default(),
1381            name,
1382            serde_name: String::new(),
1383            description: String::new(),
1384            fields: Fields::None,
1385            discriminant: None,
1386            untagged: false,
1387        }
1388    }
1389
1390    pub fn name(&self) -> &str {
1391        self.name.as_str()
1392    }
1393
1394    pub fn serde_name(&self) -> &str {
1395        if self.serde_name.is_empty() {
1396            self.name.as_str()
1397        } else {
1398            self.serde_name.as_str()
1399        }
1400    }
1401
1402    pub fn description(&self) -> &str {
1403        self.description.as_str()
1404    }
1405
1406    pub fn fields(&self) -> std::slice::Iter<'_, Field> {
1407        self.fields.iter()
1408    }
1409
1410    pub fn discriminant(&self) -> Option<isize> {
1411        self.discriminant
1412    }
1413
1414    pub fn untagged(&self) -> bool {
1415        self.untagged
1416    }
1417}
1418
1419impl PartialEq for Variant {
1420    fn eq(&self, other: &Self) -> bool {
1421        self.name == other.name
1422            && self.serde_name == other.serde_name
1423            && self.description == other.description
1424            && self.fields == other.fields
1425            && self.discriminant == other.discriminant
1426            && self.untagged == other.untagged
1427    }
1428}
1429
1430#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Eq, PartialEq, Hash, Default)]
1431#[serde(rename_all = "snake_case")]
1432pub enum Representation {
1433    /// The default.
1434    ///
1435    /// ```json
1436    /// {"variant1": {"key1": "value1", "key2": "value2"}}
1437    /// ```
1438    #[default]
1439    External,
1440
1441    /// `#[serde(tag = "type")]`
1442    ///
1443    /// ```json
1444    /// {"type": "variant1", "key1": "value1", "key2": "value2"}
1445    /// ```
1446    Internal { tag: String },
1447
1448    /// `#[serde(tag = "t", content = "c")]`
1449    ///
1450    /// ```json
1451    /// {"t": "variant1", "c": {"key1": "value1", "key2": "value2"}}
1452    /// ```
1453    Adjacent { tag: String, content: String },
1454
1455    /// `#[serde(untagged)]`
1456    ///
1457    /// ```json
1458    /// {"key1": "value1", "key2": "value2"}
1459    /// ```
1460    None,
1461}
1462
1463impl Representation {
1464    pub fn new() -> Self {
1465        Default::default()
1466    }
1467
1468    pub fn is_default(&self) -> bool {
1469        matches!(self, Representation::External)
1470    }
1471
1472    pub fn is_external(&self) -> bool {
1473        matches!(self, Representation::External)
1474    }
1475
1476    pub fn is_internal(&self) -> bool {
1477        matches!(self, Representation::Internal { .. })
1478    }
1479
1480    pub fn is_adjacent(&self) -> bool {
1481        matches!(self, Representation::Adjacent { .. })
1482    }
1483
1484    pub fn is_none(&self) -> bool {
1485        matches!(self, Representation::None)
1486    }
1487}