Purpose of the `src` Directory in Brush: Rust Workspace Structure Explained
The src directories in Brush contain the root modules and implementation code for each crate in the workspace, following standard Cargo conventions to organize entry points, sub-modules, and compilation units.
The Brush repository (ArthurBrussee/brush) implements 3D Gaussian splatting as a Rust mono-repo workspace. Understanding the purpose of the src directory in Brush reveals how the project organizes its multi-crate architecture into independent, compilable units that handle everything from dataset loading to training and rendering.
Standard Rust Module Organization
Each src folder serves as the root of a crate's module hierarchy, containing the entry point files that the Rust compiler uses to begin compilation.
Root Module Entry Points
Every crate in Brush contains either lib.rs (for library crates) or main.rs (for binary crates) directly inside its src directory. These files act as the crate root, declaring public APIs and module hierarchies. For example, crates/brush-dataset/src/lib.rs re-exports the public interface:
pub mod config;
pub mod scene;
pub mod scene_loader;
mod formats;
pub use formats::{DatasetLoadResult, load_dataset};
This structure allows other crates to access functionality through clean import paths while keeping implementation details organized in sub-modules.
Sub-Module Discovery
The compiler follows mod statements from the root file to discover additional source files. In crates/brush-dataset/src/, the module tree extends into specialized files like scene.rs and scene_loader.rs, plus subdirectories such as formats/ containing mod.rs, nerfstudio.rs, and colmap.rs. This organization isolates format-specific parsing logic while maintaining a unified public API.
Workspace Structure and Compilation
Brush employs a workspace configuration that treats each src directory as an independent compilation unit while maintaining cross-crate dependencies.
Mono-Repo Layout
The top-level Cargo.toml defines a workspace whose members array points to crate directories under crates/. Each member directory contains its own Cargo.toml and src/ folder, creating clear boundaries between concerns like data loading, training logic, and rendering backends.
Separate Compilation Units
Because each crate maintains its own src directory, Cargo can build them independently, cache artifacts, and emit separate library files (.rlllib or .so). This separation means changes to crates/brush-train/src/train.rs do not force recompilation of crates/brush-dataset/src/lib.rs, significantly accelerating development cycles in this multi-crate project.
Key Crates and Their src Contents
The Brush workspace organizes functionality across several specialized crates, each with distinct responsibilities reflected in their src structure.
brush-dataset
Located at crates/brush-dataset/src/, this crate handles 3D scene data ingestion. The lib.rs file defines the Dataset struct and re-exports loading functions, while src/formats/mod.rs delegates to format-specific implementations like nerfstudio.rs and colmap.rs.
brush-train
The training logic resides in crates/brush-train/src/, containing train.rs (implementing the train function) and config.rs (defining the Config struct). These files implement the optimization loop for Gaussian splatting parameters.
Additional Crates
- brush-render-bwd: Implementation in
crates/brush-render-bwd/src/render_bwd.rshandles backward-pass rendering computations - brush-vfs: Virtual file system abstractions in
crates/brush-vfs/src/data_source.rs - brush-process: Inter-process communication defined in
crates/brush-process/src/message.rs
Practical Implementation Examples
The src directories contain the actual implementations consumed by Brush applications. Here are examples demonstrating how code in these directories is used.
Loading a Dataset
This example uses the brush-dataset crate to load training data. The load_dataset function is defined in crates/brush-dataset/src/formats/mod.rs:
use brush_dataset::load_dataset;
use brush_dataset::Dataset;
fn main() -> anyhow::Result<()> {
// Load a NeRFStudio dataset from a folder
let dataset: Dataset = load_dataset("my/nerfstudio_scene")?;
println!("Loaded {} training views", dataset.train.views.len());
// Estimate an up-direction from the camera poses
let up = dataset.estimate_up();
println!("Estimated up vector: {up:?}");
Ok(())
}
Training a Model
The training entry point resides in crates/brush-train/src/train.rs, while configuration parsing uses crates/brush-train/src/config.rs:
use brush_train::{train, Config};
fn main() -> anyhow::Result<()> {
// Parse a TOML config file
let cfg: Config = toml::from_str(&std::fs::read_to_string("train.toml")?)?;
// Run the training loop
train(cfg)?;
Ok(())
}
Summary
- The
srcdirectory in each Brush crate follows Cargo's standard layout, containinglib.rsormain.rsas the compilation entry point. - Sub-modules are organized under
src/using files and folders that mirror Rust's module hierarchy, as seen incrates/brush-dataset/src/formats/. - Workspace configuration enables independent compilation of each
srctree, caching artifacts for faster builds. - Implementation files like
train.rs,scene.rs, andrender_bwd.rscontain the actual logic exposed through public APIs defined in their respectivelib.rsfiles.
Frequently Asked Questions
Why does each crate in Brush have its own src directory?
Each crate maintains an independent src directory because Brush is organized as a Cargo workspace. This separation allows each crate to compile as a distinct unit with its own dependencies and artifact output. According to the Brush source code, the workspace root Cargo.toml references these crates under crates/, and each follows the standard Rust convention where src/ contains the implementation code.
What is the difference between lib.rs and main.rs in Brush's src folders?
Library crates like brush-dataset and brush-train use src/lib.rs to expose public APIs that other crates can import, while binary crates use src/main.rs to define executable entry points. In Brush, most crates are libraries (lib.rs) that export functionality such as load_dataset or train, allowing the application logic to compose these capabilities while keeping the source organized in src/ directories.
How does the src directory structure affect compilation speed in Brush?
The src directories enable faster incremental compilation because Cargo treats each crate as a separate compilation unit. When you modify crates/brush-train/src/config.rs, only that crate and its dependents rebuild, while crates/brush-dataset/src/ and other crates remain cached. This architectural boundary prevents unnecessary recompilation across the mono-repo workspace.
Where are tests located in relation to the src directory in Brush?
Unit tests typically reside within the src tree using #[cfg(test)] modules inside source files like crates/brush-dataset/src/lib.rs, or in separate test files imported via mod statements. Integration tests live in a top-level tests/ folder adjacent to src/, while the source code under src/ may contain doc tests and example functions compiled only when running cargo test or cargo run --example.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →