Browse Source

Merge pull request #692 from 01-edu/adding-piscine-rust

rust piscine: readme and tests
pull/694/head
augusto-mantilla 4 years ago committed by GitHub
parent
commit
0de911d150
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 12
      rust/tests/banner_test/Cargo.lock
  2. 10
      rust/tests/banner_test/Cargo.toml
  3. 88
      rust/tests/banner_test/src/main.rs
  4. 12
      rust/tests/borrow_box_test/Cargo.lock
  5. 10
      rust/tests/borrow_box_test/Cargo.toml
  6. 91
      rust/tests/borrow_box_test/src/main.rs
  7. 12
      rust/tests/box_it_test/Cargo.lock
  8. 10
      rust/tests/box_it_test/Cargo.toml
  9. 56
      rust/tests/box_it_test/src/main.rs
  10. 12
      rust/tests/box_recursion_test/Cargo.lock
  11. 10
      rust/tests/box_recursion_test/Cargo.toml
  12. 98
      rust/tests/box_recursion_test/src/main.rs
  13. 96
      rust/tests/boxing_todo_test/Cargo.lock
  14. 12
      rust/tests/boxing_todo_test/Cargo.toml
  15. 99
      rust/tests/boxing_todo_test/src/main.rs
  16. 12
      rust/tests/cipher_test/Cargo.lock
  17. 10
      rust/tests/cipher_test/Cargo.toml
  18. 24
      rust/tests/cipher_test/src/main.rs
  19. 12
      rust/tests/drop_the_thread_test/Cargo.lock
  20. 10
      rust/tests/drop_the_thread_test/Cargo.toml
  21. 87
      rust/tests/drop_the_thread_test/src/main.rs
  22. 98
      rust/tests/error_type_test/Cargo.lock
  23. 10
      rust/tests/error_type_test/Cargo.toml
  24. 136
      rust/tests/error_type_test/src/main.rs
  25. 12
      rust/tests/handling_test/Cargo.lock
  26. 10
      rust/tests/handling_test/Cargo.toml
  27. 1
      rust/tests/handling_test/a.txt
  28. 63
      rust/tests/handling_test/src/main.rs
  29. 12
      rust/tests/how_many_references_test/Cargo.lock
  30. 10
      rust/tests/how_many_references_test/Cargo.toml
  31. 103
      rust/tests/how_many_references_test/src/main.rs
  32. 12
      rust/tests/panic_test/Cargo.lock
  33. 10
      rust/tests/panic_test/Cargo.toml
  34. 29
      rust/tests/panic_test/src/main.rs
  35. 99
      rust/tests/profanity_filter_test/Cargo.lock
  36. 11
      rust/tests/profanity_filter_test/Cargo.toml
  37. 77
      rust/tests/profanity_filter_test/src/main.rs
  38. 12
      rust/tests/project_motion_test/Cargo.lock
  39. 10
      rust/tests/project_motion_test/Cargo.toml
  40. 56
      rust/tests/project_motion_test/src/main.rs
  41. 12
      rust/tests/question_mark_test/Cargo.lock
  42. 10
      rust/tests/question_mark_test/Cargo.toml
  43. 47
      rust/tests/question_mark_test/src/main.rs
  44. 12
      rust/tests/ref_cell_test/Cargo.lock
  45. 10
      rust/tests/ref_cell_test/Cargo.toml
  46. 158
      rust/tests/ref_cell_test/src/main.rs
  47. 12
      rust/tests/sales_test/Cargo.lock
  48. 10
      rust/tests/sales_test/Cargo.toml
  49. 133
      rust/tests/sales_test/src/main.rs
  50. 12
      rust/tests/unwrap_and_expect_test/Cargo.lock
  51. 10
      rust/tests/unwrap_and_expect_test/Cargo.toml
  52. 49
      rust/tests/unwrap_and_expect_test/src/main.rs
  53. 110
      subjects/banner/README.md
  54. 83
      subjects/borrow_box/README.md
  55. 53
      subjects/box_it/README.md
  56. 79
      subjects/box_recursion/README.md
  57. 165
      subjects/boxing_todo/README.md
  58. 1
      subjects/boxing_todo/malformed_object.json
  59. 7
      subjects/boxing_todo/todo.json
  60. 4
      subjects/boxing_todo/todo_empty.json
  61. 47
      subjects/cipher/README.md
  62. 109
      subjects/drop_the_thread/README.md
  63. 124
      subjects/error_type/README.md
  64. 48
      subjects/handling/README.md
  65. 78
      subjects/how_many_references/README.md
  66. 34
      subjects/panic/README.md
  67. 81
      subjects/profanity_filter/README.md
  68. 70
      subjects/project_motion/README.md
  69. 70
      subjects/question_mark/README.md
  70. 112
      subjects/ref_cell/README.md
  71. 101
      subjects/sales/README.md
  72. 66
      subjects/unwrap_or_expect/README.md

12
rust/tests/banner_test/Cargo.lock diff.generated

@ -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",
]

10
rust/tests/banner_test/Cargo.toml

@ -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"}

88
rust/tests/banner_test/src/main.rs

@ -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"
);
}
}

12
rust/tests/borrow_box_test/Cargo.lock diff.generated

@ -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",
]

