Use TryInto.

This commit is contained in:
LukeMathWalker 2020-12-29 10:00:11 +00:00
parent f6d62fb7a1
commit 9dd9aaffd6
6 changed files with 89 additions and 12 deletions

45
Cargo.lock generated
View file

@ -701,6 +701,25 @@ dependencies = [
"syn",
]
[[package]]
name = "env_logger"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36"
dependencies = [
"log",
"regex",
]
[[package]]
name = "fake"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6479fa2c7e83ddf8be7d435421e093b072ca891b99a49bc84eba098f4044f818"
dependencies = [
"rand",
]
[[package]]
name = "flate2"
version = "1.0.19"
@ -1609,6 +1628,29 @@ version = "1.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
[[package]]
name = "quickcheck"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a44883e74aa97ad63db83c4bf8ca490f02b2fc02f92575e720c8551e843c945f"
dependencies = [
"env_logger",
"log",
"rand",
"rand_core",
]
[[package]]
name = "quickcheck_macros"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "608c156fd8e97febc07dc9c2e2c80bf74cfc6ef26893eae3daf8bc2bc94a4b7f"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "quote"
version = "1.0.7"
@ -2921,7 +2963,10 @@ dependencies = [
"chrono",
"claim",
"config",
"fake",
"lazy_static",
"quickcheck",
"quickcheck_macros",
"reqwest",
"serde",
"serde-aux",

View file

@ -30,8 +30,11 @@ tracing-actix-web = "0.2.0"
serde-aux = "1.0.1"
unicode-segmentation = "1.7.1"
validator = "0.12.0"
quickcheck_macros = "0.9.1"
[dev-dependencies]
reqwest = { version = "0.10.7", features = ["json"] }
lazy_static = "1.4.0"
claim = "0.4.0"
quickcheck = "0.9.2"
fake = "2.3.0"

View file

@ -1,6 +1,7 @@
mod subscriber_name;
mod subscriber_email;
mod new_subscriber;
mod subscriber_email;
mod subscriber_name;
pub use subscriber_name::SubscriberName;
pub use new_subscriber::NewSubscriber;
pub use subscriber_email::SubscriberEmail;
pub use subscriber_name::SubscriberName;

View file

@ -1,6 +1,8 @@
use crate::domain::subscriber_name::SubscriberName;
use crate::domain::subscriber_email::SubscriberEmail;
pub struct NewSubscriber {
pub email: String,
// We are not using `String` anymore!
pub email: SubscriberEmail,
pub name: SubscriberName,
}

View file

@ -23,6 +23,8 @@ impl AsRef<str> for SubscriberEmail {
mod tests {
use super::SubscriberEmail;
use claim::assert_err;
use fake::Fake;
use fake::faker::internet::en::SafeEmail;
#[test]
fn empty_string_is_rejected() {
@ -41,4 +43,19 @@ mod tests {
let email = "@domain.com".to_string();
assert_err!(SubscriberEmail::parse(email));
}
#[derive(Debug, Clone)]
struct ValidEmailFixture(pub String);
impl quickcheck::Arbitrary for ValidEmailFixture {
fn arbitrary<G: quickcheck::Gen>(g: &mut G) -> Self {
let email = SafeEmail().fake_with_rng(g);
Self(email)
}
}
#[quickcheck_macros::quickcheck]
fn valid_emails_are_parsed_successfully(valid_email: ValidEmailFixture) -> bool {
SubscriberEmail::parse(valid_email.0).is_ok()
}
}

View file

@ -1,7 +1,8 @@
use crate::domain::{NewSubscriber, SubscriberName};
use crate::domain::{NewSubscriber, SubscriberEmail, SubscriberName};
use actix_web::{web, HttpResponse};
use chrono::Utc;
use sqlx::PgPool;
use std::convert::TryInto;
use uuid::Uuid;
#[derive(serde::Deserialize)]
@ -10,6 +11,16 @@ pub struct FormData {
name: String,
}
impl TryInto<NewSubscriber> for FormData {
type Error = String;
fn try_into(self) -> Result<NewSubscriber, Self::Error> {
let name = SubscriberName::parse(self.name)?;
let email = SubscriberEmail::parse(self.email)?;
Ok(NewSubscriber { email, name })
}
}
#[tracing::instrument(
name = "Adding a new subscriber",
skip(form, pool),
@ -22,12 +33,10 @@ pub async fn subscribe(
form: web::Form<FormData>,
pool: web::Data<PgPool>,
) -> Result<HttpResponse, HttpResponse> {
let name =
SubscriberName::parse(form.0.name).map_err(|_| HttpResponse::BadRequest().finish())?;
let new_subscriber = NewSubscriber {
email: form.0.email,
name,
};
let new_subscriber = form
.0
.try_into()
.map_err(|_| HttpResponse::BadRequest().finish())?;
insert_subscriber(&pool, &new_subscriber)
.await
.map_err(|_| HttpResponse::InternalServerError().finish())?;
@ -48,7 +57,7 @@ pub async fn insert_subscriber(
VALUES ($1, $2, $3, $4)
"#,
Uuid::new_v4(),
new_subscriber.email,
new_subscriber.email.as_ref(),
new_subscriber.name.as_ref(),
Utc::now()
)