more specific error

master
Avril 4 years ago
parent ee355f088a
commit 79250c9b36
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -11,10 +11,26 @@ pub enum Error {
Syntax(sexp::Error), Syntax(sexp::Error),
NotFound(PathBuf), NotFound(PathBuf),
InvalidUtf8, InvalidUtf8,
InvalidSexp, TypeError{expected:LispType, got: LispType},
BadLength,
Unknown, Unknown,
} }
impl Error
{
/// Helper function for type errors
#[inline]
pub fn bad_type<T,U>(expected: T, got: U) -> Self
where T: Into<LispType>,
U: Into<LispType>
{
Self::TypeError {
expected: expected.into(),
got: got.into()
}
}
}
impl std::error::Error for Error impl std::error::Error for Error
{ {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> fn source(&self) -> Option<&(dyn std::error::Error + 'static)>
@ -33,9 +49,10 @@ impl std::fmt::Display for Error
match self { match self {
Self::IO(io) => write!(f, "i/o error: {}", io), Self::IO(io) => write!(f, "i/o error: {}", io),
Self::Syntax(sy) => write!(f, "s-expression syntax error: {}", sy), Self::Syntax(sy) => write!(f, "s-expression syntax error: {}", sy),
Self::NotFound(path) => write!(f, "File not found: {:?}", path), Self::NotFound(path) => write!(f, "File not found: {:?}", path),
Self::InvalidUtf8 => write!(f, "Invalid UTF8 decoded string or some such"), Self::InvalidUtf8 => write!(f, "Invalid UTF8 decoded string or some such"),
Self::InvalidSexp => write!(f, "Invalid s-expression"), Self::TypeError{expected, got} => write!(f, "Type mismatch: Expected {}, got {}", expected, got),
Self::BadLength => write!(f, "expected at least 1 element"),
_ => write!(f, "unknown error") _ => write!(f, "unknown error")
} }
} }
@ -67,7 +84,7 @@ impl From<Box<sexp::Error>> for Error
impl From<std::str::Utf8Error> for Error impl From<std::str::Utf8Error> for Error
{ {
fn from(from: std::str::Utf8Error) -> Self fn from(_: std::str::Utf8Error) -> Self
{ {
Self::InvalidUtf8 Self::InvalidUtf8
} }

@ -0,0 +1,177 @@
//! Formatting specifiers for the config file format
use super::*;
use sexp::{
Sexp,
Atom,
};
/// A valid type in the config file
#[derive(Debug)]
pub enum LispType
{
List,
String,
Integer,
Float,
Atom,
}
impl From<Sexp> for LispType
{
fn from(from: Sexp) -> Self
{
match from {
Sexp::Atom(atom) => atom.into(),
Sexp::List(_) => Self::List
}
}
}
impl From<Atom> for LispType
{
fn from(from: Atom) -> Self
{
match from {
Atom::F(_) => Self::Float,
Atom::I(_) => Self::Integer,
Atom::S(_) => Self::String,
}
}
}
impl<T> From<Result<T, Error>> for LispType
where T: Into<LispType>
{
fn from(from: Result<T, Error>) -> Self
{
match from {
Ok(value) => value.into(),
Err(Error::TypeError{got,..}) => got,
_ => unreachable!("you shouldn't use this here"),
}
}
}
impl std::fmt::Display for LispType
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
f.write_str(match self {
Self::List => "list",
Self::String => "string",
Self::Integer => "integer",
Self::Float => "float",
Self::Atom => "atom",
})
}
}
pub trait LispExt
{
/// Try to get `car` and `cdr`
fn try_split<'a>(&'a self) -> Result<(&'a Sexp, &'a [Sexp]), Error>;
}
impl LispExt for Vec<Sexp>
{
fn try_split<'a>(&'a self) -> Result<(&'a Sexp, &'a [Sexp]), Error>
{
if self.len() > 1 {
Ok((&self[0], &self[1..]))
} else if self.len() > 0{
Ok((&self[0], &[]))
} else {
Err(Error::BadLength)
}
}
}
// Sexp doesn't use try_from(), so...
pub trait TryIntoExt: Sized
{
fn try_into_list(self) -> Result<Vec<Sexp>, Error>;
fn try_into_atom(self) -> Result<Atom, Error>;
fn try_into_string(self) -> Result<String, Error>;
fn try_into_int(self) -> Result<i64, Error>;
fn try_into_float(self) -> Result<f64, Error>;
}
impl TryIntoExt for Sexp
{
fn try_into_list(self) -> Result<Vec<Sexp>, Error>
{
match self {
Sexp::List(this) => Ok(this),
other => Err(Error::bad_type(LispType::List, other)),
}
}
fn try_into_atom(self) -> Result<Atom, Error>
{
match self {
Sexp::Atom(this) => Ok(this),
other => Err(Error::bad_type(LispType::Atom, other)),
}
}
fn try_into_string(self) -> Result<String, Error>
{
match self.try_into_atom() {
Ok(Atom::S(this)) => Ok(this),
other => Err(Error::bad_type(LispType::String, other)),
}
}
fn try_into_int(self) -> Result<i64, Error>
{
match self.try_into_atom() {
Ok(Atom::I(this)) => Ok(this),
other => Err(Error::bad_type(LispType::Integer, other)),
}
}
fn try_into_float(self) -> Result<f64, Error>
{
match self.try_into_atom() {
Ok(Atom::F(this)) => Ok(this),
other => Err(Error::bad_type(LispType::Float, other)),
}
}
}
impl TryIntoExt for Atom
{
#[inline]
fn try_into_list(self) -> Result<Vec<Sexp>, Error>
{
Err(Error::bad_type(LispType::List, self))
}
#[inline]
fn try_into_atom(self) -> Result<Atom, Error>
{
Ok(self)
}
fn try_into_string(self) -> Result<String, Error>
{
match self {
Atom::S(this) => Ok(this),
other => Err(Error::bad_type(LispType::String, other)),
}
}
fn try_into_int(self) -> Result<i64, Error>
{
match self {
Atom::I(this) => Ok(this),
other => Err(Error::bad_type(LispType::Integer, other)),
}
}
fn try_into_float(self) -> Result<f64, Error>
{
match self {
Atom::F(this) => Ok(this),
other => Err(Error::bad_type(LispType::Float, other)),
}
}
}

