//! Database manipulation stuffs use super::*; use std::{ path::{ PathBuf, }, error, fmt, io, marker::Unpin, }; /// An error in database operations #[derive(Debug)] #[non_exhaustive] pub enum Error { ExpectedLine(Option), IO(io::Error), Unknown, } impl error::Error for Error { fn source(&self) -> Option<&(dyn error::Error + 'static)> { match &self { Self::IO(io) => Some(io), _ => None, } } } impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Self::IO(_)=> write!(f, "i/o"), Self::ExpectedLine(None) => write!(f, "expected a line that was not present in the file"), Self::ExpectedLine(Some(msg)) => write!(f, "{}", msg), _ => write!(f, "unknown"), } } } /// Contains Videl information for a database directory #[derive(Debug, Clone, PartialEq, Ord, Eq, PartialOrd, Hash)] pub struct Database { pub path: PathBuf, } impl Database { /// Create a new database for this path pub fn new(path: PathBuf) -> Self { Self { path, } } /// Save this database to a stream pub async fn save(&self, stream: &mut T) -> Result { let bytes = resolve::path_bytes(&self.path); stream.write_all(&bytes[..]).await?; stream.write_u8(b'\n').await?; Ok(bytes.len() + 1) } } /// Load database info from this file pub async fn load(stream: &mut T) -> Result { let mut buffer = String::new(); macro_rules! line { ($message:literal $($tt:tt)*) => { { buffer.clear(); let read = stream.read_line(&mut buffer).await?; if read == 0 { return Err(Error::ExpectedLine(Some(format!($message $($tt)*)))); } &buffer[..] } } } let location_encoded = line!("expected the location line"); Ok(Database{ path: PathBuf::from(location_encoded), }) } impl From for Error { #[inline] fn from(from: io::Error) -> Self { Self::IO(from) } }