Структури, модули, външни пакети

14 октомври 2021

Преговор

Преговор

Преговор

Преговор

Преговор

Преговор

Преговор

Преговор

Административни неща

Структури

Структури

Синтаксис

1 2 3 4 5
struct User {
    username: String,
    email: String,
    sign_in_count: u64,
}
struct User {
    username: String,
    email: String,
    sign_in_count: u64,
}
fn main() {}

Структури

Създаване на инстанция

1 2 3 4 5 6 7 8 9 10 11
struct User {
    username: String,
    email: String,
    sign_in_count: u64
}

let user = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};
fn main() {
struct User {
    username: String,
    email: String,
    sign_in_count: u64
}

let user = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};
}

Структури

Достъп до полета

1 2 3 4 5 6 7 8 9 10 11 12 13
struct User {
    username: String,
    email: String,
    sign_in_count: u64
}

let user = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};

println!("{}, {}", user.username, user.email);
Иванчо, ivan40@abv.bg
fn main() {
struct User {
    username: String,
    email: String,
    sign_in_count: u64
}

let user = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};

println!("{}, {}", user.username, user.email);
}

Структури

Достъп до полета

Полетата се достъпват по същия начин и през референция.
Автоматично се правят необходимия брой дереференцирания.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
struct User {
    username: String,
    email: String,
    sign_in_count: u64
}

let user = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};

let user_ref = &user;

println!("{}, {}", user_ref.username, user_ref.email);
Иванчо, ivan40@abv.bg
fn main() {
struct User {
    username: String,
    email: String,
    sign_in_count: u64
}

let user = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};

let user_ref = &user;

println!("{}, {}", user_ref.username, user_ref.email);
}

Структури

Промяна на полетата

Можем да променяме стойността на полетата, ако инстанцията е дефинирана като mut.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
struct User {
    username: String,
    email: String,
    sign_in_count: u64
}

let mut user = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};

user.email = "ivan40.ivanov@abv.bg".to_string();

println!("{}, {}", user.username, user.email);
Иванчо, ivan40.ivanov@abv.bg
fn main() {
struct User {
    username: String,
    email: String,
    sign_in_count: u64
}

let mut user = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};

user.email = "ivan40.ivanov@abv.bg".to_string();

println!("{}, {}", user.username, user.email);
}

Структури

Преместване на структури

По подразбиране структурите се преместват (защото не имплементират Copy).

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
struct User {
    username: String,
    email: String,
    sign_in_count: u64
}

let user1 = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};

let user2 = user1;

println!("user1 = {}, {}", user1.username, user1.email);
println!("user2 = {}, {}", user2.username, user2.email);
error[E0382]: borrow of moved value: `user1` --> src\bin\main_b3c03fba678cada8014f8bd9534eee85648a700d.rs:16:44 | 8 | let user1 = User { | ----- move occurs because `user1` has type `User`, which does not implement the `Copy` trait ... 14 | let user2 = user1; | ----- value moved here 15 | 16 | println!("user1 = {}, {}", user1.username, user1.email); | ^^^^^^^^^^^ value borrowed here after move For more information about this error, try `rustc --explain E0382`. error: could not compile `rust` due to previous error
fn main() {
struct User {
    username: String,
    email: String,
    sign_in_count: u64
}

let user1 = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};

let user2 = user1;

println!("user1 = {}, {}", user1.username, user1.email);
println!("user2 = {}, {}", user2.username, user2.email);
}

Структури

Клониране на структури

За да можем да създаваме копия на нашата структура, тя трябва да имплементира trait-а Clone.
Чрез атрибута #[derive(Clone)] компилатора автоматично ще ни създаде имплементация на Clone.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
#[derive(Clone)]
struct User {
    username: String,
    email: String,
    sign_in_count: u64
}

let user1 = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};

let user2 = user1.clone();

println!("user1 = {}, {}", user1.username, user1.email);
println!("user2 = {}, {}", user2.username, user2.email);
user1 = Иванчо, ivan40@abv.bg user2 = Иванчо, ivan40@abv.bg
fn main() {
#[derive(Clone)]
struct User {
    username: String,
    email: String,
    sign_in_count: u64
}

let user1 = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};

let user2 = user1.clone();

println!("user1 = {}, {}", user1.username, user1.email);
println!("user2 = {}, {}", user2.username, user2.email);
}

