<commit_before>//! Check CPU usage of the currently-running container

extern crate rustc_serialize;
extern crate docopt;

extern crate turbine_plugins;

use docopt::Docopt;

use turbine_plugins::Status;
use turbine_plugins::linux::{Jiffies, Ratio};
use turbine_plugins::procfs::{Calculations, RunningProcs};
use turbine_plugins::sys::fs::cgroup::cpuacct::Stat as CGroupStat;

static USAGE: &'static str = "
Usage:
    check-container-cpu [--one-cpu-share] [options]
    check-cpu (-h | --help)

Options:
    -h, --help            Show this help message

    -w, --warn=<percent>  Percent to warn at           [default: 80]
    -c, --crit=<percent>  Percent to critical at       [default: 80]

    -s, --sample=<secs>   Seconds to take sample over  [default: 5]

    --show-hogs=<count>   Show <count> most cpu-intensive processes in this
                          container.                   [default: 0]

About usage percentages:

    Percentages should be specified relative to a single CPU's usage. So if you
    have a process that you want to be allowed to use 4 CPUs worth of processor
    time, and you were planning on going critical at 90%, you should specify
    something like '--crit 360'
";

#[derive(RustcDecodable, Debug)]
struct Args {
    flag_warn: u32,
    flag_crit: u32,

    flag_sample: u32,
    flag_show_hogs: usize,
}

// These all should be extremely similar to each other, so just taking the
// middle one should be safe
fn find_median_jiffies_used(start: &[Calculations], end: &[Calculations]) -> Jiffies {
    let mut jiffies: Vec<_> = start.iter().zip(end)
        .map(|(start, end)| end.total() - start.total())
        .collect();
    jiffies.sort();
    jiffies[jiffies.len() / 2]
}

fn main() {
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.decode())
        .unwrap_or_else(|e| e.exit());

    let start_cpu = Calculations::load_per_cpu().unwrap();
    let start_container = CGroupStat::load();
    let mut start_per_proc = None;
    if args.flag_show_hogs > 0 {
        start_per_proc = Some(RunningProcs::currently_running().unwrap());
    }

    std::thread::sleep_ms(args.flag_sample * 1000);

    let end_cpu = Calculations::load_per_cpu().unwrap();
    let end_container = CGroupStat::load();

    let median_jiffies = find_median_jiffies_used(&start_cpu, &end_cpu);

    let container_usage = end_container.unwrap().total() - start_container.unwrap().total();
    let percent = container_usage.duration()
        .ratio(&median_jiffies.duration());

    let mut status = Status::Ok;
    if percent > args.flag_crit as f64 {
        println!("CRITICAL: Container is using {}% CPU (> {}%)", percent, args.flag_crit);
        status = Status::Critical;
    } else if percent > args.flag_warn as f64 {
        println!("WARNING: Container is using {}% CPU (> {}%)", percent, args.flag_warn);
        status = Status::Warning;
    } else {
        println!("OK: Container is using {}% CPU (< {}%)", percent, args.flag_warn);
    }
    if args.flag_show_hogs > 0 {
        let end_per_proc = RunningProcs::currently_running().unwrap();
        let start_per_proc = start_per_proc.unwrap();
        let mut per_proc = end_per_proc.percent_cpu_util_since(
            &start_per_proc,
            median_jiffies);
        per_proc.0.sort_by(|l, r| r.total.partial_cmp(&l.total).unwrap());
        println!("INFO [check-container-cpu]: hogs");
        for usage in per_proc.0.iter().take(args.flag_show_hogs) {
            println!("[{:>5}]{:>5.1}%: {}",
                     usage.process.stat.pid,
                     usage.total,
                     usage.process.useful_cmdline());
        }
    }
    status.exit();
}

#[cfg(test)]
mod unit {
    use docopt::Docopt;
    use turbine_plugins::procfs::{Calculations}; //, RunningProcs};
    use turbine_plugins::linux::Jiffies;
    use super::{USAGE, Args, find_median_jiffies_used};

    #[test]
    fn opts_parse() {
        let args: Args = Docopt::new(USAGE)
            .and_then(|d| d.argv(vec!["arg0", "--crit", "480", "--warn", "20"].into_iter())
                      .decode())
            .unwrap();
        assert_eq!(args.flag_crit, 480);
    }

    fn start() -> Calculations {
        Calculations {
            user: Jiffies::new(100),
            nice: Jiffies::new(100),
            system: Jiffies::new(100),
            idle: Jiffies::new(100),
            iowait: Jiffies::new(100),
            irq: Jiffies::new(100),
            softirq: Jiffies::new(100),
            steal: Jiffies::new(100),
            guest: Jiffies::new(100),
            guest_nice: Some(Jiffies::new(0)),
        }
    }

    #[test]
    fn median_jiffies_works_with_single_cpu() {
        let start = vec![
            start(),
            ];
        let end = vec![
            Calculations {
                user: Jiffies::new(110),
                ..start[0]
            }];

        let median = find_median_jiffies_used(&start, &end);

        assert_eq!(median, Jiffies::new(10));
    }

    #[test]
    fn median_jiffies_works_with_several_cpus() {
        let mut start_calcs = vec![
            start(),
            start(),
            start(),
            start(),
            ];
        let mut end = vec![
            Calculations {
                user: Jiffies::new(109),
                ..start_calcs[0]
            },
            Calculations {
                user: Jiffies::new(110),
                ..start_calcs[0]
            },
            Calculations {
                user: Jiffies::new(111),
                ..start_calcs[0]
            },
            Calculations {
                user: Jiffies::new(109),
                ..start_calcs[0]
            },
            ];

        let median = find_median_jiffies_used(&start_calcs, &end);

        assert_eq!(median, Jiffies::new(10));

        start_calcs.push(start());
        end.push(Calculations {
            user: Jiffies::new(109),
            ..start_calcs[0]
        });

        let median = find_median_jiffies_used(&start_calcs, &end);
        assert_eq!(median, Jiffies::new(9))
    }
}
<commit_msg>check-c-cpu: fix usage string<commit_after>//! Check CPU usage of the currently-running container

extern crate rustc_serialize;
extern crate docopt;

extern crate turbine_plugins;

use docopt::Docopt;

use turbine_plugins::Status;
use turbine_plugins::linux::{Jiffies, Ratio};
use turbine_plugins::procfs::{Calculations, RunningProcs};
use turbine_plugins::sys::fs::cgroup::cpuacct::Stat as CGroupStat;

static USAGE: &'static str = "
Usage:
    check-container-cpu [options]
    check-cpu (-h | --help)

Check the cpu usage of the currently-running container. This must be run from
inside the container to be checked.

Options:
    -h, --help            Show this help message

    -w, --warn=<percent>  Percent to warn at           [default: 80]
    -c, --crit=<percent>  Percent to critical at       [default: 80]

    -s, --sample=<secs>   Seconds to take sample over  [default: 5]

    --show-hogs=<count>   Show <count> most cpu-intensive processes in this
                          container.                   [default: 0]

About usage percentages:

    Percentages should be specified relative to a single CPU's usage. So if you
    have a process that you want to be allowed to use 4 CPUs worth of processor
    time, and you were planning on going critical at 90%, you should specify
    something like '--crit 360'
";

#[derive(RustcDecodable, Debug)]
struct Args {
    flag_warn: u32,
    flag_crit: u32,

    flag_sample: u32,
    flag_show_hogs: usize,
}

// These all should be extremely similar to each other, so just taking the
// middle one should be safe
fn find_median_jiffies_used(start: &[Calculations], end: &[Calculations]) -> Jiffies {
    let mut jiffies: Vec<_> = start.iter().zip(end)
        .map(|(start, end)| end.total() - start.total())
        .collect();
    jiffies.sort();
    jiffies[jiffies.len() / 2]
}

fn main() {
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.decode())
        .unwrap_or_else(|e| e.exit());

    let start_cpu = Calculations::load_per_cpu().unwrap();
    let start_container = CGroupStat::load();
    let mut start_per_proc = None;
    if args.flag_show_hogs > 0 {
        start_per_proc = Some(RunningProcs::currently_running().unwrap());
    }

    std::thread::sleep_ms(args.flag_sample * 1000);

    let end_cpu = Calculations::load_per_cpu().unwrap();
    let end_container = CGroupStat::load();

    let median_jiffies = find_median_jiffies_used(&start_cpu, &end_cpu);

    let container_usage = end_container.unwrap().total() - start_container.unwrap().total();
    let percent = container_usage.duration()
        .ratio(&median_jiffies.duration());

    let mut status = Status::Ok;
    if percent > args.flag_crit as f64 {
        println!("CRITICAL: Container is using {}% CPU (> {}%)", percent, args.flag_crit);
        status = Status::Critical;
    } else if percent > args.flag_warn as f64 {
        println!("WARNING: Container is using {}% CPU (> {}%)", percent, args.flag_warn);
        status = Status::Warning;
    } else {
        println!("OK: Container is using {}% CPU (< {}%)", percent, args.flag_warn);
    }
    if args.flag_show_hogs > 0 {
        let end_per_proc = RunningProcs::currently_running().unwrap();
        let start_per_proc = start_per_proc.unwrap();
        let mut per_proc = end_per_proc.percent_cpu_util_since(
            &start_per_proc,
            median_jiffies);
        per_proc.0.sort_by(|l, r| r.total.partial_cmp(&l.total).unwrap());
        println!("INFO [check-container-cpu]: hogs");
        for usage in per_proc.0.iter().take(args.flag_show_hogs) {
            println!("[{:>5}]{:>5.1}%: {}",
                     usage.process.stat.pid,
                     usage.total,
                     usage.process.useful_cmdline());
        }
    }
    status.exit();
}

#[cfg(test)]
mod unit {
    use docopt::Docopt;
    use turbine_plugins::procfs::{Calculations}; //, RunningProcs};
    use turbine_plugins::linux::Jiffies;
    use super::{USAGE, Args, find_median_jiffies_used};

    #[test]
    fn opts_parse() {
        let args: Args = Docopt::new(USAGE)
            .and_then(|d| d.argv(vec!["arg0", "--crit", "480", "--warn", "20"].into_iter())
                      .decode())
            .unwrap();
        assert_eq!(args.flag_crit, 480);
    }

