<commit_before>extern crate regex;
extern crate toml;

use self::regex::Error as RegexError;
use self::toml::ParserError as ParseTomlError;

use constant::{self, ME};
use std::num::ParseIntError;
use std::error::Error;
use std::fmt::{Display, Formatter, Result as FmtResult};
use std::io::Error as IoError;

#[derive(Debug)]
pub enum CliError {
    Config(ConfigError),
    Cron(CronError),
    Essential(EssentialLack),
    Io(IoError),
    ParseInt(ParseIntError),
    ParseToml(ParseTomlError),
    Regex(RegexError),
    RunningPlace(RunningPlaceError),
    Usage(Usage),
}
impl Display for CliError {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        match *self {
            CliError::Config(ref e)       => e.fmt(f),
            CliError::Cron(ref e)         => e.fmt(f),
            CliError::Essential(ref e)    => e.fmt(f),
            CliError::Io(ref e)           => e.fmt(f),
            CliError::ParseInt(ref e)     => e.fmt(f),
            CliError::ParseToml(ref e)    => e.fmt(f),
            CliError::Regex(ref e)        => e.fmt(f),
            CliError::RunningPlace(ref e) => e.fmt(f),
            CliError::Usage(ref u)        => u.fmt(f),
        }
    }
}
impl Error for CliError {
    fn cause(&self) -> Option<&Error> {
        match *self {
            CliError::Config(ref e)       => Some(e),
            CliError::Cron(ref e)         => Some(e),
            CliError::Essential(ref e)    => Some(e),
            CliError::Io(ref e)           => Some(e),
            CliError::ParseInt(ref e)     => Some(e),
            CliError::ParseToml(ref e)    => Some(e),
            CliError::Regex(ref e)        => Some(e),
            CliError::RunningPlace(ref e) => Some(e),
            CliError::Usage(ref u)        => Some(u),
        }
    }

    fn description(&self) -> &str {
        match *self {
            CliError::Config(ref e)       => e.description(),
            CliError::Cron(ref e)         => e.description(),
            CliError::Essential(ref e)    => e.description(),
            CliError::Io(ref e)           => e.description(),
            CliError::ParseInt(ref e)     => e.description(),
            CliError::ParseToml(ref e)    => e.description(),
            CliError::Regex(ref e)        => e.description(),
            CliError::RunningPlace(ref e) => e.description(),
            CliError::Usage(ref u)        => u.description(),
        }
    }
}
impl From<ConfigError> for CliError {
    fn from(e: ConfigError) -> CliError {
        CliError::Config(e)
    }
}
impl From<CronError> for CliError {
    fn from(e: CronError) -> CliError {
        CliError::Cron(e)
    }
}
impl From<EssentialLack> for CliError {
    fn from(e: EssentialLack) -> CliError {
        CliError::Essential(e)
    }
}
impl From<IoError> for CliError {
    fn from(e: IoError) -> CliError {
        CliError::Io(e)
    }
}
impl From<ParseIntError> for CliError {
    fn from(e: ParseIntError) -> CliError {
        CliError::ParseInt(e)
    }
}
impl From<ParseTomlError> for CliError {
    fn from(e: ParseTomlError) -> CliError {
        CliError::ParseToml(e)
    }
}
impl From<RegexError> for CliError {
    fn from(e: RegexError) -> CliError {
        CliError::Regex(e)
    }
}
impl From<RunningPlaceError> for CliError {
    fn from(e: RunningPlaceError) -> CliError {
        CliError::RunningPlace(e)
    }
}
impl From<Usage> for CliError {
    fn from(u: Usage) -> CliError {
        CliError::Usage(u)
    }
}

#[derive(Debug, PartialEq)]
pub enum ConfigErrorKind {
    Something,
    InvalidKey,
    NonStringValue,
    NotFoundBurnMoratorium,
    NotFoundSweepMoratorium,
    NotFoundSweepPeriod,
    NotFoundSweepTime,
    BurnMoratorium,
    SweepMoratorium,
    SweepPeriod,
    SweepTime,
}
#[derive(Debug, PartialEq)]
pub struct ConfigError {
    kind: ConfigErrorKind,
}
impl ConfigError {
    pub fn new(kind: ConfigErrorKind) -> ConfigError {
        ConfigError { kind: kind }
    }
}
impl Display for ConfigError {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        write!(f, "{}", match self.kind {
            ConfigErrorKind::Something               => r#"Something went to wrong"#,
            ConfigErrorKind::InvalidKey              => r#"Cannot set this key"#,
            ConfigErrorKind::NonStringValue          => r#"Please set values as "String""#,
            ConfigErrorKind::NotFoundBurnMoratorium  => r#"Please set [burn]moratorium param"#,
            ConfigErrorKind::NotFoundSweepMoratorium => r#"Please set [sweep]moratorium param"#,
            ConfigErrorKind::NotFoundSweepPeriod     => r#"Please set [sweep]period param"#,
            ConfigErrorKind::NotFoundSweepTime       => r#"Please set [sweep]time param"#,
            ConfigErrorKind::BurnMoratorium          => r#"Please set value like "3days" or "1week" as "[burn]moratorium""#,
            ConfigErrorKind::SweepMoratorium         => r#"Please set value like "10hours" or "1week" as "[sweep]moratorium""#,
            ConfigErrorKind::SweepPeriod             => r#"Please set "daily" or "weekly" as "[sweep]period""#,
            ConfigErrorKind::SweepTime               => r#"Please set value from "00:00" to "23:59" as "[sweep]time""#,
        })
    }
}
impl Error for ConfigError {
    fn description(&self) -> &str { "invalid parameters" }
}

#[derive(Debug, PartialEq)]
pub enum CronErrorKind {
    BinExistsInInvalidDir,
    InvalidCharacterCode,
    InvalidPath,
    FailedToWrite,
}
#[derive(Debug, PartialEq)]
pub struct CronError {
    kind: CronErrorKind,
}
impl CronError {
    pub fn new(kind: CronErrorKind) -> Self {
        CronError { kind: kind }
    }
}
impl Display for CronError {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        write!(f, "{}", match self.kind {
            CronErrorKind::BinExistsInInvalidDir => "The \"bin\" exists in directory whose path include non-UTF-8 charecter code",
            CronErrorKind::InvalidCharacterCode  => "The \"cron\" file consists of non-UTF-8 character code",
            CronErrorKind::InvalidPath           => "The path to current directory include non-UTF-8 character code",
            CronErrorKind::FailedToWrite         => "Failed to write new \"cron\" file"
        })
    }
}
impl Error for CronError {
    fn description(&self) -> &str { "problems around cron" }
}

#[derive(Debug, PartialEq)]
pub enum EssentialKind {
    WorkingDir,
    StorageDir,
    ConfigFile,
    IgnoreFile,
}
#[derive(Debug, PartialEq)]
pub struct EssentialLack {
    what: EssentialKind,
}
impl EssentialLack {
    pub fn new(what: EssentialKind) -> EssentialLack {
        EssentialLack { what: what }
    }
}
impl Display for EssentialLack {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        write!(f, "{} does not exist", match self.what {
            EssentialKind::WorkingDir => format!("\"{}\" directory", constant::WORKING_DIR_NAME),
            EssentialKind::StorageDir => format!("\"{}\" directory", constant::STORAGE_DIR_NAME),
            EssentialKind::ConfigFile => format!("\"{}\" file"     , constant::CONFIG_FILE_NAME),
            EssentialKind::IgnoreFile => format!("\"{}\" file"     , constant::IGNORE_FILE_NAME),
        })
    }
}
impl Error for EssentialLack {
    fn description(&self) -> &str { "essential file does not exist" }
}

#[derive(Debug, PartialEq)]
pub struct RunningPlaceError {
    dir: String,
}
impl RunningPlaceError {
    pub fn new(dir: String) -> RunningPlaceError {
        RunningPlaceError { dir: dir }
    }
}
impl Display for RunningPlaceError {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        write!(f, "Cannot run in \"{}\" directory", self.dir)
    }
}
impl Error for RunningPlaceError {
    fn description(&self) -> &str { "cannot run in banned directories" }
}

#[derive(Debug, PartialEq)]
pub enum UsageKind {
    Nothing,
    Help,
    Version,
    Init,
    Config,
    Ignore,
    Sweep,
    Burn,
    Start,
    End,
    Destroy,
    Patrol,
}
impl UsageKind {
    fn command(&self) -> &str {
        match *self {
            UsageKind::Nothing => "<Command>",
            UsageKind::Help    => "help",
            UsageKind::Version => "version",
            UsageKind::Init    => "init",
            UsageKind::Config  => "config",
            UsageKind::Ignore  => "ignore",
            UsageKind::Sweep   => "sweep",
            UsageKind::Burn    => "burn",
            UsageKind::Start   => "start",
            UsageKind::End     => "end",
            UsageKind::Destroy => "destroy",
            UsageKind::Patrol  => "patrol",
        }
    }

    fn common_usage(&self) -> String {
        format!("{} {}", ME, self.command())
    }

    fn usages(&self) -> Vec<String> {
        match *self {
            UsageKind::Help   => vec![format!("{} <SubCommand>", self.common_usage())],
            UsageKind::Config => vec![
                format!("{} set <Key> <Value>", self.common_usage()),
                format!("{} init"             , self.common_usage()),
            ],
            UsageKind::Ignore => vec![
                format!("{} add <File> ..."   , self.common_usage()),
                format!("{} remove <File> ...", self.common_usage()),
                format!("{} current"          , self.common_usage()),
                format!("{} clear"            , self.common_usage()),
            ],
            UsageKind::Sweep => vec![format!("{} [all] [indeed]", self.common_usage())],
            UsageKind::Burn  => vec![format!("{} [indeed]", self.common_usage())],
            _ => vec![self.common_usage()],
        }
    }

    fn description(&self) -> &str {
        match *self {
            UsageKind::Nothing => "Keep your directories clean!",
            UsageKind::Help    => "Display usage for each command.",
            UsageKind::Version => "Display the version of this software.",
            UsageKind::Init    => "Register current directory.",
            UsageKind::Config  => "Change parameter.",
            UsageKind::Ignore  => "Change \"non-dust\" file's list.",
            UsageKind::Sweep   => "Sweep \"dust\" files and empty directories in current directory.",
            UsageKind::Burn    => "Burn \"sweeped\" files.",
            UsageKind::Start   => "Register with \"cron\" for autonomous operation.",
            UsageKind::End     => "Unregister from \"cron\".",
            UsageKind::Destroy => "Unregister current directory.",
            UsageKind::Patrol  => "Keep \"cron\" file clean.",
        }
    }