Структури

Принтиране на структури

Аналогично можем да използваме атрибута #[derive(Debug)] за да получим имплементация на trait-а Debug.
Това ни позволява да принтираме нашата структура с println! инползвайки placeholder {:?}.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
#[derive(Clone, Debug)]
struct User {
    username: String,
    email: String,
    sign_in_count: u64
}

let user1 = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};

let user2 = user1.clone();

println!("user1 = {:?}", user1);
println!("user2 = {:?}", user2);
user1 = User { username: "Иванчо", email: "ivan40@abv.bg", sign_in_count: 10 } user2 = User { username: "Иванчо", email: "ivan40@abv.bg", sign_in_count: 10 }
fn main() {
#[derive(Clone, Debug)]
struct User {
    username: String,
    email: String,
    sign_in_count: u64
}

let user1 = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};

let user2 = user1.clone();

println!("user1 = {:?}", user1);
println!("user2 = {:?}", user2);
}

Структури

Struct update синтаксис

Можем да дадем стойност само на част от полетата и останалите да попълним от друга инстанция

1 2 3 4 5 6 7 8 9 10 11 12
let user = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};

let hacker = User {
    email: String::from("hackerman@l33t.hax"),
    ..user
};

println!("{}, {}", hacker.username, hacker.email);
Иванчо, hackerman@l33t.hax
struct User { username: String, email: String, sign_in_count: u64 }
fn main() {
let user = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};

let hacker = User {
    email: String::from("hackerman@l33t.hax"),
    ..user
};

println!("{}, {}", hacker.username, hacker.email);
}

Структури

Struct update синтаксис

Това ще премести полетата от оригиналната инстанция

1 2 3 4 5 6 7 8 9 10 11 12 13
let user = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};

let hacker = User {
    email: String::from("hackerman@l33t.hax"),
    ..user
};

println!("{}, {}", hacker.username, hacker.email);
println!("{}, {}", user.username, user.email);
error[E0382]: borrow of moved value: `user.username` --> src\bin\main_209502704f19bd1ac614f06e4f28a71d4c84dc9b.rs:15:20 | 9 | let hacker = User { | ______________- 10 | | email: String::from("hackerman@l33t.hax"), 11 | | ..user 12 | | }; | |_- value moved here ... 15 | println!("{}, {}", user.username, user.email); | ^^^^^^^^^^^^^ value borrowed here after move | = note: move occurs because `user.username` has type `String`, which does not implement the `Copy` trait For more information about this error, try `rustc --explain E0382`. error: could not compile `rust` due to previous error
struct User { username: String, email: String, sign_in_count: u64 }
fn main() {
let user = User {
    username: String::from("Иванчо"),
    email: String::from("ivan40@abv.bg"),
    sign_in_count: 10,
};

let hacker = User {
    email: String::from("hackerman@l33t.hax"),
    ..user
};

println!("{}, {}", hacker.username, hacker.email);
println!("{}, {}", user.username, user.email);
}

Структури

Кратък синтаксис за създаване на структури

Често се случва стойността на поле да се задава чрез променлива със същото име.

1 2 3 4 5 6 7 8 9 10 11 12
struct Rectangle {
    width: f64,
    height: f64,
}

let width = 2.0;
let height = 3.0;

let rect = Rectangle {
    width: width,
    height: height,
};
fn main() {
struct Rectangle {
    width: f64,
    height: f64,
}

let width = 2.0;
let height = 3.0;

let rect = Rectangle {
    width: width,
    height: height,
};
}

Структури

Кратък синтаксис за създаване на структури

Често се случва стойността на поле да се задава чрез променлива със същото име. Има кратък синтаксис за това.

1 2 3 4 5 6 7 8 9 10 11 12
struct Rectangle {
    width: f64,
    height: f64,
}

let width = 2.0;
let height = 3.0;

let rect = Rectangle {
    width,   // <-
    height,  // <-
};
fn main() {
struct Rectangle {
    width: f64,
    height: f64,
}

let width = 2.0;
let height = 3.0;

let rect = Rectangle {
    width,   // <-
    height,  // <-
};
}

Методи и асоциирани функции

Асоциирани функции

Методи и асоциирани функции

Асоциирани функции

1 2 3 4 5 6 7 8 9 10 11
struct User { ... }