    fn start() -> Calculations {
        Calculations {
            user: Jiffies::new(100),
            nice: Jiffies::new(100),
            system: Jiffies::new(100),
            idle: Jiffies::new(100),
            iowait: Jiffies::new(100),
            irq: Jiffies::new(100),
            softirq: Jiffies::new(100),
            steal: Jiffies::new(100),
            guest: Jiffies::new(100),
            guest_nice: Some(Jiffies::new(0)),
        }
    }

    #[test]
    fn median_jiffies_works_with_single_cpu() {
        let start = vec![
            start(),
            ];
        let end = vec![
            Calculations {
                user: Jiffies::new(110),
                ..start[0]
            }];

        let median = find_median_jiffies_used(&start, &end);

        assert_eq!(median, Jiffies::new(10));
    }

    #[test]
    fn median_jiffies_works_with_several_cpus() {
        let mut start_calcs = vec![
            start(),
            start(),
            start(),
            start(),
            ];
        let mut end = vec![
            Calculations {
                user: Jiffies::new(109),
                ..start_calcs[0]
            },
            Calculations {
                user: Jiffies::new(110),
                ..start_calcs[0]
            },
            Calculations {
                user: Jiffies::new(111),
                ..start_calcs[0]
            },
            Calculations {
                user: Jiffies::new(109),
                ..start_calcs[0]
            },
            ];

        let median = find_median_jiffies_used(&start_calcs, &end);

        assert_eq!(median, Jiffies::new(10));

        start_calcs.push(start());
        end.push(Calculations {
            user: Jiffies::new(109),
            ..start_calcs[0]
        });

        let median = find_median_jiffies_used(&start_calcs, &end);
        assert_eq!(median, Jiffies::new(9))
    }
}
<|endoftext|>


<commit_before>// Std
use std::{ops::BitOr, str::FromStr};

// Third party
use bitflags::bitflags;

#[doc(hidden)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ArgFlags(Flags);

impl Default for ArgFlags {
    fn default() -> Self {
        Self::empty()
    }
}

/// Various settings that apply to arguments and may be set, unset, and checked via getter/setter
/// methods [`Arg::setting`], [`Arg::unset_setting`], and [`Arg::is_set`]. This is what the
/// [`Arg`] methods which accept a `bool` use internally.
///
/// [`Arg`]: crate::Arg
/// [`Arg::setting`]: crate::Arg::setting()
/// [`Arg::unset_setting`]: crate::Arg::unset_setting()
/// [`Arg::is_set`]: crate::Arg::is_set()
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum ArgSettings {
    /// Specifies that an arg must be used
    Required,
    /// Allows an arg to accept multiple values
    MultipleValues,
    /// Allows an arg to appear multiple times
    MultipleOccurrences,
    /// Deprecated, see [`ArgSettings::MultipleOccurrences`] (most likely what you want) and
    /// [`ArgSettings::MultipleValues`]
    #[deprecated(
        since = "3.0.0",
        note = "Split into `ArgSettings::MultipleOccurrences` (most likely what you want)  and `ArgSettings::MultipleValues`"
    )]
    Multiple,
    /// Forbids an arg from accepting empty values such as `""`
    ForbidEmptyValues,
    /// Sets an arg to be global (i.e. exist in all subcommands)
    Global,
    /// Hides an arg from the help message
    Hidden,
    /// Allows an argument to take a value (such as `--option value`)
    TakesValue,
    /// Enables a delimiter to break up arguments `--option val1,val2,val3` becomes three values
    /// (`val1`, `val2`, and `val3`) instead of the default one (`val1,val2,val3`)
    UseValueDelimiter,
    /// Tells an arg to display it's help on the line below the arg itself in the help message
    NextLineHelp,
    /// Says that arg *must* use a delimiter to separate values
    RequireDelimiter,
    /// Hides the possible values from the help message
    HidePossibleValues,
    /// Allows values that start with a hyphen
    AllowHyphenValues,
    /// Deprecated, replaced with [`ArgSettings::AllowHyphenValues`]
    #[deprecated(
        since = "3.0.0",
        note = "Replaced with `ArgSettings::AllowHyphenValues`"
    )]
    AllowLeadingHyphen,
    /// Requires that an equals be used to provide a value to an option such as `--option=value`
    RequireEquals,
    /// Says that a positional arg will be the last positional, and requires `--` to be accessed.
    /// It can also be accessed early (i.e. before other positionals) by providing `--`
    Last,
    /// Hides the default value from the help message
    HideDefaultValue,
    /// Possible values become case insensitive
    IgnoreCase,
    /// Deprecated, replaced with [`ArgSettings::IgnoreCase`]
    #[deprecated(since = "3.0.0", note = "Replaced with `ArgSettings::IgnoreCase`")]
    CaseInsensitive,
    /// Hides environment variable arguments from the help message
    #[cfg(feature = "env")]
    HideEnv,
    /// Hides any values currently assigned to ENV variables in the help message (good for sensitive
    /// information)
    #[cfg(feature = "env")]
    HideEnvValues,
    /// The argument should **not** be shown in short help text
    HiddenShortHelp,
    /// The argument should **not** be shown in long help text
    HiddenLongHelp,
    /// Specifies that option values that are invalid UTF-8 should *not* be treated as an error.
    AllowInvalidUtf8,
    /// Specifies that option should exist on its own.
    /// Having any othe arguments present at runtime is an error.
    Exclusive,
}

bitflags! {
    struct Flags: u32 {
        const REQUIRED         = 1;
        const MULTIPLE_OCC     = 1 << 1;
        const NO_EMPTY_VALS    = 1 << 2;
        const GLOBAL           = 1 << 3;
        const HIDDEN           = 1 << 4;
        const TAKES_VAL        = 1 << 5;
        const USE_DELIM        = 1 << 6;
        const NEXT_LINE_HELP   = 1 << 7;
        const REQ_DELIM        = 1 << 9;
        const DELIM_NOT_SET    = 1 << 10;
        const HIDE_POS_VALS    = 1 << 11;
        const ALLOW_TAC_VALS   = 1 << 12;
        const REQUIRE_EQUALS   = 1 << 13;
        const LAST             = 1 << 14;
        const HIDE_DEFAULT_VAL = 1 << 15;
        const CASE_INSENSITIVE = 1 << 16;
        #[cfg(feature = "env")]
        const HIDE_ENV_VALS    = 1 << 17;
        const HIDDEN_SHORT_H   = 1 << 18;
        const HIDDEN_LONG_H    = 1 << 19;
        const MULTIPLE_VALS    = 1 << 20;
        const MULTIPLE         = Self::MULTIPLE_OCC.bits | Self::MULTIPLE_VALS.bits;
        #[cfg(feature = "env")]
        const HIDE_ENV         = 1 << 21;
        const UTF8_NONE        = 1 << 22;
        const EXCLUSIVE        = 1 << 23;
        const NO_OP            = 0;
    }
}

// @TODO @p6 @internal: Reorder alphabetically
impl_settings! { ArgSettings, ArgFlags,
    Required("required") => Flags::REQUIRED,
    MultipleOccurrences("multipleoccurrences") => Flags::MULTIPLE_OCC,
    MultipleValues("multiplevalues") => Flags::MULTIPLE_VALS,
    Multiple("multiple") => Flags::MULTIPLE,
    ForbidEmptyValues("forbidemptyvalues") => Flags::NO_EMPTY_VALS,
    Global("global") => Flags::GLOBAL,
    Hidden("hidden") => Flags::HIDDEN,
    TakesValue("takesvalue") => Flags::TAKES_VAL,
    UseValueDelimiter("usevaluedelimiter") => Flags::USE_DELIM,
    NextLineHelp("nextlinehelp") => Flags::NEXT_LINE_HELP,
    RequireDelimiter("requiredelimiter") => Flags::REQ_DELIM,
    HidePossibleValues("hidepossiblevalues") => Flags::HIDE_POS_VALS,
    AllowHyphenValues("allowhyphenvalues") => Flags::ALLOW_TAC_VALS,
    AllowLeadingHyphen("allowleadinghypyhen") => Flags::ALLOW_TAC_VALS,
    RequireEquals("requireequals") => Flags::REQUIRE_EQUALS,
    Last("last") => Flags::LAST,
    IgnoreCase("ignorecase") => Flags::CASE_INSENSITIVE,
    CaseInsensitive("caseinsensitive") => Flags::CASE_INSENSITIVE,
    #[cfg(feature = "env")]
    HideEnv("hideenv") => Flags::HIDE_ENV,
    #[cfg(feature = "env")]
    HideEnvValues("hideenvvalues") => Flags::HIDE_ENV_VALS,
    HideDefaultValue("hidedefaultvalue") => Flags::HIDE_DEFAULT_VAL,
    HiddenShortHelp("hiddenshorthelp") => Flags::HIDDEN_SHORT_H,
    HiddenLongHelp("hiddenlonghelp") => Flags::HIDDEN_LONG_H,
    AllowInvalidUtf8("allowinvalidutf8") => Flags::UTF8_NONE,
    Exclusive("exclusive") => Flags::EXCLUSIVE
}

#[cfg(test)]
mod test {
    use super::ArgSettings;

