<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

const NUMBER: [&'static str; 20] = [
    "zero",
    "one",
    "two",
    "three",
    "four",
    "five",
    "six",
    "seven",
    "eight",
    "nine",
    "ten",
    "eleven",
    "twelve",
    "thirteen",
    "fourteen",
    "fifteen",
    "sixteen",
    "seventeen",
    "eighteen",
    "nineteen",
];

const TENS: [&'static str; 10] = [
    "",
    "",
    "twenty",
    "thirty",
    "forty",
    "fifty",
    "sixty",
    "seventy",
    "eighty",
    "ninety",
];

const MULTIPLIER: [&'static str; 9] = [
    "",
    "thousand",
    "million",
    "billion",
    "trillion",
    "quadrillion",
    "quintillion",
    "sextillion",
    "septillion",
];

/// The `Numeral` trait provides the written form of a number.
pub trait Numeral {
    /// Yields the ordinal form of a number.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use numeral::Numeral;
    /// let written_form = 127.ordinal();
    /// assert_eq!(written_form, "one hundred twenty-seven");
    /// ```
    fn ordinal(&self) -> String;
}

macro_rules! impl_numeral_signed {
    ($($numtype: ty),*) => ($(
        impl Numeral for $numtype {
            fn ordinal(&self) -> String {
                ordinal_int(i64::from(*self).abs() as u64, *self < 0).concat()
            }
        }
    )*)
}

impl_numeral_signed!(i8, i16, i32);

impl Numeral for i64 {
    fn ordinal(&self) -> String {
        let n_abs = if *self == i64::min_value() { *self as u64 } else { self.abs() as u64 };
        ordinal_int(n_abs, *self < 0).concat()
    }
}

macro_rules! impl_numeral_unsigned {
    ($($numtype: ty),*) => ($(
        impl Numeral for $numtype {
            fn ordinal(&self) -> String {
                ordinal_int(u64::from(*self), false).concat()
            }
        }
    )*)
}

impl_numeral_unsigned!(u8, u16, u32, u64);

/// Returns the written form of any 64-bit integer
/// as a vector of strings.
#[inline]
fn ordinal_int(n: u64, negative: bool) -> Vec<&'static str> {
    if n == 0 { return vec![NUMBER[0]] }
    let multiple_order = ((n as f32).log10() as u32) / 3;
    let max_len = multiple_order as usize * 8 + 6;
    let mut numeral = Vec::with_capacity(max_len);
    if negative { numeral.push("minus "); }
    compose_ordinal_int(n, multiple_order, &mut numeral);
    debug_assert!(numeral.len() <= max_len);
    numeral
}

macro_rules! push {
    ($table: ident[$index: ident] on $vec: ident) => (
        debug_assert!(($index as usize) < $table.len(), format!("{} out of {}'s range", stringify!($index), stringify!($table)));
        $vec.push($table[$index as usize]);
    )
}

/// Pushes the strings composing the ordinal form of any unsigned 64-bit number
/// on a vector. Zero is ignored.
#[inline]
fn compose_ordinal_int(n: u64, multiple_order: u32, numeral: &mut Vec<&'static str>) {
    debug_assert!(multiple_order == ((n as f32).log10() as u32) / 3, "wrong value for multiple_order in compose_ordinal_int()");
    let (mut n, mut multiple_order) = (n, multiple_order);
    let mut multiplier = 10u64.pow(multiple_order * 3);
    let mut multiplicand;
    if multiple_order > 0 {
        loop {
            multiplicand = n / multiplier;
            n %= multiplier;
            if multiplicand != 0 {
                push_triplet(multiplicand, numeral);
                numeral.push(" ");
                push!(MULTIPLIER[multiple_order] on numeral);
                if n != 0 { numeral.push(" "); }
            }
            multiple_order -= 1;
            if multiple_order == 0 { break }
            multiplier = multiplier / 1000;
        }
    }
    push_triplet(n, numeral);
}

/// Takes a three-digit integer (n in [1,999]) and adds it's written form
/// to a numeral in construction. Zero is ignored.
#[inline]
fn push_triplet(n: u64, numeral: &mut Vec<&'static str>) {
    debug_assert!(n < 1000, "n >= 1000 in push_triplet()");
    let hundreds = n / 100;
    let rest = n % 100;
    if hundreds != 0 {
        push!(NUMBER[hundreds] on numeral);
        if rest == 0 { numeral.push(" hundred"); }
        else { numeral.push(" hundred "); }
    }
    push_doublet(rest, numeral);
}

/// Takes a two-digit integer (n in [1,99]) and adds it's written form
/// to a numeral in construction. Zero is ignored.
#[inline]
fn push_doublet(n: u64, numeral: &mut Vec<&'static str>) {
    debug_assert!(n < 100, "n >= 100 in push_doublet()");
    if n == 0 { return }
    else if n < 20  {
        push!(NUMBER[n] on numeral);
    }
    else {
        let tens = n / 10;
        let ones = n % 10;
        push!(TENS[tens] on numeral);
        if ones != 0 {
            numeral.push("-");
            push!(NUMBER[ones] on numeral);
        }
    }
}
<commit_msg>add crate documentation<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

//! A Rust library providing the written english form of a number.
//!
//! # Example
//!
//! ```rust
//! use numeral::Numeral;
//!
//! let n = 127;
//! println!("{} is written: {}", n, n.ordinal());
//! ```

#![warn(missing_docs)]

const NUMBER: [&'static str; 20] = [
    "zero",
    "one",
    "two",
    "three",
    "four",
    "five",
    "six",
    "seven",
    "eight",
    "nine",
    "ten",
    "eleven",
    "twelve",
    "thirteen",
    "fourteen",
    "fifteen",
    "sixteen",
    "seventeen",
    "eighteen",
    "nineteen",
];

const TENS: [&'static str; 10] = [
    "",
    "",
    "twenty",
    "thirty",
    "forty",
    "fifty",
    "sixty",
    "seventy",
    "eighty",
    "ninety",
];

const MULTIPLIER: [&'static str; 9] = [
    "",
    "thousand",
    "million",
    "billion",
    "trillion",
    "quadrillion",
    "quintillion",
    "sextillion",
    "septillion",
];

/// The `Numeral` trait provides the written form of a number.
pub trait Numeral {
    /// Yields the ordinal form of a number.
    ///
    /// # Examples
    ///
    /// ```rust
    /// # use numeral::Numeral;
    /// let written_form = 127.ordinal();
    /// assert_eq!(written_form, "one hundred twenty-seven");
    /// ```
    fn ordinal(&self) -> String;
}

macro_rules! impl_numeral_signed {
    ($($numtype: ty),*) => ($(
        impl Numeral for $numtype {
            fn ordinal(&self) -> String {
                ordinal_int(i64::from(*self).abs() as u64, *self < 0).concat()
            }
        }
    )*)
}

impl_numeral_signed!(i8, i16, i32);

impl Numeral for i64 {
    fn ordinal(&self) -> String {
        let n_abs = if *self == i64::min_value() { *self as u64 } else { self.abs() as u64 };
        ordinal_int(n_abs, *self < 0).concat()
    }
}

macro_rules! impl_numeral_unsigned {
    ($($numtype: ty),*) => ($(
        impl Numeral for $numtype {
            fn ordinal(&self) -> String {
                ordinal_int(u64::from(*self), false).concat()
            }
        }
    )*)
}

impl_numeral_unsigned!(u8, u16, u32, u64);

/// Returns the written form of any 64-bit integer
/// as a vector of strings.
#[inline]
fn ordinal_int(n: u64, negative: bool) -> Vec<&'static str> {
    if n == 0 { return vec![NUMBER[0]] }
    let multiple_order = ((n as f32).log10() as u32) / 3;
    let max_len = multiple_order as usize * 8 + 6;
    let mut numeral = Vec::with_capacity(max_len);
    if negative { numeral.push("minus "); }
    compose_ordinal_int(n, multiple_order, &mut numeral);
    debug_assert!(numeral.len() <= max_len);
    numeral
}

macro_rules! push {
    ($table: ident[$index: ident] on $vec: ident) => (
        debug_assert!(($index as usize) < $table.len(), format!("{} out of {}'s range", stringify!($index), stringify!($table)));
        $vec.push($table[$index as usize]);
    )
}

/// Pushes the strings composing the ordinal form of any unsigned 64-bit number
/// on a vector. Zero is ignored.
#[inline]
fn compose_ordinal_int(n: u64, multiple_order: u32, numeral: &mut Vec<&'static str>) {
    debug_assert!(multiple_order == ((n as f32).log10() as u32) / 3, "wrong value for multiple_order in compose_ordinal_int()");
    let (mut n, mut multiple_order) = (n, multiple_order);
    let mut multiplier = 10u64.pow(multiple_order * 3);
    let mut multiplicand;
    if multiple_order > 0 {
        loop {
            multiplicand = n / multiplier;
            n %= multiplier;
            if multiplicand != 0 {
                push_triplet(multiplicand, numeral);
                numeral.push(" ");
                push!(MULTIPLIER[multiple_order] on numeral);
                if n != 0 { numeral.push(" "); }
            }
            multiple_order -= 1;
            if multiple_order == 0 { break }
            multiplier = multiplier / 1000;
        }
    }
    push_triplet(n, numeral);
}

/// Takes a three-digit integer (n in [1,999]) and adds it's written form
/// to a numeral in construction. Zero is ignored.
#[inline]
fn push_triplet(n: u64, numeral: &mut Vec<&'static str>) {
    debug_assert!(n < 1000, "n >= 1000 in push_triplet()");
    let hundreds = n / 100;
    let rest = n % 100;
    if hundreds != 0 {
        push!(NUMBER[hundreds] on numeral);
        if rest == 0 { numeral.push(" hundred"); }
        else { numeral.push(" hundred "); }
    }
    push_doublet(rest, numeral);
}

/// Takes a two-digit integer (n in [1,99]) and adds it's written form
/// to a numeral in construction. Zero is ignored.
#[inline]
fn push_doublet(n: u64, numeral: &mut Vec<&'static str>) {
    debug_assert!(n < 100, "n >= 100 in push_doublet()");
    if n == 0 { return }
    else if n < 20  {
        push!(NUMBER[n] on numeral);
    }
    else {
        let tens = n / 10;
        let ones = n % 10;
        push!(TENS[tens] on numeral);
        if ones != 0 {
            numeral.push("-");
            push!(NUMBER[ones] on numeral);
        }
    }
}
<|endoftext|>


<commit_before>//! Provides some common lints for syntax extensions.
#![feature(plugin_registrar)]
#![feature(rustc_private)]

extern crate syntax;
#[macro_use]
extern crate rustc;

use syntax::ast;
use rustc::lint::{Context, LintPass, LintPassObject, LintArray};
use rustc::plugin;
use std::ops::Deref;

declare_lint!(DUMMY_SPAN,
              Warn,
              "detects uses of DUMMY_SP");

struct Pass;

impl Pass {
    fn new() -> Pass {
        Pass
    }
}

impl LintPass for Pass {
    fn get_lints(&self) -> LintArray {
        lint_array!(DUMMY_SPAN)
    }

    fn check_expr(&mut self, cx: &Context, expr: &ast::Expr) {
        match expr.node {
            ast::ExprPath(None, ref path) => {
                let name = path.segments.last().unwrap().identifier.name.as_str();
                if name.deref() == "DUMMY_SP" {
                    cx.span_lint(DUMMY_SPAN, expr.span,
                                 "usage of 'DUMMY_SP' is discouraged");
                }
            },
            _ => {},
        }
    }
}

