Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CON-3318 Fix rust piscine's quest-04 #2887

Merged
merged 19 commits into from
Mar 14, 2025
Merged
70 changes: 36 additions & 34 deletions subjects/banner/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<String, ParseFloatError>;

pub struct FlagsHandler {
pub flags: HashMap<(String, String), Callback>,
pub flags: HashMap<String, Callback>,
}

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<String, String> {
todo!()
}
}

pub fn div(a: &str, b: &str) -> Result<String, ParseFloatError> {

todo!()
}
pub fn rem(a: &str, b: &str) -> Result<String, ParseFloatError> {

pub fn rem(a: &str, b: &str) -> Result<String, ParseFloatError> {
todo!()
}

```
Expand All @@ -88,27 +90,27 @@ 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"]));
}
```

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")
$
```

Expand Down
127 changes: 63 additions & 64 deletions subjects/boxing_todo/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,88 +16,65 @@ 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<dyn Error>`.

- `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<dyn Error>`.
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

[json = "0.12.4"](https://docs.rs/json/0.12.4/json/)

### 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 {
Expand All @@ -114,7 +91,7 @@ pub struct TodoList {

impl TodoList {
pub fn get_todo(path: &str) -> Result<TodoList, Box<dyn Error>> {

todo!()
}
}
```
Expand All @@ -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());
}
}
}
}
Expand All @@ -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 }))
$
```

Expand Down
21 changes: 7 additions & 14 deletions subjects/cipher/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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<Result<bool, CipherError>> {

pub fn cipher(original: &str, ciphered: &str) -> Result<(), CipherError> {
todo!()
}
```

Expand All @@ -36,16 +31,14 @@ use cipher::*;
fn main() {
println!("{:?}", cipher("1Hello 2world!", "1Svool 2dliow!"));
println!("{:?}", cipher("1Hello 2world!", "svool"));
println!("{:?}", cipher("", "svool"));
}
```

And its output:

```console
$ cargo run
Some(Ok(true))
Some(Err(CipherError { validation: false, expected: "1Svool 2dliow!" }))
None
Ok(())
Err(CipherError { expected: "1Svool 2dliow!" })
$
```
Loading
Loading