<commit_before>pub mod bldr;
pub mod cli;
pub mod config;
pub mod file;
pub mod license;
pub mod origin;
pub mod pkg;
pub mod plan;
pub mod ring;
pub mod studio;
pub mod sup;
pub mod svc;
#[cfg(test)]
mod tests;
pub mod user;
pub mod util;

use self::{bldr::{Bldr,
                  ConfigOptBldr},
           cli::{Cli,
                 ConfigOptCli},
           config::{ConfigOptServiceConfig,
                    ConfigOptServiceConfigApply,
                    ServiceConfig,
                    ServiceConfigApply},
           file::{ConfigOptFile,
                  File},
           license::{ConfigOptLicense,
                     License},
           origin::{ConfigOptOrigin,
                    Origin},
           pkg::{ConfigOptPkg,
                 ConfigOptPkgInstall,
                 Pkg,
                 PkgInstall},
           plan::{ConfigOptPlan,
                  Plan},
           ring::{ConfigOptRing,
                  Ring},
           studio::{ConfigOptStudio,
                    Studio},
           sup::{ConfigOptHabSup,
                 ConfigOptSupRun,
                 HabSup,
                 SupRun},
           svc::{ConfigOptSvc,
                 ConfigOptSvcStart,
                 ConfigOptSvcStop,
                 Svc,
                 SvcStart,
                 SvcStop},
           user::{ConfigOptUser,
                  User},
           util::{CacheKeyPath,
                  ConfigOptCacheKeyPath}};
use crate::{cli::AFTER_HELP,
            VERSION};
use configopt::ConfigOpt;
use structopt::{clap::AppSettings,
                StructOpt};

#[derive(ConfigOpt, StructOpt)]
#[structopt(name = "hab",
            version = VERSION,
            about = "Patents: https://chef.io/patents\n\"A Habitat is the natural environment for your services\" - Alan Turing",
            author = "\nThe Habitat Maintainers <humans@habitat.sh>\n",
            settings = &[AppSettings::GlobalVersion],
            after_help = AFTER_HELP
        )]
#[allow(clippy::large_enum_variant)]
pub enum Hab {
    #[structopt(no_version)]
    Bldr(Bldr),
    #[structopt(no_version)]
    Cli(Cli),
    #[structopt(no_version)]
    Config(ServiceConfig),
    #[structopt(no_version)]
    File(File),
    #[structopt(no_version)]
    License(License),
    #[structopt(no_version)]
    Origin(Origin),
    #[structopt(no_version)]
    Pkg(Pkg),
    #[structopt(no_version)]
    Plan(Plan),
    #[structopt(no_version)]
    Ring(Ring),
    #[structopt(no_version, aliases = &["stu", "stud", "studi"])]
    Studio(Studio),
    #[structopt(no_version)]
    Sup(HabSup),
    /// Create a tarball of Habitat Supervisor data to send to support
    #[structopt(no_version)]
    Supportbundle,
    #[structopt(no_version)]
    Svc(Svc),
    #[structopt(no_version)]
    User(User),

    /// Alias for 'config apply'
    #[structopt(no_version, settings = &[AppSettings::Hidden])]
    Apply(ServiceConfigApply),
    /// Alias for 'pkg install'
    #[structopt(no_version, settings = &[AppSettings::Hidden])]
    Install(PkgInstall),
    #[cfg(not(target_os = "macos"))]
    /// Alias for 'sup run'
    #[structopt(no_version, settings = &[AppSettings::Hidden])]
    Run(SupRun),
    /// Alias for 'cli setup'
    #[structopt(no_version, settings = &[AppSettings::Hidden])]
    Setup(CacheKeyPath),
    /// Alias for 'svc start'
    #[structopt(no_version, settings = &[AppSettings::Hidden])]
    Start(SvcStart),
    /// Alias for 'svc stop'
    #[structopt(no_version, settings = &[AppSettings::Hidden])]
    Stop(SvcStop),
    #[cfg(not(target_os = "macos"))]
    /// Alias for 'sup term'
    #[structopt(no_version, settings = &[AppSettings::Hidden])]
    Term,
}
<commit_msg>Added aliases<commit_after>pub mod bldr;
pub mod cli;
pub mod config;
pub mod file;
pub mod license;
pub mod origin;
pub mod pkg;
pub mod plan;
pub mod ring;
pub mod studio;
pub mod sup;
pub mod svc;
#[cfg(test)]
mod tests;
pub mod user;
pub mod util;

use self::{bldr::{Bldr,
                  ConfigOptBldr},
           cli::{Cli,
                 ConfigOptCli},
           config::{ConfigOptServiceConfig,
                    ConfigOptServiceConfigApply,
                    ServiceConfig,
                    ServiceConfigApply},
           file::{ConfigOptFile,
                  File},
           license::{ConfigOptLicense,
                     License},
           origin::{ConfigOptOrigin,
                    Origin},
           pkg::{ConfigOptPkg,
                 ConfigOptPkgInstall,
                 Pkg,
                 PkgInstall},
           plan::{ConfigOptPlan,
                  Plan},
           ring::{ConfigOptRing,
                  Ring},
           studio::{ConfigOptStudio,
                    Studio},
           sup::{ConfigOptHabSup,
                 ConfigOptSupRun,
                 HabSup,
                 SupRun},
           svc::{ConfigOptSvc,
                 ConfigOptSvcStart,
                 ConfigOptSvcStop,
                 Svc,
                 SvcStart,
                 SvcStop},
           user::{ConfigOptUser,
                  User},
           util::{CacheKeyPath,
                  ConfigOptCacheKeyPath}};
use crate::{cli::AFTER_HELP,
            VERSION};
use configopt::ConfigOpt;
use structopt::{clap::AppSettings,
                StructOpt};

#[derive(ConfigOpt, StructOpt)]
#[structopt(name = "hab",
            version = VERSION,
            about = "Patents: https://chef.io/patents\n\"A Habitat is the natural environment for your services\" - Alan Turing",
            author = "\nThe Habitat Maintainers <humans@habitat.sh>\n",
            settings = &[AppSettings::GlobalVersion],
            after_help = AFTER_HELP
        )]
#[allow(clippy::large_enum_variant)]
pub enum Hab {
    #[structopt(no_version)]
    Bldr(Bldr),
    #[structopt(no_version)]
    Cli(Cli),
    #[structopt(no_version)]
    Config(ServiceConfig),
    #[structopt(no_version)]
    File(File),
    #[structopt(no_version)]
    License(License),
    #[structopt(no_version)]
    Origin(Origin),
    #[structopt(no_version)]
    Pkg(Pkg),
    #[structopt(no_version)]
    Plan(Plan),
    #[structopt(no_version)]
    Ring(Ring),
    #[structopt(no_version, aliases = &["stu", "stud", "studi"])]
    Studio(Studio),
    #[structopt(no_version)]
    Sup(HabSup),
    /// Create a tarball of Habitat Supervisor data to send to support
    #[structopt(no_version)]
    Supportbundle,
    #[structopt(no_version)]
    Svc(Svc),
    #[structopt(no_version)]
    User(User),

    /// Alias for 'config apply'
    #[structopt(no_version, settings = &[AppSettings::Hidden])]
    Apply(ServiceConfigApply),
    /// Alias for 'pkg install'
    #[structopt(no_version, settings = &[AppSettings::Hidden], aliases = &["i", "in", "ins", "inst", "insta", "instal"])]
    Install(PkgInstall),
    #[cfg(not(target_os = "macos"))]
    /// Alias for 'sup run'
    #[structopt(no_version, settings = &[AppSettings::Hidden])]
    Run(SupRun),
    /// Alias for 'cli setup'
    #[structopt(no_version, settings = &[AppSettings::Hidden], aliases = &["set", "setu"])]
    Setup(CacheKeyPath),
    /// Alias for 'svc start'
    #[structopt(no_version, settings = &[AppSettings::Hidden], aliases = &["sta", "star"])]
    Start(SvcStart),
    /// Alias for 'svc stop'
    #[structopt(no_version, settings = &[AppSettings::Hidden], aliases = &["sto"])]
    Stop(SvcStop),
    #[cfg(not(target_os = "macos"))]
    /// Alias for 'sup term'
    #[structopt(no_version, settings = &[AppSettings::Hidden])]
    Term,
}
<|endoftext|>


<commit_before>extern crate chrono;

use chrono::prelude::*;
use regex::{Regex, Captures};

#[derive(Debug)]
pub enum Command {
    BadCommand,
    OneTimeEvent(OneTimeEventImpl),
}

#[derive(Debug)]
pub struct OneTimeEventImpl{
    pub event_time : DateTime<Utc>,
    pub event_text : String,
}

// const MOMENT_REGEX: &str =
//     r"(?P<day>[\d]*)(?:-(?P<month>[\d]*))?(?:-(?P<year>[\d]*))? (?P<hour>[\d]*).(?P<minute>[\d]*)";

// const DURATION_REGEX: &str =
//     r"";

pub fn parse_command(command_line : String) -> Command {
    let command_line = String::from(command_line.trim());
    debug!("parse incoming text: {}", command_line);

    let mut result;
    result = try_parse_for(&command_line);
    if result.is_some() {
        return result.unwrap();
    }

    result = try_parse_at(&command_line);
    if result.is_some() {
        return result.unwrap();
    }

    warn!("parse_command: line {} doesn't match any regex", command_line);
    Command::BadCommand
}

fn try_parse_at(command_line : &String) -> Option<Command>{
    let time_format = Regex::new(r"[at|в]\s*(?P<day>[\d]*)(?:-(?P<month>[\d]*))?(?:-(?P<year>[\d]*))? (?P<hour>[\d]*).(?P<minute>[\d]*) (?P<main_text>.*)").unwrap();

    let date_captures = time_format.captures(command_line);
    if date_captures.is_none() {

        return None;
    }
    let date_captures = date_captures.unwrap();
    let text = date_captures.name("main_text").unwrap().as_str();

    const DEFAULT_TZ : i64 = -3;
    let dt = chrono::Duration::seconds(DEFAULT_TZ * 60 * 60);
    let d = get_datetime_from_capture(&date_captures) + dt;

    Some(Command::OneTimeEvent
            (OneTimeEventImpl
                { event_text : String::from(text)
                , event_time : d }
            ))
}

fn try_parse_for(command_line : &String) -> Option<Command>{
    let reg_main    = Regex::new(r"(?P<spec>[\d\w]*)(?P<divider> )(?P<main_text>.*)").unwrap();

    let reg_day     = r"(?P<days>[\d]*)[D|d|Д|д]";
    let reg_hour    = r"(?P<hours>[\d]*)[H|h|Ч|ч]";
    let reg_min     = r"(?P<minuts>[\d]*)[M|m|М|м]";
    let reg_sec     = r"(?P<seconds>[\d]*)[S|s|С|с]";

    let caps = reg_main.captures(command_line);
    if caps.is_none() {
        return None;
    }
    let caps = caps.unwrap();
    let spec = caps.name("spec").unwrap().as_str();
    let text = caps.name("main_text").unwrap().as_str();

    let days    = get_first_regex_group_as_u32(reg_day,  spec);
    let hours   = get_first_regex_group_as_u32(reg_hour, spec);
    let minutes = get_first_regex_group_as_u32(reg_min,  spec);
    let seconds = get_first_regex_group_as_u32(reg_sec,  spec);

    if days == 0 && hours == 0 && minutes == 0 && seconds == 0 {
        return None;
    }

    // TODO: should we a better way to do this
    let dt = chrono::Duration::seconds((days as i64) * (60*60*24)
                                    + (hours as i64) * (60*60)
                                    + (minutes as i64) * 60
                                    + (seconds as i64)
                                    );

    let event_time = Utc::now() + dt;

    Some(Command::OneTimeEvent(OneTimeEventImpl
            { event_text : String::from(text)
            , event_time : event_time }
        ))
}

fn get_first_regex_group_as_u32(reg : &str, text : &str) -> u32{
    let reg = Regex::new(reg).expect("get_first_regex_group_as_u32: wrong regex string");
    let number = match reg.captures(text){
        None => "0",
        Some(d) => d.get(1)
            .expect("get_first_regex_group_as_u32: expect regex string with at least 1 group")
            .as_str(),
    };
    number.parse().unwrap_or(0)
}

