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),
NotFound(PathBuf),
InvalidUtf8,
InvalidSexp,
TypeError{expected:LispType, got: LispType},
BadLength,
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
{
fn source(&self) -> Option<&(dyn std::error::Error + 'static)>
@ -33,9 +49,10 @@ impl std::fmt::Display for Error
match self {
Self::IO(io) => write!(f, "i/o error: {}", io),
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::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")
}
}
@ -67,7 +84,7 @@ impl From<Box<sexp::Error>> for Error
impl From<std::str::Utf8Error> for Error
{
fn from(from: std::str::Utf8Error) -> Self
fn from(_: std::str::Utf8Error) -> Self
{
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 format;
pub use format::*;
mod error;
pub use error::*;

@ -1,10 +1,13 @@
//! Parses the config files
use super::*;
use tokio::fs::File;
use tokio::prelude::*;
use std::{
convert::TryFrom,
};
use tokio::{
prelude::*,
fs::File,
};
use sexp::{
parse,
Sexp,
Atom,
};
@ -13,7 +16,7 @@ fn get_atom_string<'a>(maybe_atom: &'a Sexp) -> Result<&'a String, Error>
{
match &maybe_atom {
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]
fn mwee(to: &mut Config, cdr: &[Sexp]) -> Result<(), Error> {
println!("{:?}", cdr);
//todo!()
Ok(())
}
@ -54,44 +58,35 @@ pub async fn global(to: &mut Config, path: impl AsRef<Path>) -> Result<(), error
if path.exists() {
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?;
let parsed = sexp::parse(std::str::from_utf8(&contents[..])?)?;
if let Sexp::List(sexp) = parsed {
for sexp in sexp.into_iter() {
if let Sexp::List(sexp) = sexp {
let car = &sexp[0];
let cdr = &sexp[1..];
match car {
Sexp::List(_) => return Err(Error::InvalidSexp),
Sexp::Atom(car) => {
if let Atom::S(car) = car {
match car.to_lowercase().trim() {
"jobs-dir" => add_job(to, cdr),
"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);
let sexp = parsed.try_into_list()?;
for sexp in sexp.into_iter() {
let sexp = sexp.try_into_list()?;
let (car,cdr) = sexp.try_split()?;
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.to_lowercase().trim() {
"jobs-dir" => add_job(to, cdr),
"debug" => set_debug(to ,cdr),
"allow" => mwee(to, cdr),
"deny" => mwee(to, cdr),
_ => return Err(Error::Unknown),
}?;
}
Ok(())
Ok(())
} 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");
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?;

Loading…
Cancel
Save