Rust modules: Difference between revisions
No edit summary |
|||
(38 intermediate revisions by the same user not shown) | |||
Line 5: | Line 5: | ||
<blockquote> | <blockquote> | ||
{| class="wikitable" | {| class="wikitable" | ||
|- | |||
| official docs || https://doc.rust-lang.org/reference/items/modules.html | |||
|- | |- | ||
| cargo book: package layout || https://doc.rust-lang.org/cargo/guide/project-layout.html | | cargo book: package layout || https://doc.rust-lang.org/cargo/guide/project-layout.html | ||
Line 20: | Line 22: | ||
</blockquote><!-- Tutorials --> | </blockquote><!-- Tutorials --> | ||
= | = Examples = | ||
<blockquote> | <blockquote> | ||
The core idea is that <code>main.rs/lib.rs</code> must directly/indirectly import all paths. | |||
* <code>crate</code> is the root namespace of the crate | |||
* <code>mod</code> allows access to a namespace, using namespace prefix, for modules in same-directory | |||
* <code>use</code> merges a namespace (or elements from it) into the current namespace | |||
* <code>pub mod</code> exposes module externally | |||
* <code>super</code>, within <code>use/mod</code> refers to the parent scope | |||
== sample-1 == | == sample-1: (mod) use module from namespace == | ||
<blockquote> | <blockquote> | ||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
Line 32: | Line 40: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
{{ expand | |||
| <code>src/main.rs</code> | |||
| | |||
<syntaxhighlight lang="rust"> | <syntaxhighlight lang="rust"> | ||
// main.rs | // main.rs | ||
Line 41: | Line 52: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
}} | |||
{{ expand | |||
| <code>house.rs</code> / <code>house/mod.rs</code> | |||
| | |||
<syntaxhighlight lang="rust"> | <syntaxhighlight lang="rust"> | ||
// house.rs | // house.rs / house/mod.rs | ||
pub fn house_name() -> String { | pub fn house_name() -> String { | ||
Line 49: | Line 64: | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
}} | |||
</blockquote><!-- sample-1 --> | </blockquote><!-- sample-1 --> | ||
= | == sample-2 (mod) use file from submodule == | ||
<blockquote> | <blockquote> | ||
In order to use <code>street::lamps::*</code> from <code>main.rs</code>,<br> | |||
we must publish <code>lamps</code> from street. | |||
<syntaxhighlight lang="bash"> | |||
src/ | |||
main.rs | |||
street/ | |||
mod.rs | |||
lamps.rs | |||
</syntaxhighlight> | |||
{{ expand | |||
| <code>main.rs</code> | |||
| | |||
<syntaxhighlight lang="rust"> | |||
// main.rs | |||
mod street; | |||
fn main() { | |||
printlnt("{}", street::lamps::brightness()); | |||
} | |||
</syntaxhighlight> | |||
}} | |||
{{ expand | |||
| <code>street/mod.rs</code> | |||
| | |||
<syntaxhighlight lang="rust"> | |||
// street/mod.rs | |||
pub mod lamps; | |||
</syntaxhighlight> | |||
}} | |||
{{ expand | |||
| <code>street/lamps.rs</code> | |||
| | |||
<syntaxhighlight lang="rust"> | |||
// street/lamps.rs | |||
</blockquote><!-- | pub fn brightness() -> isize { | ||
100 | |||
} | |||
</syntaxhighlight> | |||
}} | |||
</blockquote><!-- sample-2 --> | |||
= | == sample-3 (use) use file from submodule == | ||
<blockquote> | <blockquote> | ||
In order to use <code>street::lamps::*</code> from <code>main.rs</code>,<br> | |||
we must publish <code>lamps</code> from street. | |||
< | <syntaxhighlight lang="bash"> | ||
src/ | |||
street/ | |||
mod.rs | |||
lamps.rs | |||
main.rs | |||
</syntaxhighlight> | |||
</ | |||
{{ expand | |||
* <code>src/ | | <code>src/main.rs</code> | ||
* <code>src/ | | | ||
</blockquote><!-- | <syntaxhighlight lang="rust"> | ||
mod street; | |||
use street::lamps::*; | |||
fn main() { | |||
println!("{}", brightness()); | |||
} | |||
</syntaxhighlight> | |||
}} | |||
{{ expand | |||
| <code>src/street/mod.rs</code> | |||
| | |||
<syntaxhighlight lang="rust"> | |||
// src/street/mod.rs | |||
pub mod lamps; | |||
</syntaxhighlight> | |||
}} | |||
{{ expand | |||
| <code>src/street/lamp.rs</code> | |||
| | |||
<syntaxhighlight lang="rust"> | |||
// src/street/lamp.rs | |||
pub fn brightness() -> isize { | |||
100 | |||
} | |||
</syntaxhighlight> | |||
}} | |||
</blockquote><!-- sample-3 (kwd use) --> | |||
== sample-4 use lib.rs from main.rs == | |||
<blockquote> | |||
When building executables, it's customary for most of the business-logic to live in <code>lib.rs</code>,<br> | |||
with a tiny skeleton program in <code>main.rs</code>. | |||
Code from <code>lib.rs</code> will be imported from your project-name's namespace. | |||
<syntaxhighlight lang="rust"> | |||
// main.rs | |||
use my_project; // code from `lib.rs` | |||
fn main() { | |||
my_project::some_function(); | |||
} | |||
</syntaxhighlight> | |||
</blockquote><!-- sample-4 use lib.rs from main.rs --> | |||
</blockquote><!-- Examples --> | |||
= Entrypoints = | |||
<blockquote> | |||
For modules to be compiled, they must be used (however indirectly) from their crate-root (build target).<br> | |||
By default these are: | |||
* <code>src/main.rs</code> for executables | |||
* <code>src/lib.rs</code> for libraries (imported as the package-name) | |||
See [[rust anatomy]] for more details. | |||
</blockquote><!-- Entrypoints --> | |||
= Imports = | = Imports = | ||
<blockquote> | <blockquote> | ||
* <code>use</code> merge namespace into current (ex. <code>use foo; myfn();</code>) | * <code>use</code> merge namespace into current (ex. <code>use foo; myfn();</code>) | ||
* <code>use as</code> lets you alias a namespace | |||
* <code>mod</code> enables you to access from namespace (ex. <code>mod foo; foo::myfn();</code>) | * <code>mod</code> enables you to access from namespace (ex. <code>mod foo; foo::myfn();</code>) | ||
Line 92: | Line 210: | ||
use std::fs::File; // import 'File' only into current namespace | use std::fs::File; // import 'File' only into current namespace | ||
use std::fs::{File, DirBuilder}; // import multiple types/functions into current namespace | use std::fs::{File, DirBuilder}; // import multiple types/functions into current namespace | ||
use std::fs as fs // within this namespace, refer to 'std::fs' as 'fs' | |||
std::io::stdin() // you also can access objects directly from their namespace without `use` | std::io::stdin() // you also can access objects directly from their namespace without `use` | ||
</syntaxhighlight> | </syntaxhighlight> | ||
<code>mod</code> | <code>mod</code> enables access to submodules, 1-level deep, from current module. | ||
<syntaxhighlight lang="rust"> | <syntaxhighlight lang="rust"> | ||
// expose ./foo.rs or ./foo/mod.rs from current module | |||
pub mod foo; | |||
</syntaxhighlight> | </syntaxhighlight> | ||
</blockquote><!-- Imports --> | </blockquote><!-- Imports --> | ||
Line 105: | Line 225: | ||
<blockquote> | <blockquote> | ||
By default, a module's code is public to itself and it's children,<br> | By default, a module's code is public to itself and it's children,<br> | ||
but private to it's parents and/or callers. | but private to it's parents and/or callers.<br> | ||
The <code>pub</code> keyword exposes a module/function. | |||
< | * parents modules can expose access to their children with <code>pub mod ${foo}</code> | ||
pub mod | * child modules can access their parents without importing them using <code>super::</code> | ||
* child modules can use absolute paths to symbols, from the <code>crate::</code> namespace | |||
* imports are private by default, unless you import using <code>pub use some::module</code> | |||
See [[rust access control]] for more details. | |||
</ | |||
</blockquote><!-- Access Control --> | </blockquote><!-- Access Control --> |
Latest revision as of 03:22, 9 February 2023
Modules are rust libraries.
The std::prelude
module is included in the scope of every program.
Documentation
official docs https://doc.rust-lang.org/reference/items/modules.html cargo book: package layout https://doc.rust-lang.org/cargo/guide/project-layout.html
Tutorials
rust module system https://www.sheshbabu.com/posts/rust-module-system/
Examples
The core idea is that
main.rs/lib.rs
must directly/indirectly import all paths.
crate
is the root namespace of the cratemod
allows access to a namespace, using namespace prefix, for modules in same-directoryuse
merges a namespace (or elements from it) into the current namespacepub mod
exposes module externallysuper
, withinuse/mod
refers to the parent scopesample-1: (mod) use module from namespace
src/ main.rs house.rs
src/main.rs
// main.rs mod house; fn main() { println!("{}", house::house_name()); }
house.rs
/house/mod.rs
// house.rs / house/mod.rs pub fn house_name() -> String { String:from("hi") }sample-2 (mod) use file from submodule
In order to use
street::lamps::*
frommain.rs
,
we must publishlamps
from street.src/ main.rs street/ mod.rs lamps.rs
main.rs
// main.rs mod street; fn main() { printlnt("{}", street::lamps::brightness()); }
street/mod.rs
// street/mod.rs pub mod lamps;
street/lamps.rs
// street/lamps.rs pub fn brightness() -> isize { 100 }sample-3 (use) use file from submodule
In order to use
street::lamps::*
frommain.rs
,
we must publishlamps
from street.src/ street/ mod.rs lamps.rs main.rs
src/main.rs
mod street; use street::lamps::*; fn main() { println!("{}", brightness()); }
src/street/mod.rs
// src/street/mod.rs pub mod lamps;
src/street/lamp.rs
// src/street/lamp.rs pub fn brightness() -> isize { 100 }sample-4 use lib.rs from main.rs
When building executables, it's customary for most of the business-logic to live in
lib.rs
,
with a tiny skeleton program inmain.rs
.Code from
lib.rs
will be imported from your project-name's namespace.// main.rs use my_project; // code from `lib.rs` fn main() { my_project::some_function(); }
Entrypoints
For modules to be compiled, they must be used (however indirectly) from their crate-root (build target).
By default these are:
src/main.rs
for executablessrc/lib.rs
for libraries (imported as the package-name)See rust anatomy for more details.
Imports
use
merge namespace into current (ex.use foo; myfn();
)use as
lets you alias a namespacemod
enables you to access from namespace (ex.mod foo; foo::myfn();
)
use
(merge with current namespace)use std::io; // merges objects from namespace into your own use std::io::*; // use std::fs::File; // import 'File' only into current namespace use std::fs::{File, DirBuilder}; // import multiple types/functions into current namespace use std::fs as fs // within this namespace, refer to 'std::fs' as 'fs' std::io::stdin() // you also can access objects directly from their namespace without `use`
mod
enables access to submodules, 1-level deep, from current module.// expose ./foo.rs or ./foo/mod.rs from current module pub mod foo;
Access Control
By default, a module's code is public to itself and it's children,
but private to it's parents and/or callers.
Thepub
keyword exposes a module/function.
- parents modules can expose access to their children with
pub mod ${foo}
- child modules can access their parents without importing them using
super::
- child modules can use absolute paths to symbols, from the
crate::
namespace- imports are private by default, unless you import using
pub use some::module
See rust access control for more details.