Rust has a number of features that allow to manage code’s organization, including which details are exposed, which details are private, and what names are in each scope in programs. These features, sometimes collectively referred to as the module system, include:
- Workspaces: acts like a solution in .NET. It may contain multiple packages.
- Packages: one or more crates that provide a set of functionality. A
package contains a
Cargo.tomlfile. It’s like a project in .NET.
- Crates: a binary or library. It’s a compilation unit for the compiler. Other languages treat a single file as a compilation unit
- Modules: let us organize code within a crate into groups for readability and easy reuse.
- Paths: A way of naming an item, such as a struct, function, or module.
A package contains crates. It can be as many binary crates as needed and just
one library crate.
We create packages with
cargo new my-project-name.
A workspace may contain multiple packages. We need to define how packages are related (which one depends on which one).
We can specify project to run in a workspace with
cargo run -p my-package.
Pckages in a workspace use the same versions of dependencies. There’s just one
Modules control encapsulation. Some items might be public, others can be private. Modules may be nested.
Modules may contain definitions of anything (modules, functions, structs, enums, etc.).
The root of every module is
crate. It is either
There is a module tree similar to filesystem:
To refer to an entity we can use absolute or relative paths.
We separate identifiers by
super acts like
.. in Unix filesystems. We can use it to go up a module.
All entities are private by default.
The privacy rules apply to structs, enums, functions, methods, and modules.
Items in a parent module cannot use the privte items inside child modules.
items in child modules can use items in their ancestor modules.
sibling items can access each other.
items can be made public with the
struct can be made public, but its fields will stay private unless they are individually made public:
all enum’s options are public if enum itself is public.
use keyword brings a path into the local scope so we don’t have to repeat
paths all the time.
use is like a symbolic link in a filesystem.
Relative paths can be used with
use as well.
The imported entities may be re-exported with the use of
If there are entities with the same names (e.g. two structs) we can’t import them both directly. Instead, we should import their containing modules.
We could also change name of an imported entity using the
* (glob) operator allows us to bring in all items from some module:
Sometimes having a deep structure of types is good for the author of the crate, but troublesome for the users of the crate. Things can be reexported to change the way how they are visible outside.
UsefulType is available from the level of the file where we put that
declaration. It will be also visible in the documentation of our crate.