use std::string::String;
use std::collections::HashMap;
use std::marker::PhantomData; use std::path::PathBuf;
use std::path::Path;
use std::ffi::OsString;
#[cfg(not(feature="keep-cache"))]
use tempfile::tempdir;
#[cfg(not(feature="keep-cache"))]
use tempfile::TempDir;
#[cfg(feature="keep-cache")]
struct TempDir
{
path: PathBuf
}
#[cfg(feature="keep-cache")]
impl TempDir
{
pub fn path(&self) -> &Path
{
return &self.path;
}
}
#[cfg(feature="keep-cache")]
fn tempdir() -> std::io::Result<TempDir>
{
let path = Path::new(".").join("cache");
if path.exists()
{
std::fs::remove_dir_all(&path)?;
}
std::fs::create_dir(&path)?;
return Ok(TempDir
{
path: path
});
}
use crate::error::Error;
fn gen_cache<TError: Error>() -> Result<TempDir, TError::ErrorType>
{
let temp = match tempdir()
{
Ok(v) => v,
Err(e) => return Err(TError::io(e))
};
return Ok(temp);
}
pub struct Cache<TError: Error>
{
cached: Option<TempDir>,
cache: HashMap<usize, OsString>,
uselessbrokenrust: PhantomData<TError>
}
impl <TError: Error> Cache<TError>
{
pub fn new() -> Cache<TError>
{
return Cache
{
cached: None,
cache: HashMap::new(),
uselessbrokenrust: PhantomData
};
}
pub fn get_path(&mut self, path: &Path) -> Result<PathBuf, TError::ErrorType>
{
match &self.cached
{
Some(v) => return Ok(v.path().join(path)),
None =>
{
let dir = gen_cache::<TError>()?;
let res = dir.path().join(path);
self.cached = Some(dir);
return Ok(res);
}
}
}
pub fn insert<TVal: Into<OsString>>(&mut self, resid: usize, value: TVal)
{
self.cache.insert(resid, value.into());
}
pub fn get(&self, resid: usize) -> Result<&OsString, TError::ErrorType>
{
match self.cache.get(&resid)
{
None => return Err(TError::unknown_resource(resid)),
Some(v) => return Ok(v)
};
}
pub fn parse_string(&self, from: &str) -> Result<OsString, TError::ErrorType>
{
let mut s = OsString::new();
let mut resblk = false;
let mut tmp = String::new();
for c in from.chars()
{
let mut fuck = false;
if c == '%'
{
resblk = !resblk;
if !resblk
{
if tmp.starts_with("%res:")
{
let resid: usize = match tmp[5..tmp.len()].parse()
{
Ok(v) => v,
Err(e) => return Err(TError::parse_int(e))
};
if let Some(v) = self.cache.get(&resid)
{
s.push(v);
fuck = true;
}
else
{
return Err(TError::unknown_resource(resid))
}
}
else
{
s.push(&tmp);
}
tmp = String::new();
}
}
if resblk
{
tmp.push(c);
}
else
{
if !fuck
{
s.push(c.to_string());
}
}
}
return Ok(s);
}
}