Modules control the organization, scope and privacy. They're defined by the
mod
keyword:
mod blazer {
// ...
}
Crate is a compilation unit, an application entrypoint. They can be compiled:
- as a binary using
rustc <root>.rs
- as a library using
rustc --crate-type=lib <root>.rs
It is recommended to use
cargo
for compiling configured inCargo.toml
instead of usingrustc
directly.
Absolute paths within a crate can be referenced using the crate
keyword:
mod yolo {
pub enum YoloSwag {
Yolo,
Swag,
}
}
fn main() {
use crate::yolo::YoloSwag;
// ...
}
Everything is private by default and only made public by the pub
keyword:
mod blazer {
fn light_me_up() {
// ...
}
pub fn blaze_it() {
// ...
}
}
This applies to all module's items, like functions, traits, structs, enums, etc...
Structs have per-field visibility which is private by default and made public
using pub
:
mod auth {
pub struct User {
pub name: &str,
// public
created_at: u64, // private
}
}
Only public structs can have public fields.
Methods defined in impl
blocks need to also be made public explicitly using
pub
:
mod c {
pub struct Count {
count: u32,
}
impl Count {
// public api
pub fn inc(&mut self, times: u32) {
for _ in 0..times {
self.inc_by_one();
}
}
// private implementation
fn inc_by_one(&mut self) {
self.count += 1;
}
}
}
The self
keyword is used for removing ambiguity, and accessing items
relative to the current module, rather than using an absolute path of the
current crate:
mod yolo {
mod swag {
pub enum YoloSwag {
Yolo,
Swag,
}
}
fn go() {
use self::swag::YoloSwag; // use crate::yolo::swag::YoloSwag;
// ...
}
}
The super
keyword works as self
, except it refers to the parent module:
mod yolo {
mod swag {
pub enum YoloSwag {
Yolo,
Swag,
}
}
mod runner {
fn go() {
use super::swag::YoloSwag; // use crate::yolo::swag::YoloSwag;
// ...
}
}
}
The pub
keyword's scope can be specified explicitly:
pub(in path)
makes an item visible in the specified path which must be an ancestor of the target item's modulepub(crate)
makes an item visible to the cratepub(super)
makes an item visible to the parent module, same aspub(in super)
pub(self)
makes an item visible to the current module, same aspub(in self)
or not usingpub
at all, thus being private
The path specifier in pub(in path)
must start with one of crate
, self
or
super
.
The use
keyword binds a full path to a new name, for easier access:
use std::collections::HashMap;
use std::fs;
fn main() {
let file = fs::read_to_string("file.txt")?;
let m = HashMap::new();
// ...
}
Multiple items can be specified within a path using {}
:
use std::io::{self, Result};
fn main() -> Result<()> {
let e = io::empty();
// ...
Ok(())
}
An alias can be specified for an item using as
:
use std::fs as stdfs;
fn main() {
let file = stdfs::read_to_string("file.txt")?;
// ...
}
Paths are relative by default. An absolute path can be specified for disambiguation:
mod std {
pub fn fs() {
// ...
}
}
fn main() {
use ::std::fs as stdfs; // absolute external crate path
use self::std::fs; // explicit relative path
}
Names can be re-exported using pub use
to create flatter APIs:
mod yolo {
mod swag {
pub enum YoloSwag {
Yolo,
Swag,
}
}
pub use swag::{YoloSwag};
}
fn main() {
use yolo::{YoloSwag}; // instead of yolo::swag::{YoloSwag}
// ...
}
A wildcard *
can be used for using everything, although commonly only used
with re-exporting:
pub use lib::nested::*;
Enum variants are sometimes used within a function for cleaner match
syntax:
mod swag {
pub enum YoloSwag {
Yolo,
Swag,
}
}
fn main() {
use swag::YoloSwag::*;
let s = Yolo;
match s {
Yolo => println!("Yolo"),
Swag => println!("Swag"),
};
}
The use
path binding conventions are:
- using whole modules for their public API,
use std::io;
- using structs, enums and traits directly,
use std::collections::HashMap;
- sometimes using enum variants with wildcards in
functions,
use lib::Enum::*;
- re-exporting to create flatter APIs,
pub use lib::nested::*;
Files and folders can act as modules. The mod <name>;
declaration can be
used to bring <name>.rs
or <name>/mod.rs
items under the current scope
inside a module named <name>
:
// <root>/custom.rs or <root>/custom/mod.rs
pub fn do_stuff() {
// ...
}
// some file in <root>
mod custom;
fn stuff() {
custom::do_stuff();
}
The pub mod <name>;
declaration can be used for re-exporting:
// <root>/custom/core.rs
pub fn do_stuff() {
// ...
}
// <root>/custom/mod.rs
pub mod core;
// some file in <root>
mod custom;
fn stuff() {
custom::core::do_stuff();
}