    fn sub_descriptions(&self) -> Vec<String> {
        match *self {
            UsageKind::Nothing => vec![
                format!("{}{}", "help    # ", UsageKind::Help   .description()),
                format!("{}{}", "version # ", UsageKind::Version.description()),
                format!("{}{}", "init    # ", UsageKind::Init   .description()),
                format!("{}{}", "config  # ", UsageKind::Config .description()),
                format!("{}{}", "ignore  # ", UsageKind::Ignore .description()),
                format!("{}{}", "sweep   # ", UsageKind::Sweep  .description()),
                format!("{}{}", "burn    # ", UsageKind::Burn   .description()),
                format!("{}{}", "start   # ", UsageKind::Start  .description()),
                format!("{}{}", "end     # ", UsageKind::End    .description()),
                format!("{}{}", "destroy # ", UsageKind::Destroy.description()),
                format!("{}{}", "patrol  # ", UsageKind::Patrol .description()),
            ],
            UsageKind::Config => vec![
                "set  # Set parameter"       .to_string(),
                "init # Initialize configure".to_string(),
            ],
            UsageKind::Ignore => {
                let file_expression = "\"non-dust\" file's list";
                vec![
                    format!("add     # Add specified files to {}"        , file_expression),
                    format!("remove  # Remove specified files from {}"   , file_expression),
                    format!("current # Replace {} with current all files", file_expression),
                    format!("clear   # Clear {}"                         , file_expression),
                ]
            },
            UsageKind::Sweep => vec![
                "(none)     # Sweep fakely \"dust\"s"                                  .to_string(),
                "indeed     # Sweep indeed \"dust\"s"                                  .to_string(),
                "all        # Sweep fakely \"dust\"s including recently accessed files".to_string(),
                "all indeed # Sweep indeed \"dust\"s including recently accessed files".to_string(),
            ],
            UsageKind::Burn => vec![
                "(none) # Burn expired \"dust box\"s fakely".to_string(),
                "indeed # Burn expired \"dust box\"s indeed".to_string(),
            ],
            _ => Vec::new(),
        }
    }
}

#[derive(Debug, PartialEq)]
pub struct Usage {
    kind: UsageKind,
}
impl Usage {
    pub fn new(kind: UsageKind) -> Usage {
        Usage { kind: kind }
    }

    fn message(&self) -> String {
        let usage = self.kind
            .usages()
            .iter()
            .fold(String::new(), |message, line| {
                message + "    " + line + "\n"
            });

        let main = format!("Usage:\n{}\nDescription:\n    {}\n", usage, self.kind.description());

        let sub_description = self.kind
            .sub_descriptions()
            .iter()
            .fold(String::new(), |message, line| {
                message + "    " + line + "\n"
            });

        if sub_description.is_empty() {
            main
        } else {
            format!("{}{}{}", main, "\nCommand:\n", sub_description)
        }
    }
}
impl Display for Usage {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        write!(f, "{}", self.message())
    }
}
impl Error for Usage {
    fn description(&self) -> &str { "show usage" }
}
<commit_msg>[Remedy] Change error messages for ConfigError<commit_after>extern crate regex;
extern crate toml;

use self::regex::Error as RegexError;
use self::toml::ParserError as ParseTomlError;

use constant::{self, ME};
use std::num::ParseIntError;
use std::error::Error;
use std::fmt::{Display, Formatter, Result as FmtResult};
use std::io::Error as IoError;

#[derive(Debug)]
pub enum CliError {
    Config(ConfigError),
    Cron(CronError),
    Essential(EssentialLack),
    Io(IoError),
    ParseInt(ParseIntError),
    ParseToml(ParseTomlError),
    Regex(RegexError),
    RunningPlace(RunningPlaceError),
    Usage(Usage),
}
impl Display for CliError {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        match *self {
            CliError::Config(ref e)       => e.fmt(f),
            CliError::Cron(ref e)         => e.fmt(f),
            CliError::Essential(ref e)    => e.fmt(f),
            CliError::Io(ref e)           => e.fmt(f),
            CliError::ParseInt(ref e)     => e.fmt(f),
            CliError::ParseToml(ref e)    => e.fmt(f),
            CliError::Regex(ref e)        => e.fmt(f),
            CliError::RunningPlace(ref e) => e.fmt(f),
            CliError::Usage(ref u)        => u.fmt(f),
        }
    }
}
impl Error for CliError {
    fn cause(&self) -> Option<&Error> {
        match *self {
            CliError::Config(ref e)       => Some(e),
            CliError::Cron(ref e)         => Some(e),
            CliError::Essential(ref e)    => Some(e),
            CliError::Io(ref e)           => Some(e),
            CliError::ParseInt(ref e)     => Some(e),
            CliError::ParseToml(ref e)    => Some(e),
            CliError::Regex(ref e)        => Some(e),
            CliError::RunningPlace(ref e) => Some(e),
            CliError::Usage(ref u)        => Some(u),
        }
    }

    fn description(&self) -> &str {
        match *self {
            CliError::Config(ref e)       => e.description(),
            CliError::Cron(ref e)         => e.description(),
            CliError::Essential(ref e)    => e.description(),
            CliError::Io(ref e)           => e.description(),
            CliError::ParseInt(ref e)     => e.description(),
            CliError::ParseToml(ref e)    => e.description(),
            CliError::Regex(ref e)        => e.description(),
            CliError::RunningPlace(ref e) => e.description(),
            CliError::Usage(ref u)        => u.description(),
        }
    }
}
impl From<ConfigError> for CliError {
    fn from(e: ConfigError) -> CliError {
        CliError::Config(e)
    }
}
impl From<CronError> for CliError {
    fn from(e: CronError) -> CliError {
        CliError::Cron(e)
    }
}
impl From<EssentialLack> for CliError {
    fn from(e: EssentialLack) -> CliError {
        CliError::Essential(e)
    }
}
impl From<IoError> for CliError {
    fn from(e: IoError) -> CliError {
        CliError::Io(e)
    }
}
impl From<ParseIntError> for CliError {
    fn from(e: ParseIntError) -> CliError {
        CliError::ParseInt(e)
    }
}
impl From<ParseTomlError> for CliError {
    fn from(e: ParseTomlError) -> CliError {
        CliError::ParseToml(e)
    }
}
impl From<RegexError> for CliError {
    fn from(e: RegexError) -> CliError {
        CliError::Regex(e)
    }
}
impl From<RunningPlaceError> for CliError {
    fn from(e: RunningPlaceError) -> CliError {
        CliError::RunningPlace(e)
    }
}
impl From<Usage> for CliError {
    fn from(u: Usage) -> CliError {
        CliError::Usage(u)
    }
}

#[derive(Debug, PartialEq)]
pub enum ConfigErrorKind {
    Something,
    InvalidKey,
    NonStringValue,
    NotFoundBurnMoratorium,
    NotFoundSweepMoratorium,
    NotFoundSweepPeriod,
    NotFoundSweepTime,
    BurnMoratorium,
    SweepMoratorium,
    SweepPeriod,
    SweepTime,
}
#[derive(Debug, PartialEq)]
pub struct ConfigError {
    kind: ConfigErrorKind,
}
impl ConfigError {
    pub fn new(kind: ConfigErrorKind) -> ConfigError {
        ConfigError { kind: kind }
    }
}
impl Display for ConfigError {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        write!(f, "{}", match self.kind {
            ConfigErrorKind::Something               => r#"Something went to wrong"#,
            ConfigErrorKind::InvalidKey              => r#"Please set key in ["burn.moratorium", "sweep.moratorium", "sweep.period", "sweep.time"]"#,
            ConfigErrorKind::NonStringValue          => r#"Please set values as "String""#,
            ConfigErrorKind::NotFoundBurnMoratorium  => r#"Please set "burn.moratorium""#,
            ConfigErrorKind::NotFoundSweepMoratorium => r#"Please set "sweep.moratorium""#,
            ConfigErrorKind::NotFoundSweepPeriod     => r#"Please set "sweep.period""#,
            ConfigErrorKind::NotFoundSweepTime       => r#"Please set "sweep.time""#,
            ConfigErrorKind::BurnMoratorium          => r#"Please set value like "3days" or "1week" as "burn.moratorium""#,
            ConfigErrorKind::SweepMoratorium         => r#"Please set value like "10hours" or "1week" as "sweep.moratorium""#,
            ConfigErrorKind::SweepPeriod             => r#"Please set "daily" or "weekly" as "sweep.period""#,
            ConfigErrorKind::SweepTime               => r#"Please set value from "00:00" to "23:59" as "sweep.time""#,
        })
    }
}
impl Error for ConfigError {
    fn description(&self) -> &str { "invalid parameters" }
}

#[derive(Debug, PartialEq)]
pub enum CronErrorKind {
    BinExistsInInvalidDir,
    InvalidCharacterCode,
    InvalidPath,
    FailedToWrite,
}
#[derive(Debug, PartialEq)]
pub struct CronError {
    kind: CronErrorKind,
}
impl CronError {
    pub fn new(kind: CronErrorKind) -> Self {
        CronError { kind: kind }
    }
}
impl Display for CronError {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        write!(f, "{}", match self.kind {
            CronErrorKind::BinExistsInInvalidDir => "The \"bin\" exists in directory whose path include non-UTF-8 charecter code",
            CronErrorKind::InvalidCharacterCode  => "The \"cron\" file consists of non-UTF-8 character code",
            CronErrorKind::InvalidPath           => "The path to current directory include non-UTF-8 character code",
            CronErrorKind::FailedToWrite         => "Failed to write new \"cron\" file"
        })
    }
}
impl Error for CronError {
    fn description(&self) -> &str { "problems around cron" }
}

#[derive(Debug, PartialEq)]
pub enum EssentialKind {
    WorkingDir,
    StorageDir,
    ConfigFile,
    IgnoreFile,
}
#[derive(Debug, PartialEq)]
pub struct EssentialLack {
    what: EssentialKind,
}
impl EssentialLack {
    pub fn new(what: EssentialKind) -> EssentialLack {
        EssentialLack { what: what }
    }
}
impl Display for EssentialLack {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        write!(f, "{} does not exist", match self.what {
            EssentialKind::WorkingDir => format!("\"{}\" directory", constant::WORKING_DIR_NAME),
            EssentialKind::StorageDir => format!("\"{}\" directory", constant::STORAGE_DIR_NAME),
            EssentialKind::ConfigFile => format!("\"{}\" file"     , constant::CONFIG_FILE_NAME),
            EssentialKind::IgnoreFile => format!("\"{}\" file"     , constant::IGNORE_FILE_NAME),
        })
    }
}
impl Error for EssentialLack {
    fn description(&self) -> &str { "essential file does not exist" }
}