impl User {
    fn new(username: String, email: String) -> User {
        User {
            username: username,
            email: email,
            sign_in_count: 0,
        }
    }
}
fn main() {}
struct User { username: String, email: String, sign_in_count: u64 }
/*
struct User { ... }
*/

impl User {
    fn new(username: String, email: String) -> User {
        User {
            username: username,
            email: email,
            sign_in_count: 0,
        }
    }
}

Методи и асоциирани функции

Асоциирани функции

1 2 3 4 5 6 7 8 9 10 11
struct User { ... }

impl User {
    fn new(username: String, email: String) -> User {
        User {
            username: username,
            email: email,
            sign_in_count: 0,
        }
    }
}
fn main() {}
struct User { username: String, email: String, sign_in_count: u64 }
/*
struct User { ... }
*/

impl User {
    fn new(username: String, email: String) -> User {
        User {
            username: username,
            email: email,
            sign_in_count: 0,
        }
    }
}

Методи и асоциирани функции

Асоциирани функции

1 2 3 4 5 6 7 8 9 10 11
struct User { ... }

impl User {
    fn new(username: String, email: String) -> User {
        User {
            username: username,
            email: email,
            sign_in_count: 0,
        }
    }
}
fn main() {}
struct User { username: String, email: String, sign_in_count: u64 }
/*
struct User { ... }
*/

impl User {
    fn new(username: String, email: String) -> User {
        User {
            username: username,
            email: email,
            sign_in_count: 0,
        }
    }
}

Методи и асоциирани функции

Асоциирани функции

1 2 3 4 5 6 7 8 9 10 11
struct User { ... }

impl User {
    fn new(username: String, email: String) -> User {
        User {
            username: username,
            email: email,
            sign_in_count: 0,
        }
    }
}
fn main() {}
struct User { username: String, email: String, sign_in_count: u64 }
/*
struct User { ... }
*/

impl User {
    fn new(username: String, email: String) -> User {
        User {
            username: username,
            email: email,
            sign_in_count: 0,
        }
    }
}

Методи и асоциирани функции

Асоциирани функции

1 2 3 4 5 6 7 8 9 10 11 12 13
struct User { ... }

impl User {
    fn new(username: String, email: String) -> User {
        User {
            username: username,
            email: email,
            sign_in_count: 0,
        }
    }
}

let user = User::new(String::from("Иванчо"), String::from("ivan40@abv.bg"));
struct User { username: String, email: String, sign_in_count: u64 }
/*
struct User { ... }
*/

impl User {
    fn new(username: String, email: String) -> User {
        User {
            username: username,
            email: email,
            sign_in_count: 0,
        }
    }
}

fn main() {
let user = User::new(String::from("Иванчо"), String::from("ivan40@abv.bg"));
}

Методи и асоциирани функции

Асоциирани функции

1 2 3 4 5 6 7 8 9 10 11 12 13
struct User { ... }

impl User {
    fn new(username: String, email: String) -> User {
        User {
            username: username,
            email: email,
            sign_in_count: 0,
        }
    }
}

let user = User::new(String::from("Иванчо"), String::from("ivan40@abv.bg"));
struct User { username: String, email: String, sign_in_count: u64 }
/*
struct User { ... }
*/

impl User {
    fn new(username: String, email: String) -> User {
        User {
            username: username,
            email: email,
            sign_in_count: 0,
        }
    }
}

fn main() {
let user = User::new(String::from("Иванчо"), String::from("ivan40@abv.bg"));
}

Методи и асоциирани функции

Конструктори и деструктори

Методи и асоциирани функции

Конструктори и деструктори

Методи и асоциирани функции

Конструктори и деструктори

Методи и асоциирани функции

Конструктори и деструктори

Методи и асоциирани функции

Конструктори и деструктори

Методи и асоциирани функции

Конструктори и деструктори

Методи и асоциирани функции

Типа Self

1 2 3 4 5 6 7
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn new(width: f64, height: f64) -> Self {
        Self { width, height }
    }
}
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn new(width: f64, height: f64) -> Self {
        Self { width, height }
    }
}
fn main() {}

Методи и асоциирани функции

Типа Self

1 2 3 4 5 6 7
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn new(width: f64, height: f64) -> Self {
        Self { width, height }
    }
}
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn new(width: f64, height: f64) -> Self {
        Self { width, height }
    }
}
fn main() {}