#[plugin_registrar]
pub fn register_plugins(reg: &mut plugin::Registry) {
    reg.register_lint_pass(Box::new(Pass::new()) as LintPassObject);
}
<commit_msg>Nightly fallout (9-8-15)<commit_after>//! Provides some common lints for syntax extensions.
#![feature(plugin_registrar)]
#![feature(rustc_private)]

extern crate syntax;
#[macro_use]
extern crate rustc;
extern crate rustc_front;

use rustc_front::hir as ast;
use rustc::lint::{Context, LintPass, LintPassObject, LintArray};
use rustc::plugin;
use std::ops::Deref;

declare_lint!(DUMMY_SPAN,
              Warn,
              "detects uses of DUMMY_SP");

struct Pass;

impl Pass {
    fn new() -> Pass {
        Pass
    }
}

impl LintPass for Pass {
    fn get_lints(&self) -> LintArray {
        lint_array!(DUMMY_SPAN)
    }

    fn check_expr(&mut self, cx: &Context, expr: &ast::Expr) {
        match expr.node {
            ast::ExprPath(None, ref path) => {
                let name = path.segments.last().unwrap().identifier.name.as_str();
                if name.deref() == "DUMMY_SP" {
                    cx.span_lint(DUMMY_SPAN, expr.span,
                                 "usage of 'DUMMY_SP' is discouraged");
                }
            },
            _ => {},
        }
    }
}

#[plugin_registrar]
pub fn register_plugins(reg: &mut plugin::Registry) {
    reg.register_lint_pass(Box::new(Pass::new()) as LintPassObject);
}
<|endoftext|>