fn get_datetime_from_capture(cap: &Captures) -> DateTime<Utc>{
    let day = cap.name("day").unwrap().as_str().parse().unwrap();
    let hour = cap.name("hour").unwrap().as_str().parse().unwrap();
    let minute = cap.name("minute").unwrap().as_str().parse().unwrap();

    let now = Utc::now();

    let month = match cap.name("month"){
        None => now.month(),
        Some(m) => m.as_str().parse().unwrap(),
    };

    let year = match cap.name("year"){
        None => now.year(),
        Some(m) => m.as_str().parse().unwrap(),
    };

    Utc.ymd(year, month, day).and_hms(hour, minute, 0)
}

//-------- TESTS ---------------------------------------------------------------

#[cfg(test)]
mod tests {
    use super::*;
    use command::Command::*;

    #[test]
    fn parse_for_general() {
        let command = String::from("1d2h3m4s");
        let text = "some text";
        let command_text = command + " " + text;
        let dt = chrono::Duration::seconds((1 as i64) * (60*60*24)  // days
                                        + (2 as i64) * (60*60)      // hours
                                        + (3 as i64) * 60           // minutes
                                        + (4 as i64)                // seconds
                                        );
        let result = try_parse_for(&command_text);
        assert!(result.is_some());
        match result.unwrap(){
            OneTimeEvent(res) => {
                assert_eq!(res.event_text, text);
                assert!(time_moment_eq(res.event_time, Utc::now() + dt));
            },
            _ => panic!("Wrong command type")
        };
    }

    #[test]
    fn parse_for_hm() {
        let command = String::from("2h30m");
        let text = "some text";
        let command_text = command + " " + text;
        let dt = chrono::Duration::seconds((0 as i64) * (60*60*24)  // days
                                        + (2 as i64) * (60*60)      // hours
                                        + (30 as i64) * 60           // minutes
                                        + (0 as i64)                // seconds
                                        );
        let result = try_parse_for(&command_text);
        assert!(result.is_some());
        match result.unwrap(){
            OneTimeEvent(res) => {
                assert_eq!(res.event_text, text);
                assert!(time_moment_eq(res.event_time, Utc::now() + dt));
            },
            _ => panic!("Wrong command type")
        };
    }

    #[test]
    #[ignore]
    fn parse_for_negative() {
        let command = String::from("1d-2h3m4s");
        let text = "some text";
        let command_text = command + " " + text;
        let result = try_parse_for(&command_text);
        assert!(result.is_some());
        match result.unwrap(){
            BadCommand => {},
            _ => panic!("Wrong command type")
        };
    }

    #[test]
    #[ignore]
    fn parse_for_misspell() {
        let command = String::from("1d2j3m4s");
        let text = "some text";
        let command_text = command + " " + text;
        let result = try_parse_for(&command_text);
        assert!(result.is_some());
        match result.unwrap(){
            BadCommand => {},
            _ => panic!("Wrong command type")
        };
    }

    #[test]
    fn parse_at_tests() {
        {
            let command = String::from("24-10 18:30");
            let text = "some text";
            let mut command_text = command + " " + text;
            command_text.insert_str(0, "at");
            let t = Utc.ymd(2017, 10, 24).and_hms(18-3, 30, 0);

            let result = try_parse_at(&command_text);
            assert!(result.is_some());
            match result.unwrap(){
                OneTimeEvent(res) => {
                    assert_eq!(res.event_text, text);
                    assert_eq!(res.event_time, t);
                },
                _ => panic!("Wrong command type")
            };
        }

        {
            let command = String::from("24 18:30");
            let text = "some text";
            let mut command_text = command + " " + text;
            command_text.insert_str(0, "at");
            let t = Utc.ymd(2017, 9, 24).and_hms(18-3, 30, 0);

            let result = try_parse_at(&command_text);
            assert!(result.is_some());
            match result.unwrap(){
                OneTimeEvent(res) => {
                    assert_eq!(res.event_text, text);
                    assert_eq!(res.event_time, t);
                },
                _ => panic!("Wrong command type")
            };
        }
    }

    fn time_moment_eq(t1: DateTime<Utc>, t2: DateTime<Utc>) -> bool{
        t1.signed_duration_since(t2).num_milliseconds().abs() < 100
    }
}<commit_msg>Regex modification and tests fix<commit_after>extern crate chrono;

use chrono::prelude::*;
use regex::{Regex, Captures};

#[derive(Debug)]
pub enum Command {
    BadCommand,
    OneTimeEvent(OneTimeEventImpl),
}

#[derive(Debug)]
pub struct OneTimeEventImpl{
    pub event_time : DateTime<Utc>,
    pub event_text : String,
}

const MOMENT_REGEX: &str =
    r"(?P<day>[\d]*)(?:-(?P<month>[\d]*))?(?:-(?P<year>[\d]*))? (?P<hour>[\d]*).(?P<minute>[\d]*)";

const DURATION_REGEX: &str =
    r"(:?(?P<days>[\d]*)[D|d|Д|д])?(:?(?P<hours>[\d]*)[H|h|Ч|ч])?(:?(?P<minuts>[\d]*)[M|m|М|м])?(:?(?P<seconds>[\d]*)[S|s|С|с])?";

pub fn parse_command(command_line : String) -> Command {
    let command_line = String::from(command_line.trim());
    debug!("parse incoming text: {}", command_line);

    let mut result;
    result = try_parse_for(&command_line);
    if result.is_some() {
        return result.unwrap();
    }

    result = try_parse_at(&command_line);
    if result.is_some() {
        return result.unwrap();
    }

    warn!("parse_command: line {} doesn't match any regex", command_line);
    Command::BadCommand
}

fn try_parse_at(command_line : &String) -> Option<Command>{
    let reg = String::from(r"[at|в]\s*") + MOMENT_REGEX + " (?P<main_text>.*)";
    let time_format = Regex::new(&reg[..]).unwrap();

    let date_captures = time_format.captures(command_line);
    if date_captures.is_none() {
        return None;
    }
    let date_captures = date_captures.unwrap();
    let text = date_captures.name("main_text").unwrap().as_str();

    const DEFAULT_TZ : i64 = -3;
    let dt = chrono::Duration::seconds(DEFAULT_TZ * 60 * 60);
    let d = get_datetime_from_capture(&date_captures) + dt;

    Some(Command::OneTimeEvent
            (OneTimeEventImpl
                { event_text : String::from(text)
                , event_time : d }
            ))
}

fn try_parse_for(command_line : &String) -> Option<Command>{
    let reg_main    = Regex::new(r"^(?P<spec>[\d|D|d|Д|д|H|h|Ч|ч|M|m|М|м|S|s|С|с]*)(?P<divider> )(?P<main_text>.*)").unwrap();

    let reg_day     = r"(?P<days>[\d]*)[D|d|Д|д]";
    let reg_hour    = r"(?P<hours>[\d]*)[H|h|Ч|ч]";
    let reg_min     = r"(?P<minuts>[\d]*)[M|m|М|м]";
    let reg_sec     = r"(?P<seconds>[\d]*)[S|s|С|с]";

    let caps = reg_main.captures(command_line);
    if caps.is_none() {
        return None;
    }
    let caps = caps.unwrap();
    let spec = caps.name("spec").unwrap().as_str();
    let text = caps.name("main_text").unwrap().as_str();

    let days    = get_first_regex_group_as_u32(reg_day,  spec);
    let hours   = get_first_regex_group_as_u32(reg_hour, spec);
    let minutes = get_first_regex_group_as_u32(reg_min,  spec);
    let seconds = get_first_regex_group_as_u32(reg_sec,  spec);

    if days == 0 && hours == 0 && minutes == 0 && seconds == 0 {
        return None;
    }

    // TODO: should we a better way to do this
    let dt = chrono::Duration::seconds((days as i64) * (60*60*24)
                                    + (hours as i64) * (60*60)
                                    + (minutes as i64) * 60
                                    + (seconds as i64)
                                    );

    let event_time = Utc::now() + dt;

    Some(Command::OneTimeEvent(OneTimeEventImpl
            { event_text : String::from(text)
            , event_time : event_time }
        ))
}

fn get_first_regex_group_as_u32(reg : &str, text : &str) -> u32{
    let reg = Regex::new(reg).expect("get_first_regex_group_as_u32: wrong regex string");
    let number = match reg.captures(text){
        None => "0",
        Some(d) => d.get(1)
            .expect("get_first_regex_group_as_u32: expect regex string with at least 1 group")
            .as_str(),
    };
    number.parse().unwrap_or(0)
}

fn get_datetime_from_capture(cap: &Captures) -> DateTime<Utc>{
    let day = cap.name("day").unwrap().as_str().parse().unwrap();
    let hour = cap.name("hour").unwrap().as_str().parse().unwrap();
    let minute = cap.name("minute").unwrap().as_str().parse().unwrap();

    let now = Utc::now();

    let month = match cap.name("month"){
        None => now.month(),
        Some(m) => m.as_str().parse().unwrap(),
    };

    let year = match cap.name("year"){
        None => now.year(),
        Some(m) => m.as_str().parse().unwrap(),
    };

    Utc.ymd(year, month, day).and_hms(hour, minute, 0)
}

//-------- TESTS ---------------------------------------------------------------

#[cfg(test)]
mod tests {
    use super::*;
    use command::Command::*;

    #[test]
    fn parse_for_general() {
        let command = String::from("1d2h3m4s");
        let text = "some text";
        let command_text = command + " " + text;
        let dt = chrono::Duration::seconds((1 as i64) * (60*60*24)  // days
                                        + (2 as i64) * (60*60)      // hours
                                        + (3 as i64) * 60           // minutes
                                        + (4 as i64)                // seconds
                                        );
        let result = try_parse_for(&command_text);
        assert!(result.is_some());
        match result.unwrap(){
            OneTimeEvent(res) => {
                assert_eq!(res.event_text, text);
                assert!(time_moment_eq(res.event_time, Utc::now() + dt));
            },
            _ => panic!("Wrong command type")
        };
    }

    #[test]
    fn parse_for_hm() {
        let command = String::from("2h30m");
        let text = "some text";
        let command_text = command + " " + text;
        let dt = chrono::Duration::seconds((0 as i64) * (60*60*24)  // days
                                        + (2 as i64) * (60*60)      // hours
                                        + (30 as i64) * 60           // minutes
                                        + (0 as i64)                // seconds
                                        );
        let result = try_parse_for(&command_text);
        assert!(result.is_some());
        match result.unwrap(){
            OneTimeEvent(res) => {
                assert_eq!(res.event_text, text);
                assert!(time_moment_eq(res.event_time, Utc::now() + dt));
            },
            _ => panic!("Wrong command type")
        };
    }

    #[test]
    // #[ignore]
    fn parse_for_negative() {
        let command = String::from("1d-2h3m4s");
        let text = "some text";
        let command_text = command + " " + text;
        let result = try_parse_for(&command_text);
        assert!(result.is_none());
    }

    #[test]
    // #[ignore]
    fn parse_for_misspell() {
        let command = String::from("1d2j3m4s");
        let text = "some text";
        let command_text = command + " " + text;
        let result = try_parse_for(&command_text);
        assert!(result.is_none());
    }

    #[test]
    fn parse_at_tests() {
        {
            let command = String::from("24-10 18:30");
            let text = "some text";
            let mut command_text = command + " " + text;
            command_text.insert_str(0, "at");
            let now = Utc::now();
            let t = Utc.ymd(now.year(), 10, 24).and_hms(18-3, 30, 0);

            let result = try_parse_at(&command_text);
            assert!(result.is_some());
            match result.unwrap(){
                OneTimeEvent(res) => {
                    assert_eq!(res.event_text, text);
                    assert_eq!(res.event_time, t);
                },
                _ => panic!("Wrong command type")
            };
        }

        {
            let command = String::from("24 18:30");
            let text = "some text";
            let mut command_text = command + " " + text;
            command_text.insert_str(0, "at");
            let now = Utc::now();
            let t = Utc.ymd(now.year(), now.month(), 24).and_hms(18-3, 30, 0);

            let result = try_parse_at(&command_text);
            assert!(result.is_some());
            match result.unwrap(){
                OneTimeEvent(res) => {
                    assert_eq!(res.event_text, text);
                    assert_eq!(res.event_time, t);
                },
                _ => panic!("Wrong command type")
            };
        }
    }

    fn time_moment_eq(t1: DateTime<Utc>, t2: DateTime<Utc>) -> bool{
        t1.signed_duration_since(t2).num_milliseconds().abs() < 100
    }
}<|endoftext|>


