1use std::fmt::{Display, Formatter};
16
17#[derive(Debug, Clone, PartialEq, Hash, Eq, serde::Serialize, serde::Deserialize)]
18#[serde(tag = "type")]
19pub enum WitExport {
20 Function(WitFunction),
21 Interface(WitInterface),
22}
23
24#[derive(Debug, Clone, PartialEq, Hash, Eq, serde::Serialize, serde::Deserialize)]
25pub struct WitFunction {
26 pub name: String,
27 pub parameters: Vec<WitFunctionParameter>,
28 pub result: Option<WitFunctionResult>,
29}
30
31impl WitFunction {
32 pub fn is_constructor(&self) -> bool {
33 self.name.starts_with("[constructor]")
34 && self.result.is_some()
35 && matches!(
36 &self.result.as_ref().unwrap().typ,
37 WitType::Handle(TypeHandle {
38 mode: AnalysedResourceMode::Owned,
39 ..
40 })
41 )
42 }
43
44 pub fn is_method(&self) -> bool {
45 self.name.starts_with("[method]")
46 && !self.parameters.is_empty()
47 && matches!(
48 &self.parameters[0].typ,
49 WitType::Handle(TypeHandle {
50 mode: AnalysedResourceMode::Borrowed,
51 ..
52 })
53 )
54 }
55
56 pub fn is_static_method(&self) -> bool {
57 self.name.starts_with("[static]")
58 }
59}
60
61#[derive(Debug, Clone, PartialEq, Hash, Eq, serde::Serialize, serde::Deserialize)]
62pub struct WitInterface {
63 pub name: String,
64 pub functions: Vec<WitFunction>,
65}
66
67#[derive(Debug, Clone, PartialEq, Hash, Eq, serde::Serialize, serde::Deserialize)]
68pub struct TypeResult {
69 pub name: Option<String>,
70 pub owner: Option<String>,
71 pub ok: Option<Box<WitType>>,
72 pub err: Option<Box<WitType>>,
73}
74
75#[derive(Debug, Clone, PartialEq, Hash, Eq, serde::Serialize, serde::Deserialize)]
76pub struct NameTypePair {
77 pub name: String,
78 pub typ: WitType,
79}
80
81#[derive(Debug, Clone, PartialEq, Hash, Eq, serde::Serialize, serde::Deserialize)]
82pub struct NameOptionTypePair {
83 pub name: String,
84 pub typ: Option<WitType>,
85}
86
87#[derive(Debug, Clone, PartialEq, Hash, Eq, serde::Serialize, serde::Deserialize)]
88pub struct TypeVariant {
89 pub name: Option<String>,
90 pub owner: Option<String>,
91 pub cases: Vec<NameOptionTypePair>,
92}
93
94#[derive(Debug, Clone, PartialEq, Hash, Eq, serde::Serialize, serde::Deserialize)]
95pub struct TypeOption {
96 pub name: Option<String>,
97 pub owner: Option<String>,
98 pub inner: Box<WitType>,
99}
100
101#[derive(Debug, Clone, PartialEq, Hash, Eq, serde::Serialize, serde::Deserialize)]
102pub struct TypeEnum {
103 pub name: Option<String>,
104 pub owner: Option<String>,
105 pub cases: Vec<String>,
106}
107
108#[derive(Debug, Clone, PartialEq, Hash, Eq, serde::Serialize, serde::Deserialize)]
109pub struct TypeFlags {
110 pub name: Option<String>,
111 pub owner: Option<String>,
112 pub names: Vec<String>,
113}
114
115#[derive(Debug, Clone, PartialEq, Hash, Eq, serde::Serialize, serde::Deserialize)]
116pub struct TypeRecord {
117 pub name: Option<String>,
118 pub owner: Option<String>,
119 pub fields: Vec<NameTypePair>,
120}
121
122#[derive(Debug, Clone, PartialEq, Hash, Eq, serde::Serialize, serde::Deserialize)]
123pub struct TypeTuple {
124 pub name: Option<String>,
125 pub owner: Option<String>,
126 pub items: Vec<WitType>,
127}
128
129#[derive(Debug, Clone, PartialEq, Hash, Eq, serde::Serialize, serde::Deserialize)]
130pub struct TypeList {
131 pub name: Option<String>,
132 pub owner: Option<String>,
133 pub inner: Box<WitType>,
134}
135
136#[derive(Debug, Clone, PartialEq, Hash, Eq, serde::Serialize, serde::Deserialize)]
137pub struct TypeStr;
138
139#[derive(Debug, Clone, PartialEq, Hash, Eq, serde::Serialize, serde::Deserialize)]
140pub struct TypeChr;
141
142#[derive(Debug, Clone, PartialEq, Hash, Eq, serde::Serialize, serde::Deserialize)]
143pub struct TypeF64;
144
145#[derive(Debug, Clone, PartialEq, Hash, Eq, serde::Serialize, serde::Deserialize)]
146pub struct TypeF32;
147
148#[derive(Debug, Clone, PartialEq, Hash, Eq, serde::Serialize, serde::Deserialize)]
149pub struct TypeU64;
150
151#[derive(Debug, Clone, PartialEq, Hash, Eq, serde::Serialize, serde::Deserialize)]
152pub struct TypeS64;
153
154#[derive(Debug, Clone, PartialEq, Hash, Eq, serde::Serialize, serde::Deserialize)]
155pub struct TypeU32;
156
157#[derive(Debug, Clone, PartialEq, Hash, Eq, serde::Serialize, serde::Deserialize)]
158pub struct TypeS32;
159
160#[derive(Debug, Clone, PartialEq, Hash, Eq, serde::Serialize, serde::Deserialize)]
161pub struct TypeU16;
162
163#[derive(Debug, Clone, PartialEq, Hash, Eq, serde::Serialize, serde::Deserialize)]
164pub struct TypeS16;
165
166#[derive(Debug, Clone, PartialEq, Hash, Eq, serde::Serialize, serde::Deserialize)]
167pub struct TypeU8;
168
169#[derive(Debug, Clone, PartialEq, Hash, Eq, serde::Serialize, serde::Deserialize)]
170pub struct TypeS8;
171
172#[derive(Debug, Clone, PartialEq, Hash, Eq, serde::Serialize, serde::Deserialize)]
173pub struct TypeBool;
174
175#[derive(Debug, Clone, PartialEq, Hash, Eq, serde::Serialize, serde::Deserialize)]
176pub struct TypeHandle {
177 pub name: Option<String>,
178 pub owner: Option<String>,
179 pub resource_id: AnalysedResourceId,
180 pub mode: AnalysedResourceMode,
181}
182
183#[derive(Debug, Clone, Hash, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
184#[serde(tag = "type")]
185pub enum WitType {
186 Variant(TypeVariant),
187 Result(TypeResult),
188 Option(TypeOption),
189 Enum(TypeEnum),
190 Flags(TypeFlags),
191 Record(TypeRecord),
192 Tuple(TypeTuple),
193 List(TypeList),
194 Str(TypeStr),
195 Chr(TypeChr),
196 F64(TypeF64),
197 F32(TypeF32),
198 U64(TypeU64),
199 S64(TypeS64),
200 U32(TypeU32),
201 S32(TypeS32),
202 U16(TypeU16),
203 S16(TypeS16),
204 U8(TypeU8),
205 S8(TypeS8),
206 Bool(TypeBool),
207 Handle(TypeHandle),
208}
209
210impl WitType {
211 pub fn name(&self) -> Option<&str> {
212 match self {
213 WitType::Variant(typ) => typ.name.as_deref(),
214 WitType::Result(typ) => typ.name.as_deref(),
215 WitType::Option(typ) => typ.name.as_deref(),
216 WitType::Enum(typ) => typ.name.as_deref(),
217 WitType::Flags(typ) => typ.name.as_deref(),
218 WitType::Record(typ) => typ.name.as_deref(),
219 WitType::Tuple(typ) => typ.name.as_deref(),
220 WitType::List(typ) => typ.name.as_deref(),
221 WitType::Handle(typ) => typ.name.as_deref(),
222 _ => None,
223 }
224 }
225
226 pub fn with_optional_name(self, name: Option<String>) -> Self {
227 match self {
228 WitType::Variant(mut typ) => {
229 typ.name = name;
230 WitType::Variant(typ)
231 }
232 WitType::Result(mut typ) => {
233 typ.name = name;
234 WitType::Result(typ)
235 }
236 WitType::Option(mut typ) => {
237 typ.name = name;
238 WitType::Option(typ)
239 }
240 WitType::Enum(mut typ) => {
241 typ.name = name;
242 WitType::Enum(typ)
243 }
244 WitType::Flags(mut typ) => {
245 typ.name = name;
246 WitType::Flags(typ)
247 }
248 WitType::Record(mut typ) => {
249 typ.name = name;
250 WitType::Record(typ)
251 }
252 WitType::Tuple(mut typ) => {
253 typ.name = name;
254 WitType::Tuple(typ)
255 }
256 WitType::List(mut typ) => {
257 typ.name = name;
258 WitType::List(typ)
259 }
260 WitType::Handle(mut typ) => {
261 typ.name = name;
262 WitType::Handle(typ)
263 }
264 _ => self,
265 }
266 }
267
268 pub fn named(self, name: impl AsRef<str>) -> Self {
269 self.with_optional_name(Some(name.as_ref().to_string()))
270 }
271
272 pub fn owner(&self) -> Option<&str> {
273 match self {
274 WitType::Variant(typ) => typ.owner.as_deref(),
275 WitType::Result(typ) => typ.owner.as_deref(),
276 WitType::Option(typ) => typ.owner.as_deref(),
277 WitType::Enum(typ) => typ.owner.as_deref(),
278 WitType::Flags(typ) => typ.owner.as_deref(),
279 WitType::Record(typ) => typ.owner.as_deref(),
280 WitType::Tuple(typ) => typ.owner.as_deref(),
281 WitType::List(typ) => typ.owner.as_deref(),
282 WitType::Handle(typ) => typ.owner.as_deref(),
283 _ => None,
284 }
285 }
286
287 pub fn with_optional_owner(self, owner: Option<String>) -> Self {
288 match self {
289 WitType::Variant(mut typ) => {
290 typ.owner = owner;
291 WitType::Variant(typ)
292 }
293 WitType::Result(mut typ) => {
294 typ.owner = owner;
295 WitType::Result(typ)
296 }
297 WitType::Option(mut typ) => {
298 typ.owner = owner;
299 WitType::Option(typ)
300 }
301 WitType::Enum(mut typ) => {
302 typ.owner = owner;
303 WitType::Enum(typ)
304 }
305 WitType::Flags(mut typ) => {
306 typ.owner = owner;
307 WitType::Flags(typ)
308 }
309 WitType::Record(mut typ) => {
310 typ.owner = owner;
311 WitType::Record(typ)
312 }
313 WitType::Tuple(mut typ) => {
314 typ.owner = owner;
315 WitType::Tuple(typ)
316 }
317 WitType::List(mut typ) => {
318 typ.owner = owner;
319 WitType::List(typ)
320 }
321 WitType::Handle(mut typ) => {
322 typ.owner = owner;
323 WitType::Handle(typ)
324 }
325 _ => self,
326 }
327 }
328
329 pub fn owned(self, owner: impl AsRef<str>) -> Self {
330 self.with_optional_owner(Some(owner.as_ref().to_string()))
331 }
332
333 pub fn contains_handle(&self) -> bool {
334 match self {
335 WitType::Handle(_) => true,
336 WitType::Variant(typ) => typ
337 .cases
338 .iter()
339 .any(|case| case.typ.as_ref().is_some_and(|t| t.contains_handle())),
340 WitType::Result(typ) => {
341 typ.ok.as_ref().is_some_and(|t| t.contains_handle())
342 || typ.err.as_ref().is_some_and(|t| t.contains_handle())
343 }
344 WitType::Option(typ) => typ.inner.contains_handle(),
345 WitType::Record(typ) => typ.fields.iter().any(|f| f.typ.contains_handle()),
346 WitType::Tuple(typ) => typ.items.iter().any(|t| t.contains_handle()),
347 WitType::List(typ) => typ.inner.contains_handle(),
348 _ => false,
349 }
350 }
351}
352
353impl Display for WitType {
354 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
355 match self {
356 WitType::Variant(_) => write!(f, "Variant"),
357 WitType::Result(_) => write!(f, "Result"),
358 WitType::Option(_) => write!(f, "Option"),
359 WitType::Enum(_) => write!(f, "Enum"),
360 WitType::Flags(_) => write!(f, "Flags"),
361 WitType::Record(_) => write!(f, "Record"),
362 WitType::Tuple(_) => write!(f, "Tuple"),
363 WitType::List(_) => write!(f, "List"),
364 WitType::Str(_) => write!(f, "Str"),
365 WitType::Chr(_) => write!(f, "Chr"),
366 WitType::F64(_) => write!(f, "F64"),
367 WitType::F32(_) => write!(f, "F32"),
368 WitType::U64(_) => write!(f, "U64"),
369 WitType::S64(_) => write!(f, "S64"),
370 WitType::U32(_) => write!(f, "U32"),
371 WitType::S32(_) => write!(f, "S32"),
372 WitType::U16(_) => write!(f, "U16"),
373 WitType::S16(_) => write!(f, "S16"),
374 WitType::U8(_) => write!(f, "U8"),
375 WitType::S8(_) => write!(f, "S8"),
376 WitType::Bool(_) => write!(f, "Bool"),
377 WitType::Handle(_) => write!(f, "Handle"),
378 }
379 }
380}
381
382#[derive(Debug, Clone, PartialEq, Hash, Eq, serde::Serialize, serde::Deserialize)]
383pub enum AnalysedResourceMode {
384 Owned,
385 Borrowed,
386}
387
388#[derive(Debug, Copy, Clone, PartialEq, Hash, Eq, serde::Serialize, serde::Deserialize)]
389pub struct AnalysedResourceId(pub u64);
390
391#[derive(Debug, Clone, PartialEq, Hash, Eq, serde::Serialize, serde::Deserialize)]
392pub struct WitFunctionParameter {
393 pub name: String,
394 pub typ: WitType,
395}
396
397#[derive(Debug, Clone, PartialEq, Hash, Eq, serde::Serialize, serde::Deserialize)]
398pub struct WitFunctionResult {
399 pub typ: WitType,
400}
401
402pub mod builders {
404 use super::*;
405
406 pub fn field(name: &str, typ: WitType) -> NameTypePair {
407 NameTypePair {
408 name: name.to_string(),
409 typ,
410 }
411 }
412
413 pub fn case(name: &str, typ: WitType) -> NameOptionTypePair {
414 NameOptionTypePair {
415 name: name.to_string(),
416 typ: Some(typ),
417 }
418 }
419
420 pub fn opt_case(name: &str, typ: Option<WitType>) -> NameOptionTypePair {
421 NameOptionTypePair {
422 name: name.to_string(),
423 typ,
424 }
425 }
426
427 pub fn unit_case(name: &str) -> NameOptionTypePair {
428 NameOptionTypePair {
429 name: name.to_string(),
430 typ: None,
431 }
432 }
433
434 pub fn bool() -> WitType {
435 WitType::Bool(TypeBool)
436 }
437
438 pub fn s8() -> WitType {
439 WitType::S8(TypeS8)
440 }
441
442 pub fn s16() -> WitType {
443 WitType::S16(TypeS16)
444 }
445
446 pub fn s32() -> WitType {
447 WitType::S32(TypeS32)
448 }
449
450 pub fn s64() -> WitType {
451 WitType::S64(TypeS64)
452 }
453
454 pub fn u8() -> WitType {
455 WitType::U8(TypeU8)
456 }
457
458 pub fn u16() -> WitType {
459 WitType::U16(TypeU16)
460 }
461
462 pub fn u32() -> WitType {
463 WitType::U32(TypeU32)
464 }
465
466 pub fn u64() -> WitType {
467 WitType::U64(TypeU64)
468 }
469
470 pub fn f32() -> WitType {
471 WitType::F32(TypeF32)
472 }
473
474 pub fn f64() -> WitType {
475 WitType::F64(TypeF64)
476 }
477
478 pub fn chr() -> WitType {
479 WitType::Chr(TypeChr)
480 }
481
482 pub fn str() -> WitType {
483 WitType::Str(TypeStr)
484 }
485
486 pub fn list(inner: WitType) -> WitType {
487 WitType::List(TypeList {
488 name: None,
489 owner: None,
490 inner: Box::new(inner),
491 })
492 }
493
494 pub fn option(inner: WitType) -> WitType {
495 WitType::Option(TypeOption {
496 name: None,
497 owner: None,
498 inner: Box::new(inner),
499 })
500 }
501
502 pub fn flags(names: &[&str]) -> WitType {
503 WitType::Flags(TypeFlags {
504 name: None,
505 owner: None,
506 names: names.iter().map(|n| n.to_string()).collect(),
507 })
508 }
509
510 pub fn r#enum(cases: &[&str]) -> WitType {
511 WitType::Enum(TypeEnum {
512 name: None,
513 owner: None,
514 cases: cases.iter().map(|n| n.to_string()).collect(),
515 })
516 }
517
518 pub fn tuple(items: Vec<WitType>) -> WitType {
519 WitType::Tuple(TypeTuple {
520 name: None,
521 owner: None,
522 items,
523 })
524 }
525
526 pub fn result(ok: WitType, err: WitType) -> WitType {
527 WitType::Result(TypeResult {
528 name: None,
529 owner: None,
530 ok: Some(Box::new(ok)),
531 err: Some(Box::new(err)),
532 })
533 }
534
535 pub fn result_ok(ok: WitType) -> WitType {
536 WitType::Result(TypeResult {
537 name: None,
538 owner: None,
539 ok: Some(Box::new(ok)),
540 err: None,
541 })
542 }
543
544 pub fn result_err(err: WitType) -> WitType {
545 WitType::Result(TypeResult {
546 name: None,
547 owner: None,
548 ok: None,
549 err: Some(Box::new(err)),
550 })
551 }
552
553 pub fn unit_result() -> WitType {
554 WitType::Result(TypeResult {
555 name: None,
556 owner: None,
557 ok: None,
558 err: None,
559 })
560 }
561
562 pub fn record(fields: Vec<NameTypePair>) -> WitType {
563 WitType::Record(TypeRecord {
564 name: None,
565 owner: None,
566 fields,
567 })
568 }
569
570 pub fn variant(cases: Vec<NameOptionTypePair>) -> WitType {
571 WitType::Variant(TypeVariant {
572 name: None,
573 owner: None,
574 cases,
575 })
576 }
577
578 pub fn handle(resource_id: AnalysedResourceId, mode: AnalysedResourceMode) -> WitType {
579 WitType::Handle(TypeHandle {
580 name: None,
581 owner: None,
582 resource_id,
583 mode,
584 })
585 }
586}
587
588pub use builders::*;