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 description: a.description,
323 summary: a.summary,
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 description: a.description,
338 summary: a.summary,
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 documentation: n.documentation,
419 title: n.title,
420 read_only: n.read_only,
421 write_only: n.write_only,
422 external_docs: n.external_docs.map(external_docs_from),
423 default: n.default,
424 examples: examples_from(n.examples),
425 xml: n.xml.map(xml_object_from),
426 definition: type_def_from(n.definition)?,
427 extensions: extensions_from(n.extensions),
428 location: n.location.map(loc_from),
429 })
430 }
431
432 fn named_type_to(n: ir::NamedType) -> b::NamedType {
433 b::NamedType {
434 id: n.id,
435 original_name: n.original_name,
436 documentation: n.documentation,
437 title: n.title,
438 read_only: n.read_only,
439 write_only: n.write_only,
440 external_docs: n.external_docs.map(external_docs_to),
441 default: n.default,
442 examples: examples_to(n.examples),
443 xml: n.xml.map(xml_object_to),
444 definition: type_def_to(n.definition),
445 extensions: extensions_to(n.extensions),
446 location: n.location.map(loc_to),
447 }
448 }
449
450 fn external_docs_from(d: b::ExternalDocs) -> ir::ExternalDocs {
451 ir::ExternalDocs {
452 description: d.description,
453 url: d.url,
454 }
455 }
456
457 fn external_docs_to(d: ir::ExternalDocs) -> b::ExternalDocs {
458 b::ExternalDocs {
459 description: d.description,
460 url: d.url,
461 }
462 }
463
464 fn example_from(e: b::Example) -> ir::Example {
465 ir::Example {
466 summary: e.summary,
467 description: e.description,
468 value: e.value,
469 external_value: e.external_value,
470 data_value: e.data_value,
471 serialized_value: e.serialized_value,
472 }
473 }
474
475 fn example_to(e: ir::Example) -> b::Example {
476 b::Example {
477 summary: e.summary,
478 description: e.description,
479 value: e.value,
480 external_value: e.external_value,
481 data_value: e.data_value,
482 serialized_value: e.serialized_value,
483 }
484 }
485
486 fn examples_from(xs: Vec<(String, b::Example)>) -> Vec<(String, ir::Example)> {
487 xs.into_iter().map(|(k, v)| (k, example_from(v))).collect()
488 }
489
490 fn examples_to(xs: Vec<(String, ir::Example)>) -> Vec<(String, b::Example)> {
491 xs.into_iter().map(|(k, v)| (k, example_to(v))).collect()
492 }
493
494 fn xml_object_from(x: b::XmlObject) -> ir::XmlObject {
495 ir::XmlObject {
496 name: x.name,
497 namespace: x.namespace,
498 prefix: x.prefix,
499 attribute: x.attribute,
500 wrapped: x.wrapped,
501 text: x.text,
502 ordered: x.ordered,
503 extensions: x.extensions,
504 }
505 }
506
507 fn xml_object_to(x: ir::XmlObject) -> b::XmlObject {
508 b::XmlObject {
509 name: x.name,
510 namespace: x.namespace,
511 prefix: x.prefix,
512 attribute: x.attribute,
513 wrapped: x.wrapped,
514 text: x.text,
515 ordered: x.ordered,
516 extensions: x.extensions,
517 }
518 }
519
520 fn link_from(l: b::Link) -> ir::Link {
521 ir::Link {
522 operation_ref: l.operation_ref,
523 operation_id: l.operation_id,
524 parameters: l.parameters,
525 request_body: l.request_body,
526 description: l.description,
527 server: l.server.map(server_from),
528 extensions: l.extensions,
529 }
530 }
531
532 fn link_to(l: ir::Link) -> b::Link {
533 b::Link {
534 operation_ref: l.operation_ref,
535 operation_id: l.operation_id,
536 parameters: l.parameters,
537 request_body: l.request_body,
538 description: l.description,
539 server: l.server.map(server_to),
540 extensions: l.extensions,
541 }
542 }
543
544 fn links_from(xs: Vec<(String, b::Link)>) -> Vec<(String, ir::Link)> {
545 xs.into_iter().map(|(k, v)| (k, link_from(v))).collect()
546 }
547
548 fn links_to(xs: Vec<(String, ir::Link)>) -> Vec<(String, b::Link)> {
549 xs.into_iter().map(|(k, v)| (k, link_to(v))).collect()
550 }
551
552 fn webhook_from(w: b::Webhook) -> Result<ir::Webhook, BindgenError> {
553 Ok(ir::Webhook {
554 name: w.name,
555 operations: w
556 .operations
557 .into_iter()
558 .map(operation_from)
559 .collect::<Result<_, _>>()?,
560 })
561 }
562
563 fn webhook_to(w: ir::Webhook) -> b::Webhook {
564 b::Webhook {
565 name: w.name,
566 operations: w.operations.into_iter().map(operation_to).collect(),
567 }
568 }
569
570 fn callback_from(c: b::Callback) -> ir::Callback {
571 ir::Callback {
572 name: c.name,
573 expression: c.expression,
574 operation_ids: c.operation_ids,
575 extensions: c.extensions,
576 }
577 }
578
579 fn callback_to(c: ir::Callback) -> b::Callback {
580 b::Callback {
581 name: c.name,
582 expression: c.expression,
583 operation_ids: c.operation_ids,
584 extensions: c.extensions,
585 }
586 }
587
588 fn tag_from(t: b::Tag) -> ir::Tag {
589 ir::Tag {
590 name: t.name,
591 summary: t.summary,
592 description: t.description,
593 external_docs: t.external_docs.map(external_docs_from),
594 parent: t.parent,
595 kind: t.kind,
596 extensions: t.extensions,
597 }
598 }
599
600 fn tag_to(t: ir::Tag) -> b::Tag {
601 b::Tag {
602 name: t.name,
603 summary: t.summary,
604 description: t.description,
605 external_docs: t.external_docs.map(external_docs_to),
606 parent: t.parent,
607 kind: t.kind,
608 extensions: t.extensions,
609 }
610 }
611
612 fn type_def_from(d: b::TypeDef) -> Result<ir::TypeDef, BindgenError> {
613 Ok(match d {
614 b::TypeDef::Primitive(p) => ir::TypeDef::Primitive(prim_from(p)),
615 b::TypeDef::Object(o) => ir::TypeDef::Object(object_from(o)),
616 b::TypeDef::Array(a) => ir::TypeDef::Array(array_from(a)),
617 b::TypeDef::EnumString(e) => ir::TypeDef::EnumString(enum_str_from(e)),
618 b::TypeDef::EnumInt(e) => ir::TypeDef::EnumInt(enum_int_from(e)),
619 b::TypeDef::Union(u) => ir::TypeDef::Union(union_from(u)),
620 b::TypeDef::Null => ir::TypeDef::Null,
621 })
622 }
623
624 fn type_def_to(d: ir::TypeDef) -> b::TypeDef {
625 match d {
626 ir::TypeDef::Primitive(p) => b::TypeDef::Primitive(prim_to(p)),
627 ir::TypeDef::Object(o) => b::TypeDef::Object(object_to(o)),
628 ir::TypeDef::Array(a) => b::TypeDef::Array(array_to(a)),
629 ir::TypeDef::EnumString(e) => b::TypeDef::EnumString(enum_str_to(e)),
630 ir::TypeDef::EnumInt(e) => b::TypeDef::EnumInt(enum_int_to(e)),
631 ir::TypeDef::Union(u) => b::TypeDef::Union(union_to(u)),
632 ir::TypeDef::Null => b::TypeDef::Null,
633 }
634 }
635
636 fn prim_kind_from(k: b::PrimitiveKind) -> ir::PrimitiveKind {
639 use b::PrimitiveKind as W;
640 use ir::PrimitiveKind as I;
641 match k {
642 W::PrimString => I::String,
643 W::PrimInteger => I::Integer,
644 W::PrimNumber => I::Number,
645 W::PrimBool => I::Bool,
646 }
647 }
648
649 fn prim_kind_to(k: ir::PrimitiveKind) -> b::PrimitiveKind {
650 use b::PrimitiveKind as W;
651 use ir::PrimitiveKind as I;
652 match k {
653 I::String => W::PrimString,
654 I::Integer => W::PrimInteger,
655 I::Number => W::PrimNumber,
656 I::Bool => W::PrimBool,
657 }
658 }
659
660 fn prim_constraints_from(c: b::PrimitiveConstraints) -> ir::PrimitiveConstraints {
661 ir::PrimitiveConstraints {
662 minimum: c.minimum,
663 maximum: c.maximum,
664 exclusive_minimum: c.exclusive_minimum,
665 exclusive_maximum: c.exclusive_maximum,
666 multiple_of: c.multiple_of,
667 min_length: c.min_length,
668 max_length: c.max_length,
669 pattern: c.pattern,
670 format_extension: c.format_extension,
671 content_encoding: c.content_encoding,
672 content_media_type: c.content_media_type,
673 content_schema: c.content_schema,
674 }
675 }
676
677 fn prim_constraints_to(c: ir::PrimitiveConstraints) -> b::PrimitiveConstraints {
678 b::PrimitiveConstraints {
679 minimum: c.minimum,
680 maximum: c.maximum,
681 exclusive_minimum: c.exclusive_minimum,
682 exclusive_maximum: c.exclusive_maximum,
683 multiple_of: c.multiple_of,
684 min_length: c.min_length,
685 max_length: c.max_length,
686 pattern: c.pattern,
687 format_extension: c.format_extension,
688 content_encoding: c.content_encoding,
689 content_media_type: c.content_media_type,
690 content_schema: c.content_schema,
691 }
692 }
693
694 fn prim_from(p: b::PrimitiveType) -> ir::PrimitiveType {
695 ir::PrimitiveType {
696 kind: prim_kind_from(p.kind),
697 constraints: prim_constraints_from(p.constraints),
698 }
699 }
700
701 fn prim_to(p: ir::PrimitiveType) -> b::PrimitiveType {
702 b::PrimitiveType {
703 kind: prim_kind_to(p.kind),
704 constraints: prim_constraints_to(p.constraints),
705 }
706 }
707
708 fn array_from(a: b::ArrayType) -> ir::ArrayType {
711 ir::ArrayType {
712 items: a.items,
713 constraints: ir::ArrayConstraints {
714 min_items: a.constraints.min_items,
715 max_items: a.constraints.max_items,
716 unique_items: a.constraints.unique_items,
717 },
718 }
719 }
720
721 fn array_to(a: ir::ArrayType) -> b::ArrayType {
722 b::ArrayType {
723 items: a.items,
724 constraints: b::ArrayConstraints {
725 min_items: a.constraints.min_items,
726 max_items: a.constraints.max_items,
727 unique_items: a.constraints.unique_items,
728 },
729 }
730 }
731
732 fn object_from(o: b::ObjectType) -> ir::ObjectType {
735 ir::ObjectType {
736 properties: o
737 .properties
738 .into_iter()
739 .map(|p| ir::Property {
740 name: p.name,
741 r#type: p.type_,
742 required: p.required,
743 documentation: p.documentation,
744 deprecated: p.deprecated,
745 read_only: p.read_only,
746 write_only: p.write_only,
747 default: p.default,
748 extensions: p.extensions,
749 })
750 .collect(),
751 additional_properties: match o.additional_properties {
752 b::AdditionalProperties::Forbidden => ir::AdditionalProperties::Forbidden,
753 b::AdditionalProperties::Any => ir::AdditionalProperties::Any,
754 b::AdditionalProperties::Typed(t) => {
755 ir::AdditionalProperties::Typed { r#type: t }
756 }
757 },
758 constraints: ir::ObjectConstraints {
759 min_properties: o.constraints.min_properties,
760 max_properties: o.constraints.max_properties,
761 },
762 }
763 }
764
765 fn object_to(o: ir::ObjectType) -> b::ObjectType {
766 b::ObjectType {
767 properties: o
768 .properties
769 .into_iter()
770 .map(|p| b::Property {
771 name: p.name,
772 type_: p.r#type,
773 required: p.required,
774 documentation: p.documentation,
775 deprecated: p.deprecated,
776 read_only: p.read_only,
777 write_only: p.write_only,
778 default: p.default,
779 extensions: p.extensions,
780 })
781 .collect(),
782 additional_properties: match o.additional_properties {
783 ir::AdditionalProperties::Forbidden => b::AdditionalProperties::Forbidden,
784 ir::AdditionalProperties::Any => b::AdditionalProperties::Any,
785 ir::AdditionalProperties::Typed { r#type } => {
786 b::AdditionalProperties::Typed(r#type)
787 }
788 },
789 constraints: b::ObjectConstraints {
790 min_properties: o.constraints.min_properties,
791 max_properties: o.constraints.max_properties,
792 },
793 }
794 }
795
796 fn enum_str_from(e: b::EnumStringType) -> ir::EnumStringType {
801 ir::EnumStringType {
802 values: e
803 .values
804 .into_iter()
805 .map(|v| ir::EnumStringValue {
806 value: v.value,
807 documentation: v.documentation,
808 })
809 .collect(),
810 }
811 }
812
813 fn enum_str_to(e: ir::EnumStringType) -> b::EnumStringType {
814 b::EnumStringType {
815 values: e
816 .values
817 .into_iter()
818 .map(|v| b::EnumStringValue {
819 value: v.value,
820 documentation: v.documentation,
821 })
822 .collect(),
823 }
824 }
825
826 fn enum_int_from(e: b::EnumIntType) -> ir::EnumIntType {
827 ir::EnumIntType {
828 values: e
829 .values
830 .into_iter()
831 .map(|v| ir::EnumIntValue {
832 value: v.value,
833 documentation: v.documentation,
834 })
835 .collect(),
836 kind: match e.kind {
837 b::IntKind::Int32 => ir::IntKind::Int32,
838 b::IntKind::Int64 => ir::IntKind::Int64,
839 },
840 }
841 }
842
843 fn enum_int_to(e: ir::EnumIntType) -> b::EnumIntType {
844 b::EnumIntType {
845 values: e
846 .values
847 .into_iter()
848 .map(|v| b::EnumIntValue {
849 value: v.value,
850 documentation: v.documentation,
851 })
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 deprecated: h.deprecated,
975 documentation: h.documentation,
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 deprecated: h.deprecated,
990 documentation: h.documentation,
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 documentation: p.documentation,
1006 deprecated: p.deprecated,
1007 style: p.style.map(param_style_from),
1008 explode: p.explode,
1009 allow_empty_value: p.allow_empty_value,
1010 allow_reserved: p.allow_reserved,
1011 examples: examples_from(p.examples),
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 documentation: p.documentation,
1023 deprecated: p.deprecated,
1024 style: p.style.map(param_style_to),
1025 explode: p.explode,
1026 allow_empty_value: p.allow_empty_value,
1027 allow_reserved: p.allow_reserved,
1028 examples: examples_to(p.examples),
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 documentation: b_.documentation,
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 documentation: b_.documentation,
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 documentation: r.documentation,
1126 links: links_from(r.links),
1127 extensions: extensions_from(r.extensions),
1128 }
1129 }
1130
1131 fn response_to(r: ir::Response) -> b::Response {
1132 b::Response {
1133 status: match r.status {
1134 ir::ResponseStatus::Explicit { code } => b::ResponseStatus::Explicit(code),
1135 ir::ResponseStatus::Default => b::ResponseStatus::Default,
1136 ir::ResponseStatus::Range { class } => b::ResponseStatus::Range(class),
1137 },
1138 content: r.content.into_iter().map(body_content_to).collect(),
1139 headers: r
1140 .headers
1141 .into_iter()
1142 .map(|(k, v)| (k, header_to(v)))
1143 .collect(),
1144 documentation: r.documentation,
1145 links: links_to(r.links),
1146 extensions: extensions_to(r.extensions),
1147 }
1148 }
1149
1150 fn operation_from(op: b::Operation) -> Result<ir::Operation, BindgenError> {
1151 Ok(ir::Operation {
1152 id: op.id,
1153 original_id: op.original_id,
1154 method: http_method_from(op.method),
1155 path_template: op.path_template,
1156 path_params: op.path_params.into_iter().map(parameter_from).collect(),
1157 query_params: op.query_params.into_iter().map(parameter_from).collect(),
1158 header_params: op.header_params.into_iter().map(parameter_from).collect(),
1159 cookie_params: op.cookie_params.into_iter().map(parameter_from).collect(),
1160 querystring_params: op
1161 .querystring_params
1162 .into_iter()
1163 .map(parameter_from)
1164 .collect(),
1165 request_body: op.request_body.map(body_from),
1166 responses: op.responses.into_iter().map(response_from).collect(),
1167 security: op
1168 .security
1169 .into_iter()
1170 .map(|s| ir::SecurityRequirement {
1171 scheme_id: s.scheme_id,
1172 scopes: s.scopes,
1173 })
1174 .collect(),
1175 tags: op.tags,
1176 documentation: op.documentation,
1177 deprecated: op.deprecated,
1178 extensions: op.extensions,
1179 external_docs: op.external_docs.map(external_docs_from),
1180 servers: op.servers.into_iter().map(server_from).collect(),
1181 callbacks: op.callbacks.into_iter().map(callback_from).collect(),
1182 location: op.location.map(loc_from),
1183 })
1184 }
1185
1186 fn operation_to(op: ir::Operation) -> b::Operation {
1187 b::Operation {
1188 id: op.id,
1189 original_id: op.original_id,
1190 method: http_method_to(op.method),
1191 path_template: op.path_template,
1192 path_params: op.path_params.into_iter().map(parameter_to).collect(),
1193 query_params: op.query_params.into_iter().map(parameter_to).collect(),
1194 header_params: op.header_params.into_iter().map(parameter_to).collect(),
1195 cookie_params: op.cookie_params.into_iter().map(parameter_to).collect(),
1196 querystring_params: op
1197 .querystring_params
1198 .into_iter()
1199 .map(parameter_to)
1200 .collect(),
1201 request_body: op.request_body.map(body_to),
1202 responses: op.responses.into_iter().map(response_to).collect(),
1203 security: op
1204 .security
1205 .into_iter()
1206 .map(|s| b::SecurityRequirement {
1207 scheme_id: s.scheme_id,
1208 scopes: s.scopes,
1209 })
1210 .collect(),
1211 tags: op.tags,
1212 documentation: op.documentation,
1213 deprecated: op.deprecated,
1214 extensions: op.extensions,
1215 external_docs: op.external_docs.map(external_docs_to),
1216 servers: op.servers.into_iter().map(server_to).collect(),
1217 callbacks: op.callbacks.into_iter().map(callback_to).collect(),
1218 location: op.location.map(loc_to),
1219 }
1220 }
1221
1222 fn security_scheme_from(s: b::SecurityScheme) -> ir::SecurityScheme {
1227 ir::SecurityScheme {
1228 id: s.id,
1229 kind: match s.kind {
1230 b::SecuritySchemeKind::ApiKey(k) => {
1231 ir::SecuritySchemeKind::ApiKey(ir::ApiKeyScheme {
1232 name: k.name,
1233 location: match k.location {
1234 b::ApiKeyLocation::Header => ir::ApiKeyLocation::Header,
1235 b::ApiKeyLocation::Query => ir::ApiKeyLocation::Query,
1236 b::ApiKeyLocation::Cookie => ir::ApiKeyLocation::Cookie,
1237 },
1238 })
1239 }
1240 b::SecuritySchemeKind::HttpBasic => ir::SecuritySchemeKind::HttpBasic,
1241 b::SecuritySchemeKind::HttpBearer(f) => {
1242 ir::SecuritySchemeKind::HttpBearer { bearer_format: f }
1243 }
1244 b::SecuritySchemeKind::MutualTls => ir::SecuritySchemeKind::MutualTls,
1245 b::SecuritySchemeKind::Oauth2(o) => {
1246 ir::SecuritySchemeKind::Oauth2(ir::OAuth2Scheme {
1247 flows: o.flows.into_iter().map(oauth2_flow_from).collect(),
1248 })
1249 }
1250 b::SecuritySchemeKind::OpenIdConnect(u) => {
1251 ir::SecuritySchemeKind::OpenIdConnect { url: u }
1252 }
1253 },
1254 documentation: s.documentation,
1255 deprecated: s.deprecated,
1256 extensions: extensions_from(s.extensions),
1257 }
1258 }
1259
1260 fn security_scheme_to(s: ir::SecurityScheme) -> b::SecurityScheme {
1261 b::SecurityScheme {
1262 id: s.id,
1263 kind: match s.kind {
1264 ir::SecuritySchemeKind::ApiKey(k) => {
1265 b::SecuritySchemeKind::ApiKey(b::ApiKeyScheme {
1266 name: k.name,
1267 location: match k.location {
1268 ir::ApiKeyLocation::Header => b::ApiKeyLocation::Header,
1269 ir::ApiKeyLocation::Query => b::ApiKeyLocation::Query,
1270 ir::ApiKeyLocation::Cookie => b::ApiKeyLocation::Cookie,
1271 },
1272 })
1273 }
1274 ir::SecuritySchemeKind::HttpBasic => b::SecuritySchemeKind::HttpBasic,
1275 ir::SecuritySchemeKind::HttpBearer { bearer_format } => {
1276 b::SecuritySchemeKind::HttpBearer(bearer_format)
1277 }
1278 ir::SecuritySchemeKind::MutualTls => b::SecuritySchemeKind::MutualTls,
1279 ir::SecuritySchemeKind::Oauth2(o) => {
1280 b::SecuritySchemeKind::Oauth2(b::Oauth2Scheme {
1281 flows: o.flows.into_iter().map(oauth2_flow_to).collect(),
1282 })
1283 }
1284 ir::SecuritySchemeKind::OpenIdConnect { url } => {
1285 b::SecuritySchemeKind::OpenIdConnect(url)
1286 }
1287 },
1288 documentation: s.documentation,
1289 deprecated: s.deprecated,
1290 extensions: extensions_to(s.extensions),
1291 }
1292 }
1293
1294 fn oauth2_flow_from(f: b::Oauth2Flow) -> ir::OAuth2Flow {
1295 ir::OAuth2Flow {
1296 kind: match f.kind {
1297 b::Oauth2FlowKind::Implicit => ir::OAuth2FlowKind::Implicit,
1298 b::Oauth2FlowKind::Password => ir::OAuth2FlowKind::Password,
1299 b::Oauth2FlowKind::ClientCredentials => {
1300 ir::OAuth2FlowKind::ClientCredentials
1301 }
1302 b::Oauth2FlowKind::AuthorizationCode => {
1303 ir::OAuth2FlowKind::AuthorizationCode
1304 }
1305 },
1306 authorization_url: f.authorization_url,
1307 token_url: f.token_url,
1308 refresh_url: f.refresh_url,
1309 scopes: f.scopes,
1310 extensions: extensions_from(f.extensions),
1311 }
1312 }
1313
1314 fn oauth2_flow_to(f: ir::OAuth2Flow) -> b::Oauth2Flow {
1315 b::Oauth2Flow {
1316 kind: match f.kind {
1317 ir::OAuth2FlowKind::Implicit => b::Oauth2FlowKind::Implicit,
1318 ir::OAuth2FlowKind::Password => b::Oauth2FlowKind::Password,
1319 ir::OAuth2FlowKind::ClientCredentials => {
1320 b::Oauth2FlowKind::ClientCredentials
1321 }
1322 ir::OAuth2FlowKind::AuthorizationCode => {
1323 b::Oauth2FlowKind::AuthorizationCode
1324 }
1325 },
1326 authorization_url: f.authorization_url,
1327 token_url: f.token_url,
1328 refresh_url: f.refresh_url,
1329 scopes: f.scopes,
1330 extensions: extensions_to(f.extensions),
1331 }
1332 }
1333 }
1334 };
1335}
1336
1337define_world_conversions!(transformer, transformer);
1338define_world_conversions!(generator, generator);
1339
1340#[cfg(test)]
1341mod tests {
1342 use super::*;
1343 use forge_ir::proptest_util::small_ir;
1344 use proptest::prelude::*;
1345
1346 proptest! {
1347 #[test]
1349 fn roundtrip_transformer(ir in small_ir()) {
1350 let wit = transformer::ir_to_wit(ir.clone());
1351 let back = transformer::ir_from_wit(wit).unwrap();
1352 prop_assert_eq!(ir, back);
1353 }
1354
1355 #[test]
1357 fn roundtrip_generator(ir in small_ir()) {
1358 let wit = generator::ir_to_wit(ir.clone());
1359 let back = generator::ir_from_wit(wit).unwrap();
1360 prop_assert_eq!(ir, back);
1361 }
1362 }
1363}