install-framework-base 1.0.0

[Install Framework] Official generic interface implementation
Documentation
// Copyright 2021 Yuri6037

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:

// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.

// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.

use std::string::String;
use std::collections::HashMap;
use std::marker::PhantomData; //Because rust is a peace of shit
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);
    }
}