forked from root/public
24 changed files with 1239 additions and 0 deletions
@ -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