<commit_before>#[macro_export]
macro_rules! delegate_method {
    {impl $($tt:tt)*} =>
    {delegate_method!{@impl_collect () $($tt)*}};

    {@impl_collect ($($headtt:tt)*) {$($tailtt:tt)*}} =>
    {delegate_method!{@impl_expansion ($($headtt)*) ($($tailtt)*) ()}};

    {@impl_collect ($($headtt:tt)*) $tt:tt $($tailtt:tt)*} =>
    {delegate_method!{@impl_collect ($($headtt)* $tt) $($tailtt)*}};

    {@impl_expansion_impl ($($headtt:tt)*) ($($itemtt:tt)*) ($($resttt:tt)*) ($($tailtt:tt)*)} =>
    {delegate_method!{@impl_expansion ($($headtt)*) ($($resttt)*) ($($tailtt)* #[inline] $($itemtt)*)}};

    (@impl_finalization ($($headtt:tt)*) ($($tailtt:tt)*)) =>
    {delegate_method!(@as_item #[allow(dead_code)]impl $($headtt)* { $($tailtt)* });};

    (@as_item $i:item) => { $i };

    {@impl_expansion ($($headtt:tt)*) () ($($tailtt:tt)*)} =>
    {delegate_method!(@impl_finalization ($($headtt)*) ($($tailtt)*));};

    {@impl_expansion ($($headtt:tt)*)
     (type $ascty:ident = $dstty:ty; $($resttt:tt)*) ($($tailtt:tt)*)} =>
    {delegate_method!(@impl_expansion ($($headtt)*) ($($resttt)*) ($($tailtt)* type $ascty = $dstty; ));};

    {@impl_expansion ($($headtt:tt)*)
     ($fld:tt $(as $fldty:ty)* : ) ($($tailtt:tt)*)} =>
    {delegate_method!(@impl_expansion ($($headtt)*) () ($($tailtt)*));};

    {@impl_expansion ($($headtt:tt)*)
     ($fld_last:tt $(as $fldty_last:ty)* :
      $fld:tt $(as $fldty:ty)* : $($resttt:tt)*) ($($tailtt:tt)*)} =>
    {delegate_method!(@impl_expansion ($($headtt)*)
                      ($fld $(as $fldty)* : $($resttt)*) ($($tailtt)*));};

    {@impl_expansion ($($headtt:tt)*)
     ($fld:tt : $($resttt:tt)*) ($($tailtt:tt)*)} =>
    {delegate_method!(@impl_expansion ($($headtt)*) ($fld as () : $($resttt)*) ($($tailtt)*))};

    {@impl_expansion ($($headtt:tt)*)
     ($fld:tt as $fldty:ty :
      pub fn $fcn:ident $(< $($lt:tt),* >)* ($($args:tt)*) $(-> $r:ty)* ; $($resttt:tt)* )
     ($($tailtt:tt)*)} =>
    {delegate_method!(@impl_expansion_item ($($headtt)*)
                      ($fld) ($fldty) ($fcn) (pub fn) ($($($lt),*),*) ($($args)*) ($(-> $r)*)
                      ($fld as $fldty : $($resttt)*) ($($tailtt)*));};

    {@impl_expansion ($($headtt:tt)*)
     ($fld:tt as $fldty:ty :
      fn $fcn:ident $(< $($lt:tt),* >)* ($($args:tt)*) $(-> $r:ty)* ; $($resttt:tt)* )
     ($($tailtt:tt)*)} =>
    {delegate_method!(@impl_expansion_item ($($headtt)*)
                      ($fld) ($fldty) ($fcn) (fn) ($($($lt),*),*) ($($args)*) ($(-> $r)*)
                      ($fld as $fldty : $($resttt)*) ($($tailtt)*));};

    (@impl_expansion_item ($($headtt:tt)*)
     ($fld:tt) ($fldty:ty) ($fcn:ident) ($($kwtt:tt)*) ($($gp:tt)+) ($($args:tt)*) ($($r:tt)*)
     ($($resttt:tt)*) ($($tailtt:tt)*)) =>
    {delegate_method!(@impl_expansion_gp ($($headtt)*)
                      ($fld) ($fldty) ($fcn) ($($kwtt)*) (<$($gp)*>) ($($args)*) ($($r)*)
                      ($($resttt)*) ($($tailtt)*));};

    (@impl_expansion_item ($($headtt:tt)*)
     ($fld:tt) ($fldty:ty) ($fcn:ident) ($($kwtt:tt)*) () ($($args:tt)*) ($($r:tt)*)
     ($($resttt:tt)*) ($($tailtt:tt)*)) =>
    {delegate_method!(@impl_expansion_gp ($($headtt)*)
                      ($fld) ($fldty) ($fcn) ($($kwtt)*) () ($($args)*) ($($r)*)
                      ($($resttt)*) ($($tailtt)*));};

    (@impl_expansion_gp ($($headtt:tt)*)
     ($fld:tt) ($fldty:ty) ($fcn:ident) ($($kwtt:tt)*) ($($gp:tt)*) (self) ($($r:tt)*)
     ($($resttt:tt)*) ($($tailtt:tt)*)) =>
    {delegate_method!(@impl_expansion_impl ($($headtt)*)
                      ($($kwtt)* $fcn $($gp)* (self) $($r)* { (self.$fld).$fcn() })
                      ($($resttt)*) ($($tailtt)*));};

    (@impl_expansion_gp ($($headtt:tt)*)
     ($fld:tt) ($fldty:ty) ($fcn:ident) ($($kwtt:tt)*) ($($gp:tt)*) (&self) ($($r:tt)*)
     ($($resttt:tt)*) ($($tailtt:tt)*)) =>
    {delegate_method!(@impl_expansion_impl ($($headtt)*)
                      ($($kwtt)* $fcn $($gp)* (&self) $($r)* { (self.$fld).$fcn() })
      ($($resttt)*) ($($tailtt)*));};

    (@impl_expansion_gp ($($headtt:tt)*)
    ($fld:tt) ($fldty:ty) ($fcn:ident) ($($kwtt:tt)*) ($($gp:tt)*) (&mut self) ($($r:tt)*)
    ($($resttt:tt)*) ($($tailtt:tt)*)) =>
    {delegate_method!(@impl_expansion_impl ($($headtt)*)
      ($($kwtt)* $fcn $($gp)* (&mut self) $($r)* { (self.$fld).$fcn() })
      ($($resttt)*) ($($tailtt)*));};

    (@impl_expansion_gp ($($headtt:tt)*)
   ($fld:tt) ($fldty:ty) ($fcn:ident) ($($kwtt:tt)*) ($($gp:tt)*)
   (self, $( $a:ident : $at:ty ),*) ($($r:tt)*)
    ($($resttt:tt)*) ($($tailtt:tt)*)) =>
    {delegate_method!(@impl_expansion_impl ($($headtt)*)
      ($($kwtt)* $fcn $($gp)* (self,$($a : $at)*) $($r)* { (self.$fld).$fcn($($a),*) })
      ($($resttt)*) ($($tailtt)*));};

    (@impl_expansion_gp ($($headtt:tt)*)
   ($fld:tt) ($fldty:ty) ($fcn:ident) ($($kwtt:tt)*) ($($gp:tt)*)
   (&self, $( $a:ident : $at:ty ),*) ($($r:tt)*)
    ($($resttt:tt)*) ($($tailtt:tt)*)) =>
    {delegate_method!(@impl_expansion_impl ($($headtt)*)
      ($($kwtt)* $fcn $($gp)* (&self,$($a : $at)*) $($r)* { (self.$fld).$fcn($($a),*) })
      ($($resttt)*) ($($tailtt)*));};

    (@impl_expansion_gp ($($headtt:tt)*)
   ($fld:tt) ($fldty:ty) ($fcn:ident) ($($kwtt:tt)*) ($($gp:tt)*)
   (&mut self, $( $a:ident : $at:ty ),*) ($($r:tt)*)
    ($($resttt:tt)*) ($($tailtt:tt)*)) =>
    {delegate_method!(@impl_expansion_impl ($($headtt)*)
      ($($kwtt)* $fcn $($gp)* (&mut self,$($a : $at)*) $($r)* { (self.$fld).$fcn($($a),*) })
      ($($resttt)*) ($($tailtt)*));};

    (@impl_expansion_gp ($($headtt:tt)*)
   ($fld:tt) ($fldty:ty) ($fcn:ident) ($($kwtt:tt)*) ($($gp:tt)*)
   ($( $a:ident : $at:ty ),*) ($($r:tt)*)
    ($($resttt:tt)*) ($($tailtt:tt)*)) =>
    {delegate_method!(@ impl_expansion_impl ($($headtt)*)
      ($($kwtt)* $fcn $($gp)* ($($a : $at)*) $($r)* { <$fldty>::$fcn($($a),*) })
      ($($resttt)*) ($($tailtt)*));};
}

#[cfg(test)]
mod tests {
    #[derive(Copy, Clone)]
    struct Inner {
        data: usize,
    }

    impl Inner {
        pub fn new_inner() -> Self {
            Inner { data: 42 }
        }

        pub fn new_inner_add(val: usize) -> Self {
            Inner { data: 42 + val }
        }

        pub fn noop(&self) {}

        pub fn str_to_owned<'a>(str: &'a str) -> String {
            str.to_owned()
        }

        pub fn get(&self) -> usize {
            self.data
        }

        pub fn get_add(&self, val: usize) -> usize {
            self.data + val
        }

        pub fn reset(&mut self) -> usize {
            self.data = 0;
            self.data
        }

        pub fn set(&mut self, val: usize) -> usize {
            self.data = val;
            self.data
        }

        pub fn to_data(self) -> usize {
            self.data
        }

        pub fn to_data_add(self, val: usize) -> usize {
            self.data + val
        }
    }

    #[test]
    fn test_delegate() {
        #[derive(Copy, Clone)]
        struct Outer {
            inner: Inner,
        }

        delegate_method! {
			      impl Outer {
                inner as Inner:
                fn new_inner() -> Inner;
                fn new_inner_add(val: usize) -> Inner;
                fn noop(&self);
				        fn str_to_owned<'a>(str: &'a str) -> String;
                fn get(&self) -> usize;
                fn get_add(&self, val: usize) -> usize;
                fn reset(&mut self) -> usize;
                fn set(&mut self, val: usize) -> usize;
                inner as Inner:
                fn to_data(self) -> usize;
                fn to_data_add(self, val: usize) -> usize;
            }
        }

        assert_eq!(Outer::new_inner().get(), 42);
        assert_eq!(Outer::new_inner_add(58).get(), 100);

        assert_eq!(Outer::str_to_owned("Hello"), "Hello".to_owned());

        let mut x = Outer { inner: Inner::new_inner() };

        assert_eq!(x.get(), 42);
        assert_eq!(x.get_add(58), 100);
        x.noop();

        x.reset();
        assert_eq!(x.get(), 0);

        x.set(36);
        assert_eq!(x.get(), 36);

        assert_eq!(x.clone().to_data(), 36);
        assert_eq!(x.clone().to_data_add(4), 40);
    }
}
<commit_msg>add support for function where clause.<commit_after>#[macro_export]
macro_rules! delegate_method {
    {impl $($tt:tt)*} =>
    {delegate_method!{@impl_collect () $($tt)*}};

    {@impl_collect ($($headtt:tt)*) {$($tailtt:tt)*}} =>
    {delegate_method!{@impl_expansion ($($headtt)*) ($($tailtt)*) ()}};

    {@impl_collect ($($headtt:tt)*) $tt:tt $($tailtt:tt)*} =>
    {delegate_method!{@impl_collect ($($headtt)* $tt) $($tailtt)*}};

    {@impl_expansion_impl ($($headtt:tt)*) ($($itemtt:tt)*) ($($resttt:tt)*) ($($tailtt:tt)*)} =>
    {delegate_method!{@impl_expansion ($($headtt)*) ($($resttt)*) ($($tailtt)* #[inline] $($itemtt)*)}};

    (@impl_finalization ($($headtt:tt)*) ($($tailtt:tt)*)) =>
    {delegate_method!(@as_item #[allow(dead_code)]impl $($headtt)* { $($tailtt)* });};

    (@as_item $i:item) => { $i };

    {@impl_expansion ($($headtt:tt)*) () ($($tailtt:tt)*)} =>
    {delegate_method!(@impl_finalization ($($headtt)*) ($($tailtt)*));};

    {@impl_expansion ($($headtt:tt)*)
     (type $ascty:ident = $dstty:ty; $($resttt:tt)*) ($($tailtt:tt)*)} =>
    {delegate_method!(@impl_expansion ($($headtt)*) ($($resttt)*) ($($tailtt)* type $ascty = $dstty; ));};

    {@impl_expansion ($($headtt:tt)*)
     ($fld:tt $(as $fldty:ty)* : ) ($($tailtt:tt)*)} =>
    {delegate_method!(@impl_expansion ($($headtt)*) () ($($tailtt)*));};

    {@impl_expansion ($($headtt:tt)*)
     ($fld_last:tt $(as $fldty_last:ty)* :
      $fld:tt $(as $fldty:ty)* : $($resttt:tt)*) ($($tailtt:tt)*)} =>
    {delegate_method!(@impl_expansion ($($headtt)*)
                      ($fld $(as $fldty)* : $($resttt)*) ($($tailtt)*));};

    {@impl_expansion ($($headtt:tt)*)
     ($fld:tt : $($resttt:tt)*) ($($tailtt:tt)*)} =>
    {delegate_method!(@impl_expansion ($($headtt)*) ($fld as () : $($resttt)*) ($($tailtt)*))};

    {@impl_expansion ($($headtt:tt)*)
     ($fld:tt as $fldty:ty :
      pub fn $fcn:ident $(< $($lt:tt),* >)* ($($args:tt)*) $(-> $r:ty)* $(where $($aty:ident : $atyb_first:tt $(+ $ayb_rest:tt)*),*)*; $($resttt:tt)* )
     ($($tailtt:tt)*)} =>
    {delegate_method!(@impl_expansion_item ($($headtt)*)
                      ($fld) ($fldty) ($fcn) (pub fn) ($($($lt),*),*) ($($args)*) ($(-> $r)*) ($($($aty : $atyb_first $(+ $ayb_rest:tt)*),*)*)
                      ($fld as $fldty : $($resttt)*) ($($tailtt)*));};

    {@impl_expansion ($($headtt:tt)*)
     ($fld:tt as $fldty:ty :
      fn $fcn:ident $(< $($lt:tt),* >)* ($($args:tt)*) $(-> $r:ty)* $(where $($aty:ident : $atyb_first:tt $(+ $ayb_rest:tt)*),*)*; $($resttt:tt)* )
     ($($tailtt:tt)*)} =>
    {delegate_method!(@impl_expansion_item ($($headtt)*)
                      ($fld) ($fldty) ($fcn) (fn) ($($($lt),*),*) ($($args)*) ($(-> $r)*) ($($($aty : $atyb_first $(+ $ayb_rest:tt)*),*)*)
                      ($fld as $fldty : $($resttt)*) ($($tailtt)*));};

    (@impl_expansion_item ($($headtt:tt)*)
     ($fld:tt) ($fldty:ty) ($fcn:ident) ($($kwtt:tt)*) ($($gp:tt)*) ($($args:tt)*) ($($r:tt)*) ($($b:tt)+)
     ($($resttt:tt)*) ($($tailtt:tt)*)) =>
    {delegate_method!(@impl_expansion_bound ($($headtt)*)
                      ($fld) ($fldty) ($fcn) ($($kwtt)*) ($($gp)*) ($($args)*) ($($r)* where $($b)*)
                      ($($resttt)*) ($($tailtt)*));};

    (@impl_expansion_item ($($headtt:tt)*)
     ($fld:tt) ($fldty:ty) ($fcn:ident) ($($kwtt:tt)*) ($($gp:tt)*) ($($args:tt)*) ($($r:tt)*) ()
     ($($resttt:tt)*) ($($tailtt:tt)*)) =>
    {delegate_method!(@impl_expansion_bound ($($headtt)*)
                      ($fld) ($fldty) ($fcn) ($($kwtt)*) ($($gp)*) ($($args)*) ($($r)*)
                      ($($resttt)*) ($($tailtt)*));};

    (@impl_expansion_bound ($($headtt:tt)*)
     ($fld:tt) ($fldty:ty) ($fcn:ident) ($($kwtt:tt)*) ($($gp:tt)+) ($($args:tt)*) ($($r:tt)*)
     ($($resttt:tt)*) ($($tailtt:tt)*)) =>
    {delegate_method!(@impl_expansion_gp ($($headtt)*)
                      ($fld) ($fldty) ($fcn) ($($kwtt)*) (<$($gp)*>) ($($args)*) ($($r)*)
                      ($($resttt)*) ($($tailtt)*));};

    (@impl_expansion_bound ($($headtt:tt)*)
     ($fld:tt) ($fldty:ty) ($fcn:ident) ($($kwtt:tt)*) () ($($args:tt)*) ($($r:tt)*)
     ($($resttt:tt)*) ($($tailtt:tt)*)) =>
    {delegate_method!(@impl_expansion_gp ($($headtt)*)
                      ($fld) ($fldty) ($fcn) ($($kwtt)*) () ($($args)*) ($($r)*)
                      ($($resttt)*) ($($tailtt)*));};

    (@impl_expansion_gp ($($headtt:tt)*)
     ($fld:tt) ($fldty:ty) ($fcn:ident) ($($kwtt:tt)*) ($($gp:tt)*) (self) ($($r:tt)*)
     ($($resttt:tt)*) ($($tailtt:tt)*)) =>
    {delegate_method!(@impl_expansion_impl ($($headtt)*)
                      ($($kwtt)* $fcn $($gp)* (self) $($r)* { (self.$fld).$fcn() })
                      ($($resttt)*) ($($tailtt)*));};

    (@impl_expansion_gp ($($headtt:tt)*)
     ($fld:tt) ($fldty:ty) ($fcn:ident) ($($kwtt:tt)*) ($($gp:tt)*) (&self) ($($r:tt)*)
     ($($resttt:tt)*) ($($tailtt:tt)*)) =>
    {delegate_method!(@impl_expansion_impl ($($headtt)*)
                      ($($kwtt)* $fcn $($gp)* (&self) $($r)* { (self.$fld).$fcn() })
      ($($resttt)*) ($($tailtt)*));};

    (@impl_expansion_gp ($($headtt:tt)*)
    ($fld:tt) ($fldty:ty) ($fcn:ident) ($($kwtt:tt)*) ($($gp:tt)*) (&mut self) ($($r:tt)*)
    ($($resttt:tt)*) ($($tailtt:tt)*)) =>
    {delegate_method!(@impl_expansion_impl ($($headtt)*)
      ($($kwtt)* $fcn $($gp)* (&mut self) $($r)* { (self.$fld).$fcn() })
      ($($resttt)*) ($($tailtt)*));};

    (@impl_expansion_gp ($($headtt:tt)*)
   ($fld:tt) ($fldty:ty) ($fcn:ident) ($($kwtt:tt)*) ($($gp:tt)*)
   (self, $( $a:ident : $at:ty ),*) ($($r:tt)*)
    ($($resttt:tt)*) ($($tailtt:tt)*)) =>
    {delegate_method!(@impl_expansion_impl ($($headtt)*)
      ($($kwtt)* $fcn $($gp)* (self,$($a : $at)*) $($r)* { (self.$fld).$fcn($($a),*) })
      ($($resttt)*) ($($tailtt)*));};

    (@impl_expansion_gp ($($headtt:tt)*)
   ($fld:tt) ($fldty:ty) ($fcn:ident) ($($kwtt:tt)*) ($($gp:tt)*)
   (&self, $( $a:ident : $at:ty ),*) ($($r:tt)*)
    ($($resttt:tt)*) ($($tailtt:tt)*)) =>
    {delegate_method!(@impl_expansion_impl ($($headtt)*)
      ($($kwtt)* $fcn $($gp)* (&self,$($a : $at)*) $($r)* { (self.$fld).$fcn($($a),*) })
      ($($resttt)*) ($($tailtt)*));};

    (@impl_expansion_gp ($($headtt:tt)*)
   ($fld:tt) ($fldty:ty) ($fcn:ident) ($($kwtt:tt)*) ($($gp:tt)*)
   (&mut self, $( $a:ident : $at:ty ),*) ($($r:tt)*)
    ($($resttt:tt)*) ($($tailtt:tt)*)) =>
    {delegate_method!(@impl_expansion_impl ($($headtt)*)
      ($($kwtt)* $fcn $($gp)* (&mut self,$($a : $at)*) $($r)* { (self.$fld).$fcn($($a),*) })
      ($($resttt)*) ($($tailtt)*));};

    (@impl_expansion_gp ($($headtt:tt)*)
   ($fld:tt) ($fldty:ty) ($fcn:ident) ($($kwtt:tt)*) ($($gp:tt)*)
   ($( $a:ident : $at:ty ),*) ($($r:tt)*)
    ($($resttt:tt)*) ($($tailtt:tt)*)) =>
    {delegate_method!(@ impl_expansion_impl ($($headtt)*)
      ($($kwtt)* $fcn $($gp)* ($($a : $at)*) $($r)* { <$fldty>::$fcn($($a),*) })
      ($($resttt)*) ($($tailtt)*));};
}

#[cfg(test)]
mod tests {
    #[derive(Copy, Clone)]
    struct Inner {
        data: usize,
    }

    impl Inner {
        pub fn new_inner() -> Self {
            Inner { data: 42 }
        }

        pub fn new_inner_add(val: usize) -> Self {
            Inner { data: 42 + val }
        }

        pub fn noop(&self) {}

        pub fn str_to_owned<'a>(str: &'a str) -> String {
            str.to_owned()
        }

        pub fn get(&self) -> usize {
            self.data
        }

        pub fn get_add(&self, val: usize) -> usize {
            self.data + val
        }

        pub fn reset(&mut self) -> usize {
            self.data = 0;
            self.data
        }

        pub fn set(&mut self, val: usize) -> usize {
            self.data = val;
            self.data
        }

        pub fn to_data(self) -> usize {
            self.data
        }

        pub fn to_data_add(self, val: usize) -> usize {
            self.data + val
        }
    }

    #[test]
    fn test_delegate() {
        #[derive(Copy, Clone)]
        struct Outer {
            inner: Inner,
        }

        delegate_method! {
			      impl Outer {
                inner as Inner:
                fn new_inner() -> Inner;
                fn new_inner_add(val: usize) -> Inner;
                fn noop(&self);
				        fn str_to_owned<'a>(str: &'a str) -> String;
                fn get(&self) -> usize;
                fn get_add(&self, val: usize) -> usize;
                fn reset(&mut self) -> usize;
                fn set(&mut self, val: usize) -> usize;
                inner as Inner:
                fn to_data(self) -> usize;
                fn to_data_add(self, val: usize) -> usize;
            }
        }

        assert_eq!(Outer::new_inner().get(), 42);
        assert_eq!(Outer::new_inner_add(58).get(), 100);

        assert_eq!(Outer::str_to_owned("Hello"), "Hello".to_owned());

        let mut x = Outer { inner: Inner::new_inner() };

        assert_eq!(x.get(), 42);
        assert_eq!(x.get_add(58), 100);
        x.noop();

        x.reset();
        assert_eq!(x.get(), 0);

        x.set(36);
        assert_eq!(x.get(), 36);

        assert_eq!(x.clone().to_data(), 36);
        assert_eq!(x.clone().to_data_add(4), 40);
    }
}
<|endoftext|>


<commit_before>
extern crate websocket;

use std::thread;
use std::sync::{Arc, Mutex};
use std::fs::File;
use std::path::Path;
use std::env;
use std::io::Read;
use std::io::Write;
use std::io::{Error,ErrorKind};
use std::string::*;
use std::collections::BTreeMap;
use std::fmt::format;

use std::net::UdpSocket;

use websocket::{Server, Message, Sender, Receiver};
use websocket::header::WebSocketProtocol;
use websocket::message::Type;

extern crate iron;

use iron::prelude::*;
use iron::status;
use iron::mime::Mime;

#[macro_use]
mod tryopt;
mod stringerror;
mod controls;
mod broadcaster;
mod string_defaults;
mod control_updates;

extern crate serde_json;
use serde_json::Value;

fn load_string(file_name: &str) -> Result<String, Box<std::error::Error> >
{
  let path = &Path::new(&file_name);
  let mut inf = try!(File::open(path));
  let mut result = String::new();
  try!(inf.read_to_string(&mut result));
  Ok(result)
}

fn write_string(text: &str, file_name: &str) -> Result<(), Box<std::error::Error> >
{
  let path = &Path::new(&file_name);
  let mut inf = try!(File::create(path));
  match inf.write(text.as_bytes()) {
    Ok(_) => Ok(()),
    Err(e) => Err(Box::new(e)),
    }
}

pub struct ControlInfo {
  cm: controls::ControlMap,
  guijson: String,
}

pub fn startserver(guifilename: &str, ip: &str, http_port: &str, websockets_port: &str, htmltemplatefile: Option<&str> ) -> Result<(), Box<std::error::Error> >
{
    let mut http_ip = String::from(ip);
    http_ip.push_str(":");
    http_ip.push_str(&http_port);

    let mut websockets_ip = String::from(ip);
    websockets_ip.push_str(":");
    websockets_ip.push_str(&websockets_port);

    let htmltemplate = {
      match htmltemplatefile {
        Some(fname) => {
          try!(load_string(fname))
        }
        None => string_defaults::MAIN_HTML.to_string()
      }
    };

    let htmlstring = htmltemplate.replace("<websockets-port>", &websockets_port);

    // println!("{}", htmlstring);

    let guistring = try!(load_string(&guifilename[..]));
    let guival: Value = try!(serde_json::from_str(&guistring[..]));

    let blah = try!(controls::deserialize_root(&guival));

    println!("title: {} rootcontroltype: {} ",
      blah.title, blah.root_control.control_type());
    println!("controls: {:?}", blah.root_control);

    // from control tree, make a map of ids->controls.
    let mapp = controls::make_control_map(&*blah.root_control);
    let guijson = guistring.clone();

    let ci = ControlInfo { cm: mapp, guijson: guijson };

    let cmshare = Arc::new(Mutex::new(ci));
    let wscmshare = cmshare.clone();
    // let oscsocket = try!(UdpSocket::bind(&oscrecvip[..]));
    // for sending, bind to this.  if we bind to localhost, we can't
    // send messages to other machines.
    // let oscsendsocket = try!(UdpSocket::bind("0.0.0.0:0"));
    let bc = broadcaster::Broadcaster::new();
    // let wsos = try!(oscsendsocket.try_clone());
    let wsbc = bc.clone();
    // let wsoscsendip = oscsendip.clone();

    /*
    thread::spawn(move || {
      match oscmain(oscsocket, bc, cmshare) {
        Err(e) => println!("oscmain exited with error: {:?}", e),
        Ok(_) => (),
      }
      });
    */

    // Spawn a thread for the websockets handler.
    thread::spawn(move || {
      match websockets_main(websockets_ip, wscmshare, wsbc) {
        Ok(_) => (),
        Err(e) => println!("error in websockets_main: {:?}", e),
      }
    });

    // use this thread for the web server.
    try!(Iron::new(move | _: &mut Request| {
        let content_type = "text/html".parse::<Mime>().unwrap();
        Ok(Response::with((content_type, status::Ok, &*htmlstring)))
    }).http(&http_ip[..]));

    // return when the web server dies, if it ever does.
    Ok(())
}

// TODO: refactor to return a (rx/sx) pair for sending, recieving messages.
// library users start the websockets_main and get that pair of things.
// then, can send the various control structs and receive the messages.
fn websockets_main( ipaddr: String,
                    ci: Arc<Mutex<ControlInfo>>,
                    broadcaster: broadcaster::Broadcaster)
                  -> Result<(), Box<std::error::Error> >
{
	let server = try!(Server::bind(&ipaddr[..]));

	for connection in server {

    println!("new websockets connection!");
		// Spawn a new thread for each connection.

    let sci = ci.clone();
//    let osock = try!(oscsocket.try_clone());
 //   let osend = oscsendip.clone();
    let broadcaster = broadcaster.clone();

    let conn = try!(connection);
    thread::spawn(move || {
      match websockets_client(conn,
                            sci,
                            broadcaster) {
        Ok(_) => (),
        Err(e) => {
          println!("error in websockets thread: {:?}", e);
          ()
        },
      }
    });
  }

  Ok(())
}

fn websockets_client(connection: websocket::server::Connection<websocket::stream::WebSocketStream, websocket::stream::WebSocketStream>,
                    ci: Arc<Mutex<ControlInfo>>,
                    mut broadcaster: broadcaster::Broadcaster,
                    ) -> Result<(), Box<std::error::Error> >
{
  // Get the request
  let request = try!(connection.read_request());
  // Keep the headers so we can check them
  let headers = request.headers.clone();

  try!(request.validate()); // Validate the request

  let mut response = request.accept(); // Form a response

  if let Some(&WebSocketProtocol(ref protocols)) = headers.get() {
    if protocols.contains(&("rust-websocket".to_string())) {
      // We have a protocol we want to use
      response.headers.set(WebSocketProtocol(vec!["rust-websocket".to_string()]));
    }
  }

  let mut client = try!(response.send()); // Send the response

  let ip = try!(client.get_mut_sender()
                  .get_mut()
                  .peer_addr());

  println!("Websocket connection from {}", ip);

  // send up the json of the current controls.
  {
    let sci = ci.lock().unwrap();

    let updarray = controls::cm_to_update_array(&sci.cm);

    // build json message containing both guijson and the updarray.
    // let updvals = updarray.into_iter().map(|x|{controls::encode_update_message(&x)}).collect();

    let mut updvals = Vec::new();

    for upd in updarray {
      let um = controls::encode_update_message(&upd);
      updvals.push(um);
    }

    let mut guival: Value = try!(serde_json::from_str(&sci.guijson[..]));

    match guival.as_object_mut() {
      Some(obj) => {
        obj.insert("state".to_string(), Value::Array(updvals));
        ()
      },
      None => (),
    }

    let guistring = try!(serde_json::ser::to_string(&guival));
    let message = Message::text(guistring);
    try!(client.send_message(&message));
  }

  let (sender, mut receiver) = client.split();

  let sendmeh = Arc::new(Mutex::new(sender));

  broadcaster.register(sendmeh.clone());

  for msg in receiver.incoming_messages() {
    let message: Message = try!(msg);
    // println!("message: {:?}", message);

    match message.opcode {
      Type::Close => {
        let message = Message::close();
        // let mut sender = try!(sendmeh.lock());
        let mut sender = sendmeh.lock().unwrap();
        try!(sender.send_message(&message));
        println!("Client {} disconnected", ip);
        return Ok(());
      }
      Type::Ping => {
        println!("Message::Ping(data)");
        let message = Message::pong(message.payload);
        let mut sender = sendmeh.lock().unwrap();
        try!(sender.send_message(&message));
      }
      Type::Text => {
        let u8 = message.payload.to_owned();
        let str = try!(std::str::from_utf8(&*u8));
        let jsonval: Value = try!(serde_json::from_str(str));
        let s_um = controls::decode_update_message(&jsonval);
        match s_um {
          Some(updmsg) => {
            let mut sci  = ci.lock().unwrap();
            let mbcntrl = sci.cm.get_mut(controls::get_um_id(&updmsg));
            match mbcntrl {
              Some(cntrl) => {
                (*cntrl).update(&updmsg);
                broadcaster.broadcast_others(&ip, Message::text(str));

                // TODO: callback ftn??
                /*
                match ctrl_update_to_osc(&updmsg, &**cntrl) {
                  Ok(v) => match oscsocket.send_to(&v, &oscsendip[..]) {
                    Ok(_) => (),
                    Err(e) =>
                      println!("error sending osc message: {:?}", e),
                    },
                  Err(e) =>
                    println!("error building osc message: {:?}", e),
                };
                */

                println!("websockets control update recieved: {:?}", updmsg);
                ()
              },
              None => println!("none"),
            }
          },
          _ => println!("decode_update_message failed on websockets msg: {:?}", message),
        }
      },
      _ => {
        println!("unknown websockets msg: {:?}", message);
      }
    }
  }

  Ok(())
}

<commit_msg>add loadguistring ftn<commit_after>
extern crate websocket;

use std::thread;
use std::sync::{Arc, Mutex};
use std::fs::File;
use std::path::Path;
use std::env;
use std::io::Read;
use std::io::Write;
use std::io::{Error,ErrorKind};
use std::string::*;
use std::collections::BTreeMap;
use std::fmt::format;

use std::net::UdpSocket;

use websocket::{Server, Message, Sender, Receiver};
use websocket::header::WebSocketProtocol;
use websocket::message::Type;

extern crate iron;

use iron::prelude::*;
use iron::status;
use iron::mime::Mime;

#[macro_use]
mod tryopt;
mod stringerror;
mod controls;
mod broadcaster;
mod string_defaults;
mod control_updates;

extern crate serde_json;
use serde_json::Value;

fn load_string(file_name: &str) -> Result<String, Box<std::error::Error> >
{
  let path = &Path::new(&file_name);
  let mut inf = try!(File::open(path));
  let mut result = String::new();
  try!(inf.read_to_string(&mut result));
  Ok(result)
}

fn write_string(text: &str, file_name: &str) -> Result<(), Box<std::error::Error> >
{
  let path = &Path::new(&file_name);
  let mut inf = try!(File::create(path));
  match inf.write(text.as_bytes()) {
    Ok(_) => Ok(()),
    Err(e) => Err(Box::new(e)),
    }
}

pub struct ControlInfo {
  cm: controls::ControlMap,
  guijson: String,
}

pub fn startserver(guifilename: &str, ip: &str, http_port: &str, websockets_port: &str, htmltemplatefile: Option<&str> ) -> Result<(), Box<std::error::Error> >
{
    let mut http_ip = String::from(ip);
    http_ip.push_str(":");
    http_ip.push_str(&http_port);

    let mut websockets_ip = String::from(ip);
    websockets_ip.push_str(":");
    websockets_ip.push_str(&websockets_port);

    let htmltemplate = {
      match htmltemplatefile {
        Some(fname) => {
          try!(load_string(fname))
        }
        None => string_defaults::MAIN_HTML.to_string()
      }
    };

    let htmlstring = htmltemplate.replace("<websockets-port>", &websockets_port);

    // println!("{}", htmlstring);

    let guistring = try!(load_string(&guifilename[..]));
    let guival: Value = try!(serde_json::from_str(&guistring[..]));

    let blah = try!(controls::deserialize_root(&guival));

    println!("title: {} rootcontroltype: {} ",
      blah.title, blah.root_control.control_type());
    println!("controls: {:?}", blah.root_control);

    // from control tree, make a map of ids->controls.
    let mapp = controls::make_control_map(&*blah.root_control);
    let guijson = guistring.clone();

    let ci = ControlInfo { cm: mapp, guijson: guijson };

    let cmshare = Arc::new(Mutex::new(ci));
    let wscmshare = cmshare.clone();
    // let oscsocket = try!(UdpSocket::bind(&oscrecvip[..]));
    // for sending, bind to this.  if we bind to localhost, we can't
    // send messages to other machines.
    // let oscsendsocket = try!(UdpSocket::bind("0.0.0.0:0"));
    let bc = broadcaster::Broadcaster::new();
    // let wsos = try!(oscsendsocket.try_clone());
    let wsbc = bc.clone();
    // let wsoscsendip = oscsendip.clone();

    /*
    thread::spawn(move || {
      match oscmain(oscsocket, bc, cmshare) {
        Err(e) => println!("oscmain exited with error: {:?}", e),
        Ok(_) => (),
      }
      });
    */

    // Spawn a thread for the websockets handler.
    thread::spawn(move || {
      match websockets_main(websockets_ip, wscmshare, wsbc) {
        Ok(_) => (),
        Err(e) => println!("error in websockets_main: {:?}", e),
      }
    });

    thread::spawn(move || {
      // use this thread for the web server.
      Iron::new(move | _: &mut Request| {
          let content_type = "text/html".parse::<Mime>().unwrap();
          Ok(Response::with((content_type, status::Ok, &*htmlstring)))
      }).http(&http_ip[..]);
      // return when the web server dies, if it ever does.
      });

    Ok(())

}

// need to lock the control structs and stuff, refresh them, then send out the
// updates.

static mut mutie: Mutex<i32> = Mutex::default();

pub fn loadguistring(guistring: &str) -> Result<(), Box<std::error::Error> >
{
  match serde_json::from_str(guistring) {
    Ok(guival) => {
      match controls::deserialize_root(&guival) {
        Ok(controltree) => {
          println!("new control layout recieved!");

          println!("title: {} count: {} ",
            controltree.title, controltree.root_control.control_type());
          println!("controls: {:?}", controltree.root_control);

          // from control tree, make a map of ids->controls.
          let mapp = controls::make_control_map(&*controltree.root_control);
          let cnm = controls::control_map_to_name_map(&mapp);
/*
          sci.cm = mapp;
          sci.guijson = guistring.to_string();
          bc.broadcast(Message::text(guistring.to_string()));
*/
          Ok(())
        },
        Err(e) => {
          println!("error reading guiconfig from json: {:?}", e);
          let s = format!("error reading guiconfig json: {:?}", e);
          Err(Box::new(Error::new(ErrorKind::Other, s))) },
      }
    },
    Err(e) => {
      // println!("error reading guiconfig json: {:?}", e);
      let s = format!("error reading guiconfig json: {:?}", e);
      Err(Box::new(Error::new(ErrorKind::Other, s))) },
  }
}

// TODO: refactor to return a (rx/sx) pair for sending, recieving messages.
// library users start the websockets_main and get that pair of things.
// then, can send the various control structs and receive the messages.
fn websockets_main( ipaddr: String,
                    ci: Arc<Mutex<ControlInfo>>,
                    broadcaster: broadcaster::Broadcaster)
                  -> Result<(), Box<std::error::Error> >
{
	let server = try!(Server::bind(&ipaddr[..]));

	for connection in server {

    println!("new websockets connection!");
		// Spawn a new thread for each connection.

    let sci = ci.clone();
//    let osock = try!(oscsocket.try_clone());
 //   let osend = oscsendip.clone();
    let broadcaster = broadcaster.clone();

    let conn = try!(connection);
    thread::spawn(move || {
      match websockets_client(conn,
                            sci,
                            broadcaster) {
        Ok(_) => (),
        Err(e) => {
          println!("error in websockets thread: {:?}", e);
          ()
        },
      }
    });
  }

  Ok(())
}

fn websockets_client(connection: websocket::server::Connection<websocket::stream::WebSocketStream, websocket::stream::WebSocketStream>,
                    ci: Arc<Mutex<ControlInfo>>,
                    mut broadcaster: broadcaster::Broadcaster,
                    ) -> Result<(), Box<std::error::Error> >
{
  // Get the request
  let request = try!(connection.read_request());
  // Keep the headers so we can check them
  let headers = request.headers.clone();

  try!(request.validate()); // Validate the request

  let mut response = request.accept(); // Form a response

  if let Some(&WebSocketProtocol(ref protocols)) = headers.get() {
    if protocols.contains(&("rust-websocket".to_string())) {
      // We have a protocol we want to use
      response.headers.set(WebSocketProtocol(vec!["rust-websocket".to_string()]));
    }
  }

  let mut client = try!(response.send()); // Send the response

  let ip = try!(client.get_mut_sender()
                  .get_mut()
                  .peer_addr());

  println!("Websocket connection from {}", ip);

  // send up the json of the current controls.
  {
    let sci = ci.lock().unwrap();

    let updarray = controls::cm_to_update_array(&sci.cm);

    // build json message containing both guijson and the updarray.
    // let updvals = updarray.into_iter().map(|x|{controls::encode_update_message(&x)}).collect();

    let mut updvals = Vec::new();

    for upd in updarray {
      let um = controls::encode_update_message(&upd);
      updvals.push(um);
    }

    let mut guival: Value = try!(serde_json::from_str(&sci.guijson[..]));

    match guival.as_object_mut() {
      Some(obj) => {
        obj.insert("state".to_string(), Value::Array(updvals));
        ()
      },
      None => (),
    }

    let guistring = try!(serde_json::ser::to_string(&guival));
    let message = Message::text(guistring);
    try!(client.send_message(&message));
  }

  let (sender, mut receiver) = client.split();

  let sendmeh = Arc::new(Mutex::new(sender));

  broadcaster.register(sendmeh.clone());

  for msg in receiver.incoming_messages() {
    let message: Message = try!(msg);
    // println!("message: {:?}", message);

    match message.opcode {
      Type::Close => {
        let message = Message::close();
        // let mut sender = try!(sendmeh.lock());
        let mut sender = sendmeh.lock().unwrap();
        try!(sender.send_message(&message));
        println!("Client {} disconnected", ip);
        return Ok(());
      }
      Type::Ping => {
        println!("Message::Ping(data)");
        let message = Message::pong(message.payload);
        let mut sender = sendmeh.lock().unwrap();
        try!(sender.send_message(&message));
      }
      Type::Text => {
        let u8 = message.payload.to_owned();
        let str = try!(std::str::from_utf8(&*u8));
        let jsonval: Value = try!(serde_json::from_str(str));
        let s_um = controls::decode_update_message(&jsonval);
        match s_um {
          Some(updmsg) => {
            let mut sci  = ci.lock().unwrap();
            let mbcntrl = sci.cm.get_mut(controls::get_um_id(&updmsg));
            match mbcntrl {
              Some(cntrl) => {
                (*cntrl).update(&updmsg);
                broadcaster.broadcast_others(&ip, Message::text(str));

                // TODO: callback ftn??
                /*
                match ctrl_update_to_osc(&updmsg, &**cntrl) {
                  Ok(v) => match oscsocket.send_to(&v, &oscsendip[..]) {
                    Ok(_) => (),
                    Err(e) =>
                      println!("error sending osc message: {:?}", e),
                    },
                  Err(e) =>
                    println!("error building osc message: {:?}", e),
                };
                */

                println!("websockets control update recieved: {:?}", updmsg);
                ()
              },
              None => println!("none"),
            }
          },
          _ => println!("decode_update_message failed on websockets msg: {:?}", message),
        }
      },
      _ => {
        println!("unknown websockets msg: {:?}", message);
      }
    }
  }

  Ok(())
}

<|endoftext|>


<commit_before>// Copyright ⓒ 2015-2016 Kevin B. Knapp and [`clap-rs` contributors](https://github.com/clap-rs/clap/graphs/contributors).
// Licensed under the MIT license
// (see LICENSE or <http://opensource.org/licenses/MIT>) All files in the project carrying such
// notice may not be copied, modified, or distributed except according to those terms.

#![doc(html_logo_url = "https://raw.githubusercontent.com/clap-rs/clap/master/assets/clap.png")]
#![cfg_attr(feature = "unstable-doc", doc = include_str!("../README.md"))]
//! <https://github.com/clap-rs/clap>
#![warn(
    missing_docs,
    missing_debug_implementations,
    missing_copy_implementations,
    trivial_casts,
    unused_allocation,
    trivial_numeric_casts
)]
#![forbid(unsafe_code)]
// TODO: https://github.com/rust-lang/rust-clippy/issues/7290
#![allow(clippy::single_component_path_imports)]
#![allow(clippy::branches_sharing_code)]

#[cfg(not(feature = "std"))]
compile_error!("`std` feature is currently required to build `clap`");

#[cfg(feature = "color")]
pub use crate::util::color::ColorChoice;
pub use crate::{
    build::{
        App, AppFlags, AppSettings, Arg, ArgFlags, ArgGroup, ArgSettings, PossibleValue, ValueHint,
    },
    parse::errors::{Error, ErrorKind, Result},
    parse::{ArgMatches, Indices, OsValues, Values},
};

pub use crate::derive::{ArgEnum, Args, FromArgMatches, IntoApp, Parser, Subcommand};

#[cfg(feature = "yaml")]
#[doc(hidden)]
#[deprecated(
    since = "3.0.0",
    note = "Deprecated in Issue #9, maybe clap::Parser would fit your use case?"
)]
pub use yaml_rust::YamlLoader;

#[cfg(feature = "derive")]
#[doc(hidden)]
pub use clap_derive::{self, *};

/// Deprecated, replaced with [`Parser`]
#[deprecated(since = "3.0.0", note = "Replaced with `Parser`")]
pub use Parser as StructOpt;

#[cfg(any(feature = "derive", feature = "cargo"))]
#[doc(hidden)]
pub use lazy_static;

#[macro_use]
#[allow(missing_docs)]
mod macros;

mod derive;

#[cfg(feature = "regex")]
pub use crate::build::arg::RegexRef;

mod build;
mod mkeymap;
mod output;
mod parse;
mod util;

const INTERNAL_ERROR_MSG: &str = "Fatal internal error. Please consider filing a bug \
                                  report at https://github.com/clap-rs/clap/issues";
const INVALID_UTF8: &str = "unexpected invalid UTF-8 code point";

/// Deprecated, replaced with [`App`]
#[deprecated(since = "3.0.0", note = "Replaced with `App`")]
#[derive(Debug, Copy, Clone)]
pub struct SubCommand {}

#[allow(deprecated)]
impl SubCommand {
    /// Deprecated, replaced with [`App::new`]
    #[deprecated(since = "3.0.0", note = "Replaced with `App::new`")]
    pub fn with_name<'help>(name: &str) -> App<'help> {
        App::new(name)
    }

    /// Deprecated in [Issue #3087](https://github.com/clap-rs/clap/issues/3087), maybe [`clap::Parser`][crate::Parser] would fit your use case?
    #[cfg(feature = "yaml")]
    #[deprecated(
        since = "3.0.0",
        note = "Deprecated in Issue #9, maybe clap::Parser would fit your use case?"
    )]
    pub fn from_yaml(yaml: &yaml_rust::Yaml) -> App {
        #![allow(deprecated)]
        App::from_yaml(yaml)
    }
}
<commit_msg>docs: Enable lib doc in more cases<commit_after>// Copyright ⓒ 2015-2016 Kevin B. Knapp and [`clap-rs` contributors](https://github.com/clap-rs/clap/graphs/contributors).
// Licensed under the MIT license
// (see LICENSE or <http://opensource.org/licenses/MIT>) All files in the project carrying such
// notice may not be copied, modified, or distributed except according to those terms.