10
rust/tests/borrow_box_test/Cargo.toml

@ -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"}

91
rust/tests/borrow_box_test/src/main.rs

@ -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);
// }
// }
}

12
rust/tests/box_it_test/Cargo.lock diff.generated

@ -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",
]

10
rust/tests/box_it_test/Cargo.toml

@ -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"}

56
rust/tests/box_it_test/src/main.rs

@ -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);
}
}

12
rust/tests/box_recursion_test/Cargo.lock diff.generated

@ -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",
]

10
rust/tests/box_recursion_test/Cargo.toml

@ -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"}

98
rust/tests/box_recursion_test/src/main.rs

@ -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"))
);
}
}

96
rust/tests/boxing_todo_test/Cargo.lock diff.generated

@ -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"

12
rust/tests/boxing_todo_test/Cargo.toml

@ -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"

99
rust/tests/boxing_todo_test/src/main.rs

@ -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));
}
}

12
rust/tests/cipher_test/Cargo.lock diff.generated

@ -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",
]

10
rust/tests/cipher_test/Cargo.toml

@ -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"}

24
rust/tests/cipher_test/src/main.rs

@ -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") })));
}
}

12
rust/tests/drop_the_thread_test/Cargo.lock diff.generated

@ -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",
]

10
rust/tests/drop_the_thread_test/Cargo.toml

@ -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"}

87
rust/tests/drop_the_thread_test/src/main.rs

@ -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();
}
}

98
rust/tests/error_type_test/Cargo.lock diff.generated

@ -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"

10
rust/tests/error_type_test/Cargo.toml

@ -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"}

136
rust/tests/error_type_test/src/main.rs

@ -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);
}
}
}

12
rust/tests/handling_test/Cargo.lock diff.generated

@ -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",
]

10
rust/tests/handling_test/Cargo.toml

@ -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"}

1
rust/tests/handling_test/a.txt

@ -0,0 +1 @@
content to be written

63
rust/tests/handling_test/src/main.rs

@ -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());
}
}

12
rust/tests/how_many_references_test/Cargo.lock diff.generated

@ -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",
]

10
rust/tests/how_many_references_test/Cargo.toml

@ -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"}

103
rust/tests/how_many_references_test/src/main.rs

@ -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);
}
}

12
rust/tests/panic_test/Cargo.lock diff.generated

@ -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",
]

10
rust/tests/panic_test/Cargo.toml

@ -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"}

29
rust/tests/panic_test/src/main.rs

@ -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();
}
}

99
rust/tests/profanity_filter_test/Cargo.lock diff.generated

@ -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"

11
rust/tests/profanity_filter_test/Cargo.toml

@ -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"

77
rust/tests/profanity_filter_test/src/main.rs

@ -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);
}
}
}

12
rust/tests/project_motion_test/Cargo.lock diff.generated

@ -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",
]

10
rust/tests/project_motion_test/Cargo.toml

@ -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"}

56
rust/tests/project_motion_test/src/main.rs

@ -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);
}
}

12
rust/tests/question_mark_test/Cargo.lock diff.generated

@ -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",
]

10
rust/tests/question_mark_test/Cargo.toml

@ -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"}

47
rust/tests/question_mark_test/src/main.rs

@ -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));
}
}

12
rust/tests/ref_cell_test/Cargo.lock diff.generated

@ -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",
]

10
rust/tests/ref_cell_test/Cargo.toml

@ -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"}

158
rust/tests/ref_cell_test/src/main.rs

@ -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]);
}
}
}

12
rust/tests/sales_test/Cargo.lock diff.generated

@ -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",
]

10
rust/tests/sales_test/Cargo.toml

@ -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"}

133
rust/tests/sales_test/src/main.rs

@ -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);
}
}
}

12
rust/tests/unwrap_and_expect_test/Cargo.lock diff.generated

@ -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",
]

10
rust/tests/unwrap_and_expect_test/Cargo.toml

@ -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"}

49
rust/tests/unwrap_and_expect_test/src/main.rs

@ -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]);
}
}

110
subjects/banner/README.md

@ -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

83
subjects/borrow_box/README.md

@ -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

53
subjects/box_it/README.md

@ -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

79
subjects/box_recursion/README.md

@ -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

165
subjects/boxing_todo/README.md

@ -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

1
subjects/boxing_todo/malformed_object.json

@ -0,0 +1 @@
{}

7
subjects/boxing_todo/todo.json

@ -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 }
]
}

4
subjects/boxing_todo/todo_empty.json

@ -0,0 +1,4 @@
{
"title" : "TODO LIST FOR PISCINE RUST",
"tasks": []
}

47
subjects/cipher/README.md

@ -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$
```

109
subjects/drop_the_thread/README.md

@ -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

124
subjects/error_type/README.md

@ -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

48
subjects/handling/README.md

@ -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

78
subjects/how_many_references/README.md

@ -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

34
subjects/panic/README.md

@ -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$
```

81
subjects/profanity_filter/README.md

@ -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

70
subjects/project_motion/README.md

@ -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

70
subjects/question_mark/README.md

@ -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

112
subjects/ref_cell/README.md

@ -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

101
subjects/sales/README.md

@ -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

66
subjects/unwrap_or_expect/README.md

@ -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…
Cancel
Save