diff --git a/subjects/banner/README.md b/subjects/banner/README.md index 424c0b98f7..b27a9bf002 100644 --- a/subjects/banner/README.md +++ b/subjects/banner/README.md @@ -2,71 +2,73 @@ ### Instructions -"`Result` is a better version of the `Option` type that describes a possible `error` instead of possible `absence`". +"`Result` is a version of the `Option` type that describes a possible `Err` instead of `None`". Create a structure called `Flag` which has the following elements: -- `short_hand`: `String` -- `long_hand`: `String` -- `desc`: `String` +- `short_hand: String` +- `long_hand: String` +- `desc: String` -This structure must have a **function** called `opt_flag` which initializes the structure. +This structure must have an associated **function** called `opt_flag` which initializes the structure. This **function** receives two string references and returns a structure `Flag`. Here is an example of its usage: ```rust - let d = Flag::opt_flag("diff", "gives the difference between two numbers"); +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" +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" ``` -A second structure named `FlagsHandler` will be given which just has one element: `flags: HashMap<(String, String), Callback>`. You'll need to implement the following **associated functions**" (methods) associated with `FlagsHandler` are for you to complete:" +An associated **type** called `Callback` will also be provided. It should represent a function pointer which is going to be used in the structure and functions below. This function will represent the callback for the flag associated to it. -- `add_flag`, which adds the flag and callback function to the HashMap. -- `exec_func`, which executes the function using the flag provided and returns the result. The result will be either a string with the value from the callback or an error. +A second structure named `FlagsHandler` will be given which just has one element: `flags: HashMap<(String, String), Callback>`. You'll also need to implement the following associated **functions**: -A `type` called `Callback` will also be provided. It is a function which is going to be used in the structure and functions above. This function will be the callback for the flag associated to it. +- `add_flag`, which adds the flag and callback function to the HashMap. +- `exec_func`, which executes the function using the flag provided and returns the result. The callback should be executed with the first two arguments of the supplied `argv` argument. Return either the successful result from the callback or the error stringified. You will have to create the following callback functions: -- `div`: which converts the reference strings to `f32`s and returns the `Result`, as the division of the `f32`s or the standard (std) error: `ParseFloatError`. -- `rem`: which converts the reference strings to `f32`s and returns the `Result`, as the remainder of the division of the `f32`s or the standard (std) error `ParseFloatError`. +- `div`: which converts the reference strings to `f64`s and returns the `Result`, as the division of these floats or the error `ParseFloatError`. +- `rem`: which converts the reference strings to `f64`s and returns the `Result`, as the remainder of the division of these floats or the error `ParseFloatError`. ### Expected Function ```rust -use std::collections::HashMap; +use std::{collections::HashMap, num::ParseFloatError}; pub struct Flag { // expected public fields } -impl Flag { - pub fn opt_flag(l_h: &str, d: &str) -> Flag { - +impl<'a> Flag<'a> { + pub fn opt_flag(name: &'a str, d: &'a str) -> Self { + todo!() } } pub type Callback = fn(&str, &str) -> Result; pub struct FlagsHandler { - pub flags: HashMap<(String, String), Callback>, + pub flags: HashMap, } impl FlagsHandler { - pub fn add_flag(&mut self, flag: (String, String), func: Callback) { - + pub fn add_flag(&mut self, flag: Flag, func: Callback) { + todo!() } - pub fn exec_func(&mut self, flag: (String, String), argv: &[&str]) -> String { + pub fn exec_func(&self, input: &str, argv: &[&str]) -> Result { + todo!() } } pub fn div(a: &str, b: &str) -> Result { - + todo!() } -pub fn rem(a: &str, b: &str) -> Result { +pub fn rem(a: &str, b: &str) -> Result { + todo!() } ``` @@ -88,16 +90,16 @@ fn main() { "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); + handler.add_flag(d, div); + handler.add_flag(r, rem); - println!("{:?}", handler.exec_func(("-d".to_string(), "--division".to_string()), &["1.0", "2.0"])); + println!("{:?}", handler.exec_func("-d", &["1.0", "2.0"])); - println!("{:?}",handler.exec_func(("-r".to_string(), "--remainder".to_string()), &["2.0", "2.0"])); + println!("{:?}", handler.exec_func("-r", &["2.0", "2.0"])); - println!("{:?}",handler.exec_func(("-d".to_string(), "--division".to_string()), &["a", "2.0"])); + println!("{:?}", handler.exec_func("--division", &["a", "2.0"])); - println!("{:?}",handler.exec_func(("-r".to_string(), "--remainder".to_string()), &["2.0", "fd"])); + println!("{:?}", handler.exec_func("--remainder", &["2.0", "fd"])); } ``` @@ -105,10 +107,10 @@ And its output: ```console $ cargo run -"0.5" -"0" -"invalid float literal" -"invalid float literal" +Ok("0.5") +Ok("0") +Err("invalid float literal") +Err("invalid float literal") $ ``` diff --git a/subjects/boxing_todo/README.md b/subjects/boxing_todo/README.md index acd2fb6f4d..53cf6599dc 100644 --- a/subjects/boxing_todo/README.md +++ b/subjects/boxing_todo/README.md @@ -16,31 +16,26 @@ Organization of the JSON file: } ``` -#### err.rs +Create a file named `err.rs` which handles the boxing of errors. -Create a module in a file named **err.rs** which handles the boxing of errors. +This file must: -This module must implement an `enum` called `ParseErr` which will take care of the parsing errors. It must have the following elements: +- Implement an `enum` called `ParseErr` which will represent parsing errors. It must have the following variants: + - `Empty` + - `Malformed`: which has a dynamic boxed error as element +- Implement a `struct` called `ReadErr` which will represent reading errors with a single field called `child_err` of type `Box`. -- `Empty` -- `Malformed`: which has a dynamic boxed error as element +These structures must implement the `Display` trait. They should write `"Failed to parse todo file"` and `"Failed to read todo file"`, depending on the respective error case. -A structure called `ReadErr` which will take care of the reading errors, with an element called `child_err` of type `Box`. +These structures should also naturally implement the `Error` trait. We will override its method `source` to manipulate the error source output. -For each data structure, you will have to implement a function called `fmt` for the `Display` trait. It should write the message **"Fail to parse todo"** in the case of any parsing error. Otherwise, it should write the message **"Fail to read todo file"**. +- For the `ReadErr` structure, `child_err` should be returned, wrapped in `Some()`. +- For the `ParseErr` structure, `None` should be returned if we have no tasks, otherwise, with a parsing malformation, we should just return `self` wrapped in `Some()`. -For the `Error` trait, the following functions (methods) have to be implemented: +In the `lib.rs` file you will have to declare and implement a `TodoList` and a `Task` structure. -- `source` which returns an `Option` with the error: - - - For the `ReadErr`, it must return the option with the error. - - For the `ParseErr`, it will return an option which is `None` if the tasks are **empty**, and the error if the parsing is **malformed**. - -#### lib.rs - -In the **lib** file you will have to implement a **function** called `get_todo` which receives a string and returns a `Result` which 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 it returns the error. +- The `Task` structure serves merely to represent and encapsulate the fields of the tasks in the JSON file. +- The `TodoList` structure will have two fields called `title` and `tasks` as shown below, and an associated **function** called `get_todo` which receives a `&str` and returns a `Result` which will represent either the deserialized and parsed content in a `Self` instance on success, or any error type on failure. ### Dependencies @@ -48,56 +43,38 @@ Basically it must parse and read the JSON file and return the `TodoList` if ever ### Expected Functions -For **err.rs** +For `err.rs` ```rust -use std::fmt; -use std::fmt::Display; -use std::error::Error; +use std::{error::Error, fmt::Display}; pub enum ParseErr { // expected public fields } -// required by error trait impl Display for ParseErr { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +} - } +impl Error for ParseErr { } 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 ParseErr { - fn source(&self) -> Option<&(dyn Error + 'static)> { - - } } impl Error for ReadErr { - fn source(&self) -> Option<&(dyn Error + 'static)> { - - } } ``` -for **lib.rs** +For `lib.rs` ```rust mod err; -use err::{ ParseErr, ReadErr }; -pub use json::{parse, stringify}; -pub use std::error::Error; +use std::error::Error; #[derive(Debug, Eq, PartialEq)] pub struct Task { @@ -114,7 +91,7 @@ pub struct TodoList { impl TodoList { pub fn get_todo(path: &str) -> Result> { - + todo!() } } ``` @@ -126,27 +103,49 @@ Here is a program to test your function. You can create some _todos_ yourself, inside the boxing_todo file in order to test it. The JSON structure can be found above. ```rust +use std::{fs::File, io::Write}; + use boxing_todo::TodoList; + fn main() { - let todos = TodoList::get_todo("todo.json"); - match todos { - Ok(list) => println!("{:?}", list), - Err(e) => { - println!("{}{:?}", e.to_string(), e.source()); - } - } - let todos = TodoList::get_todo("todo_empty.json"); - match todos { - Ok(list) => println!("{:?}", list), - Err(e) => { - println!("{}{:?}", e.to_string(), e.source()); - } - } - let todos = TodoList::get_todo("malformed_object.json"); - match todos { - Ok(list) => println!("{:?}", list), - Err(e) => { - println!("{}{:?}", e.to_string(), e.source()); + let files = [ + ( + "todo.json", + r#"{ + "title" : "TODO LIST FOR PISCINE RUST", + "tasks": [ + { "id": 0, "description": "do this", "level": 0 }, + { "id": 1, "description": "do that", "level": 5 } + ] + }"#, + ), + ( + "todo_empty.json", + r#"{ + "title" : "TODO LIST FOR PISCINE RUST", + "tasks": [] + }"#, + ), + ( + "malformed_object.json", + r#"{ + "something": , + }"#, + ), + ]; + + for (name, content) in files { + File::create(name) + .unwrap() + .write(content.as_bytes()) + .unwrap(); + + let todos = TodoList::get_todo(name); + match todos { + Ok(list) => println!("{:?}", list), + Err(e) => { + println!("{}: {:?}", e.to_string(), e.source()); + } } } } @@ -157,8 +156,8 @@ And its output: ```console $ 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 }] } -Fail to parse todoNone -Fail to parse todo Some(Malformed(UnexpectedCharacter { ch: ',', line: 2, column: 18 })) +Failed to parse todo file: None +Failed to parse todo file: Some(Malformed(UnexpectedCharacter { ch: ',', line: 2, column: 18 })) $ ``` diff --git a/subjects/cipher/README.md b/subjects/cipher/README.md index f24277ae80..510709adbd 100644 --- a/subjects/cipher/README.md +++ b/subjects/cipher/README.md @@ -4,25 +4,20 @@ The Atbash cipher is an encryption method in which each letter of a word is replaced by its mirror letter in the alphabet. -Your objective is to create a **function** named `cipher` which must return a `Result` wrapped in an `Option`. The `Result` should contain either a `boolean` or an `Error` based on the `CipherError` structure. This structure should be the error type for the **function** `cipher`. +Your objective is to create a **function** named `cipher` which must return a `Result`. -`cipher` should compare the original `String` with the ciphered `String`. It should return `true` if the cipher is correct. If the cipher is incorrect it should return the error type `CipherError` with a `boolean` and the expected atbash cipher `String`. +`cipher` should compare the original string with a ciphered string. It should return an empty value (`()`) if the cipher is correct. If the cipher is incorrect it should return the error type `CipherError` with the expected cipher (`expected: String`). ### Expected Function and structure ```rust - -#[derive(Debug, Clone, Eq, PartialEq)] +#[derive(Debug, 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> { +pub fn cipher(original: &str, ciphered: &str) -> Result<(), CipherError> { + todo!() } ``` @@ -36,7 +31,6 @@ use cipher::*; fn main() { println!("{:?}", cipher("1Hello 2world!", "1Svool 2dliow!")); println!("{:?}", cipher("1Hello 2world!", "svool")); - println!("{:?}", cipher("", "svool")); } ``` @@ -44,8 +38,7 @@ And its output: ```console $ cargo run -Some(Ok(true)) -Some(Err(CipherError { validation: false, expected: "1Svool 2dliow!" })) -None +Ok(()) +Err(CipherError { expected: "1Svool 2dliow!" }) $ ``` diff --git a/subjects/error_types/README.md b/subjects/error_types/README.md index d343c9b5f8..533ad6ab26 100644 --- a/subjects/error_types/README.md +++ b/subjects/error_types/README.md @@ -2,53 +2,46 @@ ### Instructions -For this exercise, you will have to implement an **error type** for a form validator. This must validate the password and the first name. +For this exercise, you will have to implement an **error type** for a form validator. We will validate the password and the first name. -The first name must not be empty and the password must have **at least 8 characters**, and a combination of **alphabetic**, **numeric** and **none-alphanumeric** (`<`, `&`, `/` ...). +The first name must not be empty and the password must have **at least 8 characters**, and a combination of ASCII **alphanumeric characters** and **symbols** (`<`, `&`, `/` ...). Examples: + - `"asDd123=%"`: **good**. - `"asgfD"`: **error** as it only contains alphabetic characters. -- `"asdsdf2"`: **error** as it is missing none-alphanumeric characters. +- `"asdsdf2"`: **error** as it is missing symbols. - `"sad\_#$"`: **error** as it is missing numeric characters. Create a structure named `Form` that will have the following fields: -- `first_name`: `String` -- `last_name`: `String` -- `birth`: `NaiveDate` that will convert a string `"2015-09-05"` to a date of that format. -- `birth_location`: `String` + +- `name`: `String` - `password`: `String` -You must implement the **associated functions** `new` and -`validate` that will validate the form. +You must implement the **associated functions** `new` and `validate` that will validate the form. For the error type you must create a `struct` named `FormError`. It must have the fields: -- `form_values`: this will be a tuple of strings representing the invalid input. For example: `("password", "asdaSD\_")` or `("first_name", "someone")` - -- `date`: that will have the date that the error occurred in the format `"2020-12-14 09:33:41"` -- `err`: the error description: - - `"No user name"` - - `"At least 8 characters"` - - `"Combination of different ASCII character types (numbers, letters and none alphanumeric characters)"` - - -### Dependencies - -chrono = "0.4" +- `form_values`: represents the invalid input in a key-value pair. For example: `("password", "asdaSD\_")` or `("first_name", "someone")` +- `date`: represents when the error occurred in the format `"YYYY-MM-DD HH:MM:SS"` +- `err`: the error description, which should be either of the following values: + - `"Username is empty"` + - `"Password should be at least 8 characters long"` + - `"Password should be a combination of ASCII numbers, letters and symbols"` ### Expected Function ```rust -pub use chrono::{Utc, NaiveDate}; - // this will be the structure that wil handle the errors #[derive(Debug, Eq, PartialEq)] pub struct FormError { // expected public fields } + impl FormError { - pub fn new(field_name: String, field_value: String, err: String) -> FormError {} + pub fn new(field_name: &'static str, field_value: String, err: &'static str) -> Self { + todo!() + } } #[derive(Debug, Eq, PartialEq)] @@ -57,15 +50,9 @@ pub struct Form { } impl Form { - pub fn new( - first_name: String, - last_name: String, - birth: NaiveDate, - birth_location: String, - password: String, - ) -> Form {} - - pub fn validate(&self) -> Result, FormError> {} + pub fn validate(&self) -> Result<(), FormError> { + todo!() + } } ``` @@ -77,29 +64,26 @@ Here is a program to test your function: use error_types::*; fn main() { - let mut form_output = Form::new( - String::from("Lee"), - String::from("Silva"), - create_date("2015-09-05"), - String::from("Africa"), - String::from("qwqwsa1dty_"), - ); + let mut form_output = Form { + name: "Lee".to_owned(), + password: "qwqwsa1dty_".to_owned(), + }; println!("{:?}", form_output); - println!("{:?}", form_output.validate().unwrap()); + println!("{:?}", form_output.validate()); - form_output.first_name = String::from(""); - println!("{:?}", form_output.validate().unwrap_err()); + form_output.name = "".to_owned(); + println!("{:?}", form_output.validate()); - form_output.first_name = String::from("as"); - form_output.password = String::from("dty_1"); - println!("{:?}", form_output.validate().unwrap_err()); + form_output.name = "as".to_owned(); + form_output.password = "dty_1".to_owned(); + println!("{:?}", form_output.validate()); - form_output.password = String::from("asdasASd(_"); - println!("{:?}", form_output.validate().unwrap_err()); + form_output.password = "asdasASd(_".to_owned(); + println!("{:?}", form_output.validate()); - form_output.password = String::from("asdasASd123SA"); - println!("{:?}", form_output.validate().unwrap_err()); + form_output.password = "asdasASd123SA".to_owned(); + println!("{:?}", form_output.validate()); } ``` @@ -107,16 +91,16 @@ And its output: ```console $ cargo run -Form { first_name: "Lee", last_name: "Silva", birth: 2015-09-05, birth_location: "Africa", password: "qwqwsa1dty_" } -["Valid first name", "Valid password"] -FormError { form_values: ("first_name", ""), date: "2022-10-17 12:09:25", err: "No user name" } -FormError { form_values: ("password", "dty_1"), date: "2022-10-17 12:09:25", err: "At least 8 characters" } -FormError { form_values: ("password", "asdasASd(_"), date: "2022-10-17 12:09:25", err: "Combination of different ASCII character types (numbers, letters and none alphanumeric characters)" } -FormError { form_values: ("password", "asdasASd123SA"), date: "2022-10-17 12:09:25", err: "Combination of different ASCII character types (numbers, letters and none alphanumeric characters)" } +Form { name: "Lee", password: "qwqwsa1dty_" } +Ok(()) +Err(FormError { form_values: ("name", ""), date: "2022-10-17 12:09:25", err: "Username is empty" }) +Err(FormError { form_values: ("password", "dty_1"), date: "2022-10-17 12:09:25", err: "Password should be at least 8 characters long" }) +Err(FormError { form_values: ("password", "asdasASd(_"), date: "2022-10-17 12:09:25", err: "Password should be a combination of ASCII numbers, letters and symbols" }) +Err(FormError { form_values: ("password", "asdasASd123SA"), date: "2022-10-17 12:09:25", err: "Password should be a combination of ASCII numbers, letters and symbols" }) $ ``` ### Notions - [Error types](https://doc.rust-lang.org/rust-by-example/error/multiple_error_types/define_error_type.html) -- [Struct NaiveDate](https://docs.rs/chrono/0.4.19/chrono/naive/struct.NaiveDate.html) +- [chrono](https://docs.rs/chrono/latest/chrono/index.html) diff --git a/subjects/handling/README.md b/subjects/handling/README.md index 48edbddb1f..507e23a58c 100644 --- a/subjects/handling/README.md +++ b/subjects/handling/README.md @@ -2,18 +2,22 @@ ### Instructions -Create a **function** named `open_or_create` which has two arguments: +Create a **function** `open_or_create` with two arguments: -- `file : &str`: which represents a file path. -- `content: &str` which will be the content to be written to the file. +- `file`, which represents a file path. +- `content`, which represents the content to be written to the file. -This function should try to open a file. If it does not exist, the file should be created. -In case something goes wrong, it should panic, with the error. +This function should try to open the file. If it does not exist, the file should be created. +The content should be appended to the file. This means it shouldn't replace whatever content is inside, but append to it. +Should anything go wrong, the function should panic. ### Expected Function ```rust -pub fn open_or_create(file: &str, content: &str) { +use std::path::Path; + +pub fn open_or_create>(path: &P, content: &str) { + todo!() } ``` @@ -22,20 +26,15 @@ pub fn open_or_create(file: &str, content: &str) { Here is a program to test your function ```rust -use std::fs::File; -use std::io::Read; -use handling::*; +use std::fs; 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(); + handling::open_or_create(&path, "content to be written"); - let mut s = String::new(); - file.read_to_string(&mut s).unwrap(); - println!("{}", s); + let contents = fs::read_to_string(path).unwrap(); + println!("{}", contents); } ``` @@ -49,6 +48,6 @@ $ ### Notions -- [Error kind](https://doc.rust-lang.org/std/io/enum.ErrorKind.html) -- [struct file](https://doc.rust-lang.org/std/fs/struct.File.html) -- [OPenOptions](https://doc.rust-lang.org/std/fs/struct.OpenOptions.html) +- [ErrorKind](https://doc.rust-lang.org/std/io/enum.ErrorKind.html) +- [File](https://doc.rust-lang.org/std/fs/struct.File.html) +- [OpenOptions](https://doc.rust-lang.org/std/fs/struct.OpenOptions.html) diff --git a/subjects/panic/README.md b/subjects/panic/README.md index 0cfa41017e..984c6acd6f 100644 --- a/subjects/panic/README.md +++ b/subjects/panic/README.md @@ -8,7 +8,7 @@ Create a **function** that tries to open a file and panics if the file does not ```rust pub fn open_file(s: &str) -> File { - + todo!() } ``` @@ -17,21 +17,19 @@ pub fn open_file(s: &str) -> File { Here is a program to test your function: ```rust -use std::fs::File; -use std::fs; use panic::*; +use std::fs::{self, File}; fn main() { let filename = "created.txt"; File::create(filename).unwrap(); - let a = open_file(filename); - println!("{:?}", a); - + println!("{:?}", open_file(filename)); + fs::remove_file(filename).unwrap(); - //It must panic - let b = open_file(filename); + // this should panic! + open_file(filename); } ``` @@ -39,7 +37,10 @@ And its output: ```console $ cargo run -File { fd: 3, path: "panic/a.txt", read: true, write: false } -thread 'main' panicked at 'File not found' +File { fd: 3, path: ".../src/created.txt", read: true, write: false } + +thread 'main' panicked at src/main.rs: +called `Result::unwrap()` on an `Err` value: Os { code: 2, kind: NotFound, message: "No such file or directory" } +... $ ``` diff --git a/subjects/profanity_filter/README.md b/subjects/profanity_filter/README.md index c4d286e980..d30f3acf9e 100644 --- a/subjects/profanity_filter/README.md +++ b/subjects/profanity_filter/README.md @@ -7,6 +7,7 @@ Sometimes it is more desirable to catch the failure of some parts of a program i 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`, which contains: + - elements: - `content`: `String` - `user`: `String` @@ -15,27 +16,15 @@ You will have to create a structure called `Message`, which contains: - `send_ms`: which only has its implementation type (**self**) as argument. It should return `None` if the content of the message is either **empty** or contains the word **stupid**. It should return the content of the message otherwise. You will also need to create a **function** named `check_ms` which accepts a reference to a `Message`, and returns a tuple. This function will invoke the `send_ms` function. + - If `send_ms` returns `None`, then your function should return `false` and `"ERROR: illegal"`. - Else, your function should return `true` and the contents of the message sent. ##### Expected Function ```rust -pub struct Message { - -} - -impl Message { - pub fn new(ms: String, u: String) -> Message { - - } - pub fn send_ms(&self) -> Option<&str> { - - } -} - -pub fn check_ms(ms: &Message) -> (bool, &str) { - +pub fn check_ms(message: &str) -> Result<&str, &str> { + todo!() } ``` @@ -47,17 +36,9 @@ Here is a program to test your function use profanity_filter::*; fn main() { - let m0 = Message::new("hello there".to_string(), "toby".to_string()); - println!("{:?}", check_ms(&m0)); - - let m1 = Message::new("".to_string(), "toby".to_string()); - println!("{:?}", check_ms(&m1)); - - let m2 = Message::new("you are stupid".to_string(), "toby".to_string()); - println!("{:?}", check_ms(&m2)); - - let m3 = Message::new("stupid".to_string(), "toby".to_string()); - println!("{:?}", check_ms(&m3)); + ["hello there", "", "you are stupid", "stupid"] + .into_iter() + .for_each(|m| println!("{:?}", profanity_filter::check_ms(m))); } ``` @@ -65,13 +46,13 @@ And its output: ```console $ cargo run -(true, "hello there") -(false, "ERROR: illegal") -(false, "ERROR: illegal") -(false, "ERROR: illegal") +Ok("hello there") +Err("ERROR: illegal") +Err("ERROR: illegal") +Err("ERROR: illegal") $ ``` -# Notions +### Notions - [Enum Definition](https://doc.rust-lang.org/stable/book/ch06-01-defining-an-enum.html?highlight=option#the-option-enum-and-its-advantages-over-null-values) diff --git a/subjects/question_mark/README.md b/subjects/question_mark/README.md index 9640ddc552..2ab7ea23c5 100644 --- a/subjects/question_mark/README.md +++ b/subjects/question_mark/README.md @@ -2,14 +2,14 @@ ### Instructions -Create the following structures. Each has one element: +Create the following structures. Each has one field: -- `One`: `first_layer` as type `Option`. -- `Two`: `second_layer` as type `Option` -- `Three`: `third_layer` as type `Option` -- `Four`: `fourth_layer` as type `Option`. +- `One`: `first_layer` with type `Option`. +- `Two`: `second_layer` with type `Option` +- `Three`: `third_layer` with type `Option` +- `Four`: `fourth_layer` with type `Option`. -Beside the structures, you must create a **function** named `get_fourth_layer`, and associate it to the `One` structure. This **function** should return the `Option` value in the `Four` structure. +You must also create a **function** associated to the structure `One` called `get_fourth_layer`, which should return the `fourth_layer` value in the `Four` structure. ### Expected Function and structures @@ -28,7 +28,9 @@ pub struct Four { } impl One { - pub fn get_fourth_layer(&self) -> Option {} + pub fn get_fourth_layer(self) -> Option { + todo!() + } } ``` @@ -41,7 +43,7 @@ use question_mark::*; fn main() { let a = One { - first_layer : Some(Two { + first_layer: Some(Two { second_layer: Some(Three { third_layer: Some(Four { fourth_layer: Some(1000) @@ -50,11 +52,7 @@ fn main() { }) }; - // output: 1000 - println!("{:?}", match a.get_fourth_layer() { - Some(e) => e, - None => 0 - }) + println!("{:?}", a.get_fourth_layer()); } ``` @@ -62,7 +60,7 @@ And its output: ```console $ cargo run -1000 +Some(1000) $ ``` diff --git a/subjects/unwrap_or_expect/README.md b/subjects/unwrap_or_expect/README.md index 58068ca252..eeead1bf99 100644 --- a/subjects/unwrap_or_expect/README.md +++ b/subjects/unwrap_or_expect/README.md @@ -2,32 +2,32 @@ ### Instructions -Create a **function** named **fetch_data** which has two arguments: -- `server`: Which is a `Result` having the server url or an error message inside. -- `security_level`: Which is an `enum` defining the behavior of the function in case of errors. +Create a **function** named `fetch_data` with two arguments: -The `security_level` will work as follow: -- `Unknown`: The function panics without printing any custom message. -- `High`: The function panics and prints the error message `ERROR: program stops`. -- `Medium`: The function returns the string `WARNING: check the server`. -- `Low`: The function returns the string `Not found: [SERVER_URL]`. -- `BlockServer`: The function will panic only if the `Result` value is `Ok` and the error message will be the string contained in `Ok`. +- `server`: A `Result`, with either a server URL or an error message inside, respectively. +- `security_level`: An `enum` instance representing the desired behavior of the function in case of errors. -To return from **fetch_data** you must use `expect`, `unwrap_or`, `unwrap_err`, `unwrap` and `unwrap_or_else`. +The `security_level` enum should be defined as follows: + +- `Unknown`: Returns the server URL or panics. +- `Message`: Returns the server URL or panics with the error message `ERROR: program stops`. +- `Warning`: Returns the server URL or the message `WARNING: check the server`. +- `NotFound`: Returns the server URL or the message `Not found: [MESSAGE]`, where `[MESSAGE]` represents the `server`'s error message. +- `UnexpectedUrl`: Returns the error message or panics with the error message being the server URL. ### Expected Functions ```rust pub enum Security { - Unknown, - High, - Medium, - Low, - BlockServer, + Unknown, + Message, + Warning, + NotFound, + UnexpectedUrl, } -pub fn fetch_data(server: Result, security_level: Security) -> String { - +pub fn fetch_data(server: Result<&str, &str>, security_level: Security) -> String { + todo!() } ``` @@ -39,18 +39,18 @@ Here is a program to test your function: use unwrap_or_expect::*; fn main() { - println!("{}", fetch_data(Ok("server1.com".to_string()), Security::Medium)); - println!("{}", fetch_data(Err(String::new()), Security::Medium)); - println!("{}", fetch_data(Err("server2.com".to_string()), Security::Low)); + println!("{}", fetch_data(Ok("server1.com"), Security::Warning)); + println!("{}", fetch_data(Err("server.com"), Security::Warning)); + println!("{}", fetch_data(Err("server2.com"), Security::NotFound)); // Panics with no custom message - // fetch_data(Err("ERROR CRITICAL".to_string()), Security::Unknown); + // fetch_data(Err("ERROR CRITICAL"), Security::Unknown); // Panics with the message "ERROR: program stops" - // fetch_data(Err(String::new()), Security::High); + // fetch_data(Err("server.com"), Security::Message); // Panics with the message "malicious_server.com" - // fetch_data(Ok("malicious_server.com".to_string()), Security::BlockServer); + // fetch_data(Ok("malicious_server.com"), Security::UnexpectedUrl); } ```