inspect-rs 0.1.0

Universal introspection for Rust
Documentation

inspect-rs

Universal introspection and semantic terminal rendering for Rust.

Crates.io Documentation MSRV Safety Build License

Inspect Rust values as traversable structured data without coupling your applicationto a debugger, serializer, UI framework, or runtime reflection engine.


Highlights

✦ Zero-Copy & Lazy Traversal

Scalar values and strings borrow directly from target memory without eager allocations. Child structures evaluate on-demand via lightweight closures.

✦ Production Terminal Styling

Semantic syntax highlighting communicating structure—types, fields, enums, variants, and secrets. Automatic TTY, NO_COLOR, and FORCE_COLOR handling.

✦ Built-In Security Model

First-class support for #[inspect(secret)] (redacted to [REDACTED]) and #[inspect(sensitive)] PII classification. Secrets never leak into default logs.

✦ Memory & Resource Safety

Configurable limits for recursion depth, item truncation (… N more), string bounds, and cycle detection to neutralize traversal bombs.

✦ Strict Decoupling

inspect-core is 100% dependency-free with zero knowledge of terminal escapes. Styling lives strictly in inspect-format.

✦ 100% Safe Rust

#![forbid(unsafe_code)] enforced workspace-wide across every crate, macro, example, and test suite.


Quick Start

Add inspect-rs to your Cargo.toml:

[dependencies]
inspect-rs = "0.1"

Derive Inspect on your types and format them:

use inspect_rs::{format_tree, Inspect, InspectCx};

#[derive(Inspect)]
struct Server {
    host: String,
    port: u16,
    running: bool,
    #[inspect(secret)]
    api_key: String,
}

let server = Server {
    host: "127.0.0.1".to_string(),
    port: 8080,
    running: true,
    api_key: "sk_live_99a8b7c6d5e4f3".to_string(),
};

let mut cx = InspectCx::new();
println!("{}", format_tree(&server.inspect(&mut cx)));

Output

Server
├── host: "127.0.0.1"
├── port: 8080
├── running: true
└── api_key: [REDACTED]

[!TIP] When stdout is connected to an interactive terminal, format_tree renders restrained, high-contrast semantic syntax highlighting. When redirected (| less or > log.txt) or when NO_COLOR=1 is set, clean plain text is emitted automatically.


Beautiful Terminal Output

inspect-rs includes a production-grade terminal rendering engine styled like a modern Rust compiler and developer tool—not a demo drenched in random ANSI colors.

Semantic Color Roles

Colors communicate structural roles rather than arbitrary text:

