Added Connection and connection::Builder; Fixed a lot of Clippy lints;

This commit is contained in:
Nathan Fisher 2023-05-29 11:33:36 -04:00
parent c9eb30f4e7
commit 477de69ca3
13 changed files with 89 additions and 41 deletions

35
src/connection/builder.rs Normal file
View file

@ -0,0 +1,35 @@
use super::verifier::Verifier;
use crate::prelude::CertificateStore;
use std::net::TcpStream;
#[derive(Debug)]
pub struct Builder<S: CertificateStore> {
pub stream: Option<TcpStream>,
pub verifier: Option<Verifier<S>>,
}
impl<S: CertificateStore> Default for Builder<S> {
fn default() -> Self {
Self { stream: None, verifier: None }
}
}
impl<S: CertificateStore> Builder<S> {
pub fn new() -> Self {
Self::default()
}
pub fn stream(mut self, stream: TcpStream) -> Self {
self.stream = Some(stream);
self
}
pub fn verifier(mut self, verifier: Verifier<S>) -> Self {
self.verifier = Some(verifier);
self
}
pub fn build(self) -> super::Connection {
todo!()
}
}

1
src/connection/error.rs Normal file
View file

@ -0,0 +1 @@

8
src/connection/mod.rs Normal file
View file

@ -0,0 +1,8 @@
pub mod builder;
pub mod error;
pub mod verifier;
#[derive(Debug)]
pub struct Connection {
pub inner: rustls::ServerConnection,
}

View file

@ -0,0 +1,7 @@
use crate::prelude::CertificateStore;
use std::sync::Mutex;
#[derive(Debug)]
pub struct Verifier<S: CertificateStore> {
pub store: Mutex<S>,
}

View file

