partial implement client app
This commit is contained in:
110
src/models/email.rs
Normal file
110
src/models/email.rs
Normal file
@@ -0,0 +1,110 @@
|
||||
use std::{fmt, str::FromStr};
|
||||
|
||||
use email_address::{EmailAddress, Options};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct Email(String);
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum EmailError {
|
||||
Empty,
|
||||
InvalidUtf8,
|
||||
InvalidFormat,
|
||||
}
|
||||
|
||||
impl Email {
|
||||
pub fn new(s: impl AsRef<str>) -> Result<Self, EmailError> {
|
||||
let s = s.as_ref().trim();
|
||||
if s.is_empty() {
|
||||
return Err(EmailError::Empty);
|
||||
}
|
||||
|
||||
// Strict "address only" validation (no "Name <a@b.com>")
|
||||
EmailAddress::parse_with_options(s, Options::default().without_display_text())
|
||||
.map_err(|_| EmailError::InvalidFormat)?;
|
||||
|
||||
Ok(Self(s.to_owned()))
|
||||
}
|
||||
|
||||
pub fn as_str(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
|
||||
pub fn as_bytes(&self) -> &[u8] {
|
||||
self.0.as_bytes()
|
||||
}
|
||||
|
||||
pub fn into_inner(self) -> String {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn into_bytes(self) -> Vec<u8> {
|
||||
self.0.into_bytes()
|
||||
}
|
||||
|
||||
pub fn from_bytes(bytes: &[u8]) -> Result<Self, EmailError> {
|
||||
let s = std::str::from_utf8(bytes).map_err(|_| EmailError::InvalidUtf8)?;
|
||||
Self::new(s)
|
||||
}
|
||||
}
|
||||
|
||||
/* ---- std traits ---- */
|
||||
|
||||
impl fmt::Display for Email {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str(self.as_str())
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for Email {
|
||||
type Err = EmailError;
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
Email::new(s)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<String> for Email {
|
||||
type Error = EmailError;
|
||||
fn try_from(value: String) -> Result<Self, Self::Error> {
|
||||
Email::new(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&str> for Email {
|
||||
type Error = EmailError;
|
||||
fn try_from(value: &str) -> Result<Self, Self::Error> {
|
||||
Email::new(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<&[u8]> for Email {
|
||||
type Error = EmailError;
|
||||
fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
|
||||
Email::from_bytes(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Vec<u8>> for Email {
|
||||
type Error = EmailError;
|
||||
fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
|
||||
Email::from_bytes(&value)
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<str> for Email {
|
||||
fn as_ref(&self) -> &str {
|
||||
self.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<[u8]> for Email {
|
||||
fn as_ref(&self) -> &[u8] {
|
||||
self.as_bytes()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Email> for Vec<u8> {
|
||||
fn from(value: Email) -> Self {
|
||||
value.into_bytes()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user