Skip to content

Latest commit

 

History

History
70 lines (53 loc) · 3.12 KB

README.md

File metadata and controls

70 lines (53 loc) · 3.12 KB

codespace

codespace on crates.io Documentation (latest release) License

Structural scratch space for generated Rust code

Overview

Code generators that emit raw TokenStreams face a practical problem: a single type definition often requires several top-level items--the struct or enum itself, impl blocks, helper functions, etc. Some of them live together; others live somewhere else entirely (a serde default helper in a defaults module, say). Emitting everything into one flat stream makes related items drift apart; routing some output into separate mods involves annoying bookkeeping.

codespace holds the code during generation. A Codespace owns a tree of Mods; each Mod holds named items (opaque TokenStream fragments) and named (Mod) submodules. Items are added under a "::"-delimited path--intermediate segments name modules; the final segment is a sort key that is never emitted:

use codespace::Codespace;
use quote::quote;

let mut cs = Codespace::default();
cs.add_item("Status", quote! { pub enum Status { Active, Inactive } });
cs.add_item("defaults::status_default", quote! {
    pub fn status_default() -> Status { Status::Active }
});

Adding an item under an existing key appends those tokens, so a type and its impl blocks can accumulate separately and still render together. Each Mod also carries optional metadata: visibility, doc paragraphs, attributes.

codespace never parses, validates, or understands the fragments it holds, and makes no naming decisions. Module names are the exception--invalid names (including Rust keywords) are caller bugs and panic. See the crate docs for details.

Output

Generators can output tokens into a single TokenStream with Codespace::into_stream or into multiple files with Codespace::into_files, where each TokenStream is intended for a particular file path. The former is good for proc macro implementation or calls from a build.rs file; the latter can be well-suited for a stand-alone crate generator.

Both forms are deterministic and unformatted. Callers process the emitted TokenStreams and apply formatting as needed with rustfmt or prettyplease.

Dependencies

A Codespace may also include the external dependencies that its code requires. Generators register what they emit with Codespace::add_dependency; entries are kept by the identifier the code uses, and registrations under one identifier merge. Nesting one codespace in another with Codespace::add_mod_from_codespace carries its list along, and Codespace::to_toml_dependencies writes the [dependencies] section of a Cargo.toml for everything registered. codespace never infers a dependency from the code it holds.

Notes

  • Early alpha; API unstable.
  • Part of the typify/progenitor code-generation stack.