<commit_before>//! CLI tool to compile cretonne IL into native code.
//!
//! Reads IR files into Cretonne IL and compiles it.

use cton_reader::parse_test;
use std::path::PathBuf;
use cretonne::Context;
use cretonne::settings::FlagsOrIsa;
use std::path::Path;
use utils::{pretty_error, read_to_string, parse_sets_and_isa};

pub fn run(
    files: Vec<String>,
    flag_print: bool,
    mut flag_set: Vec<String>,
    flag_isa: String,
) -> Result<(), String> {
    // Enable the verifier by default, since we're reading IL in from a
    // text file.
    flag_set.insert(0, "enable_verifier=1".to_string());

    let parsed = parse_sets_and_isa(flag_set, flag_isa)?;

    for filename in files {
        let path = Path::new(&filename);
        let name = String::from(path.as_os_str().to_string_lossy());
        handle_module(flag_print, path.to_path_buf(), name, parsed.as_fisa())?;
    }
    Ok(())
}

fn handle_module(
    flag_print: bool,
    path: PathBuf,
    name: String,
    fisa: FlagsOrIsa,
) -> Result<(), String> {
    let buffer = read_to_string(&path).map_err(
        |e| format!("{}: {}", name, e),
    )?;
    let test_file = parse_test(&buffer).map_err(|e| format!("{}: {}", name, e))?;

    // If we have an isa from the command-line, use that. Otherwise if the
    // file contins a unique isa, use that.
    let isa = if let Some(isa) = fisa.isa {
        isa
    } else if let Some(isa) = test_file.isa_spec.unique_isa() {
        isa
    } else {
        return Err(String::from("compilation requires a target isa"));
    };

    for (func, _) in test_file.functions.into_iter() {
        let mut context = Context::new();
        context.func = func;
        context.compile(isa).map_err(|err| {
            pretty_error(&context.func, Some(isa), err)
        })?;
        if flag_print {
            println!("{}", context.func.display(isa));
        }
    }

    Ok(())
}
<commit_msg>Avoid an unneeded .into_iter().<commit_after>//! CLI tool to compile cretonne IL into native code.
//!
//! Reads IR files into Cretonne IL and compiles it.

use cton_reader::parse_test;
use std::path::PathBuf;
use cretonne::Context;
use cretonne::settings::FlagsOrIsa;
use std::path::Path;
use utils::{pretty_error, read_to_string, parse_sets_and_isa};

pub fn run(
    files: Vec<String>,
    flag_print: bool,
    mut flag_set: Vec<String>,
    flag_isa: String,
) -> Result<(), String> {
    // Enable the verifier by default, since we're reading IL in from a
    // text file.
    flag_set.insert(0, "enable_verifier=1".to_string());

    let parsed = parse_sets_and_isa(flag_set, flag_isa)?;

    for filename in files {
        let path = Path::new(&filename);
        let name = String::from(path.as_os_str().to_string_lossy());
        handle_module(flag_print, path.to_path_buf(), name, parsed.as_fisa())?;
    }
    Ok(())
}

fn handle_module(
    flag_print: bool,
    path: PathBuf,
    name: String,
    fisa: FlagsOrIsa,
) -> Result<(), String> {
    let buffer = read_to_string(&path).map_err(
        |e| format!("{}: {}", name, e),
    )?;
    let test_file = parse_test(&buffer).map_err(|e| format!("{}: {}", name, e))?;

    // If we have an isa from the command-line, use that. Otherwise if the
    // file contins a unique isa, use that.
    let isa = if let Some(isa) = fisa.isa {
        isa
    } else if let Some(isa) = test_file.isa_spec.unique_isa() {
        isa
    } else {
        return Err(String::from("compilation requires a target isa"));
    };

    for (func, _) in test_file.functions {
        let mut context = Context::new();
        context.func = func;
        context.compile(isa).map_err(|err| {
            pretty_error(&context.func, Some(isa), err)
        })?;
        if flag_print {
            println!("{}", context.func.display(isa));
        }
    }

    Ok(())
}
<|endoftext|>


<commit_before>// http://rosettacode.org/wiki/Synchronous_concurrency
//
// Reader unit reads lines from input.txt, send lines one at a time to printer
// unit, which then prints lines, keeping track of lines printed. At the end of
// the file, the reader unit requests number of lines printed from the printer
// unit, and then prints them.
use std::fs::File;
use std::io::{BufReader, BufRead};
use std::sync::mpsc::{channel, Sender, Receiver};
use std::thread::spawn;

const FILENAME: &'static str = "resources/input.txt";

enum Message {
    Line(String),
    End
}

fn printer(i_snd: Sender<i32>, msg_rcv: Receiver<Message>) {
    let mut count = 0;
    loop {
        match msg_rcv.recv().unwrap() {
            Message::Line(line) => {
                print!("{}", line);
                count += 1;
            }
            Message::End => {break;}
        }
    }
    i_snd.send(count).unwrap();
}

fn reader(msg_snd: Sender<Message>, i_rcv: Receiver<i32>) {
    let file = BufReader::new(File::open(FILENAME).unwrap());
    for line in file.lines() {
        msg_snd.send(Message::Line(line.unwrap())).unwrap();
    }
    msg_snd.send(Message::End).unwrap();
    println!("Total Lines: {:?}", i_rcv.recv());
}

fn main() {
    let (msg_snd, msg_rcv) = channel();
    let (i_snd, i_rcv) = channel();

    spawn(move || printer(i_snd, msg_rcv));
    spawn(move || reader(msg_snd, i_rcv));
}
<commit_msg>Fix synchronous_concurrency (use println)<commit_after>// http://rosettacode.org/wiki/Synchronous_concurrency
//
// Reader unit reads lines from input.txt, send lines one at a time to printer
// unit, which then prints lines, keeping track of lines printed. At the end of
// the file, the reader unit requests number of lines printed from the printer
// unit, and then prints them.
use std::fs::File;
use std::io::{BufReader, BufRead};
use std::sync::mpsc::{channel, Sender, Receiver};
use std::thread;

const FILENAME: &'static str = "resources/input.txt";

enum Message {
    Line(String),
    End
}

fn printer(i_snd: Sender<i32>, msg_rcv: Receiver<Message>) {
    let mut count = 0;
    loop {
        match msg_rcv.recv().unwrap() {
            Message::Line(line) => {
                println!("{}", line);
                count += 1;
            }
            Message::End => {break;}
        }
    }
    i_snd.send(count).unwrap();
}

fn reader(msg_snd: Sender<Message>, i_rcv: Receiver<i32>) {
    let file = BufReader::new(File::open(FILENAME).unwrap());
    for line in file.lines() {
        msg_snd.send(Message::Line(line.unwrap())).unwrap();
    }
    msg_snd.send(Message::End).unwrap();
    println!("Total Lines: {}", i_rcv.recv().unwrap());
}

fn main() {
    let (msg_snd, msg_rcv) = channel();
    let (i_snd, i_rcv) = channel();

    thread::spawn(move || printer(i_snd, msg_rcv));
    thread::spawn(move || reader(msg_snd, i_rcv));
}
<|endoftext|>


<commit_before>use ffi;
use types::{Result, PortMidiDeviceId, Error};
use io::{InputPort, OutputPort};
use device::DeviceInfo;

/// The elements are static after initializing
pub struct PortMidi {
    device_cnt: i32,
    buffer_size: i32,
}
impl PortMidi {
    /// Initializes the underlying PortMidi C library.
    /// It does not support *hot plugging*, this means
    /// that devices that are connect after calling `new`
    /// are not picked up by PortMidi.
    pub fn new() -> Result<Self> {
        try!(Result::from(unsafe { ffi::Pm_Initialize() }));

        Ok(PortMidi {
            device_cnt: unsafe { ffi::Pm_CountDevices() },
            buffer_size: 1024, // TODO: argument
        })
    }

    /// Return the number of devices. This number will not change during the lifetime
    /// of the program.
    pub fn device_cnt(self) -> PortMidiDeviceId {
        self.device_cnt
    }

    /// Gets the `PortMidiDeviceId` for the default input, or `None` if
    /// there isn't one
    ///
    /// See the PortMidi documentation for details of how to set the default device
    pub fn default_input_device_id(&self) -> Result<PortMidiDeviceId> {
        match unsafe { ffi::Pm_GetDefaultInputDeviceID() } {
            ffi::PM_NO_DEVICE => Err(Error::NoDefaultDevice),
            id @ _ => Ok(id),
        }
    }

    /// Gets the `PortMidiDeviceId` for the default output, or `None` if
    /// there isn't one
    ///
    /// See the PortMidi documentation for details of how to set the default device
    pub fn default_output_device_id(&self) -> Result<PortMidiDeviceId> {
        match unsafe { ffi::Pm_GetDefaultOutputDeviceID() } {
            ffi::PM_NO_DEVICE => Err(Error::NoDefaultDevice),
            id @ _ => Ok(id),
        }
    }

    pub fn device_info(&self, id: PortMidiDeviceId) -> Result<DeviceInfo> {
        DeviceInfo::new(id)
    }

    pub fn default_input_port(&self) -> Result<InputPort> {
        let info = try!(self.default_input_device_id().and_then(|id| self.device_info(id)));
        InputPort::new(info, self.buffer_size)
    }

    pub fn input_port(&self, device: DeviceInfo) -> Result<InputPort> {
        if device.is_input() {
            InputPort::new(device, self.buffer_size)
        } else {
            Err(Error::Invalid)
        }
    }

    pub fn default_output_port(&self) -> Result<OutputPort> {
        let info = try!(self.default_output_device_id().and_then(|id| self.device_info(id)));
        OutputPort::new(info, self.buffer_size)
    }

    pub fn output_port(&self, device: DeviceInfo) -> Result<InputPort> {
        if device.is_output() {
            InputPort::new(device, self.buffer_size)
        } else {
            Err(Error::Invalid)
        }
    }
}
impl Drop for PortMidi {
    fn drop(&mut self) {
        Result::from(unsafe { ffi::Pm_Terminate() })
            .map_err(|err| println!("Could not terminate library: {}", err));
    }
}
<commit_msg>Pass `self` reference to `device_cnt`<commit_after>use ffi;
use types::{Result, PortMidiDeviceId, Error};
use io::{InputPort, OutputPort};
use device::DeviceInfo;

/// The elements are static after initializing
pub struct PortMidi {
    device_cnt: i32,
    buffer_size: i32,
}
impl PortMidi {
    /// Initializes the underlying PortMidi C library.
    /// It does not support *hot plugging*, this means
    /// that devices that are connect after calling `new`
    /// are not picked up by PortMidi.
    pub fn new() -> Result<Self> {
        try!(Result::from(unsafe { ffi::Pm_Initialize() }));

        Ok(PortMidi {
            device_cnt: unsafe { ffi::Pm_CountDevices() },
            buffer_size: 1024, // TODO: argument
        })
    }

    /// Return the number of devices. This number will not change during the lifetime
    /// of the program.
    pub fn device_cnt(&self) -> PortMidiDeviceId {
        self.device_cnt
    }

    /// Gets the `PortMidiDeviceId` for the default input, or `None` if
    /// there isn't one
    ///
    /// See the PortMidi documentation for details of how to set the default device
    pub fn default_input_device_id(&self) -> Result<PortMidiDeviceId> {
        match unsafe { ffi::Pm_GetDefaultInputDeviceID() } {
            ffi::PM_NO_DEVICE => Err(Error::NoDefaultDevice),
            id @ _ => Ok(id),
        }
    }

    /// Gets the `PortMidiDeviceId` for the default output, or `None` if
    /// there isn't one
    ///
    /// See the PortMidi documentation for details of how to set the default device
    pub fn default_output_device_id(&self) -> Result<PortMidiDeviceId> {
        match unsafe { ffi::Pm_GetDefaultOutputDeviceID() } {
            ffi::PM_NO_DEVICE => Err(Error::NoDefaultDevice),
            id @ _ => Ok(id),
        }
    }

    pub fn device_info(&self, id: PortMidiDeviceId) -> Result<DeviceInfo> {
        DeviceInfo::new(id)
    }

    pub fn default_input_port(&self) -> Result<InputPort> {
        let info = try!(self.default_input_device_id().and_then(|id| self.device_info(id)));
        InputPort::new(info, self.buffer_size)
    }