#[derive(Debug, PartialEq)]
pub struct RunningPlaceError {
    dir: String,
}
impl RunningPlaceError {
    pub fn new(dir: String) -> RunningPlaceError {
        RunningPlaceError { dir: dir }
    }
}
impl Display for RunningPlaceError {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        write!(f, "Cannot run in \"{}\" directory", self.dir)
    }
}
impl Error for RunningPlaceError {
    fn description(&self) -> &str { "cannot run in banned directories" }
}

#[derive(Debug, PartialEq)]
pub enum UsageKind {
    Nothing,
    Help,
    Version,
    Init,
    Config,
    Ignore,
    Sweep,
    Burn,
    Start,
    End,
    Destroy,
    Patrol,
}
impl UsageKind {
    fn command(&self) -> &str {
        match *self {
            UsageKind::Nothing => "<Command>",
            UsageKind::Help    => "help",
            UsageKind::Version => "version",
            UsageKind::Init    => "init",
            UsageKind::Config  => "config",
            UsageKind::Ignore  => "ignore",
            UsageKind::Sweep   => "sweep",
            UsageKind::Burn    => "burn",
            UsageKind::Start   => "start",
            UsageKind::End     => "end",
            UsageKind::Destroy => "destroy",
            UsageKind::Patrol  => "patrol",
        }
    }

    fn common_usage(&self) -> String {
        format!("{} {}", ME, self.command())
    }

    fn usages(&self) -> Vec<String> {
        match *self {
            UsageKind::Help   => vec![format!("{} <SubCommand>", self.common_usage())],
            UsageKind::Config => vec![
                format!("{} set <Key> <Value>", self.common_usage()),
                format!("{} init"             , self.common_usage()),
            ],
            UsageKind::Ignore => vec![
                format!("{} add <File> ..."   , self.common_usage()),
                format!("{} remove <File> ...", self.common_usage()),
                format!("{} current"          , self.common_usage()),
                format!("{} clear"            , self.common_usage()),
            ],
            UsageKind::Sweep => vec![format!("{} [all] [indeed]", self.common_usage())],
            UsageKind::Burn  => vec![format!("{} [indeed]", self.common_usage())],
            _ => vec![self.common_usage()],
        }
    }

    fn description(&self) -> &str {
        match *self {
            UsageKind::Nothing => "Keep your directories clean!",
            UsageKind::Help    => "Display usage for each command.",
            UsageKind::Version => "Display the version of this software.",
            UsageKind::Init    => "Register current directory.",
            UsageKind::Config  => "Change parameter.",
            UsageKind::Ignore  => "Change \"non-dust\" file's list.",
            UsageKind::Sweep   => "Sweep \"dust\" files and empty directories in current directory.",
            UsageKind::Burn    => "Burn \"sweeped\" files.",
            UsageKind::Start   => "Register with \"cron\" for autonomous operation.",
            UsageKind::End     => "Unregister from \"cron\".",
            UsageKind::Destroy => "Unregister current directory.",
            UsageKind::Patrol  => "Keep \"cron\" file clean.",
        }
    }

    fn sub_descriptions(&self) -> Vec<String> {
        match *self {
            UsageKind::Nothing => vec![
                format!("{}{}", "help    # ", UsageKind::Help   .description()),
                format!("{}{}", "version # ", UsageKind::Version.description()),
                format!("{}{}", "init    # ", UsageKind::Init   .description()),
                format!("{}{}", "config  # ", UsageKind::Config .description()),
                format!("{}{}", "ignore  # ", UsageKind::Ignore .description()),
                format!("{}{}", "sweep   # ", UsageKind::Sweep  .description()),
                format!("{}{}", "burn    # ", UsageKind::Burn   .description()),
                format!("{}{}", "start   # ", UsageKind::Start  .description()),
                format!("{}{}", "end     # ", UsageKind::End    .description()),
                format!("{}{}", "destroy # ", UsageKind::Destroy.description()),
                format!("{}{}", "patrol  # ", UsageKind::Patrol .description()),
            ],
            UsageKind::Config => vec![
                "set  # Set parameter"       .to_string(),
                "init # Initialize configure".to_string(),
            ],
            UsageKind::Ignore => {
                let file_expression = "\"non-dust\" file's list";
                vec![
                    format!("add     # Add specified files to {}"        , file_expression),
                    format!("remove  # Remove specified files from {}"   , file_expression),
                    format!("current # Replace {} with current all files", file_expression),
                    format!("clear   # Clear {}"                         , file_expression),
                ]
            },
            UsageKind::Sweep => vec![
                "(none)     # Sweep fakely \"dust\"s"                                  .to_string(),
                "indeed     # Sweep indeed \"dust\"s"                                  .to_string(),
                "all        # Sweep fakely \"dust\"s including recently accessed files".to_string(),
                "all indeed # Sweep indeed \"dust\"s including recently accessed files".to_string(),
            ],
            UsageKind::Burn => vec![
                "(none) # Burn expired \"dust box\"s fakely".to_string(),
                "indeed # Burn expired \"dust box\"s indeed".to_string(),
            ],
            _ => Vec::new(),
        }
    }
}

#[derive(Debug, PartialEq)]
pub struct Usage {
    kind: UsageKind,
}
impl Usage {
    pub fn new(kind: UsageKind) -> Usage {
        Usage { kind: kind }
    }

    fn message(&self) -> String {
        let usage = self.kind
            .usages()
            .iter()
            .fold(String::new(), |message, line| {
                message + "    " + line + "\n"
            });

        let main = format!("Usage:\n{}\nDescription:\n    {}\n", usage, self.kind.description());

        let sub_description = self.kind
            .sub_descriptions()
            .iter()
            .fold(String::new(), |message, line| {
                message + "    " + line + "\n"
            });

        if sub_description.is_empty() {
            main
        } else {
            format!("{}{}{}", main, "\nCommand:\n", sub_description)
        }
    }
}
impl Display for Usage {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        write!(f, "{}", self.message())
    }
}
impl Error for Usage {
    fn description(&self) -> &str { "show usage" }
}
<|endoftext|>


<commit_before>extern crate num;
extern crate nalgebra as na;

pub const TOTAL_FLUIDS: usize = 2;
pub const NORMAL_DIFFUSION: [f64; 2] = [0.5, 1.0];

const TIMESTEP: f64 = 0.5;

#[derive(Default, Debug)]
pub struct Solution {
    pub fluids: [f64; TOTAL_FLUIDS],
    pub coefficients: [f64; TOTAL_FLUIDS],
    diffuse: [f64; TOTAL_FLUIDS],
}

impl Solution {
    pub fn new(fluids: [f64; TOTAL_FLUIDS], coefficients: [f64; TOTAL_FLUIDS]) -> Self {
        Solution {
            fluids: fluids,
            coefficients: coefficients,
            diffuse: [0.0; TOTAL_FLUIDS],
        }
    }

    pub fn react_deltas(&self) -> [f64; TOTAL_FLUIDS] {
        let a = self.fluids[1];
        let b = self.fluids[0];
        let f = 0.018;
        let k = 0.055;
        [a * b * b - (k + f) * b, -a * b * b + f * (1.0 - a)]
    }

    pub fn diffuse_from(&mut self, other: &Solution) {
        for i in 0..TOTAL_FLUIDS {
            self.diffuse[i] += other.fluids[i] * other.coefficients[i] / 6.0;
        }
    }

    pub fn end_cycle(&mut self) {
        let reacts = self.react_deltas();
        for i in 0..TOTAL_FLUIDS {
            self.fluids[i] += TIMESTEP *
                              (reacts[i] + self.diffuse[i] - self.coefficients[i] * self.fluids[i]);
            self.diffuse[i] = 0.0;
        }
    }
}
<commit_msg>mazes produce more interesting results<commit_after>extern crate num;
extern crate nalgebra as na;

pub const TOTAL_FLUIDS: usize = 2;
pub const NORMAL_DIFFUSION: [f64; 2] = [0.5, 1.0];

const TIMESTEP: f64 = 0.5;

#[derive(Default, Debug)]
pub struct Solution {
    pub fluids: [f64; TOTAL_FLUIDS],
    pub coefficients: [f64; TOTAL_FLUIDS],
    diffuse: [f64; TOTAL_FLUIDS],
}

impl Solution {
    pub fn new(fluids: [f64; TOTAL_FLUIDS], coefficients: [f64; TOTAL_FLUIDS]) -> Self {
        Solution {
            fluids: fluids,
            coefficients: coefficients,
            diffuse: [0.0; TOTAL_FLUIDS],
        }
    }

    pub fn react_deltas(&self) -> [f64; TOTAL_FLUIDS] {
        let a = self.fluids[1];
        let b = self.fluids[0];
        let f = 0.029;
        let k = 0.057;
        [a * b * b - (k + f) * b, -a * b * b + f * (1.0 - a)]
    }

    pub fn diffuse_from(&mut self, other: &Solution) {
        for i in 0..TOTAL_FLUIDS {
            self.diffuse[i] += other.fluids[i] * other.coefficients[i] / 6.0;
        }
    }

    pub fn end_cycle(&mut self) {
        let reacts = self.react_deltas();
        for i in 0..TOTAL_FLUIDS {
            self.fluids[i] += TIMESTEP *
                              (reacts[i] + self.diffuse[i] - self.coefficients[i] * self.fluids[i]);
            self.diffuse[i] = 0.0;
        }
    }
}
<|endoftext|>


<commit_before>//! Glyph caching

use std::path::Path;
use std::collections::hash_map::{ HashMap, Entry };
use { freetype, graphics };
use gfx_lib as gfx;

/// The type alias for the font size.
pub type FontSize = u32;

/// The type alias for font characters.
pub type Character<D> = graphics::character::Character<::Texture<D>>;

/// An enum to represent various possible run-time errors that may occur.
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Error {
    /// An error happened when creating a gfx texture.
    Texture(gfx::tex::TextureError),
    /// An error happened with the FreeType library.
    Freetype(freetype::error::Error),
}

/// A struct used for caching rendered font.
pub struct GlyphCache<R: gfx::Resources> {
    /// The font face.
    pub face: freetype::Face,
    empty_texture: ::Texture<R>,
    data: HashMap<(FontSize, char), Character<R>>,
}

