Add Mailbox, Message, Lines, Recipients types

This commit is contained in:
Nathan Fisher 2023-05-25 23:35:24 -04:00
parent c57bb83c5c
commit b2f60c61ec
7 changed files with 216 additions and 0 deletions

View file

@ -6,6 +6,7 @@ edition = "2021"
[dependencies] [dependencies]
digest = "0.10.7" digest = "0.10.7"
sha2 = "0.10.6" sha2 = "0.10.6"
time = "0.3.21"
x509-parser = "0.15.0" x509-parser = "0.15.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

View file

@ -2,6 +2,8 @@
mod certificate_store; mod certificate_store;
mod fingerprint; mod fingerprint;
mod host; mod host;
mod mailbox;
mod message;
pub mod prelude; pub mod prelude;
mod receiver; mod receiver;
mod request; mod request;

35
src/mailbox/error.rs Normal file
View file

@ -0,0 +1,35 @@
use {crate::prelude::ParseHostError, std::fmt};
#[derive(Debug, PartialEq)]
/// Errors which can occur when parsing a request
pub enum Error {
MissingSeparator,
EmptyUser,
EmptyHost,
ParseHostError(ParseHostError),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::ParseHostError(e) => write!(f, "{e}"),
_ => write!(f, "{self:?}"),
}
}
}
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::ParseHostError(e) => Some(e),
_ => None,
}
}
}
impl From<ParseHostError> for Error {
fn from(value: ParseHostError) -> Self {
Self::ParseHostError(value)
}
}

56
src/mailbox/mod.rs Normal file
View file

@ -0,0 +1,56 @@
use std::{fmt, str::FromStr};
use crate::prelude::Host;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
mod error;
pub use error::Error;
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
pub struct Mailbox {
pub username: String,
pub host: Host,
pub blurb: Option<String>,
}
impl fmt::Display for Mailbox {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"{}@{}",
self.username,
self.host,
)
}
}
impl FromStr for Mailbox {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut blurb = None;
if let Some((username, mut host)) = s.split_once('@') {
if username.is_empty() {
Err(Error::EmptyUser)
} else {
let username = username.to_string();
if let Some((h, b)) = host.split_once(|c: char| c.is_whitespace()) {
if h.is_empty() {
return Err(Error::EmptyHost);
} else {
host = h;
if !b.is_empty() {
blurb = Some(b.to_string());
}
}
}
let host = host.parse()?;
Ok(Self { username, host, blurb })
}
} else {
Err(Error::MissingSeparator)
}
}
}

36
src/message/error.rs Normal file
View file

@ -0,0 +1,36 @@
use {crate::prelude::ParseHostError, std::fmt};
#[derive(Debug, PartialEq)]
/// Errors which can occur when parsing a request
pub enum Error {
MissingSeparator,
EmptyUser,
EmptyHost,
EmptyMessage,
ParseHostError(ParseHostError),
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::ParseHostError(e) => write!(f, "{e}"),
_ => write!(f, "{self:?}"),
}
}
}
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::ParseHostError(e) => Some(e),
_ => None,
}
}
}
impl From<ParseHostError> for Error {
fn from(value: ParseHostError) -> Self {
Self::ParseHostError(value)
}
}

84
src/message/mod.rs Normal file
View file

@ -0,0 +1,84 @@
use std::{fmt, str::FromStr};
use crate::prelude::{Host, Mailbox};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
mod error;
pub use error::Error;
#[derive(Clone, Debug, PartialEq)]
pub struct Recipients {
pub boxes: Vec<Mailbox>,
}
impl fmt::Display for Recipients {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, ":")?;
self.boxes.iter().try_for_each(|b| {
write!(f, " {b}")
})
}
}
#[derive(Clone, Debug, PartialEq)]
pub enum Lines {
Sender(Mailbox),
Recipients(Recipients),
Timestamp(String),
Text(String),
Heading1(String),
Heading2(String),
Heading3(String),
Quote(String),
Preformatted(String),
}
impl fmt::Display for Lines {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Sender(m) => writeln!(f, "< {m}"),
Self::Recipients(r) => writeln!(f, "{r}"),
Self::Timestamp(t) => writeln!(f, "@ {t}"),
Self::Text(t) => writeln!(f, "{t}"),
Self::Heading1(h) => writeln!(f, "# {h}"),
Self::Heading2(h) => writeln!(f, "## {h}"),
Self::Heading3(h) => writeln!(f, "### {h}"),
Self::Quote(q) => {
for l in q.lines() {
writeln!(f, "> {l}")?;
}
Ok(())
},
Self::Preformatted(p) => writeln!(f, "```\n{p}\n```"),
}
}
}
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
pub struct Message {
pub senders: Vec<Mailbox>,
pub recipients: Vec<Mailbox>,
pub timstamp: Option<String>,
pub body: String,
}
impl fmt::Display for Message {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if !self.senders.is_empty() {
write!(f, "< ")?;
self.senders.iter().try_for_each(|s| {
write!(f, "{s}\n")
})?;
}
if !self.recipients.is_empty() {
write!(f, ": ")?;
self.recipients.iter().try_for_each(|r| {
write!(f, " {r}")
})?;
write!(f, "\n")?;
}
write!(f, "{}\r\n", self.body)
}
}

View file

@ -2,6 +2,8 @@ pub use super::{
certificate_store::CertificateStore, certificate_store::CertificateStore,
fingerprint::{Error as FingerprintError, Fingerprint, GetFingerprint}, fingerprint::{Error as FingerprintError, Fingerprint, GetFingerprint},
host::{Error as ParseHostError, Host}, host::{Error as ParseHostError, Host},
mailbox::{Error as ParseMailboxError, Mailbox},
message::{Error as ParseMessageError, Lines, Message, Recipients},
//receiver, //receiver,
request::{Error as ParseRequestError, Request}, request::{Error as ParseRequestError, Request},
response::{Error as ParseResponseError, Response}, response::{Error as ParseResponseError, Response},