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 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 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 strip_hidden_fields(&mut self) {
207 fn strip(ts: &mut Typespace) {
208 for ty in ts.types.iter_mut() {
209 match ty {
210 Type::Struct(s) => s.fields.retain(|f| !f.hidden),
211 Type::Enum(e) => {
212 for v in e.variants.iter_mut() {
213 v.fields.retain(|f| !f.hidden);
214 }
215 }
216 Type::Primitive(_) => {}
217 }
218 }
219 }
220 strip(&mut self.input_types);
221 strip(&mut self.output_types);
222 }
223
224 pub fn fold_transparent_types(&mut self) {
225 #[derive(Debug)]
227 struct SubstVisitor {
228 strukt: Struct,
229 to: TypeReference,
230 }
231
232 impl SubstVisitor {
233 fn new(strukt: Struct) -> Self {
234 assert!(strukt.transparent && strukt.fields.len() == 1);
235 Self {
236 to: strukt.fields[0].type_ref.clone(),
237 strukt,
238 }
239 }
240 }
241
242 impl Visitor for SubstVisitor {
243 type Output = ();
244
245 fn visit_type_ref(
246 &mut self,
247 type_ref: &mut TypeReference,
248 ) -> ControlFlow<Self::Output, Self::Output> {
249 if type_ref.name == self.strukt.name {
250 let subst = subst::mk_subst(&self.strukt.parameters, &type_ref.arguments);
251 *type_ref = self.to.clone().subst(&subst);
252 }
253
254 type_ref.visit_mut(self)?;
255
256 ControlFlow::Continue(())
257 }
258 }
259
260 let transparent_types = self
261 .input_types()
262 .types()
263 .filter_map(|t| {
264 t.as_struct()
265 .filter(|i| i.transparent && i.fields.len() == 1)
266 .cloned()
267 })
268 .collect::<Vec<_>>();
269
270 for strukt in transparent_types {
271 self.input_types.remove_type(strukt.name());
272 let _ = SubstVisitor::new(strukt).visit_schema_inputs(self);
273 }
274
275 let transparent_types = self
276 .output_types()
277 .types()
278 .filter_map(|t| {
279 t.as_struct()
280 .filter(|i| i.transparent && i.fields.len() == 1)
281 .cloned()
282 })
283 .collect::<Vec<_>>();
284
285 for strukt in transparent_types {
286 self.output_types.remove_type(strukt.name());
287 let _ = SubstVisitor::new(strukt).visit_schema_outputs(self);
288 }
289 }
290}
291
292#[derive(Clone, serde::Serialize, serde::Deserialize, Default)]
293pub struct Typespace {
294 #[serde(skip_serializing_if = "Vec::is_empty", default)]
295 types: Vec<Type>,
296
297 #[serde(skip_serializing, default)]
298 types_map: std::cell::RefCell<HashMap<String, usize>>,
299}
300
301impl fmt::Debug for Typespace {
302 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
303 f.debug_map()
304 .entries(self.types.iter().map(|t| (t.name().to_string(), t)))
305 .finish()
306 }
307}
308
309impl Typespace {
310 pub fn new() -> Self {
311 Typespace {
312 types: Vec::new(),
313 types_map: std::cell::RefCell::new(HashMap::new()),
314 }
315 }
316
317 pub fn is_empty(&self) -> bool {
318 self.types.is_empty()
319 }
320
321 pub fn types(&self) -> std::slice::Iter<'_, Type> {
322 self.types.iter()
323 }
324
325 pub fn get_type(&self, name: &str) -> Option<&Type> {
326 self.ensure_types_map();
327 let index = {
328 let b = self.types_map.borrow();
329 b.get(name).copied().unwrap_or(usize::MAX)
330 };
331 if index == usize::MAX {
332 return None;
333 }
334 self.types.get(index)
335 }
336
337 pub fn get_type_mut(&mut self, name: &str) -> Option<&mut Type> {
338 self.ensure_types_map();
339 let index = {
340 let b = self.types_map.borrow();
341 b.get(name).copied().unwrap_or(usize::MAX)
342 };
343 if index == usize::MAX {
344 return None;
345 }
346 self.types.get_mut(index)
347 }
348
349 pub fn reserve_type(&mut self, name: &str) -> bool {
350 self.ensure_types_map();
351 if self.types_map.borrow().contains_key(name) {
352 return false;
353 }
354 self.types_map.borrow_mut().insert(name.into(), usize::MAX);
355 true
356 }
357
358 pub fn insert_type(&mut self, ty: Type) {
359 self.ensure_types_map();
360 if let Some(index) = self.types_map.borrow().get(ty.name()) {
361 if index != &usize::MAX {
362 return;
363 }
364 }
365 self.types_map
366 .borrow_mut()
367 .insert(ty.name().into(), self.types.len());
368 self.types.push(ty);
369 }
370
371 pub fn remove_type(&mut self, ty: &str) -> Option<Type> {
372 self.ensure_types_map();
373 let index = self
374 .types_map
375 .borrow()
376 .get(ty)
377 .copied()
378 .unwrap_or(usize::MAX);
379 if index == usize::MAX {
380 return None;
381 }
382
383 let removed = self.types.remove(index);
384 self.invalidate_types_map();
390 Some(removed)
391 }
392
393 pub fn sort_types(&mut self) {
394 self.types.sort_by(|a, b| a.name().cmp(b.name()));
395 self.build_types_map();
396 }
397
398 pub fn has_type(&self, name: &str) -> bool {
399 self.ensure_types_map();
400 self.types_map.borrow().contains_key(name)
401 }
402
403 pub fn extend(&mut self, other: Self) {
404 self.ensure_types_map();
405 for ty in other.types {
406 if self.has_type(ty.name()) {
407 continue;
408 }
409 self.insert_type(ty);
410 }
411 }
412
413 fn invalidate_types_map(&self) {
414 self.types_map.borrow_mut().clear()
415 }
416
417 fn ensure_types_map(&self) {
418 if self.types_map.borrow().is_empty() && !self.types.is_empty() {
419 self.build_types_map();
420 }
421 }
422
423 fn build_types_map(&self) {
424 let mut types_map = HashMap::new();
425 for (i, ty) in self.types.iter().enumerate() {
426 types_map.insert(ty.name().into(), i);
427 }
428 *(self.types_map.borrow_mut()) = types_map;
429 }
430}
431
432#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
433pub struct Function {
434 pub name: String,
436 pub path: String,
438 #[serde(skip_serializing_if = "String::is_empty", default)]
440 pub description: String,
441 #[serde(skip_serializing_if = "Option::is_none", default)]
444 pub deprecation_note: Option<String>,
445
446 #[serde(skip_serializing_if = "Option::is_none", default)]
447 pub input_type: Option<TypeReference>,
448 #[serde(skip_serializing_if = "Option::is_none", default)]
449 pub input_headers: Option<TypeReference>,
450
451 #[serde(skip_serializing_if = "Option::is_none", default)]
452 pub error_type: Option<TypeReference>,
453
454 #[serde(flatten)]
455 pub output_type: OutputType,
456
457 #[serde(skip_serializing_if = "Vec::is_empty", default)]
466 pub serialization: Vec<SerializationMode>,
467
468 #[serde(skip_serializing_if = "is_false", default)]
470 pub readonly: bool,
471
472 #[serde(skip_serializing_if = "BTreeSet::is_empty", default)]
473 pub tags: BTreeSet<String>,
474}
475
476impl Function {
477 pub fn new(name: String) -> Self {
478 Function {
479 name,
480 deprecation_note: Default::default(),
481 path: Default::default(),
482 description: Default::default(),
483 input_type: None,
484 input_headers: None,
485 error_type: None,
486 output_type: OutputType::Complete { output_type: None },
487 serialization: Default::default(),
488 readonly: Default::default(),
489 tags: Default::default(),
490 }
491 }
492
493 pub fn name(&self) -> &str {
494 self.name.as_str()
495 }
496
497 pub fn path(&self) -> &str {
498 self.path.as_str()
499 }
500
501 pub fn description(&self) -> &str {
502 self.description.as_str()
503 }
504
505 pub fn deprecated(&self) -> bool {
506 self.deprecation_note.is_some()
507 }
508
509 pub fn input_type(&self) -> Option<&TypeReference> {
510 self.input_type.as_ref()
511 }
512
513 pub fn input_headers(&self) -> Option<&TypeReference> {
514 self.input_headers.as_ref()
515 }
516
517 pub fn output_type(&self) -> &OutputType {
518 &self.output_type
519 }
520
521 pub fn serialization(&self) -> std::slice::Iter<'_, SerializationMode> {
522 self.serialization.iter()
523 }
524
525 pub fn readonly(&self) -> bool {
526 self.readonly
527 }
528}
529
530#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
531#[serde(tag = "output_kind", rename_all = "snake_case")]
532pub enum OutputType {
533 Complete {
534 #[serde(skip_serializing_if = "Option::is_none", default)]
535 output_type: Option<TypeReference>,
536 },
537 Stream {
538 item_type: TypeReference,
539 },
540}
541
542impl OutputType {
543 pub fn type_refs(&self) -> Vec<&TypeReference> {
544 match self {
545 OutputType::Complete {
546 output_type: Some(output_type),
547 } => vec![output_type],
548 OutputType::Complete { output_type: None } => vec![],
549 OutputType::Stream { item_type } => vec![item_type],
550 }
551 }
552}
553
554#[derive(Debug, Default, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
555#[serde(rename_all = "snake_case")]
556pub enum SerializationMode {
557 #[default]
558 Json,
559 Msgpack,
560}
561
562#[derive(
563 Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq, Hash, PartialOrd, Ord,
564)]
565pub struct TypeReference {
566 pub name: String,
567 #[serde(skip_serializing_if = "Vec::is_empty", default)]
572 pub arguments: Vec<TypeReference>,
573}
574
575impl TypeReference {
576 pub fn new(name: impl Into<String>, arguments: Vec<TypeReference>) -> Self {
577 TypeReference {
578 name: name.into(),
579 arguments,
580 }
581 }
582
583 pub fn name(&self) -> &str {
584 self.name.as_str()
585 }
586
587 pub fn arguments(&self) -> std::slice::Iter<'_, TypeReference> {
588 self.arguments.iter()
589 }
590
591 pub fn fallback_recursively(&mut self, schema: &Typespace) {
592 loop {
593 let Some(type_def) = schema.get_type(self.name()) else {
594 return;
595 };
596 let Some(fallback_type_ref) = type_def.fallback_internal(self) else {
597 return;
598 };
599 *self = fallback_type_ref;
600 }
601 }
602
603 pub fn fallback_once(&self, schema: &Typespace) -> Option<TypeReference> {
604 let type_def = schema.get_type(self.name())?;
605 type_def.fallback_internal(self)
606 }
607}
608
609impl From<&str> for TypeReference {
610 fn from(name: &str) -> Self {
611 TypeReference::new(name, Vec::new())
612 }
613}
614
615impl From<String> for TypeReference {
616 fn from(name: String) -> Self {
617 TypeReference::new(name, Vec::new())
618 }
619}
620
621#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
622pub struct TypeParameter {
623 pub name: String,
624 #[serde(skip_serializing_if = "String::is_empty", default)]
625 pub description: String,
626}
627
628impl TypeParameter {
629 pub fn new(name: String, description: String) -> Self {
630 TypeParameter { name, description }
631 }
632
633 pub fn name(&self) -> &str {
634 self.name.as_str()
635 }
636
637 pub fn description(&self) -> &str {
638 self.description.as_str()
639 }
640}
641
642impl From<&str> for TypeParameter {
643 fn from(name: &str) -> Self {
644 TypeParameter {
645 name: name.into(),
646 description: String::new(),
647 }
648 }
649}
650
651impl From<String> for TypeParameter {
652 fn from(name: String) -> Self {
653 TypeParameter {
654 name,
655 description: String::new(),
656 }
657 }
658}
659
660impl PartialEq for TypeParameter {
661 fn eq(&self, other: &Self) -> bool {
662 self.name == other.name
663 }
664}
665
666impl Eq for TypeParameter {}
667
668impl std::hash::Hash for TypeParameter {
669 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
670 self.name.hash(state);
671 }
672}
673
674#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Eq, PartialEq)]
675#[serde(rename_all = "snake_case", tag = "kind")]
676pub enum Type {
677 Primitive(Primitive),
678 Struct(Struct),
679 Enum(Enum),
680}
681
682impl Type {
683 pub fn name(&self) -> &str {
684 match self {
685 Type::Primitive(p) => &p.name,
686 Type::Struct(s) => &s.name,
687 Type::Enum(e) => &e.name,
688 }
689 }
690
691 pub fn serde_name(&self) -> &str {
692 match self {
693 Type::Primitive(_) => self.name(),
694 Type::Struct(s) => s.serde_name(),
695 Type::Enum(e) => e.serde_name(),
696 }
697 }
698
699 pub fn description(&self) -> &str {
700 match self {
701 Type::Primitive(p) => &p.description,
702 Type::Struct(s) => &s.description,
703 Type::Enum(e) => &e.description,
704 }
705 }
706
707 pub fn parameters(&self) -> std::slice::Iter<'_, TypeParameter> {
708 match self {
709 Type::Primitive(p) => p.parameters(),
710 Type::Struct(s) => s.parameters(),
711 Type::Enum(e) => e.parameters(),
712 }
713 }
714
715 pub fn as_struct(&self) -> Option<&Struct> {
716 match self {
717 Type::Struct(s) => Some(s),
718 _ => None,
719 }
720 }
721
722 pub fn is_struct(&self) -> bool {
723 matches!(self, Type::Struct(_))
724 }
725
726 pub fn as_enum(&self) -> Option<&Enum> {
727 match self {
728 Type::Enum(e) => Some(e),
729 _ => None,
730 }
731 }
732
733 pub fn is_enum(&self) -> bool {
734 matches!(self, Type::Enum(_))
735 }
736
737 pub fn as_primitive(&self) -> Option<&Primitive> {
738 match self {
739 Type::Primitive(p) => Some(p),
740 _ => None,
741 }
742 }
743
744 pub fn is_primitive(&self) -> bool {
745 matches!(self, Type::Primitive(_))
746 }
747
748 fn fallback_internal(&self, origin: &TypeReference) -> Option<TypeReference> {
749 match self {
750 Type::Primitive(p) => p.fallback_internal(origin),
751 Type::Struct(_) => None,
752 Type::Enum(_) => None,
753 }
754 }
755
756 pub fn __internal_rename_current(&mut self, new_name: String) {
757 match self {
758 Type::Primitive(p) => p.name = new_name,
759 Type::Struct(s) => s.name = new_name,
760 Type::Enum(e) => e.name = new_name,
761 }
762 }
763
764 pub fn __internal_rebind_generic_parameters(
765 &mut self,
766 unresolved_to_resolved_map: &std::collections::HashMap<TypeReference, TypeReference>,
767 schema: &Typespace,
768 ) {
769 internal::replace_type_references_for_type(self, unresolved_to_resolved_map, schema)
770 }
771}
772
773#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq, Hash)]
774pub struct Primitive {
775 pub name: String,
776 #[serde(skip_serializing_if = "String::is_empty", default)]
777 pub description: String,
778
779 #[serde(skip_serializing_if = "Vec::is_empty", default)]
781 pub parameters: Vec<TypeParameter>,
782
783 #[serde(skip_serializing_if = "Option::is_none", default)]
785 pub fallback: Option<TypeReference>,
786
787 #[serde(
788 skip_serializing_if = "LanguageSpecificTypeCodegenConfig::is_serialization_default",
789 default
790 )]
791 pub codegen_config: LanguageSpecificTypeCodegenConfig,
792}
793
794impl Primitive {
795 pub fn new(
796 name: String,
797 description: String,
798 parameters: Vec<TypeParameter>,
799 fallback: Option<TypeReference>,
800 ) -> Self {
801 Primitive {
802 name,
803 description,
804 parameters,
805 fallback,
806 codegen_config: Default::default(),
807 }
808 }
809
810 pub fn name(&self) -> &str {
811 self.name.as_str()
812 }
813
814 pub fn description(&self) -> &str {
815 self.description.as_str()
816 }
817
818 pub fn parameters(&self) -> std::slice::Iter<'_, TypeParameter> {
819 self.parameters.iter()
820 }
821
822 pub fn fallback(&self) -> Option<&TypeReference> {
823 self.fallback.as_ref()
824 }
825
826 fn fallback_internal(&self, origin: &TypeReference) -> Option<TypeReference> {
827 let fallback = self.fallback.as_ref()?;
833
834 if let Some((type_def_param_index, _)) = self
835 .parameters()
836 .enumerate()
837 .find(|(_, type_def_param)| type_def_param.name() == fallback.name())
838 {
839 let Some(origin_type_ref_param) = origin.arguments.get(type_def_param_index) else {
842 return None;
846 };
847 return Some(TypeReference {
848 name: origin_type_ref_param.name.clone(),
849 arguments: origin_type_ref_param.arguments.clone(),
850 });
851 }
852
853 let mut new_arguments_for_origin = Vec::new();
854 for fallback_type_ref_param in fallback.arguments() {
855 let Some((type_def_param_index, _)) =
856 self.parameters().enumerate().find(|(_, type_def_param)| {
857 type_def_param.name() == fallback_type_ref_param.name()
858 })
859 else {
860 continue;
864 };
865
866 let Some(origin_type_ref_param) = origin.arguments.get(type_def_param_index) else {
868 return None;
872 };
873 new_arguments_for_origin.push(origin_type_ref_param.clone());
874 }
875
876 Some(TypeReference {
877 name: fallback.name.clone(),
878 arguments: new_arguments_for_origin,
879 })
880 }
881}
882
883impl From<Primitive> for Type {
884 fn from(val: Primitive) -> Self {
885 Type::Primitive(val)
886 }
887}
888
889#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq)]
890pub struct Struct {
891 pub name: String,
893
894 #[serde(skip_serializing_if = "String::is_empty", default)]
897 pub serde_name: String,
898
899 #[serde(skip_serializing_if = "String::is_empty", default)]
901 pub description: String,
902
903 #[serde(skip_serializing_if = "Vec::is_empty", default)]
905 pub parameters: Vec<TypeParameter>,
906
907 pub fields: Fields,
908
909 #[serde(skip_serializing_if = "is_false", default)]
911 pub transparent: bool,
912
913 #[serde(
914 skip_serializing_if = "LanguageSpecificTypeCodegenConfig::is_serialization_default",
915 default
916 )]
917 pub codegen_config: LanguageSpecificTypeCodegenConfig,
918}
919
920impl Struct {
921 pub fn new(name: impl Into<String>) -> Self {
922 let name = name.into();
923 Struct {
924 name,
925 serde_name: Default::default(),
926 description: Default::default(),
927 parameters: Default::default(),
928 fields: Default::default(),
929 transparent: Default::default(),
930 codegen_config: Default::default(),
931 }
932 }
933
934 pub fn name(&self) -> &str {
936 self.name.as_str()
937 }
938
939 pub fn serde_name(&self) -> &str {
941 if self.serde_name.is_empty() {
942 self.name.as_str()
943 } else {
944 self.serde_name.as_str()
945 }
946 }
947
948 pub fn description(&self) -> &str {
949 self.description.as_str()
950 }
951
952 pub fn parameters(&self) -> std::slice::Iter<'_, TypeParameter> {
953 self.parameters.iter()
954 }
955
956 pub fn fields(&self) -> std::slice::Iter<'_, Field> {
957 self.fields.iter()
958 }
959
960 pub fn transparent(&self) -> bool {
961 self.transparent
962 }
963
964 pub fn is_alias(&self) -> bool {
967 self.fields.len() == 1 && (self.fields[0].name() == "0" || self.transparent)
968 }
969
970 pub fn is_unit(&self) -> bool {
974 let Some(first_field) = self.fields.iter().next() else {
975 return false;
976 };
977
978 self.fields.len() == 1
979 && first_field.name() == "0"
980 && first_field.type_ref.name == "std::tuple::Tuple0"
981 && !first_field.required
982 }
983
984 pub fn is_tuple(&self) -> bool {
986 !self.fields.is_empty()
987 && self
988 .fields
989 .iter()
990 .all(|f| f.name().parse::<usize>().is_ok())
991 }
992}
993
994impl From<Struct> for Type {
995 fn from(val: Struct) -> Self {
996 Type::Struct(val)
997 }
998}
999
1000#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Eq, PartialEq, Default)]
1001#[serde(rename_all = "snake_case")]
1002pub enum Fields {
1003 Named(Vec<Field>),
1007 Unnamed(Vec<Field>),
1011 #[default]
1016 None,
1017}
1018
1019impl Fields {
1020 pub fn is_empty(&self) -> bool {
1021 match self {
1022 Fields::Named(fields) | Fields::Unnamed(fields) => fields.is_empty(),
1023 Fields::None => true,
1024 }
1025 }
1026
1027 pub fn len(&self) -> usize {
1028 match self {
1029 Fields::Named(fields) | Fields::Unnamed(fields) => fields.len(),
1030 Fields::None => 0,
1031 }
1032 }
1033
1034 pub fn iter(&self) -> std::slice::Iter<'_, Field> {
1035 match self {
1036 Fields::Named(fields) | Fields::Unnamed(fields) => fields.iter(),
1037 Fields::None => [].iter(),
1038 }
1039 }
1040
1041 pub fn iter_mut(&mut self) -> std::slice::IterMut<'_, Field> {
1042 match self {
1043 Fields::Named(fields) | Fields::Unnamed(fields) => fields.iter_mut(),
1044 Fields::None => [].iter_mut(),
1045 }
1046 }
1047
1048 pub fn retain<F>(&mut self, mut predicate: F)
1050 where
1051 F: FnMut(&Field) -> bool,
1052 {
1053 match self {
1054 Fields::Named(fields) | Fields::Unnamed(fields) => fields.retain(|f| predicate(f)),
1055 Fields::None => {}
1056 }
1057 }
1058}
1059
1060impl Index<usize> for Fields {
1061 type Output = Field;
1062
1063 fn index(&self, index: usize) -> &Self::Output {
1064 match self {
1065 Fields::Named(fields) | Fields::Unnamed(fields) => &fields[index],
1066 Fields::None => panic!("index out of bounds"),
1067 }
1068 }
1069}
1070
1071impl IntoIterator for Fields {
1072 type Item = Field;
1073 type IntoIter = std::vec::IntoIter<Field>;
1074
1075 fn into_iter(self) -> Self::IntoIter {
1076 match self {
1077 Fields::Named(fields) => fields.into_iter(),
1078 Fields::Unnamed(fields) => fields.into_iter(),
1079 Fields::None => vec![].into_iter(),
1080 }
1081 }
1082}
1083
1084#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Eq)]
1085pub struct Field {
1086 pub name: String,
1088 #[serde(skip_serializing_if = "String::is_empty", default)]
1091 pub serde_name: String,
1092 #[serde(skip_serializing_if = "String::is_empty", default)]
1094 pub description: String,
1095
1096 #[serde(skip_serializing_if = "Option::is_none", default)]
1099 pub deprecation_note: Option<String>,
1100
1101 #[serde(rename = "type")]
1103 pub type_ref: TypeReference,
1104 #[serde(skip_serializing_if = "is_false", default)]
1123 pub required: bool,
1124 #[serde(skip_serializing_if = "is_false", default)]
1127 pub flattened: bool,
1128
1129 #[serde(skip_serializing_if = "is_false", default)]
1133 pub hidden: bool,
1134
1135 #[serde(skip, default)]
1136 pub transform_callback: String,
1137 #[serde(skip, default)]
1138 pub transform_callback_fn: Option<fn(&mut TypeReference, &Typespace) -> ()>,
1139}
1140
1141impl PartialEq for Field {
1142 fn eq(
1143 &self,
1144 Self {
1145 name,
1146 serde_name,
1147 description,
1148 deprecation_note,
1149 type_ref,
1150 required,
1151 flattened,
1152 hidden,
1153 transform_callback,
1154 transform_callback_fn: _,
1155 }: &Self,
1156 ) -> bool {
1157 self.name == *name
1158 && self.serde_name == *serde_name
1159 && self.description == *description
1160 && self.deprecation_note == *deprecation_note
1161 && self.type_ref == *type_ref
1162 && self.required == *required
1163 && self.flattened == *flattened
1164 && self.hidden == *hidden
1165 && self.transform_callback == *transform_callback
1166 }
1167}
1168
1169impl std::hash::Hash for Field {
1170 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
1171 self.name.hash(state);
1172 self.serde_name.hash(state);
1173 self.description.hash(state);
1174 self.deprecation_note.hash(state);
1175 self.type_ref.hash(state);
1176 self.required.hash(state);
1177 self.flattened.hash(state);
1178 self.hidden.hash(state);
1179 self.transform_callback.hash(state);
1180 }
1181}
1182
1183impl Field {
1184 pub fn new(name: String, type_ref: TypeReference) -> Self {
1185 Field {
1186 name,
1187 type_ref,
1188 serde_name: Default::default(),
1189 description: Default::default(),
1190 deprecation_note: Default::default(),
1191 required: Default::default(),
1192 flattened: Default::default(),
1193 hidden: Default::default(),
1194 transform_callback: Default::default(),
1195 transform_callback_fn: Default::default(),
1196 }
1197 }
1198
1199 pub fn with_required(mut self, required: bool) -> Self {
1200 self.required = required;
1201 self
1202 }
1203
1204 pub fn name(&self) -> &str {
1205 self.name.as_str()
1206 }
1207
1208 pub fn is_named(&self) -> bool {
1209 !self.is_unnamed()
1210 }
1211
1212 pub fn is_unnamed(&self) -> bool {
1213 self.name.parse::<u64>().is_ok()
1214 }
1215
1216 pub fn serde_name(&self) -> &str {
1217 if self.serde_name.is_empty() {
1218 self.name.as_str()
1219 } else {
1220 self.serde_name.as_str()
1221 }
1222 }
1223
1224 pub fn description(&self) -> &str {
1225 self.description.as_str()
1226 }
1227
1228 pub fn deprecated(&self) -> bool {
1229 self.deprecation_note.is_some()
1230 }
1231
1232 pub fn hidden(&self) -> bool {
1233 self.hidden
1234 }
1235
1236 pub fn type_ref(&self) -> &TypeReference {
1237 &self.type_ref
1238 }
1239
1240 pub fn required(&self) -> bool {
1241 self.required
1242 }
1243
1244 pub fn flattened(&self) -> bool {
1245 self.flattened
1246 }
1247
1248 pub fn transform_callback(&self) -> &str {
1249 self.transform_callback.as_str()
1250 }
1251
1252 pub fn transform_callback_fn(&self) -> Option<fn(&mut TypeReference, &Typespace)> {
1253 self.transform_callback_fn
1254 }
1255}
1256
1257fn is_false(b: &bool) -> bool {
1258 !*b
1259}
1260
1261#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq)]
1262pub struct Enum {
1263 pub name: String,
1264 #[serde(skip_serializing_if = "String::is_empty", default)]
1265 pub serde_name: String,
1266 #[serde(skip_serializing_if = "String::is_empty", default)]
1267 pub description: String,
1268
1269 #[serde(skip_serializing_if = "Vec::is_empty", default)]
1271 pub parameters: Vec<TypeParameter>,
1272
1273 #[serde(skip_serializing_if = "Representation::is_default", default)]
1274 pub representation: Representation,
1275
1276 #[serde(skip_serializing_if = "Vec::is_empty", default)]
1277 pub variants: Vec<Variant>,
1278
1279 #[serde(
1280 skip_serializing_if = "LanguageSpecificTypeCodegenConfig::is_serialization_default",
1281 default
1282 )]
1283 pub codegen_config: LanguageSpecificTypeCodegenConfig,
1284}
1285
1286impl Enum {
1287 pub fn new(name: String) -> Self {
1288 Enum {
1289 name,
1290 serde_name: Default::default(),
1291 description: Default::default(),
1292 parameters: Default::default(),
1293 representation: Default::default(),
1294 variants: Default::default(),
1295 codegen_config: Default::default(),
1296 }
1297 }
1298
1299 pub fn name(&self) -> &str {
1300 self.name.as_str()
1301 }
1302
1303 pub fn serde_name(&self) -> &str {
1304 if self.serde_name.is_empty() {
1305 self.name.as_str()
1306 } else {
1307 self.serde_name.as_str()
1308 }
1309 }
1310
1311 pub fn description(&self) -> &str {
1312 self.description.as_str()
1313 }
1314
1315 pub fn parameters(&self) -> std::slice::Iter<'_, TypeParameter> {
1316 self.parameters.iter()
1317 }
1318
1319 pub fn representation(&self) -> &Representation {
1320 &self.representation
1321 }
1322
1323 pub fn variants(&self) -> std::slice::Iter<'_, Variant> {
1324 self.variants.iter()
1325 }
1326}
1327
1328impl From<Enum> for Type {
1329 fn from(val: Enum) -> Self {
1330 Type::Enum(val)
1331 }
1332}
1333
1334#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq, Eq)]
1335pub struct Variant {
1336 pub name: String,
1337 #[serde(skip_serializing_if = "String::is_empty", default)]
1338 pub serde_name: String,
1339 #[serde(skip_serializing_if = "String::is_empty", default)]
1340 pub description: String,
1341
1342 pub fields: Fields,
1343 #[serde(skip_serializing_if = "Option::is_none", default)]
1344 pub discriminant: Option<isize>,
1345
1346 #[serde(skip_serializing_if = "is_false", default)]
1348 pub untagged: bool,
1349}
1350
1351impl Variant {
1352 pub fn new(name: String) -> Self {
1353 Variant {
1354 name,
1355 serde_name: String::new(),
1356 description: String::new(),
1357 fields: Fields::None,
1358 discriminant: None,
1359 untagged: false,
1360 }
1361 }
1362
1363 pub fn name(&self) -> &str {
1364 self.name.as_str()
1365 }
1366
1367 pub fn serde_name(&self) -> &str {
1368 if self.serde_name.is_empty() {
1369 self.name.as_str()
1370 } else {
1371 self.serde_name.as_str()
1372 }
1373 }
1374
1375 pub fn description(&self) -> &str {
1376 self.description.as_str()
1377 }
1378
1379 pub fn fields(&self) -> std::slice::Iter<'_, Field> {
1380 self.fields.iter()
1381 }
1382
1383 pub fn discriminant(&self) -> Option<isize> {
1384 self.discriminant
1385 }
1386
1387 pub fn untagged(&self) -> bool {
1388 self.untagged
1389 }
1390}
1391
1392#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, Eq, PartialEq, Hash, Default)]
1393#[serde(rename_all = "snake_case")]
1394pub enum Representation {
1395 #[default]
1401 External,
1402
1403 Internal { tag: String },
1409
1410 Adjacent { tag: String, content: String },
1416
1417 None,
1423}
1424
1425impl Representation {
1426 pub fn new() -> Self {
1427 Default::default()
1428 }
1429
1430 pub fn is_default(&self) -> bool {
1431 matches!(self, Representation::External)
1432 }
1433
1434 pub fn is_external(&self) -> bool {
1435 matches!(self, Representation::External)
1436 }
1437
1438 pub fn is_internal(&self) -> bool {
1439 matches!(self, Representation::Internal { .. })
1440 }
1441
1442 pub fn is_adjacent(&self) -> bool {
1443 matches!(self, Representation::Adjacent { .. })
1444 }
1445
1446 pub fn is_none(&self) -> bool {
1447 matches!(self, Representation::None)
1448 }
1449}
1450
1451#[cfg(test)]
1452mod tests {
1453 use super::*;
1454
1455 fn primitive(name: &str) -> Type {
1456 Type::Primitive(Primitive {
1457 name: name.to_string(),
1458 description: String::new(),
1459 parameters: vec![],
1460 fallback: None,
1461 codegen_config: LanguageSpecificTypeCodegenConfig::default(),
1462 })
1463 }
1464
1465 #[test]
1472 fn remove_type_keeps_map_consistent_across_multiple_removals() {
1473 let mut ts = Typespace::default();
1474 ts.insert_type(primitive("a"));
1475 ts.insert_type(primitive("b"));
1476 ts.insert_type(primitive("c"));
1477 ts.insert_type(primitive("d"));
1478
1479 let _ = ts.remove_type("b");
1481 let _ = ts.remove_type("c");
1482
1483 assert!(ts.has_type("a"), "untouched type 'a' should still resolve");
1484 assert!(ts.has_type("d"), "untouched type 'd' should still resolve");
1485 assert!(!ts.has_type("b"));
1486 assert!(!ts.has_type("c"));
1487
1488 assert_eq!(ts.get_type("a").map(|t| t.name()), Some("a"));
1491 assert_eq!(ts.get_type("d").map(|t| t.name()), Some("d"));
1492 }
1493
1494 #[test]
1495 fn remove_type_returns_the_value_we_asked_for() {
1496 let mut ts = Typespace::default();
1497 ts.insert_type(primitive("first"));
1498 ts.insert_type(primitive("second"));
1499 ts.insert_type(primitive("third"));
1500
1501 let removed = ts.remove_type("second").expect("should find 'second'");
1502 assert_eq!(removed.name(), "second");
1503
1504 assert_eq!(ts.get_type("first").map(|t| t.name()), Some("first"));
1506 assert_eq!(ts.get_type("third").map(|t| t.name()), Some("third"));
1507 }
1508}