seferize

Crates.ioseferize
lib.rsseferize
version1.5.6
created_at2025-10-10 02:09:25.392844+00
updated_at2025-10-25 19:16:43.319041+00
descriptionProcedural macro for converting Rust code blocks into string constants for reflection or documentation generation.
homepage
repositoryhttps://github.com/patrickfp93/seferize
max_upload_size
id1876430
size23,802
Patrick Fernandes PeΓ§anha (patrickfp93)

documentation

README

πŸ“œ SEFERIZE

"Revealing the written form of your Rust code." ✨

A procedural macro that converts any Rust item (struct, enum, trait, impl, fields, variants, methods, etc.) into its string representation at compile time.

It can automatically generate a &'static str constant with the textual content of the item β€” useful for reflection, documentation generation, code generation tests,code introspection, or debugging macro systems.


🧩 Features

  • βœ… Converts entire Rust items (structs, traits, impls, enums, fields, variants, methods, etc.) into strings.
  • βœ… Removes self-invoking macros from within the processed item.
  • βœ… Supports the attribute #[ignore] to exclude specific items or blocks from being stringified.
  • 🧱 Optionally accepts a custom name for the generated string constant.
  • πŸ” Supports stringification of inner elements (fields, variants, or methods) using #[stringify].
  • πŸ’¬ Accepts both quoted and unquoted identifiers: #[stringify("TEXT")] or #[stringify(TEXT)].
  • ⚑ Works at compile time β€” no runtime cost.
  • πŸ•ŠοΈ 100% safe and pure Rust.
  • πŸ§ͺ New: #[expose_for_tests] attribute to generate a public version of private functions only for tests, keeping the original function private.

🧠 How it works

When you annotate an item with #[stringify], it generates a &'static str constant containing the exact Rust source of that item. By default, the generated constant name follows the pattern CODE_<ITEM_NAME> unless another name is provided.

Example

use seferize::stringify;

#[stringify]
pub struct User {
    id: u32,
    name: String,
}

Generates:

pub const CODE_USER: &str = "pub struct User { id: u32, name: String }";

🧱 Using inside structs, enums, and impl blocks

You can apply #[stringify] directly to fields, enum variants, or methods inside an item annotated with #[stringify]. Each annotated element will generate its own &'static str constant alongside the main one.

Example β€” inside a struct

use seferize::stringify;

#[stringify]
pub struct ExtractStruct {
    pub field_1: usize,
    #[stringify("FIELD_2")]
    pub field_2: String,
}

Produces:

pub const CODE_EXTRACT_STRUCT: &'static str =
    "pub struct ExtractStruct { pub field_1: usize, pub field_2: String, }";

pub const FIELD_2: &'static str = "pub field_2: String";

pub struct ExtractStruct {
    pub field_1: usize,
    pub field_2: String,
}

The same logic applies to enum variants and impl methods.


πŸ§ͺ Exposing private functions for tests

Use the #[expose_for_tests] attribute to generate a public version of a private function that is only available in test builds (#[cfg(test)]). The original function stays private and encapsulated.

Example

use seferize::expose_for_tests;

struct MyStruct;

impl MyStruct {
    #[expose_for_tests]
    fn hidden(&self) -> i32 {
        42
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn can_call_hidden() {
        let s = MyStruct;
        // Call the public test version
        assert_eq!(s.test_hidden(), 42);
    }
}

πŸ’¬ Attribute flexibility

The #[stringify] attribute accepts both quoted and unquoted identifiers for naming the generated constant:

#[stringify("CUSTOM_NAME")]
// or
#[stringify(CUSTOM_NAME)]

Both produce the same result:

pub const CUSTOM_NAME: &str = "...";

🚫 Ignoring code with #[ignore]

Mark any item, block, or function with #[ignore] to prevent it from being included in the generated string.

Example β€” ignoring items

use seferize::stringify;

#[stringify]
mod my_module {
    pub struct Visible {
        field: i32,
    }

    #[ignore]
    pub fn hidden_fn() {
        println!("This function won't appear in CODE_MY_MODULE");
    }
}

Generates:

pub const CODE_MY_MODULE: &str = r#"
mod my_module {
    pub struct Visible {
        field: i32,
    }
}
"#;

βš™οΈ Advanced usage

Custom constant name

Override the generated name by passing a custom identifier:

use seferize::stringify;

#[stringify("CUSTOM_NAME")]
pub enum Event {
    Created,
    Updated,
}

Produces:

pub const CUSTOM_NAME: &str = "pub enum Event { Created, Updated }";

πŸͺΆ Internal behavior

  • Macros like seferize::stringify, stringify, seferize::ignore, and ignore are removed before string generation.
  • Works recursively: modules, impls, or nested structures with ignored items are filtered out.
  • Inner attributes marked with #[stringify] produce individual constants.
  • #[stringify(TEXT)] and #[stringify("TEXT")] are both supported.
  • Uses the Rust syn and quote crates for parsing and regenerating code.
  • #[expose_for_tests] clones the original function, makes it pub and wraps it in #[cfg(test)].

πŸ“¦ Installation

Add to your Cargo.toml:

[dependencies]
seferize = "1.5.5"

πŸ“– Example project structure

src/
β”œβ”€β”€ main.rs
β”œβ”€β”€ lib.rs
└── samples/
    β”œβ”€β”€ user.rs
    └── example.rs

πŸ™Œ Inspiration

The name Seferize comes from the Hebrew word β€œSefer” (Χ‘Χ€Χ¨), meaning β€œbook” or β€œscroll”, symbolizing the act of revealing written words.

β€œThe entrance of Thy words giveth light.” β€” Psalm 119:130

Commit count: 0

cargo fmt