    #[test]
    fn arg_settings_fromstr() {
        assert_eq!(
            "allowhyphenvalues".parse::<ArgSettings>().unwrap(),
            ArgSettings::AllowHyphenValues
        );
        assert_eq!(
            "forbidemptyvalues".parse::<ArgSettings>().unwrap(),
            ArgSettings::ForbidEmptyValues
        );
        assert_eq!(
            "hidepossiblevalues".parse::<ArgSettings>().unwrap(),
            ArgSettings::HidePossibleValues
        );
        assert_eq!(
            "hidden".parse::<ArgSettings>().unwrap(),
            ArgSettings::Hidden
        );
        assert_eq!(
            "nextlinehelp".parse::<ArgSettings>().unwrap(),
            ArgSettings::NextLineHelp
        );
        assert_eq!(
            "requiredelimiter".parse::<ArgSettings>().unwrap(),
            ArgSettings::RequireDelimiter
        );
        assert_eq!(
            "required".parse::<ArgSettings>().unwrap(),
            ArgSettings::Required
        );
        assert_eq!(
            "takesvalue".parse::<ArgSettings>().unwrap(),
            ArgSettings::TakesValue
        );
        assert_eq!(
            "usevaluedelimiter".parse::<ArgSettings>().unwrap(),
            ArgSettings::UseValueDelimiter
        );
        assert_eq!(
            "requireequals".parse::<ArgSettings>().unwrap(),
            ArgSettings::RequireEquals
        );
        assert_eq!("last".parse::<ArgSettings>().unwrap(), ArgSettings::Last);
        assert_eq!(
            "hidedefaultvalue".parse::<ArgSettings>().unwrap(),
            ArgSettings::HideDefaultValue
        );
        assert_eq!(
            "ignorecase".parse::<ArgSettings>().unwrap(),
            ArgSettings::IgnoreCase
        );
        #[cfg(feature = "env")]
        assert_eq!(
            "hideenv".parse::<ArgSettings>().unwrap(),
            ArgSettings::HideEnv
        );
        #[cfg(feature = "env")]
        assert_eq!(
            "hideenvvalues".parse::<ArgSettings>().unwrap(),
            ArgSettings::HideEnvValues
        );
        assert_eq!(
            "hiddenshorthelp".parse::<ArgSettings>().unwrap(),
            ArgSettings::HiddenShortHelp
        );
        assert_eq!(
            "hiddenlonghelp".parse::<ArgSettings>().unwrap(),
            ArgSettings::HiddenLongHelp
        );
        assert_eq!(
            "allowinvalidutf8".parse::<ArgSettings>().unwrap(),
            ArgSettings::AllowInvalidUtf8
        );
        assert_eq!(
            "exclusive".parse::<ArgSettings>().unwrap(),
            ArgSettings::Exclusive
        );
        assert!("hahahaha".parse::<ArgSettings>().is_err());
    }
}
<commit_msg>fix: Fix typo<commit_after>// Std
use std::{ops::BitOr, str::FromStr};

// Third party
use bitflags::bitflags;

#[doc(hidden)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ArgFlags(Flags);

impl Default for ArgFlags {
    fn default() -> Self {
        Self::empty()
    }
}

/// Various settings that apply to arguments and may be set, unset, and checked via getter/setter
/// methods [`Arg::setting`], [`Arg::unset_setting`], and [`Arg::is_set`]. This is what the
/// [`Arg`] methods which accept a `bool` use internally.
///
/// [`Arg`]: crate::Arg
/// [`Arg::setting`]: crate::Arg::setting()
/// [`Arg::unset_setting`]: crate::Arg::unset_setting()
/// [`Arg::is_set`]: crate::Arg::is_set()
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum ArgSettings {
    /// Specifies that an arg must be used
    Required,
    /// Allows an arg to accept multiple values
    MultipleValues,
    /// Allows an arg to appear multiple times
    MultipleOccurrences,
    /// Deprecated, see [`ArgSettings::MultipleOccurrences`] (most likely what you want) and
    /// [`ArgSettings::MultipleValues`]
    #[deprecated(
        since = "3.0.0",
        note = "Split into `ArgSettings::MultipleOccurrences` (most likely what you want)  and `ArgSettings::MultipleValues`"
    )]
    Multiple,
    /// Forbids an arg from accepting empty values such as `""`
    ForbidEmptyValues,
    /// Sets an arg to be global (i.e. exist in all subcommands)
    Global,
    /// Hides an arg from the help message
    Hidden,
    /// Allows an argument to take a value (such as `--option value`)
    TakesValue,
    /// Enables a delimiter to break up arguments `--option val1,val2,val3` becomes three values
    /// (`val1`, `val2`, and `val3`) instead of the default one (`val1,val2,val3`)
    UseValueDelimiter,
    /// Tells an arg to display it's help on the line below the arg itself in the help message
    NextLineHelp,
    /// Says that arg *must* use a delimiter to separate values
    RequireDelimiter,
    /// Hides the possible values from the help message
    HidePossibleValues,
    /// Allows values that start with a hyphen
    AllowHyphenValues,
    /// Deprecated, replaced with [`ArgSettings::AllowHyphenValues`]
    #[deprecated(
        since = "3.0.0",
        note = "Replaced with `ArgSettings::AllowHyphenValues`"
    )]
    AllowLeadingHyphen,
    /// Requires that an equals be used to provide a value to an option such as `--option=value`
    RequireEquals,
    /// Says that a positional arg will be the last positional, and requires `--` to be accessed.
    /// It can also be accessed early (i.e. before other positionals) by providing `--`
    Last,
    /// Hides the default value from the help message
    HideDefaultValue,
    /// Possible values become case insensitive
    IgnoreCase,
    /// Deprecated, replaced with [`ArgSettings::IgnoreCase`]
    #[deprecated(since = "3.0.0", note = "Replaced with `ArgSettings::IgnoreCase`")]
    CaseInsensitive,
    /// Hides environment variable arguments from the help message
    #[cfg(feature = "env")]
    HideEnv,
    /// Hides any values currently assigned to ENV variables in the help message (good for sensitive
    /// information)
    #[cfg(feature = "env")]
    HideEnvValues,
    /// The argument should **not** be shown in short help text
    HiddenShortHelp,
    /// The argument should **not** be shown in long help text
    HiddenLongHelp,
    /// Specifies that option values that are invalid UTF-8 should *not* be treated as an error.
    AllowInvalidUtf8,
    /// Specifies that option should exist on its own.
    /// Having any other arguments present at runtime is an error.
    Exclusive,
}

bitflags! {
    struct Flags: u32 {
        const REQUIRED         = 1;
        const MULTIPLE_OCC     = 1 << 1;
        const NO_EMPTY_VALS    = 1 << 2;
        const GLOBAL           = 1 << 3;
        const HIDDEN           = 1 << 4;
        const TAKES_VAL        = 1 << 5;
        const USE_DELIM        = 1 << 6;
        const NEXT_LINE_HELP   = 1 << 7;
        const REQ_DELIM        = 1 << 9;
        const DELIM_NOT_SET    = 1 << 10;
        const HIDE_POS_VALS    = 1 << 11;
        const ALLOW_TAC_VALS   = 1 << 12;
        const REQUIRE_EQUALS   = 1 << 13;
        const LAST             = 1 << 14;
        const HIDE_DEFAULT_VAL = 1 << 15;
        const CASE_INSENSITIVE = 1 << 16;
        #[cfg(feature = "env")]
        const HIDE_ENV_VALS    = 1 << 17;
        const HIDDEN_SHORT_H   = 1 << 18;
        const HIDDEN_LONG_H    = 1 << 19;
        const MULTIPLE_VALS    = 1 << 20;
        const MULTIPLE         = Self::MULTIPLE_OCC.bits | Self::MULTIPLE_VALS.bits;
        #[cfg(feature = "env")]
        const HIDE_ENV         = 1 << 21;
        const UTF8_NONE        = 1 << 22;
        const EXCLUSIVE        = 1 << 23;
        const NO_OP            = 0;
    }
}

// @TODO @p6 @internal: Reorder alphabetically
impl_settings! { ArgSettings, ArgFlags,
    Required("required") => Flags::REQUIRED,
    MultipleOccurrences("multipleoccurrences") => Flags::MULTIPLE_OCC,
    MultipleValues("multiplevalues") => Flags::MULTIPLE_VALS,
    Multiple("multiple") => Flags::MULTIPLE,
    ForbidEmptyValues("forbidemptyvalues") => Flags::NO_EMPTY_VALS,
    Global("global") => Flags::GLOBAL,
    Hidden("hidden") => Flags::HIDDEN,
    TakesValue("takesvalue") => Flags::TAKES_VAL,
    UseValueDelimiter("usevaluedelimiter") => Flags::USE_DELIM,
    NextLineHelp("nextlinehelp") => Flags::NEXT_LINE_HELP,
    RequireDelimiter("requiredelimiter") => Flags::REQ_DELIM,
    HidePossibleValues("hidepossiblevalues") => Flags::HIDE_POS_VALS,
    AllowHyphenValues("allowhyphenvalues") => Flags::ALLOW_TAC_VALS,
    AllowLeadingHyphen("allowleadinghypyhen") => Flags::ALLOW_TAC_VALS,
    RequireEquals("requireequals") => Flags::REQUIRE_EQUALS,
    Last("last") => Flags::LAST,
    IgnoreCase("ignorecase") => Flags::CASE_INSENSITIVE,
    CaseInsensitive("caseinsensitive") => Flags::CASE_INSENSITIVE,
    #[cfg(feature = "env")]
    HideEnv("hideenv") => Flags::HIDE_ENV,
    #[cfg(feature = "env")]
    HideEnvValues("hideenvvalues") => Flags::HIDE_ENV_VALS,
    HideDefaultValue("hidedefaultvalue") => Flags::HIDE_DEFAULT_VAL,
    HiddenShortHelp("hiddenshorthelp") => Flags::HIDDEN_SHORT_H,
    HiddenLongHelp("hiddenlonghelp") => Flags::HIDDEN_LONG_H,
    AllowInvalidUtf8("allowinvalidutf8") => Flags::UTF8_NONE,
    Exclusive("exclusive") => Flags::EXCLUSIVE
}

#[cfg(test)]
mod test {
    use super::ArgSettings;

