100 exercises to learn Rust
This commit is contained in:
6
helpers/common/Cargo.toml
Normal file
6
helpers/common/Cargo.toml
Normal file
@@ -0,0 +1,6 @@
|
||||
[package]
|
||||
name = "common"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
15
helpers/common/src/lib.rs
Normal file
15
helpers/common/src/lib.rs
Normal file
@@ -0,0 +1,15 @@
|
||||
pub fn overly_long_description() -> String {
|
||||
"At vero eos et accusamus et iusto odio dignissimos ducimus qui blanditiis praesentium voluptatum deleniti atque corrupti quos dolores et quas molestias excepturi sint occaecati cupiditate non provident, similique sunt in culpa qui officia deserunt mollitia animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis est et expedita distinctio. Nam libero tempore, cum soluta nobis est eligendi optio cumque nihil impedit quo minus id quod maxime placeat facere possimus, omnis voluptas assumenda est, omnis dolor repellendus. Temporibus autem quibusdam et aut officiis debitis aut rerum necessitatibus saepe eveniet ut et voluptates repudiandae sint et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut perferendis doloribus asperiores repellat.".into()
|
||||
}
|
||||
|
||||
pub fn overly_long_title() -> String {
|
||||
"A title that's definitely longer than what should be allowed in a development ticket".into()
|
||||
}
|
||||
|
||||
pub fn valid_title() -> String {
|
||||
"A title".into()
|
||||
}
|
||||
|
||||
pub fn valid_description() -> String {
|
||||
"A description".into()
|
||||
}
|
||||
8
helpers/ticket_fields/Cargo.toml
Normal file
8
helpers/ticket_fields/Cargo.toml
Normal file
@@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "ticket_fields"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
thiserror = "1.0.59"
|
||||
common = { path = "../common" }
|
||||
73
helpers/ticket_fields/src/description.rs
Normal file
73
helpers/ticket_fields/src/description.rs
Normal file
@@ -0,0 +1,73 @@
|
||||
#[derive(Debug, PartialEq, Clone, Eq)]
|
||||
pub struct TicketDescription(String);
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum TicketDescriptionError {
|
||||
#[error("The description cannot be empty")]
|
||||
Empty,
|
||||
#[error("The description cannot be longer than 500 characters")]
|
||||
TooLong,
|
||||
}
|
||||
|
||||
impl TryFrom<String> for TicketDescription {
|
||||
type Error = TicketDescriptionError;
|
||||
|
||||
fn try_from(value: String) -> Result<Self, Self::Error> {
|
||||
validate(&value)?;
|
||||
Ok(Self(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for TicketDescription {
|
||||
type Error = TicketDescriptionError;
|
||||
|
||||
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
||||
validate(value)?;
|
||||
Ok(Self(value.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
fn validate(description: &str) -> Result<(), TicketDescriptionError> {
|
||||
if description.is_empty() {
|
||||
Err(TicketDescriptionError::Empty)
|
||||
} else if description.len() > 500 {
|
||||
Err(TicketDescriptionError::TooLong)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use common::{overly_long_description, valid_description};
|
||||
use std::convert::TryFrom;
|
||||
|
||||
#[test]
|
||||
fn test_try_from_string() {
|
||||
let input = valid_description();
|
||||
let description = TicketDescription::try_from(input.clone()).unwrap();
|
||||
assert_eq!(description.0, input);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_from_empty_string() {
|
||||
let err = TicketDescription::try_from("".to_string()).unwrap_err();
|
||||
assert_eq!(err.to_string(), "The description cannot be empty");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_from_long_string() {
|
||||
let err = TicketDescription::try_from(overly_long_description()).unwrap_err();
|
||||
assert_eq!(
|
||||
err.to_string(),
|
||||
"The description cannot be longer than 500 characters"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_from_str() {
|
||||
let description = TicketDescription::try_from("A description").unwrap();
|
||||
assert_eq!(description.0, "A description");
|
||||
}
|
||||
}
|
||||
6
helpers/ticket_fields/src/lib.rs
Normal file
6
helpers/ticket_fields/src/lib.rs
Normal file
@@ -0,0 +1,6 @@
|
||||
mod description;
|
||||
pub mod test_helpers;
|
||||
mod title;
|
||||
|
||||
pub use description::TicketDescription;
|
||||
pub use title::TicketTitle;
|
||||
14
helpers/ticket_fields/src/test_helpers.rs
Normal file
14
helpers/ticket_fields/src/test_helpers.rs
Normal file
@@ -0,0 +1,14 @@
|
||||
use crate::{TicketDescription, TicketTitle};
|
||||
use common::{valid_description, valid_title};
|
||||
|
||||
/// A function to generate a valid ticket title,
|
||||
/// for test purposes.
|
||||
pub fn ticket_title() -> TicketTitle {
|
||||
valid_title().try_into().unwrap()
|
||||
}
|
||||
|
||||
/// A function to generate a valid ticket description,
|
||||
/// for test purposes.
|
||||
pub fn ticket_description() -> TicketDescription {
|
||||
valid_description().try_into().unwrap()
|
||||
}
|
||||
75
helpers/ticket_fields/src/title.rs
Normal file
75
helpers/ticket_fields/src/title.rs
Normal file
@@ -0,0 +1,75 @@
|
||||
use std::convert::TryFrom;
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Eq)]
|
||||
pub struct TicketTitle(String);
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum TicketTitleError {
|
||||
#[error("The title cannot be empty")]
|
||||
Empty,
|
||||
#[error("The title cannot be longer than 50 characters")]
|
||||
TooLong,
|
||||
}
|
||||
|
||||
impl TryFrom<String> for TicketTitle {
|
||||
type Error = TicketTitleError;
|
||||
|
||||
fn try_from(value: String) -> Result<Self, Self::Error> {
|
||||
validate(&value)?;
|
||||
Ok(Self(value))
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for TicketTitle {
|
||||
type Error = TicketTitleError;
|
||||
|
||||
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
||||
validate(value)?;
|
||||
Ok(Self(value.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
fn validate(title: &str) -> Result<(), TicketTitleError> {
|
||||
if title.is_empty() {
|
||||
Err(TicketTitleError::Empty)
|
||||
} else if title.len() > 50 {
|
||||
Err(TicketTitleError::TooLong)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use common::{overly_long_title, valid_title};
|
||||
use std::convert::TryFrom;
|
||||
|
||||
#[test]
|
||||
fn test_try_from_string() {
|
||||
let input = valid_title();
|
||||
let title = TicketTitle::try_from(input.clone()).unwrap();
|
||||
assert_eq!(title.0, input);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_from_empty_string() {
|
||||
let err = TicketTitle::try_from("".to_string()).unwrap_err();
|
||||
assert_eq!(err.to_string(), "The title cannot be empty");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_from_long_string() {
|
||||
let err = TicketTitle::try_from(overly_long_title()).unwrap_err();
|
||||
assert_eq!(
|
||||
err.to_string(),
|
||||
"The title cannot be longer than 50 characters"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_try_from_str() {
|
||||
let title = TicketTitle::try_from("A title").unwrap();
|
||||
assert_eq!(title.0, "A title");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user