#![doc(html_logo_url = "https://raw.githubusercontent.com/clap-rs/clap/master/assets/clap.png")]
#![cfg_attr(feature = "derive", doc = include_str!("../README.md"))]
//! <https://github.com/clap-rs/clap>
#![warn(
    missing_docs,
    missing_debug_implementations,
    missing_copy_implementations,
    trivial_casts,
    unused_allocation,
    trivial_numeric_casts
)]
#![forbid(unsafe_code)]
// TODO: https://github.com/rust-lang/rust-clippy/issues/7290
#![allow(clippy::single_component_path_imports)]
#![allow(clippy::branches_sharing_code)]

#[cfg(not(feature = "std"))]
compile_error!("`std` feature is currently required to build `clap`");

#[cfg(feature = "color")]
pub use crate::util::color::ColorChoice;
pub use crate::{
    build::{
        App, AppFlags, AppSettings, Arg, ArgFlags, ArgGroup, ArgSettings, PossibleValue, ValueHint,
    },
    parse::errors::{Error, ErrorKind, Result},
    parse::{ArgMatches, Indices, OsValues, Values},
};

pub use crate::derive::{ArgEnum, Args, FromArgMatches, IntoApp, Parser, Subcommand};

#[cfg(feature = "yaml")]
#[doc(hidden)]
#[deprecated(
    since = "3.0.0",
    note = "Deprecated in Issue #9, maybe clap::Parser would fit your use case?"
)]
pub use yaml_rust::YamlLoader;

