wit_encoder/
ty.rs

1use std::fmt::{self, Display};
2
3use crate::{
4    ident::Ident, Docs, Enum, EnumCase, Field, Flag, Flags, Record, Render, RenderOpts, Resource,
5    ResourceFunc, Result_, Tuple, Variant,
6};
7
8#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
9#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
10#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
11pub enum Type {
12    Bool,
13    U8,
14    U16,
15    U32,
16    U64,
17    S8,
18    S16,
19    S32,
20    S64,
21    F32,
22    F64,
23    Char,
24    String,
25    Borrow(Ident),
26    Option(Box<Type>),
27    Result(Box<Result_>),
28    List(Box<Type>),
29    Tuple(Tuple),
30    Future(Option<Box<Type>>),
31    Stream(Option<Box<Type>>),
32    ErrorContext,
33    Named(Ident),
34}
35
36impl Type {
37    pub fn borrow(name: impl Into<Ident>) -> Self {
38        Type::Borrow(name.into())
39    }
40    pub fn option(type_: Type) -> Self {
41        Type::Option(Box::new(type_))
42    }
43    pub fn result(result: Result_) -> Self {
44        Type::Result(Box::new(result))
45    }
46    pub fn result_ok(type_: Type) -> Self {
47        Type::Result(Box::new(Result_::ok(type_)))
48    }
49    pub fn result_err(type_: Type) -> Self {
50        Type::Result(Box::new(Result_::err(type_)))
51    }
52    pub fn result_both(ok: Type, err: Type) -> Self {
53        Type::Result(Box::new(Result_::both(ok, err)))
54    }
55    pub fn result_empty() -> Self {
56        Type::Result(Box::new(Result_::empty()))
57    }
58    pub fn list(type_: Type) -> Self {
59        Type::List(Box::new(type_))
60    }
61    pub fn tuple(types: impl IntoIterator<Item = Type>) -> Self {
62        Type::Tuple(Tuple {
63            types: types.into_iter().collect(),
64        })
65    }
66    pub fn future(type_: Option<Type>) -> Self {
67        Type::Future(type_.map(Box::new))
68    }
69    pub fn stream(type_: Option<Type>) -> Self {
70        Type::Stream(type_.map(Box::new))
71    }
72    pub fn named(name: impl Into<Ident>) -> Self {
73        Type::Named(name.into())
74    }
75}
76impl From<Result_> for Type {
77    fn from(value: Result_) -> Self {
78        Self::result(value)
79    }
80}
81impl From<Tuple> for Type {
82    fn from(value: Tuple) -> Self {
83        Type::Tuple(value)
84    }
85}
86impl From<Ident> for Type {
87    fn from(value: Ident) -> Self {
88        Self::named(value)
89    }
90}
91
92impl Display for Type {
93    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
94        match self {
95            Type::Bool => write!(f, "bool"),
96            Type::U8 => write!(f, "u8"),
97            Type::U16 => write!(f, "u16"),
98            Type::U32 => write!(f, "u32"),
99            Type::U64 => write!(f, "u64"),
100            Type::S8 => write!(f, "s8"),
101            Type::S16 => write!(f, "s16"),
102            Type::S32 => write!(f, "s32"),
103            Type::S64 => write!(f, "s64"),
104            Type::F32 => write!(f, "f32"),
105            Type::F64 => write!(f, "f64"),
106            Type::Char => write!(f, "char"),
107            Type::String => write!(f, "string"),
108            Type::Named(name) => write!(f, "{}", name),
109            Type::Borrow(type_) => {
110                write!(f, "borrow<{type_}>")
111            }
112            Type::Option(type_) => {
113                write!(f, "option<{type_}>")
114            }
115            Type::Result(result) => result.fmt(f),
116            Type::List(type_) => {
117                write!(f, "list<{type_}>")
118            }
119            Type::Tuple(tuple) => tuple.fmt(f),
120            Type::Future(None) => {
121                write!(f, "future")
122            }
123            Type::Future(Some(type_)) => {
124                write!(f, "future<{type_}>")
125            }
126            Type::Stream(None) => {
127                write!(f, "stream")
128            }
129            Type::Stream(Some(type_)) => {
130                write!(f, "stream<{type_}>")
131            }
132            Type::ErrorContext => write!(f, "error-context"),
133        }
134    }
135}
136
137#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
138#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
139#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
140pub struct VariantCase {
141    name: Ident,
142    #[cfg_attr(feature = "serde", serde(rename = "type"))]
143    type_: Option<Type>,
144    docs: Option<Docs>,
145}
146
147impl VariantCase {
148    pub fn empty(name: impl Into<Ident>) -> Self {
149        Self {
150            name: name.into(),
151            type_: None,
152            docs: None,
153        }
154    }
155
156    pub fn value(name: impl Into<Ident>, ty: Type) -> Self {
157        Self {
158            name: name.into(),
159            type_: Some(ty),
160            docs: None,
161        }
162    }
163
164    pub fn set_name(&mut self, name: impl Into<Ident>) {
165        self.name = name.into();
166    }
167
168    pub fn name(&self) -> &Ident {
169        &self.name
170    }
171
172    pub fn name_mut(&mut self) -> &mut Ident {
173        &mut self.name
174    }
175
176    pub fn type_(&self) -> Option<&Type> {
177        self.type_.as_ref()
178    }
179
180    pub fn type_mut(&mut self) -> &mut Option<Type> {
181        &mut self.type_
182    }
183
184    pub fn set_docs(&mut self, docs: Option<impl Into<Docs>>) {
185        self.docs = docs.map(|d| d.into());
186    }
187
188    pub fn docs(&self) -> &Option<Docs> {
189        &self.docs
190    }
191}
192
193impl<N> Into<VariantCase> for (N,)
194where
195    N: Into<Ident>,
196{
197    fn into(self) -> VariantCase {
198        VariantCase::empty(self.0)
199    }
200}
201
202impl<N> Into<VariantCase> for (N, Type)
203where
204    N: Into<Ident>,
205{
206    fn into(self) -> VariantCase {
207        VariantCase::value(self.0, self.1)
208    }
209}
210
211impl<N, D> Into<VariantCase> for (N, Type, D)
212where
213    N: Into<Ident>,
214    D: Into<Docs>,
215{
216    fn into(self) -> VariantCase {
217        let mut field = VariantCase::value(self.0, self.1);
218        field.set_docs(Some(self.2.into()));
219        field
220    }
221}
222
223#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
224#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
225#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
226pub struct TypeDef {
227    name: Ident,
228    kind: TypeDefKind,
229    docs: Option<Docs>,
230}
231
232impl TypeDef {
233    pub fn new(name: impl Into<Ident>, kind: TypeDefKind) -> Self {
234        TypeDef {
235            name: name.into(),
236            kind,
237            docs: None,
238        }
239    }
240
241    pub fn record(
242        name: impl Into<Ident>,
243        fields: impl IntoIterator<Item = impl Into<Field>>,
244    ) -> Self {
245        TypeDef {
246            name: name.into(),
247            kind: TypeDefKind::record(fields),
248            docs: None,
249        }
250    }
251
252    pub fn resource(
253        name: impl Into<Ident>,
254        funcs: impl IntoIterator<Item = impl Into<ResourceFunc>>,
255    ) -> Self {
256        TypeDef {
257            name: name.into(),
258            kind: TypeDefKind::resource(funcs),
259            docs: None,
260        }
261    }
262
263    pub fn flags(name: impl Into<Ident>, flags: impl IntoIterator<Item = impl Into<Flag>>) -> Self {
264        TypeDef {
265            name: name.into(),
266            kind: TypeDefKind::flags(flags),
267            docs: None,
268        }
269    }
270
271    pub fn variant(
272        name: impl Into<Ident>,
273        cases: impl IntoIterator<Item = impl Into<VariantCase>>,
274    ) -> Self {
275        TypeDef {
276            name: name.into(),
277            kind: TypeDefKind::variant(cases),
278            docs: None,
279        }
280    }
281
282    pub fn enum_(
283        name: impl Into<Ident>,
284        cases: impl IntoIterator<Item = impl Into<EnumCase>>,
285    ) -> Self {
286        TypeDef {
287            name: name.into(),
288            kind: TypeDefKind::enum_(cases),
289            docs: None,
290        }
291    }
292
293    pub fn type_(name: impl Into<Ident>, type_: Type) -> Self {
294        TypeDef {
295            name: name.into(),
296            kind: TypeDefKind::type_(type_),
297            docs: None,
298        }
299    }
300
301    pub fn name(&self) -> &Ident {
302        &self.name
303    }
304
305    pub fn name_mut(&mut self) -> &mut Ident {
306        &mut self.name
307    }
308
309    pub fn kind(&self) -> &TypeDefKind {
310        &self.kind
311    }
312
313    pub fn kind_mut(&mut self) -> &mut TypeDefKind {
314        &mut self.kind
315    }
316
317    pub fn set_docs(&mut self, docs: Option<impl Into<Docs>>) {
318        self.docs = docs.map(|d| d.into());
319    }
320
321    pub fn docs(&self) -> &Option<Docs> {
322        &self.docs
323    }
324}
325
326#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
327#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
328#[cfg_attr(feature = "serde", serde(rename_all = "kebab-case"))]
329pub enum TypeDefKind {
330    Record(Record),
331    Resource(Resource),
332    Flags(Flags),
333    Variant(Variant),
334    Enum(Enum),
335    Type(Type),
336}
337
338impl TypeDefKind {
339    pub fn record(fields: impl IntoIterator<Item = impl Into<Field>>) -> Self {
340        Self::Record(Record {
341            fields: fields.into_iter().map(|c| c.into()).collect(),
342        })
343    }
344
345    pub fn resource(funcs: impl IntoIterator<Item = impl Into<ResourceFunc>>) -> Self {
346        Self::Resource(Resource {
347            funcs: funcs.into_iter().map(|f| f.into()).collect(),
348        })
349    }
350
351    pub fn flags(flags: impl IntoIterator<Item = impl Into<Flag>>) -> Self {
352        Self::Flags(Flags {
353            flags: flags.into_iter().map(|f| f.into()).collect(),
354        })
355    }
356
357    pub fn variant(cases: impl IntoIterator<Item = impl Into<VariantCase>>) -> Self {
358        Self::Variant(Variant {
359            cases: cases.into_iter().map(|c| c.into()).collect(),
360        })
361    }
362
363    pub fn enum_(cases: impl IntoIterator<Item = impl Into<EnumCase>>) -> Self {
364        Self::Enum(Enum {
365            cases: cases.into_iter().map(|c| c.into()).collect(),
366        })
367    }
368
369    pub fn type_(type_: Type) -> Self {
370        Self::Type(type_)
371    }
372}
373
374impl Render for TypeDef {
375    fn render(&self, f: &mut fmt::Formatter<'_>, opts: &RenderOpts) -> fmt::Result {
376        match &self.kind {
377            TypeDefKind::Record(record) => {
378                if let Some(docs) = &self.docs {
379                    docs.render(f, opts)?;
380                }
381                write!(f, "{}record {} {{", opts.spaces(), self.name)?;
382                for (index, field) in record.fields.iter().enumerate() {
383                    if index == 0 {
384                        write!(f, "\n")?;
385                    }
386                    let opts = opts.indent();
387                    if let Some(docs) = &field.docs {
388                        docs.render(f, &opts)?;
389                    }
390                    write!(f, "{}{}: {},\n", opts.spaces(), field.name, field.type_)?;
391                }
392                write!(f, "{}}}\n", opts.spaces())?;
393            }
394            TypeDefKind::Resource(resource) => {
395                if let Some(docs) = &self.docs {
396                    docs.render(f, opts)?;
397                }
398                write!(f, "{}resource {} {{\n", opts.spaces(), self.name)?;
399                for func in &resource.funcs {
400                    let opts = opts.indent();
401                    if let Some(docs) = &func.docs {
402                        docs.render(f, &opts)?;
403                    }
404                    match &func.kind {
405                        crate::ResourceFuncKind::Method(name, result) => {
406                            write!(f, "{}{}: func({})", opts.spaces(), name, func.params)?;
407                            if let Some(ty) = result {
408                                write!(f, " -> {ty}")?;
409                            }
410                            write!(f, ";\n")?;
411                        }
412                        crate::ResourceFuncKind::Static(name, result) => {
413                            write!(f, "{}{}: static func({})", opts.spaces(), name, func.params)?;
414                            if let Some(ty) = result {
415                                write!(f, " -> {ty}")?;
416                            }
417                            write!(f, ";\n")?;
418                        }
419                        crate::ResourceFuncKind::Constructor => {
420                            write!(f, "{}constructor({});\n", opts.spaces(), func.params)?;
421                        }
422                    }
423                }
424                write!(f, "{}}}\n", opts.spaces())?;
425            }
426            TypeDefKind::Flags(flags) => {
427                if let Some(docs) = &self.docs {
428                    docs.render(f, opts)?;
429                }
430                write!(f, "{}flags {} {{\n", opts.spaces(), self.name)?;
431                for flag in &flags.flags {
432                    let opts = opts.indent();
433                    if let Some(docs) = &flag.docs {
434                        docs.render(f, &opts)?;
435                    }
436                    write!(f, "{}{},\n", opts.spaces(), flag.name)?;
437                }
438                write!(f, "{}}}\n", opts.spaces())?;
439            }
440            TypeDefKind::Variant(variant) => {
441                if let Some(docs) = &self.docs {
442                    docs.render(f, opts)?;
443                }
444                write!(f, "{}variant {} {{\n", opts.spaces(), self.name)?;
445                for case in &variant.cases {
446                    let opts = opts.indent();
447                    if let Some(docs) = &case.docs {
448                        docs.render(f, &opts)?;
449                    }
450                    match &case.type_ {
451                        Some(type_) => {
452                            write!(f, "{}{}({}),\n", opts.spaces(), case.name, type_)?;
453                        }
454                        None => {
455                            write!(f, "{}{},\n", opts.spaces(), case.name)?;
456                        }
457                    }
458                }
459                write!(f, "{}}}\n", opts.spaces())?;
460            }
461            TypeDefKind::Enum(enum_) => {
462                if let Some(docs) = &self.docs {
463                    docs.render(f, opts)?;
464                }
465                write!(f, "{}enum {} {{\n", opts.spaces(), self.name)?;
466                for case in &enum_.cases {
467                    let opts = opts.indent();
468                    if let Some(docs) = &case.docs {
469                        docs.render(f, &opts)?;
470                    }
471                    write!(f, "{}{},\n", opts.spaces(), case.name)?;
472                }
473                write!(f, "{}}}\n", opts.spaces())?;
474            }
475            TypeDefKind::Type(type_) => {
476                if let Some(docs) = &self.docs {
477                    docs.render(f, opts)?;
478                }
479                write!(f, "{}type {} = {};\n", opts.spaces(), self.name, type_)?;
480            }
481        }
482        Ok(())
483    }
484}