    #[test]
    fn arg_settings_fromstr() {
        assert_eq!(
            "allowhyphenvalues".parse::<ArgSettings>().unwrap(),
            ArgSettings::AllowHyphenValues
        );
        assert_eq!(
            "forbidemptyvalues".parse::<ArgSettings>().unwrap(),
            ArgSettings::ForbidEmptyValues
        );
        assert_eq!(
            "hidepossiblevalues".parse::<ArgSettings>().unwrap(),
            ArgSettings::HidePossibleValues
        );
        assert_eq!(
            "hidden".parse::<ArgSettings>().unwrap(),
            ArgSettings::Hidden
        );
        assert_eq!(
            "nextlinehelp".parse::<ArgSettings>().unwrap(),
            ArgSettings::NextLineHelp
        );
        assert_eq!(
            "requiredelimiter".parse::<ArgSettings>().unwrap(),
            ArgSettings::RequireDelimiter
        );
        assert_eq!(
            "required".parse::<ArgSettings>().unwrap(),
            ArgSettings::Required
        );
        assert_eq!(
            "takesvalue".parse::<ArgSettings>().unwrap(),
            ArgSettings::TakesValue
        );
        assert_eq!(
            "usevaluedelimiter".parse::<ArgSettings>().unwrap(),
            ArgSettings::UseValueDelimiter
        );
        assert_eq!(
            "requireequals".parse::<ArgSettings>().unwrap(),
            ArgSettings::RequireEquals
        );
        assert_eq!("last".parse::<ArgSettings>().unwrap(), ArgSettings::Last);
        assert_eq!(
            "hidedefaultvalue".parse::<ArgSettings>().unwrap(),
            ArgSettings::HideDefaultValue
        );
        assert_eq!(
            "ignorecase".parse::<ArgSettings>().unwrap(),
            ArgSettings::IgnoreCase
        );
        #[cfg(feature = "env")]
        assert_eq!(
            "hideenv".parse::<ArgSettings>().unwrap(),
            ArgSettings::HideEnv
        );
        #[cfg(feature = "env")]
        assert_eq!(
            "hideenvvalues".parse::<ArgSettings>().unwrap(),
            ArgSettings::HideEnvValues
        );
        assert_eq!(
            "hiddenshorthelp".parse::<ArgSettings>().unwrap(),
            ArgSettings::HiddenShortHelp
        );
        assert_eq!(
            "hiddenlonghelp".parse::<ArgSettings>().unwrap(),
            ArgSettings::HiddenLongHelp
        );
        assert_eq!(
            "allowinvalidutf8".parse::<ArgSettings>().unwrap(),
            ArgSettings::AllowInvalidUtf8
        );
        assert_eq!(
            "exclusive".parse::<ArgSettings>().unwrap(),
            ArgSettings::Exclusive
        );
        assert!("hahahaha".parse::<ArgSettings>().is_err());
    }
}
<|endoftext|>


<commit_before>//! A antialiasing oscillator.
//!
//! ## Waveforms
//!
//! The oscillator supports several classical waveforms. The square, triangle,
//! and saw waves support both aliased and antialiased variants.
//!
//! The aliased variants produce pure signals; for example, a square wave only
//! emits two values: `-1.0` and `+1.0`. This is useful when a control signal is
//! wanted, but produces aliasing in the frequency domain.
//!
//! The antialiased variants use PolyBLEP (polynomial bandlimited step) to
//! mitigate the aliasing in the pure signals. This results in a much cleaner
//! audible signal, and is more desirable for most musical purposes.
//!
//! ## Pitch Bend
//!
//! The oscillator supports pitch bending as an additional modifier of the base
//! frequency. This makes it easier to bend a single note when working with
//! MIDI, rather than manually tracking the base frequency and computing a new
//! frequency yourself.
//!
//! ## Low Frequency Oscillator
//!
//! The oscillator supports a low frequency oscillator (LFO) as optional input.
//! If provided, then the LFO is used to modulate the frequency of the
//! oscillator, producing a vibrato.
//!
//! ## Example
//!
//! The oscillator uses a builder pattern for initialization. The following will
//! set up an antialiased saw wave at 440 Hz, with a 0.1 step vibrato:
//!
//! ```
//! use oxcable::oscillator::*;
//! let osc = Oscillator::new(Saw(PolyBlep)).freq(440.0).lfo_intensity(0.1);
//! ```

use std::f32::consts::PI;
use num::traits::Float;
use rand::random;

use types::{SAMPLE_RATE, AudioDevice, MessageReceiver, Sample, Time};

/// Defines the messages that the Oscillator supports.
#[derive(Clone, Copy, Debug)]
pub enum Message {
    /// Sets the frequency in Hz.
    SetFreq(f32),
    /// Sets the waveform type.
    SetWaveform(Waveform),
    /// Sets the LFO vibrato depth, in steps.
    SetLFOIntensity(f32),
    /// Sets the pitch transposition, in steps.
    SetTranspose(f32),
    /// Sets the pitch bend, in steps.
    SetBend(f32),
}
pub use self::Message::*;

/// Antialiasing method for certain waveforms.
#[derive(Clone, Copy, Debug)]
pub enum AntialiasType {
    /// Naive, aliasing waveforms.
    Aliased,
    /// Antialiasing using PolyBLEP.
    PolyBlep
}
pub use self::AntialiasType::*;

/// Oscillator waveforms.
#[derive(Clone, Copy, Debug)]
pub enum Waveform {
    /// A sine wave.
    Sine,
    /// A saw wave.
    Saw(AntialiasType),
    /// A square wave.
    Square(AntialiasType),
    /// A triangle wave.
    Tri(AntialiasType),
    /// Pure white noise.
    WhiteNoise,
    /// A series of impulses.
    PulseTrain
}
pub use self::Waveform::*;

/// An oscillator that generates a periodic waveform.
pub struct Oscillator {
    waveform: Waveform,
    lfo_intensity: f32,
    transpose: f32,
    bend: f32,
    phase: f32,
    phase_delta: f32,
    last_sample: Sample,
}

impl Oscillator {
    /// Returns an oscillator with the specified waveform.
    pub fn new(waveform: Waveform) -> Self {
        Oscillator {
            waveform: waveform,
            lfo_intensity: 0.0,
            transpose: 1.0,
            bend: 1.0,
            phase: 0.0,
            phase_delta: 0.0,
            last_sample: 0.0
        }
    }

    /// Sets the frequency of the waveform, and return the same oscillator.
    pub fn freq(mut self, freq: f32) -> Self {
        self.handle_message(SetFreq(freq));
        self
    }

    /// Sets the frequency transposition (in steps), and return the same
    /// oscillator.
    pub fn transpose(mut self, steps: f32) -> Self {
        self.handle_message(SetTranspose(steps));
        self
    }

    /// Sets the intensity of the LFO vibrato, and return the same oscillator.
    ///
    /// The intensity is provided in half steps (1/2ths of an octave).
    pub fn lfo_intensity(mut self, lfo_intensity: f32) -> Self {
        self.handle_message(SetLFOIntensity(lfo_intensity));
        self
    }
}

impl MessageReceiver for Oscillator {
    type Msg = Message;
    fn handle_message(&mut self, msg: Message) {
        match msg {
            SetFreq(freq) => {
                self.phase_delta = freq*2.0*PI/(SAMPLE_RATE as f32);
            },
            SetWaveform(waveform) => {
                self.waveform = waveform;
            },
            SetLFOIntensity(steps) => {
                self.lfo_intensity = steps/12.0;
            },
            SetTranspose(steps) => {
                self.transpose = 2.0.powf(steps/12.0);
            },
            SetBend(steps) => {
                self.bend = 2.0.powf(steps/12.0);
            },
        }
    }
}

impl AudioDevice for Oscillator {
    fn num_inputs(&self) -> usize {
        1
    }

    fn num_outputs(&self) -> usize {
        1
    }

    fn tick(&mut self, _: Time, inputs: &[Sample], outputs: &mut[Sample]) {
        // Tick the phase
        let phase_delta = if inputs.len() > 0 {
            self.phase_delta*2.0.powf(inputs[0]*self.lfo_intensity)
        } else {
            self.phase_delta
        } * self.bend * self.transpose;
        self.phase += phase_delta;
        if self.phase >= 2.0*PI {
            self.phase -= 2.0*PI;
        }

        // Compute the next sample
        let s: Sample = match self.waveform.clone() {
            Sine => self.phase.sin(),
            Saw(aa) => {
                let mut out = self.phase/PI -1.0;
                match aa {
                    PolyBlep => {
                        out -= poly_belp_offset(self.phase/(2.0*PI),
                                                phase_delta/(2.0*PI));
                    },
                    _ => ()
                }
                out
            },
            Square(aa) => {
                let mut out = if self.phase < PI { 1.0 } else { -1.0 };
                match aa {
                    PolyBlep => {
                        // two discontinuities, at rising and falling edges
                        out += poly_belp_offset(self.phase/(2.0*PI),
                                                phase_delta/(2.0*PI));
                        out -= poly_belp_offset(fmod(self.phase/(2.0*PI)+0.5, 1.0),
                                                phase_delta/(2.0*PI));
                    },
                    _ => ()
                }
                out
            },
            Tri(aa) => {
                // Compute a square wave signal
                let mut out = if self.phase < PI { 1.0 } else { -1.0 };
                match aa {
                    PolyBlep => {
                        // two discontinuities, at rising and falling edges
                        out += poly_belp_offset(self.phase/(2.0*PI),
                                                phase_delta/(2.0*PI));
                        out -= poly_belp_offset(fmod(self.phase/(2.0*PI)+0.5, 1.0),
                                                phase_delta/(2.0*PI));
                    },
                    _ => ()
                }

                // Perform leaky integration
                phase_delta*out + (1.0-phase_delta)*self.last_sample
            },
            WhiteNoise => 2.0*random::<f32>() - 1.0,
            PulseTrain => {
                // If we wrapped around...
                if self.phase < self.phase_delta {
                    1.0
                } else {
                    0.0
                }
            }
        };

        // Push the sample out
        self.last_sample = s;
        outputs[0] = s;
    }
}

/// Floating point modulus
fn fmod(n: f32, base: f32) -> f32 {
    assert!(base > 0.0);
    let mut out = n;
    while out < 0.0 {
        out += base;
    }
    while out >= base {
        out -= base;
    }
    out
}

/// Computes an offset for PolyBLEP antialiasing
///
/// `t` should be the current waveform phase, normalized
/// `dt` should be the change in phase for one sample time, normalized
fn poly_belp_offset(t: f32, dt: f32) -> f32 {
    if t < dt { // t ~= 0
        let t = t / dt;
        -t*t + 2.0*t - 1.0
    } else if t > 1.0-dt { // t ~= 1
        let t = (t-1.0) / dt;
        t*t + 2.0*t + 1.0
    } else {
        0.0
    }
}

// A couple of basic unit tests...
#[cfg(test)]
mod test {
    use testing::flt_eq;

    /// Tests fmod with many values
    #[test]
    fn test_fmod() {
        use super::fmod;

        // negatives...
        assert!(flt_eq(fmod(-1.5, 1.0), 0.5));
        assert!(flt_eq(fmod(-1.0, 1.0), 0.0));
        assert!(flt_eq(fmod(-0.5, 1.0), 0.5));

        // in range...
        assert!(flt_eq(fmod(0.0, 1.0), 0.0));
        assert!(flt_eq(fmod(0.5, 1.0), 0.5));
        assert!(flt_eq(fmod(0.9, 1.0), 0.9));

        // above...
        assert!(flt_eq(fmod(1.0, 1.0), 0.0));
        assert!(flt_eq(fmod(1.5, 1.0), 0.5));
        assert!(flt_eq(fmod(2.0, 1.0), 0.0));
        assert!(flt_eq(fmod(2.5, 1.0), 0.5));

        // different base...
        assert!(flt_eq(fmod(-0.5, 0.9), 0.4));
        assert!(flt_eq(fmod(0.0, 0.9), 0.0));
        assert!(flt_eq(fmod(0.5, 0.9), 0.5));
        assert!(flt_eq(fmod(0.9, 0.9), 0.0));
        assert!(flt_eq(fmod(1.0, 0.9), 0.1));
    }

