completed most of 05 ticket v2
This commit is contained in:
@@ -7,15 +7,18 @@
|
||||
struct Ticket {
|
||||
title: String,
|
||||
description: String,
|
||||
status: String,
|
||||
status: Status,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||
enum Status {
|
||||
// TODO: add the missing variants
|
||||
ToDo,
|
||||
InProgress,
|
||||
Done,
|
||||
}
|
||||
|
||||
impl Ticket {
|
||||
pub fn new(title: String, description: String, status: String) -> Ticket {
|
||||
pub fn new(title: String, description: String, status: Status) -> Ticket {
|
||||
if title.is_empty() {
|
||||
panic!("Title cannot be empty");
|
||||
}
|
||||
@@ -28,7 +31,7 @@ impl Ticket {
|
||||
if description.len() > 500 {
|
||||
panic!("Description cannot be longer than 500 bytes");
|
||||
}
|
||||
if status != "To-Do" && status != "In Progress" && status != "Done" {
|
||||
if status != Status::ToDo && status != Status::InProgress && status != Status::Done {
|
||||
panic!("Only `To-Do`, `In Progress`, and `Done` statuses are allowed");
|
||||
}
|
||||
|
||||
@@ -47,7 +50,7 @@ impl Ticket {
|
||||
&self.description
|
||||
}
|
||||
|
||||
pub fn status(&self) -> &String {
|
||||
pub fn status(&self) -> &Status {
|
||||
&self.status
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,13 @@ enum Shape {
|
||||
impl Shape {
|
||||
// TODO: Implement the `n_sides` method using a `match`.
|
||||
pub fn n_sides(&self) -> u8 {
|
||||
todo!()
|
||||
match self {
|
||||
Self::Circle => 0,
|
||||
Self::Pentagon => 5,
|
||||
Self::Rectangle => 4,
|
||||
Self::Square => 4,
|
||||
Self::Triangle => 3,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ struct Ticket {
|
||||
status: Status,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
enum Status {
|
||||
ToDo,
|
||||
InProgress { assigned_to: String },
|
||||
@@ -38,7 +38,11 @@ impl Ticket {
|
||||
}
|
||||
}
|
||||
pub fn assigned_to(&self) -> &str {
|
||||
todo!()
|
||||
match &self.status {
|
||||
Status::InProgress { assigned_to } => assigned_to,
|
||||
_ => panic!("Only `In-Progress` tickets can be assigned to someone"),
|
||||
}
|
||||
// let Status::InProgress { assigned_to } = self.status;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,8 +7,19 @@ enum Shape {
|
||||
impl Shape {
|
||||
// TODO: Implement the `radius` method using
|
||||
// either an `if let` or a `let/else`.
|
||||
// pub fn radius(&self) -> f64 {
|
||||
// if let Shape::Circle { radius } = self {
|
||||
// return radius.clone();
|
||||
// } else {
|
||||
// panic!("");
|
||||
// }
|
||||
// }
|
||||
|
||||
pub fn radius(&self) -> f64 {
|
||||
todo!()
|
||||
let Shape::Circle { radius } = self else {
|
||||
panic!("");
|
||||
};
|
||||
radius.clone()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,10 @@ impl Ticket {
|
||||
}
|
||||
}
|
||||
pub fn assigned_to(&self) -> Option<&String> {
|
||||
todo!()
|
||||
let Status::InProgress { assigned_to } = &self.status else {
|
||||
return None;
|
||||
};
|
||||
Some(assigned_to)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,25 +16,25 @@ enum Status {
|
||||
}
|
||||
|
||||
impl Ticket {
|
||||
pub fn new(title: String, description: String, status: Status) -> Ticket {
|
||||
pub fn new(title: String, description: String, status: Status) -> Result<Ticket, String> {
|
||||
if title.is_empty() {
|
||||
panic!("Title cannot be empty");
|
||||
return Err("Title cannot be empty".to_string());
|
||||
}
|
||||
if title.len() > 50 {
|
||||
panic!("Title cannot be longer than 50 bytes");
|
||||
return Err("Title cannot be longer than 50 bytes".to_string());
|
||||
}
|
||||
if description.is_empty() {
|
||||
panic!("Description cannot be empty");
|
||||
return Err("Description cannot be empty".to_string());
|
||||
}
|
||||
if description.len() > 500 {
|
||||
panic!("Description cannot be longer than 500 bytes");
|
||||
return Err("Description cannot be longer than 500 bytes".to_string());
|
||||
}
|
||||
|
||||
Ticket {
|
||||
Ok(Ticket {
|
||||
title,
|
||||
description,
|
||||
status,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,25 @@
|
||||
// When the description is invalid, instead, it should use a default description:
|
||||
// "Description not provided".
|
||||
fn easy_ticket(title: String, description: String, status: Status) -> Ticket {
|
||||
todo!()
|
||||
let tick = Ticket::new(title.clone(), description.clone(), status.clone());
|
||||
match tick {
|
||||
Ok(res) => return res,
|
||||
Err(err) => {
|
||||
match err.as_str() {
|
||||
"Description cannot be empty" | "Description cannot be longer than 500 bytes" => {
|
||||
return Ticket {
|
||||
title: title.clone(),
|
||||
description: "Description not provided".to_string(),
|
||||
status: status.clone(),
|
||||
};
|
||||
}
|
||||
|
||||
_ => {
|
||||
panic!("{err}");
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
|
||||
@@ -1,14 +1,27 @@
|
||||
// TODO: Use two variants, one for a title error and one for a description error.
|
||||
// Each variant should contain a string with the explanation of what went wrong exactly.
|
||||
// You'll have to update the implementation of `Ticket::new` as well.
|
||||
enum TicketNewError {}
|
||||
enum TicketNewError {
|
||||
TitleError { desc: String },
|
||||
DescError { desc: String },
|
||||
}
|
||||
|
||||
// TODO: `easy_ticket` should panic when the title is invalid, using the error message
|
||||
// stored inside the relevant variant of the `TicketNewError` enum.
|
||||
// When the description is invalid, instead, it should use a default description:
|
||||
// "Description not provided".
|
||||
fn easy_ticket(title: String, description: String, status: Status) -> Ticket {
|
||||
todo!()
|
||||
match Ticket::new(title.clone(), description, status.clone()) {
|
||||
Ok(proper) => proper,
|
||||
Err(TicketNewError::DescError { desc }) => Ticket {
|
||||
title: title.clone(),
|
||||
description: "Description not provided".to_string(),
|
||||
status: status.clone(),
|
||||
},
|
||||
Err(TicketNewError::TitleError { desc }) => {
|
||||
panic!("{desc}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
@@ -32,16 +45,24 @@ impl Ticket {
|
||||
status: Status,
|
||||
) -> Result<Ticket, TicketNewError> {
|
||||
if title.is_empty() {
|
||||
return Err("Title cannot be empty".to_string());
|
||||
return Err(TicketNewError::TitleError {
|
||||
desc: "Title cannot be empty".to_string(),
|
||||
});
|
||||
}
|
||||
if title.len() > 50 {
|
||||
return Err("Title cannot be longer than 50 bytes".to_string());
|
||||
return Err(TicketNewError::TitleError {
|
||||
desc: "Title cannot be longer than 50 bytes".to_string(),
|
||||
});
|
||||
}
|
||||
if description.is_empty() {
|
||||
return Err("Description cannot be empty".to_string());
|
||||
return Err(TicketNewError::DescError {
|
||||
desc: "Description cannot be empty".to_string(),
|
||||
});
|
||||
}
|
||||
if description.len() > 500 {
|
||||
return Err("Description cannot be longer than 500 bytes".to_string());
|
||||
return Err(TicketNewError::DescError {
|
||||
desc: "Description cannot be longer than 500 bytes".to_string(),
|
||||
});
|
||||
}
|
||||
|
||||
Ok(Ticket {
|
||||
|
||||
@@ -3,17 +3,41 @@
|
||||
// The docs for the `std::fmt` module are a good place to start and look for examples:
|
||||
// https://doc.rust-lang.org/std/fmt/index.html#write
|
||||
|
||||
use std::error::Error;
|
||||
use std::fmt::{Display, Formatter};
|
||||
|
||||
#[derive(Debug)]
|
||||
enum TicketNewError {
|
||||
TitleError(String),
|
||||
DescriptionError(String),
|
||||
}
|
||||
|
||||
impl Display for TicketNewError {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
|
||||
match self {
|
||||
TicketNewError::TitleError(msg) => write!(f, "{msg}"),
|
||||
TicketNewError::DescriptionError(msg) => write!(f, "{msg}"),
|
||||
}
|
||||
// write!(f, "")
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for TicketNewError {}
|
||||
|
||||
// TODO: `easy_ticket` should panic when the title is invalid, using the error message
|
||||
// stored inside the relevant variant of the `TicketNewError` enum.
|
||||
// When the description is invalid, instead, it should use a default description:
|
||||
// "Description not provided".
|
||||
fn easy_ticket(title: String, description: String, status: Status) -> Ticket {
|
||||
todo!()
|
||||
match Ticket::new(title.clone(), description, status.clone()) {
|
||||
Ok(ticket) => ticket,
|
||||
Err(err) => match err {
|
||||
TicketNewError::TitleError(_) => panic!("{err}"),
|
||||
TicketNewError::DescriptionError(_) => {
|
||||
Ticket::new(title, "Description not provided".to_string(), status).unwrap()
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
|
||||
1
exercises/05_ticket_v2/10_packages/src/lib.rs
Normal file
1
exercises/05_ticket_v2/10_packages/src/lib.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub fn hello_world() {}
|
||||
@@ -2,3 +2,6 @@
|
||||
name = "deps"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "*"
|
||||
|
||||
@@ -4,6 +4,6 @@ version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
|
||||
thiserror = "*"
|
||||
[dev-dependencies]
|
||||
common = { path = "../../../helpers/common" }
|
||||
|
||||
@@ -3,10 +3,17 @@
|
||||
// a `String` field into each variant.
|
||||
// You'll also have to add `thiserror` as a dependency in the `Cargo.toml` file.
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
enum TicketNewError {
|
||||
#[error("Title cannot be empty")]
|
||||
TitleCannotBeEmpty,
|
||||
#[error("Title cannot be longer than 50 bytes")]
|
||||
TitleTooLong,
|
||||
#[error("Description cannot be empty")]
|
||||
DescriptionCannotBeEmpty,
|
||||
#[error("Description cannot be longer than 500 bytes")]
|
||||
DescriptionTooLong,
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user