You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
108 lines
2.5 KiB
108 lines
2.5 KiB
4 years ago
|
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<aes::AesKey>,
|
||
|
hash: Option<sha256::Sha256Hash>,
|
||
|
|
||
|
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<Entry, EntryBuildError>
|
||
|
{
|
||
|
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")
|
||
|
}
|
||
|
}
|