    pub fn input_port(&self, device: DeviceInfo) -> Result<InputPort> {
        if device.is_input() {
            InputPort::new(device, self.buffer_size)
        } else {
            Err(Error::Invalid)
        }
    }

    pub fn default_output_port(&self) -> Result<OutputPort> {
        let info = try!(self.default_output_device_id().and_then(|id| self.device_info(id)));
        OutputPort::new(info, self.buffer_size)
    }

    pub fn output_port(&self, device: DeviceInfo) -> Result<InputPort> {
        if device.is_output() {
            InputPort::new(device, self.buffer_size)
        } else {
            Err(Error::Invalid)
        }
    }
}
impl Drop for PortMidi {
    fn drop(&mut self) {
        Result::from(unsafe { ffi::Pm_Terminate() })
            .map_err(|err| println!("Could not terminate library: {}", err));
    }
}
<|endoftext|>


<commit_before>#![allow(experimental)]

use std::io::{File,fs};
//use std::io::process::Command;
use std::path::posix::Path;
use std::os::{homedir};
#[cfg(test)] use std::rand::random;
#[cfg(test)] use std::finally::Finally;

static TEMPLATE: &'static str = include_str!("creator/template.yml");
static DEFAULT_MUXED_DIR: &'static str = "muxed";

pub fn new(name: &str) {
    let muxed_dir = if muxed_dir_exists(&DEFAULT_MUXED_DIR.to_string()) {
      Path::new(format!("{}/.{}/", homedir_string(), &DEFAULT_MUXED_DIR.to_string()))
    } else {
      create_muxed_dir(&DEFAULT_MUXED_DIR.to_string())
    };

    let path = &Path::new(format!("{}/{}", muxed_dir.display(), name));
    if !path.exists() {
      create_project_file(path)
    } else {
      println!("Project already exists.");
    }
}

fn create_project_file(path: &Path) {
    match File::create(path).write(TEMPLATE.as_bytes()) {
        Ok(()) => (), // succeeded
        Err(_e) => println!("Failed to create project {}", path.filename()),
    }
//    Command::new("vim").arg(format!("{}", path.display())).detached();
}

fn create_muxed_dir(name: &String) -> Path {
    let path = &Path::new(format!("{}/.{}", homedir_string(), name));
    fs::mkdir(path, ::std::io::UserRWX);
    path.clone()
}

fn muxed_dir_exists(name: &String) -> bool {
    let path = &Path::new(format!("{}/.{}", homedir_string(), name));
    path.exists()
}

fn homedir_string() -> String {
    let home_unwrap = homedir().unwrap();
    format!("{}", home_unwrap.display())
}

#[test]
fn muxed_dir_exists_returns_false() {
  let dir = format!("test_dir_{}", random::<f64>());
  assert!(!muxed_dir_exists(&dir));
}

#[test]
fn muxed_dir_exists_returns_true() {
  let dir = format!("test_dir_{}", random::<f64>());
  create_muxed_dir(&dir);
  assert!(muxed_dir_exists(&dir));

  let muxed_path  = &Path::new(format!("{}/.{}/", homedir_string(), dir.as_slice()));
  fs::rmdir_recursive(muxed_path);
}

#[test]
fn creates_muxed_dir() {
    let name        = format!("test_project_{}", random::<f64>());
    let dir         = format!("test_dir_{}", random::<f64>());
    let muxed_path  = &Path::new(format!("{}/.{}/", homedir_string(), dir.as_slice()));
    create_muxed_dir(&dir);
    assert!(muxed_path.exists());
    fs::rmdir_recursive(muxed_path);
}

#[test]
fn new_writes_file_to_muxed_dir() {
    let name = format!("test_project_{}", random::<f64>());
    let path = &Path::new(format!("{}/.muxed/{}", homedir_string(), name));
    new(name.as_slice());
    assert!(path.exists());
    fs::unlink(path);
}

#[test]
// TODO: Fix this test so it verifies something better.
fn new_doesnt_overwrite_existing_file() {
    let name = format!("test_project_{}", random::<f64>());
    let path = &Path::new(format!("{}/.muxed/{}", homedir_string(), name));
    new(name.as_slice());
    (|| {
        new(name.as_slice());
    }).finally(|| {
        fs::unlink(path);
    })
}
<commit_msg>Handle io failures when creating the muxed directory.<commit_after>#![allow(experimental)]

use std::io::{File,fs};
//use std::io::process::Command;
use std::path::posix::Path;
use std::os::{homedir};
#[cfg(test)] use std::rand::random;
#[cfg(test)] use std::finally::Finally;

static TEMPLATE: &'static str = include_str!("creator/template.yml");
static DEFAULT_MUXED_DIR: &'static str = "muxed";

pub fn new(name: &str) {
    let muxed_dir = if muxed_dir_exists(&DEFAULT_MUXED_DIR.to_string()) {
      Path::new(format!("{}/.{}/", homedir_string(), &DEFAULT_MUXED_DIR.to_string()))
    } else {
      create_muxed_dir(&DEFAULT_MUXED_DIR.to_string())
    };

    let path = &Path::new(format!("{}/{}", muxed_dir.display(), name));
    if !path.exists() {
      create_project_file(path)
    } else {
      println!("Project already exists.");
    }
}

fn create_project_file(path: &Path) {
    match File::create(path).write(TEMPLATE.as_bytes()) {
        Ok(()) => (), // succeeded
        Err(_e) => println!("Failed to create project {}", path.filename()),
    }
//    Command::new("vim").arg(format!("{}", path.display())).detached();
}

fn create_muxed_dir(name: &String) -> Path {
    let path = &Path::new(format!("{}/.{}", homedir_string(), name));
    match fs::mkdir(path, ::std::io::UserRWX) {
        Ok(()) => (), // succeeded
        Err(_e) => println!("Failed to create project {}", path.filename()),
    }

    path.clone()
}

fn muxed_dir_exists(name: &String) -> bool {
    let path = &Path::new(format!("{}/.{}", homedir_string(), name));
    path.exists()
}

fn homedir_string() -> String {
    let home_unwrap = homedir().unwrap();
    format!("{}", home_unwrap.display())
}

#[test]
fn muxed_dir_exists_returns_false() {
  let dir = format!("test_dir_{}", random::<f64>());
  assert!(!muxed_dir_exists(&dir));
}

#[test]
fn muxed_dir_exists_returns_true() {
  let dir = format!("test_dir_{}", random::<f64>());
  create_muxed_dir(&dir);
  assert!(muxed_dir_exists(&dir));

  let muxed_path  = &Path::new(format!("{}/.{}/", homedir_string(), dir.as_slice()));
  fs::rmdir_recursive(muxed_path);
}

#[test]
fn creates_muxed_dir() {
    let name        = format!("test_project_{}", random::<f64>());
    let dir         = format!("test_dir_{}", random::<f64>());
    let muxed_path  = &Path::new(format!("{}/.{}/", homedir_string(), dir.as_slice()));
    create_muxed_dir(&dir);
    assert!(muxed_path.exists());
    fs::rmdir_recursive(muxed_path);
}

#[test]
fn new_writes_file_to_muxed_dir() {
    let name = format!("test_project_{}", random::<f64>());
    let path = &Path::new(format!("{}/.muxed/{}", homedir_string(), name));
    new(name.as_slice());
    assert!(path.exists());
    fs::unlink(path);
}

#[test]
// TODO: Fix this test so it verifies something better.
fn new_doesnt_overwrite_existing_file() {
    let name = format!("test_project_{}", random::<f64>());
    let path = &Path::new(format!("{}/.muxed/{}", homedir_string(), name));
    new(name.as_slice());
    (|| {
        new(name.as_slice());
    }).finally(|| {
        fs::unlink(path);
    })
}
<|endoftext|>


<commit_before>use chrono::{FixedOffset, Local};
use cron::Schedule;

use std::str::FromStr;
use std::thread;
use std::time::Duration;

use command::Command;

/// The object to create and execute cronjobs for yout application.
pub struct CronJob {
    name: String,
    command: Box<dyn Command>,
    seconds: Option<String>,
    minutes: Option<String>,
    hours: Option<String>,
    day_of_month: Option<String>,
    month: Option<String>,
    day_of_week: Option<String>,
    year: Option<String>,
    offset: Option<FixedOffset>,
}

impl CronJob {
    /// Constructs new `CronJob` object.
    pub fn new<C: Command>(name: &str, command: C) -> Self {
        CronJob {
            name: name.to_string(),
            command: Box::new(command),
            seconds: None,
            minutes: None,
            hours: None,
            day_of_month: None,
            month: None,
            day_of_week: None,
            year: None,
            offset: None,
        }
    }

    pub fn seconds(&mut self, seconds: &str) -> &mut Self {
        self.seconds = Some(seconds.to_string());
        self
    }

    pub fn minutes(&mut self, minutes: &str) -> &mut Self {
        self.minutes = Some(minutes.to_string());
        self
    }

    pub fn hours(&mut self, hours: &str) -> &mut Self {
        self.hours = Some(hours.to_string());
        self
    }

    pub fn day_of_month(&mut self, day_of_month: &str) -> &mut Self {
        self.day_of_month = Some(day_of_month.to_string());
        self
    }

    pub fn month(&mut self, month: &str) -> &mut Self {
        self.month = Some(month.to_string());
        self
    }

    pub fn day_of_week(&mut self, day_of_week: &str) -> &mut Self {
        self.day_of_week = Some(day_of_week.to_string());
        self
    }

    pub fn year(&mut self, year: &str) -> &mut Self {
        self.year = Some(year.to_string());
        self
    }

    pub fn offset(&mut self, timezone_offset: i32) -> &mut Self {
        self.offset = Some(FixedOffset::east(timezone_offset));
        self
    }

    /// Returns the schedule for the cronjob, with this you are able to get the next occurences.
    pub fn get_schedule(&mut self) -> Schedule {
        let asterix = String::from("*");
        let cron = format!(
            "{} {} {} {} {} {} {}",
            self.seconds.as_ref().unwrap_or(&asterix),
            self.minutes.as_ref().unwrap_or(&asterix),
            self.hours.as_ref().unwrap_or(&asterix),
            self.day_of_month.as_ref().unwrap_or(&asterix),
            self.month.as_ref().unwrap_or(&asterix),
            self.day_of_week.as_ref().unwrap_or(&asterix),
            self.year.as_ref().unwrap_or(&asterix)
        );
        Schedule::from_str(&cron).unwrap()
    }

    /// Starts the cronjob without threading.
    pub fn start_job(&mut self) {
        let schedule = self.get_schedule();
        let offset = self.offset.unwrap_or_else(|| FixedOffset::east(0));

        loop {
            let mut upcoming = schedule.upcoming(offset).take(1);
            thread::sleep(Duration::from_millis(500));
            let local = &Local::now();

            if let Some(datetime) = upcoming.next() {
                if datetime.timestamp() <= local.timestamp() {
                    self.command.execute(&self.name);
                }
            }
        }
    }

    /// Starts the cronjob with threading. Stops when application quits.
    pub fn start_job_threaded(mut cronjob: CronJob) {
        thread::Builder::new()
            .name(cronjob.name.clone())
            .spawn(move || {
                cronjob.start_job();
            })
            .expect("There was an error in an cronjob");
    }
}
<commit_msg>shorten threaded method<commit_after>use chrono::{FixedOffset, Local};
use cron::Schedule;

use std::str::FromStr;
use std::thread;
use std::time::Duration;

use command::Command;

/// The object to create and execute cronjobs for yout application.
pub struct CronJob {
    name: String,
    command: Box<dyn Command>,
    seconds: Option<String>,
    minutes: Option<String>,
    hours: Option<String>,
    day_of_month: Option<String>,
    month: Option<String>,
    day_of_week: Option<String>,
    year: Option<String>,
    offset: Option<FixedOffset>,
}

impl CronJob {
    /// Constructs new `CronJob` object.
    pub fn new<C: Command>(name: &str, command: C) -> Self {
        CronJob {
            name: name.to_string(),
            command: Box::new(command),
            seconds: None,
            minutes: None,
            hours: None,
            day_of_month: None,
            month: None,
            day_of_week: None,
            year: None,
            offset: None,
        }
    }

    pub fn seconds(&mut self, seconds: &str) -> &mut Self {
        self.seconds = Some(seconds.to_string());
        self
    }

    pub fn minutes(&mut self, minutes: &str) -> &mut Self {
        self.minutes = Some(minutes.to_string());
        self
    }

