Rust’s code organization can be divided into functions, modules, Crate, and Workspace. Workspace manages different Grates, crate manages different mods, and mod manages different functions.

function

A function is the smallest unit of organization code. For example:

fn main() { greet(); //do one thing ask_location(); //do another thing } fn greet() { println! ("Hello!" ); } fn ask_location() { println! ("Where are you from?" ); }Copy the code

Add unit tests for functions in the same file

#[test] fn test_greet() { assert_eq! ("Hello, world!" , greet()) }Copy the code

The #[test] attribute indicates that the function is a unit test.

mod
The mod and the code are in the same file
fn main(){ greetings::hello(); } mod greetings { pub fn hello() { println! ("Hello world !" ); }}Copy the code

Nested mod

fn main(){
	phrases::greetints::hello();
}
mod phrases {
	pub mod greetings {
		pub fn hello(){
			println!("Hello, world!");
		}
	}
}Copy the code

Private functions can be called in the same mod or submod

fn main() { phrases::greet(); } mod phrases { pub fn greet() { hello(); //or self::hello(); } fn hello() { println! ("Hello, world!" ); } } fn main() { phrases::greetings::hello(); } mod phrases { fn private_fn() { println! ("Hello, world!" ); } pub mod greetings { pub fn hello() { super::private_fn(); }}}Copy the code

In the above program, self represents the current mod and super represents the parent mod.

Split the mod into different files under the same path
// main.rs mod greetings; // import greetings module fn main() { greetings::hello(); } // greetings. Rs // No need to display declaration mod, default is the filename as the mod name pub fn hello() {println! ("Hello, world!" ); }Copy the code

If a mod file is wrapped with the mod keyword:

// ↳ main.rs mod phrases; fn main() { phrases::greetings::hello(); } // ↳ phrases.rs pub mod greetings {pub fn hello() {println! ("Hello, world!" ); }}Copy the code
The mod is scattered to different files in different paths

Mod. rs is the entry file of a mod in the real path, and all files in the same path are its submods.

// ↳ main.rs mod greetings; fn main() { greetings::hello(); } // ↳ greetings/mod.rs pub fn hello() {println! ("Hello, world!" ); }Copy the code

Put it in a different file

// ↳ main.rs mod phrases; fn main() { phrases::greetings::hello(); } // ↳ phrases/mod.rs pub mod greetings; // ↳ phrases/greetings. Rs pub fn hello() {println! ("Hello, world!" ); }Copy the code
crate
Lib. rs and the executable are in the same Crate

When writing executables, you can put other functions in SRC /lib.rs and reference them in SRC /main.rs

cargo new --bin greetings

touch greetings/src/lib.rsCopy the code
// 01. greetings/src/lib.rs pub fn hello() { println! ("Hello, world!" ); } // 02. greetings/src/main.rs extern crate greetings; fn main() { greetings::hello(); }Copy the code

The lib.rs file references other files

cargo new --bin phrases touch phrases/src/lib.rs touch phrases/src/greetings.rs // # Think we modify following files // 01. phrases/src/greetings.rs pub fn hello() { println! ("Hello, world!" ); } // 02. phrases/src/main.rs extern crate phrases; fn main() { phrases::greetings::hello(); } // 03. phrases/src/lib.rs pub mod greetings;Copy the code
Declare dependencies in Cargo. Toml

Dependency based on file path:

[package] name = "phrases" version = "0.1.0" authors = ["Dumindu Rajarathna"] [dependencies] greetings = {path = "greetings" } // 02. phrases/greetings/src/lib.rs pub fn hello() { println! ("Hello, world!" ); } // 03. phrases/src/main.rs extern crate greetings; fn main() { greetings::hello(); }Copy the code

Git based dependencies:

// -- Cargo.toml -- [dependencies] rocket = { git = "https://github.com/SergioBenitez/Rocket" } rocket = { git = "https://github.com/SergioBenitez/Rocket", Branch = "v0.3"} rocket = {git = "https://github.com/SergioBenitez/Rocket", Tag = "v0.3.2}" rocket = {git = "https://github.com/SergioBenitez/Rocket", rev = "8183f636305cef4adaa9525506c33cbea72d1745" }Copy the code

Based on the crates. IO version

[dependencies] test_crate_hello_world = "0.1.0 from"Copy the code
workspace

As code volumes grow, a project may contain multiple Grates, which Rust supports through workspace.

// # Think we run mkdir greetings touch greetings/Cargo.toml cargo new greetings/lib cargo new --bin greetings/examples/hello // # That generates, . ├ ─ ─ Cargo. Toml ├ ─ ─ examples │ └ ─ ─ the hello │ ├ ─ ─ Cargo. Toml │ └ ─ ─ the SRC │ └ ─ ─ main. Rs └ ─ ─ lib ├ ─ ─ Cargo. Toml └ ─ ─ the SRC └ ─ ─ lib.rs // # Think we modify following files // 01. greetings/Cargo.toml [workspace] members = [ "lib", "Examples /hello"] // 02.1 greetings/lib/Cargo. Toml [package] name = "greetings" version = "0.1.0" authors = ["Dumindu Madunuwan"] [dependencies] // 02.2 greetings/lib/ SRC /lib.rs pub fn hello() {println! ("Hello, world!" ); } / / 03.1't/examples/hello/Cargo toml [package] name = "hello" version = "0.1.0 from the authors =" [" Dumindu Madunuwan "]  [dependencies] greetings = { path = ".. /.. "} / lib / / 03.2't/examples/hello/SRC/main rs extern crate't; fn main() { greetings::hello(); }Copy the code
use

The main purpose of use is to simplify, without writing the full path for each call, for example:

mod phrases { pub mod greetings { pub fn hello() { println! ("Hello, world!" ); } } } fn main() { phrases::greetings::hello(); // using full path }Copy the code

The use of the use

use phrases::greetings;
fn main() { 
  greetings::hello();
}
// 02. create alias for module elements
use phrases::greetings::hello;
fn main() { 
  hello();
}
// 03. customize names with as keyword
use phrases::greetings::hello as greet;
fn main() { 
  greet();
}Copy the code

Another function of use is to pour elements into the current scope

fn hello() -> String { "Hello, world!" .to_string() } #[cfg(test)] mod tests { use super::hello; //import hello() into scope #[test] fn test_hello() { assert_eq! ("Hello, world!" , hello()); //if not using above use statement, we can run same via super::hello() } }Copy the code

Use Imports the standard library

use std::fs::File; fn main() { File::create("empty.txt").expect("Can not create the file!" ); } // -- 02. importing module and elements-- std::fs::{self, File} //use std::fs; use std::fs::File fn main() { fs::create_dir("some_dir").expect("Can not create the directry!" ); File::create("some_dir/empty.txt").expect("Can not create the file!" ); } // -- 03. importing multiple elements use std::fs::File; use std::io::{BufReader, BufRead}; //use std::io::BufReader; use std::io::BufRead; fn main() { let file = File::open("src/hello.txt").expect("file not found"); let buf_reader = BufReader::new(file); for line in buf_reader.lines() { println! ("{}", line.unwrap()); }}Copy the code

Pub use imports a member of a mod

mod phrases; fn main() { phrases::hello(); //not directly map} // ↳ phrases/mod.rs pub mod greetings; pub use self::greetings::hello; //re-export greetings::hello to phrases/ / ↳ phrases/greetings. Rs pub fn hello() {println! ("Hello, world!" ); }Copy the code

The standard library that Rust imports by default

// Reexported core operators
pub use marker::{Copy, Send, Sized, Sync};
pub use ops::{Drop, Fn, FnMut, FnOnce};
// Reexported functions
pub use mem::drop;
// Reexported types and traits
pub use boxed::Box;
pub use borrow::ToOwned;
pub use clone::Clone;
pub use cmp::{PartialEq, PartialOrd, Eq, Ord};
pub use convert::{AsRef, AsMut, Into, From};
pub use default::Default;
pub use iter::{Iterator, Extend, IntoIterator};
pub use iter::{DoubleEndedIterator, ExactSizeIterator};
pub use option::Option::{self, Some, None};
pub use result::Result::{self, Ok, Err};
pub use slice::SliceConcatExt;
pub use string::{String, ToString};
pub use vec::Vec;Copy the code