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