You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

119 lines
4.6 KiB

## ref_cell
### Instructions
4 years ago
#### First part (messenger.rs)
Create a module named `messenger`. This module will be able to inform a user of how many references of a given value they are using.
4 years ago
The main objective of this module is to limit how many times a value is referenced.
4 years ago
For this module the following must be created:
Implement `Logger`: a trait which implements the following three functions:
```rust
fn warning(&self, msg: &str);
fn info(&self, msg: &str);
fn error(&self, msg: &str);
```
Implement the `Tracker` structure with the following fields:
2 years ago
- `logger`: a reference to `Logger`.
- `value`: the count of how many times the value was referenced. It should not exceed `max`.
- `max`: the max count of references.
Add the following associated functions to `Tracker`:
2 years ago
- `new`: that initializes the structure.
- `set_value`: that sets the `value`. It should compare the number of references to `value` and `max` to work out the percentage used. It should write to the following traits if it exceeds the specified usage percentage:
- percentage >= 100%: `"Error: you are over your quota!"` should be written to `error`.
- percentage >= 70% and percentage < 100%: `"Warning: you have used up over X% of your quota! Proceeds with precaution"` should be written to `warning`, where `X` should be replaced with the calculated percentage.
2 years ago
- `peek`: that will take a peek at how much usage the variable already has. It should write `"Info: you are using up to X% of your quota"` to the `info` trait function. `X` should be replaced with the calculated percentage.
4 years ago
### Second part (lib.rs)
Now that you've created `messenger`, you can now create the following:
Create the `Worker` structure with the following fields:
2 years ago
- `track_value`: which is the value that will be tracked by the tracker.
- `mapped_messages`: that will store the latest messages from the `Logger` trait functions. This will be a HashMap. The key will represent the type of message (`info`, `error` or `warning`), and the value will be the actual message.
- `all_messages`: that will be a vector of **all** messages sent.
Create the following associated functions for `Worker`:
2 years ago
- `new`: that initializes a `Worker` structure.
- `Logger`: 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 field of the `Worker` structure.
2 years ago
You must use **interior mutability**, this means it must be possible to mutate data, even when there are immutable references to that data. Consequently, the user will not need to use the keyword `mut`. _tip:_ RefCell.
### Usage
4 years ago
Here is a program to test your function,
```rust
4 years ago
use ref_cell::*;
fn main() {
// initialize the worker
4 years ago
let logger = Worker::new(1);
// initialize the tracker, with the max number of
// called references as 10
4 years ago
let track = Tracker::new(&logger, 10);
4 years ago
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
4 years ago
track.peek(&logger.track_value);
4 years ago
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
4 years ago
track.set_value(&logger.track_value);
4 years ago
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
4 years ago
track.set_value(&logger.track_value);
4 years ago
let _c1 = logger.track_value.clone(); // | -> increase the Rc to 10 references, this will be the limit
4 years ago
track.set_value(&logger.track_value);
4 years ago
for (k ,v) in logger.mapped_messages.into_inner() {
println!("{:?}", (k ,v));
}
4 years ago
println!("{:?}", logger.all_messages.into_inner());
}
```
And its output:
```console
$ cargo run
2 years ago
("Info", "you are using up to 40% of your quota")
("Warning", "you have used up over 90% of your quota! Proceeds with precaution")
("Error", "you are over your quota!")
[
2 years ago
"Info: you are using up to 40% of your quota",
"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!"
]
$
```
### Notions
- [std::cell::RefCell](https://doc.rust-lang.org/std/cell/struct.RefCell.html)
- [Struct std::rc::Rc](https://doc.rust-lang.org/std/rc/struct.Rc.html)