1use forge_ir as ir;
30
31#[derive(Debug, Clone, PartialEq)]
34pub enum StageErrorRepr {
35 Rejected {
36 reason: String,
37 diagnostics: Vec<ir::Diagnostic>,
38 },
39 PluginBug(String),
40 ConfigInvalid(String),
41 ResourceExceeded(ResourceKindRepr),
42}
43
44#[derive(Debug, Clone, Copy, PartialEq, Eq)]
45pub enum ResourceKindRepr {
46 Fuel,
47 Memory,
48 Time,
49 OutputSize,
50}
51
52macro_rules! define_world_conversions {
53 ($mod:ident, $world:ident) => {
54 pub mod $mod {
55 #![doc = concat!(" `", stringify!($world), "` world's WIT types.")]
57
58 use super::{ResourceKindRepr, StageErrorRepr};
59 use crate::bindings::$world::forge::plugin::{stage as b_stage, types as b};
60 use crate::BindgenError;
61 use forge_ir as ir;
62
63 pub fn plugin_info_from_wit(p: b::PluginInfo) -> ir::PluginInfo {
68 ir::PluginInfo {
69 name: p.name,
70 version: p.version,
71 }
72 }
73
74 pub fn plugin_info_to_wit(p: ir::PluginInfo) -> b::PluginInfo {
75 b::PluginInfo {
76 name: p.name,
77 version: p.version,
78 }
79 }
80
81 fn loc_from(l: b::SpecLocation) -> ir::SpecLocation {
86 ir::SpecLocation {
87 pointer: l.pointer,
88 file: l.file,
89 }
90 }
91
92 fn loc_to(l: ir::SpecLocation) -> b::SpecLocation {
93 b::SpecLocation {
94 pointer: l.pointer,
95 file: l.file,
96 }
97 }
98
99 fn value_from(v: b::Value) -> ir::Value {
104 match v {
105 b::Value::Null => ir::Value::Null,
106 b::Value::Bool(value) => ir::Value::Bool { value },
107 b::Value::Int(value) => ir::Value::Int { value },
108 b::Value::Float(value) => ir::Value::Float { value },
109 b::Value::String(value) => ir::Value::String { value },
110 b::Value::List(items) => ir::Value::List { items },
111 b::Value::Object(fields) => ir::Value::Object {
112 fields: fields.into_iter().collect(),
113 },
114 }
115 }
116
117 fn value_to(v: ir::Value) -> b::Value {
118 match v {
119 ir::Value::Null => b::Value::Null,
120 ir::Value::Bool { value } => b::Value::Bool(value),
121 ir::Value::Int { value } => b::Value::Int(value),
122 ir::Value::Float { value } => b::Value::Float(value),
123 ir::Value::String { value } => b::Value::String(value),
124 ir::Value::List { items } => b::Value::List(items),
125 ir::Value::Object { fields } => b::Value::Object(fields),
126 }
127 }
128
129 fn extensions_from(xs: Vec<(String, ir::ValueRef)>) -> Vec<(String, ir::ValueRef)> {
133 xs
134 }
135
136 fn extensions_to(xs: Vec<(String, ir::ValueRef)>) -> Vec<(String, ir::ValueRef)> {
137 xs
138 }
139
140 pub fn diagnostic_from_wit(d: b::Diagnostic) -> Result<ir::Diagnostic, BindgenError> {
145 Ok(ir::Diagnostic {
146 severity: severity_from(d.severity),
147 code: d.code,
148 message: d.message,
149 location: d.location.map(loc_from),
150 related: d.related.into_iter().map(related_from).collect(),
151 suggested_fix: d.suggested_fix.map(fix_from),
152 })
153 }
154
155 pub fn diagnostic_to_wit(d: ir::Diagnostic) -> b::Diagnostic {
156 b::Diagnostic {
157 severity: severity_to(d.severity),
158 code: d.code,
159 message: d.message,
160 location: d.location.map(loc_to),
161 related: d.related.into_iter().map(related_to).collect(),
162 suggested_fix: d.suggested_fix.map(fix_to),
163 }
164 }
165
166 fn severity_from(s: b::Severity) -> ir::Severity {
167 match s {
168 b::Severity::Error => ir::Severity::Error,
169 b::Severity::Warning => ir::Severity::Warning,
170 b::Severity::Info => ir::Severity::Info,
171 b::Severity::Hint => ir::Severity::Hint,
172 }
173 }
174
175 fn severity_to(s: ir::Severity) -> b::Severity {
176 match s {
177 ir::Severity::Error => b::Severity::Error,
178 ir::Severity::Warning => b::Severity::Warning,
179 ir::Severity::Info => b::Severity::Info,
180 ir::Severity::Hint => b::Severity::Hint,
181 }
182 }
183
184 fn related_from(r: b::RelatedInfo) -> ir::RelatedInfo {
185 ir::RelatedInfo {
186 message: r.message,
187 location: r.location.map(loc_from),
188 }
189 }
190
191 fn related_to(r: ir::RelatedInfo) -> b::RelatedInfo {
192 b::RelatedInfo {
193 message: r.message,
194 location: r.location.map(loc_to),
195 }
196 }
197
198 fn fix_from(f: b::FixSuggestion) -> ir::FixSuggestion {
199 ir::FixSuggestion {
200 message: f.message,
201 edits: f
202 .edits
203 .into_iter()
204 .map(|e| ir::FixEdit {
205 location: loc_from(e.location),
206 replacement: e.replacement,
207 })
208 .collect(),
209 }
210 }
211
212 fn fix_to(f: ir::FixSuggestion) -> b::FixSuggestion {
213 b::FixSuggestion {
214 message: f.message,
215 edits: f
216 .edits
217 .into_iter()
218 .map(|e| b::FixEdit {
219 location: loc_to(e.location),
220 replacement: e.replacement,
221 })
222 .collect(),
223 }
224 }
225
226 pub fn stage_error_from_wit(e: b_stage::StageError) -> StageErrorRepr {
231 match e {
232 b_stage::StageError::Rejected(r) => StageErrorRepr::Rejected {
233 reason: r.reason,
234 diagnostics: r
239 .diagnostics
240 .into_iter()
241 .filter_map(|d| diagnostic_from_wit(d).ok())
242 .collect(),
243 },
244 b_stage::StageError::PluginBug(s) => StageErrorRepr::PluginBug(s),
245 b_stage::StageError::ConfigInvalid(s) => StageErrorRepr::ConfigInvalid(s),
246 b_stage::StageError::ResourceExceeded(k) => {
247 StageErrorRepr::ResourceExceeded(match k {
248 b_stage::ResourceKind::Fuel => ResourceKindRepr::Fuel,
249 b_stage::ResourceKind::Memory => ResourceKindRepr::Memory,
250 b_stage::ResourceKind::Time => ResourceKindRepr::Time,
251 b_stage::ResourceKind::OutputSize => ResourceKindRepr::OutputSize,
252 })
253 }
254 }
255 }
256
257 pub fn ir_to_wit(i: ir::Ir) -> b::Ir {
262 b::Ir {
263 info: api_info_to(i.info),
264 operations: i.operations.into_iter().map(operation_to).collect(),
265 types: i.types.into_iter().map(named_type_to).collect(),
266 security_schemes: i
267 .security_schemes
268 .into_iter()
269 .map(security_scheme_to)
270 .collect(),
271 servers: i.servers.into_iter().map(server_to).collect(),
272 webhooks: i.webhooks.into_iter().map(webhook_to).collect(),
273 external_docs: i.external_docs.map(external_docs_to),
274 tags: i.tags.into_iter().map(tag_to).collect(),
275 json_schema_dialect: i.json_schema_dialect,
276 self_url: i.self_url,
277 values: i.values.into_iter().map(value_to).collect(),
278 }
279 }
280
281 pub fn ir_from_wit(i: b::Ir) -> Result<ir::Ir, BindgenError> {
282 let out = ir::Ir {
283 info: api_info_from(i.info),
284 operations: i
285 .operations
286 .into_iter()
287 .map(operation_from)
288 .collect::<Result<_, _>>()?,
289 types: i
290 .types
291 .into_iter()
292 .map(named_type_from)
293 .collect::<Result<_, _>>()?,
294 security_schemes: i
295 .security_schemes
296 .into_iter()
297 .map(security_scheme_from)
298 .collect(),
299 servers: i.servers.into_iter().map(server_from).collect(),
300 webhooks: i
301 .webhooks
302 .into_iter()
303 .map(webhook_from)
304 .collect::<Result<_, _>>()?,
305 external_docs: i.external_docs.map(external_docs_from),
306 tags: i.tags.into_iter().map(tag_from).collect(),
307 json_schema_dialect: i.json_schema_dialect,
308 self_url: i.self_url,
309 values: i.values.into_iter().map(value_from).collect(),
310 };
311 Ok(out)
312 }
313
314 fn api_info_from(a: b::ApiInfo) -> ir::ApiInfo {
319 ir::ApiInfo {
320 title: a.title,
321 version: a.version,
322 summary: a.summary,
323 description: a.description,
324 terms_of_service: a.terms_of_service,
325 contact: a.contact.map(contact_from),
326 license_name: a.license_name,
327 license_url: a.license_url,
328 license_identifier: a.license_identifier,
329 extensions: extensions_from(a.extensions),
330 }
331 }
332
333 fn api_info_to(a: ir::ApiInfo) -> b::ApiInfo {
334 b::ApiInfo {
335 title: a.title,
336 version: a.version,
337 summary: a.summary,
338 description: a.description,
339 terms_of_service: a.terms_of_service,
340 contact: a.contact.map(contact_to),
341 license_name: a.license_name,
342 license_url: a.license_url,
343 license_identifier: a.license_identifier,
344 extensions: extensions_to(a.extensions),
345 }
346 }
347
348 fn contact_from(c: b::Contact) -> ir::Contact {
349 ir::Contact {
350 name: c.name,
351 url: c.url,
352 email: c.email,
353 }
354 }
355
356 fn contact_to(c: ir::Contact) -> b::Contact {
357 b::Contact {
358 name: c.name,
359 url: c.url,
360 email: c.email,
361 }
362 }
363
364 fn server_from(s: b::Server) -> ir::Server {
365 ir::Server {
366 url: s.url,
367 description: s.description,
368 name: s.name,
369 variables: s
370 .variables
371 .into_iter()
372 .map(|(k, v)| (k, server_var_from(v)))
373 .collect(),
374 extensions: extensions_from(s.extensions),
375 }
376 }
377
378 fn server_to(s: ir::Server) -> b::Server {
379 b::Server {
380 url: s.url,
381 description: s.description,
382 name: s.name,
383 variables: s
384 .variables
385 .into_iter()
386 .map(|(k, v)| (k, server_var_to(v)))
387 .collect(),
388 extensions: extensions_to(s.extensions),
389 }
390 }
391
392 fn server_var_from(v: b::ServerVariable) -> ir::ServerVariable {
393 ir::ServerVariable {
394 default: v.default,
395 r#enum: v.enum_,
396 description: v.description,
397 extensions: extensions_from(v.extensions),
398 }
399 }
400
401 fn server_var_to(v: ir::ServerVariable) -> b::ServerVariable {
402 b::ServerVariable {
403 default: v.default,
404 enum_: v.r#enum,
405 description: v.description,
406 extensions: extensions_to(v.extensions),
407 }
408 }
409
410 fn named_type_from(n: b::NamedType) -> Result<ir::NamedType, BindgenError> {
415 Ok(ir::NamedType {
416 id: n.id,
417 original_name: n.original_name,
418 title: n.title,
419 description: n.description,
420 deprecated: n.deprecated,
421 read_only: n.read_only,
422 write_only: n.write_only,
423 external_docs: n.external_docs.map(external_docs_from),
424 default: n.default,
425 examples: examples_from(n.examples),
426 xml: n.xml.map(xml_object_from),
427 definition: type_def_from(n.definition)?,
428 extensions: extensions_from(n.extensions),
429 location: n.location.map(loc_from),
430 })
431 }
432
433 fn named_type_to(n: ir::NamedType) -> b::NamedType {
434 b::NamedType {
435 id: n.id,
436 original_name: n.original_name,
437 title: n.title,
438 description: n.description,
439 deprecated: n.deprecated,
440 read_only: n.read_only,
441 write_only: n.write_only,
442 external_docs: n.external_docs.map(external_docs_to),
443 default: n.default,
444 examples: examples_to(n.examples),
445 xml: n.xml.map(xml_object_to),
446 definition: type_def_to(n.definition),
447 extensions: extensions_to(n.extensions),
448 location: n.location.map(loc_to),
449 }
450 }
451
452 fn external_docs_from(d: b::ExternalDocs) -> ir::ExternalDocs {
453 ir::ExternalDocs {
454 description: d.description,
455 url: d.url,
456 }
457 }
458
459 fn external_docs_to(d: ir::ExternalDocs) -> b::ExternalDocs {
460 b::ExternalDocs {
461 description: d.description,
462 url: d.url,
463 }
464 }
465
466 fn example_from(e: b::Example) -> ir::Example {
467 ir::Example {
468 summary: e.summary,
469 description: e.description,
470 value: e.value,
471 external_value: e.external_value,
472 data_value: e.data_value,
473 serialized_value: e.serialized_value,
474 }
475 }
476
477 fn example_to(e: ir::Example) -> b::Example {
478 b::Example {
479 summary: e.summary,
480 description: e.description,
481 value: e.value,
482 external_value: e.external_value,
483 data_value: e.data_value,
484 serialized_value: e.serialized_value,
485 }
486 }
487
488 fn examples_from(xs: Vec<(String, b::Example)>) -> Vec<(String, ir::Example)> {
489 xs.into_iter().map(|(k, v)| (k, example_from(v))).collect()
490 }
491
492 fn examples_to(xs: Vec<(String, ir::Example)>) -> Vec<(String, b::Example)> {
493 xs.into_iter().map(|(k, v)| (k, example_to(v))).collect()
494 }
495
496 fn xml_object_from(x: b::XmlObject) -> ir::XmlObject {
497 ir::XmlObject {
498 name: x.name,
499 namespace: x.namespace,
500 prefix: x.prefix,
501 attribute: x.attribute,
502 wrapped: x.wrapped,
503 text: x.text,
504 ordered: x.ordered,
505 extensions: x.extensions,
506 }
507 }
508
509 fn xml_object_to(x: ir::XmlObject) -> b::XmlObject {
510 b::XmlObject {
511 name: x.name,
512 namespace: x.namespace,
513 prefix: x.prefix,
514 attribute: x.attribute,
515 wrapped: x.wrapped,
516 text: x.text,
517 ordered: x.ordered,
518 extensions: x.extensions,
519 }
520 }
521
522 fn link_from(l: b::Link) -> ir::Link {
523 ir::Link {
524 operation_ref: l.operation_ref,
525 operation_id: l.operation_id,
526 parameters: l.parameters,
527 request_body: l.request_body,
528 description: l.description,
529 server: l.server.map(server_from),
530 extensions: l.extensions,
531 }
532 }
533
534 fn link_to(l: ir::Link) -> b::Link {
535 b::Link {
536 operation_ref: l.operation_ref,
537 operation_id: l.operation_id,
538 parameters: l.parameters,
539 request_body: l.request_body,
540 description: l.description,
541 server: l.server.map(server_to),
542 extensions: l.extensions,
543 }
544 }
545
546 fn links_from(xs: Vec<(String, b::Link)>) -> Vec<(String, ir::Link)> {
547 xs.into_iter().map(|(k, v)| (k, link_from(v))).collect()
548 }
549
550 fn links_to(xs: Vec<(String, ir::Link)>) -> Vec<(String, b::Link)> {
551 xs.into_iter().map(|(k, v)| (k, link_to(v))).collect()
552 }
553
554 fn webhook_from(w: b::Webhook) -> Result<ir::Webhook, BindgenError> {
555 Ok(ir::Webhook {
556 name: w.name,
557 summary: w.summary,
558 description: w.description,
559 operations: w
560 .operations
561 .into_iter()
562 .map(operation_from)
563 .collect::<Result<_, _>>()?,
564 })
565 }
566
567 fn webhook_to(w: ir::Webhook) -> b::Webhook {
568 b::Webhook {
569 name: w.name,
570 summary: w.summary,
571 description: w.description,
572 operations: w.operations.into_iter().map(operation_to).collect(),
573 }
574 }
575
576 fn callback_from(c: b::Callback) -> ir::Callback {
577 ir::Callback {
578 name: c.name,
579 expression: c.expression,
580 operation_ids: c.operation_ids,
581 extensions: c.extensions,
582 }
583 }
584
585 fn callback_to(c: ir::Callback) -> b::Callback {
586 b::Callback {
587 name: c.name,
588 expression: c.expression,
589 operation_ids: c.operation_ids,
590 extensions: c.extensions,
591 }
592 }
593
594 fn tag_from(t: b::Tag) -> ir::Tag {
595 ir::Tag {
596 name: t.name,
597 summary: t.summary,
598 description: t.description,
599 external_docs: t.external_docs.map(external_docs_from),
600 parent: t.parent,
601 kind: t.kind,
602 extensions: t.extensions,
603 }
604 }
605
606 fn tag_to(t: ir::Tag) -> b::Tag {
607 b::Tag {
608 name: t.name,
609 summary: t.summary,
610 description: t.description,
611 external_docs: t.external_docs.map(external_docs_to),
612 parent: t.parent,
613 kind: t.kind,
614 extensions: t.extensions,
615 }
616 }
617
618 fn type_def_from(d: b::TypeDef) -> Result<ir::TypeDef, BindgenError> {
619 Ok(match d {
620 b::TypeDef::Primitive(p) => ir::TypeDef::Primitive(prim_from(p)),
621 b::TypeDef::Object(o) => ir::TypeDef::Object(object_from(o)),
622 b::TypeDef::Array(a) => ir::TypeDef::Array(array_from(a)),
623 b::TypeDef::EnumString(e) => ir::TypeDef::EnumString(enum_str_from(e)),
624 b::TypeDef::EnumInt(e) => ir::TypeDef::EnumInt(enum_int_from(e)),
625 b::TypeDef::Union(u) => ir::TypeDef::Union(union_from(u)),
626 b::TypeDef::Null => ir::TypeDef::Null,
627 b::TypeDef::Any => ir::TypeDef::Any,
628 })
629 }
630
631 fn type_def_to(d: ir::TypeDef) -> b::TypeDef {
632 match d {
633 ir::TypeDef::Primitive(p) => b::TypeDef::Primitive(prim_to(p)),
634 ir::TypeDef::Object(o) => b::TypeDef::Object(object_to(o)),
635 ir::TypeDef::Array(a) => b::TypeDef::Array(array_to(a)),
636 ir::TypeDef::EnumString(e) => b::TypeDef::EnumString(enum_str_to(e)),
637 ir::TypeDef::EnumInt(e) => b::TypeDef::EnumInt(enum_int_to(e)),
638 ir::TypeDef::Union(u) => b::TypeDef::Union(union_to(u)),
639 ir::TypeDef::Null => b::TypeDef::Null,
640 ir::TypeDef::Any => b::TypeDef::Any,
641 }
642 }
643
644 fn prim_kind_from(k: b::PrimitiveKind) -> ir::PrimitiveKind {
647 use b::PrimitiveKind as W;
648 use ir::PrimitiveKind as I;
649 match k {
650 W::PrimString => I::String,
651 W::PrimInteger => I::Integer,
652 W::PrimNumber => I::Number,
653 W::PrimBool => I::Bool,
654 }
655 }
656
657 fn prim_kind_to(k: ir::PrimitiveKind) -> b::PrimitiveKind {
658 use b::PrimitiveKind as W;
659 use ir::PrimitiveKind as I;
660 match k {
661 I::String => W::PrimString,
662 I::Integer => W::PrimInteger,
663 I::Number => W::PrimNumber,
664 I::Bool => W::PrimBool,
665 }
666 }
667
668 fn prim_constraints_from(c: b::PrimitiveConstraints) -> ir::PrimitiveConstraints {
669 ir::PrimitiveConstraints {
670 minimum: c.minimum,
671 maximum: c.maximum,
672 exclusive_minimum: c.exclusive_minimum,
673 exclusive_maximum: c.exclusive_maximum,
674 multiple_of: c.multiple_of,
675 min_length: c.min_length,
676 max_length: c.max_length,
677 pattern: c.pattern,
678 format_extension: c.format_extension,
679 content_encoding: c.content_encoding,
680 content_media_type: c.content_media_type,
681 content_schema: c.content_schema,
682 }
683 }
684
685 fn prim_constraints_to(c: ir::PrimitiveConstraints) -> b::PrimitiveConstraints {
686 b::PrimitiveConstraints {
687 minimum: c.minimum,
688 maximum: c.maximum,
689 exclusive_minimum: c.exclusive_minimum,
690 exclusive_maximum: c.exclusive_maximum,
691 multiple_of: c.multiple_of,
692 min_length: c.min_length,
693 max_length: c.max_length,
694 pattern: c.pattern,
695 format_extension: c.format_extension,
696 content_encoding: c.content_encoding,
697 content_media_type: c.content_media_type,
698 content_schema: c.content_schema,
699 }
700 }
701
702 fn prim_from(p: b::PrimitiveType) -> ir::PrimitiveType {
703 ir::PrimitiveType {
704 kind: prim_kind_from(p.kind),
705 constraints: prim_constraints_from(p.constraints),
706 }
707 }
708
709 fn prim_to(p: ir::PrimitiveType) -> b::PrimitiveType {
710 b::PrimitiveType {
711 kind: prim_kind_to(p.kind),
712 constraints: prim_constraints_to(p.constraints),
713 }
714 }
715
716 fn array_from(a: b::ArrayType) -> ir::ArrayType {
719 ir::ArrayType {
720 items: a.items,
721 constraints: ir::ArrayConstraints {
722 min_items: a.constraints.min_items,
723 max_items: a.constraints.max_items,
724 unique_items: a.constraints.unique_items,
725 },
726 }
727 }
728
729 fn array_to(a: ir::ArrayType) -> b::ArrayType {
730 b::ArrayType {
731 items: a.items,
732 constraints: b::ArrayConstraints {
733 min_items: a.constraints.min_items,
734 max_items: a.constraints.max_items,
735 unique_items: a.constraints.unique_items,
736 },
737 }
738 }
739
740 fn object_from(o: b::ObjectType) -> ir::ObjectType {
743 ir::ObjectType {
744 properties: o
745 .properties
746 .into_iter()
747 .map(|p| ir::Property {
748 name: p.name,
749 r#type: p.type_,
750 required: p.required,
751 title: p.title,
752 description: p.description,
753 deprecated: p.deprecated,
754 read_only: p.read_only,
755 write_only: p.write_only,
756 external_docs: p.external_docs.map(external_docs_from),
757 default: p.default,
758 examples: examples_from(p.examples),
759 extensions: p.extensions,
760 })
761 .collect(),
762 pattern_properties: o
763 .pattern_properties
764 .into_iter()
765 .map(|p| ir::PatternProperty {
766 pattern: p.pattern,
767 r#type: p.type_,
768 })
769 .collect(),
770 additional_properties: match o.additional_properties {
771 b::AdditionalProperties::Forbidden => ir::AdditionalProperties::Forbidden,
772 b::AdditionalProperties::Any => ir::AdditionalProperties::Any,
773 b::AdditionalProperties::Typed(t) => {
774 ir::AdditionalProperties::Typed { r#type: t }
775 }
776 },
777 property_names: o.property_names,
778 constraints: ir::ObjectConstraints {
779 min_properties: o.constraints.min_properties,
780 max_properties: o.constraints.max_properties,
781 },
782 }
783 }
784
785 fn object_to(o: ir::ObjectType) -> b::ObjectType {
786 b::ObjectType {
787 properties: o
788 .properties
789 .into_iter()
790 .map(|p| b::Property {
791 name: p.name,
792 type_: p.r#type,
793 required: p.required,
794 title: p.title,
795 description: p.description,
796 deprecated: p.deprecated,
797 read_only: p.read_only,
798 write_only: p.write_only,
799 external_docs: p.external_docs.map(external_docs_to),
800 default: p.default,
801 examples: examples_to(p.examples),
802 extensions: p.extensions,
803 })
804 .collect(),
805 pattern_properties: o
806 .pattern_properties
807 .into_iter()
808 .map(|p| b::PatternProperty {
809 pattern: p.pattern,
810 type_: p.r#type,
811 })
812 .collect(),
813 additional_properties: match o.additional_properties {
814 ir::AdditionalProperties::Forbidden => b::AdditionalProperties::Forbidden,
815 ir::AdditionalProperties::Any => b::AdditionalProperties::Any,
816 ir::AdditionalProperties::Typed { r#type } => {
817 b::AdditionalProperties::Typed(r#type)
818 }
819 },
820 property_names: o.property_names,
821 constraints: b::ObjectConstraints {
822 min_properties: o.constraints.min_properties,
823 max_properties: o.constraints.max_properties,
824 },
825 }
826 }
827
828 fn enum_str_from(e: b::EnumStringType) -> ir::EnumStringType {
833 ir::EnumStringType {
834 values: e
835 .values
836 .into_iter()
837 .map(|v| ir::EnumStringValue { value: v.value })
838 .collect(),
839 }
840 }
841
842 fn enum_str_to(e: ir::EnumStringType) -> b::EnumStringType {
843 b::EnumStringType {
844 values: e
845 .values
846 .into_iter()
847 .map(|v| b::EnumStringValue { value: v.value })
848 .collect(),
849 }
850 }
851
852 fn enum_int_from(e: b::EnumIntType) -> ir::EnumIntType {
853 ir::EnumIntType {
854 values: e
855 .values
856 .into_iter()
857 .map(|v| ir::EnumIntValue { value: v.value })
858 .collect(),
859 kind: match e.kind {
860 b::IntKind::Int32 => ir::IntKind::Int32,
861 b::IntKind::Int64 => ir::IntKind::Int64,
862 },
863 }
864 }
865
866 fn enum_int_to(e: ir::EnumIntType) -> b::EnumIntType {
867 b::EnumIntType {
868 values: e
869 .values
870 .into_iter()
871 .map(|v| b::EnumIntValue { value: v.value })
872 .collect(),
873 kind: match e.kind {
874 ir::IntKind::Int32 => b::IntKind::Int32,
875 ir::IntKind::Int64 => b::IntKind::Int64,
876 },
877 }
878 }
879
880 fn union_from(u: b::UnionType) -> ir::UnionType {
883 ir::UnionType {
884 variants: u
885 .variants
886 .into_iter()
887 .map(|v| ir::UnionVariant {
888 r#type: v.type_,
889 tag: v.tag,
890 })
891 .collect(),
892 discriminator: u.discriminator.map(|d| ir::Discriminator {
893 property_name: d.property_name,
894 mapping: d.mapping.into_iter().collect(),
895 extensions: d.extensions,
896 }),
897 kind: match u.kind {
898 b::UnionKind::OneOf => ir::UnionKind::OneOf,
899 b::UnionKind::AnyOf => ir::UnionKind::AnyOf,
900 },
901 }
902 }
903
904 fn union_to(u: ir::UnionType) -> b::UnionType {
905 b::UnionType {
906 variants: u
907 .variants
908 .into_iter()
909 .map(|v| b::UnionVariant {
910 type_: v.r#type,
911 tag: v.tag,
912 })
913 .collect(),
914 discriminator: u.discriminator.map(|d| b::Discriminator {
915 property_name: d.property_name,
916 mapping: d.mapping,
917 extensions: d.extensions,
918 }),
919 kind: match u.kind {
920 ir::UnionKind::OneOf => b::UnionKind::OneOf,
921 ir::UnionKind::AnyOf => b::UnionKind::AnyOf,
922 },
923 }
924 }
925
926 fn http_method_from(m: b::HttpMethod) -> ir::HttpMethod {
931 use b::HttpMethod as W;
932 use ir::HttpMethod as I;
933 match m {
934 W::Get => I::Get,
935 W::Put => I::Put,
936 W::Post => I::Post,
937 W::Delete => I::Delete,
938 W::Options => I::Options,
939 W::Head => I::Head,
940 W::Patch => I::Patch,
941 W::Trace => I::Trace,
942 W::Other(s) => I::Other(s),
943 }
944 }
945
946 fn http_method_to(m: ir::HttpMethod) -> b::HttpMethod {
947 use b::HttpMethod as W;
948 use ir::HttpMethod as I;
949 match m {
950 I::Get => W::Get,
951 I::Put => W::Put,
952 I::Post => W::Post,
953 I::Delete => W::Delete,
954 I::Options => W::Options,
955 I::Head => W::Head,
956 I::Patch => W::Patch,
957 I::Trace => W::Trace,
958 I::Other(s) => W::Other(s),
959 }
960 }
961
962 fn param_style_from(s: b::ParameterStyle) -> ir::ParameterStyle {
963 use b::ParameterStyle as W;
964 use ir::ParameterStyle as I;
965 match s {
966 W::ParamForm => I::Form,
967 W::ParamSimple => I::Simple,
968 W::ParamLabel => I::Label,
969 W::ParamMatrix => I::Matrix,
970 W::ParamSpaceDelimited => I::SpaceDelimited,
971 W::ParamPipeDelimited => I::PipeDelimited,
972 W::ParamDeepObject => I::DeepObject,
973 }
974 }
975
976 fn param_style_to(s: ir::ParameterStyle) -> b::ParameterStyle {
977 use b::ParameterStyle as W;
978 use ir::ParameterStyle as I;
979 match s {
980 I::Form => W::ParamForm,
981 I::Simple => W::ParamSimple,
982 I::Label => W::ParamLabel,
983 I::Matrix => W::ParamMatrix,
984 I::SpaceDelimited => W::ParamSpaceDelimited,
985 I::PipeDelimited => W::ParamPipeDelimited,
986 I::DeepObject => W::ParamDeepObject,
987 }
988 }
989
990 fn header_from(h: b::Header) -> ir::Header {
991 ir::Header {
992 r#type: h.type_,
993 required: h.required,
994 description: h.description,
995 deprecated: h.deprecated,
996 examples: examples_from(h.examples),
997 style: h.style.map(param_style_from),
998 explode: h.explode,
999 allow_reserved: h.allow_reserved,
1000 allow_empty_value: h.allow_empty_value,
1001 location: h.location.map(loc_from),
1002 }
1003 }
1004
1005 fn header_to(h: ir::Header) -> b::Header {
1006 b::Header {
1007 type_: h.r#type,
1008 required: h.required,
1009 description: h.description,
1010 deprecated: h.deprecated,
1011 examples: examples_to(h.examples),
1012 style: h.style.map(param_style_to),
1013 explode: h.explode,
1014 allow_reserved: h.allow_reserved,
1015 allow_empty_value: h.allow_empty_value,
1016 location: h.location.map(loc_to),
1017 }
1018 }
1019
1020 fn parameter_from(p: b::Parameter) -> ir::Parameter {
1021 ir::Parameter {
1022 name: p.name,
1023 r#type: p.type_,
1024 required: p.required,
1025 description: p.description,
1026 deprecated: p.deprecated,
1027 examples: examples_from(p.examples),
1028 style: p.style.map(param_style_from),
1029 explode: p.explode,
1030 allow_empty_value: p.allow_empty_value,
1031 allow_reserved: p.allow_reserved,
1032 extensions: extensions_from(p.extensions),
1033 location: p.location.map(loc_from),
1034 }
1035 }
1036
1037 fn parameter_to(p: ir::Parameter) -> b::Parameter {
1038 b::Parameter {
1039 name: p.name,
1040 type_: p.r#type,
1041 required: p.required,
1042 description: p.description,
1043 deprecated: p.deprecated,
1044 examples: examples_to(p.examples),
1045 style: p.style.map(param_style_to),
1046 explode: p.explode,
1047 allow_empty_value: p.allow_empty_value,
1048 allow_reserved: p.allow_reserved,
1049 extensions: extensions_to(p.extensions),
1050 location: p.location.map(loc_to),
1051 }
1052 }
1053
1054 fn body_from(b_: b::Body) -> ir::Body {
1055 ir::Body {
1056 content: b_.content.into_iter().map(body_content_from).collect(),
1057 required: b_.required,
1058 description: b_.description,
1059 extensions: extensions_from(b_.extensions),
1060 }
1061 }
1062
1063 fn body_to(b_: ir::Body) -> b::Body {
1064 b::Body {
1065 content: b_.content.into_iter().map(body_content_to).collect(),
1066 required: b_.required,
1067 description: b_.description,
1068 extensions: extensions_to(b_.extensions),
1069 }
1070 }
1071
1072 fn body_content_from(c: b::BodyContent) -> ir::BodyContent {
1073 ir::BodyContent {
1074 media_type: c.media_type,
1075 r#type: c.type_,
1076 encoding: c
1077 .encoding
1078 .into_iter()
1079 .map(|(k, v)| (k, encoding_from(v)))
1080 .collect(),
1081 item_schema: c.item_schema,
1082 examples: examples_from(c.examples),
1083 extensions: extensions_from(c.extensions),
1084 }
1085 }
1086
1087 fn body_content_to(c: ir::BodyContent) -> b::BodyContent {
1088 b::BodyContent {
1089 media_type: c.media_type,
1090 type_: c.r#type,
1091 encoding: c
1092 .encoding
1093 .into_iter()
1094 .map(|(k, v)| (k, encoding_to(v)))
1095 .collect(),
1096 item_schema: c.item_schema,
1097 examples: examples_to(c.examples),
1098 extensions: extensions_to(c.extensions),
1099 }
1100 }
1101
1102 fn encoding_from(e: b::Encoding) -> ir::Encoding {
1103 ir::Encoding {
1104 content_type: e.content_type,
1105 style: e.style.map(param_style_from),
1106 explode: e.explode,
1107 allow_reserved: e.allow_reserved,
1108 headers: e
1109 .headers
1110 .into_iter()
1111 .map(|(k, v)| (k, header_from(v)))
1112 .collect(),
1113 extensions: extensions_from(e.extensions),
1114 }
1115 }
1116
1117 fn encoding_to(e: ir::Encoding) -> b::Encoding {
1118 b::Encoding {
1119 content_type: e.content_type,
1120 style: e.style.map(param_style_to),
1121 explode: e.explode,
1122 allow_reserved: e.allow_reserved,
1123 headers: e
1124 .headers
1125 .into_iter()
1126 .map(|(k, v)| (k, header_to(v)))
1127 .collect(),
1128 extensions: extensions_to(e.extensions),
1129 }
1130 }
1131
1132 fn response_from(r: b::Response) -> ir::Response {
1133 ir::Response {
1134 status: match r.status {
1135 b::ResponseStatus::Explicit(code) => ir::ResponseStatus::Explicit { code },
1136 b::ResponseStatus::Default => ir::ResponseStatus::Default,
1137 b::ResponseStatus::Range(class) => ir::ResponseStatus::Range { class },
1138 },
1139 content: r.content.into_iter().map(body_content_from).collect(),
1140 headers: r
1141 .headers
1142 .into_iter()
1143 .map(|(k, v)| (k, header_from(v)))
1144 .collect(),
1145 summary: r.summary,
1146 description: r.description,
1147 links: links_from(r.links),
1148 extensions: extensions_from(r.extensions),
1149 }
1150 }
1151
1152 fn response_to(r: ir::Response) -> b::Response {
1153 b::Response {
1154 status: match r.status {
1155 ir::ResponseStatus::Explicit { code } => b::ResponseStatus::Explicit(code),
1156 ir::ResponseStatus::Default => b::ResponseStatus::Default,
1157 ir::ResponseStatus::Range { class } => b::ResponseStatus::Range(class),
1158 },
1159 content: r.content.into_iter().map(body_content_to).collect(),
1160 headers: r
1161 .headers
1162 .into_iter()
1163 .map(|(k, v)| (k, header_to(v)))
1164 .collect(),
1165 summary: r.summary,
1166 description: r.description,
1167 links: links_to(r.links),
1168 extensions: extensions_to(r.extensions),
1169 }
1170 }
1171
1172 fn operation_from(op: b::Operation) -> Result<ir::Operation, BindgenError> {
1173 Ok(ir::Operation {
1174 id: op.id,
1175 original_id: op.original_id,
1176 method: http_method_from(op.method),
1177 path_template: op.path_template,
1178 path_params: op.path_params.into_iter().map(parameter_from).collect(),
1179 query_params: op.query_params.into_iter().map(parameter_from).collect(),
1180 header_params: op.header_params.into_iter().map(parameter_from).collect(),
1181 cookie_params: op.cookie_params.into_iter().map(parameter_from).collect(),
1182 querystring_params: op
1183 .querystring_params
1184 .into_iter()
1185 .map(parameter_from)
1186 .collect(),
1187 request_body: op.request_body.map(body_from),
1188 responses: op.responses.into_iter().map(response_from).collect(),
1189 security: op
1190 .security
1191 .into_iter()
1192 .map(|s| ir::SecurityRequirement {
1193 scheme_id: s.scheme_id,
1194 scopes: s.scopes,
1195 })
1196 .collect(),
1197 tags: op.tags,
1198 summary: op.summary,
1199 description: op.description,
1200 deprecated: op.deprecated,
1201 external_docs: op.external_docs.map(external_docs_from),
1202 extensions: op.extensions,
1203 servers: op.servers.into_iter().map(server_from).collect(),
1204 callbacks: op.callbacks.into_iter().map(callback_from).collect(),
1205 location: op.location.map(loc_from),
1206 })
1207 }
1208
1209 fn operation_to(op: ir::Operation) -> b::Operation {
1210 b::Operation {
1211 id: op.id,
1212 original_id: op.original_id,
1213 method: http_method_to(op.method),
1214 path_template: op.path_template,
1215 path_params: op.path_params.into_iter().map(parameter_to).collect(),
1216 query_params: op.query_params.into_iter().map(parameter_to).collect(),
1217 header_params: op.header_params.into_iter().map(parameter_to).collect(),
1218 cookie_params: op.cookie_params.into_iter().map(parameter_to).collect(),
1219 querystring_params: op
1220 .querystring_params
1221 .into_iter()
1222 .map(parameter_to)
1223 .collect(),
1224 request_body: op.request_body.map(body_to),
1225 responses: op.responses.into_iter().map(response_to).collect(),
1226 security: op
1227 .security
1228 .into_iter()
1229 .map(|s| b::SecurityRequirement {
1230 scheme_id: s.scheme_id,
1231 scopes: s.scopes,
1232 })
1233 .collect(),
1234 tags: op.tags,
1235 summary: op.summary,
1236 description: op.description,
1237 deprecated: op.deprecated,
1238 external_docs: op.external_docs.map(external_docs_to),
1239 extensions: op.extensions,
1240 servers: op.servers.into_iter().map(server_to).collect(),
1241 callbacks: op.callbacks.into_iter().map(callback_to).collect(),
1242 location: op.location.map(loc_to),
1243 }
1244 }
1245
1246 fn security_scheme_from(s: b::SecurityScheme) -> ir::SecurityScheme {
1251 ir::SecurityScheme {
1252 id: s.id,
1253 kind: match s.kind {
1254 b::SecuritySchemeKind::ApiKey(k) => {
1255 ir::SecuritySchemeKind::ApiKey(ir::ApiKeyScheme {
1256 name: k.name,
1257 location: match k.location {
1258 b::ApiKeyLocation::Header => ir::ApiKeyLocation::Header,
1259 b::ApiKeyLocation::Query => ir::ApiKeyLocation::Query,
1260 b::ApiKeyLocation::Cookie => ir::ApiKeyLocation::Cookie,
1261 },
1262 })
1263 }
1264 b::SecuritySchemeKind::HttpBasic => ir::SecuritySchemeKind::HttpBasic,
1265 b::SecuritySchemeKind::HttpBearer(f) => {
1266 ir::SecuritySchemeKind::HttpBearer { bearer_format: f }
1267 }
1268 b::SecuritySchemeKind::MutualTls => ir::SecuritySchemeKind::MutualTls,
1269 b::SecuritySchemeKind::Oauth2(o) => {
1270 ir::SecuritySchemeKind::Oauth2(ir::OAuth2Scheme {
1271 flows: o.flows.into_iter().map(oauth2_flow_from).collect(),
1272 })
1273 }
1274 b::SecuritySchemeKind::OpenIdConnect(u) => {
1275 ir::SecuritySchemeKind::OpenIdConnect { url: u }
1276 }
1277 },
1278 description: s.description,
1279 deprecated: s.deprecated,
1280 extensions: extensions_from(s.extensions),
1281 }
1282 }
1283
1284 fn security_scheme_to(s: ir::SecurityScheme) -> b::SecurityScheme {
1285 b::SecurityScheme {
1286 id: s.id,
1287 kind: match s.kind {
1288 ir::SecuritySchemeKind::ApiKey(k) => {
1289 b::SecuritySchemeKind::ApiKey(b::ApiKeyScheme {
1290 name: k.name,
1291 location: match k.location {
1292 ir::ApiKeyLocation::Header => b::ApiKeyLocation::Header,
1293 ir::ApiKeyLocation::Query => b::ApiKeyLocation::Query,
1294 ir::ApiKeyLocation::Cookie => b::ApiKeyLocation::Cookie,
1295 },
1296 })
1297 }
1298 ir::SecuritySchemeKind::HttpBasic => b::SecuritySchemeKind::HttpBasic,
1299 ir::SecuritySchemeKind::HttpBearer { bearer_format } => {
1300 b::SecuritySchemeKind::HttpBearer(bearer_format)
1301 }
1302 ir::SecuritySchemeKind::MutualTls => b::SecuritySchemeKind::MutualTls,
1303 ir::SecuritySchemeKind::Oauth2(o) => {
1304 b::SecuritySchemeKind::Oauth2(b::Oauth2Scheme {
1305 flows: o.flows.into_iter().map(oauth2_flow_to).collect(),
1306 })
1307 }
1308 ir::SecuritySchemeKind::OpenIdConnect { url } => {
1309 b::SecuritySchemeKind::OpenIdConnect(url)
1310 }
1311 },
1312 description: s.description,
1313 deprecated: s.deprecated,
1314 extensions: extensions_to(s.extensions),
1315 }
1316 }
1317
1318 fn oauth2_flow_from(f: b::Oauth2Flow) -> ir::OAuth2Flow {
1319 ir::OAuth2Flow {
1320 kind: match f.kind {
1321 b::Oauth2FlowKind::Implicit => ir::OAuth2FlowKind::Implicit,
1322 b::Oauth2FlowKind::Password => ir::OAuth2FlowKind::Password,
1323 b::Oauth2FlowKind::ClientCredentials => {
1324 ir::OAuth2FlowKind::ClientCredentials
1325 }
1326 b::Oauth2FlowKind::AuthorizationCode => {
1327 ir::OAuth2FlowKind::AuthorizationCode
1328 }
1329 },
1330 authorization_url: f.authorization_url,
1331 token_url: f.token_url,
1332 refresh_url: f.refresh_url,
1333 scopes: f.scopes,
1334 extensions: extensions_from(f.extensions),
1335 }
1336 }
1337
1338 fn oauth2_flow_to(f: ir::OAuth2Flow) -> b::Oauth2Flow {
1339 b::Oauth2Flow {
1340 kind: match f.kind {
1341 ir::OAuth2FlowKind::Implicit => b::Oauth2FlowKind::Implicit,
1342 ir::OAuth2FlowKind::Password => b::Oauth2FlowKind::Password,
1343 ir::OAuth2FlowKind::ClientCredentials => {
1344 b::Oauth2FlowKind::ClientCredentials
1345 }
1346 ir::OAuth2FlowKind::AuthorizationCode => {
1347 b::Oauth2FlowKind::AuthorizationCode
1348 }
1349 },
1350 authorization_url: f.authorization_url,
1351 token_url: f.token_url,
1352 refresh_url: f.refresh_url,
1353 scopes: f.scopes,
1354 extensions: extensions_to(f.extensions),
1355 }
1356 }
1357 }
1358 };
1359}
1360
1361define_world_conversions!(transformer, transformer);
1362define_world_conversions!(generator, generator);
1363
1364#[cfg(test)]
1365mod tests {
1366 use super::*;
1367 use forge_ir::proptest_util::small_ir;
1368 use proptest::prelude::*;
1369
1370 proptest! {
1371 #[test]
1373 fn roundtrip_transformer(ir in small_ir()) {
1374 let wit = transformer::ir_to_wit(ir.clone());
1375 let back = transformer::ir_from_wit(wit).unwrap();
1376 prop_assert_eq!(ir, back);
1377 }
1378
1379 #[test]
1381 fn roundtrip_generator(ir in small_ir()) {
1382 let wit = generator::ir_to_wit(ir.clone());
1383 let back = generator::ir_from_wit(wit).unwrap();
1384 prop_assert_eq!(ir, back);
1385 }
1386 }
1387}