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.
videl/src/database.rs

100 lines
2.0 KiB

//! 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<String>),
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<T: AsyncWrite + Unpin + ?Sized>(&self, stream: &mut T) -> Result<usize, Error>
{
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<T: AsyncBufRead + Unpin + ?Sized>(stream: &mut T) -> Result<Database, Error>
{
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<io::Error> for Error
{
#[inline] fn from(from: io::Error) -> Self
{
Self::IO(from)
}
}