impl<R> GlyphCache<R> where R: gfx::Resources {
     /// Constructor for a GlyphCache.
     pub fn new<D: gfx::Factory<R>>(font: &Path, device: &mut D)
                -> Result<Self, Error> {
        let freetype = match freetype::Library::init() {
            Ok(freetype) => freetype,
            Err(why) => return Err(Error::Freetype(why)),
        };
        let face = match freetype.new_face(font, 0) {
            Ok(face) => face,
            Err(why) => return Err(Error::Freetype(why)),
        };
        let texture = {
            let tinfo = gfx::tex::TextureInfo {
                width: 1,
                height: 1,
                depth: 1,
                levels: 1,
                format: gfx::tex::RGBA8,
                kind: gfx::tex::TextureKind::Texture2D,
            };
            let image_info = tinfo.to_image_info();
            match device.create_texture(tinfo) {
                Ok(t) => match device.update_texture(&t, &image_info, &[0u8; 4],
                                                     Some(gfx::tex::TextureKind::Texture2D)) {
                    Ok(()) => t,
                    Err(e) => return Err(Error::Texture(e)),
                },
                Err(e) => return Err(Error::Texture(e)),
            }
        };
        Ok(GlyphCache {
            face: face,
            empty_texture: ::Texture {
                handle: texture
            },
            data: HashMap::new(),
        })
    }

    /// Generate all pending characters.
    pub fn update<D: gfx::Factory<R>>(&mut self, device: &mut D) {
        let empty_handle = self.empty_texture.handle.clone();
        for (&(size, ch), value) in self.data.iter_mut()
                .filter(|&(_, ref c)| c.texture.handle == empty_handle) {
            self.face.set_pixel_sizes(0, size).unwrap();
            self.face.load_char(ch as usize, freetype::face::DEFAULT).unwrap();
            let glyph = self.face.glyph().get_glyph().unwrap();
            let bitmap_glyph = glyph.to_bitmap(
                freetype::render_mode::RenderMode::Normal, None)
                .unwrap();
            let bitmap = bitmap_glyph.bitmap();
            let texture = ::Texture::from_memory_alpha(
                device,
                bitmap.buffer(),
                bitmap.width() as u32,
                bitmap.rows() as u32);
            let glyph_size = glyph.advance();
            *value = Character {
                offset: [
                    bitmap_glyph.left() as f64,
                    bitmap_glyph.top() as f64
                ],
                size: [
                    (glyph_size.x >> 16) as f64,
                    (glyph_size.y >> 16) as f64
                ],
                texture: texture,
            };
        }
    }
}

impl<R: gfx::Resources> graphics::character::CharacterCache for GlyphCache<R> {
    type Texture = ::Texture<R>;

    fn character(&mut self, size: FontSize, ch: char) -> &Character<R> {
        match self.data.entry((size, ch)) {
            //returning `into_mut()' to work around lifetime issues
            Entry::Occupied(v) => v.into_mut(),
            Entry::Vacant(v) => {
                v.insert(graphics::character::Character {
                    offset: [0.0; 2],
                    size: [1.0; 2],
                    texture: ::Texture {
                        handle: self.empty_texture.handle.clone()
                    },
                })
            },
        }
    }
}
<commit_msg>Upgrade to latest freetype<commit_after>//! Glyph caching

use std::path::Path;
use std::collections::hash_map::{ HashMap, Entry };
use { freetype, graphics };
use gfx_lib as gfx;

/// The type alias for the font size.
pub type FontSize = u32;

/// The type alias for font characters.
pub type Character<D> = graphics::character::Character<::Texture<D>>;

/// An enum to represent various possible run-time errors that may occur.
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Error {
    /// An error happened when creating a gfx texture.
    Texture(gfx::tex::TextureError),
    /// An error happened with the FreeType library.
    Freetype(freetype::error::Error),
}

/// A struct used for caching rendered font.
pub struct GlyphCache<'a, R: gfx::Resources> {
    /// The font face.
    pub face: freetype::Face<'a>,
    empty_texture: ::Texture<R>,
    data: HashMap<(FontSize, char), Character<R>>,
}

impl<'a, R> GlyphCache<'a, R> where R: gfx::Resources {
     /// Constructor for a GlyphCache.
     pub fn new<D: gfx::Factory<R>>(font: &Path, device: &mut D)
                -> Result<GlyphCache<'static, R>, Error> {
        let freetype = match freetype::Library::init() {
            Ok(freetype) => freetype,
            Err(why) => return Err(Error::Freetype(why)),
        };
        let face = match freetype.new_face(font, 0) {
            Ok(face) => face,
            Err(why) => return Err(Error::Freetype(why)),
        };
        let texture = {
            let tinfo = gfx::tex::TextureInfo {
                width: 1,
                height: 1,
                depth: 1,
                levels: 1,
                format: gfx::tex::RGBA8,
                kind: gfx::tex::TextureKind::Texture2D,
            };
            let image_info = tinfo.to_image_info();
            match device.create_texture(tinfo) {
                Ok(t) => match device.update_texture(&t, &image_info, &[0u8; 4],
                                                     Some(gfx::tex::TextureKind::Texture2D)) {
                    Ok(()) => t,
                    Err(e) => return Err(Error::Texture(e)),
                },
                Err(e) => return Err(Error::Texture(e)),
            }
        };
        Ok(GlyphCache {
            face: face,
            empty_texture: ::Texture {
                handle: texture
            },
            data: HashMap::new(),
        })
    }

    /// Generate all pending characters.
    pub fn update<D: gfx::Factory<R>>(&mut self, device: &mut D) {
        let empty_handle = self.empty_texture.handle.clone();
        for (&(size, ch), value) in self.data.iter_mut()
                .filter(|&(_, ref c)| c.texture.handle == empty_handle) {
            self.face.set_pixel_sizes(0, size).unwrap();
            self.face.load_char(ch as usize, freetype::face::DEFAULT).unwrap();
            let glyph = self.face.glyph().get_glyph().unwrap();
            let bitmap_glyph = glyph.to_bitmap(
                freetype::render_mode::RenderMode::Normal, None)
                .unwrap();
            let bitmap = bitmap_glyph.bitmap();
            let texture = ::Texture::from_memory_alpha(
                device,
                bitmap.buffer(),
                bitmap.width() as u32,
                bitmap.rows() as u32);
            let glyph_size = glyph.advance();
            *value = Character {
                offset: [
                    bitmap_glyph.left() as f64,
                    bitmap_glyph.top() as f64
                ],
                size: [
                    (glyph_size.x >> 16) as f64,
                    (glyph_size.y >> 16) as f64
                ],
                texture: texture,
            };
        }
    }
}

impl<'a, R: gfx::Resources> graphics::character::CharacterCache for GlyphCache<'a, R> {
    type Texture = ::Texture<R>;

    fn character(&mut self, size: FontSize, ch: char) -> &Character<R> {
        match self.data.entry((size, ch)) {
            //returning `into_mut()' to work around lifetime issues
            Entry::Occupied(v) => v.into_mut(),
            Entry::Vacant(v) => {
                v.insert(graphics::character::Character {
                    offset: [0.0; 2],
                    size: [1.0; 2],
                    texture: ::Texture {
                        handle: self.empty_texture.handle.clone()
                    },
                })
            },
        }
    }
}
<|endoftext|>


<commit_before>extern crate iron;
extern crate staticfile;

// This example will serve the docs (from doc).
// To use, `make examples doc && ./examples/doc`.

use std::io::net::ip::Ipv4Addr;

use iron::{Iron, ServerT};

use staticfile::Static;

fn main() {
    let mut server: ServerT = Iron::new();
    // Serve the docs
    server.smelt(Static::new(Path::new("doc/")));
    // Serve the index.html
    server.smelt(Static::new(Path::new("doc/staticfile/")));
    server.listen(Ipv4Addr(127, 0, 0, 1), 3000);
}
<commit_msg>(fix) Updated for chain.link.<commit_after>extern crate iron;
extern crate staticfile;

// This example will serve the docs (from doc).
// To use, `make examples doc && ./examples/doc`.

use std::io::net::ip::Ipv4Addr;

use iron::{Iron, ServerT, Chain};

use staticfile::Static;

fn main() {
    let mut server: ServerT = Iron::new();
    // Serve the docs
    server.chain.link(Static::new(Path::new("doc/")));
    // Serve the index.html
    server.chain.link(Static::new(Path::new("doc/staticfile/")));
    server.listen(Ipv4Addr(127, 0, 0, 1), 3000);
}
<|endoftext|>


<commit_before>extern crate libc;

use std;
use std::mem;
use libc::c_char;

use rparser::*;

use ipsec_parser::*;
use num_traits::cast::FromPrimitive;

use nom::IResult;

pub struct IPsecParser<'a> {
    _name: Option<&'a[u8]>,

    pub client_proposals : Vec<IkeV2Transform>,

    pub dh_group: Option<IkeTransformDHType>,
}

impl<'a> RParser for IPsecParser<'a> {
    fn parse(&mut self, i: &[u8], _direction: u8) -> u32 {
        match parse_ikev2_header(i) {
            IResult::Done(rem,ref hdr) => {
                debug!("parse_ikev2_header: {:?}",hdr);
                if rem.len() == 0 && hdr.length == 28 {
                    return R_STATUS_OK;
                }
                match parse_ikev2_payload_list(rem,hdr.next_payload) {
                    IResult::Done(_,Ok(ref p)) => {
                        debug!("parse_ikev2_payload_with_type: {:?}",p);
                        for payload in p {
                            match payload.content {
                                IkeV2PayloadContent::SA(ref prop) => {
                                    if hdr.flags & IKEV2_FLAG_INITIATOR != 0 {
                                        self.add_client_proposals(prop);
                                    }
                                },
                                IkeV2PayloadContent::KE(ref kex) => {
                                    self.dh_group = IkeTransformDHType::from_u16(kex.dh_group);
                                    // XXX if self.dh_group == None, raise decoder event
                                    debug!("KEX {}/{:?}", kex.dh_group, self.dh_group);
                                },
                                IkeV2PayloadContent::Nonce(ref n) => {
                                    debug!("Nonce: {:?}", n);
                                },
                                IkeV2PayloadContent::Notify(ref n) => {
                                    debug!("Notify: {:?}", n);
                                },
                                _ => {
                                    debug!("Unknown payload content {:?}", payload.content);
                                },
                            }
                        }
                    },
                    e @ _ => warn!("parse_ikev2_payload_with_type: {:?}",e),
                };
            },
            e @ _ => warn!("parse_ikev2_header: {:?}",e),
        };
        R_STATUS_OK
    }
}