    /// Tests square wave
    #[test]
    fn test_naive_square() {
        use super::{AntialiasType, Waveform, Oscillator};
        use types::AudioDevice;
        let mut osc = Oscillator::new(Waveform::Square(AntialiasType::Aliased))
            .freq(4410.0);
        let input = vec![];
        let mut output = vec![0.0];

        osc.tick(0, &input, &mut output); assert!(output[0] == 1.0);
        osc.tick(1, &input, &mut output); assert!(output[0] == 1.0);
        osc.tick(2, &input, &mut output); assert!(output[0] == 1.0);
        osc.tick(3, &input, &mut output); assert!(output[0] == 1.0);
        osc.tick(4, &input, &mut output); assert!(output[0] == -1.0);
        osc.tick(5, &input, &mut output); assert!(output[0] == -1.0);
        osc.tick(6, &input, &mut output); assert!(output[0] == -1.0);
        osc.tick(7, &input, &mut output); assert!(output[0] == -1.0);
        osc.tick(8, &input, &mut output); assert!(output[0] == -1.0);
    }

    /// Tests saw wave
    #[test]
    fn test_naive_saw() {
        use super::{AntialiasType, Waveform, Oscillator};
        use types::AudioDevice;
        let mut osc = Oscillator::new(Waveform::Saw(AntialiasType::Aliased))
            .freq(4410.0);
        let input = vec![];
        let mut output = vec![0.0];

        osc.tick(0, &input, &mut output); assert!(flt_eq(output[0], -0.8));
        osc.tick(1, &input, &mut output); assert!(flt_eq(output[0], -0.6));
        osc.tick(2, &input, &mut output); assert!(flt_eq(output[0], -0.4));
        osc.tick(3, &input, &mut output); assert!(flt_eq(output[0], -0.2));
        osc.tick(4, &input, &mut output); assert!(flt_eq(output[0], 0.0));
        osc.tick(5, &input, &mut output); assert!(flt_eq(output[0], 0.2));
        osc.tick(6, &input, &mut output); assert!(flt_eq(output[0], 0.4));
        osc.tick(7, &input, &mut output); assert!(flt_eq(output[0], 0.6));
        osc.tick(8, &input, &mut output); assert!(flt_eq(output[0], 0.8));
    }
}
<commit_msg>Replace fmod with regular modulo<commit_after>//! A antialiasing oscillator.
//!
//! ## Waveforms
//!
//! The oscillator supports several classical waveforms. The square, triangle,
//! and saw waves support both aliased and antialiased variants.
//!
//! The aliased variants produce pure signals; for example, a square wave only
//! emits two values: `-1.0` and `+1.0`. This is useful when a control signal is
//! wanted, but produces aliasing in the frequency domain.
//!
//! The antialiased variants use PolyBLEP (polynomial bandlimited step) to
//! mitigate the aliasing in the pure signals. This results in a much cleaner
//! audible signal, and is more desirable for most musical purposes.
//!
//! ## Pitch Bend
//!
//! The oscillator supports pitch bending as an additional modifier of the base
//! frequency. This makes it easier to bend a single note when working with
//! MIDI, rather than manually tracking the base frequency and computing a new
//! frequency yourself.
//!
//! ## Low Frequency Oscillator
//!
//! The oscillator supports a low frequency oscillator (LFO) as optional input.
//! If provided, then the LFO is used to modulate the frequency of the
//! oscillator, producing a vibrato.
//!
//! ## Example
//!
//! The oscillator uses a builder pattern for initialization. The following will
//! set up an antialiased saw wave at 440 Hz, with a 0.1 step vibrato:
//!
//! ```
//! use oxcable::oscillator::*;
//! let osc = Oscillator::new(Saw(PolyBlep)).freq(440.0).lfo_intensity(0.1);
//! ```

use std::f32::consts::PI;
use num::traits::Float;
use rand::random;

use types::{SAMPLE_RATE, AudioDevice, MessageReceiver, Sample, Time};

/// Defines the messages that the Oscillator supports.
#[derive(Clone, Copy, Debug)]
pub enum Message {
    /// Sets the frequency in Hz.
    SetFreq(f32),
    /// Sets the waveform type.
    SetWaveform(Waveform),
    /// Sets the LFO vibrato depth, in steps.
    SetLFOIntensity(f32),
    /// Sets the pitch transposition, in steps.
    SetTranspose(f32),
    /// Sets the pitch bend, in steps.
    SetBend(f32),
}
pub use self::Message::*;

/// Antialiasing method for certain waveforms.
#[derive(Clone, Copy, Debug)]
pub enum AntialiasType {
    /// Naive, aliasing waveforms.
    Aliased,
    /// Antialiasing using PolyBLEP.
    PolyBlep
}
pub use self::AntialiasType::*;

/// Oscillator waveforms.
#[derive(Clone, Copy, Debug)]
pub enum Waveform {
    /// A sine wave.
    Sine,
    /// A saw wave.
    Saw(AntialiasType),
    /// A square wave.
    Square(AntialiasType),
    /// A triangle wave.
    Tri(AntialiasType),
    /// Pure white noise.
    WhiteNoise,
    /// A series of impulses.
    PulseTrain
}
pub use self::Waveform::*;

/// An oscillator that generates a periodic waveform.
pub struct Oscillator {
    waveform: Waveform,
    lfo_intensity: f32,
    transpose: f32,
    bend: f32,
    phase: f32,
    phase_delta: f32,
    last_sample: Sample,
}

impl Oscillator {
    /// Returns an oscillator with the specified waveform.
    pub fn new(waveform: Waveform) -> Self {
        Oscillator {
            waveform: waveform,
            lfo_intensity: 0.0,
            transpose: 1.0,
            bend: 1.0,
            phase: 0.0,
            phase_delta: 0.0,
            last_sample: 0.0
        }
    }

    /// Sets the frequency of the waveform, and return the same oscillator.
    pub fn freq(mut self, freq: f32) -> Self {
        self.handle_message(SetFreq(freq));
        self
    }

    /// Sets the frequency transposition (in steps), and return the same
    /// oscillator.
    pub fn transpose(mut self, steps: f32) -> Self {
        self.handle_message(SetTranspose(steps));
        self
    }

    /// Sets the intensity of the LFO vibrato, and return the same oscillator.
    ///
    /// The intensity is provided in half steps (1/2ths of an octave).
    pub fn lfo_intensity(mut self, lfo_intensity: f32) -> Self {
        self.handle_message(SetLFOIntensity(lfo_intensity));
        self
    }
}

impl MessageReceiver for Oscillator {
    type Msg = Message;
    fn handle_message(&mut self, msg: Message) {
        match msg {
            SetFreq(freq) => {
                self.phase_delta = freq*2.0*PI/(SAMPLE_RATE as f32);
            },
            SetWaveform(waveform) => {
                self.waveform = waveform;
            },
            SetLFOIntensity(steps) => {
                self.lfo_intensity = steps/12.0;
            },
            SetTranspose(steps) => {
                self.transpose = 2.0.powf(steps/12.0);
            },
            SetBend(steps) => {
                self.bend = 2.0.powf(steps/12.0);
            },
        }
    }
}

impl AudioDevice for Oscillator {
    fn num_inputs(&self) -> usize {
        1
    }

    fn num_outputs(&self) -> usize {
        1
    }

    fn tick(&mut self, _: Time, inputs: &[Sample], outputs: &mut[Sample]) {
        // Tick the phase
        let phase_delta = if inputs.len() > 0 {
            self.phase_delta*2.0.powf(inputs[0]*self.lfo_intensity)
        } else {
            self.phase_delta
        } * self.bend * self.transpose;
        self.phase += phase_delta;
        if self.phase >= 2.0*PI {
            self.phase -= 2.0*PI;
        }

        // Compute the next sample
        let s: Sample = match self.waveform.clone() {
            Sine => self.phase.sin(),
            Saw(aa) => {
                let mut out = self.phase/PI -1.0;
                match aa {
                    PolyBlep => {
                        out -= poly_belp_offset(self.phase/(2.0*PI),
                                                phase_delta/(2.0*PI));
                    },
                    _ => ()
                }
                out
            },
            Square(aa) => {
                let mut out = if self.phase < PI { 1.0 } else { -1.0 };
                match aa {
                    PolyBlep => {
                        // two discontinuities, at rising and falling edges
                        out += poly_belp_offset(self.phase/(2.0*PI),
                                                phase_delta/(2.0*PI));
                        out -= poly_belp_offset(self.phase/(2.0*PI)+0.5 % 1.0,
                                                phase_delta/(2.0*PI));
                    },
                    _ => ()
                }
                out
            },
            Tri(aa) => {
                // Compute a square wave signal
                let mut out = if self.phase < PI { 1.0 } else { -1.0 };
                match aa {
                    PolyBlep => {
                        // two discontinuities, at rising and falling edges
                        out += poly_belp_offset(self.phase/(2.0*PI),
                                                phase_delta/(2.0*PI));
                        out -= poly_belp_offset(self.phase/(2.0*PI)+0.5 % 1.0,
                                                phase_delta/(2.0*PI));
                    },
                    _ => ()
                }

                // Perform leaky integration
                phase_delta*out + (1.0-phase_delta)*self.last_sample
            },
            WhiteNoise => 2.0*random::<f32>() - 1.0,
            PulseTrain => {
                // If we wrapped around...
                if self.phase < self.phase_delta {
                    1.0
                } else {
                    0.0
                }
            }
        };

        // Push the sample out
        self.last_sample = s;
        outputs[0] = s;
    }
}

/// Computes an offset for PolyBLEP antialiasing
///
/// `t` should be the current waveform phase, normalized
/// `dt` should be the change in phase for one sample time, normalized
fn poly_belp_offset(t: f32, dt: f32) -> f32 {
    if t < dt { // t ~= 0
        let t = t / dt;
        -t*t + 2.0*t - 1.0
    } else if t > 1.0-dt { // t ~= 1
        let t = (t-1.0) / dt;
        t*t + 2.0*t + 1.0
    } else {
        0.0
    }
}

