mirror of https://github.com/01-edu/public.git
augusto-mantilla
4 years ago
committed by
GitHub
72 changed files with 3471 additions and 0 deletions
@ -0,0 +1,12 @@ |
|||||||
|
# This file is automatically @generated by Cargo. |
||||||
|
# It is not intended for manual editing. |
||||||
|
[[package]] |
||||||
|
name = "banner" |
||||||
|
version = "0.1.0" |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "banner_test" |
||||||
|
version = "0.1.0" |
||||||
|
dependencies = [ |
||||||
|
"banner", |
||||||
|
] |
@ -0,0 +1,10 @@ |
|||||||
|
[package] |
||||||
|
name = "banner_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] |
||||||
|
banner = { path = "../../../../rust-piscine-solutions/banner"} |
@ -0,0 +1,88 @@ |
|||||||
|
use std::collections::HashMap; |
||||||
|
use banner::*; |
||||||
|
|
||||||
|
fn main() { |
||||||
|
let mut handler = FlagsHandler { flags: HashMap::new() }; |
||||||
|
|
||||||
|
let d = Flag::opt_flag("division", "divides the values, formula (a / b)"); |
||||||
|
let r = Flag::opt_flag( |
||||||
|
"remainder", |
||||||
|
"remainder of the division between two values, formula (a % b)", |
||||||
|
); |
||||||
|
|
||||||
|
handler.add_flag((d.short_hand, d.long_hand), div); |
||||||
|
handler.add_flag((r.short_hand, r.long_hand), rem); |
||||||
|
|
||||||
|
println!("{:?}", handler.exec_func(("-d".to_string(), "--division".to_string()), &["1.0", "2.0"])); |
||||||
|
// output: "0.5"
|
||||||
|
|
||||||
|
println!("{:?}",handler.exec_func(("-r".to_string(), "--remainder".to_string()), &["2.0", "2.0"])); |
||||||
|
// output: "0.0"
|
||||||
|
|
||||||
|
println!("{:?}",handler.exec_func(("-d".to_string(), "--division".to_string()), &["a", "2.0"])); |
||||||
|
// output: "invalid float literal"
|
||||||
|
|
||||||
|
println!("{:?}",handler.exec_func(("-r".to_string(), "--remainder".to_string()), &["2.0", "fd"])); |
||||||
|
// output: "invalid float literal"
|
||||||
|
} |
||||||
|
|
||||||
|
#[cfg(test)] |
||||||
|
mod tests { |
||||||
|
use super::*; |
||||||
|
|
||||||
|
fn init() -> FlagsHandler { |
||||||
|
let d = Flag::opt_flag("division", "divides two numbers"); |
||||||
|
let r = Flag::opt_flag( |
||||||
|
"remainder", |
||||||
|
"gives the remainder of the division between two numbers", |
||||||
|
); |
||||||
|
let mut handler = FlagsHandler { flags: HashMap::new() }; |
||||||
|
|
||||||
|
handler.add_flag((d.short_hand, d.long_hand), div); |
||||||
|
handler.add_flag((r.short_hand, r.long_hand), rem); |
||||||
|
return handler; |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn ok_test() { |
||||||
|
let mut handler = init(); |
||||||
|
assert_eq!( |
||||||
|
handler.exec_func(("-d".to_string(), "--division".to_string()), &["1.0", "2.0"]), |
||||||
|
"0.5" |
||||||
|
); |
||||||
|
assert_eq!( |
||||||
|
handler.exec_func(("-r".to_string(), "--remainder".to_string()), &["2.0", "2.0"]), |
||||||
|
"0" |
||||||
|
); |
||||||
|
assert_eq!( |
||||||
|
handler.exec_func(("-d".to_string(), "--division".to_string()), &["12.323", "212.32"]), |
||||||
|
"0.05803975" |
||||||
|
); |
||||||
|
assert_eq!( |
||||||
|
handler.exec_func(("-r".to_string(), "--remainder".to_string()), &["12.323", "212.32"]), |
||||||
|
"12.323" |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn error_test() { |
||||||
|
let mut handler = init(); |
||||||
|
assert_eq!( |
||||||
|
handler.exec_func(("-d".to_string(), "--division".to_string()), &["a", "2.0"]), |
||||||
|
"invalid float literal" |
||||||
|
); |
||||||
|
assert_eq!( |
||||||
|
handler.exec_func(("-r".to_string(), "--remainder".to_string()), &["2.0", "f"]), |
||||||
|
"invalid float literal" |
||||||
|
); |
||||||
|
assert_eq!( |
||||||
|
handler.exec_func(("-d".to_string(), "--division".to_string()), &["1.0", "0.0"]), |
||||||
|
"inf" |
||||||
|
); |
||||||
|
assert_eq!( |
||||||
|
handler.exec_func(("-r".to_string(), "--remainder".to_string()), &["2.0", "0.0"]), |
||||||
|
"NaN" |
||||||
|
); |
||||||
|
} |
||||||
|
} |
||||||
|
|
@ -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,96 @@ |
|||||||
|
# This file is automatically @generated by Cargo. |
||||||
|
# It is not intended for manual editing. |
||||||
|
[[package]] |
||||||
|
name = "boxing_todo" |
||||||
|
version = "0.1.0" |
||||||
|
dependencies = [ |
||||||
|
"serde", |
||||||
|
"serde_json", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "boxing_todo_test" |
||||||
|
version = "0.1.0" |
||||||
|
dependencies = [ |
||||||
|
"boxing_todo", |
||||||
|
"serde", |
||||||
|
"serde_json", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "itoa" |
||||||
|
version = "0.4.7" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "proc-macro2" |
||||||
|
version = "1.0.24" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" |
||||||
|
dependencies = [ |
||||||
|
"unicode-xid", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "quote" |
||||||
|
version = "1.0.8" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df" |
||||||
|
dependencies = [ |
||||||
|
"proc-macro2", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "ryu" |
||||||
|
version = "1.0.5" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "serde" |
||||||
|
version = "1.0.118" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800" |
||||||
|
dependencies = [ |
||||||
|
"serde_derive", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "serde_derive" |
||||||
|
version = "1.0.118" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "c84d3526699cd55261af4b941e4e725444df67aa4f9e6a3564f18030d12672df" |
||||||
|
dependencies = [ |
||||||
|
"proc-macro2", |
||||||
|
"quote", |
||||||
|
"syn", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "serde_json" |
||||||
|
version = "1.0.60" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "1500e84d27fe482ed1dc791a56eddc2f230046a040fa908c08bda1d9fb615779" |
||||||
|
dependencies = [ |
||||||
|
"itoa", |
||||||
|
"ryu", |
||||||
|
"serde", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "syn" |
||||||
|
version = "1.0.56" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "a9802ddde94170d186eeee5005b798d9c159fa970403f1be19976d0cfb939b72" |
||||||
|
dependencies = [ |
||||||
|
"proc-macro2", |
||||||
|
"quote", |
||||||
|
"unicode-xid", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "unicode-xid" |
||||||
|
version = "0.2.1" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" |
@ -0,0 +1,12 @@ |
|||||||
|
[package] |
||||||
|
name = "boxing_todo_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] |
||||||
|
boxing_todo = { path = "../../../../rust-piscine-solutions/boxing_todo"} |
||||||
|
serde = { version = "1.0", features = ["derive"] } |
||||||
|
serde_json = "1.0" |
@ -0,0 +1,99 @@ |
|||||||
|
use boxing_todo::*; |
||||||
|
|
||||||
|
// Note that you can create some todo list your self to test it, but you can find the JSON files that
|
||||||
|
// are being tested [here](https://github.com/01-edu/public/blob/master/subjects/boxing_todo)
|
||||||
|
fn main() { |
||||||
|
let todos = TodoList::get_todo("todo.json"); |
||||||
|
match todos { |
||||||
|
Ok(list) => println!("{:?}", list), |
||||||
|
Err(e) => { |
||||||
|
println!("{}{:?}", e.description(), e.cause()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
let todos = TodoList::get_todo("malforned_object.json"); |
||||||
|
match todos { |
||||||
|
Ok(list) => println!("{:?}", list), |
||||||
|
Err(e) => { |
||||||
|
println!("{}{:?}", e.description(), e.cause().unwrap()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
let todos = TodoList::get_todo("permission_err.json"); |
||||||
|
match todos { |
||||||
|
Ok(list) => println!("{:?}", list), |
||||||
|
Err(e) => { |
||||||
|
println!("{}{:?}", e.description(), e.cause().unwrap()); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[cfg(test)] |
||||||
|
mod tests { |
||||||
|
use super::*; |
||||||
|
use std::fs::File; |
||||||
|
use std::fs; |
||||||
|
|
||||||
|
fn new_todo(s: String, v: Vec<Task>) -> TodoList { |
||||||
|
TodoList { title: s, tasks: v } |
||||||
|
} |
||||||
|
fn run(s: &TodoList, f: &str) -> Result<TodoList, Box<dyn Error>> { |
||||||
|
serde_json::to_writer(&File::create(f)?, s)?; |
||||||
|
let result = TodoList::get_todo(f); |
||||||
|
fs::remove_file(f)?; |
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn test_good_todo() { |
||||||
|
let file_name = "todo.json"; |
||||||
|
let good_struct = new_todo( |
||||||
|
String::from("todo list for something"), |
||||||
|
vec![ |
||||||
|
Task { id: 0, description: "do this".to_string(), level: 0 }, |
||||||
|
Task { id: 1, description: "do that".to_string(), level: 5 }, |
||||||
|
], |
||||||
|
); |
||||||
|
let result = run(&good_struct, file_name).unwrap(); |
||||||
|
|
||||||
|
assert_eq!(result.title, good_struct.title); |
||||||
|
assert_eq!(&result.tasks, &good_struct.tasks); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn test_empty_tasks() { |
||||||
|
let file_name = "empty_tasks.json"; |
||||||
|
let result = run(&new_todo(String::from("empty tasks"), vec![]), file_name).unwrap_err(); |
||||||
|
|
||||||
|
assert_eq!(result.to_string(), "Failed to parses todo"); |
||||||
|
assert_eq!(result.description(), "Todo List parse failed: "); |
||||||
|
assert!(!result.cause().is_some()); |
||||||
|
} |
||||||
|
#[test] |
||||||
|
fn test_read() { |
||||||
|
let result = TodoList::get_todo("no_file.json").unwrap_err(); |
||||||
|
|
||||||
|
assert_eq!(result.to_string(), "Failed to read todo file"); |
||||||
|
assert_eq!(result.description(), "Todo List read failed: "); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
#[should_panic(expected = "Malformed(Error(\"missing field `title`\", line: 1, column: 2))")] |
||||||
|
fn test_malformed_json() { |
||||||
|
#[derive(Serialize, Deserialize)] |
||||||
|
struct Mal {}; |
||||||
|
let file_name = "malformed.json"; |
||||||
|
let malformed: Mal = serde_json::from_str(r#"{}"#).unwrap(); |
||||||
|
serde_json::to_writer(&File::create(file_name).unwrap(), &malformed).unwrap(); |
||||||
|
let result = TodoList::get_todo(file_name); |
||||||
|
fs::remove_file(file_name).unwrap(); |
||||||
|
|
||||||
|
result.unwrap_or_else(|e| panic!("{:?}", e)); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
#[should_panic(expected = "ReadErr { child_err: Os { code: 2, kind: NotFound, message: \"No such file or directory\" } }")] |
||||||
|
fn test_read_error() { |
||||||
|
TodoList::get_todo("no_file.json").unwrap_or_else(|e| panic!("{:?}", e)); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
# This file is automatically @generated by Cargo. |
||||||
|
# It is not intended for manual editing. |
||||||
|
[[package]] |
||||||
|
name = "cipher" |
||||||
|
version = "0.1.0" |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "cipher_test" |
||||||
|
version = "0.1.0" |
||||||
|
dependencies = [ |
||||||
|
"cipher", |
||||||
|
] |
@ -0,0 +1,10 @@ |
|||||||
|
[package] |
||||||
|
name = "cipher_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] |
||||||
|
cipher = { path = "../../../../rust-piscine-solutions/cipher"} |
@ -0,0 +1,24 @@ |
|||||||
|
use cipher::*; |
||||||
|
|
||||||
|
fn main() { |
||||||
|
println!("{:?}", cipher("1Hello 2world!", "1Svool 2dliow!")); |
||||||
|
println!("{:?}", cipher("1Hello 2world!", "svool")); |
||||||
|
println!("{:?}", cipher("", "svool")); |
||||||
|
} |
||||||
|
|
||||||
|
#[cfg(test)] |
||||||
|
mod tests { |
||||||
|
use super::*; |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn test_cipher() { |
||||||
|
assert_eq!(cipher("1Hello 2world!", "1Svool 2dliow!"), Some(Ok(true))); |
||||||
|
assert_eq!(cipher("", "1Svool 2dliow!"), None); |
||||||
|
assert_eq!(cipher("1Hello 2world!", ""), None); |
||||||
|
assert_eq!(cipher("1Hello 2world!", "1svool 2dliow!"), Some(Err(CipherError { validation: false, expected: String::from("1Svool 2dliow!") }))); |
||||||
|
assert_eq!(cipher("asdasd", "zhwzhw"), Some(Ok(true))); |
||||||
|
assert_eq!(cipher("asdasd", "lkdas"), Some(Err(CipherError { validation: false, expected: String::from("zhwzhw") }))); |
||||||
|
assert_eq!(cipher("3(/&%fsd 32das", "3(/&%uhw 32wzh"), Some(Ok(true))); |
||||||
|
assert_eq!(cipher("3(/&%sd 32das", "3(/&%uhw 32wzh"), Some(Err(CipherError { validation: false, expected: String::from("3(/&%hw 32wzh") }))); |
||||||
|
} |
||||||
|
} |
@ -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,98 @@ |
|||||||
|
# This file is automatically @generated by Cargo. |
||||||
|
# It is not intended for manual editing. |
||||||
|
[[package]] |
||||||
|
name = "autocfg" |
||||||
|
version = "1.0.1" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "chrono" |
||||||
|
version = "0.4.19" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" |
||||||
|
dependencies = [ |
||||||
|
"libc", |
||||||
|
"num-integer", |
||||||
|
"num-traits", |
||||||
|
"time", |
||||||
|
"winapi", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "error_type" |
||||||
|
version = "0.1.0" |
||||||
|
dependencies = [ |
||||||
|
"chrono", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "error_type_test" |
||||||
|
version = "0.1.0" |
||||||
|
dependencies = [ |
||||||
|
"error_type", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "libc" |
||||||
|
version = "0.2.81" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb" |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "num-integer" |
||||||
|
version = "0.1.44" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" |
||||||
|
dependencies = [ |
||||||
|
"autocfg", |
||||||
|
"num-traits", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "num-traits" |
||||||
|
version = "0.2.14" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" |
||||||
|
dependencies = [ |
||||||
|
"autocfg", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "time" |
||||||
|
version = "0.1.44" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" |
||||||
|
dependencies = [ |
||||||
|
"libc", |
||||||
|
"wasi", |
||||||
|
"winapi", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "wasi" |
||||||
|
version = "0.10.0+wasi-snapshot-preview1" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "winapi" |
||||||
|
version = "0.3.9" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" |
||||||
|
dependencies = [ |
||||||
|
"winapi-i686-pc-windows-gnu", |
||||||
|
"winapi-x86_64-pc-windows-gnu", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "winapi-i686-pc-windows-gnu" |
||||||
|
version = "0.4.0" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "winapi-x86_64-pc-windows-gnu" |
||||||
|
version = "0.4.0" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" |
@ -0,0 +1,10 @@ |
|||||||
|
[package] |
||||||
|
name = "error_type_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] |
||||||
|
error_type = { path = "../../../../rust-piscine-solutions/error_type"} |
@ -0,0 +1,136 @@ |
|||||||
|
use error_type::*; |
||||||
|
|
||||||
|
#[allow(dead_code)] |
||||||
|
fn create_date(date: &str) -> NaiveDate { |
||||||
|
NaiveDate::parse_from_str(date, "%Y-%m-%d").unwrap() |
||||||
|
} |
||||||
|
|
||||||
|
fn main() { |
||||||
|
let mut form_output = Form::new( |
||||||
|
String::from("Lee"), |
||||||
|
String::from("Silva"), |
||||||
|
create_date("2015-09-05"), |
||||||
|
SexType::Male, |
||||||
|
String::from("Africa"), |
||||||
|
String::from("qwqwsa1dty_")); |
||||||
|
|
||||||
|
println!("{:?}", form_output); |
||||||
|
println!("{:?}", form_output.validate().unwrap()); |
||||||
|
|
||||||
|
form_output.first_name = String::from(""); |
||||||
|
println!("{:?}", form_output.validate().unwrap_err()); |
||||||
|
|
||||||
|
form_output.first_name = String::from("as"); |
||||||
|
form_output.password = String::from("dty_1"); |
||||||
|
println!("{:?}", form_output.validate().unwrap_err()); |
||||||
|
|
||||||
|
form_output.password = String::from("asdasASd(_"); |
||||||
|
println!("{:?}", form_output.validate().unwrap_err()); |
||||||
|
|
||||||
|
form_output.password = String::from("asdasASd123SA"); |
||||||
|
println!("{:?}", form_output.validate().unwrap_err()); |
||||||
|
} |
||||||
|
|
||||||
|
#[cfg(test)] |
||||||
|
mod tests { |
||||||
|
use super::*; |
||||||
|
|
||||||
|
#[derive(Debug)] |
||||||
|
struct TestForm<'a> { |
||||||
|
form: Form, |
||||||
|
validation: Result<Vec<&'a str>, FErr> |
||||||
|
} |
||||||
|
|
||||||
|
impl <'a> TestForm<'_> { |
||||||
|
// all test cases
|
||||||
|
fn new() -> Vec<TestForm<'a>> { |
||||||
|
vec![ |
||||||
|
TestForm { |
||||||
|
form : Form::new( |
||||||
|
String::from("Katy"), |
||||||
|
String::from("Silva"), |
||||||
|
create_date("2015-09-05"), |
||||||
|
SexType::Female, |
||||||
|
String::from("Africa"), |
||||||
|
String::from("qwTw12&%$3sa1dty_")), |
||||||
|
validation: Ok(vec!["Valid first name", "Valid password"]), |
||||||
|
}, |
||||||
|
TestForm { |
||||||
|
form : Form::new( |
||||||
|
String::from(""), |
||||||
|
String::from("Bear"), |
||||||
|
create_date("2015-09-05"), |
||||||
|
SexType::Male, |
||||||
|
String::from("Africa"), |
||||||
|
String::from("qwTw12&%$3sa1dty_")), |
||||||
|
validation: Err(FErr { |
||||||
|
form_values: (String::from("first_name"), |
||||||
|
String::from("")), |
||||||
|
date: Utc::now().format("%Y-%m-%d %H:%M:%S").to_string(), |
||||||
|
err: String::from("No user name")}), |
||||||
|
}, |
||||||
|
TestForm { |
||||||
|
form : Form::new( |
||||||
|
String::from("Someone"), |
||||||
|
String::from("Bear"), |
||||||
|
create_date("2015-09-05"), |
||||||
|
SexType::Male, |
||||||
|
String::from("Africa"), |
||||||
|
String::from("12345")), |
||||||
|
validation: Err(FErr { |
||||||
|
form_values: (String::from("password"), String::from("12345")), |
||||||
|
date: Utc::now().format("%Y-%m-%d %H:%M:%S").to_string(), |
||||||
|
err: String::from("At least 8 characters") }), |
||||||
|
}, |
||||||
|
TestForm { |
||||||
|
form : Form::new( |
||||||
|
String::from("Someone"), |
||||||
|
String::from("Bear"), |
||||||
|
create_date("2015-09-05"), |
||||||
|
SexType::Male, |
||||||
|
String::from("Africa"), |
||||||
|
String::from("sdASDsrW")), |
||||||
|
validation: Err(FErr { |
||||||
|
form_values: (String::from("password"), String::from("sdASDsrW")), |
||||||
|
date: Utc::now().format("%Y-%m-%d %H:%M:%S").to_string(), |
||||||
|
err: String::from("Combination of different ASCII character types (numbers, letters and none alphanumeric characters)") }), |
||||||
|
}, |
||||||
|
TestForm { |
||||||
|
form : Form::new( |
||||||
|
String::from("Someone"), |
||||||
|
String::from("Bear"), |
||||||
|
create_date("2015-09-05"), |
||||||
|
SexType::Female, |
||||||
|
String::from("Africa"), |
||||||
|
String::from("dsGE1SAD213")), |
||||||
|
validation: Err(FErr { |
||||||
|
form_values: (String::from("password"), String::from("dsGE1SAD213")), |
||||||
|
date: Utc::now().format("%Y-%m-%d %H:%M:%S").to_string(), |
||||||
|
err: String::from("Combination of different ASCII character types (numbers, letters and none alphanumeric characters)") }), |
||||||
|
}, |
||||||
|
TestForm { |
||||||
|
form : Form::new( |
||||||
|
String::from("Someone"), |
||||||
|
String::from("Bear"), |
||||||
|
create_date("2015-09-05"), |
||||||
|
SexType::Female, |
||||||
|
String::from("Africa"), |
||||||
|
String::from("dsaSD&%DF!?=")), |
||||||
|
validation: Err(FErr { |
||||||
|
form_values: (String::from("password"), String::from("dsaSD&%DF!?=")), |
||||||
|
date: Utc::now().format("%Y-%m-%d %H:%M:%S").to_string(), |
||||||
|
err: String::from("Combination of different ASCII character types (numbers, letters and none alphanumeric characters)") }), |
||||||
|
} |
||||||
|
] |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn test_error_type() { |
||||||
|
let form_cases = TestForm::new(); |
||||||
|
|
||||||
|
for v in form_cases { |
||||||
|
assert_eq!(v.form.validate(), v.validation); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
# This file is automatically @generated by Cargo. |
||||||
|
# It is not intended for manual editing. |
||||||
|
[[package]] |
||||||
|
name = "handling" |
||||||
|
version = "0.1.0" |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "handling_test" |
||||||
|
version = "0.1.0" |
||||||
|
dependencies = [ |
||||||
|
"handling", |
||||||
|
] |
@ -0,0 +1,10 @@ |
|||||||
|
[package] |
||||||
|
name = "handling_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] |
||||||
|
handling = { path = "../../../../rust-piscine-solutions/handling"} |
@ -0,0 +1 @@ |
|||||||
|
content to be written |
@ -0,0 +1,63 @@ |
|||||||
|
use std::fs::{File, OpenOptions}; |
||||||
|
use std::io::prelude::*; |
||||||
|
use std::io::{ErrorKind, Write}; |
||||||
|
use handling::*; |
||||||
|
|
||||||
|
fn main() { |
||||||
|
let path = "a.txt"; |
||||||
|
File::create(path).unwrap(); |
||||||
|
open_or_create(path, "content to be written"); |
||||||
|
|
||||||
|
let mut file = File::open(path).unwrap(); |
||||||
|
|
||||||
|
let mut s = String::new(); |
||||||
|
file.read_to_string(&mut s).unwrap(); |
||||||
|
println!("{}", s); |
||||||
|
// output: content to be written
|
||||||
|
} |
||||||
|
|
||||||
|
#[cfg(test)] |
||||||
|
mod tests { |
||||||
|
use super::*; |
||||||
|
use std::fs; |
||||||
|
use std::panic; |
||||||
|
|
||||||
|
fn get_file_content(filename: &str) -> String { |
||||||
|
let mut file = File::open(filename).unwrap(); |
||||||
|
let mut s = String::new(); |
||||||
|
file.read_to_string(&mut s).unwrap(); |
||||||
|
fs::remove_file(filename).unwrap(); |
||||||
|
return s; |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn test_if_file_exists() { |
||||||
|
let filename = "test_existing_file.txt"; |
||||||
|
let content = "hello world!"; |
||||||
|
File::create(filename).unwrap(); |
||||||
|
open_or_create(filename, content); |
||||||
|
|
||||||
|
assert_eq!(content, get_file_content(filename)); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn test_create_file() { |
||||||
|
let file = "no_existing_file.txt"; |
||||||
|
let content = "hello world!"; |
||||||
|
open_or_create(file, content); |
||||||
|
|
||||||
|
assert_eq!(content, get_file_content(file)); |
||||||
|
} |
||||||
|
#[test] |
||||||
|
fn test_error_case() { |
||||||
|
let filename = "hello.txt"; |
||||||
|
File::create(filename).unwrap(); |
||||||
|
let mut perms = fs::metadata(filename).unwrap().permissions(); |
||||||
|
perms.set_readonly(true); |
||||||
|
fs::set_permissions(filename, perms).unwrap(); |
||||||
|
|
||||||
|
let result = panic::catch_unwind(|| open_or_create(filename, "test")); |
||||||
|
fs::remove_file(filename).unwrap(); |
||||||
|
assert!(result.is_err()); |
||||||
|
} |
||||||
|
} |
@ -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 = "panic" |
||||||
|
version = "0.1.0" |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "panic_test" |
||||||
|
version = "0.1.0" |
||||||
|
dependencies = [ |
||||||
|
"panic", |
||||||
|
] |
@ -0,0 +1,10 @@ |
|||||||
|
[package] |
||||||
|
name = "panic_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] |
||||||
|
panic = { path = "../../../../rust-piscine-solutions/panic"} |
@ -0,0 +1,29 @@ |
|||||||
|
use panic::*; |
||||||
|
use std::fs::{self, File}; |
||||||
|
|
||||||
|
fn main() { |
||||||
|
let filename = "created.txt"; |
||||||
|
File::create(filename).unwrap(); |
||||||
|
let a = open_file(filename); |
||||||
|
println!("{:?}", a); |
||||||
|
fs::remove_file(filename).unwrap(); |
||||||
|
} |
||||||
|
|
||||||
|
#[cfg(test)] |
||||||
|
mod tests { |
||||||
|
use super::*; |
||||||
|
|
||||||
|
#[test] |
||||||
|
#[should_panic] |
||||||
|
fn test_opening() { |
||||||
|
open_file("file.txt"); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn test_opening_existing() { |
||||||
|
let filename = "created.txt"; |
||||||
|
File::create(filename).unwrap(); |
||||||
|
open_file(filename); |
||||||
|
fs::remove_file(filename).unwrap(); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,99 @@ |
|||||||
|
# This file is automatically @generated by Cargo. |
||||||
|
# It is not intended for manual editing. |
||||||
|
[[package]] |
||||||
|
name = "autocfg" |
||||||
|
version = "1.0.1" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "chrono" |
||||||
|
version = "0.4.19" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" |
||||||
|
dependencies = [ |
||||||
|
"libc", |
||||||
|
"num-integer", |
||||||
|
"num-traits", |
||||||
|
"time", |
||||||
|
"winapi", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "libc" |
||||||
|
version = "0.2.81" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb" |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "num-integer" |
||||||
|
version = "0.1.44" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" |
||||||
|
dependencies = [ |
||||||
|
"autocfg", |
||||||
|
"num-traits", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "num-traits" |
||||||
|
version = "0.2.14" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" |
||||||
|
dependencies = [ |
||||||
|
"autocfg", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "profanity_filter" |
||||||
|
version = "0.1.0" |
||||||
|
dependencies = [ |
||||||
|
"chrono", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "profanity_filter_test" |
||||||
|
version = "0.1.0" |
||||||
|
dependencies = [ |
||||||
|
"chrono", |
||||||
|
"profanity_filter", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "time" |
||||||
|
version = "0.1.44" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" |
||||||
|
dependencies = [ |
||||||
|
"libc", |
||||||
|
"wasi", |
||||||
|
"winapi", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "wasi" |
||||||
|
version = "0.10.0+wasi-snapshot-preview1" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "winapi" |
||||||
|
version = "0.3.9" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" |
||||||
|
dependencies = [ |
||||||
|
"winapi-i686-pc-windows-gnu", |
||||||
|
"winapi-x86_64-pc-windows-gnu", |
||||||
|
] |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "winapi-i686-pc-windows-gnu" |
||||||
|
version = "0.4.0" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "winapi-x86_64-pc-windows-gnu" |
||||||
|
version = "0.4.0" |
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index" |
||||||
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" |
@ -0,0 +1,11 @@ |
|||||||
|
[package] |
||||||
|
name = "profanity_filter_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] |
||||||
|
profanity_filter = { path = "../../../../rust-piscine-solutions/profanity_filter"} |
||||||
|
chrono = "0.4.19" |
@ -0,0 +1,77 @@ |
|||||||
|
use profanity_filter::*; |
||||||
|
|
||||||
|
fn main() { |
||||||
|
let m0 = Message::new("hello there".to_string(), "toby".to_string(), format_date()); |
||||||
|
println!("{:?}", check_ms(&m0)); |
||||||
|
// output: (true, "hello there")
|
||||||
|
|
||||||
|
let m1 = Message::new("".to_string(), "toby".to_string(), format_date()); |
||||||
|
println!("{:?}", check_ms(&m1)); |
||||||
|
// output: (false, "ERROR: illegal")
|
||||||
|
|
||||||
|
let m2 = Message::new("you are stupid".to_string(), "toby".to_string(), format_date()); |
||||||
|
println!("{:?}", check_ms(&m2)); |
||||||
|
// output: (false, "ERROR: illegal")
|
||||||
|
|
||||||
|
let m3 = Message::new("stupid".to_string(), "toby".to_string(), format_date()); |
||||||
|
println!("{:?}", check_ms(&m3)); |
||||||
|
// output: (false, "ERROR: illegal")
|
||||||
|
} |
||||||
|
|
||||||
|
#[cfg(test)] |
||||||
|
mod tests { |
||||||
|
use super::*; |
||||||
|
use chrono::prelude::Utc; |
||||||
|
|
||||||
|
fn test_format() -> String { |
||||||
|
Utc::now().format("%a %b %e %T %Y").to_string() |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn test_time_format() { |
||||||
|
assert_eq!(format_date(), test_format()); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn test_error_ms() { |
||||||
|
let v = vec![ |
||||||
|
Message::new("".to_string(), "toby".to_string(), format_date()), |
||||||
|
Message::new("stupid".to_string(), "jack".to_string(), format_date()), |
||||||
|
Message::new( |
||||||
|
"you are stupid".to_string(), |
||||||
|
"jacob".to_string(), |
||||||
|
format_date(), |
||||||
|
), |
||||||
|
]; |
||||||
|
for value in v { |
||||||
|
let (t, _) = check_ms(&value); |
||||||
|
assert!(!t); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn test_ok_ms() { |
||||||
|
let v = vec![ |
||||||
|
Message::new( |
||||||
|
"get out of the car".to_string(), |
||||||
|
"police".to_string(), |
||||||
|
format_date(), |
||||||
|
), |
||||||
|
Message::new("no!".to_string(), "thief".to_string(), format_date()), |
||||||
|
Message::new( |
||||||
|
"get the werewolf".to_string(), |
||||||
|
"police".to_string(), |
||||||
|
format_date(), |
||||||
|
), |
||||||
|
Message::new( |
||||||
|
"wait the wha...".to_string(), |
||||||
|
"thief".to_string(), |
||||||
|
format_date(), |
||||||
|
), |
||||||
|
]; |
||||||
|
for value in v { |
||||||
|
let (t, _) = check_ms(&value); |
||||||
|
assert!(t); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
# This file is automatically @generated by Cargo. |
||||||
|
# It is not intended for manual editing. |
||||||
|
[[package]] |
||||||
|
name = "project_motion" |
||||||
|
version = "0.1.0" |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "project_motion_test" |
||||||
|
version = "0.1.0" |
||||||
|
dependencies = [ |
||||||
|
"project_motion", |
||||||
|
] |
@ -0,0 +1,10 @@ |
|||||||
|
[package] |
||||||
|
name = "project_motion_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] |
||||||
|
project_motion = { path = "../../../../rust-piscine-solutions/project_motion"} |
@ -0,0 +1,56 @@ |
|||||||
|
use project_motion::*; |
||||||
|
|
||||||
|
fn main() { |
||||||
|
let mut obj = Object::throw_object(50.0, 150.0); |
||||||
|
println!("{:?}", obj.next()); |
||||||
|
println!("{:?}", obj.next()); |
||||||
|
println!("{:?}", obj.next()); |
||||||
|
println!("{:?}", obj.next()); |
||||||
|
println!("{:?}", obj.next()); |
||||||
|
println!("{:?}", obj.next()); |
||||||
|
} |
||||||
|
|
||||||
|
#[cfg(test)] |
||||||
|
mod tests { |
||||||
|
use super::*; |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn test_short_distance() { |
||||||
|
let mut object = Object::throw_object(50.0, 20.0); |
||||||
|
|
||||||
|
assert_eq!(object.next(), Some(Object { distance: 50.0, velocity: 50.0, height: 15.1, time: 1.0 })); |
||||||
|
assert_eq!(object, Object { distance: 50.0, velocity: 50.0, height: 15.1, time: 1.0 }); |
||||||
|
|
||||||
|
assert!(object.next().is_none(), "{:?} instead of None", object); |
||||||
|
assert!(object.next().is_none(), "{:?} instead of None", object); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn test_media_distance() { |
||||||
|
let mut object = Object::throw_object(100.0, 30.0); |
||||||
|
|
||||||
|
assert_eq!(object.next(), Some(Object { distance: 100.0, velocity: 100.0, height: 25.1, time: 1.0 })); |
||||||
|
assert_eq!(object, Object { distance: 100.0, velocity: 100.0, height: 25.1, time: 1.0 }); |
||||||
|
|
||||||
|
assert_eq!(object.next(), Some(Object { distance: 200.0, velocity: 100.0, height: 5.5, time: 2.0 })); |
||||||
|
assert_eq!(object, Object { distance: 200.0, velocity: 100.0, height: 5.5, time: 2.0 }); |
||||||
|
|
||||||
|
assert!(object.next().is_none(), "{:?} instead of None", object); |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn test_long_distance() { |
||||||
|
let mut object = Object::throw_object(120.0, 100.0); |
||||||
|
|
||||||
|
assert_eq!(object.next(), Some(Object { distance: 120.0, velocity: 120.0, height: 95.1, time: 1.0 })); |
||||||
|
assert_eq!(object, Object { distance: 120.0, velocity: 120.0, height: 95.1, time: 1.0 }); |
||||||
|
|
||||||
|
assert_eq!(object.next(), Some(Object { distance: 240.0, velocity: 120.0, height: 75.5, time: 2.0 })); |
||||||
|
assert_eq!(object, Object { distance: 240.0, velocity: 120.0, height: 75.5, time: 2.0 }); |
||||||
|
|
||||||
|
assert_eq!(object.next(), Some(Object { distance: 360.0, velocity: 120.0, height: 31.4, time: 3.0 })); |
||||||
|
assert_eq!(object, Object { distance: 360.0, velocity: 120.0, height: 31.4, time: 3.0 }); |
||||||
|
|
||||||
|
assert!(object.next().is_none(), "{:?} instead of None", object); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
# This file is automatically @generated by Cargo. |
||||||
|
# It is not intended for manual editing. |
||||||
|
[[package]] |
||||||
|
name = "question_mark" |
||||||
|
version = "0.1.0" |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "question_mark_test" |
||||||
|
version = "0.1.0" |
||||||
|
dependencies = [ |
||||||
|
"question_mark", |
||||||
|
] |
@ -0,0 +1,10 @@ |
|||||||
|
[package] |
||||||
|
name = "question_mark_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] |
||||||
|
question_mark = { path = "../../../../rust-piscine-solutions/question_mark"} |
@ -0,0 +1,47 @@ |
|||||||
|
use question_mark::*; |
||||||
|
|
||||||
|
fn main() { |
||||||
|
let a = One { |
||||||
|
first_layer : Some(Two { |
||||||
|
second_layer: Some(Three { |
||||||
|
third_layer: Some(Four { |
||||||
|
fourth_layer: Some(1000) |
||||||
|
}) |
||||||
|
}) |
||||||
|
}) |
||||||
|
}; |
||||||
|
|
||||||
|
// output: 1000
|
||||||
|
println!("{:?}", match a.get_fourth_layer() { |
||||||
|
Some(e) => e, |
||||||
|
None => 0 |
||||||
|
}) |
||||||
|
} |
||||||
|
|
||||||
|
#[cfg(test)] |
||||||
|
mod tests { |
||||||
|
use super::*; |
||||||
|
#[test] |
||||||
|
fn test_value() { |
||||||
|
let a = One { |
||||||
|
first_layer : Some(Two { |
||||||
|
second_layer: Some(Three { |
||||||
|
third_layer: Some(Four { |
||||||
|
fourth_layer: Some(1000) |
||||||
|
}) |
||||||
|
}) |
||||||
|
}) |
||||||
|
}; |
||||||
|
let b = One { |
||||||
|
first_layer : Some(Two { |
||||||
|
second_layer: Some(Three { |
||||||
|
third_layer: Some(Four { |
||||||
|
fourth_layer: Some(3) |
||||||
|
}) |
||||||
|
}) |
||||||
|
}) |
||||||
|
}; |
||||||
|
assert_eq!(a.get_fourth_layer(), Some(1000)); |
||||||
|
assert_eq!(b.get_fourth_layer(), Some(3)); |
||||||
|
} |
||||||
|
} |
@ -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,12 @@ |
|||||||
|
# This file is automatically @generated by Cargo. |
||||||
|
# It is not intended for manual editing. |
||||||
|
[[package]] |
||||||
|
name = "sales" |
||||||
|
version = "0.1.0" |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "sales_test" |
||||||
|
version = "0.1.0" |
||||||
|
dependencies = [ |
||||||
|
"sales", |
||||||
|
] |
@ -0,0 +1,10 @@ |
|||||||
|
[package] |
||||||
|
name = "sales_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] |
||||||
|
sales = { path = "../../../../rust-piscine-solutions/sales"} |
@ -0,0 +1,133 @@ |
|||||||
|
use sales::*; |
||||||
|
|
||||||
|
fn main() { |
||||||
|
let store = Store::new(vec![ |
||||||
|
(String::from("product A"), 1.23), |
||||||
|
(String::from("product B"), 23.1), |
||||||
|
(String::from("product C"), 3.12)]); |
||||||
|
|
||||||
|
println!("{:?}", store); |
||||||
|
// output:
|
||||||
|
// Store { products: [("product A", 1.23), ("product B", 23.1), ("product C", 3.12)] }
|
||||||
|
|
||||||
|
let mut cart = Cart::new(); |
||||||
|
cart.insert_item(&store, String::from("product A")); |
||||||
|
cart.insert_item(&store, String::from("product B")); |
||||||
|
cart.insert_item(&store, String::from("product C")); |
||||||
|
|
||||||
|
println!("{:?}", cart.generate_receipt()); |
||||||
|
// output:
|
||||||
|
// [1.17, 2.98, 22.07]
|
||||||
|
|
||||||
|
println!("{:?}", cart); |
||||||
|
// output:
|
||||||
|
// Cart { items: [("product A", 1.23), ("product B", 23.1), ("product C", 3.12)], receipt: [1.17, 2.98, 22.07] }
|
||||||
|
} |
||||||
|
#[cfg(test)] |
||||||
|
mod tests { |
||||||
|
use super::*; |
||||||
|
|
||||||
|
#[derive(Debug)] |
||||||
|
struct Tests { |
||||||
|
store: Store, |
||||||
|
carts: Vec<(Cart, Vec<f32>)>, |
||||||
|
} |
||||||
|
|
||||||
|
fn add_items(s: &Store, items: Vec<&str>, c: &mut Cart) { |
||||||
|
for item in items.iter() { |
||||||
|
c.insert_item(s, item.to_string()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl Tests { |
||||||
|
fn new() -> Tests { |
||||||
|
let store = Store::new(vec![ |
||||||
|
(String::from("product A"), 1.23), |
||||||
|
(String::from("product B"), 23.1), |
||||||
|
(String::from("product C"), 3.12), |
||||||
|
(String::from("product D"), 9.75), |
||||||
|
(String::from("product E"), 1.75), |
||||||
|
(String::from("product F"), 23.75), |
||||||
|
(String::from("product G"), 2.75), |
||||||
|
(String::from("product H"), 1.64), |
||||||
|
(String::from("product I"), 15.23), |
||||||
|
(String::from("product J"), 2.10), |
||||||
|
(String::from("product K"), 54.91), |
||||||
|
(String::from("product L"), 43.99), |
||||||
|
]); |
||||||
|
|
||||||
|
let mut c = Cart::new(); |
||||||
|
let mut c1 = Cart::new(); |
||||||
|
let mut c2 = Cart::new(); |
||||||
|
let mut c3 = Cart::new(); |
||||||
|
add_items(&store, vec!["product A", "product B", "product C"], &mut c); |
||||||
|
let sol = vec![1.17, 2.98, 22.07]; |
||||||
|
add_items( |
||||||
|
&store, |
||||||
|
vec![ |
||||||
|
"product A", |
||||||
|
"product B", |
||||||
|
"product C", |
||||||
|
"product D", |
||||||
|
"product E", |
||||||
|
"product F", |
||||||
|
"product G", |
||||||
|
], |
||||||
|
&mut c1, |
||||||
|
); |
||||||
|
let sol1 = vec![1.17, 1.67, 2.62, 2.98, 9.31, 22.05, 22.67]; |
||||||
|
add_items( |
||||||
|
&store, |
||||||
|
vec![ |
||||||
|
"product A", |
||||||
|
"product B", |
||||||
|
"product C", |
||||||
|
"product D", |
||||||
|
"product E", |
||||||
|
"product F", |
||||||
|
"product G", |
||||||
|
"product H", |
||||||
|
"product I", |
||||||
|
], |
||||||
|
&mut c2, |
||||||
|
); |
||||||
|
let sol2 = vec![1.16, 1.55, 1.65, 2.6, 2.94, 9.2, 14.38, 21.8, 22.42]; |
||||||
|
add_items( |
||||||
|
&store, |
||||||
|
vec![ |
||||||
|
"product A", |
||||||
|
"product B", |
||||||
|
"product C", |
||||||
|
"product D", |
||||||
|
"product E", |
||||||
|
"product F", |
||||||
|
"product G", |
||||||
|
"product H", |
||||||
|
"product I", |
||||||
|
"product J", |
||||||
|
"product K", |
||||||
|
"product L", |
||||||
|
], |
||||||
|
&mut c3, |
||||||
|
); |
||||||
|
let sol3 = vec![ |
||||||
|
1.18, 1.58, 1.69, 2.02, 2.65, 3.01, 9.39, 14.67, 22.25, 22.88, 42.38, 52.89, |
||||||
|
]; |
||||||
|
|
||||||
|
Tests { |
||||||
|
store, |
||||||
|
carts: vec![(c, sol), (c1, sol1), (c2, sol2), (c3, sol3)], |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[test] |
||||||
|
fn test_generate_receipt() { |
||||||
|
let cases = Tests::new(); |
||||||
|
|
||||||
|
for (mut c, sol) in cases.carts.into_iter() { |
||||||
|
assert_eq!(c.generate_receipt(), sol); |
||||||
|
assert_eq!(c.receipt, sol); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,12 @@ |
|||||||
|
# This file is automatically @generated by Cargo. |
||||||
|
# It is not intended for manual editing. |
||||||
|
[[package]] |
||||||
|
name = "unwrap_and_expect" |
||||||
|
version = "0.1.0" |
||||||
|
|
||||||
|
[[package]] |
||||||
|
name = "unwrap_and_expect_test" |
||||||
|
version = "0.1.0" |
||||||
|
dependencies = [ |
||||||
|
"unwrap_and_expect", |
||||||
|
] |
@ -0,0 +1,10 @@ |
|||||||
|
[package] |
||||||
|
name = "unwrap_and_expect_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] |
||||||
|
unwrap_and_expect = { path = "../../../../rust-piscine-solutions/unwrap_and_expect"} |
@ -0,0 +1,49 @@ |
|||||||
|
use unwrap_and_expect::*; |
||||||
|
|
||||||
|
fn main() { |
||||||
|
println!("{:?}", unwrap_or(vec![1, 3, 2, 5])); |
||||||
|
println!("{:?}", unwrap_or(vec![1, 3, 5])); |
||||||
|
println!("{:?}", unwrap_err(vec![1, 3, 2, 5])); |
||||||
|
println!("{:?}", unwrap(vec![1, 3, 5])); |
||||||
|
println!("{:?}", unwrap_or_else(vec![1, 3, 5])); |
||||||
|
println!("{:?}", unwrap_or_else(vec![3, 2, 6, 5])); |
||||||
|
} |
||||||
|
|
||||||
|
#[cfg(test)] |
||||||
|
mod tests { |
||||||
|
use super::*; |
||||||
|
|
||||||
|
#[test] |
||||||
|
#[should_panic(expected = "ERROR : (\"There is a even value in the vector!\", [2])")] |
||||||
|
fn test_expect() { |
||||||
|
expect(vec![1, 3, 2, 5]); |
||||||
|
} |
||||||
|
#[test] |
||||||
|
#[should_panic(expected = "called `Result::unwrap()` on an `Err` value: (\"There is a even value in the vector!\", [2])")] |
||||||
|
fn test_unwrap() { |
||||||
|
unwrap(vec![1, 3, 2, 5]); |
||||||
|
} |
||||||
|
#[test] |
||||||
|
#[should_panic] |
||||||
|
fn test_unwrap_err() { |
||||||
|
unwrap_err(vec![1, 3, 5]); |
||||||
|
} |
||||||
|
#[test] |
||||||
|
fn test_unwrap_or() { |
||||||
|
assert_eq!(unwrap_or(vec![1, 3, 2, 5]), vec![]); |
||||||
|
} |
||||||
|
#[test] |
||||||
|
fn test_unwrap_or_else() { |
||||||
|
assert_eq!(unwrap_or_else(vec![1, 3, 5]), vec![2, 4, 6]); |
||||||
|
assert_eq!(unwrap_or_else(vec![6, 8, 3, 2, 5, 4]), vec![6, 8, 2, 4]); |
||||||
|
} |
||||||
|
#[test] |
||||||
|
fn test_ok() { |
||||||
|
assert_eq!(expect(vec![1, 3, 5]), vec![2, 4, 6]); |
||||||
|
assert_eq!(unwrap_or(vec![1, 3, 5]), vec![2, 4, 6]); |
||||||
|
assert_eq!(unwrap_or_else(vec![1, 3, 5]), vec![2, 4, 6]); |
||||||
|
assert_eq!(unwrap(vec![1, 3, 5]), vec![2, 4, 6]); |
||||||
|
assert_eq!(unwrap_err(vec![1, 2, 3, 4, 5]).0, "There is a even value in the vector!"); |
||||||
|
assert_eq!(unwrap_err(vec![1, 2, 3, 4, 5]).1, vec![2, 4]); |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,110 @@ |
|||||||
|
## banner |
||||||
|
|
||||||
|
### Instructions |
||||||
|
|
||||||
|
`Result` is a better version of the `Option` type that describes possible error instead |
||||||
|
of possible absence |
||||||
|
|
||||||
|
Create a structure called `Flag` that as the following elements: |
||||||
|
|
||||||
|
- short_hand: String |
||||||
|
- long_hand: String |
||||||
|
- desc: String |
||||||
|
|
||||||
|
This structure must have associated to it a function called `opt_flag` that initializes the structure. |
||||||
|
Receiving two references strings and returns the structure `Flag`. It should be used like this: |
||||||
|
|
||||||
|
```rust |
||||||
|
let d = Flag::opt_flag("diff", "gives the difference between two numbers"); |
||||||
|
|
||||||
|
println!("short hand: {}, long hand: {}, description: {}", d.short_hand, d.long_hand, d.desc); |
||||||
|
// output: "short hand: -d, long hand: --diff, description: gives the difference between two numbers" |
||||||
|
``` |
||||||
|
|
||||||
|
It will be given a second structure called `FlagsHandler` that has just one element: `flags: HashMap<(String, String), Callback>` |
||||||
|
And the following functions associated to it, for you to complete : |
||||||
|
|
||||||
|
- `add_flag`, that adds to the HashMap the flag and the Callback function. |
||||||
|
- `exec_func`, that executes the function using the flag provided and returns the result, that can |
||||||
|
be either a string with the value from the callback or an error. |
||||||
|
|
||||||
|
It will also be provided a `type` called `Callback` being a function that is going to be used in the structure |
||||||
|
and functions above. This function will be the callback for the flag associated to it. |
||||||
|
|
||||||
|
You will have to create the following callback functions : |
||||||
|
|
||||||
|
- `div`, that converts the reference strings to `float`s and returns the `Result`, being the division of the `float`s or the standard (std) error: `ParseFloatError`. |
||||||
|
- `rem`, that converts the reference strings to `float`s and returns the `Result`, being the remainder of the division of the `float`s or the standard (std) error `ParseFloatError`. |
||||||
|
|
||||||
|
### Expected Function |
||||||
|
|
||||||
|
```rust |
||||||
|
use std::collections::HashMap; |
||||||
|
|
||||||
|
pub type Callback = fn(&str, &str) -> Result<String, ParseFloatError>; |
||||||
|
|
||||||
|
pub struct FlagsHandler { |
||||||
|
pub flags: HashMap<(String, String), Callback>, |
||||||
|
} |
||||||
|
|
||||||
|
impl FlagsHandler { |
||||||
|
pub fn add_flag(&mut self, flag: (String, String), func: Callback) {} |
||||||
|
pub fn exec_func(&mut self, flag: (String, String), argv: &[&str]) -> String {} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
pub struct Flag { |
||||||
|
// expected public fields |
||||||
|
} |
||||||
|
|
||||||
|
impl Flag { |
||||||
|
pub fn opt_flag(l_h: &str, d: &str) -> Flag {} |
||||||
|
} |
||||||
|
|
||||||
|
pub fn div(a: &str, b: &str) -> Result<String, ParseFloatError> {} |
||||||
|
pub fn rem(a: &str, b: &str) -> Result<String, ParseFloatError> {} |
||||||
|
|
||||||
|
``` |
||||||
|
|
||||||
|
### Usage |
||||||
|
|
||||||
|
Here is a program to test your function |
||||||
|
|
||||||
|
```rust |
||||||
|
fn main() { |
||||||
|
let mut handler = FlagsHandler { flags: HashMap::new() }; |
||||||
|
|
||||||
|
let d = Flag::opt_flag("division", "divides the values, formula (a / b)"); |
||||||
|
let r = Flag::opt_flag( |
||||||
|
"remainder", |
||||||
|
"remainder of the division between two values, formula (a % b)", |
||||||
|
); |
||||||
|
|
||||||
|
handler.add_flag((d.short_hand, d.long_hand), div); |
||||||
|
handler.add_flag((r.short_hand, r.long_hand), rem); |
||||||
|
|
||||||
|
println!("{:?}", handler.exec_func(("-d".to_string(), "--division".to_string()), &["1.0", "2.0"])); |
||||||
|
|
||||||
|
println!("{:?}",handler.exec_func(("-r".to_string(), "--remainder".to_string()), &["2.0", "2.0"])); |
||||||
|
|
||||||
|
println!("{:?}",handler.exec_func(("-d".to_string(), "--division".to_string()), &["a", "2.0"])); |
||||||
|
|
||||||
|
println!("{:?}",handler.exec_func(("-r".to_string(), "--remainder".to_string()), &["2.0", "fd"])); |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
And its output: |
||||||
|
|
||||||
|
```console |
||||||
|
student@ubuntu:~/[[ROOT]]/test$ cargo run |
||||||
|
"0.5" |
||||||
|
"0" |
||||||
|
"invalid float literal" |
||||||
|
"invalid float literal" |
||||||
|
student@ubuntu:~/[[ROOT]]/test$ |
||||||
|
``` |
||||||
|
|
||||||
|
### Notions |
||||||
|
|
||||||
|
- https://doc.rust-lang.org/rust-by-example/error/result.html |
||||||
|
- https://docs.rs/getopts/0.2.18/getopts/struct.Options.html#method.optflag |
@ -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,165 @@ |
|||||||
|
## boxing_todo |
||||||
|
|
||||||
|
### Instructions |
||||||
|
|
||||||
|
The objective is to do an api to parse a list of *todos* that is organized in a JSON file, |
||||||
|
handling all possible errors in a multiple error system. |
||||||
|
|
||||||
|
Organization of the JSON file: |
||||||
|
|
||||||
|
```json |
||||||
|
{ |
||||||
|
"title" : "TODO LIST FOR PISCINE RUST", |
||||||
|
"tasks": [ |
||||||
|
{ "id": 0, "description": "do this", "level": 0 }, |
||||||
|
{ "id": 1, "description": "do that", "level": 5 } |
||||||
|
] |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
Create a module in another file called **error.rs** that handles the boxing of errors. |
||||||
|
This module must implement an `enum` called `ParseErr` that will take care of the |
||||||
|
parsing errors, it must have the following elements: |
||||||
|
|
||||||
|
- Empty |
||||||
|
- Malformed, that has a dynamic boxed error as element |
||||||
|
|
||||||
|
A structure called `ReadErr` that will take care of the reading errors, having just an element called `child_err` of type `Box<dyn Error>`. |
||||||
|
|
||||||
|
For each data structure you will have to implement a function called `fmt` for the trait `Display` that writes |
||||||
|
out the message **"Fail to parse todo"** in case it's a parsing error, otherwise it writes the message |
||||||
|
**"Failed to read todo file"**. |
||||||
|
And for the `Error` trait the following functions: |
||||||
|
|
||||||
|
- `description` that returns a string literal that says: |
||||||
|
- "Todo List parse failed: " for the `ParseErr` |
||||||
|
- "Todo List read failed: " for the `ReadErr`. |
||||||
|
|
||||||
|
- `cause` that returns an `Option` with the error: |
||||||
|
- For the `ReadErr` it must just return the option with the error |
||||||
|
- For the `ParseErr` it will return an option that can be `None` if the tasks are **empty** otherwise the error, if |
||||||
|
the parsing is **malformed**. |
||||||
|
|
||||||
|
In the **lib** file you will have to implement a function called `get_todo` that receives a string and returns a Result |
||||||
|
that can be the structure `TodoList` or a boxing error. This function must be able to deserialize the json file, |
||||||
|
basically it must parse and read the JSON file and return the `TodoList` if everything is fine otherwise the error. |
||||||
|
|
||||||
|
### Expected Function |
||||||
|
|
||||||
|
For **error.rs** |
||||||
|
|
||||||
|
```rust |
||||||
|
use std::fmt; |
||||||
|
use std::fmt::Display; |
||||||
|
use std::error::Error; |
||||||
|
|
||||||
|
pub enum ParseErr { |
||||||
|
// expected public fields |
||||||
|
} |
||||||
|
|
||||||
|
// required by error trait |
||||||
|
impl Display for ParseErr { |
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
pub struct ReadErr { |
||||||
|
// expected public fields |
||||||
|
} |
||||||
|
|
||||||
|
// required by error trait |
||||||
|
impl Display for ReadErr { |
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl Error for ReadErr { |
||||||
|
fn description(&self) -> &str {} |
||||||
|
fn cause(&self) -> Option<&dyn Error> {} |
||||||
|
} |
||||||
|
|
||||||
|
impl Error for ParseErr { |
||||||
|
fn description(&self) -> &str {} |
||||||
|
fn cause(&self) -> Option<&dyn Error> {} |
||||||
|
} |
||||||
|
|
||||||
|
``` |
||||||
|
|
||||||
|
for **lib.rs** |
||||||
|
|
||||||
|
```rust |
||||||
|
mod error; |
||||||
|
use error::{ ParseErr, ReadErr }; |
||||||
|
use std::error::Error; |
||||||
|
use serde::{ Deserialize, Serialize }; |
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] |
||||||
|
pub struct Task { |
||||||
|
id: u32, |
||||||
|
description: String, |
||||||
|
level: u32, |
||||||
|
} |
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)] |
||||||
|
pub struct TodoList { |
||||||
|
title: String, |
||||||
|
tasks: Vec<Task>, |
||||||
|
} |
||||||
|
|
||||||
|
impl TodoList { |
||||||
|
pub fn get_todo(path: &str) -> Result<TodoList, Box<dyn Error>> {} |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
### Usage |
||||||
|
|
||||||
|
Here is a program to test your function. |
||||||
|
Note that you can create some todo list your self to test it, but you can find the JSON files that |
||||||
|
are being tested [here](https://github.com/01-edu/public/blob/master/subjects/boxing_todo) |
||||||
|
|
||||||
|
```rust |
||||||
|
mod lib; |
||||||
|
use lib::{ TodoList }; |
||||||
|
|
||||||
|
fn main() { |
||||||
|
let todos = TodoList::get_todo("todo.json"); |
||||||
|
match todos { |
||||||
|
Ok(list) => println!("{:?}", list), |
||||||
|
Err(e) => { |
||||||
|
println!("{}{:?}", e.description(), e.cause()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
let todos = TodoList::get_todo("no_todo_list.json"); |
||||||
|
match todos { |
||||||
|
Ok(list) => println!("{:?}", list), |
||||||
|
Err(e) => { |
||||||
|
println!("{}{:?}", e.description(), e.cause()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
let todos = TodoList::get_todo("malformed_object.json"); |
||||||
|
match todos { |
||||||
|
Ok(list) => println!("{:?}", list), |
||||||
|
Err(e) => { |
||||||
|
println!("{}{:?}", e.description(), e.cause().unwrap()); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
And its output: |
||||||
|
|
||||||
|
```console |
||||||
|
student@ubuntu:~/[[ROOT]]/test$ cargo run |
||||||
|
TodoList { title: "TODO LIST FOR PISCINE RUST", tasks: [Task { id: 0, description: "do this", level: 0 }, Task { id: 1, description: "do that", level: 5 }] } |
||||||
|
Todo List parse failed: None |
||||||
|
Todo List parse failed: Malformed(Error("missing field `title`", line: 1, column: 2)) |
||||||
|
student@ubuntu:~/[[ROOT]]/test$ |
||||||
|
``` |
||||||
|
|
||||||
|
### Notions |
||||||
|
|
||||||
|
- https://serde.rs/ |
||||||
|
- https://doc.rust-lang.org/stable/rust-by-example/error/multiple_error_types/boxing_errors.html |
||||||
|
- https://doc.rust-lang.org/stable/rust-by-example/trait/dyn.html |
@ -0,0 +1 @@ |
|||||||
|
{} |
@ -0,0 +1,7 @@ |
|||||||
|
{ |
||||||
|
"title" : "TODO LIST FOR PISCINE RUST", |
||||||
|
"tasks": [ |
||||||
|
{ "id": 0, "description": "do this", "level": 0 }, |
||||||
|
{ "id": 1, "description": "do that", "level": 5 } |
||||||
|
] |
||||||
|
} |
@ -0,0 +1,4 @@ |
|||||||
|
{ |
||||||
|
"title" : "TODO LIST FOR PISCINE RUST", |
||||||
|
"tasks": [] |
||||||
|
} |
@ -0,0 +1,47 @@ |
|||||||
|
## cipher |
||||||
|
|
||||||
|
### Instructions |
||||||
|
|
||||||
|
The Atbash cipher is a encryption method in which each letter of a word is replaced with its mirror letter in the alphabet |
||||||
|
|
||||||
|
Your objective is to create a function called `cipher` this must return a Result wrapped in an Option, this result should return either a boolean |
||||||
|
or an Error being the structure `CipherError`. This structure should be the error type for the function `cipher` |
||||||
|
|
||||||
|
This function should compare the original string wih the ciphered string. returning true if the cipher is correct otherwise the error type |
||||||
|
CipherErr with the a true or false if it is validated and the proper atbash cipher. |
||||||
|
|
||||||
|
### Expected Function |
||||||
|
|
||||||
|
```rust |
||||||
|
|
||||||
|
#[derive(Debug, Clone, Eq, PartialEq)] |
||||||
|
pub struct CipherError { |
||||||
|
// expected public fields |
||||||
|
} |
||||||
|
impl CipherError { |
||||||
|
pub fn new(validation: bool, expected: String) -> CipherError {} |
||||||
|
} |
||||||
|
pub fn cipher(original: &str, ciphered: &str) -> Option<Result<bool, CipherError>> {} |
||||||
|
``` |
||||||
|
|
||||||
|
### Usage |
||||||
|
|
||||||
|
Here is a program to test your function |
||||||
|
|
||||||
|
```rust |
||||||
|
fn main() { |
||||||
|
println!("{:?}", cipher("1Hello 2world!", "1Svool 2dliow!")); |
||||||
|
println!("{:?}", cipher("1Hello 2world!", "svool")); |
||||||
|
println!("{:?}", cipher("", "svool")); |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
And its output: |
||||||
|
|
||||||
|
```console |
||||||
|
student@ubuntu:~/[[ROOT]]/test$ cargo run |
||||||
|
Some(Ok(true)) |
||||||
|
Some(Err(CipherError { validation: false, expected: "1Svool 2dliow!" })) |
||||||
|
None |
||||||
|
student@ubuntu:~/[[ROOT]]/test$ |
||||||
|
``` |
@ -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,124 @@ |
|||||||
|
## error types |
||||||
|
|
||||||
|
### Instructions |
||||||
|
|
||||||
|
For this exercise you will have to implement an **error type**. |
||||||
|
|
||||||
|
The main objective is to create a form validator, where you must implement a |
||||||
|
error type. This must validate the password and the first name. The |
||||||
|
first name must not be empty and the password must have at least 8 char and a combination of alphanumeric and none alphanumeric ASCII characters |
||||||
|
|
||||||
|
ex: "asDd123=%" => good |
||||||
|
"asgfD" => error |
||||||
|
"asdsdf2" => error |
||||||
|
"sad_#$" => error |
||||||
|
|
||||||
|
Create a structure called `Form` that will have the following fields: |
||||||
|
|
||||||
|
- `first_name`, that will be a string |
||||||
|
- `last_name`, that will be a string |
||||||
|
- `birth`, of type `NaiveDate` that will convert a string "2015-09-05" to a date of that format |
||||||
|
- `sex`, SexType that must be a `enum` with the fields `Male` and `Female` |
||||||
|
- `birth_location`, that will be a string |
||||||
|
- `password`, that will be a string |
||||||
|
|
||||||
|
You must also implement for this structure a function to initialize the structure, `new` and a function called |
||||||
|
`validate` that will validate the form |
||||||
|
|
||||||
|
For the error type you must create a type struct called `FErr`, that will be the type for the error |
||||||
|
It must have the fields: |
||||||
|
|
||||||
|
- `form_values`, this will be a tuple of strings that will save the value that the user inserted into the form |
||||||
|
|
||||||
|
ex: ("password", "asdaSD_") |
||||||
|
("first_name", "someone") |
||||||
|
|
||||||
|
- `date`, that will have the date that the error occurred in the format "2020-12-14 09:33:41" |
||||||
|
- `err`, that will have the error description: |
||||||
|
- "No user name" |
||||||
|
- "At least 8 characters" |
||||||
|
- "Combination of different ASCII character types (numbers, letters and none alphanumeric characters)" |
||||||
|
|
||||||
|
### Expected Function |
||||||
|
|
||||||
|
```rust |
||||||
|
pub use chrono::{Utc, NaiveDate}; |
||||||
|
|
||||||
|
// this will be the structure that wil handle the errors |
||||||
|
#[derive(Debug, Eq, PartialEq)] |
||||||
|
pub struct FErr { |
||||||
|
// expected public fields |
||||||
|
} |
||||||
|
impl FErr { |
||||||
|
pub fn new(name: String, error: String, err: String) -> FErr {} |
||||||
|
} |
||||||
|
|
||||||
|
#[derive(Debug, Eq, PartialEq)] |
||||||
|
pub enum SexType { |
||||||
|
// expected public fields |
||||||
|
} |
||||||
|
#[derive(Debug, Eq, PartialEq)] |
||||||
|
pub struct Form { |
||||||
|
// expected public fields |
||||||
|
} |
||||||
|
|
||||||
|
impl Form { |
||||||
|
pub fn new(first_name: String, |
||||||
|
last_name: String, |
||||||
|
birth: NaiveDate, |
||||||
|
sex: SexType, |
||||||
|
birth_location: String, |
||||||
|
password: String) -> Form {} |
||||||
|
pub fn validate(&self) -> Result<Vec<&str>, FErr> {} |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
### Usage |
||||||
|
|
||||||
|
Here is a program to test your function |
||||||
|
|
||||||
|
```rust |
||||||
|
fn main() { |
||||||
|
let mut form_output = Form::new( |
||||||
|
String::from("Alice"), |
||||||
|
String::from("Bear"), |
||||||
|
create_date("2015-09-05"), |
||||||
|
SexType::Male, |
||||||
|
String::from("Africa"), |
||||||
|
String::from("qwqwsa1dty_")); |
||||||
|
|
||||||
|
println!("{:?}", form_output); |
||||||
|
println!("{:?}", form_output.validate().unwrap()); |
||||||
|
|
||||||
|
form_output.first_name = String::from(""); |
||||||
|
println!("{:?}", form_output.validate().unwrap_err()); |
||||||
|
|
||||||
|
form_output.first_name = String::from("as"); |
||||||
|
form_output.password = String::from("dty_1"); |
||||||
|
println!("{:?}", form_output.validate().unwrap_err()); |
||||||
|
|
||||||
|
form_output.password = String::from("asdasASd(_"); |
||||||
|
println!("{:?}", form_output.validate().unwrap_err()); |
||||||
|
|
||||||
|
form_output.password = String::from("asdasASd123SA"); |
||||||
|
println!("{:?}", form_output.validate().unwrap_err()); |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
And its output: |
||||||
|
|
||||||
|
```console |
||||||
|
student@ubuntu:~/[[ROOT]]/test$ cargo run |
||||||
|
Form { first_name: "Lee", last_name: "Silva", birth: 2015-09-05, sex: Male, birth_location: "Africa", password: "qwqwsa1dty_" } |
||||||
|
["Valid first name", "Valid password"] |
||||||
|
FErr { form_values: ("first_name", ""), date: "2020-12-28 13:29:11", err: "No user name" } |
||||||
|
FErr { form_values: ("password", "dty_1"), date: "2020-12-28 13:29:11", err: "At least 8 characters" } |
||||||
|
FErr { form_values: ("password", "asdasASd(_"), date: "2020-12-28 13:29:11", err: "Combination of different ASCII character types (numbers, letters and none alphanumeric characters)" } |
||||||
|
FErr { form_values: ("password", "asdasASd123SA"), date: "2020-12-28 13:29:11", err: "Combination of different ASCII character types (numbers, letters and none alphanumeric characters)" } |
||||||
|
student@ubuntu:~/[[ROOT]]/test$ |
||||||
|
``` |
||||||
|
|
||||||
|
### Notions |
||||||
|
|
||||||
|
- https://doc.rust-lang.org/rust-by-example/error/multiple_error_types/define_error_type.html |
||||||
|
- https://docs.rs/chrono/0.4.19/chrono/naive/struct.NaiveDate.html |
@ -0,0 +1,48 @@ |
|||||||
|
## handling |
||||||
|
|
||||||
|
### Instructions |
||||||
|
|
||||||
|
Write a function, called `open_or_create` that as two arguments: |
||||||
|
|
||||||
|
- `file : &str` which is the name of the files |
||||||
|
- `content: &str` being the content to be written into the file |
||||||
|
|
||||||
|
This functions should try to open a file, if it does not exist creates it. |
||||||
|
You should panic, with the error, in case something goes wrong. |
||||||
|
|
||||||
|
### Expected Function |
||||||
|
|
||||||
|
```rust |
||||||
|
pub fn open_or_create(s: &str, content: &str) {} |
||||||
|
``` |
||||||
|
|
||||||
|
### Usage |
||||||
|
|
||||||
|
Here is a program to test your function |
||||||
|
|
||||||
|
```rust |
||||||
|
fn main() { |
||||||
|
let path = "a.txt"; |
||||||
|
File::create(path).unwrap(); |
||||||
|
open_or_create(path, "content to be written"); |
||||||
|
|
||||||
|
let mut file = File::open(path).unwrap(); |
||||||
|
|
||||||
|
let mut s = String::new(); |
||||||
|
file.read_to_string(&mut s).unwrap(); |
||||||
|
println!("{}", s); |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
And its output: |
||||||
|
|
||||||
|
```console |
||||||
|
student@ubuntu:~/[[ROOT]]/test$ cargo run |
||||||
|
content to be written |
||||||
|
student@ubuntu:~/[[ROOT]]/test$ |
||||||
|
``` |
||||||
|
|
||||||
|
### Notions |
||||||
|
|
||||||
|
- https://doc.rust-lang.org/std/io/enum.ErrorKind.html |
||||||
|
- https://doc.rust-lang.org/std/fs/struct.File.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,34 @@ |
|||||||
|
## panic |
||||||
|
|
||||||
|
### Instructions |
||||||
|
|
||||||
|
Write a function that tries to open a file and panics if the file |
||||||
|
doesn't exist |
||||||
|
|
||||||
|
### Expected Function |
||||||
|
|
||||||
|
```rust |
||||||
|
pub fn open_file(s: &str) -> File {} |
||||||
|
``` |
||||||
|
|
||||||
|
### Usage |
||||||
|
|
||||||
|
Here is a program to test your function |
||||||
|
|
||||||
|
```rust |
||||||
|
fn main() { |
||||||
|
let filename = "created.txt"; |
||||||
|
File::create(filename).unwrap(); |
||||||
|
let a = open_file(filename); |
||||||
|
println!("{:?}", a); |
||||||
|
fs::remove_file(filename).unwrap(); |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
And its output: |
||||||
|
|
||||||
|
```console |
||||||
|
student@ubuntu:~/[[ROOT]]/test$ cargo run |
||||||
|
File { fd: 3, path: "[[ROOT]]/a.txt", read: true, write: false } |
||||||
|
student@ubuntu:~/[[ROOT]]/test$ |
||||||
|
``` |
@ -0,0 +1,81 @@ |
|||||||
|
## profanity filter |
||||||
|
|
||||||
|
### Instructions |
||||||
|
|
||||||
|
Sometimes it is more desirable to catch the failure of some parts of a program instead |
||||||
|
of just calling panic. |
||||||
|
|
||||||
|
For this exercise you will have to create a message blocker, where you must block the word `stupid` |
||||||
|
|
||||||
|
You will have to create a structure called `Message`, this structure |
||||||
|
must have the following elements: |
||||||
|
|
||||||
|
- content: String |
||||||
|
- user: String |
||||||
|
- time_sent: String |
||||||
|
|
||||||
|
The struct must also have a implementation of 2 functions associated to it: |
||||||
|
|
||||||
|
- `new`, that initializes the structure |
||||||
|
- `send_ms`, that only has its implementation type (**self**) as argument and returns an option. |
||||||
|
This function must return `None` if the content of the message is either **empty** or contains the |
||||||
|
word **stupid**. Otherwise it returns the content of the message. |
||||||
|
|
||||||
|
You will have to create two more functions that aren't associated to any structure: |
||||||
|
|
||||||
|
- `check_ms` that receives as parameters the reference to the structure `Message` and returns a tuple, |
||||||
|
containing a `bool` and a `string`. This function will execute the function `send_ms` and if the result |
||||||
|
of the option is `None` it should return (false, "ERROR: illegal"). Otherwise it returns `true` and the |
||||||
|
content of the message sent. |
||||||
|
- `date_format` that creates and formats the date and time that the message was sent, the format should |
||||||
|
look like this: **Mon Oct 5 10:22:19 2020** |
||||||
|
|
||||||
|
### Expected Function |
||||||
|
|
||||||
|
```rust |
||||||
|
pub struct Message {} |
||||||
|
|
||||||
|
impl Message { |
||||||
|
pub fn new(ms: String, u: String, t: String) -> Message {} |
||||||
|
pub fn send_ms(&self) -> Option<&str> {} |
||||||
|
} |
||||||
|
|
||||||
|
pub fn check_ms(ms: &Message) -> (bool, &str) {} |
||||||
|
pub fn format_date() -> String {} |
||||||
|
``` |
||||||
|
|
||||||
|
### Usage |
||||||
|
|
||||||
|
Here is a program to test your function |
||||||
|
|
||||||
|
```rust |
||||||
|
fn main() { |
||||||
|
let m0 = Message::new("hello there".to_string(), "toby".to_string(), format_date()); |
||||||
|
println!("{:?}", check_ms(&m0)); |
||||||
|
|
||||||
|
let m1 = Message::new("".to_string(), "toby".to_string(), format_date()); |
||||||
|
println!("{:?}", check_ms(&m1)); |
||||||
|
|
||||||
|
let m2 = Message::new("you are stupid".to_string(), "toby".to_string(), format_date()); |
||||||
|
println!("{:?}", check_ms(&m2)); |
||||||
|
|
||||||
|
let m3 = Message::new("stupid".to_string(), "toby".to_string(), format_date()); |
||||||
|
println!("{:?}", check_ms(&m3)); |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
And its output: |
||||||
|
|
||||||
|
```console |
||||||
|
student@ubuntu:~/[[ROOT]]/test$ cargo run |
||||||
|
(true, "hello there") |
||||||
|
(false, "ERROR: illegal") |
||||||
|
(false, "ERROR: illegal") |
||||||
|
(false, "ERROR: illegal") |
||||||
|
student@ubuntu:~/[[ROOT]]/test$ |
||||||
|
``` |
||||||
|
|
||||||
|
### Notions |
||||||
|
|
||||||
|
- https://docs.rs/chrono/0.4.19/chrono/ |
||||||
|
- https://doc.rust-lang.org/stable/book/ch06-01-defining-an-enum.html?highlight=option#the-option-enum-and-its-advantages-over-null-values |
@ -0,0 +1,70 @@ |
|||||||
|
## project_motion |
||||||
|
|
||||||
|
### Instructions |
||||||
|
|
||||||
|
For this exercise you will have to create a [projectile motion](https://cimg2.ck12.org/datastreams/f-d%3Abb024be6673110b31e78b46819e792adaed8dc661e082a61f0a6d64e%2BIMAGE%2BIMAGE.1). |
||||||
|
|
||||||
|
You will be provided with a structure called `Object` that will have all variables that are |
||||||
|
essential for the projectile physics. (distance, velocity, height, time) |
||||||
|
|
||||||
|
You must implement : |
||||||
|
|
||||||
|
- A function `throw_object` that will initialize the Object with a given velocity and height. |
||||||
|
- The trait Iterator with the `.next()` in which it must calculate the next position of the object after 1 second. |
||||||
|
It will return an `Option` with the Object, It will return `None` if the object already reached the floor. |
||||||
|
|
||||||
|
### Expected Function |
||||||
|
|
||||||
|
```rust |
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq)] |
||||||
|
pub struct Object { |
||||||
|
pub distance: f32, |
||||||
|
pub velocity: f32, |
||||||
|
pub height: f32, |
||||||
|
pub time: f32, |
||||||
|
} |
||||||
|
|
||||||
|
impl Object { |
||||||
|
pub fn throw_object(velocity: f32, height: f32) -> Object {} |
||||||
|
} |
||||||
|
|
||||||
|
impl Iterator for Object { |
||||||
|
// next |
||||||
|
} |
||||||
|
|
||||||
|
``` |
||||||
|
|
||||||
|
### Usage |
||||||
|
|
||||||
|
Here is a program to test your function |
||||||
|
|
||||||
|
```rust |
||||||
|
fn main() { |
||||||
|
let mut obj = Object::throw_object(50.0, 150.0); |
||||||
|
println!("{:?}", obj.next()); |
||||||
|
println!("{:?}", obj.next()); |
||||||
|
println!("{:?}", obj.next()); |
||||||
|
println!("{:?}", obj.next()); |
||||||
|
println!("{:?}", obj.next()); |
||||||
|
println!("{:?}", obj.next()); |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
And its output: |
||||||
|
|
||||||
|
```console |
||||||
|
student@ubuntu:~/[[ROOT]]/test$ cargo run |
||||||
|
Some(Object { distance: 50.0, velocity: 50.0, height: 145.1, time: 1.0 }) |
||||||
|
Some(Object { distance: 100.0, velocity: 50.0, height: 125.5, time: 2.0 }) |
||||||
|
Some(Object { distance: 150.0, velocity: 50.0, height: 81.4, time: 3.0 }) |
||||||
|
Some(Object { distance: 200.0, velocity: 50.0, height: 3.0, time: 4.0 }) |
||||||
|
None |
||||||
|
None |
||||||
|
student@ubuntu:~/[[ROOT]]/test$ |
||||||
|
``` |
||||||
|
|
||||||
|
### Notions |
||||||
|
|
||||||
|
- https://doc.rust-lang.org/std/iter/trait.Iterator.html |
||||||
|
- https://doc.rust-lang.org/rust-by-example/trait/iter.html |
@ -0,0 +1,70 @@ |
|||||||
|
## question_mark |
||||||
|
|
||||||
|
### Instructions |
||||||
|
|
||||||
|
You will have to create 3 structures: |
||||||
|
|
||||||
|
- `One`, that contains one element called `first_layer` it should be an `Option` for the structure `Two`. |
||||||
|
- `Two`, that contains one element called `second_layer` it should be an `Option` for the structure `Three`. |
||||||
|
- `Three`, that contains one element called `third_layer` it should be an `Option` for the structure `Four`. |
||||||
|
- `Four`, that contains one element called `fourth_layer` it should be an `u16` that is an `Option`. |
||||||
|
|
||||||
|
Beside the structure you must create a function named `get_fourth_layer` that is associated to the `One` structure. |
||||||
|
This function should return the `Option` value in the `Four` structure. |
||||||
|
|
||||||
|
### Expected Function |
||||||
|
|
||||||
|
```rust |
||||||
|
pub struct One { |
||||||
|
// expected public fields |
||||||
|
} |
||||||
|
pub struct Two { |
||||||
|
// expected public fields |
||||||
|
} |
||||||
|
pub struct Three { |
||||||
|
// expected public fields |
||||||
|
} |
||||||
|
pub struct Four { |
||||||
|
// expected public fields |
||||||
|
} |
||||||
|
|
||||||
|
impl One { |
||||||
|
pub fn get_fourth_layer(&self) -> Option<u16> {} |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
### Usage |
||||||
|
|
||||||
|
Here is a program to test your function |
||||||
|
|
||||||
|
```rust |
||||||
|
fn main() { |
||||||
|
let a = One { |
||||||
|
first_layer : Some(Two { |
||||||
|
second_layer: Some(Three { |
||||||
|
third_layer: Some(Four { |
||||||
|
fourth_layer: Some(1000) |
||||||
|
}) |
||||||
|
}) |
||||||
|
}) |
||||||
|
}; |
||||||
|
|
||||||
|
// output: 1000 |
||||||
|
println!("{:?}", match a.get_fourth_layer() { |
||||||
|
Some(e) => e, |
||||||
|
None => 0 |
||||||
|
}) |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
And its output: |
||||||
|
|
||||||
|
```console |
||||||
|
student@ubuntu:~/[[ROOT]]/test$ cargo run |
||||||
|
1000 |
||||||
|
student@ubuntu:~/[[ROOT]]/test$ |
||||||
|
``` |
||||||
|
|
||||||
|
### Notions |
||||||
|
|
||||||
|
- https://doc.rust-lang.org/stable/rust-by-example/error/option_unwrap/question_mark.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 |
@ -0,0 +1,101 @@ |
|||||||
|
## sales |
||||||
|
|
||||||
|
### Instructions |
||||||
|
|
||||||
|
You will have to create a shopping system, where you will have a : |
||||||
|
|
||||||
|
- Store that will save all the products in it |
||||||
|
- Cart that will have `items`, that the client will buy, and a `receipt` |
||||||
|
|
||||||
|
This store is having a promotion, "Buy three and get one for free" (the free item must be the cheapest). The receipt must not present |
||||||
|
any value as 0, so you will have to apply the promotion to all items instead. |
||||||
|
|
||||||
|
### Expected Function |
||||||
|
|
||||||
|
```rust |
||||||
|
|
||||||
|
#[derive(Debug, Clone)] |
||||||
|
pub struct Store { |
||||||
|
pub products: Vec<(String, f32)>, |
||||||
|
} |
||||||
|
impl Store { |
||||||
|
pub fn new(products: Vec<(String, f32)>) -> Store { |
||||||
|
Store { products } |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[derive(Debug, Clone)] |
||||||
|
pub struct Cart { |
||||||
|
// expected public fields |
||||||
|
} |
||||||
|
impl Cart { |
||||||
|
pub fn new() -> Cart {} |
||||||
|
pub fn insert_item(&mut self, s: &Store, ele: String) {} |
||||||
|
pub fn get_prices(&self) -> Vec<f32> {} |
||||||
|
pub fn generate_receipt(&mut self) -> Vec<f32> {} |
||||||
|
} |
||||||
|
|
||||||
|
``` |
||||||
|
|
||||||
|
### Example |
||||||
|
|
||||||
|
`[1.23, 3.12, 23.1]` -> receipt will be `[1.17, 2.98, 22.07]` |
||||||
|
|
||||||
|
So `1.17 + 2.98 + 22.07 == 3.12 + 23.1 + 0` |
||||||
|
|
||||||
|
This is a percentage calculation, and it can be applied to a set of three items. |
||||||
|
If the client purchase 9 items it will be applied the promotion, three for free, to all items |
||||||
|
|
||||||
|
|--------------| |---------------| |---------------| |
||||||
|
`[1.23, 23.1, 3.12, 9.75, 1.75, 23.75, 2.75, 1.64, 15.23]` -> receipt will be `[1.16, 1.55, 1.65, 2.6, 2.94, 9.2, 14.38, 21.8, 22.42]` |
||||||
|
|
||||||
|
|--------| |--------| |--------| |
||||||
|
`[3.12, 9.75, 1.75, 23.75, 2.75, 1.64, 15.23]` -> receipt will be `[1.54, 1.65, 2.59, 2.94, 9.18, 14.34, 22.36]` |
||||||
|
|
||||||
|
and so on... (hint: Closures is the way) |
||||||
|
|
||||||
|
You will have to implement for the Cart structure the following function: |
||||||
|
|
||||||
|
- `new`, that will initialize the cart |
||||||
|
- `insert_item`, that will receive a reference to `Store` and a `String`. Just like the name says you will |
||||||
|
have to insert the item to the cart |
||||||
|
- `generate_receipt`, that returns a vector of sorted floats. This function must generate the receipt just |
||||||
|
like the example above, using the promotion. Also saving the result in the filed `receipt`. |
||||||
|
|
||||||
|
### Usage |
||||||
|
|
||||||
|
Here is a program to test your function |
||||||
|
|
||||||
|
```rust |
||||||
|
fn main() { |
||||||
|
let store = Store::new(vec![ |
||||||
|
(String::from("product A"), 1.23), |
||||||
|
(String::from("product B"), 23.1), |
||||||
|
(String::from("product C"), 3.12)]); |
||||||
|
|
||||||
|
println!("{:?}", store); |
||||||
|
|
||||||
|
let mut cart = Cart::new(); |
||||||
|
cart.insert_item(&store, String::from("product A")); |
||||||
|
cart.insert_item(&store, String::from("product B")); |
||||||
|
cart.insert_item(&store, String::from("product C")); |
||||||
|
|
||||||
|
println!("{:?}", cart.generate_receipt()); |
||||||
|
|
||||||
|
println!("{:?}", cart); |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
And its output: |
||||||
|
|
||||||
|
```console |
||||||
|
student@ubuntu:~/[[ROOT]]/test$ cargo run |
||||||
|
Store { products: [("product A", 1.23), ("product B", 23.1), ("product C", 3.12)] } |
||||||
|
[1.17, 2.98, 22.07] |
||||||
|
Cart { items: [("product A", 1.23), ("product B", 23.1), ("product C", 3.12)], receipt: [1.17, 2.98, 22.07] } |
||||||
|
student@ubuntu:~/[[ROOT]]/test$ |
||||||
|
``` |
||||||
|
|
||||||
|
### Notions |
||||||
|
|
||||||
|
- https://doc.rust-lang.org/rust-by-example/fn/closures.html |
@ -0,0 +1,66 @@ |
|||||||
|
## unwrap |
||||||
|
|
||||||
|
### Instructions |
||||||
|
|
||||||
|
It will be given a function called **odd_to_even**, that returns an `Result`. If its an error it will |
||||||
|
return a tuple with a string, indicating the error, and a vector with the elements that justifies the error |
||||||
|
|
||||||
|
The objective is to execute the `odd_to_even` function and handle the error given by it |
||||||
|
|
||||||
|
Create the following functions that receives a vector : |
||||||
|
|
||||||
|
- `expect` that returns the error adding the sting "ERROR " |
||||||
|
- `unwrap_or` that in case of error returns an empty vector |
||||||
|
- `unwrap_err` that returns error if its `Ok` and returns the |
||||||
|
string containing the error in case of `Err` |
||||||
|
- `unwrap` that unwraps the `Result` |
||||||
|
- `unwrap_or_else` that in case of error returns a the vector that justifies the error |
||||||
|
|
||||||
|
### Expected Function |
||||||
|
|
||||||
|
```rust |
||||||
|
pub fn odd_to_even(data: Vec<u32>) -> Result<Vec<u32>, (String, Vec<u32>)> {} |
||||||
|
pub fn expect(v: Vec<u32>) -> Vec<u32> {} |
||||||
|
pub fn unwrap_or(v: Vec<u32>) -> Vec<u32> {} |
||||||
|
pub fn unwrap_err(v: Vec<u32>) -> (String, Vec<u32>) {} |
||||||
|
pub fn unwrap(v: Vec<u32>) -> Vec<u32> {} |
||||||
|
pub fn unwrap_or_else(v: Vec<u32>) -> Vec<u32> {} |
||||||
|
``` |
||||||
|
|
||||||
|
### Usage |
||||||
|
|
||||||
|
Here is a program to test your function |
||||||
|
|
||||||
|
```rust |
||||||
|
fn main() { |
||||||
|
// this will give an expect error |
||||||
|
// println!("{:?}", expect(vec![1, 3, 2, 5])); |
||||||
|
println!("{:?}", unwrap_or(vec![1, 3, 2, 5])); |
||||||
|
println!("{:?}", unwrap_or(vec![1, 3, 5])); |
||||||
|
println!("{:?}", unwrap_err(vec![1, 3, 2, 5])); |
||||||
|
// this will give an error that is unwraped |
||||||
|
// println!("{:?}", unwrap_err(vec![1, 3, 5])); |
||||||
|
println!("{:?}", unwrap(vec![1, 3, 5])); |
||||||
|
// this will give an error |
||||||
|
// println!("{:?}", unwrap(vec![1, 3, 2, 5])); |
||||||
|
println!("{:?}", unwrap_or_else(vec![1, 3, 5])); |
||||||
|
println!("{:?}", unwrap_or_else(vec![3, 2, 6, 5])); |
||||||
|
} |
||||||
|
``` |
||||||
|
|
||||||
|
And its output: |
||||||
|
|
||||||
|
```console |
||||||
|
student@ubuntu:~/[[ROOT]]/test$ cargo run |
||||||
|
[] |
||||||
|
[2, 4, 6] |
||||||
|
("There is a even value in the vector!", [2]) |
||||||
|
[2, 4, 6] |
||||||
|
[2, 4, 6] |
||||||
|
[2, 6] |
||||||
|
student@ubuntu:~/[[ROOT]]/test$ |
||||||
|
``` |
||||||
|
|
||||||
|
### Notions |
||||||
|
|
||||||
|
- https://doc.rust-lang.org/std/?search=unwrap |
Loading…
Reference in new issue