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