    pub fn hours(&mut self, hours: &str) -> &mut Self {
        self.hours = Some(hours.to_string());
        self
    }

    pub fn day_of_month(&mut self, day_of_month: &str) -> &mut Self {
        self.day_of_month = Some(day_of_month.to_string());
        self
    }

    pub fn month(&mut self, month: &str) -> &mut Self {
        self.month = Some(month.to_string());
        self
    }

    pub fn day_of_week(&mut self, day_of_week: &str) -> &mut Self {
        self.day_of_week = Some(day_of_week.to_string());
        self
    }

    pub fn year(&mut self, year: &str) -> &mut Self {
        self.year = Some(year.to_string());
        self
    }

    pub fn offset(&mut self, timezone_offset: i32) -> &mut Self {
        self.offset = Some(FixedOffset::east(timezone_offset));
        self
    }

    /// Returns the schedule for the cronjob, with this you are able to get the next occurences.
    pub fn get_schedule(&mut self) -> Schedule {
        let asterix = String::from("*");
        let cron = format!(
            "{} {} {} {} {} {} {}",
            self.seconds.as_ref().unwrap_or(&asterix),
            self.minutes.as_ref().unwrap_or(&asterix),
            self.hours.as_ref().unwrap_or(&asterix),
            self.day_of_month.as_ref().unwrap_or(&asterix),
            self.month.as_ref().unwrap_or(&asterix),
            self.day_of_week.as_ref().unwrap_or(&asterix),
            self.year.as_ref().unwrap_or(&asterix)
        );
        Schedule::from_str(&cron).unwrap()
    }

    /// Starts the cronjob without threading.
    pub fn start_job(&mut self) {
        let schedule = self.get_schedule();
        let offset = self.offset.unwrap_or_else(|| FixedOffset::east(0));

        loop {
            let mut upcoming = schedule.upcoming(offset).take(1);
            thread::sleep(Duration::from_millis(500));
            let local = &Local::now();

            if let Some(datetime) = upcoming.next() {
                if datetime.timestamp() <= local.timestamp() {
                    self.command.execute(&self.name);
                }
            }
        }
    }

    /// Starts the cronjob with threading. Stops when application quits.
    pub fn start_job_threaded(mut cronjob: CronJob) {
        thread::Builder::new()
            .name(cronjob.name.clone())
            .spawn(move || cronjob.start_job())
            .expect("There was an error in an cronjob");
    }
}
<|endoftext|>


<commit_before>use bytes::Bytes;
use std::path::PathBuf;

use mfa::Arity;
use module;
use rterror;
use types::{Word, Integral};
use util::reader;
use vm::VM;
use beam::compact_term;
use term::Term;

pub fn module() -> &'static str { "BEAM loader: " }

struct LImport {
  mod_atom: u32,
  fun_atom: u32,
  arity: Arity,
}

struct LExport {
  fun_atom: u32,
  arity: Arity,
  label: u32,
}

struct LFun {
  fun_atom: u32,
  arity: u32,
  code_pos: u32,
  index: u32,
  nfree: u32,
  ouniq: u32,
}

pub struct Loader {
  atom_tab: Vec<String>,
  imports: Vec<LImport>,
  exports: Vec<LExport>,
  locals: Vec<LExport>,
  funs: Vec<LFun>,
  mod_name: Term,
}

impl Loader {
  /// Construct a new loader state.
  pub fn new() -> Loader {
    Loader {
      atom_tab: Vec::new(),
      imports: Vec::new(),
      exports: Vec::new(),
      locals: Vec::new(),
      funs: Vec::new(),
      mod_name: Term::non_value(),
    }
  }

  /// Loading the module. Validate the header and iterate over sections,
  /// then call `load_stage2()` to apply changes to the VM, and then finalize
  /// it by calling `load_finalize()` which will return you a module object.
  pub fn load(&mut self, fname: &PathBuf) -> Result<(), rterror::Error>
  {
    let mut r = reader::BinaryReader::from_file(fname);

    // Parse header and check file FOR1 signature
    let hdr1 = Bytes::from(&b"FOR1"[..]);
    r.ensure_bytes(&hdr1)?;

    let beam_sz = r.read_u32be();

    // Check BEAM signature
    let hdr2 = Bytes::from(&b"BEAM"[..]);
    r.ensure_bytes(&hdr2)?;

    while true {
      // EOF may strike here when we finished reading
      let chunk_h = match r.read_str_latin1(4) {
        Ok(s) => s,
        // EOF is not an error
        Err(rterror::Error::CodeLoadingPrematureEOF) => break,
        Err(e) => return Err(e)
      };
      let chunk_sz = r.read_u32be();

      println!("Chunk {}", chunk_h);
      match chunk_h.as_ref() {
        "Atom" => self.load_atoms_latin1(&mut r),
        "Attr" => r.skip(chunk_sz as Word), // TODO: read attributes
        "AtU8" => self.load_atoms_utf8(&mut r),
        "CInf" => r.skip(chunk_sz as Word),
        "Code" => self.load_code(&mut r, chunk_sz as Word),
        "Dbgi" => r.skip(chunk_sz as Word),
        "ExpT" => self.exports = self.load_exports(&mut r),
        "FunT" => self.load_fun_table(&mut r),
        "ImpT" => self.load_imports(&mut r),
        "Line" => self.load_line_info(&mut r),
        "LocT" => self.locals = self.load_exports(&mut r),
        "StrT" => r.skip(chunk_sz as Word),
        other => {
          let msg = format!("{}Unexpected chunk: {}", module(), other);
          return Err(rterror::Error::CodeLoadingFailed(msg))
        }
      }

      // The next chunk is aligned at 4 bytes
      let aligned_sz = 4 * ((chunk_sz + 3) / 4);
      let align = aligned_sz - chunk_sz;
      if align > 0 { r.skip(align as Word); }
    }
    Ok(())
  }

  /// Call this to apply changes to the VM after module loading succeeded. The
  /// module object is not created yet, but some effects like atoms table
  /// we can already apply.
  pub fn load_stage2(&mut self, vm: &mut VM) {
    self.mod_name = vm.atom(&self.atom_tab[0]);
  }

  /// At this point loading is finished, and we create Erlang module and
  /// return a reference counted pointer to it. VM (the caller) is responsible
  /// for adding the module to its code registry.
  pub fn load_finalize(&mut self) -> Result<module::Ptr, rterror::Error> {
    let newmod = module::Module::new(self.mod_name);
    Ok(newmod)
  }

  /// Approaching AtU8 section, populate atoms table in the Loader state.
  /// The format is: "Atom"|"AtU8", u32/big count { u8 length, "atomname" }.
  /// Formats are absolutely compatible except that Atom is latin-1
  fn load_atoms_utf8(&mut self, r: &mut reader::BinaryReader) {
    let n_atoms = r.read_u32be();
    for i in 0..n_atoms {
      let atom_bytes = r.read_u8();
      let atom_text = r.read_str_utf8(atom_bytes as Word).unwrap();
      self.atom_tab.push(atom_text);
    }
  }

  /// Approaching Atom section, populate atoms table in the Loader state.
  /// The format is: "Atom"|"AtU8", u32/big count { u8 length, "atomname" }.
  /// Same as `load_atoms_utf8` but interprets strings per-character as latin-1
  fn load_atoms_latin1(&mut self, r: &mut reader::BinaryReader) {
    let n_atoms = r.read_u32be();
    self.atom_tab.reserve(n_atoms as usize);
    for i in 0..n_atoms {
      let atom_bytes = r.read_u8();
      let atom_text = r.read_str_latin1(atom_bytes as Word).unwrap();
      self.atom_tab.push(atom_text);
    }
  }

  /// Load the `Code` section
  fn load_code(&mut self, r: &mut reader::BinaryReader, chunk_sz: Word) {
    let code_ver = r.read_u32be();
    let min_opcode = r.read_u32be();
    let max_opcode = r.read_u32be();
    let n_labels = r.read_u32be();
    let n_funs = r.read_u32be();
    println!("Code section version {}, opcodes {}-{}, labels: {}, funs: {}",
      code_ver, min_opcode, max_opcode, n_labels, n_funs);
    let code = r.read_bytes(chunk_sz - 20).unwrap();
  }

  /// Read the imports table.
  /// Format is u32/big count { modindex: u32, funindex: u32, arity: u32 }
  fn load_imports(&mut self, r: &mut reader::BinaryReader) {
    let n_imports = r.read_u32be();
    self.imports.reserve(n_imports as usize);
    for i in 0..n_imports {
      let imp = LImport {
        mod_atom: r.read_u32be(),
        fun_atom: r.read_u32be(),
        arity: r.read_u32be() as Arity,
      };
      self.imports.push(imp);
    }
  }

  /// Read the exports or local functions table (same format).
  /// Format is u32/big count { funindex: u32, arity: u32, label: u32 }
  fn load_exports(&mut self, r: &mut reader::BinaryReader) -> Vec<LExport> {
    let n_exports = r.read_u32be();
    let mut exports = Vec::new();
    exports.reserve(n_exports as usize);
    for i in 0..n_exports {
      let exp = LExport {
        fun_atom: r.read_u32be(),
        arity: r.read_u32be() as Arity,
        label: r.read_u32be(),
      };
      exports.push(exp);
    }
    exports
  }

  fn load_fun_table(&mut self, r: &mut reader::BinaryReader) {
    let n_funs = r.read_u32be();
    self.funs.reserve(n_funs as usize);
    for i in 0..n_funs {
      let fun_atom = r.read_u32be();
      let arity = r.read_u32be();
      let code_pos = r.read_u32be();
      let index = r.read_u32be();
      let nfree = r.read_u32be();
      let ouniq = r.read_u32be();
      self.funs.push(LFun {
        fun_atom, arity, code_pos, index, nfree, ouniq
      })
    }
  }

  fn load_line_info(&mut self, r: &mut reader::BinaryReader) {
    let version = r.read_u32be(); // must match emulator version 0
    let flags = r.read_u32be();
    let n_line_instr = r.read_u32be();
    let n_line_refs = r.read_u32be();
    let n_filenames = r.read_u32be();
    let mut fname_index = 0u32;

    for i in 0..n_line_refs {
      match compact_term::read(r).unwrap() {
        compact_term::CompactTerm::Integer(Integral::Word(w)) => {
          // self.linerefs.push((fname_index, w));
        },
        compact_term::CompactTerm::Atom(a) =>
          fname_index = a as u32,
        other => panic!("{}Unexpected data in line info section: {:?}",
                        module(), other)
      }
    }

    for i in 0..n_filenames {
      let name_size = r.read_u16be();
      let fstr = r.read_str_utf8(name_size as Word);
    }
  }

}
<commit_msg>Loader: apply atoms to vm<commit_after>//!
//! Code loader for BEAM files uses 3 stage approach.
//! Stage 1 reads the BEAM file and fills the loader state structure.
//! Stage 2 commits changes to the VM (atom table for example)
//! Stage 3 (finalize) returns Erlang module object ready for code server.
//!
//! Call `let l = Loader::new()`, then `l.load(filename)`, then
//! `l.load_stage2(&mut vm)` and finally `let modp = l.load_finalize()`
//!
use bytes::Bytes;
use std::path::PathBuf;

use mfa::Arity;
use module;
use rterror;
use types::{Word, Integral};
use util::reader;
use vm::VM;
use beam::compact_term;
use term::Term;

pub fn module() -> &'static str { "BEAM loader: " }

/// Raw data structure as loaded from BEAM file
struct LImport {
  mod_atom: u32,
  fun_atom: u32,
  arity: Arity,
}

/// Raw data structure as loaded from BEAM file
struct LExport {
  fun_atom: u32,
  arity: Arity,
  label: u32,
}

/// Raw data structure as loaded from BEAM file
struct LFun {
  fun_atom: u32,
  arity: u32,
  code_pos: u32,
  index: u32,
  nfree: u32,
  ouniq: u32,
}

pub struct Loader {
  /// Atoms as loaded from BEAM module strings.
  atom_tab: Vec<String>,
  /// Atoms converted to VM terms (during the stage 2)
  vm_atoms: Vec<Term>,
  imports: Vec<LImport>,
  exports: Vec<LExport>,
  locals: Vec<LExport>,
  funs: Vec<LFun>,
  mod_name: Term,
}

