Skip to main content

reflectapi_schema/
lib.rs

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