// A couple of basic unit tests...
#[cfg(test)]
mod test {
    use testing::flt_eq;

    /// Tests square wave
    #[test]
    fn test_naive_square() {
        use super::{AntialiasType, Waveform, Oscillator};
        use types::AudioDevice;
        let mut osc = Oscillator::new(Waveform::Square(AntialiasType::Aliased))
            .freq(4410.0);
        let input = vec![];
        let mut output = vec![0.0];

        osc.tick(0, &input, &mut output); assert!(output[0] == 1.0);
        osc.tick(1, &input, &mut output); assert!(output[0] == 1.0);
        osc.tick(2, &input, &mut output); assert!(output[0] == 1.0);
        osc.tick(3, &input, &mut output); assert!(output[0] == 1.0);
        osc.tick(4, &input, &mut output); assert!(output[0] == -1.0);
        osc.tick(5, &input, &mut output); assert!(output[0] == -1.0);
        osc.tick(6, &input, &mut output); assert!(output[0] == -1.0);
        osc.tick(7, &input, &mut output); assert!(output[0] == -1.0);
        osc.tick(8, &input, &mut output); assert!(output[0] == -1.0);
    }

    /// Tests saw wave
    #[test]
    fn test_naive_saw() {
        use super::{AntialiasType, Waveform, Oscillator};
        use types::AudioDevice;
        let mut osc = Oscillator::new(Waveform::Saw(AntialiasType::Aliased))
            .freq(4410.0);
        let input = vec![];
        let mut output = vec![0.0];

        osc.tick(0, &input, &mut output); assert!(flt_eq(output[0], -0.8));
        osc.tick(1, &input, &mut output); assert!(flt_eq(output[0], -0.6));
        osc.tick(2, &input, &mut output); assert!(flt_eq(output[0], -0.4));
        osc.tick(3, &input, &mut output); assert!(flt_eq(output[0], -0.2));
        osc.tick(4, &input, &mut output); assert!(flt_eq(output[0], 0.0));
        osc.tick(5, &input, &mut output); assert!(flt_eq(output[0], 0.2));
        osc.tick(6, &input, &mut output); assert!(flt_eq(output[0], 0.4));
        osc.tick(7, &input, &mut output); assert!(flt_eq(output[0], 0.6));
        osc.tick(8, &input, &mut output); assert!(flt_eq(output[0], 0.8));
    }
}
<|endoftext|>


<commit_before>use dns_parser::Packet as DnsPacket;
use dns_parser::{Opcode, ResponseCode, QueryType, QueryClass, Class, RRData};
use serde_json::{Value, Map, Number, to_value};

#[derive(Serialize)]
pub struct DnsQuestion {
	name: String,
	qtype: String,
	qclass: String,
}

#[derive(Serialize)]
pub struct DnsResourceRecord {
	name: String,
	class: String,
	ttl: Number,
	rdata: String,
}

pub struct DnsHeader {
	id: Number,
	opcode: String,
	flags: Value,
	rcode: String,
	total_questions: Number,
	total_answer_rrs: Number,
	total_authority_rrs: Number,
	total_additional_rrs: Number,
	questions: Value,
	answer_rrs: Value,
	authority_rrs: Value,
	additional_rrs: Value,
}

impl DnsHeader {
	pub fn new(p: &DnsPacket) -> DnsHeader {
		let opcode_number = p.header.opcode;
		let opcode_string = match opcode_number {
			Opcode::StandardQuery => "QUERY",
			Opcode::InverseQuery => "IQUERY",
			Opcode::ServerStatusRequest => "STATUS",
			_ => "UNKNOWN",
		};

		let mut flags: Vec<&str> = Vec::new();
		if p.header.authoritative {
			flags.push("AA");
		}
		if p.header.truncated {
			flags.push("TC");
		}
		if p.header.recursion_desired {
			flags.push("RD");
		}
		if p.header.recursion_available {
			flags.push("RA");
		}
		if p.header.authenticated_data {
			flags.push("AD");
		}
		if p.header.checking_disabled {
			flags.push("CD");
		}

		let rcode_number = p.header.response_code;
		let rcode_string = match rcode_number {
			ResponseCode::NoError => "NOERROR",
			ResponseCode::FormatError => "FORMERR",
			ResponseCode::ServerFailure => "SERVFAIL",
			ResponseCode::NameError => "NXDOMAIN",
			ResponseCode::NotImplemented => "NOTIMPL",
			ResponseCode::Refused => "REFUSED",
			_ => "UNKNOWN",
		};

		let mut questions: Vec<DnsQuestion> = Vec::new();
		if ! p.questions.is_empty() {
			for q in p.questions.iter() {
				let question = DnsQuestion {
					name: q.qname.to_string(),
					qtype: match q.qtype {
						QueryType::A => String::from("A"),
						QueryType::NS => String::from("NS"),
						QueryType::MF => String::from("MF"),
						QueryType::CNAME => String::from("CNAME"),
						QueryType::SOA => String::from("SOA"),
						QueryType::MB => String::from("MB"),
						QueryType::MG => String::from("MG"),
						QueryType::MR => String::from("MR"),
						QueryType::NULL => String::from("NULL"),
						QueryType::WKS => String::from("WKS"),
						QueryType::PTR => String::from("PTR"),
						QueryType::HINFO => String::from("HINFO"),
						QueryType::MINFO => String::from("MINFO"),
						QueryType::MX => String::from("MX"),
						QueryType::TXT => String::from("TXT"),
						QueryType::AAAA => String::from("AAAA"),
						QueryType::SRV => String::from("SRV"),
						QueryType::AXFR => String::from("AXFR"),
						QueryType::MAILB => String::from("MAILB"),
						QueryType::MAILA => String::from("MAILA"),
						QueryType::All => String::from("ALL"),
					},
					qclass: match q.qclass {
						QueryClass::IN => String::from("IN"),
						QueryClass::CS => String::from("CS"),
						QueryClass::CH => String::from("CH"),
						QueryClass::HS => String::from("HS"),
						QueryClass::Any => String::from("ANY"),
					},
				};
				questions.push(question);
			}
		}

		let mut answers: Vec<DnsResourceRecord> = Vec::new();
		if ! p.answers.is_empty() {
			for a in p.answers.iter() {
				let answer = DnsResourceRecord {
					name: a.name.to_string(),
					class: match a.cls {
						Class::IN => String::from("IN"),
						Class::CS => String::from("CS"),
						Class::CH => String::from("CH"),
						Class::HS => String::from("HS"),
					},
					ttl: Number::from(a.ttl),
					rdata: match a.data {
						RRData::CNAME(cname) => cname.to_string(),
						RRData::NS(ns) => ns.to_string(),
						RRData::PTR(ptr) => ptr.to_string(),
						RRData::TXT(ref txt) => txt.clone(),
						_ => String::from("Unknown"),
					},
				};
				answers.push(answer);
			}
		}

		let mut nameservers: Vec<DnsResourceRecord> = Vec::new();
		if ! p.nameservers.is_empty() {
			for a in p.nameservers.iter() {
				let nameserver = DnsResourceRecord {
					name: a.name.to_string(),
					class: match a.cls {
						Class::IN => String::from("IN"),
						Class::CS => String::from("CS"),
						Class::CH => String::from("CH"),
						Class::HS => String::from("HS"),
					},
					ttl: Number::from(a.ttl),
					rdata: match a.data {
						RRData::CNAME(cname) => cname.to_string(),
						RRData::NS(ns) => ns.to_string(),
						RRData::PTR(ptr) => ptr.to_string(),
						RRData::TXT(ref txt) => txt.clone(),
						_ => String::from("Unknown"),
					},
				};
				nameservers.push(nameserver);
			}
		}

		let mut additionals: Vec<DnsResourceRecord> = Vec::new();
		if ! p.additional.is_empty() {
			for a in p.additional.iter() {
				let additional = DnsResourceRecord {
					name: a.name.to_string(),
					class: match a.cls {
						Class::IN => String::from("IN"),
						Class::CS => String::from("CS"),
						Class::CH => String::from("CH"),
						Class::HS => String::from("HS"),
					},
					ttl: Number::from(a.ttl),
					rdata: match a.data {
						RRData::CNAME(cname) => cname.to_string(),
						RRData::NS(ns) => ns.to_string(),
						RRData::PTR(ptr) => ptr.to_string(),
						RRData::TXT(ref txt) => txt.clone(),
						_ => String::from("Unknown"),
					},
				};
				additionals.push(additional);
			}
		}

		DnsHeader {
			id: Number::from(p.header.id),
			opcode: opcode_string.to_string(),
			flags: Value::from(flags),
			rcode: rcode_string.to_string(),
			total_questions: Number::from(p.header.questions),
			total_answer_rrs: Number::from(p.header.answers),
			total_authority_rrs: Number::from(p.header.nameservers),
			total_additional_rrs: Number::from(p.header.additional),
			questions: to_value(questions).unwrap(),
			answer_rrs: to_value(answers).unwrap(),
			authority_rrs: to_value(nameservers).unwrap(),
			additional_rrs: to_value(additionals).unwrap(),
		}
	}

	pub fn to_json_map(&self) -> Map<String, Value> {
		let mut header = Map::new();

		header.insert("id".to_string(), Value::Number(self.id.clone()));
		header.insert("opcode".to_string(), Value::String(self.opcode.clone()));
		header.insert("flags".to_string(), self.flags.clone());
		header.insert("rcode".to_string(), Value::String(self.rcode.clone()));
		header.insert("total_questions".to_string(), Value::Number(self.total_questions.clone()));
		header.insert("total_answer_rrs".to_string(), Value::Number(self.total_answer_rrs.clone()));
		header.insert("total_authority_rrs".to_string(), Value::Number(self.total_authority_rrs.clone()));
		header.insert("total_additional_rrs".to_string(), Value::Number(self.total_additional_rrs.clone()));
		header.insert("questions".to_string(), self.questions.clone());
		header.insert("answer_rrs".to_string(), self.answer_rrs.clone());
		header.insert("authority_rrs".to_string(), self.authority_rrs.clone());
		header.insert("additional_rrs".to_string(), self.additional_rrs.clone());

		header
	}
}<commit_msg>Remove code duplication<commit_after>use dns_parser::Packet as DnsPacket;
use dns_parser::{Opcode, ResponseCode, QueryType, QueryClass, Class, RRData, ResourceRecord};
use serde_json::{Value, Map, Number, to_value};

