//! Parses the config files use super::*; use std::{ convert::TryFrom, marker::Unpin, }; use tokio::{ prelude::*, fs::File, io::AsyncRead, }; use sexp::{ Sexp, Atom, }; fn get_atom_string<'a>(maybe_atom: &'a Sexp) -> Result<&'a String, Error> { match maybe_atom { Sexp::Atom(Atom::S(string)) => Ok(string), opt => Err(Error::bad_type(LispType::String, opt)), } } #[inline] fn add_job(to: &mut Config, cdr: &[Sexp]) -> Result<(), Error> { to.job_dirs.push(PathBuf::from(get_atom_string(&cdr[0])?)); Ok(()) } #[inline] fn set_debug(to: &mut Config, cdr: &[Sexp]) -> Result<(), Error> { if !to.debug { let debug = get_atom_string(&cdr[0])?; to.debug = match debug.to_lowercase().trim() { "t" => true, "nil" => false, _ => return Err(Error::Unknown) }; } else { // Should be debug is set. return Err(Error::Unknown) } Ok(()) } #[inline] fn mwee(to: &mut Config, cdr: &[Sexp]) -> Result<(), Error> { println!("{:?}", cdr); //todo!() Ok(()) } /// Parse a single config file pub async fn global(to: &mut Config, path: impl AsRef) -> Result<(), error::Error> { let path = path.as_ref(); if path.exists() { let mut file = File::open(path).await?; let mut contents = if let Ok(Ok(wv)) = file.metadata().await .map(|x| x.len()) .map(|x| usize::try_from(x)) { let mut out = Vec::with_capacity(wv+3); out.push(b'('); out } else { vec![b'('] }; file.read_to_end(&mut contents).await?; contents.push(b')'); let parsed = sexp::parse(std::str::from_utf8(&contents[..])?)?; 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.try_get_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::UnknownDefinition(car.to_owned())), }?; } Ok(()) } else { Err(Error::NotFound(path.to_owned())) } }