#[cfg(feature = "derive")]
#[doc(hidden)]
pub use clap_derive::{self, *};

/// Deprecated, replaced with [`Parser`]
#[deprecated(since = "3.0.0", note = "Replaced with `Parser`")]
pub use Parser as StructOpt;

#[cfg(any(feature = "derive", feature = "cargo"))]
#[doc(hidden)]
pub use lazy_static;

#[macro_use]
#[allow(missing_docs)]
mod macros;

mod derive;

#[cfg(feature = "regex")]
pub use crate::build::arg::RegexRef;

mod build;
mod mkeymap;
mod output;
mod parse;
mod util;

const INTERNAL_ERROR_MSG: &str = "Fatal internal error. Please consider filing a bug \
                                  report at https://github.com/clap-rs/clap/issues";
const INVALID_UTF8: &str = "unexpected invalid UTF-8 code point";

/// Deprecated, replaced with [`App`]
#[deprecated(since = "3.0.0", note = "Replaced with `App`")]
#[derive(Debug, Copy, Clone)]
pub struct SubCommand {}

#[allow(deprecated)]
impl SubCommand {
    /// Deprecated, replaced with [`App::new`]
    #[deprecated(since = "3.0.0", note = "Replaced with `App::new`")]
    pub fn with_name<'help>(name: &str) -> App<'help> {
        App::new(name)
    }

