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