install-framework-core 1.0.0

[Install Framework] Core framework and basic interfaces
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::collections::HashMap;
use std::collections::VecDeque;

pub trait Interpreter<TCommand>
{
    type ErrorType;

    /// Execute a command
    ///
    /// # Arguments
    ///
    /// * `resid` - Resource id of the command to be processed
    /// * `cmd` - The command to execute
    fn execute(&mut self, resid: usize, cmd: TCommand) -> Result<(), Self::ErrorType>;

    /// Called to let a chance to handle execution progress
    ///
    /// # Arguments
    ///
    /// * `curcmd` - Current number of commands executed
    /// * `maxcmd` - Maximum number of commands to execute
    fn progress(&mut self, curcmd: usize, maxcmd: usize) -> Result<(), Self::ErrorType>;
}

pub struct CommandQueue<TCommand>
{
    queue: VecDeque<(usize, TCommand)>,
    cur_resource_id: usize
}

impl <TCommand> CommandQueue<TCommand>
{
    pub fn new(cur_resource_id: usize) -> CommandQueue<TCommand>
    {
        return CommandQueue
        {
            queue: VecDeque::new(),
            cur_resource_id: cur_resource_id
        };
    }

    /// Execute all commands contained in this command queue with the given interpreter
    ///
    /// # Arguments
    ///
    /// * `interpreter` - The command interpreter
    pub fn run<TInterpreter: Interpreter<TCommand>>(&mut self, interpreter: &mut TInterpreter) -> Result<(), TInterpreter::ErrorType>
    {
        let mut cur = 0;
        let max = self.queue.len();
        while let Some((resid, cmd)) = self.queue.pop_front()
        {
            interpreter.execute(resid, cmd)?;
            interpreter.progress(cur, max)?;
            cur += 1;
        }
        return Ok(());
    }

    /// Push a new command into this command queue
    ///
    /// # Arguments
    ///
    /// * `resid` - Resource id of the command to be processed
    /// * `cmd` - The command to execute
    /// 
    /// # Returns
    /// 
    /// command resource id to reference the output in subsequent commands
    pub fn push(&mut self, cmd: TCommand) -> usize
    {
        self.cur_resource_id += 1;
        self.queue.push_back((self.cur_resource_id, cmd));
        return self.cur_resource_id;
    }

    /// Gets the last resource index
    pub fn get_last_resource_id(&self) -> usize
    {
        return self.cur_resource_id;
    }
}

pub enum InitCommand
{
    /// Instructs to download a file into cache
    /// 
    /// #### Arguments
    /// * filename,
    /// * url,
    /// * headers
    DownloadFile(String, String, HashMap<String, String>),

    /// Instructs to unpack an archive file from cache
    /// 
    /// #### Arguments
    /// * path in cache (use %res:<id>% to mension a file contained in a subfolder in the cache)
    UnpackCached(String),

    /// Instructs to extract a file contained in this installer's resources to the cache
    /// 
    /// #### Arguments
    /// * resource name/path
    ExtractResource(&'static str),

    /// Instructs to ask the user for input
    /// 
    /// #### Arguments
    /// * property name
    /// * input message
    UserInput(String, String)
}

pub enum InstallCommand
{
    /// Instructs to download a file into cache
    /// 
    /// #### Arguments
    /// * filename,
    /// * url,
    /// * headers
    DownloadFile(String, String, HashMap<String, String>),

    /// Instructs to unpack an archive file from cache
    /// 
    /// #### Arguments
    /// * path in cache (use %res:<id>% to mension a file contained in a subfolder in the cache)
    UnpackCached(String),

    /// Instructs to extract a file contained in this installer's resources to the cache
    /// 
    /// #### Arguments
    /// * resource name/path
    ExtractResource(&'static str),

    /// Instructs to ask the user for input
    /// 
    /// #### Arguments
    /// * property name
    /// * input message
    UserInput(String, String),

    /// Instructs to install a file contained in this installer's resources
    /// 
    /// #### Arguments
    /// * resource name/path,
    /// * target folder resource id (0 = main content directory)
    InstallResource(&'static str, usize),

    /// Instructs to create a folder
    /// 
    /// #### Arguments
    /// * folder name
    CreateFolder(String),

    /// Instructs to add a binary file to the PATH
    /// 
    /// #### Arguments
    /// * path to file relative to content directory
    AddToPath(String),

    /// Instructs to install a file or folder from cache
    /// 
    /// #### Arguments
    /// * path in cache (use %res:<id>% to mension a file contained in a subfolder in the cache),
    /// * target folder resource id (0 = main content directory)
    InstallCached(String, usize),

    /// Instructs to create a shortcut to run a GUI application
    /// 
    /// #### Arguments
    /// * path to file relative to content directory
    AddShortcut(String)
}