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