@ -9,6 +9,10 @@ use std::{
}; };
mod parse; mod parse;
mod format;
pub use format::*;
mod error; mod error;
pub use error::*; pub use error::*;

@ -1,10 +1,13 @@
//! Parses the config files //! Parses the config files
use super::*; use super::*;
use std::{
use tokio::fs::File; convert::TryFrom,
use tokio::prelude::*; };
use tokio::{
prelude::*,
fs::File,
};
use sexp::{ use sexp::{
parse,
Sexp, Sexp,
Atom, Atom,
}; };
@ -13,7 +16,7 @@ fn get_atom_string<'a>(maybe_atom: &'a Sexp) -> Result<&'a String, Error>
{ {
match &maybe_atom { match &maybe_atom {
Sexp::Atom(Atom::S(string)) => Ok(string), Sexp::Atom(Atom::S(string)) => Ok(string),
_ => Err(Error::InvalidSexp), &opt => Err(Error::bad_type(LispType::String, opt.to_owned())),
} }
} }
@ -44,6 +47,7 @@ fn set_debug(to: &mut Config, cdr: &[Sexp]) -> Result<(), Error> {
#[inline] #[inline]
fn mwee(to: &mut Config, cdr: &[Sexp]) -> Result<(), Error> { fn mwee(to: &mut Config, cdr: &[Sexp]) -> Result<(), Error> {
println!("{:?}", cdr); println!("{:?}", cdr);
//todo!()
Ok(()) Ok(())
} }
@ -54,44 +58,35 @@ pub async fn global(to: &mut Config, path: impl AsRef<Path>) -> Result<(), error
if path.exists() { if path.exists() {
let mut file = File::open(path).await?; let mut file = File::open(path).await?;
let mut contents = vec![]; let mut contents = if let Ok(Ok(wv)) = file.metadata().await
.map(|x| x.len())
.map(|x| usize::try_from(x)) {
Vec::with_capacity(wv)
} else {
Vec::new()
};
file.read_to_end(&mut contents).await?; file.read_to_end(&mut contents).await?;
let parsed = sexp::parse(std::str::from_utf8(&contents[..])?)?; let parsed = sexp::parse(std::str::from_utf8(&contents[..])?)?;
if let Sexp::List(sexp) = parsed { let sexp = parsed.try_into_list()?;
for sexp in sexp.into_iter() { for sexp in sexp.into_iter() {
if let Sexp::List(sexp) = sexp { let sexp = sexp.try_into_list()?;
let car = &sexp[0]; let (car,cdr) = sexp.try_split()?;
let cdr = &sexp[1..]; let car = car.clone()/* <- i'm too lazy to make ref versions of these `try_into_*` functions, so this will do*/.try_into_string()?;
match car { match car.to_lowercase().trim() {
Sexp::List(_) => return Err(Error::InvalidSexp), "jobs-dir" => add_job(to, cdr),
Sexp::Atom(car) => { "debug" => set_debug(to ,cdr),
if let Atom::S(car) = car { "allow" => mwee(to, cdr),
match car.to_lowercase().trim() { "deny" => mwee(to, cdr),
"jobs-dir" => add_job(to, cdr), _ => return Err(Error::Unknown),
"debug" => set_debug(to ,cdr), }?;
"allow" => mwee(to, cdr),
"deny" => mwee(to, cdr),
_ => return Err(Error::Unknown),
}?;
} else {
return Err(Error::InvalidSexp);
}
}
}
}
else {
return Err(Error::InvalidSexp);
}
}
} else {
return Err(Error::InvalidSexp);
} }
Ok(())
Ok(())
} else { } else {
return Err(Error::NotFound(path.to_owned())); Err(Error::NotFound(path.to_owned()))
} }
} }

@ -62,7 +62,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
debug!("Initialised"); debug!("Initialised");
println!("{:?}", config::parse_global_single("/home/manx/flon.txt").await.expect("Waaaaaah")); println!("{:?}", config::parse_global_single("example.rori").await.expect("Waaaaaah"));
//let (mut tx, h) = do_thing_every().await?; //let (mut tx, h) = do_thing_every().await?;

Loading…
Cancel
Save