Методи и асоциирани функции

Типа Self

1 2 3 4 5 6 7
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn new(width: f64, height: f64) -> Self {
        Self { width, height }
    }
}
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn new(width: f64, height: f64) -> Self {
        Self { width, height }
    }
}
fn main() {}

Методи и асоциирани функции

Методи

1 2 3 4 5 6 7
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}
fn main() {}

Методи и асоциирани функции

Методи

1 2 3 4 5 6 7
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}
fn main() {}

Методи и асоциирани функции

Методи

1 2 3 4 5 6 7
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}
fn main() {}

Методи и асоциирани функции

Методи

1 2 3 4 5 6 7
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}
fn main() {}

Методи и асоциирани функции

Методи

1 2 3 4 5 6 7
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}
fn main() {}

Методи и асоциирани функции

Методи

Могат да се извикват със синтаксиса за методи

1 2 3 4 5 6 7 8 9 10 11 12
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}

let rect = Rectangle::new(2.0, 3.0);
let area = rect.area();

println!("area = {}", area);
area = 6
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
fn new(width: f64, height: f64) -> Self { Self { width, height } }
    fn area(&self) -> f64 {
        self.width * self.height
    }
}

fn main() {
let rect = Rectangle::new(2.0, 3.0);
let area = rect.area();

println!("area = {}", area);
}

Методи и асоциирани функции

Методи

Могат да се извикват със синтаксиса за методи

1 2 3 4 5 6 7 8 9 10 11 12
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}

let rect = Rectangle::new(2.0, 3.0);
let area = rect.area();

println!("area = {}", area);
area = 6
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
fn new(width: f64, height: f64) -> Self { Self { width, height } }
    fn area(&self) -> f64 {
        self.width * self.height
    }
}

fn main() {
let rect = Rectangle::new(2.0, 3.0);
let area = rect.area();

println!("area = {}", area);
}

Методи и асоциирани функции

Методи

Могат да се извикват със синтаксиса за методи

1 2 3 4 5 6 7 8 9 10 11 12
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}

let rect = Rectangle::new(2.0, 3.0);
let area = rect.area();

println!("area = {}", area);
area = 6
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
fn new(width: f64, height: f64) -> Self { Self { width, height } }
    fn area(&self) -> f64 {
        self.width * self.height
    }
}

fn main() {
let rect = Rectangle::new(2.0, 3.0);
let area = rect.area();

println!("area = {}", area);
}

Методи и асоциирани функции

Методи

Могат да се извикват и като асоциирани функции

1 2 3 4 5 6 7 8 9 10 11 12
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}

let rect = Rectangle::new(2.0, 3.0);
let area = Rectangle::area(&rect);

println!("area = {}", area);
area = 6
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
fn new(width: f64, height: f64) -> Self { Self { width, height } }
    fn area(&self) -> f64 {
        self.width * self.height
    }
}

fn main() {
let rect = Rectangle::new(2.0, 3.0);
let area = Rectangle::area(&rect);

println!("area = {}", area);
}

Методи и асоциирани функции

Множество impl блокове

Позволено е декларирането на повече от един impl блок. Удобно е при групиране на методи.

1 2 3 4 5 6 7 8 9 10 11 12 13
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}

impl Rectangle {
    fn perimeter(&self) -> f64 {
        2.0 * (self.width + self.height)
    }
}
struct Rectangle { width: f64, height: f64 }

impl Rectangle {
    fn area(&self) -> f64 {
        self.width * self.height
    }
}

impl Rectangle {
    fn perimeter(&self) -> f64 {
        2.0 * (self.width + self.height)
    }
}
fn main() {}

Tuples

(преговор)

1 2 3 4 5
let tuple: (i32, u32, bool) = (1, 2, false);

println!("{}", tuple.0);
println!("{}", tuple.1);
println!("{}", tuple.2);
1 2 false
fn main() {
let tuple: (i32, u32, bool) = (1, 2, false);

println!("{}", tuple.0);
println!("{}", tuple.1);
println!("{}", tuple.2);
}

Tuple structs

Именувани кортежи

1 2 3 4 5
struct Color(f32, f32, f32);
struct Point(f32, f32, f32);

let black = Color(0.0, 0.0, 0.0);
let origin = Point(0.0, 0.0, 0.0);
fn main() {
struct Color(f32, f32, f32);
struct Point(f32, f32, f32);

let black = Color(0.0, 0.0, 0.0);
let origin = Point(0.0, 0.0, 0.0);
}