#[derive(Serialize)]
pub struct DnsQuestion {
	name: String,
	qtype: String,
	qclass: String,
}

#[derive(Serialize)]
pub struct DnsResourceRecord {
	name: String,
	class: String,
	ttl: Number,
	rdata: String,
}

pub struct DnsHeader {
	id: Number,
	opcode: String,
	flags: Value,
	rcode: String,
	total_questions: Number,
	total_answer_rrs: Number,
	total_authority_rrs: Number,
	total_additional_rrs: Number,
	questions: Value,
	answer_rrs: Value,
	authority_rrs: Value,
	additional_rrs: Value,
}

impl DnsHeader {
	pub fn new(p: &DnsPacket) -> DnsHeader {
		let opcode_number = p.header.opcode;
		let opcode_string = match opcode_number {
			Opcode::StandardQuery => "QUERY",
			Opcode::InverseQuery => "IQUERY",
			Opcode::ServerStatusRequest => "STATUS",
			_ => "UNKNOWN",
		};

		let mut flags: Vec<&str> = Vec::new();
		if p.header.authoritative {
			flags.push("AA");
		}
		if p.header.truncated {
			flags.push("TC");
		}
		if p.header.recursion_desired {
			flags.push("RD");
		}
		if p.header.recursion_available {
			flags.push("RA");
		}
		if p.header.authenticated_data {
			flags.push("AD");
		}
		if p.header.checking_disabled {
			flags.push("CD");
		}

		let rcode_number = p.header.response_code;
		let rcode_string = match rcode_number {
			ResponseCode::NoError => "NOERROR",
			ResponseCode::FormatError => "FORMERR",
			ResponseCode::ServerFailure => "SERVFAIL",
			ResponseCode::NameError => "NXDOMAIN",
			ResponseCode::NotImplemented => "NOTIMPL",
			ResponseCode::Refused => "REFUSED",
			_ => "UNKNOWN",
		};

		let mut questions: Vec<DnsQuestion> = Vec::new();
		if ! p.questions.is_empty() {
			for q in p.questions.iter() {
				let question = DnsQuestion {
					name: q.qname.to_string(),
					qtype: match q.qtype {
						QueryType::A => String::from("A"),
						QueryType::NS => String::from("NS"),
						QueryType::MF => String::from("MF"),
						QueryType::CNAME => String::from("CNAME"),
						QueryType::SOA => String::from("SOA"),
						QueryType::MB => String::from("MB"),
						QueryType::MG => String::from("MG"),
						QueryType::MR => String::from("MR"),
						QueryType::NULL => String::from("NULL"),
						QueryType::WKS => String::from("WKS"),
						QueryType::PTR => String::from("PTR"),
						QueryType::HINFO => String::from("HINFO"),
						QueryType::MINFO => String::from("MINFO"),
						QueryType::MX => String::from("MX"),
						QueryType::TXT => String::from("TXT"),
						QueryType::AAAA => String::from("AAAA"),
						QueryType::SRV => String::from("SRV"),
						QueryType::AXFR => String::from("AXFR"),
						QueryType::MAILB => String::from("MAILB"),
						QueryType::MAILA => String::from("MAILA"),
						QueryType::All => String::from("ALL"),
					},
					qclass: match q.qclass {
						QueryClass::IN => String::from("IN"),
						QueryClass::CS => String::from("CS"),
						QueryClass::CH => String::from("CH"),
						QueryClass::HS => String::from("HS"),
						QueryClass::Any => String::from("ANY"),
					},
				};
				questions.push(question);
			}
		}

		let answers = DnsHeader::parse_rr(&p.answers);

		let nameservers = DnsHeader::parse_rr(&p.nameservers);

		let additionals = DnsHeader::parse_rr(&p.additional);

		DnsHeader {
			id: Number::from(p.header.id),
			opcode: opcode_string.to_string(),
			flags: Value::from(flags),
			rcode: rcode_string.to_string(),
			total_questions: Number::from(p.header.questions),
			total_answer_rrs: Number::from(p.header.answers),
			total_authority_rrs: Number::from(p.header.nameservers),
			total_additional_rrs: Number::from(p.header.additional),
			questions: to_value(questions).unwrap(),
			answer_rrs: to_value(answers).unwrap(),
			authority_rrs: to_value(nameservers).unwrap(),
			additional_rrs: to_value(additionals).unwrap(),
		}
	}

	pub fn to_json_map(&self) -> Map<String, Value> {
		let mut header = Map::new();

		header.insert("id".to_string(), Value::Number(self.id.clone()));
		header.insert("opcode".to_string(), Value::String(self.opcode.clone()));
		header.insert("flags".to_string(), self.flags.clone());
		header.insert("rcode".to_string(), Value::String(self.rcode.clone()));
		header.insert("total_questions".to_string(), Value::Number(self.total_questions.clone()));
		header.insert("total_answer_rrs".to_string(), Value::Number(self.total_answer_rrs.clone()));
		header.insert("total_authority_rrs".to_string(), Value::Number(self.total_authority_rrs.clone()));
		header.insert("total_additional_rrs".to_string(), Value::Number(self.total_additional_rrs.clone()));
		header.insert("questions".to_string(), self.questions.clone());
		header.insert("answer_rrs".to_string(), self.answer_rrs.clone());
		header.insert("authority_rrs".to_string(), self.authority_rrs.clone());
		header.insert("additional_rrs".to_string(), self.additional_rrs.clone());

		header
	}

	fn parse_rr(rrs: &Vec<ResourceRecord>) -> Vec<DnsResourceRecord> {
		let mut parsed: Vec<DnsResourceRecord> = Vec::new();
		if ! rrs.is_empty() {
			for rr in rrs.iter() {
				let dns_rr = DnsResourceRecord {
					name: rr.name.to_string(),
					class: match rr.cls {
						Class::IN => String::from("IN"),
						Class::CS => String::from("CS"),
						Class::CH => String::from("CH"),
						Class::HS => String::from("HS"),
					},
					ttl: Number::from(rr.ttl),
					rdata: match rr.data {
						RRData::CNAME(cname) => cname.to_string(),
						RRData::NS(ns) => ns.to_string(),
						RRData::PTR(ptr) => ptr.to_string(),
						RRData::TXT(ref txt) => txt.clone(),
						_ => String::from("Unknown"),
					},
				};
				parsed.push(dns_rr);
			}
		}
		parsed
	}
}<|endoftext|>


<commit_before>//! Handles parsing GPX format.

// Just a shared macro for testing 'consume'.
#[cfg(test)]
#[macro_export]
macro_rules! consume {
    ($xml: expr, $version: expr) => {{
        let reader = BufReader::new($xml.as_bytes());
        let events = EventReader::new(reader).into_iter().peekable();
        let mut context = Context::new(events, $version);
        consume(&mut context)
    }};
}

pub mod bounds;
pub mod email;
pub mod extensions;
pub mod fix;
pub mod gpx;
pub mod link;
pub mod metadata;
pub mod person;
pub mod string;
pub mod time;
pub mod track;
pub mod tracksegment;
pub mod waypoint;

use std::io::Read;
use std::iter::Peekable;
use xml::reader::Events;
use types::GpxVersion;

pub struct Context<R: Read> {
    reader: Peekable<Events<R>>,
    version: GpxVersion,
}

impl<R: Read> Context<R> {
    pub fn new(reader: Peekable<Events<R>>, version: GpxVersion) -> Context<R> {
        Context { reader, version }
    }

    pub fn reader(&mut self) -> &mut Peekable<Events<R>> {
        &mut self.reader
    }
}
<commit_msg>Add helper function verify_starting_tag<commit_after>//! Handles parsing GPX format.

// Just a shared macro for testing 'consume'.
#[cfg(test)]
#[macro_export]
macro_rules! consume {
    ($xml: expr, $version: expr) => {{
        let reader = BufReader::new($xml.as_bytes());
        let events = EventReader::new(reader).into_iter().peekable();
        let mut context = Context::new(events, $version);
        consume(&mut context)
    }};
}

pub mod bounds;
pub mod email;
pub mod extensions;
pub mod fix;
pub mod gpx;
pub mod link;
pub mod metadata;
pub mod person;
pub mod string;
pub mod time;
pub mod track;
pub mod tracksegment;
pub mod waypoint;

use errors::*;
use std::io::Read;
use std::iter::Peekable;
use xml::reader::Events;
use xml::reader::XmlEvent;
use xml::attribute::OwnedAttribute;
use types::GpxVersion;

pub struct Context<R: Read> {
    reader: Peekable<Events<R>>,
    version: GpxVersion,
}

impl<R: Read> Context<R> {
    pub fn new(reader: Peekable<Events<R>>, version: GpxVersion) -> Context<R> {
        Context { reader, version }
    }

    pub fn reader(&mut self) -> &mut Peekable<Events<R>> {
        &mut self.reader
    }
}

pub fn verify_starting_tag<R: Read>(
    context: &mut Context<R>,
    local_name: &'static str,
) -> Result<(Vec<OwnedAttribute>)> {
    //makes sure the specified starting tag is the next tag on the stream
    //we ignore and skip all xmlevents except StartElement, Characters and EndElement
    loop {
        let next = context.reader.next();
        println!("{:?}", next);
        match next {
            Some(Ok(XmlEvent::StartElement {
                name, attributes, ..
            })) => {
                ensure!(
                    name.local_name == local_name,
                    ErrorKind::InvalidChildElement(name.local_name, local_name)
                );
                return Ok(attributes);
            }
            Some(Ok(XmlEvent::EndElement { name, .. })) => {
                bail!(ErrorKind::InvalidChildElement(name.local_name, local_name));
            }
            Some(Ok(XmlEvent::Characters(chars))) => {
                bail!(ErrorKind::InvalidChildElement(chars, local_name));
            }
            Some(_) => {} //ignore other elements
            None => bail!("did not find expected opening tag for {}", local_name),
        }
    }
}
<|endoftext|>


<commit_before>#![allow(
    clippy::no_effect_underscore_binding,
    clippy::too_many_lines,
    clippy::used_underscore_binding
)]

mod gen;

