Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Rust Cookbook

Practical, copy-paste-ready recipes for Rust code generation. For the full API of each spec type, see Building Functions & Fields, Building Types & Enums, and Files & Projects.

Struct with impl

use sigil_stitch::prelude::*;

let body = CodeBlock::of("Self { name: name.into(), port }", ()).unwrap();

let type_spec = TypeSpec::builder("Config", TypeKind::Struct)
    .visibility(Visibility::Public)
    .add_field(
        FieldSpec::builder("name", TypeName::primitive("String"))
            .visibility(Visibility::Public)
            .build()
            .unwrap(),
    )
    .add_field(
        FieldSpec::builder("port", TypeName::primitive("u16"))
            .visibility(Visibility::Public)
            .build()
            .unwrap(),
    )
    .add_method(
        FunSpec::builder("new")
            .visibility(Visibility::Public)
            .add_param(ParameterSpec::new("name", TypeName::primitive("&str")).unwrap())
            .add_param(ParameterSpec::new("port", TypeName::primitive("u16")).unwrap())
            .returns(TypeName::primitive("Self"))
            .body(body)
            .build()
            .unwrap(),
    )
    .build()
    .unwrap();
#![allow(unused)]
fn main() {
pub struct Config {
    pub name: String,
    pub port: u16,
}

impl Config {
    pub fn new(name: &str, port: u16) -> Self {
        Self { name: name.into(), port }
    }
}
}

Enum with variants

use sigil_stitch::prelude::*;
use sigil_stitch::spec::enum_variant_spec::EnumVariantSpec;

let type_spec = TypeSpec::builder("Expr", TypeKind::Enum)
    .visibility(Visibility::Public)
    .add_variant(EnumVariantSpec::new("Nil").unwrap())
    .add_variant(
        EnumVariantSpec::builder("Literal")
            .associated_type(TypeName::primitive("i64"))
            .build()
            .unwrap(),
    )
    .add_variant(
        EnumVariantSpec::builder("Binary")
            .add_field(FieldSpec::builder("left", TypeName::primitive("Box<Expr>")).build().unwrap())
            .add_field(FieldSpec::builder("op", TypeName::primitive("Op")).build().unwrap())
            .add_field(FieldSpec::builder("right", TypeName::primitive("Box<Expr>")).build().unwrap())
            .build()
            .unwrap(),
    )
    .build()
    .unwrap();
#![allow(unused)]
fn main() {
pub enum Expr {
    Nil,
    Literal(i64),
    Binary {
        left: Box<Expr>,
        op: Op,
        right: Box<Expr>,
    },
}
}

Newtype

use sigil_stitch::prelude::*;

let type_spec = TypeSpec::builder("Meters", TypeKind::Newtype)
    .visibility(Visibility::Public)
    .extends(TypeName::primitive("f64"))
    .build()
    .unwrap();
#![allow(unused)]
fn main() {
pub struct Meters(f64);
}

Trait

use sigil_stitch::prelude::*;

let type_spec = TypeSpec::builder("Summary", TypeKind::Trait)
    .visibility(Visibility::Public)
    .add_method(
        FunSpec::builder("summarize")
            .add_param(ParameterSpec::new("&self", TypeName::primitive("")).unwrap())
            .returns(TypeName::primitive("String"))
            .build()
            .unwrap(),
    )
    .add_method(
        FunSpec::builder("preview")
            .add_param(ParameterSpec::new("&self", TypeName::primitive("")).unwrap())
            .returns(TypeName::primitive("String"))
            .body(CodeBlock::of("self.summarize()[..50].to_string()", ()).unwrap())
            .build()
            .unwrap(),
    )
    .build()
    .unwrap();
#![allow(unused)]
fn main() {
pub trait Summary {
    fn summarize(&self) -> String;

    fn preview(&self) -> String {
        self.summarize()[..50].to_string()
    }
}
}

Type alias

use sigil_stitch::prelude::*;

let type_spec = TypeSpec::builder("Result", TypeKind::TypeAlias)
    .visibility(Visibility::Public)
    .add_type_param(TypeParamSpec::new("T"))
    .extends(TypeName::generic(
        TypeName::primitive("std::result::Result"),
        vec![TypeName::primitive("T"), TypeName::primitive("MyError")],
    ))
    .build()
    .unwrap();
#![allow(unused)]
fn main() {
pub type Result<T> = std::result::Result<T, MyError>;
}

Qualified paths (no import)

Use TypeName::qualified() to render types with their full module path inline without generating a use statement:

use sigil_stitch::prelude::*;

let field = FieldSpec::builder("data", TypeName::qualified("serde_json", "Value"))
    .visibility(Visibility::Public)
    .build()
    .unwrap();

// In a generic:
let map_type = TypeName::generic(
    TypeName::qualified("std::collections", "HashMap"),
    vec![
        TypeName::primitive("String"),
        TypeName::qualified("serde_json", "Value"),
    ],
);
#![allow(unused)]
fn main() {
pub data: serde_json::Value

std::collections::HashMap<String, serde_json::Value>
}