Skip to main content

wit_component/
printing.rs

1use anyhow::{Result, anyhow, bail};
2use std::borrow::Cow;
3use std::collections::HashMap;
4use std::fmt::Display;
5use std::mem;
6use std::ops::Deref;
7use wit_parser::*;
8
9/// A utility for printing WebAssembly interface definitions to a string.
10pub struct WitPrinter<O: Output = OutputToString> {
11    /// Visitor that holds the WIT document being printed.
12    pub output: O,
13
14    // Count of how many items in this current block have been printed to print
15    // a blank line between each item, but not the first item.
16    any_items: bool,
17
18    // Whether to print doc comments.
19    emit_docs: bool,
20}
21
22impl Default for WitPrinter {
23    fn default() -> Self {
24        Self::new(OutputToString::default())
25    }
26}
27
28impl<O: Output> WitPrinter<O> {
29    /// Create new instance.
30    pub fn new(output: O) -> Self {
31        Self {
32            output,
33            any_items: false,
34            emit_docs: true,
35        }
36    }
37
38    /// Prints the specified `pkg` which is located in `resolve` to `O`.
39    ///
40    /// The `nested` list of packages are other packages to include at the end
41    /// of the output in `package ... { ... }` syntax.
42    pub fn print(&mut self, resolve: &Resolve, pkg: PackageId, nested: &[PackageId]) -> Result<()> {
43        self.print_package(resolve, pkg, true)?;
44        for (i, pkg_id) in nested.iter().enumerate() {
45            if i > 0 {
46                self.output.newline();
47                self.output.newline();
48            }
49            self.print_package(resolve, *pkg_id, false)?;
50        }
51        Ok(())
52    }
53
54    /// Configure whether doc comments will be printed.
55    ///
56    /// Defaults to true.
57    pub fn emit_docs(&mut self, enabled: bool) -> &mut Self {
58        self.emit_docs = enabled;
59        self
60    }
61
62    /// Prints the specified `pkg`.
63    ///
64    /// If `is_main` is not set, nested package notation is used.
65    pub fn print_package(
66        &mut self,
67        resolve: &Resolve,
68        pkg: PackageId,
69        is_main: bool,
70    ) -> Result<()> {
71        let pkg = &resolve.packages[pkg];
72        self.print_package_outer(pkg)?;
73
74        if is_main {
75            self.output.semicolon();
76            self.output.newline();
77        } else {
78            self.output.indent_start();
79        }
80
81        for (name, id) in pkg.interfaces.iter() {
82            self.print_interface_outer(resolve, *id, name)?;
83            self.output.indent_start();
84            self.print_interface(resolve, *id)?;
85            self.output.indent_end();
86            if is_main {
87                self.output.newline();
88            }
89        }
90
91        for (name, id) in pkg.worlds.iter() {
92            self.print_docs(&resolve.worlds[*id].docs);
93            self.print_stability(&resolve.worlds[*id].stability);
94            self.output.keyword("world");
95            self.output.str(" ");
96            self.print_name_type(name, TypeKind::WorldDeclaration);
97            self.output.indent_start();
98            self.print_world(resolve, *id)?;
99            self.output.indent_end();
100        }
101        if !is_main {
102            self.output.indent_end();
103        }
104        Ok(())
105    }
106
107    /// Print the specified package without its content.
108    /// Does not print the semicolon nor starts the indentation.
109    pub fn print_package_outer(&mut self, pkg: &Package) -> Result<()> {
110        self.print_docs(&pkg.docs);
111        self.output.keyword("package");
112        self.output.str(" ");
113        self.print_name_type(&pkg.name.namespace, TypeKind::NamespaceDeclaration);
114        self.output.str(":");
115        self.print_name_type(&pkg.name.name, TypeKind::PackageNameDeclaration);
116        if let Some(version) = &pkg.name.version {
117            self.print_name_type(&format!("@{version}"), TypeKind::VersionDeclaration);
118        }
119        Ok(())
120    }
121
122    fn new_item(&mut self) {
123        if self.any_items {
124            self.output.newline();
125        }
126        self.any_items = true;
127    }
128
129    /// Print the given WebAssembly interface without its content.
130    /// Does not print the semicolon nor starts the indentation.
131    pub fn print_interface_outer(
132        &mut self,
133        resolve: &Resolve,
134        id: InterfaceId,
135        name: &str,
136    ) -> Result<()> {
137        self.print_docs(&resolve.interfaces[id].docs);
138        self.print_stability(&resolve.interfaces[id].stability);
139        self.output.keyword("interface");
140        self.output.str(" ");
141        self.print_name_type(name, TypeKind::InterfaceDeclaration);
142        Ok(())
143    }
144
145    /// Print the inner content of a given WebAssembly interface.
146    pub fn print_interface(&mut self, resolve: &Resolve, id: InterfaceId) -> Result<()> {
147        let prev_items = mem::replace(&mut self.any_items, false);
148        let interface = &resolve.interfaces[id];
149
150        let mut resource_funcs = HashMap::new();
151        let mut freestanding = Vec::new();
152        for (_, func) in interface.functions.iter() {
153            if let Some(id) = func.kind.resource() {
154                resource_funcs.entry(id).or_insert(Vec::new()).push(func);
155            } else {
156                freestanding.push(func);
157            }
158        }
159
160        self.print_types(
161            resolve,
162            TypeOwner::Interface(id),
163            interface
164                .types
165                .iter()
166                .map(|(name, id)| (name.as_str(), *id)),
167            &resource_funcs,
168        )?;
169
170        for func in freestanding {
171            self.new_item();
172            self.print_docs(&func.docs);
173            self.print_stability(&func.stability);
174            self.print_external_id(func.external_id.as_deref());
175            self.print_name_type(func.item_name(), TypeKind::FunctionFreestanding);
176            self.output.str(": ");
177            self.print_function(resolve, func)?;
178            self.output.semicolon();
179        }
180
181        self.any_items = prev_items;
182
183        Ok(())
184    }
185
186    /// Print types of an interface.
187    pub fn print_types<'a>(
188        &mut self,
189        resolve: &Resolve,
190        owner: TypeOwner,
191        types: impl Iterator<Item = (&'a str, TypeId)>,
192        resource_funcs: &HashMap<TypeId, Vec<&Function>>,
193    ) -> Result<()> {
194        // Partition types defined in this interface into either those imported
195        // from foreign interfaces or those defined locally.
196        let mut types_to_declare = Vec::new();
197        let mut types_to_import: Vec<(_, &TypeDef, Vec<_>)> = Vec::new();
198        for (name, ty_id) in types {
199            let ty = &resolve.types[ty_id];
200
201            // If `ty` points to another type, `other`, then this might actually
202            // be a `use`.
203            if let TypeDefKind::Type(Type::Id(other)) = ty.kind {
204                let other = &resolve.types[other];
205                match other.owner {
206                    TypeOwner::None => {}
207
208                    // `use` is only applicable when the owner of the current
209                    // set of types is different than the owner of `other`. Once
210                    // this is detected `types_to_import` is going to get
211                    // modified.
212                    other_owner if owner != other_owner => {
213                        let other_name = other
214                            .name
215                            .as_ref()
216                            .ok_or_else(|| anyhow!("cannot import unnamed type"))?;
217
218                        // As a convenience push onto the last set of types to
219                        // import if it's to the same interface and with
220                        // matching attributes.
221                        if let Some((prev_owner, prev_ty, list)) = types_to_import.last_mut() {
222                            if *prev_owner == other_owner
223                                && ty.stability == prev_ty.stability
224                                && ty.external_id == prev_ty.external_id
225                            {
226                                list.push((name, other_name));
227                                continue;
228                            }
229                        }
230                        types_to_import.push((other_owner, ty, vec![(name, other_name)]));
231                        continue;
232                    }
233                    _ => {}
234                }
235            }
236
237            types_to_declare.push(ty_id);
238        }
239
240        // Generate a `use` statement for all imported types.
241        let my_pkg = match owner {
242            TypeOwner::Interface(id) => resolve.interfaces[id].package.unwrap(),
243            TypeOwner::World(id) => resolve.worlds[id].package.unwrap(),
244            TypeOwner::None => unreachable!(),
245        };
246        for (owner, ty, tys) in types_to_import {
247            self.any_items = true;
248            self.print_stability(&ty.stability);
249            self.print_external_id(ty.external_id.as_deref());
250            self.output.keyword("use");
251            self.output.str(" ");
252            let id = match owner {
253                TypeOwner::Interface(id) => id,
254                // it's only possible to import types from interfaces at
255                // this time.
256                _ => unreachable!(),
257            };
258            self.print_path_to_interface(resolve, id, my_pkg)?;
259            self.output.str(".{"); // Note: not changing the indentation.
260            for (i, (my_name, other_name)) in tys.into_iter().enumerate() {
261                if i > 0 {
262                    self.output.str(", ");
263                }
264                if my_name == other_name {
265                    self.print_name_type(my_name, TypeKind::TypeImport);
266                } else {
267                    self.print_name_type(other_name, TypeKind::TypeImport);
268                    self.output.str(" ");
269                    self.output.keyword("as");
270                    self.output.str(" ");
271                    self.print_name_type(my_name, TypeKind::TypeAlias);
272                }
273            }
274            self.output.str("}"); // Note: not changing the indentation.
275            self.output.semicolon();
276        }
277
278        for id in types_to_declare {
279            self.new_item();
280            self.print_docs(&resolve.types[id].docs);
281            self.print_stability(&resolve.types[id].stability);
282            self.print_external_id(resolve.types[id].external_id.as_deref());
283            match resolve.types[id].kind {
284                TypeDefKind::Resource => self.print_resource(
285                    resolve,
286                    id,
287                    resource_funcs.get(&id).unwrap_or(&Vec::new()),
288                )?,
289                _ => self.declare_type(resolve, &Type::Id(id))?,
290            }
291        }
292
293        Ok(())
294    }
295
296    fn print_resource(&mut self, resolve: &Resolve, id: TypeId, funcs: &[&Function]) -> Result<()> {
297        let ty = &resolve.types[id];
298        self.output.ty("resource", TypeKind::BuiltIn);
299        self.output.str(" ");
300        self.print_name_type(
301            ty.name.as_ref().expect("resources must be named"),
302            TypeKind::Resource,
303        );
304        if funcs.is_empty() {
305            self.output.semicolon();
306            return Ok(());
307        }
308        self.output.indent_start();
309        for func in funcs {
310            self.print_docs(&func.docs);
311            self.print_stability(&func.stability);
312            self.print_external_id(func.external_id.as_deref());
313
314            match &func.kind {
315                FunctionKind::Constructor(_) => {}
316                FunctionKind::Method(_) | FunctionKind::AsyncMethod(_) => {
317                    self.print_name_type(func.item_name(), TypeKind::FunctionMethod);
318                    self.output.str(": ");
319                }
320                FunctionKind::Static(_) | FunctionKind::AsyncStatic(_) => {
321                    self.print_name_type(func.item_name(), TypeKind::FunctionStatic);
322                    self.output.str(": ");
323                    self.output.keyword("static");
324                    self.output.str(" ");
325                }
326                FunctionKind::Freestanding | FunctionKind::AsyncFreestanding => unreachable!(),
327            }
328            self.print_function(resolve, func)?;
329            self.output.semicolon();
330        }
331        self.output.indent_end();
332
333        Ok(())
334    }
335
336    fn print_function(&mut self, resolve: &Resolve, func: &Function) -> Result<()> {
337        // Handle the `async` prefix if necessary
338        match &func.kind {
339            FunctionKind::AsyncFreestanding
340            | FunctionKind::AsyncMethod(_)
341            | FunctionKind::AsyncStatic(_) => {
342                self.output.keyword("async");
343                self.output.str(" ");
344            }
345            _ => {}
346        }
347
348        // Constructors are named slightly differently.
349        match &func.kind {
350            FunctionKind::Constructor(_) => {
351                self.output.keyword("constructor");
352                self.output.str("(");
353            }
354            FunctionKind::Freestanding
355            | FunctionKind::AsyncFreestanding
356            | FunctionKind::Method(_)
357            | FunctionKind::AsyncMethod(_)
358            | FunctionKind::Static(_)
359            | FunctionKind::AsyncStatic(_) => {
360                self.output.keyword("func");
361                self.output.str("(");
362            }
363        }
364
365        // Methods don't print their `self` argument
366        let params_to_skip = match &func.kind {
367            FunctionKind::Method(_) | FunctionKind::AsyncMethod(_) => 1,
368            _ => 0,
369        };
370        for (i, param) in func.params.iter().skip(params_to_skip).enumerate() {
371            if i > 0 {
372                self.output.str(", ");
373            }
374            self.print_name_param(&param.name);
375            self.output.str(": ");
376            self.print_type_name(resolve, &param.ty)?;
377        }
378        self.output.str(")");
379
380        // shorthand constructors don't have their results printed
381        if func.is_constructor_shorthand(resolve) {
382            return Ok(());
383        }
384
385        if let Some(ty) = &func.result {
386            self.output.str(" -> ");
387            self.print_type_name(resolve, ty)?;
388        }
389        Ok(())
390    }
391
392    /// Prints the world `id` within `resolve`.
393    ///
394    /// This is a little tricky to preserve round-tripping that WIT wants. This
395    /// function inherently can't preserve ordering of imports because resource
396    /// functions aren't guaranteed to be all adjacent to the resource itself
397    /// they're attached to. That means that at the very least, when printing
398    /// resource functions, items may be printed out-of-order.
399    ///
400    /// To help solve this the printing here is kept in sync with WIT encoding
401    /// of worlds which is to print items in the order of:
402    ///
403    /// * Any imported interface. Ordering between interfaces is preserved.
404    /// * Any types, including resource functions on those types. Ordering
405    ///   between types is preserved.
406    /// * Any functions, which may refer to those types. Ordering between
407    ///   functions is preserved.
408    ///
409    /// This keeps things printed in a roughly topological fashion and makes
410    /// round-tripping a bit more reliable.
411    fn print_world(&mut self, resolve: &Resolve, id: WorldId) -> Result<()> {
412        let prev_items = mem::replace(&mut self.any_items, false);
413        let world = &resolve.worlds[id];
414        let pkgid = world.package.unwrap();
415        let mut types = Vec::new();
416        let mut resource_funcs = HashMap::new();
417        let mut function_imports_to_print = Vec::new();
418        for (name, import) in world.imports.iter() {
419            match import {
420                WorldItem::Type { id, .. } => match name {
421                    WorldKey::Name(s) => types.push((s.as_str(), *id)),
422                    WorldKey::Interface(_) => unreachable!(),
423                },
424                _ => {
425                    if let WorldItem::Function(f) = import {
426                        if let Some(id) = f.kind.resource() {
427                            resource_funcs.entry(id).or_insert(Vec::new()).push(f);
428                            continue;
429                        }
430                        function_imports_to_print.push((name, import));
431                        continue;
432                    }
433                    self.print_world_item(resolve, name, import, pkgid, "import")?;
434                    // Don't put a blank line between imports, but count
435                    // imports as having printed something so if anything comes
436                    // after them then a blank line is printed after imports.
437                    self.any_items = true;
438                }
439            }
440        }
441        self.print_types(
442            resolve,
443            TypeOwner::World(id),
444            types.into_iter(),
445            &resource_funcs,
446        )?;
447
448        for (name, import) in function_imports_to_print {
449            self.print_world_item(resolve, name, import, pkgid, "import")?;
450            self.any_items = true;
451        }
452        if !world.exports.is_empty() {
453            self.new_item();
454        }
455        for (name, export) in world.exports.iter() {
456            self.print_world_item(resolve, name, export, pkgid, "export")?;
457        }
458        self.any_items = prev_items;
459        Ok(())
460    }
461
462    fn print_world_item(
463        &mut self,
464        resolve: &Resolve,
465        name: &WorldKey,
466        item: &WorldItem,
467        cur_pkg: PackageId,
468        import_or_export_keyword: &str,
469    ) -> Result<()> {
470        // Print docs for this import/export statement. For interfaces, prefer
471        // the docs attached to the statement itself (`WorldItem::Interface`'s
472        // `docs`); for an inline `import x: interface { .. }` with no statement
473        // docs fall back to the interface definition's docs.
474        let docs = match item {
475            WorldItem::Interface { id, docs, .. } => {
476                if docs.contents.is_some() {
477                    Some(docs)
478                } else if matches!(name, WorldKey::Name(_)) {
479                    Some(&resolve.interfaces[*id].docs)
480                } else {
481                    None
482                }
483            }
484            WorldItem::Function(f) => Some(&f.docs),
485            // Types are handled separately
486            WorldItem::Type { .. } => unreachable!(),
487        };
488        if let Some(docs) = docs {
489            self.print_docs(docs);
490        }
491
492        self.print_stability(item.stability(resolve));
493        self.print_external_id(resolve.external_id_value(name, item).as_deref());
494        self.output.keyword(import_or_export_keyword);
495        self.output.str(" ");
496        match name {
497            WorldKey::Name(name) => {
498                match item {
499                    WorldItem::Interface { id, .. } => {
500                        self.print_name_type(name, TypeKind::Other);
501                        self.output.str(": ");
502                        if resolve.interfaces[*id].name.is_none() {
503                            // `import label: interface { .. }` syntax
504                            self.output.keyword("interface");
505                            self.output.indent_start();
506                            self.print_interface(resolve, *id)?;
507                            self.output.indent_end();
508                        } else {
509                            // `import label: use-path;` syntax
510                            self.print_path_to_interface(resolve, *id, cur_pkg)?;
511                            self.output.semicolon();
512                        }
513                    }
514                    WorldItem::Function(f) => {
515                        self.print_name_type(&f.name, TypeKind::Other);
516                        self.output.str(": ");
517                        self.print_function(resolve, f)?;
518                        self.output.semicolon();
519                    }
520                    // Types are handled separately
521                    WorldItem::Type { .. } => unreachable!(),
522                }
523            }
524            WorldKey::Interface(id) => {
525                match item {
526                    WorldItem::Interface { id: id2, .. } => assert_eq!(id, id2),
527                    _ => unreachable!(),
528                }
529                self.print_path_to_interface(resolve, *id, cur_pkg)?;
530                self.output.semicolon();
531            }
532        }
533        Ok(())
534    }
535
536    fn print_path_to_interface(
537        &mut self,
538        resolve: &Resolve,
539        interface: InterfaceId,
540        cur_pkg: PackageId,
541    ) -> Result<()> {
542        let iface = &resolve.interfaces[interface];
543        if iface.package == Some(cur_pkg) {
544            self.print_name_type(iface.name.as_ref().unwrap(), TypeKind::InterfacePath);
545        } else {
546            let pkg = &resolve.packages[iface.package.unwrap()].name;
547            self.print_name_type(&pkg.namespace, TypeKind::NamespacePath);
548            self.output.str(":");
549            self.print_name_type(&pkg.name, TypeKind::PackageNamePath);
550            self.output.str("/");
551            self.print_name_type(iface.name.as_ref().unwrap(), TypeKind::InterfacePath);
552            if let Some(version) = &pkg.version {
553                self.print_name_type(&format!("@{version}"), TypeKind::VersionPath);
554            }
555        }
556        Ok(())
557    }
558
559    /// Print the name of type `ty`.
560    pub fn print_type_name(&mut self, resolve: &Resolve, ty: &Type) -> Result<()> {
561        match ty {
562            Type::Bool => self.output.ty("bool", TypeKind::BuiltIn),
563            Type::U8 => self.output.ty("u8", TypeKind::BuiltIn),
564            Type::U16 => self.output.ty("u16", TypeKind::BuiltIn),
565            Type::U32 => self.output.ty("u32", TypeKind::BuiltIn),
566            Type::U64 => self.output.ty("u64", TypeKind::BuiltIn),
567            Type::S8 => self.output.ty("s8", TypeKind::BuiltIn),
568            Type::S16 => self.output.ty("s16", TypeKind::BuiltIn),
569            Type::S32 => self.output.ty("s32", TypeKind::BuiltIn),
570            Type::S64 => self.output.ty("s64", TypeKind::BuiltIn),
571            Type::F32 => self.output.ty("f32", TypeKind::BuiltIn),
572            Type::F64 => self.output.ty("f64", TypeKind::BuiltIn),
573            Type::Char => self.output.ty("char", TypeKind::BuiltIn),
574            Type::String => self.output.ty("string", TypeKind::BuiltIn),
575            Type::ErrorContext => self.output.ty("error-context", TypeKind::BuiltIn),
576
577            Type::Id(id) => {
578                let ty = &resolve.types[*id];
579                if let Some(name) = &ty.name {
580                    self.print_name_type(name, TypeKind::Other);
581                    return Ok(());
582                }
583
584                match &ty.kind {
585                    TypeDefKind::Handle(h) => {
586                        self.print_handle_type(resolve, h, false)?;
587                    }
588                    TypeDefKind::Resource => {
589                        bail!("resolve has an unnamed resource type");
590                    }
591                    TypeDefKind::Tuple(t) => {
592                        self.print_tuple_type(resolve, t)?;
593                    }
594                    TypeDefKind::Option(t) => {
595                        self.print_option_type(resolve, t)?;
596                    }
597                    TypeDefKind::Result(t) => {
598                        self.print_result_type(resolve, t)?;
599                    }
600                    TypeDefKind::Record(_) => {
601                        bail!("resolve has an unnamed record type");
602                    }
603                    TypeDefKind::Flags(_) => {
604                        bail!("resolve has unnamed flags type")
605                    }
606                    TypeDefKind::Enum(_) => {
607                        bail!("resolve has unnamed enum type")
608                    }
609                    TypeDefKind::Variant(_) => {
610                        bail!("resolve has unnamed variant type")
611                    }
612                    TypeDefKind::List(ty) => {
613                        self.output.ty("list", TypeKind::BuiltIn);
614                        self.output.generic_args_start();
615                        self.print_type_name(resolve, ty)?;
616                        self.output.generic_args_end();
617                    }
618                    TypeDefKind::Map(key_ty, value_ty) => {
619                        self.output.ty("map", TypeKind::BuiltIn);
620                        self.output.generic_args_start();
621                        self.print_type_name(resolve, key_ty)?;
622                        self.output.str(", ");
623                        self.print_type_name(resolve, value_ty)?;
624                        self.output.generic_args_end();
625                    }
626                    TypeDefKind::FixedLengthList(ty, size) => {
627                        self.output.ty("list", TypeKind::BuiltIn);
628                        self.output.generic_args_start();
629                        self.print_type_name(resolve, ty)?;
630                        self.output.push_str(&format!(", {}", *size));
631                        self.output.generic_args_end();
632                    }
633                    TypeDefKind::Type(ty) => self.print_type_name(resolve, ty)?,
634                    TypeDefKind::Future(ty) => {
635                        if let Some(ty) = ty {
636                            self.output.push_str("future<");
637                            self.print_type_name(resolve, ty)?;
638                            self.output.push_str(">");
639                        } else {
640                            self.output.push_str("future");
641                        }
642                    }
643                    TypeDefKind::Stream(ty) => {
644                        if let Some(ty) = ty {
645                            self.output.push_str("stream<");
646                            self.print_type_name(resolve, ty)?;
647                            self.output.push_str(">");
648                        } else {
649                            self.output.push_str("stream");
650                        }
651                    }
652                    TypeDefKind::Unknown => unreachable!(),
653                }
654            }
655        }
656
657        Ok(())
658    }
659
660    fn print_handle_type(
661        &mut self,
662        resolve: &Resolve,
663        handle: &Handle,
664        force_handle_type_printed: bool,
665    ) -> Result<()> {
666        match handle {
667            Handle::Own(ty) => {
668                let ty = &resolve.types[*ty];
669                if force_handle_type_printed {
670                    self.output.ty("own", TypeKind::BuiltIn);
671                    self.output.generic_args_start();
672                }
673                self.print_name_type(
674                    ty.name
675                        .as_ref()
676                        .ok_or_else(|| anyhow!("unnamed resource type"))?,
677                    TypeKind::Resource,
678                );
679                if force_handle_type_printed {
680                    self.output.generic_args_end();
681                }
682            }
683
684            Handle::Borrow(ty) => {
685                self.output.ty("borrow", TypeKind::BuiltIn);
686                self.output.generic_args_start();
687                let ty = &resolve.types[*ty];
688                self.print_name_type(
689                    ty.name
690                        .as_ref()
691                        .ok_or_else(|| anyhow!("unnamed resource type"))?,
692                    TypeKind::Resource,
693                );
694                self.output.generic_args_end();
695            }
696        }
697
698        Ok(())
699    }
700
701    fn print_tuple_type(&mut self, resolve: &Resolve, tuple: &Tuple) -> Result<()> {
702        self.output.ty("tuple", TypeKind::BuiltIn);
703        self.output.generic_args_start();
704        for (i, ty) in tuple.types.iter().enumerate() {
705            if i > 0 {
706                self.output.str(", ");
707            }
708            self.print_type_name(resolve, ty)?;
709        }
710        self.output.generic_args_end();
711
712        Ok(())
713    }
714
715    fn print_option_type(&mut self, resolve: &Resolve, payload: &Type) -> Result<()> {
716        self.output.ty("option", TypeKind::BuiltIn);
717        self.output.generic_args_start();
718        self.print_type_name(resolve, payload)?;
719        self.output.generic_args_end();
720        Ok(())
721    }
722
723    fn print_result_type(&mut self, resolve: &Resolve, result: &Result_) -> Result<()> {
724        match result {
725            Result_ {
726                ok: Some(ok),
727                err: Some(err),
728            } => {
729                self.output.ty("result", TypeKind::BuiltIn);
730                self.output.generic_args_start();
731                self.print_type_name(resolve, ok)?;
732                self.output.str(", ");
733                self.print_type_name(resolve, err)?;
734                self.output.generic_args_end();
735            }
736            Result_ {
737                ok: None,
738                err: Some(err),
739            } => {
740                self.output.ty("result", TypeKind::BuiltIn);
741                self.output.generic_args_start();
742                self.output.str("_, ");
743                self.print_type_name(resolve, err)?;
744                self.output.generic_args_end();
745            }
746            Result_ {
747                ok: Some(ok),
748                err: None,
749            } => {
750                self.output.ty("result", TypeKind::BuiltIn);
751                self.output.generic_args_start();
752                self.print_type_name(resolve, ok)?;
753                self.output.generic_args_end();
754            }
755            Result_ {
756                ok: None,
757                err: None,
758            } => {
759                self.output.ty("result", TypeKind::BuiltIn);
760            }
761        }
762        Ok(())
763    }
764
765    fn declare_type(&mut self, resolve: &Resolve, ty: &Type) -> Result<()> {
766        match ty {
767            Type::Bool
768            | Type::U8
769            | Type::U16
770            | Type::U32
771            | Type::U64
772            | Type::S8
773            | Type::S16
774            | Type::S32
775            | Type::S64
776            | Type::F32
777            | Type::F64
778            | Type::Char
779            | Type::String
780            | Type::ErrorContext => return Ok(()),
781
782            Type::Id(id) => {
783                let ty = &resolve.types[*id];
784                match &ty.kind {
785                    TypeDefKind::Handle(h) => {
786                        self.declare_handle(resolve, ty.name.as_deref(), h)?
787                    }
788                    TypeDefKind::Resource => panic!("resources should be processed separately"),
789                    TypeDefKind::Record(r) => {
790                        self.declare_record(resolve, ty.name.as_deref(), r)?
791                    }
792                    TypeDefKind::Tuple(t) => self.declare_tuple(resolve, ty.name.as_deref(), t)?,
793                    TypeDefKind::Flags(f) => self.declare_flags(ty.name.as_deref(), f)?,
794                    TypeDefKind::Variant(v) => {
795                        self.declare_variant(resolve, ty.name.as_deref(), v)?
796                    }
797                    TypeDefKind::Option(t) => {
798                        self.declare_option(resolve, ty.name.as_deref(), t)?
799                    }
800                    TypeDefKind::Result(r) => {
801                        self.declare_result(resolve, ty.name.as_deref(), r)?
802                    }
803                    TypeDefKind::Enum(e) => self.declare_enum(ty.name.as_deref(), e)?,
804                    TypeDefKind::List(inner) => {
805                        self.declare_list(resolve, ty.name.as_deref(), inner)?
806                    }
807                    TypeDefKind::Map(key, value) => {
808                        self.declare_map(resolve, ty.name.as_deref(), key, value)?
809                    }
810                    TypeDefKind::FixedLengthList(inner, size) => {
811                        self.declare_fixed_length_list(resolve, ty.name.as_deref(), inner, *size)?
812                    }
813                    TypeDefKind::Type(inner) => match ty.name.as_deref() {
814                        Some(name) => {
815                            self.output.keyword("type");
816                            self.output.str(" ");
817                            self.print_name_type(name, TypeKind::TypeName);
818                            self.output.str(" = ");
819                            self.print_type_name(resolve, inner)?;
820                            self.output.semicolon();
821                        }
822                        None => bail!("unnamed type in document"),
823                    },
824                    TypeDefKind::Future(inner) => {
825                        self.declare_future(resolve, ty.name.as_deref(), inner.as_ref())?
826                    }
827                    TypeDefKind::Stream(inner) => {
828                        self.declare_stream(resolve, ty.name.as_deref(), inner.as_ref())?
829                    }
830                    TypeDefKind::Unknown => unreachable!(),
831                }
832            }
833        }
834        Ok(())
835    }
836
837    fn declare_handle(
838        &mut self,
839        resolve: &Resolve,
840        name: Option<&str>,
841        handle: &Handle,
842    ) -> Result<()> {
843        match name {
844            Some(name) => {
845                self.output.keyword("type");
846                self.output.str(" ");
847                self.print_name_type(name, TypeKind::Resource);
848                self.output.str(" = ");
849                // Note that the `true` here forces owned handles to be printed
850                // as `own<T>`. The purpose of this is because `type a = b`, if
851                // `b` is a resource, is encoded differently as `type a =
852                // own<b>`. By forcing a handle to be printed here it's staying
853                // true to what's in the WIT document.
854                self.print_handle_type(resolve, handle, true)?;
855                self.output.semicolon();
856
857                Ok(())
858            }
859            None => bail!("document has unnamed handle type"),
860        }
861    }
862
863    fn declare_record(
864        &mut self,
865        resolve: &Resolve,
866        name: Option<&str>,
867        record: &Record,
868    ) -> Result<()> {
869        match name {
870            Some(name) => {
871                self.output.keyword("record");
872                self.output.str(" ");
873                self.print_name_type(name, TypeKind::Record);
874                self.output.indent_start();
875                for field in &record.fields {
876                    self.print_docs(&field.docs);
877                    self.print_name_param(&field.name);
878                    self.output.str(": ");
879                    self.print_type_name(resolve, &field.ty)?;
880                    self.output.str(",");
881                    self.output.newline();
882                }
883                self.output.indent_end();
884                Ok(())
885            }
886            None => bail!("document has unnamed record type"),
887        }
888    }
889
890    fn declare_tuple(
891        &mut self,
892        resolve: &Resolve,
893        name: Option<&str>,
894        tuple: &Tuple,
895    ) -> Result<()> {
896        if let Some(name) = name {
897            self.output.keyword("type");
898            self.output.str(" ");
899            self.print_name_type(name, TypeKind::Tuple);
900            self.output.str(" = ");
901            self.print_tuple_type(resolve, tuple)?;
902            self.output.semicolon();
903        }
904        Ok(())
905    }
906
907    fn declare_flags(&mut self, name: Option<&str>, flags: &Flags) -> Result<()> {
908        match name {
909            Some(name) => {
910                self.output.keyword("flags");
911                self.output.str(" ");
912                self.print_name_type(name, TypeKind::Flags);
913                self.output.indent_start();
914                for flag in &flags.flags {
915                    self.print_docs(&flag.docs);
916                    self.print_name_case(&flag.name);
917                    self.output.str(",");
918                    self.output.newline();
919                }
920                self.output.indent_end();
921            }
922            None => bail!("document has unnamed flags type"),
923        }
924        Ok(())
925    }
926
927    fn declare_variant(
928        &mut self,
929        resolve: &Resolve,
930        name: Option<&str>,
931        variant: &Variant,
932    ) -> Result<()> {
933        let name = match name {
934            Some(name) => name,
935            None => bail!("document has unnamed variant type"),
936        };
937        self.output.keyword("variant");
938        self.output.str(" ");
939        self.print_name_type(name, TypeKind::Variant);
940        self.output.indent_start();
941        for case in &variant.cases {
942            self.print_docs(&case.docs);
943            self.print_name_case(&case.name);
944            if let Some(ty) = case.ty {
945                self.output.str("(");
946                self.print_type_name(resolve, &ty)?;
947                self.output.str(")");
948            }
949            self.output.str(",");
950            self.output.newline();
951        }
952        self.output.indent_end();
953        Ok(())
954    }
955
956    fn declare_option(
957        &mut self,
958        resolve: &Resolve,
959        name: Option<&str>,
960        payload: &Type,
961    ) -> Result<()> {
962        if let Some(name) = name {
963            self.output.keyword("type");
964            self.output.str(" ");
965            self.print_name_type(name, TypeKind::Option);
966            self.output.str(" = ");
967            self.print_option_type(resolve, payload)?;
968            self.output.semicolon();
969        }
970        Ok(())
971    }
972
973    fn declare_result(
974        &mut self,
975        resolve: &Resolve,
976        name: Option<&str>,
977        result: &Result_,
978    ) -> Result<()> {
979        if let Some(name) = name {
980            self.output.keyword("type");
981            self.output.str(" ");
982            self.print_name_type(name, TypeKind::Result);
983            self.output.str(" = ");
984            self.print_result_type(resolve, result)?;
985            self.output.semicolon();
986        }
987        Ok(())
988    }
989
990    fn declare_enum(&mut self, name: Option<&str>, enum_: &Enum) -> Result<()> {
991        let name = match name {
992            Some(name) => name,
993            None => bail!("document has unnamed enum type"),
994        };
995        self.output.keyword("enum");
996        self.output.str(" ");
997        self.print_name_type(name, TypeKind::Enum);
998        self.output.indent_start();
999        for case in &enum_.cases {
1000            self.print_docs(&case.docs);
1001            self.print_name_case(&case.name);
1002            self.output.str(",");
1003            self.output.newline();
1004        }
1005        self.output.indent_end();
1006        Ok(())
1007    }
1008
1009    fn declare_list(&mut self, resolve: &Resolve, name: Option<&str>, ty: &Type) -> Result<()> {
1010        if let Some(name) = name {
1011            self.output.keyword("type");
1012            self.output.str(" ");
1013            self.print_name_type(name, TypeKind::List);
1014            self.output.str(" = ");
1015            self.output.ty("list", TypeKind::BuiltIn);
1016            self.output.str("<");
1017            self.print_type_name(resolve, ty)?;
1018            self.output.str(">");
1019            self.output.semicolon();
1020            return Ok(());
1021        }
1022
1023        Ok(())
1024    }
1025
1026    fn declare_map(
1027        &mut self,
1028        resolve: &Resolve,
1029        name: Option<&str>,
1030        key_ty: &Type,
1031        value_ty: &Type,
1032    ) -> Result<()> {
1033        if let Some(name) = name {
1034            self.output.keyword("type");
1035            self.output.str(" ");
1036            self.print_name_type(name, TypeKind::Map);
1037            self.output.str(" = ");
1038            self.output.ty("map", TypeKind::BuiltIn);
1039            self.output.str("<");
1040            self.print_type_name(resolve, key_ty)?;
1041            self.output.str(", ");
1042            self.print_type_name(resolve, value_ty)?;
1043            self.output.str(">");
1044            self.output.semicolon();
1045            return Ok(());
1046        }
1047
1048        Ok(())
1049    }
1050
1051    fn declare_fixed_length_list(
1052        &mut self,
1053        resolve: &Resolve,
1054        name: Option<&str>,
1055        ty: &Type,
1056        elements: u32,
1057    ) -> Result<()> {
1058        if let Some(name) = name {
1059            self.output.keyword("type");
1060            self.output.str(" ");
1061            self.print_name_type(name, TypeKind::List);
1062            self.output.str(" = ");
1063            self.output.ty("list", TypeKind::BuiltIn);
1064            self.output.str("<");
1065            self.print_type_name(resolve, ty)?;
1066            self.output.str(&format!(", {elements}"));
1067            self.output.str(">");
1068            self.output.semicolon();
1069            return Ok(());
1070        }
1071
1072        Ok(())
1073    }
1074
1075    fn declare_stream(
1076        &mut self,
1077        resolve: &Resolve,
1078        name: Option<&str>,
1079        ty: Option<&Type>,
1080    ) -> Result<()> {
1081        if let Some(name) = name {
1082            self.output.keyword("type");
1083            self.output.str(" ");
1084            self.print_name_type(name, TypeKind::Stream);
1085            self.output.str(" = ");
1086            self.output.ty("stream", TypeKind::BuiltIn);
1087            if let Some(ty) = ty {
1088                self.output.str("<");
1089                self.print_type_name(resolve, ty)?;
1090                self.output.str(">");
1091            }
1092            self.output.semicolon();
1093        }
1094
1095        Ok(())
1096    }
1097
1098    fn declare_future(
1099        &mut self,
1100        resolve: &Resolve,
1101        name: Option<&str>,
1102        ty: Option<&Type>,
1103    ) -> Result<()> {
1104        if let Some(name) = name {
1105            self.output.keyword("type");
1106            self.output.str(" ");
1107            self.print_name_type(name, TypeKind::Future);
1108            self.output.str(" = ");
1109            self.output.ty("future", TypeKind::BuiltIn);
1110            if let Some(ty) = ty {
1111                self.output.str("<");
1112                self.print_type_name(resolve, ty)?;
1113                self.output.str(">");
1114            }
1115            self.output.semicolon();
1116        }
1117
1118        Ok(())
1119    }
1120
1121    fn escape_name(name: &str) -> Cow<'_, str> {
1122        if is_keyword(name) {
1123            Cow::Owned(format!("%{name}"))
1124        } else {
1125            Cow::Borrowed(name)
1126        }
1127    }
1128
1129    fn print_name_type(&mut self, name: &str, kind: TypeKind) {
1130        self.output.ty(Self::escape_name(name).deref(), kind);
1131    }
1132
1133    fn print_name_param(&mut self, name: &str) {
1134        self.output.param(Self::escape_name(name).deref());
1135    }
1136
1137    fn print_name_case(&mut self, name: &str) {
1138        self.output.case(Self::escape_name(name).deref());
1139    }
1140
1141    fn print_docs(&mut self, docs: &Docs) {
1142        if self.emit_docs {
1143            if let Some(contents) = &docs.contents {
1144                for line in contents.lines() {
1145                    self.output.doc(line);
1146                }
1147            }
1148        }
1149    }
1150
1151    fn print_stability(&mut self, stability: &Stability) {
1152        match stability {
1153            Stability::Unknown => {}
1154            Stability::Stable { since, deprecated } => {
1155                self.output.keyword("@since");
1156                self.output.str("(");
1157                self.output.keyword("version");
1158                self.output.str(" = ");
1159                self.print_name_type(&since.to_string(), TypeKind::VersionAnnotation);
1160                self.output.str(")");
1161                self.output.newline();
1162                if let Some(version) = deprecated {
1163                    self.output.keyword("@deprecated");
1164                    self.output.str("(");
1165                    self.output.keyword("version");
1166                    self.output.str(" = ");
1167                    self.print_name_type(&version.to_string(), TypeKind::VersionAnnotation);
1168                    self.output.str(")");
1169                    self.output.newline();
1170                }
1171            }
1172            Stability::Unstable {
1173                feature,
1174                deprecated,
1175            } => {
1176                self.output.keyword("@unstable");
1177                self.output.str("(");
1178                self.output.keyword("feature");
1179                self.output.str(" = ");
1180                self.output.str(feature);
1181                self.output.str(")");
1182                self.output.newline();
1183                if let Some(version) = deprecated {
1184                    self.output.keyword("@deprecated");
1185                    self.output.str("(");
1186                    self.output.keyword("version");
1187                    self.output.str(" = ");
1188                    self.print_name_type(&version.to_string(), TypeKind::VersionAnnotation);
1189                    self.output.str(")");
1190                    self.output.newline();
1191                }
1192            }
1193        }
1194    }
1195
1196    fn print_external_id(&mut self, id: Option<&str>) {
1197        let Some(id) = id else {
1198            return;
1199        };
1200        self.output.keyword("@external-id");
1201        self.output.str("(\"");
1202        let mut buf = [0; 4];
1203        for c in id.chars() {
1204            if c.is_ascii_alphanumeric()
1205                || c == '-'
1206                || c == '_'
1207                || c == '.'
1208                || c == '/'
1209                || c == ':'
1210                || c == ' '
1211            {
1212                self.output.push_str(c.encode_utf8(&mut buf));
1213                continue;
1214            }
1215            match c {
1216                '\\' => self.output.push_str("\\\\"),
1217                '"' => self.output.push_str("\\\""),
1218                '\n' => self.output.push_str("\\n"),
1219                '\r' => self.output.push_str("\\r"),
1220                '\t' => self.output.push_str("\\t"),
1221                _ => {
1222                    self.output.push_str(&format!("\\u{{{:x}}}", c as u32));
1223                }
1224            }
1225        }
1226        self.output.str("\")");
1227        self.output.newline();
1228    }
1229}
1230
1231fn is_keyword(name: &str) -> bool {
1232    matches!(
1233        name,
1234        "use"
1235            | "type"
1236            | "func"
1237            | "u8"
1238            | "u16"
1239            | "u32"
1240            | "u64"
1241            | "s8"
1242            | "s16"
1243            | "s32"
1244            | "s64"
1245            | "f32"
1246            | "f64"
1247            | "float32"
1248            | "float64"
1249            | "char"
1250            | "resource"
1251            | "record"
1252            | "flags"
1253            | "variant"
1254            | "enum"
1255            | "bool"
1256            | "string"
1257            | "option"
1258            | "result"
1259            | "future"
1260            | "stream"
1261            | "list"
1262            | "own"
1263            | "borrow"
1264            | "_"
1265            | "as"
1266            | "from"
1267            | "static"
1268            | "interface"
1269            | "tuple"
1270            | "world"
1271            | "import"
1272            | "export"
1273            | "package"
1274            | "with"
1275            | "include"
1276            | "constructor"
1277            | "error-context"
1278            | "async"
1279            | "map"
1280    )
1281}
1282
1283/// Trait defining visitor methods driven by [`WitPrinter`](WitPrinter).
1284///
1285/// Some methods in this trait have default implementations. These default
1286/// implementations may rely on helper functions that are not
1287/// invoked directly by `WitPrinter`.
1288pub trait Output {
1289    /// Push a string slice into a buffer or an output.
1290    ///
1291    /// Parameter `src` can contain punctuation characters, and must be escaped
1292    /// when outputting to languages like HTML.
1293    /// Helper function used exclusively by the default implementations of trait methods.
1294    /// This function is not called directly by `WitPrinter`.
1295    /// When overriding all the trait methods, users do not need to handle this function.
1296    fn push_str(&mut self, src: &str);
1297
1298    /// Set the appropriate indentation.
1299    ///
1300    /// Helper function used exclusively by the default implementations of trait methods.
1301    /// This function is not called directly by `WitPrinter`.
1302    /// When overriding all the trait methods, users do not need to handle this function.
1303    fn indent_if_needed(&mut self) -> bool;
1304
1305    /// Start of indentation. In WIT this represents ` {\n`.
1306    fn indent_start(&mut self);
1307
1308    /// End of indentation. In WIT this represents `}\n`.
1309    fn indent_end(&mut self);
1310
1311    /// This method is designed to be used only by the default methods of this trait.
1312    /// Called only from the default implementation functions of this trait.
1313    fn indent_and_print(&mut self, src: &str) {
1314        assert!(!src.contains('\n'));
1315        let indented = self.indent_if_needed();
1316        if indented && src.starts_with(' ') {
1317            panic!("cannot add a space at the beginning of a line");
1318        }
1319        self.push_str(src);
1320    }
1321
1322    /// A newline is added.
1323    fn newline(&mut self);
1324
1325    /// A keyword is added. Keywords are hardcoded strings from `[a-z]`, but can start with `@`
1326    /// when printing a [Feature Gate](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md#feature-gates)
1327    fn keyword(&mut self, src: &str) {
1328        self.indent_and_print(src);
1329    }
1330
1331    /// A type is added.
1332    fn ty(&mut self, src: &str, _kind: TypeKind) {
1333        self.indent_and_print(src);
1334    }
1335
1336    /// A parameter name of a function, record or a named return is added.
1337    fn param(&mut self, src: &str) {
1338        self.indent_and_print(src);
1339    }
1340
1341    /// A case belonging to a variant, enum or flags is added.
1342    fn case(&mut self, src: &str) {
1343        self.indent_and_print(src);
1344    }
1345
1346    /// Generic argument section starts. In WIT this represents the `<` character.
1347    fn generic_args_start(&mut self) {
1348        assert!(
1349            !self.indent_if_needed(),
1350            "`generic_args_start` is never called after newline"
1351        );
1352        self.push_str("<");
1353    }
1354
1355    /// Generic argument section ends. In WIT this represents the '>' character.
1356    fn generic_args_end(&mut self) {
1357        assert!(
1358            !self.indent_if_needed(),
1359            "`generic_args_end` is never called after newline"
1360        );
1361        self.push_str(">");
1362    }
1363
1364    /// Called when a single documentation line is added.
1365    /// The `doc` parameter starts with `///` omitted, and can be an empty string.
1366    fn doc(&mut self, doc: &str) {
1367        assert!(!doc.contains('\n'));
1368        self.indent_if_needed();
1369        self.push_str("///");
1370        if !doc.is_empty() {
1371            self.push_str(" ");
1372            self.push_str(doc);
1373        }
1374        self.newline();
1375    }
1376
1377    /// A semicolon is added.
1378    fn semicolon(&mut self) {
1379        assert!(
1380            !self.indent_if_needed(),
1381            "`semicolon` is never called after newline"
1382        );
1383        self.push_str(";");
1384        self.newline();
1385    }
1386
1387    /// Any string that does not have a specialized function is added.
1388    /// Parameter `src` can contain punctuation characters, and must be escaped
1389    /// when outputting to languages like HTML.
1390    fn str(&mut self, src: &str) {
1391        self.indent_and_print(src);
1392    }
1393}
1394
1395/// Represents the different kinds of types that can be encountered while
1396/// visiting a WIT file.
1397///
1398/// Each variant refers to the name of the respective element (e.g., function, type, or namespace),
1399/// not the entire declaration.
1400#[non_exhaustive]
1401#[derive(Clone, Copy, Debug)]
1402pub enum TypeKind {
1403    /// A built-in type, such as "list" or "option".
1404    BuiltIn,
1405    /// An enumeration type name.
1406    Enum,
1407    /// An error-context type name.
1408    ErrorContext,
1409    /// A flags type name.
1410    Flags,
1411    /// A freestanding function name, not associated with any specific type or namespace.
1412    /// For example, "myfunc" in `myfunc: func() -> string;`.
1413    FunctionFreestanding,
1414    /// A method, associated with a resource.
1415    FunctionMethod,
1416    /// A static function, associated with a resource.
1417    FunctionStatic,
1418    /// A future type name.
1419    Future,
1420    /// An interface declaration name.
1421    InterfaceDeclaration,
1422    /// An interface name when printing a path, for example in `use`.
1423    InterfacePath,
1424    /// A list type name.
1425    List,
1426    /// A map type name.
1427    Map,
1428    /// A namespace declaration.
1429    NamespaceDeclaration,
1430    /// A namespace when printing a path, for example in `use`.
1431    NamespacePath,
1432    /// An option type name.
1433    Option,
1434    /// A package name declaration.
1435    PackageNameDeclaration,
1436    /// A package name when printing a path, for example in `use`.
1437    PackageNamePath,
1438    /// A record type name.
1439    Record,
1440    /// A resource type name.
1441    Resource,
1442    /// A result type name.
1443    Result,
1444    /// A stream type name.
1445    Stream,
1446    /// A tuple type name.
1447    Tuple,
1448    /// A type alias.
1449    TypeAlias,
1450    /// An imported type name.
1451    TypeImport,
1452    /// A user-defined type name.
1453    TypeName,
1454    /// A variant type name.
1455    Variant,
1456    /// A version declaration.
1457    VersionDeclaration,
1458    /// A version when printing a path, for example in `use`.
1459    VersionPath,
1460    /// A version when printing stability annotations, for example in `@since`
1461    VersionAnnotation,
1462    /// A world declaration name.
1463    WorldDeclaration,
1464    /// A fallback for types that do not fit into any other category.
1465    Other,
1466}
1467
1468/// Helper structure to help maintain an indentation level when printing source,
1469/// modeled after the support in `wit-bindgen-core`. Indentation is set to two spaces.
1470#[derive(Default)]
1471pub struct OutputToString {
1472    indent: usize,
1473    output: String,
1474    // set to true after newline, then to false after first item is indented.
1475    needs_indent: bool,
1476}
1477
1478impl Output for OutputToString {
1479    fn push_str(&mut self, src: &str) {
1480        self.output.push_str(src);
1481    }
1482
1483    fn indent_if_needed(&mut self) -> bool {
1484        if self.needs_indent {
1485            for _ in 0..self.indent {
1486                // Indenting by two spaces.
1487                self.output.push_str("  ");
1488            }
1489            self.needs_indent = false;
1490            true
1491        } else {
1492            false
1493        }
1494    }
1495
1496    fn indent_start(&mut self) {
1497        assert!(
1498            !self.needs_indent,
1499            "`indent_start` is never called after newline"
1500        );
1501        self.output.push_str(" {");
1502        self.indent += 1;
1503        self.newline();
1504    }
1505
1506    fn indent_end(&mut self) {
1507        // Note that a `saturating_sub` is used here to prevent a panic
1508        // here in the case of invalid code being generated in debug
1509        // mode. It's typically easier to debug those issues through
1510        // looking at the source code rather than getting a panic.
1511        self.indent = self.indent.saturating_sub(1);
1512        self.indent_if_needed();
1513        self.output.push('}');
1514        self.newline();
1515    }
1516
1517    fn newline(&mut self) {
1518        self.output.push('\n');
1519        self.needs_indent = true;
1520    }
1521}
1522
1523impl From<OutputToString> for String {
1524    fn from(output: OutputToString) -> String {
1525        output.output
1526    }
1527}
1528
1529impl Display for OutputToString {
1530    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1531        self.output.fmt(f)
1532    }
1533}