Tuple structs

Полетата се достъпват с .0, .1, и т.н., както при нормален tupple

1 2 3 4 5
struct Color(f32, f32, f32);

let black = Color(0.0, 0.0, 0.0);

println!("r: {}, g: {}, b: {}", black.0, black.1, black.2);
r: 0, g: 0, b: 0
fn main() {
struct Color(f32, f32, f32);

let black = Color(0.0, 0.0, 0.0);

println!("r: {}, g: {}, b: {}", black.0, black.1, black.2);
}

Tuple structs

Newtype wrapper

Tuple struct с едно поле често се използва за typesafe wrapper.
Това се нарича newtype struct или newtype wrapper.

1 2
#[derive(Debug, Clone, Copy)]
struct Token(u32);
error[E0601]: `main` function not found in crate `main_242a768ca6459a870293f82d4666e2367fefbd30` --> src\bin\main_242a768ca6459a870293f82d4666e2367fefbd30.rs:1:1 | 1 | / #[derive(Debug, Clone, Copy)] 2 | | struct Token(u32); | |__________________^ consider adding a `main` function to `src\bin\main_242a768ca6459a870293f82d4666e2367fefbd30.rs` For more information about this error, try `rustc --explain E0601`. error: could not compile `rust` due to previous error
#[derive(Debug, Clone, Copy)]
struct Token(u32);

Празни структури

Възможна е декларацията на празни структури. Могат да се използват като маркери - големината им е 0 байта.

1 2 3 4 5
struct Electron {}
struct Proton;

let x = Electron {};
let y = Proton;
fn main() {
struct Electron {}
struct Proton;

let x = Electron {};
let y = Proton;
}

Модули

Модули

Модули

Модули

Нека си създадем библиотека:

$ cargo new communicator --lib

1 2 3 4
communicator
├── Cargo.toml
└── src
    └── lib.rs

Модули

Модули

Можем да дефинираме подмодули в същия файл

1 2 3 4 5 6 7 8 9 10 11 12 13
// src/lib.rs

mod network {
    fn connect() {
        // ...
    }
}

mod client {
    fn connect() {
        // ...
    }
}
mod network {
    fn connect() {
        // ...
    }
}

mod client {
    fn connect() {
        // ...
    }
}
fn main() {}

Модули

Можем да дефинираме подмодули и в отделни файлове

1 2 3 4 5 6
communicator
├── Cargo.toml
└── src
    ├── client.rs
    ├── lib.rs
    └── network.rs
1 2 3 4
// src/lib.rs

mod network;
mod client;

1 2 3 4 5
// src/network.rs

fn connect() {
    // ...
}

fn connect() {
    // ...
}
fn main() {}

1 2 3 4 5
// src/client.rs

fn connect() {
    // ...
}

fn connect() {
    // ...
}
fn main() {}

Модули

Можем да дефинираме подмодули и в отделни файлове

1 2 3 4 5 6
communicator
├── Cargo.toml
└── src
    ├── client.rs
    ├── lib.rs
    └── network.rs
1 2 3 4
// src/lib.rs

mod network;
mod client;

1 2 3 4 5
// src/network.rs

fn connect() {
    // ...
}

fn connect() {
    // ...
}
fn main() {}

1 2 3 4 5
// src/client.rs

fn connect() {
    // ...
}

fn connect() {
    // ...
}
fn main() {}

Модули

Можем да имаме няколко нива на подмодули

1 2 3 4 5 6 7 8 9 10 11 12 13
// src/lib.rs

mod network {
    fn connect() {
        // ...
    }

    mod client {
        fn connect() {
            // ...
        }
    }
}
mod network {
    fn connect() {
        // ...
    }

    mod client {
        fn connect() {
            // ...
        }
    }
}

fn main() {}

Модули

Ако искаме да са в отделни файлове трябва да използваме директории

1 2 3 4 5 6 7
communicator
├── Cargo.toml
└── src
    ├── lib.rs
    └── network
        ├── client.rs
        └── mod.rs
1 2 3
// src/lib.rs

mod network;
1 2 3 4 5 6 7
// src/network/mod.rs

mod client;

fn connect() {
    // ...
}
1 2 3 4 5
// src/network/client.rs