use proc_macro2::{Ident, Literal, TokenStream};
use ref_cast::RefCast;
use std::fmt::{self, Debug};
use std::ops::Deref;
use syn::punctuated::Punctuated;

#[derive(RefCast)]
#[repr(transparent)]
pub struct Lite<T: ?Sized> {
    value: T,
}

#[allow(non_snake_case)]
pub fn Lite<T: ?Sized>(value: &T) -> &Lite<T> {
    Lite::ref_cast(value)
}

impl<T: ?Sized> Deref for Lite<T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.value
    }
}

impl Debug for Lite<bool> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{}", self.value)
    }
}

impl Debug for Lite<u32> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{}", self.value)
    }
}

impl Debug for Lite<usize> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{}", self.value)
    }
}

impl Debug for Lite<String> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{:?}", self.value)
    }
}

impl Debug for Lite<Ident> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{:?}", self.value.to_string())
    }
}

impl Debug for Lite<Literal> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{}", self.value)
    }
}

impl Debug for Lite<TokenStream> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        let string = self.value.to_string();
        if string.len() <= 80 {
            write!(formatter, "TokenStream(`{}`)", self.value)
        } else {
            formatter
                .debug_tuple("TokenStream")
                .field(&format_args!("`{}`", string))
                .finish()
        }
    }
}

impl<'a, T> Debug for Lite<&'a T>
where
    Lite<T>: Debug,
{
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(Lite(&*self.value), formatter)
    }
}

impl<T> Debug for Lite<Box<T>>
where
    Lite<T>: Debug,
{
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(Lite(&*self.value), formatter)
    }
}

impl<T> Debug for Lite<Vec<T>>
where
    Lite<T>: Debug,
{
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter
            .debug_list()
            .entries(self.value.iter().map(Lite))
            .finish()
    }
}

impl<T, P> Debug for Lite<Punctuated<T, P>>
where
    Lite<T>: Debug,
{
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter
            .debug_list()
            .entries(self.value.iter().map(Lite))
            .finish()
    }
}
<commit_msg>Exclude test suite's generated code from rustfmt<commit_after>#![allow(
    clippy::no_effect_underscore_binding,
    clippy::too_many_lines,
    clippy::used_underscore_binding
)]

#[rustfmt::skip]
mod gen;

use proc_macro2::{Ident, Literal, TokenStream};
use ref_cast::RefCast;
use std::fmt::{self, Debug};
use std::ops::Deref;
use syn::punctuated::Punctuated;

#[derive(RefCast)]
#[repr(transparent)]
pub struct Lite<T: ?Sized> {
    value: T,
}

#[allow(non_snake_case)]
pub fn Lite<T: ?Sized>(value: &T) -> &Lite<T> {
    Lite::ref_cast(value)
}

impl<T: ?Sized> Deref for Lite<T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.value
    }
}

impl Debug for Lite<bool> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{}", self.value)
    }
}

impl Debug for Lite<u32> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{}", self.value)
    }
}

impl Debug for Lite<usize> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{}", self.value)
    }
}

impl Debug for Lite<String> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{:?}", self.value)
    }
}

impl Debug for Lite<Ident> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{:?}", self.value.to_string())
    }
}

impl Debug for Lite<Literal> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        write!(formatter, "{}", self.value)
    }
}

impl Debug for Lite<TokenStream> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        let string = self.value.to_string();
        if string.len() <= 80 {
            write!(formatter, "TokenStream(`{}`)", self.value)
        } else {
            formatter
                .debug_tuple("TokenStream")
                .field(&format_args!("`{}`", string))
                .finish()
        }
    }
}

impl<'a, T> Debug for Lite<&'a T>
where
    Lite<T>: Debug,
{
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(Lite(&*self.value), formatter)
    }
}

impl<T> Debug for Lite<Box<T>>
where
    Lite<T>: Debug,
{
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        Debug::fmt(Lite(&*self.value), formatter)
    }
}

impl<T> Debug for Lite<Vec<T>>
where
    Lite<T>: Debug,
{
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter
            .debug_list()
            .entries(self.value.iter().map(Lite))
            .finish()
    }
}

impl<T, P> Debug for Lite<Punctuated<T, P>>
where
    Lite<T>: Debug,
{
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter
            .debug_list()
            .entries(self.value.iter().map(Lite))
            .finish()
    }
}
<|endoftext|>


<commit_before>use iron::{Request, Response, Middleware, Alloy};
use iron::middleware::{Status, Continue};
use std::sync::{Arc, Mutex};

pub struct Persistent<Data, Phantom> {
    pub data: Arc<Mutex<Data>>
}

impl<D: Send, P> Clone for Persistent<D, P> {
    fn clone(&self) -> Persistent<D, P> {
        Persistent {
            data: self.data.clone()
        }
    }
}

impl<D: Send, P> Middleware for Persistent<D, P> {
    fn enter(&mut self, _: &mut Request,
             _: &mut Response, alloy: &mut Alloy) -> Status {
        alloy.insert::<Persistent<D, P>>(self.clone());
        Continue
    }
}

<commit_msg>(feat) Refactored to use RWLock instead of Mutex.<commit_after>use iron::{Request, Response, Middleware, Alloy};
use iron::middleware::{Status, Continue};
use std::sync::{Arc, RWLock};

pub struct Persistent<Data, Phantom> {
    pub data: Arc<RWLock<Data>>
}

impl<D: Send + Share, P> Clone for Persistent<D, P> {
    fn clone(&self) -> Persistent<D, P> {
        Persistent {
            data: self.data.clone()
        }
    }
}

impl<D: Send + Share, P> Middleware for Persistent<D, P> {
    fn enter(&mut self, _: &mut Request,
             _: &mut Response, alloy: &mut Alloy) -> Status {
        alloy.insert::<Persistent<D, P>>(self.clone());
        Continue
    }
}

impl<D: Send + Share, P> Persistent<D, P> {
    pub fn new(data: D) -> Persistent<D, P> {
        Persistent { data: Arc::new(RWLock::new(data)) }
    }
}

<|endoftext|>


<commit_before>extern crate transitfeed;

use transitfeed::{GTFSIterator, Agency, Stop, Route, Trip, StopTime, Calendar, CalendarDate, FareAttribute, FareRule, Shape, Frequency, Transfer, FeedInfo};

#[test]
fn test_read_agencies() {
    let iter : GTFSIterator<_, Agency> = GTFSIterator::from_path("./examples/good_feed/agency.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_stops() {
    let iter : GTFSIterator<_, Stop> = GTFSIterator::from_path("./examples/good_feed/stops.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_routes() {
    let iter : GTFSIterator<_, Route> = GTFSIterator::from_path("./examples/good_feed/routes.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_trips() {
    let iter : GTFSIterator<_, Trip> = GTFSIterator::from_path("./examples/good_feed/trips.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_stop_times() {
    let iter : GTFSIterator<_, StopTime> = GTFSIterator::from_path("./examples/good_feed/stop_times.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_calendar() {
    let iter : GTFSIterator<_, Calendar> = GTFSIterator::from_path("./examples/good_feed/calendar.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_calendar_dates() {
    let iter : GTFSIterator<_, CalendarDate> = GTFSIterator::from_path("./examples/good_feed/calendar_dates.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_fare_attributes() {
    let iter : GTFSIterator<_, FareAttribute> = GTFSIterator::from_path("./examples/good_feed/fare_attributes.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_fare_rules() {
    let iter : GTFSIterator<_, FareRule> = GTFSIterator::from_path("./examples/good_feed/fare_rules.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_shapes() {
    let iter : GTFSIterator<_, Shape> = GTFSIterator::from_path("./examples/good_feed/shapes.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_frequencies() {
    let iter : GTFSIterator<_, Frequency> = GTFSIterator::from_path("./examples/good_feed/frequencies.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_transfers() {
    let iter : GTFSIterator<_, Transfer> = GTFSIterator::from_path("./examples/good_feed/transfers.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_feed_info() {
    let iter : GTFSIterator<_, FeedInfo> = GTFSIterator::from_path("./examples/good_feed/feed_info.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}
<commit_msg>Remove feed_info test as its not in the sample data<commit_after>extern crate transitfeed;

use transitfeed::{GTFSIterator, Agency, Stop, Route, Trip, StopTime, Calendar, CalendarDate, FareAttribute, FareRule, Shape, Frequency, Transfer, FeedInfo};

#[test]
fn test_read_agencies() {
    let iter : GTFSIterator<_, Agency> = GTFSIterator::from_path("./examples/good_feed/agency.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_stops() {
    let iter : GTFSIterator<_, Stop> = GTFSIterator::from_path("./examples/good_feed/stops.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_routes() {
    let iter : GTFSIterator<_, Route> = GTFSIterator::from_path("./examples/good_feed/routes.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_trips() {
    let iter : GTFSIterator<_, Trip> = GTFSIterator::from_path("./examples/good_feed/trips.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_stop_times() {
    let iter : GTFSIterator<_, StopTime> = GTFSIterator::from_path("./examples/good_feed/stop_times.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_calendar() {
    let iter : GTFSIterator<_, Calendar> = GTFSIterator::from_path("./examples/good_feed/calendar.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_calendar_dates() {
    let iter : GTFSIterator<_, CalendarDate> = GTFSIterator::from_path("./examples/good_feed/calendar_dates.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_fare_attributes() {
    let iter : GTFSIterator<_, FareAttribute> = GTFSIterator::from_path("./examples/good_feed/fare_attributes.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_fare_rules() {
    let iter : GTFSIterator<_, FareRule> = GTFSIterator::from_path("./examples/good_feed/fare_rules.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_shapes() {
    let iter : GTFSIterator<_, Shape> = GTFSIterator::from_path("./examples/good_feed/shapes.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_frequencies() {
    let iter : GTFSIterator<_, Frequency> = GTFSIterator::from_path("./examples/good_feed/frequencies.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

#[test]
fn test_read_transfers() {
    let iter : GTFSIterator<_, Transfer> = GTFSIterator::from_path("./examples/good_feed/transfers.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}

/*
#[test]
fn test_read_feed_info() {
    let iter : GTFSIterator<_, FeedInfo> = GTFSIterator::from_path("./examples/good_feed/feed_info.txt").unwrap();
    for result in iter {
        assert!(result.is_ok(), format!("{}", result.err().unwrap()));
    }
}
*/
<|endoftext|>