@ -31,7 +31,7 @@ impl GetFingerprint for Certificate {
subject.iter_common_name().for_each(|n| {
let mut val = n.attr_value().data;
let mut name = String::new();
if let Ok(_) = val.read_to_string(&mut name) {
if val.read_to_string(&mut name).is_ok() {
names.push(name);
}
});

View file

@ -80,7 +80,7 @@ impl ToSocketAddrs for Host {
type Iter = std::vec::IntoIter<SocketAddr>;
fn to_socket_addrs(&self) -> std::io::Result<Self::Iter> {
format!("{}:1958", self).to_socket_addrs()
format!("{self}:1958").to_socket_addrs()
}
}

View file

@ -1,5 +1,6 @@
#![warn(clippy::all, clippy::pedantic)]
pub mod certificate;
pub mod connection;
pub mod fingerprint;
pub mod host;
pub mod mailbox;

View file

@ -33,23 +33,22 @@ impl FromStr for Mailbox {
if let Some((username, mut host)) = s.split_once('@') {
if username.is_empty() {
Err(Error::EmptyUser)
} else if username.contains(|c: char| c.is_whitespace()) {
} else if username.contains(char::is_whitespace) {
Err(Error::IllegalWhitespace)
} else {
let username = username.to_string();
if let Some((h, b)) = host.split_once(|c: char| c.is_whitespace()) {
if let Some((h, b)) = host.split_once(char::is_whitespace) {
if h.is_empty() {
return Err(Error::EmptyHost);
} else if h.contains(|c: char| c.is_whitespace()) {
} else if h.contains(char::is_whitespace) {
return Err(Error::IllegalWhitespace);
} else {
host = h;
if !b.is_empty() {
if b.contains("\n") {
return Err(Error::IllegalWhitespace);
}
blurb = Some(b.to_string());
}
host = h;
if !b.is_empty() {
if b.contains('\n') {
return Err(Error::IllegalWhitespace);
}
blurb = Some(b.to_string());
}
}
let host = host.parse()?;

View file

@ -4,7 +4,6 @@ use std::{
io::{self, Write},
os::unix::fs::DirBuilderExt,
path::PathBuf,
process::id,
};
pub trait MultiDomain: MailStore {
@ -39,7 +38,7 @@ impl MailStore for Filesystem {
fn has_mailuser(&self, mailuser: &str) -> bool {
if let Some((user, host)) = mailuser.rsplit_once('@') {
let mut path = self.path.clone();
if host.contains('.') && !host.contains(|c: char| c.is_whitespace()) {
if host.contains('.') && !host.contains(char::is_whitespace) {
path.push(host);
path.push(user);
return path.exists();
@ -63,7 +62,7 @@ impl MailStore for Filesystem {
name: folder.to_string(),
messages: HashMap::new(),
};
dir.filter(|x| x.is_ok()).map(|x| x.unwrap()).for_each(|e| {
dir.filter_map(Result::ok).for_each(|e| {
if let Ok(contents) = fs::read_to_string(e.path()) {
if let Ok(message) = contents.parse::<Message>() {
folder.messages.insert(message.id.clone(), message);
@ -77,7 +76,7 @@ impl MailStore for Filesystem {
self.get_folder(user, folder).and_then(|f| {
f.messages
.values()
.find(|m| m.title.as_ref().map(|x| x.as_str()) == Some(title))
.find(|m| m.title.as_ref().map(String::as_str) == Some(title))
.cloned()
})
}
@ -172,7 +171,7 @@ impl MultiDomain for Filesystem {
if !path.exists() {
fs::DirBuilder::new()
.recursive(true)
.mode(700)
.mode(0o700)
.create(path)?;
}
Ok(())

View file

@ -1,6 +1,6 @@
#![allow(unused_variables)]
use crate::prelude::{Host, Mailbox, Mailuser, Message, ParseMailboxError};
use std::{collections::HashMap, convert::Infallible, io, str::FromStr};
use crate::prelude::{Host, Mailbox, Mailuser, Message};
use std::{collections::HashMap, io, str::FromStr};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
@ -88,8 +88,7 @@ impl MailStore for Domain {
fn has_mailuser(&self, mailuser: &str) -> bool {
self.users()
.iter()
.find(|x| x.username == mailuser)
.is_some()
.any(|x| x.username == mailuser)
}
fn get_folder(&self, user: &str, folder: &str) -> Option<Folder> {
@ -106,7 +105,7 @@ impl MailStore for Domain {
u.folders.get(folder).and_then(|f| {
f.messages
.values()
.find(|m| m.title.as_ref().map(|x| x.as_str()) == Some(title))
.find(|m| m.title.as_ref().map(String::as_str) == Some(title))
})
})
.cloned()
@ -126,7 +125,7 @@ impl MailStore for Domain {
if self.users.contains_key(user) {
return Ok(());
}
let mbox = Mailbox::from_str(&format!("{user}@{}", self.host.to_string()))
let mbox = Mailbox::from_str(&format!("{user}@{}", self.host))
.map_err(|e| io::Error::new(io::ErrorKind::Other, format!("{e}")))?;
let folders = HashMap::new();
let acct = Account {

View file

@ -68,12 +68,12 @@ 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"))?;
self.senders.iter().try_for_each(|s| writeln!(f, "{s}"))?;
}
if !self.recipients.is_empty() {
write!(f, ": ")?;
self.recipients.iter().try_for_each(|r| write!(f, " {r}"))?;
write!(f, "\n")?;
writeln!(f)?;
}
write!(f, "{}\r\n", self.body)
}

View file

@ -49,8 +49,8 @@ impl Request {
pub fn recipients(&self) -> Vec<Mailuser> {
let mut recipients = vec![];
self.message.lines().for_each(|l| {
if l.starts_with(':') {
l[1..].trim().split_whitespace().for_each(|u| {
if let Some(s) = l.strip_prefix(':') {
s.split_whitespace().for_each(|u| {
if let Ok(user) = u.parse() {
recipients.push(user);
}
@ -63,8 +63,8 @@ impl Request {
pub fn senders(&self) -> Vec<Mailbox> {
let mut senders = vec![];
self.message.lines().for_each(|l| {
if l.starts_with('<') {
if let Ok(mbox) = l[1..].trim().parse() {
if let Some(s) = l.strip_prefix('<') {
if let Ok(mbox) = s.trim().parse() {
senders.push(mbox);
}
}
@ -73,13 +73,12 @@ impl Request {
}
pub fn timestamp(&self) -> Option<String> {
let mut ts = None;
self.message.lines().for_each(|l| {
if l.starts_with('@') {
ts = Some(l[1..].trim().to_string());
for l in self.message.lines() {
if let Some(s) = l.strip_prefix('@') {
return Some(s.trim().to_string());
}
});
ts
}
None
}
}

View file

@ -9,15 +9,15 @@ use {
#[derive(Debug)]
/// A verifier is used to verify certificates sent by the receiving server
/// during the tls handshake. For convenience the [CertificateStore] trait
/// is implemented for [std::collections::HashMap<String, String>] and
/// [std::collections::BTreeMap<String, String>], so a Verifier can easily
/// during the tls handshake. For convenience the [`CertificateStore`] trait
/// is implemented for [`std::collections::HashMap<String, String>`] and
/// [`std::collections::BTreeMap<String, String>`], so a Verifier can easily
/// be constructed from those types.
///
/// This type is passed to [rustls::client::DangerousClientConfig::set_certificate_verifier]
/// This type is passed to [`rustls::client::DangerousClientConfig::set_certificate_verifier`]
/// in order to allow Tofu certificate validation.
/// # Examples
/// Create a Verifier from a HashMap
/// Create a Verifier from a `HashMap`
/// ```
/// use std::collections::HashMap;
/// use dory::prelude::{CertificateStore, Verifier};
@ -70,7 +70,7 @@ impl<S: CertificateStore> ServerCertVerifier for Verifier<S> {
.borrow_mut()
.insert_certificate(&name, &fp.fingerprint);
}
return Ok(ServerCertVerified::assertion());
Ok(ServerCertVerified::assertion())
}
}
}