impl<'a> IPsecParser<'a> {
    pub fn new(name: &'a[u8]) -> IPsecParser<'a> {
        IPsecParser{
            _name: Some(name),
            client_proposals: Vec::new(),
            dh_group: None,
        }
    }

    fn add_client_proposals(&mut self, prop: &Vec<IkeV2Proposal>) {
        debug!("num_proposals: {}",prop.len());
        for ref p in prop {
            debug!("proposal: {:?}",p);
            debug!("num_transforms: {}",p.num_transforms);
            for ref xform in &p.transforms {
                debug!("transform: {:?}",xform);
                let xty = IkeTransformType::from_u8(xform.transform_type);
                debug!("\ttype: {:?} / {}",xty,xform.transform_type);
                match xty {
                    Some(IkeTransformType::EncryptionAlgorithm) => {
                        debug!("\tEncryptionAlgorithm: {:?}",IkeTransformEncType::from_u16(xform.transform_id));
                    },
                    Some(IkeTransformType::PseudoRandomFunction) => {
                        debug!("\tPseudoRandomFunction: {:?}",IkeTransformPRFType::from_u16(xform.transform_id));
                    },
                    Some(IkeTransformType::IntegrityAlgorithm) => {
                        debug!("\tIntegrityAlgorithm: {:?}",IkeTransformAuthType::from_u16(xform.transform_id));
                    },
                    Some(IkeTransformType::DiffieHellmanGroup) => {
                        debug!("\tDiffieHellmanGroup: {:?}",IkeTransformDHType::from_u16(xform.transform_id));
                    },
                    Some(IkeTransformType::ExtendedSequenceNumbers) => {
                        debug!("\tExtendedSequenceNumbers: {:?}",IkeTransformESNType::from_u16(xform.transform_id));
                    },
                    _ => warn!("\tUnknown transform type {}",xform.transform_type),
                }
                if xform.transform_id == 0 {
                    warn!("\tTransform ID == 0 (choice left to responder)");
                };
            }
            let client_proposals : Vec<IkeV2Transform> = p.transforms.iter().map(|x| x.into()).collect();
            debug!("Client proposals\n{:?}",client_proposals);
            for prop in &client_proposals {
                match prop {
                    &IkeV2Transform::DH(ref dh) => {
                        match dh {
                            &IkeTransformDHType::Modp768 |
                            &IkeTransformDHType::Modp1024 |
                            &IkeTransformDHType::Modp1024s160 => {
                                warn!("Weak DH: {:?}", dh);
                            },
                            _ => (),
                        }
                    },
                    &IkeV2Transform::Unknown(tx_type,tx_id) => {
                        warn!("Unknown proposal: type={}, id={}", tx_type, tx_id);
                    },
                    _ => (),
                }
            }
            self.client_proposals = client_proposals;
        }
    }
}

fn ipsec_probe(i: &[u8]) -> bool {
    if i.len() <= 2 { return false; }
    true
}

r_declare_state_new!(r_ipsec_state_new,IPsecParser,b"IPsec state");
r_declare_state_free!(r_ipsec_state_free,IPsecParser,{ () });

r_implement_probe!(r_ipsec_probe,ipsec_probe);
r_implement_parse!(r_ipsec_parse,IPsecParser);

<commit_msg>IKEv2: add warning if encryption is weak, or if no DH was proposed<commit_after>extern crate libc;

use std;
use std::mem;
use libc::c_char;

use rparser::*;

use ipsec_parser::*;
use num_traits::cast::FromPrimitive;

use nom::IResult;

pub struct IPsecParser<'a> {
    _name: Option<&'a[u8]>,

    pub client_proposals : Vec<IkeV2Transform>,

    pub dh_group: Option<IkeTransformDHType>,
}

impl<'a> RParser for IPsecParser<'a> {
    fn parse(&mut self, i: &[u8], _direction: u8) -> u32 {
        match parse_ikev2_header(i) {
            IResult::Done(rem,ref hdr) => {
                debug!("parse_ikev2_header: {:?}",hdr);
                if rem.len() == 0 && hdr.length == 28 {
                    return R_STATUS_OK;
                }
                match parse_ikev2_payload_list(rem,hdr.next_payload) {
                    IResult::Done(_,Ok(ref p)) => {
                        debug!("parse_ikev2_payload_with_type: {:?}",p);
                        for payload in p {
                            match payload.content {
                                IkeV2PayloadContent::SA(ref prop) => {
                                    if hdr.flags & IKEV2_FLAG_INITIATOR != 0 {
                                        self.add_client_proposals(prop);
                                    }
                                },
                                IkeV2PayloadContent::KE(ref kex) => {
                                    self.dh_group = IkeTransformDHType::from_u16(kex.dh_group);
                                    // XXX if self.dh_group == None, raise decoder event
                                    debug!("KEX {}/{:?}", kex.dh_group, self.dh_group);
                                },
                                IkeV2PayloadContent::Nonce(ref n) => {
                                    debug!("Nonce: {:?}", n);
                                },
                                IkeV2PayloadContent::Notify(ref n) => {
                                    debug!("Notify: {:?}", n);
                                },
                                _ => {
                                    debug!("Unknown payload content {:?}", payload.content);
                                },
                            }
                        }
                    },
                    e @ _ => warn!("parse_ikev2_payload_with_type: {:?}",e),
                };
            },
            e @ _ => warn!("parse_ikev2_header: {:?}",e),
        };
        R_STATUS_OK
    }
}

impl<'a> IPsecParser<'a> {
    pub fn new(name: &'a[u8]) -> IPsecParser<'a> {
        IPsecParser{
            _name: Some(name),
            client_proposals: Vec::new(),
            dh_group: None,
        }
    }

    fn add_client_proposals(&mut self, prop: &Vec<IkeV2Proposal>) {
        debug!("num_proposals: {}",prop.len());
        for ref p in prop {
            debug!("proposal: {:?}",p);
            debug!("num_transforms: {}",p.num_transforms);
            for ref xform in &p.transforms {
                debug!("transform: {:?}",xform);
                let xty = IkeTransformType::from_u8(xform.transform_type);
                debug!("\ttype: {:?} / {}",xty,xform.transform_type);
                match xty {
                    Some(IkeTransformType::EncryptionAlgorithm) => {
                        debug!("\tEncryptionAlgorithm: {:?}",IkeTransformEncType::from_u16(xform.transform_id));
                    },
                    Some(IkeTransformType::PseudoRandomFunction) => {
                        debug!("\tPseudoRandomFunction: {:?}",IkeTransformPRFType::from_u16(xform.transform_id));
                    },
                    Some(IkeTransformType::IntegrityAlgorithm) => {
                        debug!("\tIntegrityAlgorithm: {:?}",IkeTransformAuthType::from_u16(xform.transform_id));
                    },
                    Some(IkeTransformType::DiffieHellmanGroup) => {
                        debug!("\tDiffieHellmanGroup: {:?}",IkeTransformDHType::from_u16(xform.transform_id));
                    },
                    Some(IkeTransformType::ExtendedSequenceNumbers) => {
                        debug!("\tExtendedSequenceNumbers: {:?}",IkeTransformESNType::from_u16(xform.transform_id));
                    },
                    _ => warn!("\tUnknown transform type {}",xform.transform_type),
                }
                if xform.transform_id == 0 {
                    warn!("\tTransform ID == 0 (choice left to responder)");
                };
            }
            let client_proposals : Vec<IkeV2Transform> = p.transforms.iter().map(|x| x.into()).collect();
            debug!("Client proposals\n{:?}",client_proposals);
            // Rule 1: warn on weak or unknown transforms
            for prop in &client_proposals {
                match prop {
                    &IkeV2Transform::Encryption(ref enc) => {
                        match enc {
                            &IkeTransformEncType::DesIV64 |
                            &IkeTransformEncType::Des |
                            &IkeTransformEncType::TripleDes |
                            &IkeTransformEncType::Rc5 |
                            &IkeTransformEncType::Idea |
                            &IkeTransformEncType::Cast |
                            &IkeTransformEncType::Blowfish |
                            &IkeTransformEncType::TripleIdea |
                            &IkeTransformEncType::DesIV32 |
                            &IkeTransformEncType::Null => {
                                warn!("Weak Encryption: {:?}", enc);
                            },
                            _ => (),
                        }
                    },
                    &IkeV2Transform::DH(ref dh) => {
                        match dh {
                            &IkeTransformDHType::None => {
                                warn!("'None' DH transform proposed");
                            },
                            &IkeTransformDHType::Modp768 |
                            &IkeTransformDHType::Modp1024 |
                            &IkeTransformDHType::Modp1024s160 => {
                                warn!("Weak DH: {:?}", dh);
                            },
                            _ => (),
                        }
                    },
                    &IkeV2Transform::Unknown(tx_type,tx_id) => {
                        warn!("Unknown proposal: type={}, id={}", tx_type, tx_id);
                    },
                    _ => (),
                }
            }
            // Rule 2: check if no DH was proposed
            if ! client_proposals.iter().any(|x| {
                if let &IkeV2Transform::DH(_) = x { true } else { false }
            })
            {
                warn!("No DH transform found");
            }
            // finally
            self.client_proposals = client_proposals;
        }
    }
}

fn ipsec_probe(i: &[u8]) -> bool {
    if i.len() <= 2 { return false; }
    true
}

r_declare_state_new!(r_ipsec_state_new,IPsecParser,b"IPsec state");
r_declare_state_free!(r_ipsec_state_free,IPsecParser,{ () });

r_implement_probe!(r_ipsec_probe,ipsec_probe);
r_implement_parse!(r_ipsec_parse,IPsecParser);

<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Parsing and loading Executable and Linkable Format (ELF) 32- and 64-bit
//! binaries.
//!
//! For more information on the ELF format, refer to:
//!
//!  + [Wikipedia](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format)
//!  + The [OS Dev Wiki](http://wiki.osdev.org/ELF)
//!  + The [ELF Format Specification](elfspec)
//!
//! [elfspec]: http://www.skyfree.org/linux/references/ELF_Format.pdf
#![feature(core_intrinsics)]
#![feature(try_from)]
#![no_std]

#[macro_use] extern crate bitflags;
#[macro_use] extern crate macro_attr;

extern crate memory;

use core::{ intrinsics, ops, mem, slice };

pub mod section;
pub mod file;
pub mod program;

/// An ELF section header.
pub type Section<'a> = section::Header<'a>;
/// An ELF header file.
pub type FileHeader<W> = file::HeaderRepr<W>;

/// TODO: should ELF have its own error type?
pub type ElfResult<T> = Result<T, &'static str>;

pub trait ElfWord: Sized + Copy + Clone
                         + ops::Add<Self> + ops::Sub<Self>
                         + ops::Mul<Self> + ops::Div<Self>
                         + ops::Shl<Self> + ops::Shr<Self> { }
impl ElfWord for u64 { }
impl ElfWord for u32 { }

/// Hack to make the type-system let me do what I want
trait ValidatesWord<Word: ElfWord> {
    fn check(&self) -> ElfResult<()>;
}

/// A handle on a parsed ELF binary
///  TODO: do we want this to own a HashMap of section names to section headers,
///        to speed up section lookup?
//          - eliza, 03/08/2017
#[derive(Debug)]
pub struct Image<'a, Word, Header = file::HeaderRepr<Word>>
where Word: ElfWord + 'a
    , Header: file::Header<Word = Word> + 'a
    {
    /// the binary's [file header](file/trait.Header.html)
    pub header: &'a Header
  , /// references to each [section header](section/struct.Header.html)
    pub sections: &'a [section::Header<'a>]
  , /// the raw binary contents of the ELF binary.
    /// note that this includes the _entire_ binary contents of the file,
    /// so the file header and each section header is included in this slice.
    binary: &'a [u8]
}