impl Loader {
  /// Construct a new loader state.
  pub fn new() -> Loader {
    Loader {
      atom_tab: Vec::new(),
      vm_atoms: Vec::new(),
      imports: Vec::new(),
      exports: Vec::new(),
      locals: Vec::new(),
      funs: Vec::new(),
      mod_name: Term::non_value(),
    }
  }

  /// Loading the module. Validate the header and iterate over sections,
  /// then call `load_stage2()` to apply changes to the VM, and then finalize
  /// it by calling `load_finalize()` which will return you a module object.
  pub fn load(&mut self, fname: &PathBuf) -> Result<(), rterror::Error>
  {
    let mut r = reader::BinaryReader::from_file(fname);

    // Parse header and check file FOR1 signature
    let hdr1 = Bytes::from(&b"FOR1"[..]);
    r.ensure_bytes(&hdr1)?;

    let beam_sz = r.read_u32be();

    // Check BEAM signature
    let hdr2 = Bytes::from(&b"BEAM"[..]);
    r.ensure_bytes(&hdr2)?;

    while true {
      // EOF may strike here when we finished reading
      let chunk_h = match r.read_str_latin1(4) {
        Ok(s) => s,
        // EOF is not an error
        Err(rterror::Error::CodeLoadingPrematureEOF) => break,
        Err(e) => return Err(e)
      };
      let chunk_sz = r.read_u32be();

      println!("Chunk {}", chunk_h);
      match chunk_h.as_ref() {
        "Atom" => self.load_atoms_latin1(&mut r),
        "Attr" => r.skip(chunk_sz as Word), // TODO: read attributes
        "AtU8" => self.load_atoms_utf8(&mut r),
        "CInf" => r.skip(chunk_sz as Word),
        "Code" => self.load_code(&mut r, chunk_sz as Word),
        "Dbgi" => r.skip(chunk_sz as Word),
        "ExpT" => self.exports = self.load_exports(&mut r),
        "FunT" => self.load_fun_table(&mut r),
        "ImpT" => self.load_imports(&mut r),
        "Line" => self.load_line_info(&mut r),
        "LocT" => self.locals = self.load_exports(&mut r),
        "StrT" => r.skip(chunk_sz as Word),
        other => {
          let msg = format!("{}Unexpected chunk: {}", module(), other);
          return Err(rterror::Error::CodeLoadingFailed(msg))
        }
      }

      // The next chunk is aligned at 4 bytes
      let aligned_sz = 4 * ((chunk_sz + 3) / 4);
      let align = aligned_sz - chunk_sz;
      if align > 0 { r.skip(align as Word); }
    }
    Ok(())
  }

  /// Call this to apply changes to the VM after module loading succeeded. The
  /// module object is not created yet, but some effects like atoms table
  /// we can already apply.
  pub fn load_stage2(&mut self, vm: &mut VM) {
    self.vm_atoms.reserve(self.atom_tab.len());
    for a in &self.atom_tab {
      self.vm_atoms.push(vm.atom(&a));
    }

    self.mod_name = self.vm_atoms[0];
  }

  /// At this point loading is finished, and we create Erlang module and
  /// return a reference counted pointer to it. VM (the caller) is responsible
  /// for adding the module to its code registry.
  pub fn load_finalize(&mut self) -> Result<module::Ptr, rterror::Error> {
    let newmod = module::Module::new(self.mod_name);
    Ok(newmod)
  }

  //============================================================================

  /// Approaching AtU8 section, populate atoms table in the Loader state.
  /// The format is: "Atom"|"AtU8", u32/big count { u8 length, "atomname" }.
  /// Formats are absolutely compatible except that Atom is latin-1
  fn load_atoms_utf8(&mut self, r: &mut reader::BinaryReader) {
    let n_atoms = r.read_u32be();
    for i in 0..n_atoms {
      let atom_bytes = r.read_u8();
      let atom_text = r.read_str_utf8(atom_bytes as Word).unwrap();
      self.atom_tab.push(atom_text);
    }
  }

  /// Approaching Atom section, populate atoms table in the Loader state.
  /// The format is: "Atom"|"AtU8", u32/big count { u8 length, "atomname" }.
  /// Same as `load_atoms_utf8` but interprets strings per-character as latin-1
  fn load_atoms_latin1(&mut self, r: &mut reader::BinaryReader) {
    let n_atoms = r.read_u32be();
    self.atom_tab.reserve(n_atoms as usize);
    for i in 0..n_atoms {
      let atom_bytes = r.read_u8();
      let atom_text = r.read_str_latin1(atom_bytes as Word).unwrap();
      self.atom_tab.push(atom_text);
    }
  }

  /// Load the `Code` section
  fn load_code(&mut self, r: &mut reader::BinaryReader, chunk_sz: Word) {
    let code_ver = r.read_u32be();
    let min_opcode = r.read_u32be();
    let max_opcode = r.read_u32be();
    let n_labels = r.read_u32be();
    let n_funs = r.read_u32be();
    println!("Code section version {}, opcodes {}-{}, labels: {}, funs: {}",
      code_ver, min_opcode, max_opcode, n_labels, n_funs);
    let code = r.read_bytes(chunk_sz - 20).unwrap();
  }

  /// Read the imports table.
  /// Format is u32/big count { modindex: u32, funindex: u32, arity: u32 }
  fn load_imports(&mut self, r: &mut reader::BinaryReader) {
    let n_imports = r.read_u32be();
    self.imports.reserve(n_imports as usize);
    for i in 0..n_imports {
      let imp = LImport {
        mod_atom: r.read_u32be(),
        fun_atom: r.read_u32be(),
        arity: r.read_u32be() as Arity,
      };
      self.imports.push(imp);
    }
  }

  /// Read the exports or local functions table (same format).
  /// Format is u32/big count { funindex: u32, arity: u32, label: u32 }
  fn load_exports(&mut self, r: &mut reader::BinaryReader) -> Vec<LExport> {
    let n_exports = r.read_u32be();
    let mut exports = Vec::new();
    exports.reserve(n_exports as usize);
    for i in 0..n_exports {
      let exp = LExport {
        fun_atom: r.read_u32be(),
        arity: r.read_u32be() as Arity,
        label: r.read_u32be(),
      };
      exports.push(exp);
    }
    exports
  }

  fn load_fun_table(&mut self, r: &mut reader::BinaryReader) {
    let n_funs = r.read_u32be();
    self.funs.reserve(n_funs as usize);
    for i in 0..n_funs {
      let fun_atom = r.read_u32be();
      let arity = r.read_u32be();
      let code_pos = r.read_u32be();
      let index = r.read_u32be();
      let nfree = r.read_u32be();
      let ouniq = r.read_u32be();
      self.funs.push(LFun {
        fun_atom, arity, code_pos, index, nfree, ouniq
      })
    }
  }

  fn load_line_info(&mut self, r: &mut reader::BinaryReader) {
    let version = r.read_u32be(); // must match emulator version 0
    let flags = r.read_u32be();
    let n_line_instr = r.read_u32be();
    let n_line_refs = r.read_u32be();
    let n_filenames = r.read_u32be();
    let mut fname_index = 0u32;

    for i in 0..n_line_refs {
      match compact_term::read(r).unwrap() {
        compact_term::CompactTerm::Integer(Integral::Word(w)) => {
          // self.linerefs.push((fname_index, w));
        },
        compact_term::CompactTerm::Atom(a) =>
          fname_index = a as u32,
        other => panic!("{}Unexpected data in line info section: {:?}",
                        module(), other)
      }
    }

    for i in 0..n_filenames {
      let name_size = r.read_u16be();
      let fstr = r.read_str_utf8(name_size as Word);
    }
  }

}
<|endoftext|>


<commit_before>extern crate nom;

use std::mem;
use nom::{IResult, ErrorKind};

static BERT_MAGIC_NUMBER: u8 = 131;
static SMALL_INTEGER_EXT: u8 = 97;
static INTEGER_EXT: u8 = 98;
static ATOM_EXT: u8 = 100;
static SMALL_TUPLE_EXT: u8 = 104;
static LARGE_TUPLE_EXT: u8 = 105;
static NIL_EXT: u8 = 106;
static STRING_EXT: u8 = 107;
static LIST_EXT: u8 = 108;
static BINARY_EXT: u8 = 109;
static ATOM_UTF8_EXT: u8 = 118;
static SMALL_ATOM_UTF8_EXT: u8 = 119;
static NEW_FLOAT_EXT: u8 = 70;

#[derive(Debug)]
pub enum BertTerm {
    Int(i32),
    Float(f64),
    Atom(String),
    Tuple(Vec<BertTerm>),
    List(Vec<BertTerm>),
    Binary(Vec<u8>)
}

#[derive(Debug)]
pub enum BertError {
    Unknown,
    InvalidMagicNumber
}

named!(bert_magic_number, tag!([BERT_MAGIC_NUMBER]));

fn small_integer(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([SMALL_INTEGER_EXT]));
    let (i2, n) = try_parse!(i1, nom::be_u8);
    IResult::Done(i2, BertTerm::Int(n as i32))
}

fn integer(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([INTEGER_EXT]));
    let (i2, n) = try_parse!(i1, nom::be_i32);
    IResult::Done(i2, BertTerm::Int(n))
}

fn atom(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([ATOM_EXT]));
    let (i2, len) = try_parse!(i1, nom::be_u16);
    let (i3, atom_name) = try_parse!(i2, take_str!(len));
    IResult::Done(i3, BertTerm::Atom(atom_name.to_string()))
}

fn small_atom_utf8(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([SMALL_ATOM_UTF8_EXT]));
    let (i2, len) = try_parse!(i1, nom::be_u8);
    let (i3, atom_name) = try_parse!(i2, take_str!(len));
    IResult::Done(i3, BertTerm::Atom(atom_name.to_string()))
}

fn atom_utf8(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([ATOM_UTF8_EXT]));
    let (i2, len) = try_parse!(i1, nom::be_u16);
    let (i3, atom_name) = try_parse!(i2, take_str!(len));
    IResult::Done(i3, BertTerm::Atom(atom_name.to_string()))
}

fn small_tuple(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([SMALL_TUPLE_EXT]));
    let (i2, arity) = try_parse!(i1, nom::be_u8);
    let (i3, tuple) = try_parse!(i2, count!(bert_term, arity as usize));
    IResult::Done(i3, BertTerm::Tuple(tuple))
}

fn large_tuple(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([LARGE_TUPLE_EXT]));
    let (i2, arity) = try_parse!(i1, nom::be_u32);
    let (i3, tuple) = try_parse!(i2, count!(bert_term, arity as usize));
    IResult::Done(i3, BertTerm::Tuple(tuple))
}

fn nil(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([NIL_EXT]));
    IResult::Done(i1, BertTerm::List(vec![]))
}

fn string_like_list(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([STRING_EXT]));
    let (i2, len) = try_parse!(i1, nom::be_u16);
    let (i3, nums) = try_parse!(i2, count!(nom::be_u8, len as usize));
    let elements = nums.into_iter().map(|n| BertTerm::Int(n as i32)).collect();
    IResult::Done(i3, BertTerm::List(elements))
}

fn list(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([LIST_EXT]));
    let (i2, len) = try_parse!(i1, nom::be_u32);
    let (i3, mut elements) = try_parse!(i2, count!(bert_term, len as usize));
    let (i4, tail) = try_parse!(i3, bert_term);
    match tail {
        BertTerm::List(_) => (),
        last_term => { elements.push(last_term); }
    };
    IResult::Done(i4, BertTerm::List(elements))
}

fn binary(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([BINARY_EXT]));
    let (i2, len) = try_parse!(i1, nom::be_u32);
    let (i3, elements) = try_parse!(i2, count!(nom::be_u8, len as usize));
    IResult::Done(i3, BertTerm::Binary(elements))
}

fn float(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([NEW_FLOAT_EXT]));
    let (i2, raw_bytes) = try_parse!(i1, nom::be_u64);
    let f: f64 = unsafe { mem::transmute(raw_bytes) };
    IResult::Done(i2, BertTerm::Float(f))
}

named!(bert_term<&[u8], BertTerm>,
       alt!(small_integer
            | integer
            | atom
            | small_atom_utf8
            | atom_utf8
            | small_tuple
            | large_tuple
            | nil
            | list
            | string_like_list
            | binary
            | float
));

pub fn parse(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, bert_magic_number);
    let (i2, t) = try_parse!(i1, bert_term);
    IResult::Done(i2, t)
}
<commit_msg>Add support for version 0 floats<commit_after>extern crate nom;

