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}