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 })
628 }
629
630 fn type_def_to(d: ir::TypeDef) -> b::TypeDef {
631 match d {
632 ir::TypeDef::Primitive(p) => b::TypeDef::Primitive(prim_to(p)),
633 ir::TypeDef::Object(o) => b::TypeDef::Object(object_to(o)),
634 ir::TypeDef::Array(a) => b::TypeDef::Array(array_to(a)),
635 ir::TypeDef::EnumString(e) => b::TypeDef::EnumString(enum_str_to(e)),
636 ir::TypeDef::EnumInt(e) => b::TypeDef::EnumInt(enum_int_to(e)),
637 ir::TypeDef::Union(u) => b::TypeDef::Union(union_to(u)),
638 ir::TypeDef::Null => b::TypeDef::Null,
639 }
640 }
641
642 fn prim_kind_from(k: b::PrimitiveKind) -> ir::PrimitiveKind {
645 use b::PrimitiveKind as W;
646 use ir::PrimitiveKind as I;
647 match k {
648 W::PrimString => I::String,
649 W::PrimInteger => I::Integer,
650 W::PrimNumber => I::Number,
651 W::PrimBool => I::Bool,
652 }
653 }
654
655 fn prim_kind_to(k: ir::PrimitiveKind) -> b::PrimitiveKind {
656 use b::PrimitiveKind as W;
657 use ir::PrimitiveKind as I;
658 match k {
659 I::String => W::PrimString,
660 I::Integer => W::PrimInteger,
661 I::Number => W::PrimNumber,
662 I::Bool => W::PrimBool,
663 }
664 }
665
666 fn prim_constraints_from(c: b::PrimitiveConstraints) -> ir::PrimitiveConstraints {
667 ir::PrimitiveConstraints {
668 minimum: c.minimum,
669 maximum: c.maximum,
670 exclusive_minimum: c.exclusive_minimum,
671 exclusive_maximum: c.exclusive_maximum,
672 multiple_of: c.multiple_of,
673 min_length: c.min_length,
674 max_length: c.max_length,
675 pattern: c.pattern,
676 format_extension: c.format_extension,
677 content_encoding: c.content_encoding,
678 content_media_type: c.content_media_type,
679 content_schema: c.content_schema,
680 }
681 }
682
683 fn prim_constraints_to(c: ir::PrimitiveConstraints) -> b::PrimitiveConstraints {
684 b::PrimitiveConstraints {
685 minimum: c.minimum,
686 maximum: c.maximum,
687 exclusive_minimum: c.exclusive_minimum,
688 exclusive_maximum: c.exclusive_maximum,
689 multiple_of: c.multiple_of,
690 min_length: c.min_length,
691 max_length: c.max_length,
692 pattern: c.pattern,
693 format_extension: c.format_extension,
694 content_encoding: c.content_encoding,
695 content_media_type: c.content_media_type,
696 content_schema: c.content_schema,
697 }
698 }
699
700 fn prim_from(p: b::PrimitiveType) -> ir::PrimitiveType {
701 ir::PrimitiveType {
702 kind: prim_kind_from(p.kind),
703 constraints: prim_constraints_from(p.constraints),
704 }
705 }
706
707 fn prim_to(p: ir::PrimitiveType) -> b::PrimitiveType {
708 b::PrimitiveType {
709 kind: prim_kind_to(p.kind),
710 constraints: prim_constraints_to(p.constraints),
711 }
712 }
713
714 fn array_from(a: b::ArrayType) -> ir::ArrayType {
717 ir::ArrayType {
718 items: a.items,
719 constraints: ir::ArrayConstraints {
720 min_items: a.constraints.min_items,
721 max_items: a.constraints.max_items,
722 unique_items: a.constraints.unique_items,
723 },
724 }
725 }
726
727 fn array_to(a: ir::ArrayType) -> b::ArrayType {
728 b::ArrayType {
729 items: a.items,
730 constraints: b::ArrayConstraints {
731 min_items: a.constraints.min_items,
732 max_items: a.constraints.max_items,
733 unique_items: a.constraints.unique_items,
734 },
735 }
736 }
737
738 fn object_from(o: b::ObjectType) -> ir::ObjectType {
741 ir::ObjectType {
742 properties: o
743 .properties
744 .into_iter()
745 .map(|p| ir::Property {
746 name: p.name,
747 r#type: p.type_,
748 required: p.required,
749 title: p.title,
750 description: p.description,
751 deprecated: p.deprecated,
752 read_only: p.read_only,
753 write_only: p.write_only,
754 external_docs: p.external_docs.map(external_docs_from),
755 default: p.default,
756 examples: examples_from(p.examples),
757 extensions: p.extensions,
758 })
759 .collect(),
760 additional_properties: match o.additional_properties {
761 b::AdditionalProperties::Forbidden => ir::AdditionalProperties::Forbidden,
762 b::AdditionalProperties::Any => ir::AdditionalProperties::Any,
763 b::AdditionalProperties::Typed(t) => {
764 ir::AdditionalProperties::Typed { r#type: t }
765 }
766 },
767 constraints: ir::ObjectConstraints {
768 min_properties: o.constraints.min_properties,
769 max_properties: o.constraints.max_properties,
770 },
771 }
772 }
773
774 fn object_to(o: ir::ObjectType) -> b::ObjectType {
775 b::ObjectType {
776 properties: o
777 .properties
778 .into_iter()
779 .map(|p| b::Property {
780 name: p.name,
781 type_: p.r#type,
782 required: p.required,
783 title: p.title,
784 description: p.description,
785 deprecated: p.deprecated,
786 read_only: p.read_only,
787 write_only: p.write_only,
788 external_docs: p.external_docs.map(external_docs_to),
789 default: p.default,
790 examples: examples_to(p.examples),
791 extensions: p.extensions,
792 })
793 .collect(),
794 additional_properties: match o.additional_properties {
795 ir::AdditionalProperties::Forbidden => b::AdditionalProperties::Forbidden,
796 ir::AdditionalProperties::Any => b::AdditionalProperties::Any,
797 ir::AdditionalProperties::Typed { r#type } => {
798 b::AdditionalProperties::Typed(r#type)
799 }
800 },
801 constraints: b::ObjectConstraints {
802 min_properties: o.constraints.min_properties,
803 max_properties: o.constraints.max_properties,
804 },
805 }
806 }
807
808 fn enum_str_from(e: b::EnumStringType) -> ir::EnumStringType {
813 ir::EnumStringType {
814 values: e
815 .values
816 .into_iter()
817 .map(|v| ir::EnumStringValue { value: v.value })
818 .collect(),
819 }
820 }
821
822 fn enum_str_to(e: ir::EnumStringType) -> b::EnumStringType {
823 b::EnumStringType {
824 values: e
825 .values
826 .into_iter()
827 .map(|v| b::EnumStringValue { value: v.value })
828 .collect(),
829 }
830 }
831
832 fn enum_int_from(e: b::EnumIntType) -> ir::EnumIntType {
833 ir::EnumIntType {
834 values: e
835 .values
836 .into_iter()
837 .map(|v| ir::EnumIntValue { value: v.value })
838 .collect(),
839 kind: match e.kind {
840 b::IntKind::Int32 => ir::IntKind::Int32,
841 b::IntKind::Int64 => ir::IntKind::Int64,
842 },
843 }
844 }
845
846 fn enum_int_to(e: ir::EnumIntType) -> b::EnumIntType {
847 b::EnumIntType {
848 values: e
849 .values
850 .into_iter()
851 .map(|v| b::EnumIntValue { value: v.value })
852 .collect(),
853 kind: match e.kind {
854 ir::IntKind::Int32 => b::IntKind::Int32,
855 ir::IntKind::Int64 => b::IntKind::Int64,
856 },
857 }
858 }
859
860 fn union_from(u: b::UnionType) -> ir::UnionType {
863 ir::UnionType {
864 variants: u
865 .variants
866 .into_iter()
867 .map(|v| ir::UnionVariant {
868 r#type: v.type_,
869 tag: v.tag,
870 })
871 .collect(),
872 discriminator: u.discriminator.map(|d| ir::Discriminator {
873 property_name: d.property_name,
874 mapping: d.mapping.into_iter().collect(),
875 extensions: d.extensions,
876 }),
877 kind: match u.kind {
878 b::UnionKind::OneOf => ir::UnionKind::OneOf,
879 b::UnionKind::AnyOf => ir::UnionKind::AnyOf,
880 },
881 }
882 }
883
884 fn union_to(u: ir::UnionType) -> b::UnionType {
885 b::UnionType {
886 variants: u
887 .variants
888 .into_iter()
889 .map(|v| b::UnionVariant {
890 type_: v.r#type,
891 tag: v.tag,
892 })
893 .collect(),
894 discriminator: u.discriminator.map(|d| b::Discriminator {
895 property_name: d.property_name,
896 mapping: d.mapping,
897 extensions: d.extensions,
898 }),
899 kind: match u.kind {
900 ir::UnionKind::OneOf => b::UnionKind::OneOf,
901 ir::UnionKind::AnyOf => b::UnionKind::AnyOf,
902 },
903 }
904 }
905
906 fn http_method_from(m: b::HttpMethod) -> ir::HttpMethod {
911 use b::HttpMethod as W;
912 use ir::HttpMethod as I;
913 match m {
914 W::Get => I::Get,
915 W::Put => I::Put,
916 W::Post => I::Post,
917 W::Delete => I::Delete,
918 W::Options => I::Options,
919 W::Head => I::Head,
920 W::Patch => I::Patch,
921 W::Trace => I::Trace,
922 W::Other(s) => I::Other(s),
923 }
924 }
925
926 fn http_method_to(m: ir::HttpMethod) -> b::HttpMethod {
927 use b::HttpMethod as W;
928 use ir::HttpMethod as I;
929 match m {
930 I::Get => W::Get,
931 I::Put => W::Put,
932 I::Post => W::Post,
933 I::Delete => W::Delete,
934 I::Options => W::Options,
935 I::Head => W::Head,
936 I::Patch => W::Patch,
937 I::Trace => W::Trace,
938 I::Other(s) => W::Other(s),
939 }
940 }
941
942 fn param_style_from(s: b::ParameterStyle) -> ir::ParameterStyle {
943 use b::ParameterStyle as W;
944 use ir::ParameterStyle as I;
945 match s {
946 W::ParamForm => I::Form,
947 W::ParamSimple => I::Simple,
948 W::ParamLabel => I::Label,
949 W::ParamMatrix => I::Matrix,
950 W::ParamSpaceDelimited => I::SpaceDelimited,
951 W::ParamPipeDelimited => I::PipeDelimited,
952 W::ParamDeepObject => I::DeepObject,
953 }
954 }
955
956 fn param_style_to(s: ir::ParameterStyle) -> b::ParameterStyle {
957 use b::ParameterStyle as W;
958 use ir::ParameterStyle as I;
959 match s {
960 I::Form => W::ParamForm,
961 I::Simple => W::ParamSimple,
962 I::Label => W::ParamLabel,
963 I::Matrix => W::ParamMatrix,
964 I::SpaceDelimited => W::ParamSpaceDelimited,
965 I::PipeDelimited => W::ParamPipeDelimited,
966 I::DeepObject => W::ParamDeepObject,
967 }
968 }
969
970 fn header_from(h: b::Header) -> ir::Header {
971 ir::Header {
972 r#type: h.type_,
973 required: h.required,
974 description: h.description,
975 deprecated: h.deprecated,
976 examples: examples_from(h.examples),
977 style: h.style.map(param_style_from),
978 explode: h.explode,
979 allow_reserved: h.allow_reserved,
980 allow_empty_value: h.allow_empty_value,
981 location: h.location.map(loc_from),
982 }
983 }
984
985 fn header_to(h: ir::Header) -> b::Header {
986 b::Header {
987 type_: h.r#type,
988 required: h.required,
989 description: h.description,
990 deprecated: h.deprecated,
991 examples: examples_to(h.examples),
992 style: h.style.map(param_style_to),
993 explode: h.explode,
994 allow_reserved: h.allow_reserved,
995 allow_empty_value: h.allow_empty_value,
996 location: h.location.map(loc_to),
997 }
998 }
999
1000 fn parameter_from(p: b::Parameter) -> ir::Parameter {
1001 ir::Parameter {
1002 name: p.name,
1003 r#type: p.type_,
1004 required: p.required,
1005 description: p.description,
1006 deprecated: p.deprecated,
1007 examples: examples_from(p.examples),
1008 style: p.style.map(param_style_from),
1009 explode: p.explode,
1010 allow_empty_value: p.allow_empty_value,
1011 allow_reserved: p.allow_reserved,
1012 extensions: extensions_from(p.extensions),
1013 location: p.location.map(loc_from),
1014 }
1015 }
1016
1017 fn parameter_to(p: ir::Parameter) -> b::Parameter {
1018 b::Parameter {
1019 name: p.name,
1020 type_: p.r#type,
1021 required: p.required,
1022 description: p.description,
1023 deprecated: p.deprecated,
1024 examples: examples_to(p.examples),
1025 style: p.style.map(param_style_to),
1026 explode: p.explode,
1027 allow_empty_value: p.allow_empty_value,
1028 allow_reserved: p.allow_reserved,
1029 extensions: extensions_to(p.extensions),
1030 location: p.location.map(loc_to),
1031 }
1032 }
1033
1034 fn body_from(b_: b::Body) -> ir::Body {
1035 ir::Body {
1036 content: b_.content.into_iter().map(body_content_from).collect(),
1037 required: b_.required,
1038 description: b_.description,
1039 extensions: extensions_from(b_.extensions),
1040 }
1041 }
1042
1043 fn body_to(b_: ir::Body) -> b::Body {
1044 b::Body {
1045 content: b_.content.into_iter().map(body_content_to).collect(),
1046 required: b_.required,
1047 description: b_.description,
1048 extensions: extensions_to(b_.extensions),
1049 }
1050 }
1051
1052 fn body_content_from(c: b::BodyContent) -> ir::BodyContent {
1053 ir::BodyContent {
1054 media_type: c.media_type,
1055 r#type: c.type_,
1056 encoding: c
1057 .encoding
1058 .into_iter()
1059 .map(|(k, v)| (k, encoding_from(v)))
1060 .collect(),
1061 item_schema: c.item_schema,
1062 examples: examples_from(c.examples),
1063 extensions: extensions_from(c.extensions),
1064 }
1065 }
1066
1067 fn body_content_to(c: ir::BodyContent) -> b::BodyContent {
1068 b::BodyContent {
1069 media_type: c.media_type,
1070 type_: c.r#type,
1071 encoding: c
1072 .encoding
1073 .into_iter()
1074 .map(|(k, v)| (k, encoding_to(v)))
1075 .collect(),
1076 item_schema: c.item_schema,
1077 examples: examples_to(c.examples),
1078 extensions: extensions_to(c.extensions),
1079 }
1080 }
1081
1082 fn encoding_from(e: b::Encoding) -> ir::Encoding {
1083 ir::Encoding {
1084 content_type: e.content_type,
1085 style: e.style.map(param_style_from),
1086 explode: e.explode,
1087 allow_reserved: e.allow_reserved,
1088 headers: e
1089 .headers
1090 .into_iter()
1091 .map(|(k, v)| (k, header_from(v)))
1092 .collect(),
1093 extensions: extensions_from(e.extensions),
1094 }
1095 }
1096
1097 fn encoding_to(e: ir::Encoding) -> b::Encoding {
1098 b::Encoding {
1099 content_type: e.content_type,
1100 style: e.style.map(param_style_to),
1101 explode: e.explode,
1102 allow_reserved: e.allow_reserved,
1103 headers: e
1104 .headers
1105 .into_iter()
1106 .map(|(k, v)| (k, header_to(v)))
1107 .collect(),
1108 extensions: extensions_to(e.extensions),
1109 }
1110 }
1111
1112 fn response_from(r: b::Response) -> ir::Response {
1113 ir::Response {
1114 status: match r.status {
1115 b::ResponseStatus::Explicit(code) => ir::ResponseStatus::Explicit { code },
1116 b::ResponseStatus::Default => ir::ResponseStatus::Default,
1117 b::ResponseStatus::Range(class) => ir::ResponseStatus::Range { class },
1118 },
1119 content: r.content.into_iter().map(body_content_from).collect(),
1120 headers: r
1121 .headers
1122 .into_iter()
1123 .map(|(k, v)| (k, header_from(v)))
1124 .collect(),
1125 summary: r.summary,
1126 description: r.description,
1127 links: links_from(r.links),
1128 extensions: extensions_from(r.extensions),
1129 }
1130 }
1131
1132 fn response_to(r: ir::Response) -> b::Response {
1133 b::Response {
1134 status: match r.status {
1135 ir::ResponseStatus::Explicit { code } => b::ResponseStatus::Explicit(code),
1136 ir::ResponseStatus::Default => b::ResponseStatus::Default,
1137 ir::ResponseStatus::Range { class } => b::ResponseStatus::Range(class),
1138 },
1139 content: r.content.into_iter().map(body_content_to).collect(),
1140 headers: r
1141 .headers
1142 .into_iter()
1143 .map(|(k, v)| (k, header_to(v)))
1144 .collect(),
1145 summary: r.summary,
1146 description: r.description,
1147 links: links_to(r.links),
1148 extensions: extensions_to(r.extensions),
1149 }
1150 }
1151
1152 fn operation_from(op: b::Operation) -> Result<ir::Operation, BindgenError> {
1153 Ok(ir::Operation {
1154 id: op.id,
1155 original_id: op.original_id,
1156 method: http_method_from(op.method),
1157 path_template: op.path_template,
1158 path_params: op.path_params.into_iter().map(parameter_from).collect(),
1159 query_params: op.query_params.into_iter().map(parameter_from).collect(),
1160 header_params: op.header_params.into_iter().map(parameter_from).collect(),
1161 cookie_params: op.cookie_params.into_iter().map(parameter_from).collect(),
1162 querystring_params: op
1163 .querystring_params
1164 .into_iter()
1165 .map(parameter_from)
1166 .collect(),
1167 request_body: op.request_body.map(body_from),
1168 responses: op.responses.into_iter().map(response_from).collect(),
1169 security: op
1170 .security
1171 .into_iter()
1172 .map(|s| ir::SecurityRequirement {
1173 scheme_id: s.scheme_id,
1174 scopes: s.scopes,
1175 })
1176 .collect(),
1177 tags: op.tags,
1178 summary: op.summary,
1179 description: op.description,
1180 deprecated: op.deprecated,
1181 external_docs: op.external_docs.map(external_docs_from),
1182 extensions: op.extensions,
1183 servers: op.servers.into_iter().map(server_from).collect(),
1184 callbacks: op.callbacks.into_iter().map(callback_from).collect(),
1185 location: op.location.map(loc_from),
1186 })
1187 }
1188
1189 fn operation_to(op: ir::Operation) -> b::Operation {
1190 b::Operation {
1191 id: op.id,
1192 original_id: op.original_id,
1193 method: http_method_to(op.method),
1194 path_template: op.path_template,
1195 path_params: op.path_params.into_iter().map(parameter_to).collect(),
1196 query_params: op.query_params.into_iter().map(parameter_to).collect(),
1197 header_params: op.header_params.into_iter().map(parameter_to).collect(),
1198 cookie_params: op.cookie_params.into_iter().map(parameter_to).collect(),
1199 querystring_params: op
1200 .querystring_params
1201 .into_iter()
1202 .map(parameter_to)
1203 .collect(),
1204 request_body: op.request_body.map(body_to),
1205 responses: op.responses.into_iter().map(response_to).collect(),
1206 security: op
1207 .security
1208 .into_iter()
1209 .map(|s| b::SecurityRequirement {
1210 scheme_id: s.scheme_id,
1211 scopes: s.scopes,
1212 })
1213 .collect(),
1214 tags: op.tags,
1215 summary: op.summary,
1216 description: op.description,
1217 deprecated: op.deprecated,
1218 external_docs: op.external_docs.map(external_docs_to),
1219 extensions: op.extensions,
1220 servers: op.servers.into_iter().map(server_to).collect(),
1221 callbacks: op.callbacks.into_iter().map(callback_to).collect(),
1222 location: op.location.map(loc_to),
1223 }
1224 }
1225
1226 fn security_scheme_from(s: b::SecurityScheme) -> ir::SecurityScheme {
1231 ir::SecurityScheme {
1232 id: s.id,
1233 kind: match s.kind {
1234 b::SecuritySchemeKind::ApiKey(k) => {
1235 ir::SecuritySchemeKind::ApiKey(ir::ApiKeyScheme {
1236 name: k.name,
1237 location: match k.location {
1238 b::ApiKeyLocation::Header => ir::ApiKeyLocation::Header,
1239 b::ApiKeyLocation::Query => ir::ApiKeyLocation::Query,
1240 b::ApiKeyLocation::Cookie => ir::ApiKeyLocation::Cookie,
1241 },
1242 })
1243 }
1244 b::SecuritySchemeKind::HttpBasic => ir::SecuritySchemeKind::HttpBasic,
1245 b::SecuritySchemeKind::HttpBearer(f) => {
1246 ir::SecuritySchemeKind::HttpBearer { bearer_format: f }
1247 }
1248 b::SecuritySchemeKind::MutualTls => ir::SecuritySchemeKind::MutualTls,
1249 b::SecuritySchemeKind::Oauth2(o) => {
1250 ir::SecuritySchemeKind::Oauth2(ir::OAuth2Scheme {
1251 flows: o.flows.into_iter().map(oauth2_flow_from).collect(),
1252 })
1253 }
1254 b::SecuritySchemeKind::OpenIdConnect(u) => {
1255 ir::SecuritySchemeKind::OpenIdConnect { url: u }
1256 }
1257 },
1258 description: s.description,
1259 deprecated: s.deprecated,
1260 extensions: extensions_from(s.extensions),
1261 }
1262 }
1263
1264 fn security_scheme_to(s: ir::SecurityScheme) -> b::SecurityScheme {
1265 b::SecurityScheme {
1266 id: s.id,
1267 kind: match s.kind {
1268 ir::SecuritySchemeKind::ApiKey(k) => {
1269 b::SecuritySchemeKind::ApiKey(b::ApiKeyScheme {
1270 name: k.name,
1271 location: match k.location {
1272 ir::ApiKeyLocation::Header => b::ApiKeyLocation::Header,
1273 ir::ApiKeyLocation::Query => b::ApiKeyLocation::Query,
1274 ir::ApiKeyLocation::Cookie => b::ApiKeyLocation::Cookie,
1275 },
1276 })
1277 }
1278 ir::SecuritySchemeKind::HttpBasic => b::SecuritySchemeKind::HttpBasic,
1279 ir::SecuritySchemeKind::HttpBearer { bearer_format } => {
1280 b::SecuritySchemeKind::HttpBearer(bearer_format)
1281 }
1282 ir::SecuritySchemeKind::MutualTls => b::SecuritySchemeKind::MutualTls,
1283 ir::SecuritySchemeKind::Oauth2(o) => {
1284 b::SecuritySchemeKind::Oauth2(b::Oauth2Scheme {
1285 flows: o.flows.into_iter().map(oauth2_flow_to).collect(),
1286 })
1287 }
1288 ir::SecuritySchemeKind::OpenIdConnect { url } => {
1289 b::SecuritySchemeKind::OpenIdConnect(url)
1290 }
1291 },
1292 description: s.description,
1293 deprecated: s.deprecated,
1294 extensions: extensions_to(s.extensions),
1295 }
1296 }
1297
1298 fn oauth2_flow_from(f: b::Oauth2Flow) -> ir::OAuth2Flow {
1299 ir::OAuth2Flow {
1300 kind: match f.kind {
1301 b::Oauth2FlowKind::Implicit => ir::OAuth2FlowKind::Implicit,
1302 b::Oauth2FlowKind::Password => ir::OAuth2FlowKind::Password,
1303 b::Oauth2FlowKind::ClientCredentials => {
1304 ir::OAuth2FlowKind::ClientCredentials
1305 }
1306 b::Oauth2FlowKind::AuthorizationCode => {
1307 ir::OAuth2FlowKind::AuthorizationCode
1308 }
1309 },
1310 authorization_url: f.authorization_url,
1311 token_url: f.token_url,
1312 refresh_url: f.refresh_url,
1313 scopes: f.scopes,
1314 extensions: extensions_from(f.extensions),
1315 }
1316 }
1317
1318 fn oauth2_flow_to(f: ir::OAuth2Flow) -> b::Oauth2Flow {
1319 b::Oauth2Flow {
1320 kind: match f.kind {
1321 ir::OAuth2FlowKind::Implicit => b::Oauth2FlowKind::Implicit,
1322 ir::OAuth2FlowKind::Password => b::Oauth2FlowKind::Password,
1323 ir::OAuth2FlowKind::ClientCredentials => {
1324 b::Oauth2FlowKind::ClientCredentials
1325 }
1326 ir::OAuth2FlowKind::AuthorizationCode => {
1327 b::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_to(f.extensions),
1335 }
1336 }
1337 }
1338 };
1339}
1340
1341define_world_conversions!(transformer, transformer);
1342define_world_conversions!(generator, generator);
1343
1344#[cfg(test)]
1345mod tests {
1346 use super::*;
1347 use forge_ir::proptest_util::small_ir;
1348 use proptest::prelude::*;
1349
1350 proptest! {
1351 #[test]
1353 fn roundtrip_transformer(ir in small_ir()) {
1354 let wit = transformer::ir_to_wit(ir.clone());
1355 let back = transformer::ir_from_wit(wit).unwrap();
1356 prop_assert_eq!(ir, back);
1357 }
1358
1359 #[test]
1361 fn roundtrip_generator(ir in small_ir()) {
1362 let wit = generator::ir_to_wit(ir.clone());
1363 let back = generator::ir_from_wit(wit).unwrap();
1364 prop_assert_eq!(ir, back);
1365 }
1366 }
1367}