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.

111 lines
3.3 KiB

## drop_the_blog
### Instructions
Define the following structures:
- `Blog`: containing:
- `drops` that will save the number of dropped articles.
- `states` that will save the state of multiple articles. If the article is not dropped, the state will be `false`, otherwise it will be `true`.
- `Article`: containing:
- `id` as `usize`.
- `body` as `String`.
- `parent` a link to the structure `Blog`. (Tip: this should be a reference).
You'll need to also add the following associated functions to the structures:
- `Blog`:
- `new` that creates an empty blog.
- `new_article` that receives a `String` for the body and returns a tuple with the `id` and a new `Article`.
- `is_dropped` that receives an `id` and returns a `bool` that indicates the state of the article.
- `new_id` which returns a `usize` representing the length of the `states` vector. (Which is also the first available id).
- `add_drop` which is **called by the `Drop` trait**. It will receive an `id` that will be used to change the state of the article. If the state of that article is `true` then it will panic with the message `"X is already dropped"`, where `X` represents the `id`). Otherwise it should change the state to `true` and increment the `drops` field by 1.
- `Article`:
- `new` that initializes a new article.
- `discard` that drops the article.
> You must implement the `Drop` trait for the `Article` structure. In this trait you must call the function `add_drop` so that the state of the article changes.
### Expected Functions
```rust
use std::cell::{RefCell, Cell};
#[derive(Debug, Default, Clone, Eq, PartialEq)]
pub struct Blog {
pub drops: Cell<usize>,
pub states: RefCell<Vec<bool>>
}
impl Blog {
pub fn new() -> Blog {}
pub fn new_article(&self, body: String) -> (usize, Article) {}
pub fn new_id(&self) -> usize {}
pub fn is_dropped(&self, id: usize) -> bool {}
pub fn add_drop(&self, id: usize) {}
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Article<'a> {
// expected public fields
}
impl<'a> Article<'a> {
pub fn new(id: usize, body: String, blog: &'a Blog) -> Article {}
pub fn discard(self) {}
}
```
### Usage
Here is a program to test your function,
```rust
use drop_the_blog::*;
use std::rc::Rc;
fn main() {
let blog = Blog::new();
let (id, article) = blog.new_article(String::from("Winter is coming"));
let (id1, article1) = blog.new_article(String::from("The story of the universe"));
article.discard();
println!("{:?}", (blog.is_dropped(id), id, &blog.drops));
article1.discard();
println!("{:?}", (blog.is_dropped(id1), id1, &blog.drops));
let (id2, article2) = blog.new_article(String::from("How to cook 101"));
let article2 = Rc::new(article2);
let article2_clone = article2.clone();
drop(article2_clone);
println!("{:?}",
(blog.is_dropped(id2), id2, &blog.drops, Rc::strong_count(&article2)));
}
```
And its output:
```console
$ cargo run
(true, 0, Cell { value: 1 })
(true, 1, Cell { value: 2 })
(false, 2, Cell { value: 2 }, 1)
$
```
### Notions
- [Trait std::ops::Drop](https://doc.bccnsoft.com/docs/rust-1.36.0-docs-html/std/ops/trait.Drop.html)
- [Struct std::cell::RefCell](https://doc.rust-lang.org/std/cell/struct.RefCell.html)
- [Interior Mutability](https://doc.rust-lang.org/book/ch15-05-interior-mutability.html)