Skip to main content
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:
// 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)?)
}
Never use blocking I/O (e.g. std::fs) inside an async context. Always use the Tokio async equivalents (tokio::fs) to avoid blocking the runtime.

Centralized Error Handling

Use the BoxliteError enum for all errors (see boxlite-shared/src/errors.rs):
// 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
    ))
})?;
Always wrap errors with BoxliteError and include descriptive context about what operation failed and why. This makes debugging significantly easier.

Public Types Must Be Send + Sync

All public types exposed through the API must be thread-safe:
// Arc for shared ownership across threads
pub struct LiteBox {
    inner: Arc<LiteBoxInner>,
}

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:
Only panic on programming errors (bugs). Use Result for all expected failures such as I/O errors, invalid input, or network issues.
Avoid vague weasel words like “Manager”, “Service”, and “Factory”. Choose names that describe what the type actually does.
Isolate and document all unsafe code in small, focused functions. Every unsafe block must explain why it is sound.
All public types must implement Debug. User-facing types should also implement Display.
All I/O operations should be async using Tokio. Never use blocking I/O inside an async context.
Use BoxliteError with descriptive messages. Every error should explain what went wrong and where.