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