impl<'a, Word, Header> Image<'a, Word, Header>
where Word: ElfWord + 'a
    , Header: file::Header<Word = Word> + 'a
    {
    /// Returns the section header [string table].
    ///
    /// [string table]: section/struct.StrTable.html
    pub fn sh_str_table(&'a self) -> section::StrTable<'a> {
        // TODO: do we want to validate that the string table index is
        //       reasonable (e.g. it's not longer than the binary)?
        //          - eliza, 03/08/2017
        // TODO: do we want to cache a ref to the string table?
        //          - eliza, 03/08/2017
        section::StrTable::from(&self.binary[self.header.sh_str_idx()..])
    }

}

/// if `n` == 0, this will give you an `&[]`. just a warning.
//  thanks to Max for making  me figure this out.
/// TODO: rewrite this as a `TryFrom` implementation (see issue #85)
//          - eliza, 03/09/2017
///       wait, possibly we should NOT do that. actually we should
///       almost certainly not do that. since this function is unsafe,
///       but `TryFrom` is not, and because this would be WAY generic.
//          - eliza, 03/09/2017
/// TODO: is this general enough to move into util?
//          - eliza, 03/09/2017
unsafe fn extract_from_slice<T: Sized>( data: &[u8]
                                      , offset: usize
                                      , n: usize)
                                      -> &[T] {
    assert!( data.len() - offset >= mem::size_of::<T>() * n
           , "Slice too short to contain {} objects of type {}"
           , n
           , intrinsics::type_name::<T>()
           );
    slice::from_raw_parts(data[offset..].as_ptr() as *const T, n)
}
<commit_msg>docs(elf): add documentation to elf::extract_from_slice function<commit_after>//
//  SOS: the Stupid Operating System
//  by Eliza Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015-2017 Eliza Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! Parsing and loading Executable and Linkable Format (ELF) 32- and 64-bit
//! binaries.
//!
//! For more information on the ELF format, refer to:
//!
//!  + [Wikipedia](https://en.wikipedia.org/wiki/Executable_and_Linkable_Format)
//!  + The [OS Dev Wiki](http://wiki.osdev.org/ELF)
//!  + The [ELF Format Specification](elfspec)
//!
//! [elfspec]: http://www.skyfree.org/linux/references/ELF_Format.pdf
#![feature(core_intrinsics)]
#![feature(try_from)]
#![no_std]

#[macro_use] extern crate bitflags;
#[macro_use] extern crate macro_attr;

extern crate memory;

use core::{ intrinsics, ops, mem, slice };

pub mod section;
pub mod file;
pub mod program;

/// An ELF section header.
pub type Section<'a> = section::Header<'a>;
/// An ELF header file.
pub type FileHeader<W> = file::HeaderRepr<W>;

/// TODO: should ELF have its own error type?
pub type ElfResult<T> = Result<T, &'static str>;

pub trait ElfWord: Sized + Copy + Clone
                         + ops::Add<Self> + ops::Sub<Self>
                         + ops::Mul<Self> + ops::Div<Self>
                         + ops::Shl<Self> + ops::Shr<Self> { }
impl ElfWord for u64 { }
impl ElfWord for u32 { }

/// Hack to make the type-system let me do what I want
trait ValidatesWord<Word: ElfWord> {
    fn check(&self) -> ElfResult<()>;
}

/// A handle on a parsed ELF binary
///  TODO: do we want this to own a HashMap of section names to section headers,
///        to speed up section lookup?
//          - eliza, 03/08/2017
#[derive(Debug)]
pub struct Image<'a, Word, Header = file::HeaderRepr<Word>>
where Word: ElfWord + 'a
    , Header: file::Header<Word = Word> + 'a
    {
    /// the binary's [file header](file/trait.Header.html)
    pub header: &'a Header
  , /// references to each [section header](section/struct.Header.html)
    pub sections: &'a [section::Header<'a>]
  , /// the raw binary contents of the ELF binary.
    /// note that this includes the _entire_ binary contents of the file,
    /// so the file header and each section header is included in this slice.
    binary: &'a [u8]
}