use std::mem;
use nom::{IResult, ErrorKind};

static BERT_MAGIC_NUMBER: u8 = 131;
static SMALL_INTEGER_EXT: u8 = 97;
static INTEGER_EXT: u8 = 98;
static FLOAT_EXT: u8 = 99;
static ATOM_EXT: u8 = 100;
static SMALL_TUPLE_EXT: u8 = 104;
static LARGE_TUPLE_EXT: u8 = 105;
static NIL_EXT: u8 = 106;
static STRING_EXT: u8 = 107;
static LIST_EXT: u8 = 108;
static BINARY_EXT: u8 = 109;
static ATOM_UTF8_EXT: u8 = 118;
static SMALL_ATOM_UTF8_EXT: u8 = 119;
static NEW_FLOAT_EXT: u8 = 70;

#[derive(Debug)]
pub enum BertTerm {
    Int(i32),
    Float(f64),
    Atom(String),
    Tuple(Vec<BertTerm>),
    List(Vec<BertTerm>),
    Binary(Vec<u8>)
}

#[derive(Debug)]
pub enum BertError {
    Unknown,
    InvalidMagicNumber
}

named!(bert_magic_number, tag!([BERT_MAGIC_NUMBER]));

fn small_integer(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([SMALL_INTEGER_EXT]));
    let (i2, n) = try_parse!(i1, nom::be_u8);
    IResult::Done(i2, BertTerm::Int(n as i32))
}

fn integer(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([INTEGER_EXT]));
    let (i2, n) = try_parse!(i1, nom::be_i32);
    IResult::Done(i2, BertTerm::Int(n))
}

fn atom(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([ATOM_EXT]));
    let (i2, len) = try_parse!(i1, nom::be_u16);
    let (i3, atom_name) = try_parse!(i2, take_str!(len));
    IResult::Done(i3, BertTerm::Atom(atom_name.to_string()))
}

fn small_atom_utf8(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([SMALL_ATOM_UTF8_EXT]));
    let (i2, len) = try_parse!(i1, nom::be_u8);
    let (i3, atom_name) = try_parse!(i2, take_str!(len));
    IResult::Done(i3, BertTerm::Atom(atom_name.to_string()))
}

fn atom_utf8(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([ATOM_UTF8_EXT]));
    let (i2, len) = try_parse!(i1, nom::be_u16);
    let (i3, atom_name) = try_parse!(i2, take_str!(len));
    IResult::Done(i3, BertTerm::Atom(atom_name.to_string()))
}

fn small_tuple(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([SMALL_TUPLE_EXT]));
    let (i2, arity) = try_parse!(i1, nom::be_u8);
    let (i3, tuple) = try_parse!(i2, count!(bert_term, arity as usize));
    IResult::Done(i3, BertTerm::Tuple(tuple))
}

fn large_tuple(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([LARGE_TUPLE_EXT]));
    let (i2, arity) = try_parse!(i1, nom::be_u32);
    let (i3, tuple) = try_parse!(i2, count!(bert_term, arity as usize));
    IResult::Done(i3, BertTerm::Tuple(tuple))
}

fn nil(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([NIL_EXT]));
    IResult::Done(i1, BertTerm::List(vec![]))
}

fn string_like_list(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([STRING_EXT]));
    let (i2, len) = try_parse!(i1, nom::be_u16);
    let (i3, nums) = try_parse!(i2, count!(nom::be_u8, len as usize));
    let elements = nums.into_iter().map(|n| BertTerm::Int(n as i32)).collect();
    IResult::Done(i3, BertTerm::List(elements))
}

fn list(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([LIST_EXT]));
    let (i2, len) = try_parse!(i1, nom::be_u32);
    let (i3, mut elements) = try_parse!(i2, count!(bert_term, len as usize));
    let (i4, tail) = try_parse!(i3, bert_term);
    match tail {
        BertTerm::List(_) => (),
        last_term => { elements.push(last_term); }
    };
    IResult::Done(i4, BertTerm::List(elements))
}

fn binary(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([BINARY_EXT]));
    let (i2, len) = try_parse!(i1, nom::be_u32);
    let (i3, elements) = try_parse!(i2, count!(nom::be_u8, len as usize));
    IResult::Done(i3, BertTerm::Binary(elements))
}

fn is_zero(b: u8) -> bool { b == 0 }
fn is_non_zero(b: u8) -> bool { b != 0 }

fn old_float(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([FLOAT_EXT]));
    let (i2, bytes) = try_parse!(i1, take_while!(is_non_zero));
    let (i3, _) = try_parse!(i2, take_while!(is_zero));
    let mut s = String::new();
    for b in bytes { s.push(*b as char); }
    let f = s.parse::<f64>().unwrap();
    IResult::Done(i3, BertTerm::Float(f))
}

fn new_float(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, tag!([NEW_FLOAT_EXT]));
    let (i2, raw_bytes) = try_parse!(i1, nom::be_u64);
    let f: f64 = unsafe { mem::transmute(raw_bytes) };
    IResult::Done(i2, BertTerm::Float(f))
}

named!(bert_term<&[u8], BertTerm>,
       alt!(small_integer
            | integer
            | atom
            | small_atom_utf8
            | atom_utf8
            | small_tuple
            | large_tuple
            | nil
            | list
            | string_like_list
            | binary
            | old_float
            | new_float
));

pub fn parse(i0: &[u8]) -> IResult<&[u8], BertTerm> {
    let (i1, _) = try_parse!(i0, bert_magic_number);
    let (i2, t) = try_parse!(i1, bert_term);
    IResult::Done(i2, t)
}
<|endoftext|>


<commit_before>pub use super::*;
use kafka::producer::{Producer, RequiredAcks};
use kafka;
use kafka::consumer::Consumer;
use std::time::Duration;

pub fn test_producer() -> Producer {
    Producer::from_hosts(vec![LOCAL_KAFKA_BOOTSTRAP_HOST.to_owned()])
        .with_ack_timeout(Duration::from_secs(1))
        .with_required_acks(RequiredAcks::One)
        .create()
        .unwrap()
}

/// Return a Consumer builder with some defaults
pub fn test_consumer_builder() -> kafka::consumer::Builder {
    Consumer::from_hosts(vec![LOCAL_KAFKA_BOOTSTRAP_HOST.to_owned()])
        .with_topic_partitions(TEST_TOPIC_NAME.to_owned(), &TEST_TOPIC_PARTITIONS)
        .with_group(TEST_GROUP_NAME.to_owned())
        .with_fallback_offset(kafka::consumer::FetchOffset::Latest)
        .with_offset_storage(kafka::consumer::GroupOffsetStorage::Kafka)
}

/// Return a ready Kafka consumer with all default settings
pub fn test_consumer() -> Consumer {
    test_consumer_builder().create().unwrap()
}

mod producer;
mod consumer;
<commit_msg>Make sure consumer is always at the latest offset<commit_after>pub use super::*;
use kafka::producer::{Producer, RequiredAcks};
use kafka;
use kafka::client::FetchOffset;
use kafka::consumer::Consumer;
use std::time::Duration;

pub fn test_producer() -> Producer {
    Producer::from_hosts(vec![LOCAL_KAFKA_BOOTSTRAP_HOST.to_owned()])
        .with_ack_timeout(Duration::from_secs(1))
        .with_required_acks(RequiredAcks::All)
        .create()
        .unwrap()
}

/// Return a Consumer builder with some defaults
pub fn test_consumer_builder() -> kafka::consumer::Builder {
    Consumer::from_hosts(vec![LOCAL_KAFKA_BOOTSTRAP_HOST.to_owned()])
        .with_topic_partitions(TEST_TOPIC_NAME.to_owned(), &TEST_TOPIC_PARTITIONS)
        .with_group(TEST_GROUP_NAME.to_owned())
        .with_fallback_offset(kafka::consumer::FetchOffset::Latest)
        .with_offset_storage(kafka::consumer::GroupOffsetStorage::Kafka)
}

/// Return a ready Kafka consumer with all default settings
pub fn test_consumer() -> Consumer {
    let mut consumer = test_consumer_builder().create().unwrap();
    let topics = [TEST_TOPIC_NAME, TEST_TOPIC_NAME_2];

    // Fetch the latest offsets and commit those so that this consumer
    // is always at the latest offset before being used.
    {
        let client = consumer.client_mut();
        let latest_offsets = client.fetch_offsets(&topics, FetchOffset::Latest).unwrap();

        for (topic, partition_offsets) in latest_offsets {
            for po in partition_offsets {
                client
                    .commit_offset(TEST_GROUP_NAME, &topic, po.partition, po.offset)
                    .unwrap();
            }
        }
    }

    consumer
}

mod producer;
mod consumer;
<|endoftext|>


<commit_before>// ignore-windows: Concurrency on Windows is not supported yet.

//! Check that destructors of the library thread locals are executed immediately
//! after a thread terminates.
//!
//! FIXME: We should have a similar test for thread-local statics (statics
//! annotated with `#[thread_local]`) once they support destructors.

#![feature(thread_local_internals)]

use std::cell::RefCell;
use std::thread;

struct TestCell {
    value: RefCell<u8>,
}

impl Drop for TestCell {
    fn drop(&mut self) {
        println!("Dropping: {}", self.value.borrow())
    }
}

static A: std::thread::LocalKey<TestCell> = {
    #[inline]
    fn __init() -> TestCell {
        TestCell { value: RefCell::new(0) }
    }

    unsafe fn __getit() -> Option<&'static TestCell> {
        static __KEY: std::thread::__OsLocalKeyInner<TestCell> =
            std::thread::__OsLocalKeyInner::new();
        __KEY.get(__init)
    }

    unsafe { std::thread::LocalKey::new(__getit) }
};

fn main() {
    thread::spawn(|| {
        A.with(|f| {
            assert_eq!(*f.value.borrow(), 0);
            *f.value.borrow_mut() = 5;
        });
    })
    .join()
    .unwrap();
    println!("Continue main.")
}
<commit_msg>Change the test not to rely on internals.<commit_after>// ignore-windows: Concurrency on Windows is not supported yet.

//! Check that destructors of the library thread locals are executed immediately
//! after a thread terminates.

use std::cell::RefCell;
use std::thread;

struct TestCell {
    value: RefCell<u8>,
}

impl Drop for TestCell {
    fn drop(&mut self) {
        println!("Dropping: {}", self.value.borrow())
    }
}

thread_local! {
    static A: TestCell = TestCell { value: RefCell::new(0) };
}

fn main() {
    thread::spawn(|| {
        A.with(|f| {
            assert_eq!(*f.value.borrow(), 0);
            *f.value.borrow_mut() = 5;
        });
    })
    .join()
    .unwrap();
    println!("Continue main.")
}
<|endoftext|>


<commit_before>#[cfg(feature = "std")]
pub trait ElfSym {
    fn st_name(&self) -> usize;
    fn st_info(&self) -> u8;
    fn st_other(&self) -> u8;
    fn st_shndx(&self) -> usize;
    fn st_value(&self) -> u64;
    fn st_size(&self) -> u64;
    fn is_function(&self) -> bool;
    fn is_import(&self) -> bool;
}

/// === Sym bindings ===
/// Local symbol.
pub const STB_LOCAL: u8 = 0;
/// Global symbol.
pub const STB_GLOBAL: u8 = 1;
/// Weak symbol.
pub const STB_WEAK: u8 = 2;
/// Number of defined types..
pub const STB_NUM: u8 = 3;
/// Start of OS-specific.
pub const STB_LOOS: u8 = 10;
/// Unique symbol..
pub const STB_GNU_UNIQUE: u8 = 10;
/// End of OS-specific.
pub const STB_HIOS: u8 = 12;
/// Start of processor-specific.
pub const STB_LOPROC: u8 = 13;
/// End of processor-specific.
pub const STB_HIPROC: u8 = 15;