    /// Deprecated in [Issue #3087](https://github.com/clap-rs/clap/issues/3087), maybe [`clap::Parser`][crate::Parser] would fit your use case?
    #[cfg(feature = "yaml")]
    #[deprecated(
        since = "3.0.0",
        note = "Deprecated in Issue #9, maybe clap::Parser would fit your use case?"
    )]
    pub fn from_yaml(yaml: &yaml_rust::Yaml) -> App {
        #![allow(deprecated)]
        App::from_yaml(yaml)
    }
}
<|endoftext|>


<commit_before>#![allow(unstable)]
use std::io;
pub use OverwriteBehavior::{AllowOverwrite, DisallowOverwrite};

pub struct AtomicFile {
    pub path: Path,
    pub overwrite: OverwriteBehavior,
    pub tmpdir: Path
}

impl AtomicFile {
    /// Open the given file in write-only mode, if not `allow_overwrite`, errors will be returned
    /// from `do(...)` if the file exists.
    ///
    /// The temporary directory defaults to `path`, and will be used for temporary files. It must
    /// reside on the same filesystem.
    pub fn new(path: &Path, overwrite: OverwriteBehavior, tmpdir: Option<&Path>) -> AtomicFile {
        AtomicFile {
            path: path.clone(),
            overwrite: overwrite,
            tmpdir: match tmpdir {
                Some(x) => x.clone(),
                None => path.dir_path()
            }
        }
    }

    pub fn write<F: FnMut(&mut io::File) -> io::IoResult<()>>(&self, mut f: F) -> io::IoResult<()> {
        let tmpdir = try!(io::TempDir::new_in(&self.tmpdir, ".atomicwrite"));
        let tmppath = tmpdir.path().join(Path::new("tmpfile.tmp"));
        {
            let mut tmpfile = try!(io::File::create(&tmppath));
            try!(f(&mut tmpfile));
        };
        try!(self.commit(&tmppath));

        Ok(())
    }

    /// Atomically move/copy the file to self.path.
    fn commit(&self, tmppath: &Path) -> io::IoResult<()> {
        self.overwrite {
            AllowOverwrite => io::fs::rename(tmppath, &self.path),
            DisallowOverwrite => io::fs::link(tmppath, &self.path)
        }
    }
}

#[derive(Copy)]
pub enum OverwriteBehavior {
    AllowOverwrite,
    DisallowOverwrite
}
<commit_msg>syntax fix<commit_after>#![allow(unstable)]
use std::io;
pub use OverwriteBehavior::{AllowOverwrite, DisallowOverwrite};

pub struct AtomicFile {
    pub path: Path,
    pub overwrite: OverwriteBehavior,
    pub tmpdir: Path
}

impl AtomicFile {
    /// Open the given file in write-only mode, if not `allow_overwrite`, errors will be returned
    /// from `do(...)` if the file exists.
    ///
    /// The temporary directory defaults to `path`, and will be used for temporary files. It must
    /// reside on the same filesystem.
    pub fn new(path: &Path, overwrite: OverwriteBehavior, tmpdir: Option<&Path>) -> AtomicFile {
        AtomicFile {
            path: path.clone(),
            overwrite: overwrite,
            tmpdir: match tmpdir {
                Some(x) => x.clone(),
                None => path.dir_path()
            }
        }
    }

    pub fn write<F: FnMut(&mut io::File) -> io::IoResult<()>>(&self, mut f: F) -> io::IoResult<()> {
        let tmpdir = try!(io::TempDir::new_in(&self.tmpdir, ".atomicwrite"));
        let tmppath = tmpdir.path().join(Path::new("tmpfile.tmp"));
        {
            let mut tmpfile = try!(io::File::create(&tmppath));
            try!(f(&mut tmpfile));
        };
        try!(self.commit(&tmppath));

        Ok(())
    }

    /// Atomically move/copy the file to self.path.
    fn commit(&self, tmppath: &Path) -> io::IoResult<()> {
        match self.overwrite {
            AllowOverwrite => io::fs::rename(tmppath, &self.path),
            DisallowOverwrite => io::fs::link(tmppath, &self.path)
        }
    }
}

#[derive(Copy)]
pub enum OverwriteBehavior {
    AllowOverwrite,
    DisallowOverwrite
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate nom;

#[macro_use]
extern crate serde_derive;
extern crate serde;

pub use self::common::{FieldExpression, Operator, SqlType, TableKey};
pub use self::column::{Column, FunctionExpression};
pub use self::condition::{ConditionBase, ConditionExpression, ConditionTree};
pub use self::create::CreateTableStatement;
pub use self::insert::InsertStatement;
pub use self::join::{JoinConstraint, JoinOperator, JoinRightSide};
pub use self::parser::*;
pub use self::select::{SelectStatement, GroupByClause, JoinClause, LimitClause, OrderClause,
                       OrderType};
pub use self::table::Table;

pub mod parser;

#[macro_use]
mod caseless_tag;
mod keywords;
mod column;
mod common;
mod condition;
mod create;
mod insert;
mod join;
mod select;
mod table;
<commit_msg>Make `Literal` public<commit_after>#[macro_use]
extern crate nom;

#[macro_use]
extern crate serde_derive;
extern crate serde;

pub use self::common::{FieldExpression, Literal, Operator, SqlType, TableKey};
pub use self::column::{Column, FunctionExpression};
pub use self::condition::{ConditionBase, ConditionExpression, ConditionTree};
pub use self::create::CreateTableStatement;
pub use self::insert::InsertStatement;
pub use self::join::{JoinConstraint, JoinOperator, JoinRightSide};
pub use self::parser::*;
pub use self::select::{SelectStatement, GroupByClause, JoinClause, LimitClause, OrderClause,
                       OrderType};
pub use self::table::Table;

pub mod parser;

#[macro_use]
mod caseless_tag;
mod keywords;
mod column;
mod common;
mod condition;
mod create;
mod insert;
mod join;
mod select;
mod table;
<|endoftext|>


<commit_before>//! # Test CLI Applications
//!
//! This crate's goal is to provide you some very easy tools to test your CLI
//! applications. It can currently execute child processes and validate their
//! exit status as well as stdout and stderr output against your assertions.
//!
//! Include the crate like
//!
//! ```rust
//! #[macro_use] // <-- import the convenience macro (optional)
//! extern crate assert_cli;
//! # fn main() { }
//! ```
//!
//! ## Basic Examples
//!
//! Here's a trivial example:
//!
//! ```rust
//! assert_cli::Assert::command(&["echo", "42"])
//!     .succeeds()
//!     .and().prints("42")
//!     .unwrap();
//! ```
//!
//! And here is one that will fail:
//!
//! ```rust,should_panic
//! assert_cli::Assert::command(&["echo", "42"])
//!     .prints_exactly("1337")
//!     .unwrap();
//! ```
//!
//! this will show a nice, colorful diff in your terminal, like this:
//!
//! ```diff
//! -1337
//! +42
//! ```
//!
//! ## Assert CLI Crates
//!
//! If you are testing a Rust binary crate, you can start with
//! `Assert::main_binary()` to use `cargo run` as command. Or, if you want to
//! run a specific binary (if you have more than one), use
//! `Assert::cargo_binary`.
//!
//! ## `assert_cmd!` Macro
//!
//! Alternatively, you can use the `assert_cmd!` macro to construct the command more conveniently:
//!
//! ```rust
//! # #[macro_use] extern crate assert_cli;
//! # fn main() {
//! assert_cmd!(echo 42).succeeds().prints("42").unwrap();
//! # }
//! ```
//!
//! Don't forget to import the crate with `#[macro_use]`. ;-)
//!
//! ## Don't Panic!
//!
//! If you don't want it to panic when the assertions are not met, simply call
//! `.execute` instead of `.unwrap` to get a `Result`:
//!
//! ```rust
//! # #[macro_use] extern crate assert_cli;
//! # fn main() {
//! let x = assert_cmd!(echo 1337).prints_exactly("42").execute();
//! assert!(x.is_err());
//! # }
//! ```

#![deny(warnings, missing_docs)]

extern crate difference;
#[macro_use] extern crate error_chain;

use std::process::Command;

use difference::Changeset;

mod errors;
use errors::*;

mod diff;

/// Assertions for a specific command.
#[derive(Debug)]
pub struct Assert {
    cmd: Vec<String>,
    expect_success: bool,
    expect_exit_code: Option<i32>,
    expect_output: Option<String>,
    fuzzy_output: bool,
    expect_error_output: Option<String>,
    fuzzy_error_output: bool,
}

impl std::default::Default for Assert {
    /// Construct an assert using `cargo run --` as command.
    ///
    /// Defaults to asserting _successful_ execution.
    fn default() -> Self {
        Assert {
            cmd: vec!["cargo", "run", "--"]
                .into_iter().map(String::from).collect(),
            expect_success: true,
            expect_exit_code: None,
            expect_output: None,
            fuzzy_output: false,
            expect_error_output: None,
            fuzzy_error_output: false,
        }
    }
}

impl Assert {
    /// Run the crate's main binary.
    ///
    /// Defaults to asserting _successful_ execution.
    pub fn main_binary() -> Self {
        Assert::default()
    }

