mirror of https://github.com/01-edu/public.git
quest 08: tests and subject
This commit is contained in:
parent
e170a345d0
commit
6bd54ffb5c
|
@ -0,0 +1,12 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "borrow_box"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "borrow_box_test"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"borrow_box",
|
||||
]
|
|
@ -0,0 +1,10 @@
|
|||
[package]
|
||||
name = "borrow_box_test"
|
||||
version = "0.1.0"
|
||||
authors = ["lee <lee-dasilva@hotmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
borrow_box = { path = "../../../../rust-piscine-solutions/borrow_box"}
|
|
@ -0,0 +1,91 @@
|
|||
use borrow_box::*;
|
||||
|
||||
fn main() {
|
||||
let mut game = Game::new(0, String::from("Joao"), String::from("Susana"), 5);
|
||||
println!("{:?}", game.read_winner());
|
||||
// output : ("Same score! tied", 0)
|
||||
|
||||
game.update_score(String::from("Joao"));
|
||||
game.update_score(String::from("Joao"));
|
||||
game.update_score(String::from("Susana"));
|
||||
game.update_score(String::from("Susana"));
|
||||
println!("{:?}", game.read_winner());
|
||||
// output : ("Same score! tied", 2)
|
||||
|
||||
game.update_score(String::from("Joao"));
|
||||
// this one will not count because it already 5 games played, the nbr_of_games
|
||||
game.update_score(String::from("Susana"));
|
||||
|
||||
println!("{:?}", game.read_winner());
|
||||
// output : ("Joao", 3)
|
||||
|
||||
println!("{:?}", game.delete());
|
||||
// output : "game deleted: id -> 0"
|
||||
|
||||
// game.read_winner();
|
||||
// this will give error
|
||||
// because the game was dropped, no longer exists on the heap
|
||||
}
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
fn create_games() -> Vec<Box<Game>> {
|
||||
vec![
|
||||
Game::new(0, String::from("player1"), String::from("player2"), 1),
|
||||
Game::new(1, String::from("Alice"), String::from("Mark"), 3),
|
||||
Game::new(2, String::from("Jack"), String::from("Miller"), 5)
|
||||
]
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_create() {
|
||||
let games = create_games();
|
||||
assert_eq!(*games[0], Game {id: 0, p1: (String::from("player1"), 0), p2: (String::from("player2"), 0), nbr_of_games: 1});
|
||||
assert_eq!(*games[1], Game {id: 1, p1: (String::from("Alice"), 0), p2: (String::from("Mark"), 0), nbr_of_games: 3});
|
||||
assert_eq!(*games[2], Game {id: 2, p1: (String::from("Jack"), 0), p2: (String::from("Miller"), 0), nbr_of_games: 5});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_update_and_read() {
|
||||
let mut games = create_games();
|
||||
games[0].update_score(String::from("player1"));
|
||||
assert_eq!(games[0].read_winner(), (String::from("player1"), 1));
|
||||
|
||||
games[0].update_score(String::from("player2"));
|
||||
// this will stay the same because the nbr_of_games is 1 so if one
|
||||
// of the players wins just once it will no longer increment the score
|
||||
assert_eq!(games[0].read_winner(), (String::from("player1"), 1));
|
||||
|
||||
games[2].update_score(String::from("Jack"));
|
||||
games[2].update_score(String::from("Jack"));
|
||||
games[2].update_score(String::from("Miller"));
|
||||
games[2].update_score(String::from("Miller"));
|
||||
// tie between players
|
||||
assert_eq!(games[2].read_winner(), (String::from("Same score! tied"), 2));
|
||||
|
||||
games[2].update_score(String::from("Jack"));
|
||||
assert_eq!(games[2].read_winner(), (String::from("Jack"), 3));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_delete() {
|
||||
let game = Game::new(0, String::from("Alice"), String::from("Mark"), 3);
|
||||
let game1 = Game::new(23, String::from("Jack"), String::from("Miller"), 1);
|
||||
|
||||
assert_eq!(game.delete(), String::from("game deleted: id -> 0"));
|
||||
assert_eq!(game1.delete(), String::from("game deleted: id -> 23"));
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// #[should_panic]
|
||||
// fn test_delete_ownership() {
|
||||
// let game = new(0, String::from("Alice"), String::from("Mark"), 3);
|
||||
// {
|
||||
// let a = &game;
|
||||
// // error! cant destroy boxed while the inner value is borrowed later in scope
|
||||
// delete(game);
|
||||
// read_winner(&a);
|
||||
// }
|
||||
// }
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "box_it"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "box_it_test"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"box_it",
|
||||
]
|
|
@ -0,0 +1,10 @@
|
|||
[package]
|
||||
name = "box_it_test"
|
||||
version = "0.1.0"
|
||||
authors = ["lee <lee-dasilva@hotmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
box_it = { path = "../../../../rust-piscine-solutions/box_it"}
|
|
@ -0,0 +1,56 @@
|
|||
use box_it::*;
|
||||
|
||||
fn main() {
|
||||
let new_str = String::from("5.5k 8.9k 32");
|
||||
|
||||
// creating a variable and we save it in the Heap
|
||||
let a_h = transform_and_save_on_heap(new_str);
|
||||
println!("Box value : {:?}", &a_h);
|
||||
println!("size occupied in the stack : {:?} bytes", (std::mem::size_of_val(&a_h)));
|
||||
|
||||
let a_b_v = take_value_ownership(a_h);
|
||||
println!("value : {:?}", &a_b_v);
|
||||
println!("size occupied in the stack : {:?} bytes", (std::mem::size_of_val(&a_b_v)));
|
||||
// whenever the box, in this case "a_h", goes out of scope it will be deallocated, freed
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::mem;
|
||||
|
||||
#[test]
|
||||
fn test_transform() {
|
||||
let new_str = String::from("5.5k 8.9k 32");
|
||||
let new_str_1 = String::from("6.8k 13.5k");
|
||||
let new_str_2 = String::from("20.3k 3.8k 7.7k 992");
|
||||
|
||||
let a = transform_and_save_on_heap(new_str);
|
||||
let b = transform_and_save_on_heap(new_str_1);
|
||||
let c = transform_and_save_on_heap(new_str_2);
|
||||
|
||||
assert_eq!(a, Box::new(vec![5500, 8900, 32]));
|
||||
assert_eq!(b, Box::new(vec![6800, 13500]));
|
||||
assert_eq!(c, Box::new(vec![20300, 3800, 7700, 992]));
|
||||
assert_eq!(mem::size_of_val(&a), 8);
|
||||
assert_eq!(mem::size_of_val(&b), 8);
|
||||
assert_eq!(mem::size_of_val(&c), 8);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_take_value_from_box() {
|
||||
let new_str = String::from("5.5k 8.9k 32");
|
||||
let new_str_1 = String::from("6.8k 13.5k");
|
||||
let new_str_2 = String::from("20.3k 3.8k 7.7k 992");
|
||||
let a = take_value_ownership(transform_and_save_on_heap(new_str));
|
||||
let b = take_value_ownership(transform_and_save_on_heap(new_str_1));
|
||||
let c = take_value_ownership(transform_and_save_on_heap(new_str_2));
|
||||
|
||||
assert_eq!(a, vec![5500, 8900, 32]);
|
||||
assert_eq!(b, vec![6800, 13500]);
|
||||
assert_eq!(c, vec![20300, 3800, 7700, 992]);
|
||||
assert_eq!(mem::size_of_val(&a), 24);
|
||||
assert_eq!(mem::size_of_val(&b), 24);
|
||||
assert_eq!(mem::size_of_val(&c), 24);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "box_recursion"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "box_recursion_test"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"box_recursion",
|
||||
]
|
|
@ -0,0 +1,10 @@
|
|||
[package]
|
||||
name = "box_recursion_test"
|
||||
version = "0.1.0"
|
||||
authors = ["lee <lee-dasilva@hotmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
box_recursion = { path = "../../../../rust-piscine-solutions/box_recursion"}
|
|
@ -0,0 +1,98 @@
|
|||
use box_recursion::*;
|
||||
|
||||
fn main() {
|
||||
let mut list = WorkEnvironment::new();
|
||||
list.add_worker(String::from("CEO"), String::from("Marie"));
|
||||
list.add_worker(String::from("Manager"), String::from("Monica"));
|
||||
list.add_worker(String::from("Normal Worker"), String::from("Ana"));
|
||||
list.add_worker(String::from("Normal Worker"), String::from("Alice"));
|
||||
println!("{:?}", list);
|
||||
|
||||
println!("{:?}", list.search_worker());
|
||||
|
||||
list.remove_worker();
|
||||
list.remove_worker();
|
||||
list.remove_worker();
|
||||
list.remove_worker();
|
||||
println!("{:?}", list);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_new() {
|
||||
let list = WorkEnvironment::new();
|
||||
assert!(list.grade.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_one_worker() {
|
||||
let mut list = WorkEnvironment::new();
|
||||
list.add_worker(String::from("CEO"), String::from("Marie"));
|
||||
list.remove_worker();
|
||||
assert!(list.grade.is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_two_workers() {
|
||||
let mut list = WorkEnvironment::new();
|
||||
list.add_worker(String::from("CEO"), String::from("Marie"));
|
||||
list.add_worker(String::from("Manager"), String::from("Monica"));
|
||||
list.remove_worker();
|
||||
|
||||
assert_eq!(list.grade.as_ref().unwrap().worker_type, "CEO");
|
||||
assert_eq!(list.grade.as_ref().unwrap().worker_name, "Marie");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_more_workers() {
|
||||
let mut list = WorkEnvironment::new();
|
||||
list.add_worker(String::from("CEO"), String::from("Marie"));
|
||||
list.add_worker(String::from("Manager"), String::from("Monica"));
|
||||
list.add_worker(String::from("Normal Worker"), String::from("Ana"));
|
||||
list.add_worker(String::from("Normal Worker"), String::from("Alice"));
|
||||
list.remove_worker();
|
||||
|
||||
assert_eq!(list.grade.as_ref().unwrap().worker_type, "Normal Worker");
|
||||
assert_eq!(list.grade.as_ref().unwrap().worker_name, "Ana");
|
||||
|
||||
list.remove_worker();
|
||||
list.remove_worker();
|
||||
assert_eq!(list.grade.as_ref().unwrap().worker_type, "CEO");
|
||||
assert_eq!(list.grade.as_ref().unwrap().worker_name, "Marie");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_search() {
|
||||
let mut list = WorkEnvironment::new();
|
||||
list.add_worker(String::from("CEO"), String::from("Marie"));
|
||||
list.add_worker(String::from("Manager"), String::from("Monica"));
|
||||
list.add_worker(String::from("Normal Worker"), String::from("Ana"));
|
||||
list.add_worker(String::from("Normal Worker"), String::from("Alice"));
|
||||
|
||||
assert_eq!(
|
||||
list.search_worker().unwrap(),
|
||||
(String::from("Alice"), String::from("Normal Worker"))
|
||||
);
|
||||
|
||||
list.remove_worker();
|
||||
assert_eq!(
|
||||
list.search_worker().unwrap(),
|
||||
(String::from("Ana"), String::from("Normal Worker"))
|
||||
);
|
||||
|
||||
list.remove_worker();
|
||||
assert_eq!(
|
||||
list.search_worker().unwrap(),
|
||||
(String::from("Monica"), String::from("Manager"))
|
||||
);
|
||||
|
||||
list.remove_worker();
|
||||
assert_eq!(
|
||||
list.search_worker().unwrap(),
|
||||
(String::from("Marie"), String::from("CEO"))
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "drop_the_thread"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "drop_the_thread_test"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"drop_the_thread",
|
||||
]
|
|
@ -0,0 +1,10 @@
|
|||
[package]
|
||||
name = "drop_the_thread_test"
|
||||
version = "0.1.0"
|
||||
authors = ["lee <lee-dasilva@hotmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
drop_the_thread = { path = "../../../../rust-piscine-solutions/drop_the_thread"}
|
|
@ -0,0 +1,87 @@
|
|||
use drop_the_thread::*;
|
||||
use std::rc::Rc;
|
||||
|
||||
fn main() {
|
||||
let worker = Workers::new();
|
||||
let (id, thread) = worker.new_worker(String::from("command"));
|
||||
let (id1, thread1) = worker.new_worker(String::from("command1"));
|
||||
|
||||
thread.skill();
|
||||
|
||||
println!("{:?}", (worker.is_dropped(id), id, &worker.drops));
|
||||
// output: (true, 0, Cell { value: 1 })
|
||||
|
||||
thread1.skill();
|
||||
println!("{:?}", (worker.is_dropped(id1), id1, &worker.drops));
|
||||
// output: (true, 1, Cell { value: 2 })
|
||||
|
||||
let (id2, thread2) = worker.new_worker(String::from("command2"));
|
||||
let thread2 = Rc::new(thread2);
|
||||
let thread2_clone = thread2.clone();
|
||||
|
||||
// thread2_clone.skill();
|
||||
drop(thread2_clone);
|
||||
|
||||
println!("{:?}", (worker.is_dropped(id2), id2, &worker.drops, Rc::strong_count(&thread2)));
|
||||
// (false, 2, Cell { value: 2 }, 1)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::rc::Rc;
|
||||
|
||||
#[test]
|
||||
fn test_is_dropped_and_drops() {
|
||||
let worker = Workers::new();
|
||||
let (pid, thread) = worker.new_worker(String::from("gnome-shell"));
|
||||
let (pid0, thread0) = worker.new_worker(String::from("i3"));
|
||||
let (pid1, thread1) = worker.new_worker(String::from("shell"));
|
||||
let (pid2, thread2) = worker.new_worker(String::from("spotify"));
|
||||
|
||||
thread.skill();
|
||||
assert_eq!(worker.drops.get(), 1_usize);
|
||||
thread0.skill();
|
||||
|
||||
assert!(worker.is_dropped(pid), "{} should have been dropped", pid);
|
||||
assert!(worker.is_dropped(pid0), "{} should have been dropped", pid0);
|
||||
assert!(!worker.is_dropped(pid1), "{} should not have been dropped", pid1);
|
||||
assert!(!worker.is_dropped(pid2), "{} should not have been dropped", pid2);
|
||||
|
||||
assert_eq!(worker.drops.get(), 2_usize);
|
||||
|
||||
thread1.skill();
|
||||
thread2.skill();
|
||||
|
||||
assert_eq!(worker.drops.get(), 4_usize);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_using_rc() {
|
||||
// will create a new reference to the thread
|
||||
// this will test the following
|
||||
// if we drop the cloned value the RC will decrease
|
||||
// but the thread will not be dropped!
|
||||
let worker = Workers::new();
|
||||
let (_, thread) = worker.new_worker(String::from("Xorg"));
|
||||
let thread = Rc::new(thread);
|
||||
let thread_clone = thread.clone();
|
||||
|
||||
assert_eq!(Rc::strong_count(&thread), 2);
|
||||
|
||||
drop(thread_clone);
|
||||
|
||||
assert_eq!(Rc::strong_count(&thread), 1);
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "0 is already dropped")]
|
||||
fn test_drop_same_thread() {
|
||||
// test if we drop the same thread after it was already been dropped
|
||||
let worker = Workers::new();
|
||||
let (pid, thread) = worker.new_worker(String::from("gsd-rfkill"));
|
||||
let thread_clone = thread.clone();
|
||||
thread.skill();
|
||||
thread_clone.skill();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "how_many_references"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "how_many_references_test"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"how_many_references",
|
||||
]
|
|
@ -0,0 +1,10 @@
|
|||
[package]
|
||||
name = "how_many_references_test"
|
||||
version = "0.1.0"
|
||||
authors = ["lee <lee-dasilva@hotmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
how_many_references = { path = "../../../../rust-piscine-solutions/how_many_references"}
|
|
@ -0,0 +1,103 @@
|
|||
use how_many_references::*;
|
||||
|
||||
fn main() {
|
||||
let a = Rc::new(String::from("a"));
|
||||
let b = Rc::new(String::from("b"));
|
||||
let c = Rc::new(String::from("c"));
|
||||
|
||||
let a1 = Rc::new(String::from("a"));
|
||||
|
||||
let mut new_node = Node::new(vec![a.clone()]);
|
||||
new_node.add_ele(b.clone());
|
||||
new_node.add_ele(a.clone());
|
||||
new_node.add_ele(c.clone());
|
||||
new_node.add_ele(a.clone());
|
||||
|
||||
println!("a: {:?}", how_many_references(&a));
|
||||
println!("b: {:?}", how_many_references(&b));
|
||||
println!("c: {:?}", how_many_references(&c));
|
||||
new_node.rm_all_ref(a1.clone());
|
||||
new_node.rm_all_ref(a.clone());
|
||||
|
||||
println!("a: {:?}", how_many_references(&a));
|
||||
println!("b: {:?}", how_many_references(&b));
|
||||
println!("c: {:?}", how_many_references(&c));
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_add_ele() {
|
||||
let a = Rc::new(String::from("a"));
|
||||
let b = Rc::new(String::from("b"));
|
||||
let c = Rc::new(String::from("c"));
|
||||
|
||||
let mut new_node = Node::new(vec![a.clone()]);
|
||||
new_node.add_ele(a.clone());
|
||||
new_node.add_ele(b.clone());
|
||||
new_node.add_ele(c.clone());
|
||||
|
||||
assert_eq!(new_node.value, vec![a.clone(), a, b, c]);
|
||||
}
|
||||
#[test]
|
||||
fn test_how_many_references() {
|
||||
let a = Rc::new(String::from("a"));
|
||||
let b = Rc::new(String::from("b"));
|
||||
let c = Rc::new(String::from("c"));
|
||||
let d = Rc::new(String::from("d"));
|
||||
let mut new_node = Node::new(vec![]);
|
||||
new_node.add_ele(b.clone());
|
||||
new_node.add_ele(a.clone());
|
||||
new_node.add_ele(c.clone());
|
||||
new_node.add_ele(a.clone());
|
||||
|
||||
assert_eq!(how_many_references(&d), 1);
|
||||
assert_eq!(how_many_references(&a), 3);
|
||||
assert_eq!(how_many_references(&b), 2);
|
||||
assert_eq!(how_many_references(&c), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rm_all_ref() {
|
||||
let a = Rc::new(String::from("a"));
|
||||
let b = Rc::new(String::from("b"));
|
||||
let c = Rc::new(String::from("c"));
|
||||
let d = Rc::new(String::from("d"));
|
||||
|
||||
let a1 = Rc::new(String::from("a"));
|
||||
let b1 = Rc::new(String::from("b"));
|
||||
let c1 = Rc::new(String::from("c"));
|
||||
let d1 = Rc::new(String::from("d"));
|
||||
let mut new_node = Node::new(vec![
|
||||
d.clone(),
|
||||
d.clone(),
|
||||
b.clone(),
|
||||
a.clone(),
|
||||
c.clone(),
|
||||
a.clone(),
|
||||
d.clone(),
|
||||
]);
|
||||
|
||||
new_node.rm_all_ref(a1.clone());
|
||||
assert_eq!(how_many_references(&a), 3);
|
||||
new_node.rm_all_ref(a.clone());
|
||||
assert_eq!(how_many_references(&a), 1);
|
||||
|
||||
new_node.rm_all_ref(b1.clone());
|
||||
assert_eq!(how_many_references(&b), 2);
|
||||
new_node.rm_all_ref(b.clone());
|
||||
assert_eq!(how_many_references(&b), 1);
|
||||
|
||||
new_node.rm_all_ref(c1.clone());
|
||||
assert_eq!(how_many_references(&c), 2);
|
||||
new_node.rm_all_ref(c.clone());
|
||||
assert_eq!(how_many_references(&c), 1);
|
||||
|
||||
new_node.rm_all_ref(d1.clone());
|
||||
assert_eq!(how_many_references(&d), 4);
|
||||
new_node.rm_all_ref(d.clone());
|
||||
assert_eq!(how_many_references(&d), 1);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
[[package]]
|
||||
name = "ref_cell"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "ref_cell_test"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"ref_cell",
|
||||
]
|
|
@ -0,0 +1,10 @@
|
|||
[package]
|
||||
name = "ref_cell_test"
|
||||
version = "0.1.0"
|
||||
authors = ["lee <lee-dasilva@hotmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
ref_cell = { path = "../../../../rust-piscine-solutions/ref_cell"}
|
|
@ -0,0 +1,158 @@
|
|||
use ref_cell::*;
|
||||
|
||||
fn main() {
|
||||
// initialize the worker
|
||||
let Logger = Worker::new(1);
|
||||
|
||||
// initialize the tracker, with the max number of
|
||||
// called references as 10
|
||||
let track = Tracker::new(&Logger, 10);
|
||||
|
||||
let _a = Logger.track_value.clone(); // |\
|
||||
let _a1 = Logger.track_value.clone(); // | -> increase the Rc to 4 references
|
||||
let _a2 = Logger.track_value.clone(); // |/
|
||||
|
||||
// take a peek of how much we already used from our quota
|
||||
track.peek(&Logger.track_value);
|
||||
|
||||
let _b = Logger.track_value.clone(); // |\
|
||||
let _b1 = Logger.track_value.clone(); // | -> increase the Rc to 8 references
|
||||
let _b2 = Logger.track_value.clone(); // | /
|
||||
let _b3 = Logger.track_value.clone(); // |/
|
||||
|
||||
// this will set the value and making a verification of
|
||||
// how much we already used of our quota
|
||||
track.set_value(&Logger.track_value);
|
||||
|
||||
let _c = Logger.track_value.clone(); // | -> increase the Rc to 9 references
|
||||
|
||||
// this will set the value and making a verification of
|
||||
// how much we already used of our quota
|
||||
track.set_value(&Logger.track_value);
|
||||
|
||||
let _c1 = Logger.track_value.clone(); // | -> increase the Rc to 10 references, this will be the limit
|
||||
|
||||
track.set_value(&Logger.track_value);
|
||||
|
||||
for (k ,v) in Logger.mapped_messages.into_inner() {
|
||||
println!("{:?}", (k ,v));
|
||||
}
|
||||
println!("{:?}", Logger.all_messages.into_inner());
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_module() {
|
||||
#[derive(Clone, Debug)]
|
||||
struct TestMs {
|
||||
value: Rc<usize>,
|
||||
ms: RefCell<Vec<String>>,
|
||||
correct: Vec<String>,
|
||||
}
|
||||
|
||||
impl Logger for TestMs {
|
||||
fn warning(&self, message: &str) {
|
||||
self.ms.borrow_mut().push(message.to_string());
|
||||
}
|
||||
fn info(&self, message: &str) {
|
||||
self.ms.borrow_mut().push(message.to_string());
|
||||
}
|
||||
fn error(&self, message: &str) {
|
||||
self.ms.borrow_mut().push(message.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
let l = TestMs {
|
||||
value: Rc::new(115),
|
||||
ms: RefCell::new(vec![]),
|
||||
correct: vec![
|
||||
String::from("Info: you are using up too 40% of your quote"),
|
||||
String::from("Warning: you have used up over 80% of your quota! Proceeds with precaution"),
|
||||
String::from("Error: you are over your quota!")
|
||||
],
|
||||
};
|
||||
|
||||
let track = Tracker::new(&l, 5);
|
||||
let _a = l.value.clone();
|
||||
track.peek(&l.value); // 40%
|
||||
let _a1 = l.value.clone();
|
||||
let _a2 = l.value.clone();
|
||||
track.set_value(&l.value); // 80%
|
||||
let _a3 = l.value.clone();
|
||||
track.set_value(&l.value); // 100%
|
||||
|
||||
for (i, v) in l.ms.into_inner().iter().enumerate() {
|
||||
assert_eq!(v, &l.correct[i])
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_module_usage_hasmap() {
|
||||
let log = Worker::new(1000);
|
||||
let track = Tracker::new(&log, 12);
|
||||
let _clone_test = log.track_value.clone();
|
||||
let _clone_test1 = log.track_value.clone();
|
||||
let _clone_test2 = log.track_value.clone();
|
||||
let _clone_test3 = log.track_value.clone();
|
||||
let _clone_test4 = log.track_value.clone();
|
||||
let _clone_test5 = log.track_value.clone();
|
||||
let _clone_test6 = log.track_value.clone();
|
||||
let _clone_test7 = log.track_value.clone();
|
||||
|
||||
// warning: 75% of the quota
|
||||
track.set_value(&log.track_value);
|
||||
assert_eq!(log.mapped_messages.borrow().get("Warning").unwrap(), "you have used up over 75% of your quota! Proceeds with precaution");
|
||||
|
||||
let _clone_test8 = log.track_value.clone();
|
||||
|
||||
// warning: 83% of the quota <- most resent of the messages last onw to be added to the hashmap
|
||||
track.set_value(&log.track_value);
|
||||
assert_eq!(log.mapped_messages.borrow().get("Warning").unwrap(), "you have used up over 83% of your quota! Proceeds with precaution");
|
||||
|
||||
// info: 83%
|
||||
track.peek(&log.track_value);
|
||||
assert_eq!(log.mapped_messages.borrow().get("Info").unwrap(), "you are using up too 83% of your quote");
|
||||
|
||||
let _clone_test9 = log.track_value.clone();
|
||||
// info: 91%
|
||||
track.peek(&log.track_value);
|
||||
assert_eq!(log.mapped_messages.borrow().get("Info").unwrap(), "you are using up too 91% of your quote");
|
||||
|
||||
let _clone_test10 = log.track_value.clone();
|
||||
// error: passed the quota
|
||||
track.set_value(&log.track_value);
|
||||
assert_eq!(log.mapped_messages.borrow().get("Error").unwrap(), "you are over your quota!");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_module_usage_vector() {
|
||||
let correct = vec![
|
||||
"Info: you are using up too 40% of your quote",
|
||||
"Warning: you have used up over 80% of your quota! Proceeds with precaution",
|
||||
"Info: you are using up too 80% of your quote", "Error: you are over your quota!"
|
||||
];
|
||||
let log = Worker::new(1);
|
||||
let track = Tracker::new(&log, 5);
|
||||
let _a = log.track_value.clone();
|
||||
// info: 40%
|
||||
track.peek(&log.track_value);
|
||||
let _a1 = log.track_value.clone();
|
||||
let _a2 = log.track_value.clone();
|
||||
|
||||
// warning: 80%
|
||||
track.set_value(&log.track_value);
|
||||
// info: 80%
|
||||
track.peek(&log.track_value);
|
||||
let _a3 = log.track_value.clone();
|
||||
|
||||
// error: passed the quota
|
||||
track.set_value(&log.track_value);
|
||||
|
||||
for (i, v) in log.all_messages.into_inner().iter().enumerate() {
|
||||
assert_eq!(v, correct[i]);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
## borrow box
|
||||
|
||||
### Instructions
|
||||
|
||||
You will have to create a **CRUD** functionality. Therefore creating the following functions :
|
||||
|
||||
- `new`, that receives two players and initializes them with a name and a score. This functions should
|
||||
return the structure wrapped in a Box.
|
||||
|
||||
- `read_winner`, returns a tuple with the name and the score of the player who is winning.
|
||||
In case none of the players are winning, it should return the same tuple with the string "Same score! tied" and the tied score.
|
||||
|
||||
- `update_score`, that receives the name of a player.
|
||||
This function should increment the score of the player. The score should only be increased if it does not pass the `nbr_of_games`.
|
||||
Example: if the nbr_of_games is 3 then the game should be best out of three. So if one play as 2 wins then
|
||||
he is the winner and the function should not increase the score anymore for either players.
|
||||
|
||||
- `delete`, that takes the ownership of the boxed game and returning a string : "Game deleted: id -> 0".
|
||||
|
||||
### Expected Function
|
||||
|
||||
```rust
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct Game {
|
||||
// expected public fields
|
||||
}
|
||||
impl Game {
|
||||
pub fn new(i: u32, pl1: String, pl2: String, n: u16) -> Box<Game> {}
|
||||
pub fn read_winner(&self) -> (String, u16) {}
|
||||
pub fn update_score(&mut self, user_name: String) {}
|
||||
pub fn delete(self) -> String {}
|
||||
}
|
||||
```
|
||||
|
||||
### Usage
|
||||
|
||||
Here is a program to test your function
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
let mut game = Game::create_game(0, String::from("Joao"), String::from("Susana"), 5);
|
||||
println!("{:?}", game.read_winner());
|
||||
// output : ("Same score! tied", 0)
|
||||
|
||||
game.update_score(String::from("Joao"));
|
||||
game.update_score(String::from("Joao"));
|
||||
game.update_score(String::from("Susana"));
|
||||
game.update_score(String::from("Susana"));
|
||||
println!("{:?}", game.read_winner());
|
||||
// output : ("Same score! tied", 2)
|
||||
|
||||
game.update_score(String::from("Joao"));
|
||||
// this one will not count because it already 5 games played, the nbr_of_games
|
||||
game.update_score(String::from("Susana"));
|
||||
|
||||
println!("{:?}", game.read_winner());
|
||||
// output : ("Joao", 3)
|
||||
|
||||
game.delete();
|
||||
println!("{:?}", game.delete());
|
||||
// output : "game deleted: id -> 0"
|
||||
|
||||
// game.read_winner();
|
||||
// this will give error
|
||||
// because the game was dropped, no longer exists on the heap
|
||||
}
|
||||
```
|
||||
|
||||
And its output:
|
||||
|
||||
```console
|
||||
student@ubuntu:~/[[ROOT]]/test$ cargo run
|
||||
("Same score! tied", 0)
|
||||
("Same score! tied", 2)
|
||||
("Joao", 3)
|
||||
"game deleted: id -> 0"
|
||||
student@ubuntu:~/[[ROOT]]/test$
|
||||
```
|
||||
|
||||
|
||||
### Notions
|
||||
|
||||
- https://doc.rust-lang.org/book/ch15-01-box.html
|
|
@ -0,0 +1,53 @@
|
|||
## box_it
|
||||
|
||||
### Instructions
|
||||
|
||||
Create the following functions:
|
||||
|
||||
- `transform_and_save_on_heap`, that receives a string with a number (that can or not have a k (kilo) suffix)
|
||||
and transforms those numbers into `u32` and inserts it into a vector that must be saved in the heap using **Box**.
|
||||
|
||||
- `take_value_ownership`, that takes the value (unboxed value) form the box and returns it
|
||||
|
||||
### Expected Function
|
||||
|
||||
```rust
|
||||
pub fn transform_and_save_on_heap(s: String) -> Box<Vec<u32>> {}
|
||||
pub fn take_value_ownership(a: Box<Vec<u32>>) -> Vec<u32> {}
|
||||
```
|
||||
|
||||
### Usage
|
||||
|
||||
Here is a program to test your function
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
let new_str = String::from("5.5k 8.9k 32");
|
||||
|
||||
// creating a variable and we save it in the Heap
|
||||
let a_h = transform_and_save_on_heap(new_str);
|
||||
println!("Box value : {:?}", &a_h);
|
||||
println!("size occupied in the stack : {:?} bytes", (std::mem::size_of_val(&a_h)));
|
||||
|
||||
let a_b_v = take_value_ownership(a_h);
|
||||
println!("value : {:?}", &a_b_v);
|
||||
println!("size occupied in the stack : {:?} bytes", (std::mem::size_of_val(&a_b_v)));
|
||||
// whenever the box, in this case "a_h", goes out of scope it will be deallocated, freed
|
||||
}
|
||||
```
|
||||
|
||||
And its output:
|
||||
|
||||
```console
|
||||
student@ubuntu:~/[[ROOT]]/test$ cargo run
|
||||
Box value : [6800, 13500]
|
||||
size occupied in the stack : 8 bytes
|
||||
value : [6800, 13500]
|
||||
size occupied in the stack : 24 bytes
|
||||
student@ubuntu:~/[[ROOT]]/test$
|
||||
```
|
||||
|
||||
### Notions
|
||||
|
||||
- https://doc.rust-lang.org/book/ch15-00-smart-pointers.html
|
||||
- https://doc.rust-lang.org/book/ch15-01-box.html
|
|
@ -0,0 +1,79 @@
|
|||
## box_recursion
|
||||
|
||||
### Instructions
|
||||
|
||||
Using the given code create the following functions:
|
||||
|
||||
- `new` that will initialize the `WorkEnvironment` as `None`
|
||||
- `add_worker`, that receives two strings, one being the type of worker and the other the name of the worker.
|
||||
- `remove_worker`, that removes the last worker that was placed in the `WorkEnvironment`, this functions should
|
||||
return a `Option` with the name of the worker.
|
||||
- `search_worker`, that return a tuple with the name and type of worker.
|
||||
|
||||
You must also create a type called `Link` this will be the connection of the structures `WorkEnvironment` and `Worker`.
|
||||
Do not forget that this will be a recursion type and it must point to `None` if there is no workers.
|
||||
|
||||
### Expected Function
|
||||
|
||||
```rust
|
||||
pub struct WorkEnvironment {
|
||||
pub grade: Link,
|
||||
}
|
||||
|
||||
pub type Link =
|
||||
|
||||
pub struct Worker {
|
||||
pub worker_type: String,
|
||||
pub worker_name: String,
|
||||
pub next_worker: Link,
|
||||
}
|
||||
|
||||
impl WorkEnvironment {
|
||||
pub fn new() -> WorkEnvironment {}
|
||||
pub fn add_worker(&mut self, t: String, name: String) {}
|
||||
pub fn remove_worker(&mut self) -> Option<String> {}
|
||||
pub fn search_worker(&self) -> Option<(String, String)> {}
|
||||
}
|
||||
|
||||
|
||||
```
|
||||
|
||||
### Usage
|
||||
|
||||
Here is a program to test your function
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
let mut list = WorkEnvironment::new();
|
||||
list.add_worker(String::from("CEO"), String::from("Marie"));
|
||||
list.add_worker(String::from("Manager"), String::from("Monica"));
|
||||
list.add_worker(String::from("Normal Worker"), String::from("Ana"));
|
||||
list.add_worker(String::from("Normal Worker"), String::from("Alice"));
|
||||
println!("{:?}", list);
|
||||
|
||||
println!("{:?}", list.search_worker());
|
||||
|
||||
list.remove_worker();
|
||||
list.remove_worker();
|
||||
list.remove_worker();
|
||||
list.remove_worker();
|
||||
println!("{:?}", list);
|
||||
}
|
||||
```
|
||||
|
||||
And its output:
|
||||
|
||||
```console
|
||||
student@ubuntu:~/[[ROOT]]/test$ cargo run
|
||||
WorkEnvironment { grade: Some(Worker { worker_type: "Normal Worker", worker_name: "Alice", next_worker: Some(Worker { worker_type: "Normal Worker", worker_name: "Ana", next_worker: Some(Worker { worker_type: "Manager", worker_name: "Monica", next_worker: Some(Worker { worker_type: "CEO", worker_name: "Marie", next_worker: None }) }) }) }) }
|
||||
Some(("Alice", "Normal Worker"))
|
||||
WorkEnvironment { grade: None }
|
||||
student@ubuntu:~/[[ROOT]]/test$
|
||||
```
|
||||
|
||||
### Notions
|
||||
|
||||
- https://doc.rust-lang.org/rust-by-example/custom_types/enum.html
|
||||
- https://doc.rust-lang.org/book/ch15-01-box.html
|
||||
- https://doc.rust-lang.org/std/option/
|
||||
- https://doc.rust-lang.org/book/ch15-01-box.html
|
|
@ -0,0 +1,109 @@
|
|||
## drop_the_thread
|
||||
|
||||
### Instructions
|
||||
|
||||
"Interior mutability is a design pattern in Rust that allows you to mutate data even when there are immutable references to that data"
|
||||
|
||||
You must create a Drop checker API. For this you must create:
|
||||
|
||||
- Two structures:
|
||||
- `Workers` that will have two fields:
|
||||
- `drops` that will save the number of dropped threads
|
||||
- `states` that will save a state of multiple threads.
|
||||
If the thread is not dropped, the state will be false otherwise true.
|
||||
- `Thread` that will have the following fields:
|
||||
- `pid`, the id of the thread
|
||||
- `cmd`, the name of the thread
|
||||
- `parent`, that will be the link to the structure `Workers` (Tip: this must be a reference to the structure Workers)
|
||||
|
||||
- Implementation of each structure:
|
||||
- `Workers` :
|
||||
- `new`, that creates a default worker
|
||||
- `new_worker`, that returns a tuple with the `pid` and a new `Thread`,
|
||||
this function must receive a `String` being the `cmd`
|
||||
- `is_dropped`, that receives a `pid` and returns a `bool` that indicates the state of the thread by using the `pid`
|
||||
- `track_worker`, it should return a `usize`, that will be the last available index of the `states` vector, being the new next thread
|
||||
- `add_drop`, this function must be **called by the `Drop` trait**. It will receive a `pid` that will be used to change the
|
||||
state of the thread. If the state of that thread is `true` then it will panic with the message ("Cannot drop {}, because its already dropped", pid).
|
||||
Otherwise it should change the state to true and increment the `drops` field by one.
|
||||
|
||||
- `Thread`:
|
||||
- `new_thread`, that initializes a new thread
|
||||
- `skill`, that drops the thread
|
||||
|
||||
- You must implement for the structure `Thread` the `Drop` trait. In this trait you must call the function `add_drop` so that the state of the thread changes
|
||||
|
||||
### Expected Function
|
||||
|
||||
```rust
|
||||
use std::cell::{RefCell, Cell};
|
||||
|
||||
#[derive(Debug, Default, Clone, Eq, PartialEq)]
|
||||
pub struct Workers {
|
||||
pub drops: Cell<usize>,
|
||||
pub state: RefCell<Vec<bool>>
|
||||
}
|
||||
|
||||
impl Workers {
|
||||
pub fn new() -> Workers {}
|
||||
pub fn new_worker(&self, c: String) -> (usize, Thread) {}
|
||||
pub fn track_worker(&self) -> usize {}
|
||||
pub fn is_dropped(&self, id: usize) -> bool {}
|
||||
pub fn add_drop(&self, id: usize) {}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct Thread<'a> {
|
||||
// expected public fields
|
||||
}
|
||||
|
||||
impl<'a> Thread<'a> {
|
||||
pub fn new_thread(p: usize, c: String, t: &'a Workers) -> Thread {}
|
||||
pub fn skill(self) {}
|
||||
}
|
||||
```
|
||||
|
||||
### Usage
|
||||
|
||||
Here is a program to test your function
|
||||
|
||||
```rust
|
||||
use std::rc::Rc;
|
||||
|
||||
fn main() {
|
||||
let worker = Workers::new();
|
||||
let (id, thread) = worker.new_worker(String::from("command"));
|
||||
let (id1, thread1) = worker.new_worker(String::from("command1"));
|
||||
|
||||
thread.skill();
|
||||
|
||||
println!("{:?}", (worker.is_dropped(id), id, &worker.drops));
|
||||
|
||||
thread1.skill();
|
||||
println!("{:?}", (worker.is_dropped(id1), id1, &worker.drops));
|
||||
|
||||
let (id2, thread2) = worker.new_worker(String::from("command2"));
|
||||
let thread2 = Rc::new(thread2);
|
||||
let thread2_clone = thread2.clone();
|
||||
|
||||
drop(thread2_clone);
|
||||
|
||||
println!("{:?}", (worker.is_dropped(id2), id2, &worker.drops, Rc::strong_count(&thread2)));
|
||||
}
|
||||
```
|
||||
|
||||
And its output:
|
||||
|
||||
```console
|
||||
student@ubuntu:~/[[ROOT]]/test$ cargo run
|
||||
(true, 0, Cell { value: 1 })
|
||||
(true, 1, Cell { value: 2 })
|
||||
(false, 2, Cell { value: 2 }, 1)
|
||||
student@ubuntu:~/[[ROOT]]/test$
|
||||
```
|
||||
|
||||
### Notions
|
||||
|
||||
- https://doc.bccnsoft.com/docs/rust-1.36.0-docs-html/std/ops/trait.Drop.html
|
||||
- https://doc.rust-lang.org/std/cell/struct.RefCell.html
|
||||
- https://doc.rust-lang.org/book/ch15-05-interior-mutability.html
|
|
@ -0,0 +1,78 @@
|
|||
## how many references
|
||||
|
||||
### Instructions
|
||||
|
||||
Create the following functions :
|
||||
|
||||
- `add_ele` that adds an element to the value in the `Node`
|
||||
- `how_many_references` that returns how many times the value is referenced in the code
|
||||
- `rm_all_ref` that receives a `Rc<String>` and removes all elements from the vector that
|
||||
are equal to that value, this should only happen if the two Rcs point to the same allocation
|
||||
|
||||
### Expected Function
|
||||
|
||||
```rust
|
||||
pub use std::rc::Rc;
|
||||
|
||||
pub struct Node {
|
||||
pub value: Vec<Rc<String>>,
|
||||
}
|
||||
|
||||
impl Node {
|
||||
pub fn new(value: Vec<Rc<String>>) -> Node {
|
||||
Node { value: value }
|
||||
}
|
||||
pub fn add_ele(&mut self, v: Rc<String>) {}
|
||||
pub fn rm_all_ref(&mut self, v: Rc<String>) {}
|
||||
}
|
||||
|
||||
pub fn how_many_references(value: &Rc<String>) -> usize {}
|
||||
```
|
||||
|
||||
### Usage
|
||||
|
||||
Here is a program to test your function
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
let a = Rc::new(String::from("a"));
|
||||
let b = Rc::new(String::from("b"));
|
||||
let c = Rc::new(String::from("c"));
|
||||
|
||||
let a1 = Rc::new(String::from("a"));
|
||||
|
||||
let mut new_node = Node::new(vec![a.clone()]);
|
||||
new_node.add_ele(b.clone());
|
||||
new_node.add_ele(a.clone());
|
||||
new_node.add_ele(c.clone());
|
||||
new_node.add_ele(a.clone());
|
||||
|
||||
println!("a: {:?}", how_many_references(&a));
|
||||
println!("b: {:?}", how_many_references(&b));
|
||||
println!("c: {:?}", how_many_references(&c));
|
||||
new_node.rm_all_ref(a1.clone());
|
||||
new_node.rm_all_ref(a.clone());
|
||||
|
||||
println!("a: {:?}", how_many_references(&a));
|
||||
println!("b: {:?}", how_many_references(&b));
|
||||
println!("c: {:?}", how_many_references(&c));
|
||||
}
|
||||
```
|
||||
|
||||
And its output:
|
||||
|
||||
```console
|
||||
student@ubuntu:~/[[ROOT]]/test$ cargo run
|
||||
a: 4
|
||||
b: 2
|
||||
c: 2
|
||||
a: 1
|
||||
b: 2
|
||||
c: 2
|
||||
student@ubuntu:~/[[ROOT]]/test$
|
||||
```
|
||||
|
||||
### Notions
|
||||
|
||||
- https://doc.rust-lang.org/book/ch15-04-rc.html
|
||||
- https://doc.rust-lang.org/std/rc/struct.Rc.html
|
|
@ -0,0 +1,112 @@
|
|||
## ref_cell
|
||||
|
||||
### Instructions
|
||||
|
||||
### 1º part
|
||||
|
||||
Create a module called `messenger`. This module will be able to inform a user of how much references of a given value he is using.
|
||||
The main objective for this module is to limit how many times a value is referenced.
|
||||
|
||||
For the module you must create the following:
|
||||
|
||||
- A trait `Logger` that implements three functions: `warning`, `info`, `error`. All function should receive a reference to themselves and a string literal.
|
||||
|
||||
```rust
|
||||
fn warning(&self, msg: &str);
|
||||
fn info(&self, msg: &str);
|
||||
fn error(&self, msg: &str);
|
||||
```
|
||||
|
||||
- A structure called `Tracker`, that must have the fields: `logger` being a reference to the `Logger`, `value` being the count of how many times the value was referenced,
|
||||
`max` being the max count of references the actual value can achieve.
|
||||
|
||||
- An implementation of three functions that are associated to the `Tracker` structure:
|
||||
- `new` that will initialize the structure
|
||||
- `set_value` that sets the value to the `Tracker` structure and writes to the trait functions. This should be done comparing the **max** and the number of referenced of the actual value.
|
||||
If the percentage is equal or greater to 100% of the limit usage, it should write **"Error: you are over your quota!"** to the `error` function
|
||||
If the percentage is equal or greater to 70% of the limit usage, it should write **("Warning: you have used up over {}% of your quota! Proceeds with precaution", <calculated_percentage>)** to the `warning` function
|
||||
- `peek` that will take a peek of how much usage the variable already has. It should write **("Info: you are using up too {}% of your quote", <calculated_percentage>)** to the `info` function
|
||||
|
||||
### 2ª part
|
||||
|
||||
Afterwards you must use the module `messenger` and create the following:
|
||||
|
||||
- A structure `Worker` that has the fields:
|
||||
- `track_value` this will be the value that will be tracked by the tracker.
|
||||
- `mapped_messages` that will have the latest messages. This must be a HashMap with the key being the type of message
|
||||
sent by the logger (info, error or warning) and the value being the message
|
||||
- `all_messages` that will be a vector of all messages sent.
|
||||
- A `new` function that initializes the structure `Worker`
|
||||
- To use the trait `Logger` you must implement it for the Worker structure. Each function (warning, error and info) must insert the message to the
|
||||
respective fields of the structure Worker.
|
||||
|
||||
You must use **interior mutability**, this means it must be able to mutate data even when there are immutable references to that data.
|
||||
|
||||
So the user doesn't need to use the keyword `mut` (tip: RefCell)
|
||||
|
||||
### Usage
|
||||
|
||||
Here is a program to test your function
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
// initialize the worker
|
||||
let Logger = Worker::new(1);
|
||||
|
||||
// initialize the tracker, with the max number of
|
||||
// called references as 10
|
||||
let track = Tracker::new(&Logger, 10);
|
||||
|
||||
let _a = Logger.track_value.clone(); // |\
|
||||
let _a1 = Logger.track_value.clone(); // | -> increase the Rc to 4 references
|
||||
let _a2 = Logger.track_value.clone(); // |/
|
||||
|
||||
// take a peek of how much we already used from our quota
|
||||
track.peek(&Logger.track_value);
|
||||
|
||||
let _b = Logger.track_value.clone(); // |\
|
||||
let _b1 = Logger.track_value.clone(); // | -> increase the Rc to 8 references
|
||||
let _b2 = Logger.track_value.clone(); // | /
|
||||
let _b3 = Logger.track_value.clone(); // |/
|
||||
|
||||
// this will set the value and making a verification of
|
||||
// how much we already used of our quota
|
||||
track.set_value(&Logger.track_value);
|
||||
|
||||
let _c = Logger.track_value.clone(); // | -> increase the Rc to 9 references
|
||||
|
||||
// this will set the value and making a verification of
|
||||
// how much we already used of our quota
|
||||
track.set_value(&Logger.track_value);
|
||||
|
||||
let _c1 = Logger.track_value.clone(); // | -> increase the Rc to 10 references, this will be the limit
|
||||
|
||||
track.set_value(&Logger.track_value);
|
||||
|
||||
for (k ,v) in Logger.mapped_messages.into_inner() {
|
||||
println!("{:?}", (k ,v));
|
||||
}
|
||||
println!("{:?}", Logger.all_messages.into_inner());
|
||||
}
|
||||
```
|
||||
|
||||
And its output:
|
||||
|
||||
```console
|
||||
student@ubuntu:~/[[ROOT]]/test$ cargo run
|
||||
("Info", "you are using up too 40% of your quote")
|
||||
("Warning", "you have used up over 90% of your quota! Proceeds with precaution")
|
||||
("Error", "you are over your quota!")
|
||||
[
|
||||
"Info: you are using up too 40% of your quote",
|
||||
"Warning: you have used up over 80% of your quota! Proceeds with precaution",
|
||||
"Warning: you have used up over 90% of your quota! Proceeds with precaution",
|
||||
"Error: you are over your quota!"
|
||||
]
|
||||
student@ubuntu:~/[[ROOT]]/test$
|
||||
```
|
||||
|
||||
### Notions
|
||||
|
||||
- https://doc.rust-lang.org/std/cell/struct.RefCell.html
|
||||
- https://doc.rust-lang.org/std/rc/struct.Rc.html
|
Loading…
Reference in New Issue