/// === Sym types ===
/// Symbol type is unspecified.
pub const STT_NOTYPE: u8 = 0;
/// Symbol is a data object.
pub const STT_OBJECT: u8 = 1;
/// Symbol is a code object.
pub const STT_FUNC: u8 = 2;
/// Symbol associated with a section.
pub const STT_SECTION: u8 = 3;
/// Symbol's name is file name.
pub const STT_FILE: u8 = 4;
/// Symbol is a common data object.
pub const STT_COMMON: u8 = 5;
/// Symbol is thread-local data object.
pub const STT_TLS: u8 = 6;
/// Number of defined types.
pub const STT_NUM: u8 = 7;
/// Start of OS-specific.
pub const STT_LOOS: u8 = 10;
/// Symbol is indirect code object.
pub const STT_GNU_IFUNC: u8 = 10;
/// End of OS-specific.
pub const STT_HIOS: u8 = 12;
/// Start of processor-specific.
pub const STT_LOPROC: u8 = 13;
/// End of processor-specific.
pub const STT_HIPROC: u8 = 15;

/// Get the ST binding.
///
/// This is the first four bits of the byte.
#[inline]
pub fn st_bind(info: u8) -> u8 {
    info >> 4
}

/// Get the ST type.
///
/// This is the last four bits of the byte.
#[inline]
pub fn st_type(info: u8) -> u8 {
    info & 0xf
}

/// Is this information defining an import?
#[inline]
pub fn is_import(info: u8, value: u64) -> bool {
    let binding = st_bind(info);
    binding == STB_GLOBAL && value == 0
}

/// Convenience function to get the &'static str type from the symbols `st_info`.
pub fn get_type(info: u8) -> &'static str {
    type_to_str(st_type(info))
}

/// Get the string for some binding.
#[inline]
pub fn bind_to_str(typ: u8) -> &'static str {
    match typ {
        STB_LOCAL => "LOCAL",
        STB_GLOBAL => "GLOBAL",
        STB_WEAK => "WEAK",
        STB_NUM => "NUM",
        STB_GNU_UNIQUE => "GNU_UNIQUE",
        _ => "UNKNOWN_STB",
    }
}

/// Get the string for some type.
#[inline]
pub fn type_to_str(typ: u8) -> &'static str {
    match typ {
        STT_NOTYPE => "NOTYPE",
        STT_OBJECT => "OBJECT",
        STT_FUNC => "FUNC",
        STT_SECTION => "SECTION",
        STT_FILE => "FILE",
        STT_COMMON => "COMMON",
        STT_TLS => "TLS",
        STT_NUM => "NUM",
        STT_GNU_IFUNC => "GNU_IFUNC",
        _ => "UNKNOWN_STT",
    }
}

macro_rules! elf_sym_impure_impl {
        ($from_endian:item) => {

            #[cfg(feature = "std")]
            pub use self::impure::*;

            #[cfg(feature = "std")]
            mod impure {
                use super::*;

                use core::fmt;
                use core::slice;

                use std::fs::File;
                use std::io::{self, Read, Seek};
                use std::io::SeekFrom::Start;

                impl ElfSym for Sym {
                    fn st_name(&self) -> usize {
                        self.st_name as usize
                    }
                    fn st_info(&self) -> u8 {
                        self.st_info
                    }
                    fn st_other(&self) -> u8 {
                        self.st_other
                    }
                    fn st_shndx(&self) -> usize {
                        self.st_shndx as usize
                    }
                    fn st_value(&self) -> u64 {
                        self.st_value as u64
                    }
                    fn st_size(&self) -> u64 {
                        self.st_size as u64
                    }
                    fn is_function(&self) -> bool {
                        self.is_function()
                    }
                    fn is_import(&self) -> bool {
                        self.is_import()
                    }
                }

                impl Sym {
                   /// Checks whether this `Sym` has `STB_GLOBAL`/`STB_WEAK` binding and a `st_value` of 0
                   pub fn is_import(&self) -> bool {
                     let binding = self.st_info >> 4;
                     (binding == STB_GLOBAL || binding == STB_WEAK) && self.st_value == 0
                   }
                   /// Checks whether this `Sym` has type `STT_FUNC`
                   pub fn is_function(&self) -> bool {
                     st_type(self.st_info) == STT_FUNC
                   }
                }

                impl fmt::Debug for Sym {
                    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                        let bind = st_bind(self.st_info);
                        let typ = st_type(self.st_info);
                        write!(f,
                               "st_name: {} {} {} st_other: {} st_shndx: {} st_value: {:x} st_size: {}",
                               self.st_name,
                               bind_to_str(bind),
                               type_to_str(typ),
                               self.st_other,
                               self.st_shndx,
                               self.st_value,
                               self.st_size)
                    }
                }

                pub unsafe fn from_raw<'a>(symp: *const Sym, count: usize) -> &'a [Sym] {
                    slice::from_raw_parts(symp, count)
                }

                pub fn from_fd<'a>(fd: &mut File, offset: usize, count: usize) -> io::Result<Vec<Sym>> {
                    // TODO: AFAIK this shouldn't work, since i pass in a byte size...
                    // FIX THIS, unecessary allocations + unsafety here
                    let mut bytes = vec![0u8; count * SIZEOF_SYM];
                    try!(fd.seek(Start(offset as u64)));
                    try!(fd.read(&mut bytes));
                    let bytes = unsafe { slice::from_raw_parts(bytes.as_ptr() as *mut Sym, count) };
                    let mut syms = Vec::with_capacity(count);
                    syms.extend_from_slice(bytes);
                    syms.dedup();
                    Ok(syms)
                }

                #[cfg(feature = "endian_fd")]
                $from_endian

            }
        };
    }
<commit_msg>elf.sym: add st_type and st_bind as convenience functions<commit_after>#[cfg(feature = "std")]
pub trait ElfSym {
    fn st_name(&self) -> usize;
    fn st_info(&self) -> u8;
    fn st_other(&self) -> u8;
    fn st_shndx(&self) -> usize;
    fn st_value(&self) -> u64;
    fn st_size(&self) -> u64;
    fn is_function(&self) -> bool;
    fn is_import(&self) -> bool;
    fn st_type(&self) -> u8;
    fn st_bind(&self) -> u8;
}

/// === Sym bindings ===
/// Local symbol.
pub const STB_LOCAL: u8 = 0;
/// Global symbol.
pub const STB_GLOBAL: u8 = 1;
/// Weak symbol.
pub const STB_WEAK: u8 = 2;
/// Number of defined types..
pub const STB_NUM: u8 = 3;
/// Start of OS-specific.
pub const STB_LOOS: u8 = 10;
/// Unique symbol..
pub const STB_GNU_UNIQUE: u8 = 10;
/// End of OS-specific.
pub const STB_HIOS: u8 = 12;
/// Start of processor-specific.
pub const STB_LOPROC: u8 = 13;
/// End of processor-specific.
pub const STB_HIPROC: u8 = 15;

/// === Sym types ===
/// Symbol type is unspecified.
pub const STT_NOTYPE: u8 = 0;
/// Symbol is a data object.
pub const STT_OBJECT: u8 = 1;
/// Symbol is a code object.
pub const STT_FUNC: u8 = 2;
/// Symbol associated with a section.
pub const STT_SECTION: u8 = 3;
/// Symbol's name is file name.
pub const STT_FILE: u8 = 4;
/// Symbol is a common data object.
pub const STT_COMMON: u8 = 5;
/// Symbol is thread-local data object.
pub const STT_TLS: u8 = 6;
/// Number of defined types.
pub const STT_NUM: u8 = 7;
/// Start of OS-specific.
pub const STT_LOOS: u8 = 10;
/// Symbol is indirect code object.
pub const STT_GNU_IFUNC: u8 = 10;
/// End of OS-specific.
pub const STT_HIOS: u8 = 12;
/// Start of processor-specific.
pub const STT_LOPROC: u8 = 13;
/// End of processor-specific.
pub const STT_HIPROC: u8 = 15;

/// Get the ST binding.
///
/// This is the first four bits of the byte.
#[inline]
pub fn st_bind(info: u8) -> u8 {
    info >> 4
}

/// Get the ST type.
///
/// This is the last four bits of the byte.
#[inline]
pub fn st_type(info: u8) -> u8 {
    info & 0xf
}

/// Is this information defining an import?
#[inline]
pub fn is_import(info: u8, value: u64) -> bool {
    let binding = st_bind(info);
    binding == STB_GLOBAL && value == 0
}

/// Convenience function to get the &'static str type from the symbols `st_info`.
pub fn get_type(info: u8) -> &'static str {
    type_to_str(st_type(info))
}

/// Get the string for some binding.
#[inline]
pub fn bind_to_str(typ: u8) -> &'static str {
    match typ {
        STB_LOCAL => "LOCAL",
        STB_GLOBAL => "GLOBAL",
        STB_WEAK => "WEAK",
        STB_NUM => "NUM",
        STB_GNU_UNIQUE => "GNU_UNIQUE",
        _ => "UNKNOWN_STB",
    }
}

/// Get the string for some type.
#[inline]
pub fn type_to_str(typ: u8) -> &'static str {
    match typ {
        STT_NOTYPE => "NOTYPE",
        STT_OBJECT => "OBJECT",
        STT_FUNC => "FUNC",
        STT_SECTION => "SECTION",
        STT_FILE => "FILE",
        STT_COMMON => "COMMON",
        STT_TLS => "TLS",
        STT_NUM => "NUM",
        STT_GNU_IFUNC => "GNU_IFUNC",
        _ => "UNKNOWN_STT",
    }
}

macro_rules! elf_sym_impure_impl {
        ($from_endian:item) => {

            #[cfg(feature = "std")]
            pub use self::impure::*;

            #[cfg(feature = "std")]
            mod impure {
                use super::*;

                use core::fmt;
                use core::slice;

                use std::fs::File;
                use std::io::{self, Read, Seek};
                use std::io::SeekFrom::Start;

                impl ElfSym for Sym {
                    fn st_name(&self) -> usize {
                        self.st_name as usize
                    }
                    fn st_info(&self) -> u8 {
                        self.st_info
                    }
                    fn st_other(&self) -> u8 {
                        self.st_other
                    }
                    fn st_shndx(&self) -> usize {
                        self.st_shndx as usize
                    }
                    fn st_value(&self) -> u64 {
                        self.st_value as u64
                    }
                    fn st_size(&self) -> u64 {
                        self.st_size as u64
                    }
                    fn is_function(&self) -> bool {
                        self.is_function()
                    }
                    fn is_import(&self) -> bool {
                        self.is_import()
                    }
                    /// Get the ST binding.
                    ///
                    /// This is the first four bits of the byte.
                    #[inline]
                    fn st_bind(&self) -> u8 {
                        self.st_info() >> 4
                    }
                    /// Get the ST type.
                    ///
                    /// This is the last four bits of the byte.
                    #[inline]
                    fn st_type(&self) -> u8 {
                        self.st_info() & 0xf
                    }
                }

                impl Sym {
                   /// Checks whether this `Sym` has `STB_GLOBAL`/`STB_WEAK` binding and a `st_value` of 0
                   pub fn is_import(&self) -> bool {
                     let binding = self.st_info >> 4;
                     (binding == STB_GLOBAL || binding == STB_WEAK) && self.st_value == 0
                   }
                   /// Checks whether this `Sym` has type `STT_FUNC`
                   pub fn is_function(&self) -> bool {
                     st_type(self.st_info) == STT_FUNC
                   }
                }

                impl fmt::Debug for Sym {
                    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                        let bind = st_bind(self.st_info);
                        let typ = st_type(self.st_info);
                        write!(f,
                               "st_name: {} {} {} st_other: {} st_shndx: {} st_value: {:x} st_size: {}",
                               self.st_name,
                               bind_to_str(bind),
                               type_to_str(typ),
                               self.st_other,
                               self.st_shndx,
                               self.st_value,
                               self.st_size)
                    }
                }

                pub unsafe fn from_raw<'a>(symp: *const Sym, count: usize) -> &'a [Sym] {
                    slice::from_raw_parts(symp, count)
                }

                pub fn from_fd<'a>(fd: &mut File, offset: usize, count: usize) -> io::Result<Vec<Sym>> {
                    // TODO: AFAIK this shouldn't work, since i pass in a byte size...
                    // FIX THIS, unecessary allocations + unsafety here
                    let mut bytes = vec![0u8; count * SIZEOF_SYM];
                    try!(fd.seek(Start(offset as u64)));
                    try!(fd.read(&mut bytes));
                    let bytes = unsafe { slice::from_raw_parts(bytes.as_ptr() as *mut Sym, count) };
                    let mut syms = Vec::with_capacity(count);
                    syms.extend_from_slice(bytes);
                    syms.dedup();
                    Ok(syms)
                }

                #[cfg(feature = "endian_fd")]
                $from_endian

            }
        };
    }
<|endoftext|>