fn connect() {
    // ...
}
fn connect() {
    // ...
}
fn main() {}

Модули

network модула може да го сложим или в src/network/mod.rs, или в src/network.rs

1 2 3 4 5 6 7
communicator
├── Cargo.toml
└── src
    ├── lib.rs
    ├── network.rs
    └── network
        └── client.rs
1 2 3
// src/lib.rs

mod network;
1 2 3 4 5 6 7
// src/network.rs

mod client;

fn connect() {
    // ...
}
1 2 3 4 5
// src/network/client.rs

fn connect() {
    // ...
}
fn connect() {
    // ...
}
fn main() {}

Достъп

В модул имаме директен достъп до всичко останало дефинирано в модула

1 2 3 4 5 6 7 8
mod client {
    fn connect() { /* ... */ }

    fn init() {
        // client::connect();
        connect();
    }
}
mod client {
    fn connect() { /* ... */ }

    fn init() {
        // client::connect();
        connect();
    }
}
fn main() {}

Достъп

Ако искаме да използваме нещо извън модула трябва да използваме пълното име

1 2 3 4 5 6 7 8 9
mod client {
    fn connect() { /* ... */ }
}

mod network {
    fn init() {
        crate::client::connect();
    }
}

Достъп

Ако искаме да използваме нещо извън модула трябва да използваме пълното име

1 2 3 4 5 6 7 8 9
mod client {
    fn connect() { /* ... */ }
}

mod network {
    fn init() {
        crate::client::connect();
    }
}

Достъп

Ако искаме да използваме нещо извън модула трябва да използваме пълното име

1 2 3 4 5 6 7 8 9
mod client {
    fn connect() { /* ... */ }
}

mod network {
    fn init() {
        crate::client::connect();
    }
}

Достъп

Ако искаме да използваме нещо извън модула трябва да използваме пълното име

1 2 3 4 5 6 7 8 9
mod client {
    fn connect() { /* ... */ }
}

mod network {
    fn init() {
        crate::client::connect();
    }
}

Достъп

Ако искаме да използваме нещо извън модула трябва да използваме пълното име..

1 2 3 4 5 6 7 8 9
mod client {
    fn connect() { /* ... */ }
}

mod network {
    fn init() {
        crate::client::connect();
    }
}
error[E0603]: function `connect` is private --> src\bin\main_45cfa89b529115e6bc0921c5bdec3a299e3e5247.rs:7:24 | 7 | crate::client::connect(); | ^^^^^^^ private function | note: the function `connect` is defined here --> src\bin\main_45cfa89b529115e6bc0921c5bdec3a299e3e5247.rs:2:5 | 2 | fn connect() { /* ... */ } | ^^^^^^^^^^^^ For more information about this error, try `rustc --explain E0603`. error: could not compile `rust` due to previous error
mod client {
    fn connect() { /* ... */ }
}

mod network {
    fn init() {
        crate::client::connect();
    }
}
fn main() {}

Достъп

… и освен това то трябва да е публично достъпно (keyword pub)

1 2 3 4 5 6 7 8 9
mod client {
    pub fn connect() { /* ... */ }
}

mod network {
    fn init() {
        crate::client::connect();
    }
}
mod client {
    pub fn connect() { /* ... */ }
}

mod network {
    fn init() {
        crate::client::connect();
    }
}
fn main() {}

Достъп

Можем да използваме use за да импортираме имена от друг модул

1 2 3 4 5 6 7 8 9 10 11
mod client {
    pub fn connect() { /* ... */ }
}

mod network {
    use crate::client::connect;

    fn init() {
        connect();
    }
}
mod client {
    pub fn connect() { /* ... */ }
}

mod network {
    use crate::client::connect;

    fn init() {
        connect();
    }
}
fn main() {}

Достъп

Можем да използваме use за да импортираме имена от друг модул

1 2 3 4 5 6 7 8 9 10 11
mod client {
    pub fn connect() { /* ... */ }
}

mod network {
    use crate::client::connect;

    fn init() {
        connect();
    }
}
mod client {
    pub fn connect() { /* ... */ }
}

mod network {
    use crate::client::connect;

    fn init() {
        connect();
    }
}
fn main() {}

Достъп

Можем да използваме use за да импортираме имена от друг модул

1 2 3 4 5 6 7 8 9 10 11
mod client {
    pub fn connect() { /* ... */ }
}