Role Default Dark Palette Semantic Purpose
Type Warm Copper (#E08A5A) Struct names, collection identifiers (Server, Vec)
Field Soft Sky Blue (#6EB4EB) Struct field names (host, port, workers)
Variant Soft Lilac (#B491E1) Enum variants (Status::Running, Postgres)
Key Teal Cyan (#69CDC3) Map keys ("us-east-1", "timeout")
String Sage Green (#8EC680) String literals with subdued quotes
Number Warm Gold (#EBC05F) Integer and float scalar values (8080, 3.14)
Boolean Soft Magenta (#C387B9) Boolean flags (true, false)
Punctuation Subdued Gray (#737882) Branch glyphs (├── , └── ), colons, quotes
Sensitive Bold Crimson (#EB5F5F) Redacted secrets ([REDACTED])
Truncated Dimmed Italic Amber (#E1B44B) Truncation notices (… 42 more)
Error Bold Red (#F05555) Recursive cycles (<cycle>), error variants

Classic Theme Suite

inspect-rs provides 14 classic developer palettes calibrated for dark, light, high-contrast, and legacy terminals:

Theme Constructor CLI / String Name Aesthetic Profile
Dark (Default) Theme::dark() "dark", "default" Warm copper & soft slate for dark terminals
Gruvbox Theme::gruvbox() "gruvbox" Iconic warm, earthy retro groove palette
Nord Theme::nord() "nord" Arctic, cool bluish-slate palette
Dracula Theme::dracula() "dracula" Vibrant dark theme with purple and cyan accents
Catppuccin Mocha Theme::catppuccin_mocha() "catppuccin", "catppuccin-mocha" Soft pastel comfort palette
Tokyo Night Theme::tokyo_night() "tokyo-night" Neon dark city aesthetic inspired by Tokyo nightlife
One Dark Theme::one_dark() "one-dark", "onedark" Iconic Atom and VS Code editor palette
Solarized Dark Theme::solarized_dark() "solarized-dark" Ethan Schoonover's precision dark palette
Solarized Light Theme::solarized_light() "solarized-light" Precision Solarized light background palette
Light Theme::light() "light" Crisp high-contrast palette for light backgrounds
Monokai Theme::monokai() "monokai" Classic Sublime Text high-contrast palette
Ayu Dark Theme::ayu_dark() "ayu-dark", "ayu" Warm modern dark editor palette
ANSI 16 Theme::ansi16() "ansi16", "ansi" Standard 4-bit ANSI for restricted terminals
Monochrome Theme::monochrome() "monochrome", "plain" Terminal effects (bold, dim, italic, underline) with zero color

Selecting Themes

use inspect_rs::{format_tree_with, Theme, TreeConfig};

// 1. Using a typed constructor
let config = TreeConfig::colored().with_theme(Theme::gruvbox());
println!("{}", format_tree_with(&inspected, config));

// 2. Dynamic lookup (case-insensitive, kebab-case or snake_case)
let theme = Theme::by_name("tokyo-night").unwrap_or_default();
let config = TreeConfig::colored().with_theme(theme);
println!("{}", format_tree_with(&inspected, config));

Custom Themes via Builder

use inspect_rs::{AnsiColor, Style, StyleRole, Theme, TreeConfig};

let custom = Theme::dark()
    .with(StyleRole::Type, Style::new().bold().fg_ansi(AnsiColor::BrightYellow))
    .with(StyleRole::Field, Style::new().fg_ansi(AnsiColor::BrightCyan))
    .with(StyleRole::String, Style::new().fg_rgb(140, 230, 140));

let config = TreeConfig::colored().with_theme(custom);

Controlling Colors & Terminal Modes

inspect-rs adheres to modern Unix CLI standards:

Signal Mechanism Behavior
NO_COLOR Environment variable (NO_COLOR=1) Completely disables ANSI escapes (https://no-color.org)
FORCE_COLOR Environment variable (FORCE_COLOR=1) Forces ANSI color emission even when piped
TERM=dumb Environment variable Disables styling for dumb/minimal terminals
TTY Detection std::io::IsTerminal Disables color when redirecting to files or pipes
use inspect_rs::{format_tree, format_tree_colored, format_tree_plain, ColorChoice, TreeConfig};

// Automatic detection (TTY + env vars)
let auto = format_tree(&inspected);

// Explicitly uncolored (guaranteed zero ANSI sequences)
let plain = format_tree_plain(&inspected);

// Explicitly colored (forces ANSI escapes)
let colored = format_tree_colored(&inspected);

Derive Macro Attributes

Fine-tune how your structs and fields are exposed:

#[derive(Inspect)]
struct DatabaseConfig {
    host: String,
    port: u16,

    // Secrets are permanently masked in default renderers
    #[inspect(secret)]
    password: String,

    // Sensitive data marked with PII metadata
    #[inspect(sensitive)]
    admin_email: String,

    // Omit field entirely from inspection
    #[inspect(skip)]
    internal_cache_key: u64,

    // Custom display name for the field
    #[inspect(rename = "service_url")]
    url: String,
}

Safety & Resource Limits

Prevent recursive cycles and inspection bombs from consuming unbounded CPU or memory:

use inspect_rs::{InspectCx, InspectLimits};

let limits = InspectLimits {
    max_depth: 12,           // Maximum tree nesting depth
    max_items: 50,           // Maximum elements per collection before truncation
    max_nodes: 5000,         // Global ceiling on total nodes visited
    max_string_length: 512,  // String clipping threshold
    max_bytes: 2048,         // Byte-slice display ceiling
};

let mut cx = InspectCx::with_limits(limits);
let inspected = large_structure.inspect(&mut cx);

Recursive structs automatically print <cycle> instead of causing a stack overflow.


Architecture

inspect-rs is cleanly partitioned into a modular workspace:

┌────────────────────────────────────────────────────────┐
│                    Your Application                    │
│             #[derive(Inspect)] / structs / enums       │
└───────────────────────────┬────────────────────────────┘
                            │ implements Inspect
                            ▼
┌────────────────────────────────────────────────────────┐
│                      inspect-core                      │
│   Inspect trait · ValueRef · InspectCx · Limits · AST  │
│              (Zero runtime dependencies)               │
└───────────────────────────┬────────────────────────────┘
                            │ borrows ValueRef
                            ▼
┌────────────────────────────────────────────────────────┐
│                     inspect-format                     │
│    TreeFormatter · Themes · StyleRoles · StyledWriter  │
│             (Optional "color" feature via anstyle)     │
└───────────────────────────┬────────────────────────────┘
                            │ re-exports facade
                            ▼
┌────────────────────────────────────────────────────────┐
│                       inspect-rs                       │
│       Convenience helpers: format_tree, Config, API    │
└────────────────────────────────────────────────────────┘
Crate Responsibility Dependencies
inspect-core Traits, borrowed value graph, context, cycle limits Zero
inspect-derive Procedural macro #[derive(Inspect)] syn, quote, proc-macro2
inspect-format Tree rendering, themes, styling, stream writing anstyle (optional)
inspect-rs Top-level facade crate Workspace members

Performance

inspect-rs is engineered for zero runtime overhead in production:

  • Zero Allocations for Scalars: Numbers, booleans, and small values return value copies directly.
  • Borrowed Strings: String slices borrow directly without reallocating.
  • Zero-Allocation Uncolored Path: When color is disabled, StyledWriter skips styling logic and streams plain bytes directly to the output.
  • Direct Stream Writing: Colored rendering emits ANSI sequences directly to the buffer without allocating intermediate strings.

Run the Criterion benchmark suite:

cargo bench

Comparison

Feature Debug bevy_reflect valuable inspect-rs
Output Type Opaque String Dynamic Types / Patching Visitor Callbacks Structured Borrowed AST
Zero-Copy Scalars
Lazy Child Traversal
Secret Redaction ✓ (#[inspect(secret)])
Resource Limits & Cycles
Semantic Color Themes ✓ (14 classic themes)
Dependency-Free Core ✓ (0 dependencies)
Safe Rust ✓ (forbid(unsafe_code))

Examples

Run any of the built-in examples:

# Demo all 14 color themes sequentially
cargo run --example colored

# Demo a specific theme
cargo run --example colored -- gruvbox
cargo run --example colored -- nord
cargo run --example colored -- dracula
cargo run --example colored -- tokyo-night

# Basic usage
cargo run --example basic

# Struct and enum nested inspection
cargo run --example nested
cargo run --example enums

# Collections (Vec, HashMap, arrays)
cargo run --example collections

# Secrets and sensitive redaction
cargo run --example attributes

MSRV & Edition

  • Edition: Rust 2024
  • Minimum Supported Rust Version: 1.85.0
  • Safety: #![forbid(unsafe_code)]

License

Dual-licensed under either of:

at your option.