    /// Run a specific binary of the current crate.
    ///
    /// Defaults to asserting _successful_ execution.
    pub fn cargo_binary(name: &str) -> Self {
        Assert {
            cmd: vec!["cargo", "run", "--bin", name, "--"]
                .into_iter().map(String::from).collect(),
            ..Self::default()
        }
    }

    /// Run a custom command.
    ///
    /// Defaults to asserting _successful_ execution.
    ///
    /// # Examples
    ///
    /// ```rust
    /// extern crate assert_cli;
    ///
    /// assert_cli::Assert::command(&["echo", "1337"])
    ///     .succeeds()
    ///     .unwrap();
    /// ```
    pub fn command(cmd: &[&str]) -> Self {
        Assert {
            cmd: cmd.into_iter().cloned().map(String::from).collect(),
            ..Self::default()
        }
    }

    /// Add arguments to the command.
    ///
    /// # Examples
    ///
    /// ```rust
    /// extern crate assert_cli;
    ///
    /// assert_cli::Assert::command(&["echo"])
    ///     .with_args(&["42"])
    ///     .succeeds()
    ///     .prints("42")
    ///     .unwrap();
    /// ```
    pub fn with_args(mut self, args: &[&str]) -> Self {
        self.cmd.extend(args.into_iter().cloned().map(String::from));
        self
    }

    /// Small helper to make chains more readable.
    ///
    /// # Examples
    ///
    /// ```rust
    /// extern crate assert_cli;
    ///
    /// assert_cli::Assert::command(&["echo", "42"])
    ///     .succeeds().and().prints("42")
    ///     .unwrap();
    /// ```
    pub fn and(self) -> Self {
        self
    }

    /// Expect the command to be executed successfully.
    ///
    /// Note: This is already set by default, so you only need this for explicitness.
    ///
    /// # Examples
    ///
    /// ```rust
    /// extern crate assert_cli;
    ///
    /// assert_cli::Assert::command(&["echo", "42"])
    ///     .succeeds()
    ///     .unwrap();
    /// ```
    pub fn succeeds(mut self) -> Self {
        self.expect_success = true;
        self
    }

    /// Expect the command to fail.
    ///
    /// Note: This does not include shell failures like `command not found`. I.e. the
    ///       command must _run_ and fail for this assertion to pass.
    ///
    /// # Examples
    ///
    /// ```rust
    /// extern crate assert_cli;
    ///
    /// assert_cli::Assert::command(&["cat", "non-exisiting-file"])
    ///     .fails()
    ///     .unwrap();
    /// ```
    pub fn fails(mut self) -> Self {
        self.expect_success = false;
        self
    }

    /// Expect the command to fail and return a specific error code.
    ///
    /// # Examples
    ///
    /// ```rust
    /// extern crate assert_cli;
    ///
    /// assert_cli::Assert::command(&["cat", "non-exisiting-file"])
    ///     .fails_with(1)
    ///     .unwrap();
    /// ```
    pub fn fails_with(mut self, expect_exit_code: i32) -> Self {
        self.expect_success = false;
        self.expect_exit_code = Some(expect_exit_code);
        self
    }

    /// Expect the command's output to contain `output`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// extern crate assert_cli;
    ///
    /// assert_cli::Assert::command(&["echo", "42"])
    ///     .prints("42")
    ///     .unwrap();
    /// ```
    pub fn prints<O: Into<String>>(mut self, output: O) -> Self {
        self.expect_output = Some(output.into());
        self.fuzzy_output = true;
        self
    }

    /// Expect the command to output exactly this `output`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// extern crate assert_cli;
    ///
    /// assert_cli::Assert::command(&["echo", "42"])
    ///     .prints_exactly("42")
    ///     .unwrap();
    /// ```
    pub fn prints_exactly<O: Into<String>>(mut self, output: O) -> Self {
        self.expect_output = Some(output.into());
        self.fuzzy_output = false;
        self
    }

    /// Expect the command's stderr output to contain `output`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// extern crate assert_cli;
    ///
    /// assert_cli::Assert::command(&["cat", "non-exisiting-file"])
    ///     .fails()
    ///     .prints_error("non-exisiting-file")
    ///     .unwrap();
    /// ```
    pub fn prints_error<O: Into<String>>(mut self, output: O) -> Self {
        self.expect_error_output = Some(output.into());
        self.fuzzy_error_output = true;
        self
    }

    /// Expect the command to output exactly this `output` to stderr.
    ///
    /// # Examples
    ///
    /// ```rust
    /// extern crate assert_cli;
    ///
    /// assert_cli::Assert::command(&["cat", "non-exisiting-file"])
    ///     .fails()
    ///     .prints_error_exactly("cat: non-exisiting-file: No such file or directory")
    ///     .unwrap();
    /// ```
    pub fn prints_error_exactly<O: Into<String>>(mut self, output: O) -> Self {
        self.expect_error_output = Some(output.into());
        self.fuzzy_error_output = false;
        self
    }

    /// Execute the command and check the assertions.
    ///
    /// # Examples
    ///
    /// ```rust
    /// extern crate assert_cli;
    ///
    /// let test = assert_cli::Assert::command(&["echo", "42"])
    ///     .succeeds()
    ///     .execute();
    /// assert!(test.is_ok());
    /// ```
    pub fn execute(self) -> Result<()> {
        let cmd = &self.cmd[0];
        let args: Vec<_> = self.cmd.iter().skip(1).collect();
        let mut command = Command::new(cmd);
        let command = command.args(&args);
        let output = command.output()?;

        if self.expect_success != output.status.success() {
            bail!(ErrorKind::StatusMismatch(
                self.cmd.clone(),
                self.expect_success.clone(),
            ));
        }

        if self.expect_exit_code.is_some() &&
            self.expect_exit_code != output.status.code() {
            bail!(ErrorKind::ExitCodeMismatch(
                self.cmd.clone(),
                self.expect_exit_code,
                output.status.code(),
            ));
        }

        let stdout = String::from_utf8_lossy(&output.stdout);
        match (self.expect_output, self.fuzzy_output) {
            (Some(ref expected_output), true) if !stdout.contains(expected_output) => {
                bail!(ErrorKind::OutputMismatch(
                    self.cmd.clone(),
                    expected_output.clone(),
                    stdout.into(),
                ));
            },
            (Some(ref expected_output), false) => {
                let differences = Changeset::new(expected_output.trim(), stdout.trim(), "\n");
                if differences.distance > 0 {
                    let nice_diff = diff::render(&differences)?;
                    bail!(ErrorKind::ExactOutputMismatch(self.cmd.clone(), nice_diff));
                }
            },
            _ => {},
        }

        let stderr = String::from_utf8_lossy(&output.stderr);
        match (self.expect_error_output, self.fuzzy_error_output) {
            (Some(ref expected_output), true) if !stderr.contains(expected_output) => {
                bail!(ErrorKind::ErrorOutputMismatch(
                    self.cmd.clone(),
                    expected_output.clone(),
                    stderr.into(),
                ));
            },
            (Some(ref expected_output), false) => {
                let differences = Changeset::new(expected_output.trim(), stderr.trim(), "\n");
                if differences.distance > 0 {
                    let nice_diff = diff::render(&differences)?;
                    bail!(ErrorKind::ExactErrorOutputMismatch(self.cmd.clone(),nice_diff));
                }
            },
            _ => {},
        }

        Ok(())
    }