mod network {
    use crate::client::connect;

    fn init() {
        connect();
    }
}
mod client {
    pub fn connect() { /* ... */ }
}

mod network {
    use crate::client::connect;

    fn init() {
        connect();
    }
}
fn main() {}

Достъп

Ако искаме да импортираме неща от подмодул, може да използваме use self::... или use super::... за релативен път

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
mod network {
    mod client {
        // еквивалентно на use crate::network::init;
        use super::init;

        pub fn connect() { /* ... */ }
    }

    // еквивалентно на use crate::network::client::connect;
    use self::client::connect;

    fn init() {
        connect();
    }
}
#![allow(unused_imports)]
mod network {
    mod client {
        // еквивалентно на use crate::network::init;
        use super::init;

        pub fn connect() { /* ... */ }
    }

    // еквивалентно на use crate::network::client::connect;
    use self::client::connect;

    fn init() {
        connect();
    }
}
fn main() {}

Достъп: public и private

Достъп: public и private

Достъп: public и private

Достъп: public и private

Достъп: public и private

Нека да пуснем следния код

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
mod product {
    pub struct User {
        username: String,
        email: String,
    }
}

use self::product::User;

fn main() {
    let user = User {
        username: String::from("Иванчо"),
        email: String::from("ivan40@abv.bg"),
    };
}

Достъп: public и private

Резултата

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
mod product {
    pub struct User {
        username: String,
        email: String,
    }
}

use self::product::User;

fn main() {
    let user = User {
        username: String::from("Иванчо"),
        email: String::from("ivan40@abv.bg"),
    };
}
error[E0451]: field `username` of struct `User` is private --> src\bin\main_c0fba21675df6ceed4f332d59bc57cc61d74014d.rs:12:9 | 12 | username: String::from("Иванчо"), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private field error[E0451]: field `email` of struct `User` is private --> src\bin\main_c0fba21675df6ceed4f332d59bc57cc61d74014d.rs:13:9 | 13 | email: String::from("ivan40@abv.bg"), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private field For more information about this error, try `rustc --explain E0451`. error: could not compile `rust` due to 2 previous errors
mod product {
    pub struct User {
        username: String,
        email: String,
    }
}

use self::product::User;

fn main() {
    let user = User {
        username: String::from("Иванчо"),
        email: String::from("ivan40@abv.bg"),
    };
}

Достъп: public и private

Както казахме, по подразбиране всичко е private за външни модули, включително и полета на структурата.
Затова трябва да ги отбележим с pub.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
mod product {
    pub struct User {
        pub username: String,
        pub email: String,
    }
}

use self::product::User;

fn main() {
    let user = User {
        username: String::from("Иванчо"),
        email: String::from("ivan40@abv.bg"),
    };
}
mod product {
    pub struct User {
        pub username: String,
        pub email: String,
    }
}

use self::product::User;

fn main() {
    let user = User {
        username: String::from("Иванчо"),
        email: String::from("ivan40@abv.bg"),
    };
}

Достъп: public и private

Без проблем може да достъпим private полета от същия модул в който е дефинирана структурата

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
mod product {
    pub struct User {
        username: String,
        email: String,
    }

    pub fn new(username: String, email: String) -> User {
        User { username, email }
    }
}

fn main() {
    let user = product::new(
        String::from("Иванчо"),
        String::from("ivan40@abv.bg"),
    );
}
mod product {
    pub struct User {
        username: String,
        email: String,
    }

    pub fn new(username: String, email: String) -> User {
        User { username, email }
    }
}

fn main() {
    let user = product::new(
        String::from("Иванчо"),
        String::from("ivan40@abv.bg"),
    );
}

Достъп: public и private

Както и без проблем може да достъпим private полета от подмодул

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
mod product {
    pub struct User {
        username: String,
        email: String,
    }

    pub mod init_user {
        use super::User;

        pub fn new(username: String, email: String) -> User {
            User { username, email }
        }
    }
}

fn main() {
    let user = product::init_user::new(
        String::from("Иванчо"),
        String::from("ivan40@abv.bg"),
    );
}
mod product {
    pub struct User {
        username: String,
        email: String,
    }

    pub mod init_user {
        use super::User;

        pub fn new(username: String, email: String) -> User {
            User { username, email }
        }
    }
}

