GGistDev

Modules and Crates in Rust

Rust organizes code with modules (namespaces) inside a crate (compilation unit). A package can contain one or more crates.

Module basics

  • Declare modules with mod and place code in files or inline blocks.
  • File layout rules:
    • mod utils; looks for utils.rs or a utils/mod.rs file.
    • Nested modules follow directories: mod net { mod http { ... } } maps to net/http.rs or net/http/mod.rs.
// src/lib.rs (crate root)
pub mod utils;        // exposes src/utils.rs
mod internal;          // private to the crate

Visibility and paths

  • Private by default. Use pub to export.
  • Fine-grained options: pub(crate), pub(super), pub(in path).
  • Paths can be absolute (crate:: or external crate name) or relative (self::, super::).
pub mod math {
    pub fn add(a: i32, b: i32) -> i32 { a + b }
    fn hidden() {}
}
use crate::math::add as plus;

Re-exports (public API design)

Re-export internal paths to curate your public API surface.

mod details { pub mod io { pub fn read() {} } }
pub use details::io::read; // consumers call your_crate::read()

Crate roots and binary vs library

  • src/lib.rs is the library crate root.
  • src/main.rs is a binary crate entry point.
  • Multiple binaries: place files under src/bin/*.rs.

External crates and use

Add dependencies in Cargo.toml, then import items with use.

[dependencies]
serde = { version = "1", features = ["derive"] }
use serde::{Serialize, Deserialize};

Workspaces vs modules

  • Modules are namespaces inside a crate.
  • Crates are compiled units.
  • Workspaces group multiple crates for unified builds and dependency resolution.
# Cargo.toml at repo root
[workspace]
members = ["core", "cli"]

Tips

  • Keep internal structure private; re-export a tidy API.
  • Prefer directory-based modules for larger trees.
  • Avoid cyclical module dependencies by extracting shared pieces into a new module or crate.