impl<'a, Word, Header> Image<'a, Word, Header>
where Word: ElfWord + 'a
    , Header: file::Header<Word = Word> + 'a
    {
    /// Returns the section header [string table].
    ///
    /// [string table]: section/struct.StrTable.html
    pub fn sh_str_table(&'a self) -> section::StrTable<'a> {
        // TODO: do we want to validate that the string table index is
        //       reasonable (e.g. it's not longer than the binary)?
        //          - eliza, 03/08/2017
        // TODO: do we want to cache a ref to the string table?
        //          - eliza, 03/08/2017
        section::StrTable::from(&self.binary[self.header.sh_str_idx()..])
    }

}

/// Extract `n` instances of type `T` from a byte slice.
///
/// This is essentially just a _slightly_ safer wrapper around
/// [`slice::from_raw_parts`]. Unlike `from_raw_parts`, this function takes
/// a valid byte slice, rather than a pointer.
///
/// # Arguments
///
/// + `data`: the byte slice to extract a slice of `&[T]`s from
/// + `offset`: a start offset into `data`
/// + `n`: the number of instances of `T` which should be contained
///        in `data[offset..]`
///
/// # Safety
///
/// While this function is safer than [`slice::from_raw_parts`],
/// it is still unsafe for the following reasons:
///
/// + The lifetime of the returned slice is inferred by `from_raw_parts`, and
///   is not necessarily tied to the lifetime of `data`.
/// + The contents of `data` may not be able to be interpreted as instances of
///   type `T`.
/// + `offset` may not be aligned on a `T`-sized boundary.
///
/// # Caveats
///
/// + If `n` == 0, this will give you an `&[]`. Just a warning.
//    thanks to Max for making  me figure this out.
/// + `offset` must be aligned on a `T`-sized boundary.
///
/// # Panics
///
/// + If the slice `data` is not long enough to contain `n` instances of `T`.
/// + If the index `offset` is longer than `T`
///
/// TODO: rewrite this as a `TryFrom` implementation (see issue #85)
//          - eliza, 03/09/2017
///       wait, possibly we should NOT do that. actually we should
///       almost certainly not do that. since this function is unsafe,
///       but `TryFrom` is not, and because this would be WAY generic.
//          - eliza, 03/09/2017
/// TODO: is this general enough to move into util?
//          - eliza, 03/09/2017
/// TODO: should this be refactored to return a `Result`?
//          - eliza, 03/13/2017
/// TODO: can we ensure that the lifetime of the returned slice is the same
///       as the lifetime of the input byte slice, rather than inferred by
///       [`slice::from_raw_parts`]?
//          - eliza, 03/13/2017
/// TODO: assert that `offset` is aligned on a `T`-sized boundary
//          - eliza, 03/13/2017
/// TODO: do we want to assert that `offset` is less than the length of `data`
///       separately from asserting that the slice is long enough, so that
///       we can panic with different messages?
//          - eliza, 03/13/2017
///
/// [`slice::from_raw_parts`]: https://doc.rust-lang.org/stable/std/slice/fn.from_raw_parts.html
unsafe fn extract_from_slice<T: Sized>( data: &[u8]
                                      , offset: usize
                                      , n: usize)
                                      -> &[T] {
    assert!( data.len() - offset >= mem::size_of::<T>() * n
           , "Slice too short to contain {} objects of type {}"
           , n
           , intrinsics::type_name::<T>()
           );
    slice::from_raw_parts(data[offset..].as_ptr() as *const T, n)
}
<|endoftext|>


<commit_before>
/*
 * Interpreter for Basic C like language
 * Lexer Module
 */

#[derive(Debug)]
pub enum Token {
    Keyword(String), // like int, string or let
    Identifier(String), // like variable names
    Char(String), // Char variables, inside " ' ""
    String(String), // String variables, inside quotes
    Number(String), // Number variable
    True, // boolean true
    False, // boolean false
    Equals, // =
    Plus, // +
    Minus, // -
    Multiple, // *
    Divide, // /
    Mod, // %
    Greater, // >
    Lesser, // <
    GreaterEqual, // >=
    LesserEqual, // <=
    LParen, // (
    RParen, // )
    LBrace, // {
    RBrace, // }
    LBracket, // [
    RBracket, // ]
    Comma, // ,
    Semicolon, // ;
    Comment // "//"
}

impl Token {
    pub fn toString(&self) -> &str {
        match *self {
            Token::Keyword(ref x) => "Keyword",
            Token::Identifier(ref x) => "Identifier",
            Token::Char(ref x) => "Char",
            Token::String(ref x) => "String",
            Token::Number(ref x) => "Number",
            Token::True => "True",
            Token::False => "False",
            Token::Equals => "Equals",
            Token::Plus => "Plus",
            Token::Minus => "Minus",
            Token::Multiple => "Multiple",
            Token::Divide => "Divide",
            Token::Mod => "Mod",
            Token::Greater => "Greater",
            Token::Lesser => "Lesser",
            Token::GreaterEqual => "GreaterEqual",
            Token::LesserEqual => "LesserEqual",
            Token::LParen => "LParen",
            Token::RParen => "RParen",
            Token::LBrace => "LBrace",
            Token::RBrace => "RBrace",
            Token::LBracket => "LBracket",
            Token::RBracket => "RBracket",
            Token::Comma => "Comma",
            Token::Semicolon => "Semicolon",
            Token::Comment => "Comment"
        }
    }
}

pub fn Initiate(code: String) -> Vec<Token> {
    lexIt(code)
}

fn lexIt(code: String) -> Vec<Token> {
    let mut tokens : Vec<Token> = vec![]; // OR Vec::new();
    let charCount = code.chars().count();
    let mut i = 0;

    while i <  charCount {

        let mut currentChar = code.chars().nth(i).unwrap();
        // If char is whitespace, just pass the current char
        if currentChar.is_whitespace() {
            i += 1;
        }
        // If char starts with alphabetic characters
        else if currentChar.is_alphabetic() {
            let mut tmp = "".to_string();

            // If current char is not out of our code scope and char starts with alphanumeric (alphabetic or numeric) characters
            while i < charCount && code.chars().nth(i).unwrap().is_alphanumeric() {

                tmp = tmp + &*code.chars().nth(i).unwrap().to_string();
                i += 1;
            }

            //We have the word, now we need to find what it is and tokenize it.
            match &*tmp {
                "main" => tokens.push(Token::Keyword("main".to_string())),
                "int" => tokens.push(Token::Keyword("int".to_string())),
                "string" => tokens.push(Token::Keyword("string".to_string())),
                "bool" => tokens.push(Token::Keyword("bool".to_string())),
                "print" => tokens.push(Token::Keyword("print".to_string())),
                "get" => tokens.push(Token::Keyword("get".to_string())),
                "true" => tokens.push(Token::True),
                "false" => tokens.push(Token::False),
                "return" => tokens.push(Token::Keyword("return".to_string())),
                _ => tokens.push(Token::Identifier(tmp)),
            }
        }
        // If current char is a numerical character
        else if currentChar.is_numeric() {
            let mut tmp = "".to_string();

            while i < charCount && code.chars().nth(i).unwrap().is_numeric() {
                tmp = tmp + &*code.chars().nth(i).unwrap().to_string();
                i += 1;
            }

            tokens.push(Token::Number(tmp));
        }
        // If current char is a starting of a string
        else if currentChar == '"' {
            let mut tmp = "".to_string();
            i += 1;

            while i < charCount && code.chars().nth(i).unwrap() != '"'  {
                tmp = tmp + &*code.chars().nth(i).unwrap().to_string();
                i += 1;
            }

            i += 1;
            tokens.push(Token::String(tmp));
        }
        // If current char is a real char
        else if currentChar == '\'' {
            i += 1;
            let tmp = code.chars().nth(i).unwrap();
            i += 1;

            if code.chars().nth(i).unwrap() == '\'' {
                tokens.push(Token::Char(tmp.to_string()));
                i += 1;
            } else {
                unexpectedToken(code.chars().nth(i).unwrap(), i);
            }
        }
        // If current char is an equals (=)
        else if currentChar == '=' {
            tokens.push(Token::Equals);
            i += 1;
        }
        // If current char is a plus (+)
        else if currentChar == '+' {
            tokens.push(Token::Plus);
            i += 1;
        }
        // If current char is a minus (-)
        else if currentChar == '-' {
            tokens.push(Token::Minus);
            i += 1;
        }
        // If current char is a multiple (*)
        else if currentChar == '*' {
            tokens.push(Token::Multiple);
            i += 1;
        }
        // If current char is a divide (/) or comment ( starts with // )
        else if currentChar == '/' {

            i += 1;
            if i < charCount && code.chars().nth(i).unwrap() == '/' {
                while i < charCount && code.chars().nth(i).unwrap() != '\n' {
                    i += 1;
                }

                i += 1;
                tokens.push(Token::Comment);
            } else {
                tokens.push(Token::Divide);
            }
        }
        // If current char is a mod (%)
        else if currentChar == '%' {
            tokens.push(Token::Mod);
            i += 1;
        }
        // If current char is a greater than (>) or greater than or equal to (>=)
        else if currentChar == '>' {
            if i + 1 < charCount && code.chars().nth(i + 1).unwrap() == '=' {
                tokens.push(Token::GreaterEqual);
                i += 1;
            } else {
                tokens.push(Token::Greater);
            }

            i += 1;
        }
        // If current char is a lesser than (<) or lesser than or equal to (<=)
        else if currentChar == '<' {
            if i < charCount && code.chars().nth(i + 1).unwrap() == '=' {
                tokens.push(Token::LesserEqual);
                i += 1;
            } else {
                tokens.push(Token::Lesser);
            }
            i += 1;
        }
        // If current char is an Open Paranthesis ( ( )
        else if currentChar == '(' {
            tokens.push(Token::LParen);
            i += 1;
        }
        // If current char is a Close Paranthesis ( ) )
        else if currentChar == ')' {
            tokens.push(Token::RParen);
            i += 1;
        }
        // If current char is an Open Braces ( { )
        else if currentChar == '{' {
            tokens.push(Token::LBrace);
            i += 1;
        }
        // If current char is a Close Braces ( } )
        else if currentChar == '}' {
            tokens.push(Token::RBrace);
            i += 1;
        }
        // If current char is an Open Brackets ( [ )
        else if currentChar == '[' {
            tokens.push(Token::LBracket);
            i += 1;
        }
        // If current char is a Close Brackets ( ] )
        else if currentChar == ']' {
            tokens.push(Token::RBracket);
            i += 1;
        }
        // If current char is an semicolon ( ; )
        else if currentChar == ',' {
            tokens.push(Token::Comma);
            i += 1;
        }
        // If current char is an semicolon ( ; )
        else if currentChar == ';' {
            tokens.push(Token::Semicolon);
            i += 1;
        }
        // Else throw an exception
        else {
            unexpectedToken(currentChar, i);
        }
    }

    tokens
}

fn unexpectedToken(c: char, i: usize) {
    panic!("Unexpected token: {:?} at {:?}th letter!", c, i);
}

<commit_msg>Lexer Changes<commit_after>
/*
 * Interpreter for Basic C like language
 * Lexer Module
 */

#[derive(Debug)]
pub enum Token {
    Keyword(String),    // like int, string or let
    Identifier(String), // like variable names
    Char(String),       // Char variables, inside " ' "
    String(String),     // String variables, inside quotes
    Number(String),     // Number variable
    True,               // Boolean true
    False,              // Boolean false
    Equals,             // =
    Plus,               // +
    Minus,              // -
    Multiple,           // *
    Divide,             // /
    Mod,                // %
    Greater,            // >
    Lesser,             // <
    GreaterEqual,       // >=
    LesserEqual,        // <=
    LParen,             // (
    RParen,             // )
    LBrace,             // {
    RBrace,             // }
    LBracket,           // [
    RBracket,           // ]
    Comma,              // ,
    Semicolon,          // ;
    Comment             // '//'
}

impl Token {
    pub fn toString(&self) -> &str {
        match *self {
            Token::Keyword(ref x) => "Keyword",
            Token::Identifier(ref x) => "Identifier",
            Token::Char(ref x) => "Char",
            Token::String(ref x) => "String",
            Token::Number(ref x) => "Number",
            Token::True => "True",
            Token::False => "False",
            Token::Equals => "Equals",
            Token::Plus => "Plus",
            Token::Minus => "Minus",
            Token::Multiple => "Multiple",
            Token::Divide => "Divide",
            Token::Mod => "Mod",
            Token::Greater => "Greater",
            Token::Lesser => "Lesser",
            Token::GreaterEqual => "GreaterEqual",
            Token::LesserEqual => "LesserEqual",
            Token::LParen => "LParen",
            Token::RParen => "RParen",
            Token::LBrace => "LBrace",
            Token::RBrace => "RBrace",
            Token::LBracket => "LBracket",
            Token::RBracket => "RBracket",
            Token::Comma => "Comma",
            Token::Semicolon => "Semicolon",
            Token::Comment => "Comment"
        }
    }
}

pub fn Initiate(code: String) -> Vec<Token> {
    lexIt(code)
}

fn lexIt(code: String) -> Vec<Token> {
    let mut tokens : Vec<Token> = vec![]; // OR Vec::new();
    let charCount = code.chars().count();
    let mut i = 0;

    while i <  charCount {
        let mut currentChar = code.chars().nth(i).unwrap();

        // If char is whitespace, just pass the current char
        if currentChar.is_whitespace() {
            i += 1;
        }
        // If char starts with alphabetic characters
        else if currentChar.is_alphabetic() {
            let mut tmp = "".to_string();

            // If current char is not out of our code scope and char starts with alphanumeric (alphabetic or numeric) characters
            while i < charCount && code.chars().nth(i).unwrap().is_alphanumeric() {

                tmp = tmp + &*code.chars().nth(i).unwrap().to_string();
                i += 1;
            }

            //We have the word, now we need to find what it is and tokenize it.
            let tmpStr = tmp.to_lowercase();
            if isKeyword(&tmpStr) {
                tokens.push(Token::Keyword(tmpStr));
            } else if tmpStr == "true" {
                tokens.push(Token::True);
            } else if tmpStr == "false" {
                tokens.push(Token::False);
            } else {
                tokens.push(Token::Identifier(tmpStr));
            }
        }
        // If current char is a numerical character
        else if currentChar.is_numeric() {
            let mut tmp = "".to_string();

            while i < charCount && code.chars().nth(i).unwrap().is_numeric() {
                tmp = tmp + &*code.chars().nth(i).unwrap().to_string();
                i += 1;
            }

            tokens.push(Token::Number(tmp));
        }
        // If current char is a starting of a string
        else if currentChar == '"' {
            let mut tmp = "".to_string();
            i += 1;

            while i < charCount && code.chars().nth(i).unwrap() != '"'  {
                tmp = tmp + &*code.chars().nth(i).unwrap().to_string();
                i += 1;
            }

            i += 1;
            tokens.push(Token::String(tmp));
        }
        // If current char is a real char
        else if currentChar == '\'' {
            let tmp = code.chars().nth(i + 1).unwrap();
            i += 2;

            if code.chars().nth(i).unwrap() == '\'' {
                tokens.push(Token::Char(tmp.to_string()));
                i += 1;
            } else {
                unexpectedToken(code.chars().nth(i).unwrap(), i);
            }
        }
        // If current char is an equals (=)
        else if currentChar == '=' {
            tokens.push(Token::Equals);
            i += 1;
        }
        // If current char is a plus (+)
        else if currentChar == '+' {
            tokens.push(Token::Plus);
            i += 1;
        }
        // If current char is a minus (-)
        else if currentChar == '-' {
            tokens.push(Token::Minus);
            i += 1;
        }
        // If current char is a multiple (*)
        else if currentChar == '*' {
            tokens.push(Token::Multiple);
            i += 1;
        }
        // If current char is a divide (/) or comment ( starts with // )
        else if currentChar == '/' {

            i += 1;
            if i < charCount && code.chars().nth(i).unwrap() == '/' {
                while i < charCount && code.chars().nth(i).unwrap() != '\n' {
                    i += 1;
                }

                i += 1;
                tokens.push(Token::Comment);
            } else {
                tokens.push(Token::Divide);
            }
        }
        // If current char is a mod (%)
        else if currentChar == '%' {
            tokens.push(Token::Mod);
            i += 1;
        }
        // If current char is a greater than (>) or greater than or equal to (>=)
        else if currentChar == '>' {
            if i + 1 < charCount && code.chars().nth(i + 1).unwrap() == '=' {
                tokens.push(Token::GreaterEqual);
                i += 1;
            } else {
                tokens.push(Token::Greater);
            }

            i += 1;
        }
        // If current char is a lesser than (<) or lesser than or equal to (<=)
        else if currentChar == '<' {
            if i < charCount && code.chars().nth(i + 1).unwrap() == '=' {
                tokens.push(Token::LesserEqual);
                i += 1;
            } else {
                tokens.push(Token::Lesser);
            }
            i += 1;
        }
        // If current char is an Open Paranthesis ( ( )
        else if currentChar == '(' {
            tokens.push(Token::LParen);
            i += 1;
        }
        // If current char is a Close Paranthesis ( ) )
        else if currentChar == ')' {
            tokens.push(Token::RParen);
            i += 1;
        }
        // If current char is an Open Braces ( { )
        else if currentChar == '{' {
            tokens.push(Token::LBrace);
            i += 1;
        }
        // If current char is a Close Braces ( } )
        else if currentChar == '}' {
            tokens.push(Token::RBrace);
            i += 1;
        }
        // If current char is an Open Brackets ( [ )
        else if currentChar == '[' {
            tokens.push(Token::LBracket);
            i += 1;
        }
        // If current char is a Close Brackets ( ] )
        else if currentChar == ']' {
            tokens.push(Token::RBracket);
            i += 1;
        }
        // If current char is an semicolon ( ; )
        else if currentChar == ',' {
            tokens.push(Token::Comma);
            i += 1;
        }
        // If current char is an semicolon ( ; )
        else if currentChar == ';' {
            tokens.push(Token::Semicolon);
            i += 1;
        }
        // Else throw an exception
        else {
            unexpectedToken(currentChar, i);
        }
    }

    tokens
}

fn isKeyword(value: &String) -> bool {
    let valueStr = &*value;
    value == "main" || value == "int" || value == "string" || value == "bool" || value == "print" || value == "get" || value == "return"
}

fn unexpectedToken(c: char, i: usize) {
    panic!("Unexpected token: {:?} at {:?}th letter!", c, i);
}
<|endoftext|>


<commit_before>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use autocxx_engine::parse_file;
use clap::{crate_authors, crate_version, App, Arg, SubCommand};
use indoc::indoc;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;

fn main() {
    let matches = App::new("autocxx-gen")
        .version(crate_version!())
        .author(crate_authors!())
        .about("Generates C++ files from Rust files that contain include_cpp! macros")
        .long_about(indoc! {"
                Command line utility to expand the Rust 'autocxx'
                include_cpp macro. Normal usage here is to use the gen-cpp
                subcommand to generate the .cpp and .h side of the bindings,
                such that you can build them and link them to Rust code.
                The Rust side of the bindings will be expanded automatically
                as part of the Rust compilation process, by virtue of procedural
                macro expansion. You can, however, also use this utility
                to expand the Rust code if you wish to avoid a dependency
                on a C++ include path within your Rust build process.
        "})
        .arg(
            Arg::with_name("INPUT")
                .help("Sets the input .rs file to use")
                .required(true)
                .index(1),
        )
        .arg(
            Arg::with_name("outdir")
                .long("outdir")
                .value_name("PATH")
                .help("output directory path")
                .takes_value(true),
        )
        .arg(
            Arg::with_name("inc")
                .long("inc")
                .value_name("INCLUDE DIRS")
                .help("include path")
                .takes_value(true),
        )
        .subcommand(
            SubCommand::with_name("gen-cpp")
                .help("Generate C++ .cpp and .h files. Normal mode of operation.")
                .arg(
                    Arg::with_name("pattern")
                        .long("pattern")
                        .value_name("PATTERN")
                        .help(".h and .cpp output pattern")
                        .default_value("gen")
                        .takes_value(true),
                )
                .arg(
                    Arg::with_name("cpp-extension")
                        .long("cpp-extension")
                        .value_name("EXTENSION")
                        .default_value("cc")
                        .help("include path")
                        .takes_value(true),
                )
                .arg(
                    Arg::with_name("generate-exact")
                        .long("generate-exact")
                        .value_name("NUM")
                        .help("always generate this number of .cc and .h files")
                        .takes_value(true),
                ),
        )
        .subcommand(SubCommand::with_name("gen-rs").help("Generate expanded Rust file."))
        .get_matches();
    let mut include_cxxs = parse_file(matches.value_of("INPUT").unwrap(), matches.value_of("inc"))
        .expect("Unable to parse Rust file and interpret autocxx macro");
    let outdir: PathBuf = matches.value_of_os("outdir").unwrap().into();
    if let Some(matches) = matches.subcommand_matches("gen-cpp") {
        let pattern = matches.value_of("pattern").unwrap_or("gen");
        let cpp = matches.value_of("cpp-extension").unwrap_or("cc");
        let desired_number = matches
            .value_of("generate-exact")
            .map(|s| s.parse::<usize>().unwrap());
        let mut counter = 0usize;
        for include_cxx in include_cxxs {
            let generations = include_cxx
                .generate_h_and_cxx()
                .expect("Unable to generate header and C++ code");
            for pair in generations.0 {
                let cppname = format!("{}{}.{}", pattern, counter, cpp);
                write_to_file(&outdir, cppname, &pair.implementation);
                write_to_file(&outdir, pair.header_name, &pair.header);
                counter += 1;
            }
        }
        if let Some(desired_number) = desired_number {
            while counter < desired_number {
                write_cpp_file(
                    &outdir,
                    pattern,
                    cpp,
                    counter,
                    "// Blank C++ file generated by autocxx".as_bytes(),
                );
                counter += 1;
            }
        }
    } else if matches.subcommand_matches("gen-rs").is_some() {
        for (count, include_cxx) in include_cxxs.drain(..).enumerate() {
            let ts = include_cxx
                .generate_rs()
                .expect("Unable to generate Rust TokenStream");
            let ts = ts.to_string();
            write_to_file(&outdir, format!("gen{}.rs", count), ts.as_bytes());
        }
    } else {
        panic!("Must specify a subcommand");
    }
}

fn write_cpp_file(outdir: &PathBuf, pattern: &str, cpp: &str, counter: usize, content: &[u8]) {
    let cppname = format!("{}{}.{}", pattern, counter, cpp);
    write_to_file(outdir, cppname, content);
}

fn write_to_file(dir: &PathBuf, filename: String, content: &[u8]) {
    let path = dir.join(filename);
    let mut f = File::create(&path).expect("Unable to create file");
    f.write_all(content).expect("Unable to write file");
}
<commit_msg>Adjust args<commit_after>// Copyright 2020 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use autocxx_engine::parse_file;
use clap::{crate_authors, crate_version, App, Arg, SubCommand};
use indoc::indoc;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;

fn main() {
    let matches = App::new("autocxx-gen")
        .version(crate_version!())
        .author(crate_authors!())
        .about("Generates C++ files from Rust files that contain include_cpp! macros")
        .long_about(indoc! {"
                Command line utility to expand the Rust 'autocxx'
                include_cpp macro. Normal usage here is to use the gen-cpp
                subcommand to generate the .cpp and .h side of the bindings,
                such that you can build them and link them to Rust code.
                The Rust side of the bindings will be expanded automatically
                as part of the Rust compilation process, by virtue of procedural
                macro expansion. You can, however, also use this utility
                to expand the Rust code if you wish to avoid a dependency
                on a C++ include path within your Rust build process.
        "})
        .arg(
            Arg::with_name("INPUT")
                .help("Sets the input .rs file to use")
                .required(true)
                .index(1),
        )
        .arg(
            Arg::with_name("outdir")
                .short("o")
                .long("outdir")
                .value_name("PATH")
                .help("output directory path")
                .takes_value(true)
                .required(true),
        )
        .arg(
            Arg::with_name("inc")
                .long("inc")
                .value_name("INCLUDE DIRS")
                .help("include path")
                .takes_value(true),
        )
        .subcommand(
            SubCommand::with_name("gen-cpp")
                .help("Generate C++ .cpp and .h files. Normal mode of operation.")
                .arg(
                    Arg::with_name("pattern")
                        .long("pattern")
                        .value_name("PATTERN")
                        .help(".h and .cpp output pattern")
                        .default_value("gen")
                        .takes_value(true),
                )
                .arg(
                    Arg::with_name("cpp-extension")
                        .long("cpp-extension")
                        .value_name("EXTENSION")
                        .default_value("cc")
                        .help("include path")
                        .takes_value(true),
                )
                .arg(
                    Arg::with_name("generate-exact")
                        .long("generate-exact")
                        .value_name("NUM")
                        .help("always generate this number of .cc and .h files")
                        .takes_value(true),
                ),
        )
        .subcommand(SubCommand::with_name("gen-rs").help("Generate expanded Rust file."))
        .get_matches();
    let mut include_cxxs = parse_file(matches.value_of("INPUT").unwrap(), matches.value_of("inc"))
        .expect("Unable to parse Rust file and interpret autocxx macro");
    let outdir: PathBuf = matches.value_of_os("outdir").unwrap().into();
    if let Some(matches) = matches.subcommand_matches("gen-cpp") {
        let pattern = matches.value_of("pattern").unwrap_or("gen");
        let cpp = matches.value_of("cpp-extension").unwrap_or("cc");
        let desired_number = matches
            .value_of("generate-exact")
            .map(|s| s.parse::<usize>().unwrap());
        let mut counter = 0usize;
        for include_cxx in include_cxxs {
            let generations = include_cxx
                .generate_h_and_cxx()
                .expect("Unable to generate header and C++ code");
            for pair in generations.0 {
                let cppname = format!("{}{}.{}", pattern, counter, cpp);
                write_to_file(&outdir, cppname, &pair.implementation);
                write_to_file(&outdir, pair.header_name, &pair.header);
                counter += 1;
            }
        }
        if let Some(desired_number) = desired_number {
            while counter < desired_number {
                write_cpp_file(
                    &outdir,
                    pattern,
                    cpp,
                    counter,
                    "// Blank C++ file generated by autocxx".as_bytes(),
                );
                counter += 1;
            }
        }
    } else if matches.subcommand_matches("gen-rs").is_some() {
        for (count, include_cxx) in include_cxxs.drain(..).enumerate() {
            let ts = include_cxx
                .generate_rs()
                .expect("Unable to generate Rust TokenStream");
            let ts = ts.to_string();
            write_to_file(&outdir, format!("gen{}.rs", count), ts.as_bytes());
        }
    } else {
        panic!("Must specify a subcommand");
    }
}

fn write_cpp_file(outdir: &PathBuf, pattern: &str, cpp: &str, counter: usize, content: &[u8]) {
    let cppname = format!("{}{}.{}", pattern, counter, cpp);
    write_to_file(outdir, cppname, content);
}

fn write_to_file(dir: &PathBuf, filename: String, content: &[u8]) {
    let path = dir.join(filename);
    let mut f = File::create(&path).expect("Unable to create file");
    f.write_all(content).expect("Unable to write file");
}
<|endoftext|>