//! Way of serialising multiple keys in file use super::*; use std::{ io, path::{ PathBuf, Path, }, marker::Unpin, fmt, error, }; use tokio::{ prelude::*, io::{ AsyncRead, AsyncWrite, }, fs::{ OpenOptions, }, }; /// An error type for serialisation or deserialisation #[derive(Debug)] pub enum SerdeError { Serialise(toml::ser::Error), Deserialise(toml::de::Error), IO(io::Error), } impl From for SerdeError { fn from(from: toml::ser::Error) -> Self { Self::Serialise(from) } } impl From for SerdeError { fn from(from: toml::de::Error) -> Self { Self::Deserialise(from) } } impl From for SerdeError { fn from(from: io::Error) -> Self { Self::IO(from) } } impl error::Error for SerdeError { fn source(&self) -> Option<&(dyn error::Error + 'static)> { match &self { Self::Serialise(s) => Some(s), Self::Deserialise(d) => Some(d), Self::IO(io) => Some(io), } } } impl fmt::Display for SerdeError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::Serialise(_) => write!(f, "writing failed"), Self::Deserialise(_) => write!(f, "reading failed"), Self::IO(_) => write!(f, "io error"), } } } /// Serialisable struct containing key file information #[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct Spec { rsa: Vec, rsa_sign: Vec, sign_all: Option, aes: Vec, } pub struct Signers<'a>(&'a Spec, usize); impl<'a> Iterator for Signers<'a> { type Item = &'a String; fn next(&mut self) -> Option { (if self.1 < self.0.rsa_sign.len() { Some(&self.0.rsa_sign[self.1]) } else if self.0.is_sign_all() { let rest = self.1 -self.0.rsa_sign.len(); if rest < self.0.rsa.len() { Some(&self.0.rsa[rest]) } else { None } } else { None }, self.1+=1).0 } fn size_hint(&self) -> (usize, Option) { let len = self.0.rsa_sign.len() + if self.0.is_sign_all() { self.0.rsa.len() } else { 0 }; (len, Some(len)) } } impl<'a> std::iter::ExactSizeIterator for Signers<'a>{} impl Spec { #[inline] fn is_sign_all(&self) -> bool { self.sign_all.unwrap_or(false) } pub fn new() -> Self { Self { rsa: Vec::new(), rsa_sign: Vec::new(), sign_all: Some(false), aes: Vec::new(), } } /// An iterator over all signers pub fn signers(&self) -> Signers<'_> { Signers(self, 0) } /// An iterator over all RSA encryptors pub fn rsa(&self) -> std::slice::Iter<'_, String> { self.rsa.iter() } /// An iterator over all AES encryptors pub fn aes(&self) -> std::slice::Iter<'_, String> { self.aes.iter() } /// Consume this instance into a `Normal` operation. /// /// # Panics /// If `op` is not `Normal` mode. pub fn into_operation(self, op: &mut Operation) { match op { Operation::Normal { rsa, aes, sign, auto_sign, .. } => { let sign_all = self.is_sign_all(); if *auto_sign == sign_all { // Both are true or both are false, no extra conversion needed sign.extend(self.rsa_sign.into_iter().map(PathBuf::from)); } else if sign_all { // Need to add `rsa` and `rsa_sign` to `sign`. sign.extend(self.rsa_sign.iter() .chain(self.rsa.iter()) .cloned() .map(PathBuf::from)); } rsa.extend(self.rsa.into_iter().map(PathBuf::from)); aes.extend(self.aes.into_iter().map(PathBuf::from)); }, _ => panic!("Tried to consume into an operation of invalid type"), } } /// Read an instance from a stream pub async fn read_from_stream(from: &mut S) -> eyre::Result { let mut output = Vec::with_capacity(4096); async fn internal(output: &mut Vec, from: &mut S) -> Result { let mut buffer = [0u8; 4096]; let mut read; while {read = from.read(&mut buffer[..]).await?; read>0} { output.extend_from_slice(&buffer[..read]); } Ok(toml::from_slice(&output[..])?) } internal(&mut output, from).await .with_section(move || String::from_utf8_lossy(&output[..]).to_string().header("Read contents was")) } /// Read an instance from a file pub async fn read_from_file>(from: P) -> eyre::Result { let mut file = OpenOptions::new() .read(true) .open(from.as_ref()).await?; Ok(Self::read_from_stream(&mut file).await .with_section(move || format!("{:?}", from.as_ref()).header("Filename was"))?) } }