    /// Execute the command, check the assertions, and panic when they fail.
    ///
    /// # Examples
    ///
    /// ```rust,should_panic="Assert CLI failure"
    /// extern crate assert_cli;
    ///
    /// assert_cli::Assert::command(&["echo", "42"])
    ///     .fails()
    ///     .unwrap(); // panics
    /// ```
    pub fn unwrap(self) {
        if let Err(err) = self.execute() {
            panic!("{}", err);
        }
    }
}

/// Easily construct an `Assert` with a custom command.
///
/// Make sure to include the crate as `#[macro_use] extern crate assert_cli;` if
/// you want to use this macro.
///
/// # Examples
///
/// To test that our very complex cli applications succeeds and prints some
/// text to stdout that contains
///
/// ```plain
/// No errors whatsoever
/// ```
///
/// ...,  you would call it like this:
///
/// ```rust
/// #[macro_use] extern crate assert_cli;
/// # fn main() {
/// assert_cmd!(echo "Launch sequence initiated.\nNo errors whatsoever!\n")
///     .succeeds()
///     .prints("No errors whatsoever")
///     .unwrap();
/// # }
/// ```
///
/// The macro will try to convert its arguments as strings, but is limited by
/// Rust's default tokenizer, e.g., you always need to quote CLI arguments
/// like `"--verbose"`.
#[macro_export]
macro_rules! assert_cmd {
    ($($x:tt)+) => {{
        $crate::Assert::command(
            &[$(stringify!($x)),*]
        )
    }}
}
<commit_msg>refactor output assertion<commit_after>//! # Test CLI Applications
//!
//! This crate's goal is to provide you some very easy tools to test your CLI
//! applications. It can currently execute child processes and validate their
//! exit status as well as stdout and stderr output against your assertions.
//!
//! Include the crate like
//!
//! ```rust
//! #[macro_use] // <-- import the convenience macro (optional)
//! extern crate assert_cli;
//! # fn main() { }
//! ```
//!
//! ## Basic Examples
//!
//! Here's a trivial example:
//!
//! ```rust
//! assert_cli::Assert::command(&["echo", "42"])
//!     .succeeds()
//!     .and().prints("42")
//!     .unwrap();
//! ```
//!
//! And here is one that will fail:
//!
//! ```rust,should_panic
//! assert_cli::Assert::command(&["echo", "42"])
//!     .prints_exactly("1337")
//!     .unwrap();
//! ```
//!
//! this will show a nice, colorful diff in your terminal, like this:
//!
//! ```diff
//! -1337
//! +42
//! ```
//!
//! ## Assert CLI Crates
//!
//! If you are testing a Rust binary crate, you can start with
//! `Assert::main_binary()` to use `cargo run` as command. Or, if you want to
//! run a specific binary (if you have more than one), use
//! `Assert::cargo_binary`.
//!
//! ## `assert_cmd!` Macro
//!
//! Alternatively, you can use the `assert_cmd!` macro to construct the command more conveniently:
//!
//! ```rust
//! # #[macro_use] extern crate assert_cli;
//! # fn main() {
//! assert_cmd!(echo 42).succeeds().prints("42").unwrap();
//! # }
//! ```
//!
//! Don't forget to import the crate with `#[macro_use]`. ;-)
//!
//! ## Don't Panic!
//!
//! If you don't want it to panic when the assertions are not met, simply call
//! `.execute` instead of `.unwrap` to get a `Result`:
//!
//! ```rust
//! # #[macro_use] extern crate assert_cli;
//! # fn main() {
//! let x = assert_cmd!(echo 1337).prints_exactly("42").execute();
//! assert!(x.is_err());
//! # }
//! ```

#![deny(warnings, missing_docs)]

extern crate difference;
#[macro_use] extern crate error_chain;

use std::process::Command;

use difference::Changeset;

mod errors;
use errors::*;

mod diff;

/// Assertions for a specific command.
#[derive(Debug)]
pub struct Assert {
    cmd: Vec<String>,
    expect_success: bool,
    expect_exit_code: Option<i32>,
    expect_stdout: Option<OutputAssertion>,
    expect_stderr: Option<OutputAssertion>,
}

#[derive(Debug)]
struct OutputAssertion {
    expect: String,
    fuzzy: bool,
}

impl std::default::Default for Assert {
    /// Construct an assert using `cargo run --` as command.
    ///
    /// Defaults to asserting _successful_ execution.
    fn default() -> Self {
        Assert {
            cmd: vec!["cargo", "run", "--"]
                .into_iter().map(String::from).collect(),
            expect_success: true,
            expect_exit_code: None,
            expect_stdout: None,
            expect_stderr: None,
        }
    }
}

impl Assert {
    /// Run the crate's main binary.
    ///
    /// Defaults to asserting _successful_ execution.
    pub fn main_binary() -> Self {
        Assert::default()
    }

    /// Run a specific binary of the current crate.
    ///
    /// Defaults to asserting _successful_ execution.
    pub fn cargo_binary(name: &str) -> Self {
        Assert {
            cmd: vec!["cargo", "run", "--bin", name, "--"]
                .into_iter().map(String::from).collect(),
            ..Self::default()
        }
    }

    /// Run a custom command.
    ///
    /// Defaults to asserting _successful_ execution.
    ///
    /// # Examples
    ///
    /// ```rust
    /// extern crate assert_cli;
    ///
    /// assert_cli::Assert::command(&["echo", "1337"])
    ///     .succeeds()
    ///     .unwrap();
    /// ```
    pub fn command(cmd: &[&str]) -> Self {
        Assert {
            cmd: cmd.into_iter().cloned().map(String::from).collect(),
            ..Self::default()
        }
    }

    /// Add arguments to the command.
    ///
    /// # Examples
    ///
    /// ```rust
    /// extern crate assert_cli;
    ///
    /// assert_cli::Assert::command(&["echo"])
    ///     .with_args(&["42"])
    ///     .succeeds()
    ///     .prints("42")
    ///     .unwrap();
    /// ```
    pub fn with_args(mut self, args: &[&str]) -> Self {
        self.cmd.extend(args.into_iter().cloned().map(String::from));
        self
    }

    /// Small helper to make chains more readable.
    ///
    /// # Examples
    ///
    /// ```rust
    /// extern crate assert_cli;
    ///
    /// assert_cli::Assert::command(&["echo", "42"])
    ///     .succeeds().and().prints("42")
    ///     .unwrap();
    /// ```
    pub fn and(self) -> Self {
        self
    }

    /// Expect the command to be executed successfully.
    ///
    /// Note: This is already set by default, so you only need this for explicitness.
    ///
    /// # Examples
    ///
    /// ```rust
    /// extern crate assert_cli;
    ///
    /// assert_cli::Assert::command(&["echo", "42"])
    ///     .succeeds()
    ///     .unwrap();
    /// ```
    pub fn succeeds(mut self) -> Self {
        self.expect_success = true;
        self
    }

    /// Expect the command to fail.
    ///
    /// Note: This does not include shell failures like `command not found`. I.e. the
    ///       command must _run_ and fail for this assertion to pass.
    ///
    /// # Examples
    ///
    /// ```rust
    /// extern crate assert_cli;
    ///
    /// assert_cli::Assert::command(&["cat", "non-exisiting-file"])
    ///     .fails()
    ///     .unwrap();
    /// ```
    pub fn fails(mut self) -> Self {
        self.expect_success = false;
        self
    }

    /// Expect the command to fail and return a specific error code.
    ///
    /// # Examples
    ///
    /// ```rust
    /// extern crate assert_cli;
    ///
    /// assert_cli::Assert::command(&["cat", "non-exisiting-file"])
    ///     .fails_with(1)
    ///     .unwrap();
    /// ```
    pub fn fails_with(mut self, expect_exit_code: i32) -> Self {
        self.expect_success = false;
        self.expect_exit_code = Some(expect_exit_code);
        self
    }

    /// Expect the command's output to contain `output`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// extern crate assert_cli;
    ///
    /// assert_cli::Assert::command(&["echo", "42"])
    ///     .prints("42")
    ///     .unwrap();
    /// ```
    pub fn prints<O: Into<String>>(mut self, output: O) -> Self {
        self.expect_stdout = Some(OutputAssertion {
            expect: output.into(),
            fuzzy: true,
        });
        self
    }

    /// Expect the command to output exactly this `output`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// extern crate assert_cli;
    ///
    /// assert_cli::Assert::command(&["echo", "42"])
    ///     .prints_exactly("42")
    ///     .unwrap();
    /// ```
    pub fn prints_exactly<O: Into<String>>(mut self, output: O) -> Self {
        self.expect_stdout = Some(OutputAssertion {
            expect: output.into(),
            fuzzy: false,
        });
        self
    }

    /// Expect the command's stderr output to contain `output`.
    ///
    /// # Examples
    ///
    /// ```rust
    /// extern crate assert_cli;
    ///
    /// assert_cli::Assert::command(&["cat", "non-exisiting-file"])
    ///     .fails()
    ///     .prints_error("non-exisiting-file")
    ///     .unwrap();
    /// ```
    pub fn prints_error<O: Into<String>>(mut self, output: O) -> Self {
        self.expect_stderr = Some(OutputAssertion {
            expect: output.into(),
            fuzzy: true,
        });
        self
    }

    /// Expect the command to output exactly this `output` to stderr.
    ///
    /// # Examples
    ///
    /// ```rust
    /// extern crate assert_cli;
    ///
    /// assert_cli::Assert::command(&["cat", "non-exisiting-file"])
    ///     .fails()
    ///     .prints_error_exactly("cat: non-exisiting-file: No such file or directory")
    ///     .unwrap();
    /// ```
    pub fn prints_error_exactly<O: Into<String>>(mut self, output: O) -> Self {
        self.expect_stderr = Some(OutputAssertion {
            expect: output.into(),
            fuzzy: false,
        });
        self
    }

    /// Execute the command and check the assertions.
    ///
    /// # Examples
    ///
    /// ```rust
    /// extern crate assert_cli;
    ///
    /// let test = assert_cli::Assert::command(&["echo", "42"])
    ///     .succeeds()
    ///     .execute();
    /// assert!(test.is_ok());
    /// ```
    pub fn execute(self) -> Result<()> {
        let cmd = &self.cmd[0];
        let args: Vec<_> = self.cmd.iter().skip(1).collect();
        let mut command = Command::new(cmd);
        let command = command.args(&args);
        let output = command.output()?;

        if self.expect_success != output.status.success() {
            bail!(ErrorKind::StatusMismatch(
                self.cmd.clone(),
                self.expect_success.clone(),
            ));
        }

        if self.expect_exit_code.is_some() &&
            self.expect_exit_code != output.status.code() {
            bail!(ErrorKind::ExitCodeMismatch(
                self.cmd.clone(),
                self.expect_exit_code,
                output.status.code(),
            ));
        }

        let stdout = String::from_utf8_lossy(&output.stdout);
        match self.expect_stdout {
            Some(OutputAssertion {
                expect: ref expected_output,
                fuzzy: true,
            }) if !stdout.contains(expected_output) => {
                bail!(ErrorKind::OutputMismatch(
                    self.cmd.clone(),
                    expected_output.clone(),
                    stdout.into(),
                ));
            },
            Some(OutputAssertion {
                expect: ref expected_output,
                fuzzy: false,
            }) => {
                let differences = Changeset::new(expected_output.trim(), stdout.trim(), "\n");
                if differences.distance > 0 {
                    let nice_diff = diff::render(&differences)?;
                    bail!(ErrorKind::ExactOutputMismatch(self.cmd.clone(), nice_diff));
                }
            },
            _ => {},
        }

        let stderr = String::from_utf8_lossy(&output.stderr);
        match self.expect_stderr {
            Some(OutputAssertion {
                expect: ref expected_output,
                fuzzy: true,
            }) if !stderr.contains(expected_output) => {
                bail!(ErrorKind::ErrorOutputMismatch(
                    self.cmd.clone(),
                    expected_output.clone(),
                    stderr.into(),
                ));
            },
            Some(OutputAssertion {
                expect: ref expected_output,
                fuzzy: false,
            }) => {
                let differences = Changeset::new(expected_output.trim(), stderr.trim(), "\n");
                if differences.distance > 0 {
                    let nice_diff = diff::render(&differences)?;
                    bail!(ErrorKind::ExactErrorOutputMismatch(self.cmd.clone(),nice_diff));
                }
            },
            _ => {},
        }

        Ok(())
    }

    /// Execute the command, check the assertions, and panic when they fail.
    ///
    /// # Examples
    ///
    /// ```rust,should_panic="Assert CLI failure"
    /// extern crate assert_cli;
    ///
    /// assert_cli::Assert::command(&["echo", "42"])
    ///     .fails()
    ///     .unwrap(); // panics
    /// ```
    pub fn unwrap(self) {
        if let Err(err) = self.execute() {
            panic!("{}", err);
        }
    }
}

/// Easily construct an `Assert` with a custom command.
///
/// Make sure to include the crate as `#[macro_use] extern crate assert_cli;` if
/// you want to use this macro.
///
/// # Examples
///
/// To test that our very complex cli applications succeeds and prints some
/// text to stdout that contains
///
/// ```plain
/// No errors whatsoever
/// ```
///
/// ...,  you would call it like this:
///
/// ```rust
/// #[macro_use] extern crate assert_cli;
/// # fn main() {
/// assert_cmd!(echo "Launch sequence initiated.\nNo errors whatsoever!\n")
///     .succeeds()
///     .prints("No errors whatsoever")
///     .unwrap();
/// # }
/// ```
///
/// The macro will try to convert its arguments as strings, but is limited by
/// Rust's default tokenizer, e.g., you always need to quote CLI arguments
/// like `"--verbose"`.
#[macro_export]
macro_rules! assert_cmd {
    ($($x:tt)+) => {{
        $crate::Assert::command(
            &[$(stringify!($x)),*]
        )
    }}
}
<|endoftext|>