use super::*; use std::{ error, fmt, }; use std::ffi::OsStr; /// Builder for creating [`Entry`] instances. #[derive(Debug, Clone, Eq, PartialEq, Hash, Default)] pub struct EntryBuilder<'a> { name: Option<&'a str>, desc: Option<&'a str>, tags: Option<&'a[&'a str]>, key: Option, hash: Option, location: Option<&'a Path>, filename: Option<&'a OsStr>, } macro_rules! build_fn { ($name:ident: $ty:ty $(, $com:literal)?) => { $(#[doc=$com])? #[inline] pub const fn $name(self, $name: $ty) -> Self { Self { $name: Some($name), ..self } } }; } impl<'a> EntryBuilder<'a> { /// Create a new entry builder #[inline] pub const fn new() -> Self { macro_rules! default { ($($name:ident),*) => { Self { $( $name: None ),* } } } default!{ name, desc, tags, key, hash, location, filename } } build_fn!(name: &'a str, "Insert the name of this entry"); build_fn!(desc: &'a str, "Insert a description for this entry"); build_fn!(tags: &'a [&'a str], "Insert the tags for this entry"); build_fn!(key: aes::AesKey, "Insert the encryption key for this entry"); build_fn!(hash: sha256::Sha256Hash, "Insert the hash for this entry"); build_fn!(location: &'a Path, "Insert the location for this entry"); build_fn!(filename: &'a OsStr, "Insert the original filename for this entry"); /// Try to build an `Entry` from this builder. #[inline] pub fn build(self) -> Result { macro_rules! fail_on { ($name:ident) => { self.$name.ok_or(EntryBuildError)? }; ($name:ident: $or:expr) =>{ if let Some(name) = self.$name { name } else { $or } }; } Ok( Entry { name: fail_on!(name).into(), description: fail_on!(desc: "").into(), tags: fail_on!(tags: &[]).iter().map(|&x| x.to_owned()).collect(), key: self.key, hash: fail_on!(hash), location: fail_on!(location).into(), filename: fail_on!(filename: OsStr::new("")).into(), cache: Default::default(), } ) } } /// Error for when an improporly configured [`EntryBuilder`] called `.build()`. /// Usually this is because of missing fields. #[derive(Debug)] pub struct EntryBuildError; impl error::Error for EntryBuildError{} impl fmt::Display for EntryBuildError { #[inline] fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "improporly configured builder") } }