fn main() {
    let user = product::init_user::new(
        String::from("Иванчо"),
        String::from("ivan40@abv.bg"),
    );
}

Достъп: public и private

Но ако модулите са съседни не можем

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
mod product {
    mod dto {
        pub struct User {
            username: String,
            email: String,
        }
    }

    pub mod init_user {
        use super::dto::User;

        pub fn new(username: String, email: String) -> User {
            User { username, email }
        }
    }
}
error[E0451]: field `username` of struct `User` is private --> src\bin\main_6b1a305aea173c6966b97719e25b5ec58a4f6555.rs:13:20 | 13 | User { username, email } | ^^^^^^^^ private field error[E0451]: field `email` of struct `User` is private --> src\bin\main_6b1a305aea173c6966b97719e25b5ec58a4f6555.rs:13:30 | 13 | User { username, email } | ^^^^^ private field For more information about this error, try `rustc --explain E0451`. error: could not compile `rust` due to 2 previous errors
mod product {
    mod dto {
        pub struct User {
            username: String,
            email: String,
        }
    }

    pub mod init_user {
        use super::dto::User;

        pub fn new(username: String, email: String) -> User {
            User { username, email }
        }
    }
}
fn main() {}

Достъп: public и private

Тези правила важат и за tuple structs

1 2 3 4 5 6 7 8 9
mod product {
    pub struct UserId(u64);
}

use self::product::UserId;

fn main() {
    let id = UserId(123);
}
error[E0423]: cannot initialize a tuple struct which contains private fields --> src\bin\main_4ab3111369e2922d14fb54434dca1a25870e2bd1.rs:8:14 | 8 | let id = UserId(123); | ^^^^^^ | note: constructor is not visible here due to private fields --> src\bin\main_4ab3111369e2922d14fb54434dca1a25870e2bd1.rs:2:23 | 2 | pub struct UserId(u64); | ^^^ private field For more information about this error, try `rustc --explain E0423`. error: could not compile `rust` due to previous error
mod product {
    pub struct UserId(u64);
}

use self::product::UserId;

fn main() {
    let id = UserId(123);
}

Достъп: public и private

Тези правила важат и за tuple structs

1 2 3 4 5 6 7 8 9
mod product {
    pub struct UserId(pub u64);
}

use self::product::UserId;

fn main() {
    let id = UserId(123);
}
mod product {
    pub struct UserId(pub u64);
}

use self::product::UserId;

fn main() {
    let id = UserId(123);
}

Пакети

Пакети

Ще си направим игра за отгатване на число

$ cargo new number_guessing_game --bin

Пакети

Пакети

Пакети

Пакети

Cargo.toml

Трябва да си добавим пакета като зависомист на проекта ни

1 2 3 4 5 6 7
[package]
name = "number_guessing_game"
version = "0.1.0"
authors = ["..."]
edition = "2018"

[dependencies]

Cargo.toml

Трябва да си добавим пакета като зависомист на проекта ни

1 2 3 4 5 6 7 8
[package]
name = "number_guessing_game"
version = "0.1.0"
authors = ["..."]
edition = "2018"

[dependencies]
rand = "0.7.2"

Използване

След като се добави библиотека в [dependencies], може да се използва както всеки останал модул

1 2 3
use rand::*;

// ...

Документация

Документация

Имплементация

Live demo

Имплементация

Код от демото

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
use rand::prelude::*;
use std::io::{self, Write};

fn main() {
    // Generate a random number between 0 and 10
    let secret = rand::thread_rng().gen_range(0, 10_u32);
    let stdin = io::stdin();

    let tries = 5;
    println!("You have {} tries to guess the number. Good luck!", tries);

    for _ in 0..tries {
        // Note that stdout is frequently line-buffered by default so it may be necessary
        // to use io::stdout().flush() to ensure the output is emitted immediately.
        print!("Your guess: ");
        let _ = io::stdout().flush();

        let mut line = String::new();
        let _ = stdin.read_line(&mut line);

        // No error handling - panic if parsing fails
        let guess: u32 =
            line
            .trim()
            .parse()
            .unwrap();

        if secret < guess {
            println!("I am less than that");
        } else if secret > guess {
            println!("I am greater than that");
        } else {
            println!("Congratulations, you won!");
            return;
        }
    }

    println!("The number was {}", secret);
}

Въпроси