Rust Style Guide

January 25, 2026 · View on GitHub

This guide extends the Microsoft Rust Guidelines with BoxLite-specific patterns.

External References

Universal Guidelines (Must Follow)

These guidelines from the Microsoft Rust Guidelines are particularly important for BoxLite:

GuidelineSummary
M-PANIC-IS-STOPPanics terminate the program - they are not exceptions
M-PANIC-ON-BUGPanic only on programming errors, never for expected failures
M-CONCISE-NAMESAvoid weasel words: "Service", "Manager", "Factory", "Handler"
M-LOG-STRUCTUREDUse structured logging with meaningful fields
M-DOCUMENTED-MAGICDocument all magic numbers and constants
M-PUBLIC-DEBUGAll public types must implement Debug
M-PUBLIC-DISPLAYUser-facing types should implement Display
M-LINT-OVERRIDE-EXPECTUse #[expect] over #[allow] for lint overrides
M-REGULAR-FNPrefer regular functions over methods when self isn't needed
M-SMALLER-CRATESKeep crates focused on a single responsibility

Safety Guidelines

GuidelineSummary
M-UNSAFEMinimize unsafe code; isolate it in small, well-documented functions
M-UNSAFE-IMPLIES-UBDocument all undefined behavior conditions in unsafe code
M-UNSOUNDNever expose unsound APIs; soundness must be guaranteed

BoxLite-Specific Patterns

Async-First Architecture

All I/O operations use async/await with Tokio runtime:

// ✅ Correct: async I/O
async fn read_config(path: &Path) -> Result<Config> {
    let contents = tokio::fs::read_to_string(path).await?;
    Ok(toml::from_str(&contents)?)
}

// ❌ Wrong: blocking I/O in async context
async fn read_config(path: &Path) -> Result<Config> {
    let contents = std::fs::read_to_string(path)?;  // Blocks!
    Ok(toml::from_str(&contents)?)
}

Centralized Error Handling

Use the BoxliteError enum for all errors (see boxlite-shared/src/errors.rs):

// ✅ Correct: use BoxliteError with context
std::fs::create_dir_all(&socket_dir).map_err(|e| {
    BoxliteError::Storage(format!(
        "Failed to create socket directory {}: {}", socket_dir.display(), e
    ))
})?;

// ❌ Wrong: generic error without context
std::fs::create_dir_all(&dir)?;

Public Types Must Be Send + Sync

All public types exposed through the API must be thread-safe:

// ✅ Correct: Arc for shared ownership across threads
pub struct LiteBox {
    inner: Arc<LiteBoxInner>,
}

// ❌ Wrong: Rc is not Send
pub struct LiteBox {
    inner: Rc<LiteBoxInner>,  // Not thread-safe!
}

Formatting and Linting

  • Formatting: cargo fmt (enforced in CI)
  • Linting: cargo clippy (warnings are errors in CI)

Run before committing:

cargo fmt
cargo clippy --all-targets --all-features

Quick Reference

When writing Rust code for BoxLite, ask yourself:

  1. Is this panic necessary? (M-PANIC-ON-BUG) - Only panic on bugs, use Result for errors
  2. Is this name clear? (M-CONCISE-NAMES) - Avoid "Manager", "Service", "Factory"
  3. Is this unsafe minimized? (M-UNSAFE) - Isolate and document unsafe code
  4. Does this implement Debug? (M-PUBLIC-DEBUG) - All public types need it
  5. Is this async? - All I/O should be async with Tokio
  6. Is the error contextual? - Use BoxliteError with descriptive messages