<commit_before>use std::collections::HashMap;

use quote::{Tokens, ToTokens};
use syn::{Body, Field, Ident, Variant, VariantData, MacroInput, Ty};
use utils::{number_idents, get_field_types};

/// Provides the hook to expand `#[derive(From)]` into an implementation of `From`
pub fn expand(input: &MacroInput, _: &str) -> Tokens {
    match input.body {
        Body::Struct(VariantData::Tuple(ref fields)) => tuple_from(input, fields),
        Body::Struct(VariantData::Struct(ref fields)) => struct_from(input, fields),
        Body::Enum(ref variants) => enum_from(input, variants),
        _ => panic!("Only tuple structs and enums can derive From"),
    }
}

pub fn from_impl<T: ToTokens>(input: &MacroInput, fields: &Vec<Field>, body: T) -> Tokens {
    let generics = &input.generics;
    let input_type = &input.ident;
    let original_types = &get_field_types(fields);
    quote!{
        impl#generics ::std::convert::From<(#(#original_types),*)> for #input_type#generics {
            fn from(original: (#(#original_types),*)) -> #input_type#generics {
                #body
            }
        }
    }
}

fn tuple_from(input: &MacroInput, fields: &Vec<Field>) -> Tokens {
    let input_type = &input.ident;
    let body = tuple_body(input_type, fields);
    from_impl(input, fields, body)
}

fn tuple_body<T: ToTokens>(return_type: T, fields: &Vec<Field>) -> Tokens {
    if fields.len() == 1 {
        quote!(#return_type(original))
    } else {
        let field_names = &number_idents(fields.len());
        quote!(#return_type(#(original.#field_names),*))
    }
}

fn struct_from(input: &MacroInput, fields: &Vec<Field>) -> Tokens {
    let input_type = &input.ident;
    let body = struct_body(input_type, fields);
    from_impl(input, fields, body)
}

fn struct_body<T: ToTokens>(return_type: T, fields: &Vec<Field>) -> Tokens {
    if fields.len() == 1 {
        let field_name = &fields[0].ident;
        quote!(#return_type{#field_name: original})
    } else {
        let argument_field_names = &number_idents(fields.len());
        let field_names: &Vec<_> = &fields.iter().map(|f| f.ident.as_ref().unwrap()).collect();
        quote!(#return_type{#(#field_names: original.#argument_field_names),*})
    }
}

fn enum_from(input: &MacroInput, variants: &Vec<Variant>) -> Tokens {
    let mut type_signature_counts = HashMap::new();
    let input_type = &input.ident;

    for variant in variants {
        match variant.data {
            VariantData::Tuple(ref fields) |
            VariantData::Struct(ref fields) => {
                let original_types = get_field_types(fields);
                let counter = type_signature_counts.entry(original_types).or_insert(0);
                *counter += 1;
            }
            _ => {}
        }
    }

    let mut tokens = Tokens::new();

    for variant in variants.iter() {
        match variant.data {

            VariantData::Tuple(ref fields) => {
                let original_types = get_field_types(fields);

                if *type_signature_counts.get(&original_types).unwrap() == 1 {
                    let variant_ident = &variant.ident;
                    let body = tuple_body(quote!(#input_type::#variant_ident), fields);
                    tokens.append(&from_impl(input, fields, body).to_string());
                }
            }

            VariantData::Struct(ref fields) => {
                let original_types = get_field_types(fields);

                if *type_signature_counts.get(&original_types).unwrap() == 1 {
                    let variant_ident = &variant.ident;
                    let body = struct_body(quote!(#input_type::#variant_ident), fields);
                    tokens.append(&from_impl(input, fields, body).to_string());
                }
            }
            _ => {}
        }
    }
    tokens
}
<commit_msg>Generics: Make from generics not fail under some conditions<commit_after>use std::collections::HashMap;

use quote::{Tokens, ToTokens};
use syn::{Body, Field, Variant, VariantData, MacroInput, Ty};
use utils::{number_idents, get_field_types};

/// Provides the hook to expand `#[derive(From)]` into an implementation of `From`
pub fn expand(input: &MacroInput, _: &str) -> Tokens {
    match input.body {
        Body::Struct(VariantData::Tuple(ref fields)) => tuple_from(input, fields),
        Body::Struct(VariantData::Struct(ref fields)) => struct_from(input, fields),
        Body::Enum(ref variants) => enum_from(input, variants),
        _ => panic!("Only tuple structs and enums can derive From"),
    }
}

pub fn from_impl<T: ToTokens>(input: &MacroInput, fields: &Vec<Field>, body: T) -> Tokens {
    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
    let input_type = &input.ident;
    let original_types = &get_field_types(fields);
    quote!{
        impl#impl_generics ::std::convert::From<(#(#original_types),*)> for #input_type#ty_generics #where_clause {
            fn from(original: (#(#original_types),*)) -> #input_type#ty_generics {
                #body
            }
        }
    }
}

fn tuple_from(input: &MacroInput, fields: &Vec<Field>) -> Tokens {
    let input_type = &input.ident;
    let body = tuple_body(input_type, fields);
    from_impl(input, fields, body)
}

fn tuple_body<T: ToTokens>(return_type: T, fields: &Vec<Field>) -> Tokens {
    if fields.len() == 1 {
        quote!(#return_type(original))
    } else {
        let field_names = &number_idents(fields.len());
        quote!(#return_type(#(original.#field_names),*))
    }
}

fn struct_from(input: &MacroInput, fields: &Vec<Field>) -> Tokens {
    let input_type = &input.ident;
    let body = struct_body(input_type, fields);
    from_impl(input, fields, body)
}

fn struct_body<T: ToTokens>(return_type: T, fields: &Vec<Field>) -> Tokens {
    if fields.len() == 1 {
        let field_name = &fields[0].ident;
        quote!(#return_type{#field_name: original})
    } else {
        let argument_field_names = &number_idents(fields.len());
        let field_names: &Vec<_> = &fields.iter().map(|f| f.ident.as_ref().unwrap()).collect();
        quote!(#return_type{#(#field_names: original.#argument_field_names),*})
    }
}

fn enum_from(input: &MacroInput, variants: &Vec<Variant>) -> Tokens {
    let mut type_signature_counts = HashMap::new();
    let input_type = &input.ident;

    for variant in variants {
        match variant.data {
            VariantData::Tuple(ref fields) |
            VariantData::Struct(ref fields) => {
                let original_types = get_field_types(fields);
                let counter = type_signature_counts.entry(original_types).or_insert(0);
                *counter += 1;
            }
            _ => {}
        }
    }

    let mut tokens = Tokens::new();

    for variant in variants.iter() {
        match variant.data {

            VariantData::Tuple(ref fields) => {
                let original_types = get_field_types(fields);

                if *type_signature_counts.get(&original_types).unwrap() == 1 {
                    let variant_ident = &variant.ident;
                    let body = tuple_body(quote!(#input_type::#variant_ident), fields);
                    tokens.append(&from_impl(input, fields, body).to_string());
                }
            }

            VariantData::Struct(ref fields) => {
                let original_types = get_field_types(fields);

                if *type_signature_counts.get(&original_types).unwrap() == 1 {
                    let variant_ident = &variant.ident;
                    let body = struct_body(quote!(#input_type::#variant_ident), fields);
                    tokens.append(&from_impl(input, fields, body).to_string());
                }
            }
            _ => {}
        }
    }
    tokens
}
<|endoftext|>


<commit_before>//! Lifting of n-ary functions.
//!
//! A lift maps a function on values to a function on signals. Given a function of
//! type `F: Fn(A, B, …) -> R` and signals of types `Signal<A>, Signal<B>, …` the
//! `lift!` macro creates a `Signal<R>`, whose content is computed using the
//! function.
//!
//! Currently lift is only implemented for functions with up to four arguments.
//! This limitation is due to the current implementation strategy (and maybe
//! limitations of Rust's type system), but it can be increased to arbitrary but
//! finite arity if required.
//!
//! # Example
//!
//! ```
//! # #[macro_use] extern crate carboxyl;
//! # fn main() {
//! # use carboxyl::Sink;
//! let sink_a = Sink::new();
//! let sink_b = Sink::new();
//! let product = lift!(
//!     |a, b| a * b,
//!     &sink_a.stream().hold(0),
//!     &sink_b.stream().hold(0)
//! );
//! assert_eq!(product.sample(), 0);
//! sink_a.send(3);
//! sink_b.send(5);
//! assert_eq!(product.sample(), 15);
//! # }
//! ```

use std::sync::Arc;
use signal::{ Signal, SignalFn, signal_build, signal_current, signal_source, reg_signal };

#[macro_export]
macro_rules! lift {
    ($f: expr)
        => ( $crate::lift::lift0($f) );

    ($f: expr, $a: expr)
        => ( $crate::lift::lift1($f, $a) );

    ($f: expr, $a: expr, $b: expr)
        => ( $crate::lift::lift2($f, $a, $b) );

    ($f: expr, $a: expr, $b: expr, $c: expr)
        => ( $crate::lift::lift3($f, $a, $b, $c) );

    ($f: expr, $a: expr, $b: expr, $c: expr, $d: expr)
        => ( $crate::lift::lift4($f, $a, $b, $c, $d) );
}

/// Lift a 0-ary function.
pub fn lift0(f: F) -> Signal
    where F: Fn() -> A + Send + Sync + 'static
{
    signal_build(SignalFn::from_fn(f), ())
}

/// Lift a unary function.
pub fn lift1(f: F, sa: &Signal) -> Signal
    where A: Send + Sync + Clone + 'static,
          B: Send + Sync + Clone + 'static,
          F: Fn(A) -> B + Send + Sync + 'static,
{
    fn make_callback(f: &Arc<F>, parent: &Signal) -> SignalFn
        where A: Send + Sync + Clone + 'static,
              B: Send + Sync + Clone + 'static,
              F: Fn(A) -> B + Send + Sync + 'static,
    {
        let pclone = parent.clone();
        let f = f.clone();
        match *signal_current(&parent).read().unwrap().future() {
            SignalFn::Const(ref a) => SignalFn::Const(f(a.clone())),
            SignalFn::Func(_) => SignalFn::from_fn(move || f(pclone.sample())),
        }
    }

    let f = Arc::new(f);
    let signal = signal_build(make_callback(&f, &sa), ());
    let sa_clone = sa.clone();
    reg_signal(&mut signal_source(&sa).write().unwrap(), &signal,
        move |_| make_callback(&f, &sa_clone));
    signal
}

/// Lift a binary function.
pub fn lift2(f: F, sa: &Signal, sb: &Signal) -> Signal<C>
    where A: Send + Sync + Clone + 'static,
          B: Send + Sync + Clone + 'static,
          C: Send + Sync + Clone + 'static,
          F: Fn(A, B) -> C + Send + Sync + 'static,
{
    fn make_callback(f: &Arc<F>, sa: &Signal, sb: &Signal) -> SignalFn<C>
        where A: Send + Sync + Clone + 'static,
              B: Send + Sync + Clone + 'static,
              C: Send + Sync + Clone + 'static,
              F: Fn(A, B) -> C + Send + Sync + 'static,
    {
        use signal::SignalFn::{ Const, Func };
        let sa_clone = sa.clone();
        let sb_clone = sb.clone();
        let f = f.clone();
        match (
            signal_current(&sa).read().unwrap().future(),
            signal_current(&sb).read().unwrap().future(),
        ) {
            (&Const(ref a), &Const(ref b)) => Const(f(a.clone(), b.clone())),
            (&Const(ref a), &Func(_)) => {
                let a = a.clone();
                SignalFn::from_fn(move || f(a.clone(), sb_clone.sample()))
            },
            (&Func(_), &Const(ref b)) => {
                let b = b.clone();
                SignalFn::from_fn(move || f(sa_clone.sample(), b.clone()))
            },
            (&Func(_), &Func(_)) => SignalFn::from_fn(
                move || f(sa_clone.sample(), sb_clone.sample())
            ),
        }
    }

    let f = Arc::new(f);
    let signal = signal_build(make_callback(&f, &sa, &sb), ());
    reg_signal(&mut signal_source(&sa).write().unwrap(), &signal, {
        let sa_clone = sa.clone();
        let sb_clone = sb.clone();
        let f = f.clone();
        move |_| make_callback(&f, &sa_clone, &sb_clone)
    });
    reg_signal(&mut signal_source(&sb).write().unwrap(), &signal, {
        let sa_clone = sa.clone();
        let sb_clone = sb.clone();
        move |_| make_callback(&f, &sa_clone, &sb_clone)
    });
    signal
}

/// Lift a ternary function.
pub fn lift3<F, A, B, C, Ret>(f: F, ca: &Signal, cb: &Signal, cc: &Signal<C>)
    -> Signal<Ret>
where F: Fn(A, B, C) -> Ret + Send + Sync + 'static,
      A: Send + Sync + Clone + 'static,
      B: Send + Sync + Clone + 'static,
      C: Send + Sync + Clone + 'static,
      Ret: Send + Sync + Clone + 'static,
{
    lift2(move |(a, b), c| f(a, b, c), &lift2(|a, b| (a, b), ca, cb), cc)
}

/// Lift a quarternary function.
pub fn lift4<F, A, B, C, D, Ret>(f: F, ca: &Signal, cb: &Signal, cc: &Signal<C>, cd: &Signal<D>)
    -> Signal<Ret>
where F: Fn(A, B, C, D) -> Ret + Send + Sync + 'static,
      A: Send + Sync + Clone + 'static,
      B: Send + Sync + Clone + 'static,
      C: Send + Sync + Clone + 'static,
      D: Send + Sync + Clone + 'static,
      Ret: Send + Sync + Clone + 'static,
{
    lift2(
        move |(a, b), (c, d)| f(a, b, c, d),
        &lift2(|a, b| (a, b), ca, cb),
        &lift2(|c, d| (c, d), cc, cd)
    )
}

#[cfg(test)]
mod test {
    use stream::Sink;
    use signal::Signal;

    #[test]
    fn lift0() {
        let signal = lift!(|| 3);
        assert_eq!(signal.sample(), 3);
    }

    #[test]
    fn lift1() {
        let sig2 = lift!(|n| n + 2, &Signal::new(3));
        assert_eq!(sig2.sample(), 5);
    }

    #[test]
    fn lift2() {
        let sink1 = Sink::new();
        let sink2 = Sink::new();
        let lifted = lift!(|a, b| a + b, &sink1.stream().hold(0),
            &sink2.stream().hold(3));
        assert_eq!(lifted.sample(), 3);
        sink1.send(1);
        assert_eq!(lifted.sample(), 4);
        sink2.send(11);
        assert_eq!(lifted.sample(), 12);
    }

    #[test]
    fn lift2_identical() {
        let sig = Signal::new(16);
        let sig2 = lift!(|a, b| a + b, &sig, &sig);
        assert_eq!(sig2.sample(), 32);
    }

    #[test]
    fn lift3() {
        let sink = Sink::new();
        assert_eq!(
            lift!(|x, y, z| x + 2 * y + z,
                &sink.stream().hold(5),
                &sink.stream().hold(3),
                &sink.stream().hold(-4)
            ).sample(),
            7
        );
    }

    #[test]
    fn lift4() {
        let sink = Sink::new();
        assert_eq!(
            lift!(|w, x, y, z| 4 * w + x + 2 * y + z,
                &sink.stream().hold(-2),
                &sink.stream().hold(5),
                &sink.stream().hold(3),
                &sink.stream().hold(-4)
            ).sample(),
            -1
        );
    }
}
<commit_msg>Wrap lifts in commit transactions<commit_after>//! Lifting of n-ary functions.
//!
//! A lift maps a function on values to a function on signals. Given a function of
//! type `F: Fn(A, B, …) -> R` and signals of types `Signal<A>, Signal<B>, …` the
//! `lift!` macro creates a `Signal<R>`, whose content is computed using the
//! function.
//!
//! Currently lift is only implemented for functions with up to four arguments.
//! This limitation is due to the current implementation strategy (and maybe
//! limitations of Rust's type system), but it can be increased to arbitrary but
//! finite arity if required.
//!
//! # Example
//!
//! ```
//! # #[macro_use] extern crate carboxyl;
//! # fn main() {
//! # use carboxyl::Sink;
//! let sink_a = Sink::new();
//! let sink_b = Sink::new();
//! let product = lift!(
//!     |a, b| a * b,
//!     &sink_a.stream().hold(0),
//!     &sink_b.stream().hold(0)
//! );
//! assert_eq!(product.sample(), 0);
//! sink_a.send(3);
//! sink_b.send(5);
//! assert_eq!(product.sample(), 15);
//! # }
//! ```

use std::sync::Arc;
use signal::{ Signal, SignalFn, signal_build, signal_current, signal_source, reg_signal };
use transaction::commit;

#[macro_export]
macro_rules! lift {
    ($f: expr)
        => ( $crate::lift::lift0($f) );

    ($f: expr, $a: expr)
        => ( $crate::lift::lift1($f, $a) );

    ($f: expr, $a: expr, $b: expr)
        => ( $crate::lift::lift2($f, $a, $b) );

    ($f: expr, $a: expr, $b: expr, $c: expr)
        => ( $crate::lift::lift3($f, $a, $b, $c) );

    ($f: expr, $a: expr, $b: expr, $c: expr, $d: expr)
        => ( $crate::lift::lift4($f, $a, $b, $c, $d) );
}

/// Lift a 0-ary function.
pub fn lift0(f: F) -> Signal
    where F: Fn() -> A + Send + Sync + 'static
{
    commit(|| signal_build(SignalFn::from_fn(f), ()))
}

/// Lift a unary function.
pub fn lift1(f: F, sa: &Signal) -> Signal
    where A: Send + Sync + Clone + 'static,
          B: Send + Sync + Clone + 'static,
          F: Fn(A) -> B + Send + Sync + 'static,
{
    fn make_callback(f: &Arc<F>, parent: &Signal) -> SignalFn
        where A: Send + Sync + Clone + 'static,
              B: Send + Sync + Clone + 'static,
              F: Fn(A) -> B + Send + Sync + 'static,
    {
        let pclone = parent.clone();
        let f = f.clone();
        match *signal_current(&parent).read().unwrap().future() {
            SignalFn::Const(ref a) => SignalFn::Const(f(a.clone())),
            SignalFn::Func(_) => SignalFn::from_fn(move || f(pclone.sample())),
        }
    }

    commit(|| {
        let f = Arc::new(f);
        let signal = signal_build(make_callback(&f, &sa), ());
        let sa_clone = sa.clone();
        reg_signal(&mut signal_source(&sa).write().unwrap(), &signal,
            move |_| make_callback(&f, &sa_clone));
        signal
    })
}

/// Lift a binary function.
pub fn lift2(f: F, sa: &Signal, sb: &Signal) -> Signal<C>
    where A: Send + Sync + Clone + 'static,
          B: Send + Sync + Clone + 'static,
          C: Send + Sync + Clone + 'static,
          F: Fn(A, B) -> C + Send + Sync + 'static,
{
    fn make_callback(f: &Arc<F>, sa: &Signal, sb: &Signal) -> SignalFn<C>
        where A: Send + Sync + Clone + 'static,
              B: Send + Sync + Clone + 'static,
              C: Send + Sync + Clone + 'static,
              F: Fn(A, B) -> C + Send + Sync + 'static,
    {
        use signal::SignalFn::{ Const, Func };
        let sa_clone = sa.clone();
        let sb_clone = sb.clone();
        let f = f.clone();
        match (
            signal_current(&sa).read().unwrap().future(),
            signal_current(&sb).read().unwrap().future(),
        ) {
            (&Const(ref a), &Const(ref b)) => Const(f(a.clone(), b.clone())),
            (&Const(ref a), &Func(_)) => {
                let a = a.clone();
                SignalFn::from_fn(move || f(a.clone(), sb_clone.sample()))
            },
            (&Func(_), &Const(ref b)) => {
                let b = b.clone();
                SignalFn::from_fn(move || f(sa_clone.sample(), b.clone()))
            },
            (&Func(_), &Func(_)) => SignalFn::from_fn(
                move || f(sa_clone.sample(), sb_clone.sample())
            ),
        }
    }

    commit(move || {
        let f = Arc::new(f);
        let signal = signal_build(make_callback(&f, &sa, &sb), ());
        reg_signal(&mut signal_source(&sa).write().unwrap(), &signal, {
            let sa_clone = sa.clone();
            let sb_clone = sb.clone();
            let f = f.clone();
            move |_| make_callback(&f, &sa_clone, &sb_clone)
        });
        reg_signal(&mut signal_source(&sb).write().unwrap(), &signal, {
            let sa_clone = sa.clone();
            let sb_clone = sb.clone();
            move |_| make_callback(&f, &sa_clone, &sb_clone)
        });
        signal
    })
}

/// Lift a ternary function.
pub fn lift3<F, A, B, C, Ret>(f: F, ca: &Signal, cb: &Signal, cc: &Signal<C>)
    -> Signal<Ret>
where F: Fn(A, B, C) -> Ret + Send + Sync + 'static,
      A: Send + Sync + Clone + 'static,
      B: Send + Sync + Clone + 'static,
      C: Send + Sync + Clone + 'static,
      Ret: Send + Sync + Clone + 'static,
{
    lift2(move |(a, b), c| f(a, b, c), &lift2(|a, b| (a, b), ca, cb), cc)
}

/// Lift a quarternary function.
pub fn lift4<F, A, B, C, D, Ret>(f: F, ca: &Signal, cb: &Signal, cc: &Signal<C>, cd: &Signal<D>)
    -> Signal<Ret>
where F: Fn(A, B, C, D) -> Ret + Send + Sync + 'static,
      A: Send + Sync + Clone + 'static,
      B: Send + Sync + Clone + 'static,
      C: Send + Sync + Clone + 'static,
      D: Send + Sync + Clone + 'static,
      Ret: Send + Sync + Clone + 'static,
{
    lift2(
        move |(a, b), (c, d)| f(a, b, c, d),
        &lift2(|a, b| (a, b), ca, cb),
        &lift2(|c, d| (c, d), cc, cd)
    )
}

#[cfg(test)]
mod test {
    use stream::Sink;
    use signal::Signal;

    #[test]
    fn lift0() {
        let signal = lift!(|| 3);
        assert_eq!(signal.sample(), 3);
    }

    #[test]
    fn lift1() {
        let sig2 = lift!(|n| n + 2, &Signal::new(3));
        assert_eq!(sig2.sample(), 5);
    }

    #[test]
    fn lift2() {
        let sink1 = Sink::new();
        let sink2 = Sink::new();
        let lifted = lift!(|a, b| a + b, &sink1.stream().hold(0),
            &sink2.stream().hold(3));
        assert_eq!(lifted.sample(), 3);
        sink1.send(1);
        assert_eq!(lifted.sample(), 4);
        sink2.send(11);
        assert_eq!(lifted.sample(), 12);
    }

    #[test]
    fn lift2_identical() {
        let sig = Signal::new(16);
        let sig2 = lift!(|a, b| a + b, &sig, &sig);
        assert_eq!(sig2.sample(), 32);
    }

    #[test]
    fn lift3() {
        let sink = Sink::new();
        assert_eq!(
            lift!(|x, y, z| x + 2 * y + z,
                &sink.stream().hold(5),
                &sink.stream().hold(3),
                &sink.stream().hold(-4)
            ).sample(),
            7
        );
    }

    #[test]
    fn lift4() {
        let sink = Sink::new();
        assert_eq!(
            lift!(|w, x, y, z| 4 * w + x + 2 * y + z,
                &sink.stream().hold(-2),
                &sink.stream().hold(5),
                &sink.stream().hold(3),
                &sink.stream().hold(-4)
            ).sample(),
            -1
        );
    }
}
<|endoftext|>


<commit_before>use af;
use af::Array;

use utils;
use error::HALError;

/// Return a vector form of the l2 error
/// (y - x) * (y - x)
pub fn l2_vec(pred: &Array, target: &Array) -> Array{
  let diff = af::sub(pred, target, false);
  af::mul(&diff, &diff, false)
}

/// Return a vector form of the mean squared error
/// 0.5 * (y - x) * (y - x)
pub fn mse_vec(pred: &Array, target: &Array) -> Array {
  af::mul(&l2_vec(pred, target), &0.5f32, false)
}

/// Return a vector form of cross entropy
/// -ylnx - [1-y]ln[1-x]
pub fn cross_entropy_vec(pred: &Array, target: &Array) -> Array {
  // -yln x
  let pos = af::mul(&af::mul(&-1.0f32, target, false)
                    , &af::log(&utils::clip_by_value(pred, 0.0, 1.0)), false);
  //[1-y]ln[1-x]
  let neg = af::mul(&af::sub(&1.0f32, target, false)
                    , &af::log(&utils::clip_by_value(&af::sub(&1.0f32
                                                              , pred
                                                              , false)
                                                     , 0.0, 1.0)), false);
  af::sub(&pos, &neg, false)
}

/// Provide a reduced form the L2 loss (single scalar)
pub fn l2(pred: &Array, target: &Array) -> f32 {
  af::sum_all(&l2_vec(pred, target)).0 as f32
}

/// Provide a reduced form the mean squared error loss (single scalar)
pub fn mse(pred: &Array, target: &Array) -> f32 {
  0.5f32 * af::mean_all(&l2_vec(pred, target)).0 as f32
}

/// Provide a reduced form the cross-entropy loss (single scalar)
pub fn cross_entropy(pred: &Array, target: &Array) -> f32 {
  // y: true target, x: prediction
  // E = sum(-ylnx - [1-y]ln[1-x])
  af::sum_all(&cross_entropy_vec(pred, target)).0 as f32
}

/// Provides the vector derivative of the mean squared error
pub fn mse_derivative(pred: &Array, target: &Array) -> Array {
  af::sub(pred, target, false)
}
/// Provides the vector derivative of the l2 error
pub fn l2_derivative(pred: &Array, target: &Array) -> Array {
  af::mul(&mse_derivative(pred, target), &2.0f32, false)
}

/// Provides the vector derivative of the cross-entropy error
pub fn cross_entropy_derivative(pred: &Array, target: &Array) -> Array {
  mse_derivative(pred, target)
}

/// Helper to provide a loss from a string
pub fn get_loss(name: &str, pred: &Array, target: &Array) -> Result<f32, HALError> {
  match name {
    "l2"            => Ok(l2(pred, target)),
    "mse"           => Ok(mse(pred, target)),
    "cross_entropy" => Ok(cross_entropy(pred, target)),
    _               => Err(HALError::UNKNOWN),
  }
}

/// Helper to provide a loss vector from a string
pub fn get_loss_vec(name: &str, pred: &Array, target: &Array) -> Result<Array, HALError> {
  match name {
    "l2"            => Ok(l2_vec(pred, target)),
    "mse"           => Ok(mse_vec(pred, target)),
    "cross_entropy" => Ok(cross_entropy_vec(pred, target)),
    _               => Err(HALError::UNKNOWN),
  }
}

/// Helper to provide a loss derivative from a string
pub fn get_loss_derivative(name: &str, pred: &Array, target: &Array) -> Result<Array, HALError> {
  match name {
    "l2"            => Ok(l2_derivative(pred, target)),
    "mse"           => Ok(mse_derivative(pred, target)),
    "cross_entropy" => Ok(cross_entropy_derivative(pred, target)),
    _               => Err(HALError::UNKNOWN),
  }
}
<commit_msg>clip to 1e-10 instead of 0<commit_after>use af;
use af::Array;

use utils;
use error::HALError;

/// Return a vector form of the l2 error
/// (y - x) * (y - x)
pub fn l2_vec(pred: &Array, target: &Array) -> Array{
  let diff = af::sub(pred, target, false);
  af::mul(&diff, &diff, false)
}

/// Return a vector form of the mean squared error
/// 0.5 * (y - x) * (y - x)
pub fn mse_vec(pred: &Array, target: &Array) -> Array {
  af::mul(&l2_vec(pred, target), &0.5f32, false)
}

/// Return a vector form of cross entropy
/// -ylnx - [1-y]ln[1-x]
pub fn cross_entropy_vec(pred: &Array, target: &Array) -> Array {
  // -yln x
  let pos = af::mul(&af::mul(&-1.0f32, target, false)
                    , &af::log(&utils::clip_by_value(pred, 1e-10, 1.0)), false);
  //[1-y]ln[1-x]
  let neg = af::mul(&af::sub(&1.0f32, target, false)
                    , &af::log(&utils::clip_by_value(&af::sub(&1.0f32
                                                              , pred
                                                              , false)
                                                     , 1e-10, 1.0)), false);
  af::sub(&pos, &neg, false)
}

/// Provide a reduced form the L2 loss (single scalar)
pub fn l2(pred: &Array, target: &Array) -> f32 {
  af::sum_all(&l2_vec(pred, target)).0 as f32
}

/// Provide a reduced form the mean squared error loss (single scalar)
pub fn mse(pred: &Array, target: &Array) -> f32 {
  0.5f32 * af::mean_all(&l2_vec(pred, target)).0 as f32
}

/// Provide a reduced form the cross-entropy loss (single scalar)
pub fn cross_entropy(pred: &Array, target: &Array) -> f32 {
  // y: true target, x: prediction
  // E = sum(-ylnx - [1-y]ln[1-x])
  af::sum_all(&cross_entropy_vec(pred, target)).0 as f32
}

/// Provides the vector derivative of the mean squared error
pub fn mse_derivative(pred: &Array, target: &Array) -> Array {
  af::sub(pred, target, false)
}
/// Provides the vector derivative of the l2 error
pub fn l2_derivative(pred: &Array, target: &Array) -> Array {
  af::mul(&mse_derivative(pred, target), &2.0f32, false)
}

/// Provides the vector derivative of the cross-entropy error
pub fn cross_entropy_derivative(pred: &Array, target: &Array) -> Array {
  mse_derivative(pred, target)
}

/// Helper to provide a loss from a string
pub fn get_loss(name: &str, pred: &Array, target: &Array) -> Result<f32, HALError> {
  match name {
    "l2"            => Ok(l2(pred, target)),
    "mse"           => Ok(mse(pred, target)),
    "cross_entropy" => Ok(cross_entropy(pred, target)),
    _               => Err(HALError::UNKNOWN),
  }
}

/// Helper to provide a loss vector from a string
pub fn get_loss_vec(name: &str, pred: &Array, target: &Array) -> Result<Array, HALError> {
  match name {
    "l2"            => Ok(l2_vec(pred, target)),
    "mse"           => Ok(mse_vec(pred, target)),
    "cross_entropy" => Ok(cross_entropy_vec(pred, target)),
    _               => Err(HALError::UNKNOWN),
  }
}

/// Helper to provide a loss derivative from a string
pub fn get_loss_derivative(name: &str, pred: &Array, target: &Array) -> Result<Array, HALError> {
  match name {
    "l2"            => Ok(l2_derivative(pred, target)),
    "mse"           => Ok(mse_derivative(pred, target)),
    "cross_entropy" => Ok(cross_entropy_derivative(pred, target)),
    _               => Err(HALError::UNKNOWN),
  }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate log;
#[macro_use]
extern crate nom;

extern crate bip_bencode;
extern crate bip_metainfo;
extern crate bip_utracker;
extern crate chrono;
extern crate hyper;
extern crate pnet;
extern crate pnet_macros_support;
extern crate pretty_env_logger;
extern crate rustyline;
extern crate url;

mod packet;

use bip_bencode::Bencode;
use bip_metainfo::MetainfoFile;
use bip_utracker::contact::CompactPeersV4;
use chrono::{TimeZone, UTC};
use hyper::Client;
use hyper::header::Connection;
use packet::peer_pkt::MutablePeerHandshakePacket;
use pnet::packet::Packet;
use rustyline::Editor;
use rustyline::error::ReadlineError;
use url::Url;

use std::fs::File;
use std::io::prelude::*;
use std::net::TcpStream;
use std::str;
use std::string::String;
use std::time::{SystemTime, UNIX_EPOCH};

const HISTORY_FILE: &'static str = ".rustyline.history";
const PEER_HANDSHAKE_STRUCT_SZ: usize = 68;

/// Print general information about the torrent.
fn print_metainfo_overview(bytes: &[u8]) {
    let metainfo = MetainfoFile::from_bytes(bytes).unwrap();
    let info = metainfo.info();
    let info_hash_hex = metainfo.info_hash()
        .as_ref()
        .iter()
        .map(|b| format!("{:02X}", b))
        .fold(String::new(), |mut acc, nex| {
            acc.push_str(&nex);
            acc
        });
    let utc_creation_date = metainfo.creation_date().map(|c| UTC.timestamp(c, 0));

    println!("------Metainfo File Overview-----");

    println!("InfoHash: {}", info_hash_hex);
    println!("Main Tracker: {:?}", metainfo.main_tracker());
    println!("Comment: {:?}", metainfo.comment());
    println!("Creator: {:?}", metainfo.created_by());
    println!("Creation Date: {:?}", utc_creation_date);

    println!("Directory: {:?}", info.directory());
    println!("Piece Length: {:?}", info.piece_length());
    println!("Number Of Pieces: {}", info.pieces().count());
    println!("Number Of Files: {}", info.files().count());
    println!("Total File Size: {}",
             info.files().fold(0, |acc, nex| acc + nex.length()));
}

fn connect_to_tracker(metainfo_file: MetainfoFile,
                      peer_id: &str,
                      port: u16)
                      -> Result<(Vec<String>, String), String> {
    debug!("connecting to tracker: {:?}", metainfo_file.main_tracker());
    let info_hash = metainfo_file.info_hash();
    // TODO figure can this conversion to url-encoded form be done safely?
    let info_hash_str = unsafe { str::from_utf8_unchecked(info_hash.as_ref()) };
    // TODO this needs to be calculated based on what we have
    let total_len = metainfo_file.info().files().fold(0, |acc, nex| acc + nex.length());

    let mut url = Url::parse(metainfo_file.main_tracker().unwrap()).unwrap();
    url.query_pairs_mut()
        .append_pair("info_hash", info_hash_str)
        .append_pair("peer_id", peer_id)
        .append_pair("port", &(port.to_string()))
        // TODO parametrize this
        .append_pair("uploaded", "0")
        // TODO parametrize this
        .append_pair("downloaded", "0")
        // TODO see note on total_len above
        .append_pair("left", &(total_len.to_string()))
        .append_pair("compact", "1")
        .append_pair("event", "started")
        .append_pair("supportcrypto", "0");
    debug!("URL {:?}", url);

    let client = Client::new();
    let mut res = client.get(url).header(Connection::close()).send().unwrap();
    let mut buffer = Vec::new();
    res.read_to_end(&mut buffer).unwrap();
    debug!("Resp {:?}", res);
    let bencode = Bencode::decode(&buffer).unwrap();
    debug!("{:?}", bencode);
    let (_, peers) = CompactPeersV4::from_bytes(bencode.dict()
            .unwrap()
            .lookup("peers")
            .unwrap()
            .bytes()
            .unwrap())
        .unwrap();
    debug!("{:?}", peers);
    let mut ip_ports: Vec<String> = Vec::new();
    for peer in peers.iter() {
        debug!("{:?}", peer);
        ip_ports.push(peer.to_string());
    }
    Ok((ip_ports, info_hash_str.to_string()))
}

fn handshake_peer(peer_ip_port: &str, info_hash: &str, peer_id: &str) -> Result<(), String> {
    let mut buf = vec![0u8; PEER_HANDSHAKE_STRUCT_SZ];
    let mut ph = MutablePeerHandshakePacket::new(&mut buf).unwrap();
    ph.set_pstrlen("BitTorrent protocol".len() as u8);
    ph.set_pstr(&String::from("BitTorrent protocol").into_bytes());
    ph.set_reserved(&[0; 8]);
    ph.set_info_hash(info_hash.as_bytes());
    ph.set_peer_id(peer_id.as_bytes());
    debug!("Size of the peer handshake struct: {:?}", ph.packet().len());
    match TcpStream::connect(peer_ip_port) {
        Ok(mut stream) => {
            debug!("Connection to peer {:?} successful!", peer_ip_port);
            match stream.write(ph.packet()) {
                Ok(_) => {
                    debug!("Sending message successful!");
                    Ok(())
                }
                Err(_) => {
                    error!("Sending message failed!");
                    Err("Sending message failed!".to_owned())
                }
            }
        }
        Err(e) => {
            error!("Connection to peer {:?} failed! {:?}", peer_ip_port, e);
            Err("Connection to peer failed!".to_owned())
        }
    }

}

fn main() {
    pretty_env_logger::init();

    let mut rl = Editor::<()>::new();
    if rl.load_history(HISTORY_FILE).is_err() {
        info!("No previous history!");
    }

    let now = SystemTime::now();
    let duration = now.duration_since(UNIX_EPOCH).unwrap();
    let client_id = "-bittorrent-rs-".to_owned() + &format!("{}", duration.as_secs() % 100_000);

    loop {
        let readline = rl.readline("> ");
        match readline {
            Ok(cmd) => {
                rl.add_history_entry(&cmd);

                let cmd = cmd.trim().split(' ').collect::<Vec<&str>>();

                match cmd[0] {
                    "parse" => {
                        if cmd.len() != 2 {
                            error!("usage: parse <torrent file>");
                        } else {
                            let path = cmd[1];
                            debug!("MetainfoFile: {:?}", path);

                            match File::open(path) {
                                Ok(mut f) => {
                                    let mut bytes: Vec<u8> = Vec::new();
                                    f.read_to_end(&mut bytes).unwrap();
                                    print_metainfo_overview(&bytes);
                                }
                                Err(e) => error!("{:?}", e),
                            }
                        }
                    }
                    "connect" => {
                        if cmd.len() != 2 {
                            error!("usage: connect <torrent file>");
                        } else {
                            let path = cmd[1];
                            match File::open(path) {
                                Ok(mut f) => {
                                    let mut bytes: Vec<u8> = Vec::new();
                                    f.read_to_end(&mut bytes).unwrap();

                                    // TODO: generate peer ID
                                    let result =
                                        connect_to_tracker(MetainfoFile::from_bytes(&bytes)
                                                               .unwrap(),
                                                           &client_id,
                                                           6882)
                                            .unwrap();
                                    for peer_ip_port in result.0 {
                                        handshake_peer(&peer_ip_port, &result.1, &client_id)
                                            .unwrap();
                                    }
                                }
                                Err(e) => error!("{:?}", e),
                            }
                        }
                    }
                    _ => {}
                }
            }
            Err(ReadlineError::Interrupted) |
            Err(ReadlineError::Eof) => {
                break;
            }
            Err(err) => {
                error!("Error: {:?}", err);
                break;
            }
        }
    }
    rl.save_history(HISTORY_FILE).unwrap();
}
<commit_msg>Tracing cleanup<commit_after>#[macro_use]
extern crate log;
#[macro_use]
extern crate nom;

extern crate bip_bencode;
extern crate bip_metainfo;
extern crate bip_utracker;
extern crate chrono;
extern crate hyper;
extern crate pnet;
extern crate pnet_macros_support;
extern crate pretty_env_logger;
extern crate rustyline;
extern crate url;

mod packet;

use bip_bencode::Bencode;
use bip_metainfo::MetainfoFile;
use bip_utracker::contact::CompactPeersV4;
use chrono::{TimeZone, UTC};
use hyper::Client;
use hyper::header::Connection;
use packet::peer_pkt::MutablePeerHandshakePacket;
use pnet::packet::Packet;
use rustyline::Editor;
use rustyline::error::ReadlineError;
use url::Url;

use std::fs::File;
use std::io::prelude::*;
use std::net::TcpStream;
use std::str;
use std::string::String;
use std::time::{SystemTime, UNIX_EPOCH};

const HISTORY_FILE: &'static str = ".rustyline.history";
const PEER_HANDSHAKE_STRUCT_SZ: usize = 68;

/// Print general information about the torrent.
fn print_metainfo_overview(bytes: &[u8]) {
    let metainfo = MetainfoFile::from_bytes(bytes).unwrap();
    let info = metainfo.info();
    let info_hash_hex = metainfo.info_hash()
        .as_ref()
        .iter()
        .map(|b| format!("{:02X}", b))
        .fold(String::new(), |mut acc, nex| {
            acc.push_str(&nex);
            acc
        });
    let utc_creation_date = metainfo.creation_date().map(|c| UTC.timestamp(c, 0));

    println!("------Metainfo File Overview-----");

    println!("InfoHash: {}", info_hash_hex);
    println!("Main Tracker: {:?}", metainfo.main_tracker());
    println!("Comment: {:?}", metainfo.comment());
    println!("Creator: {:?}", metainfo.created_by());
    println!("Creation Date: {:?}", utc_creation_date);

    println!("Directory: {:?}", info.directory());
    println!("Piece Length: {:?}", info.piece_length());
    println!("Number Of Pieces: {}", info.pieces().count());
    println!("Number Of Files: {}", info.files().count());
    println!("Total File Size: {}",
             info.files().fold(0, |acc, nex| acc + nex.length()));
}

fn connect_to_tracker(metainfo_file: MetainfoFile,
                      peer_id: &str,
                      port: u16)
                      -> Result<(Vec<String>, String), String> {
    debug!("connecting to tracker: {:?}", metainfo_file.main_tracker());
    let info_hash = metainfo_file.info_hash();
    // TODO figure can this conversion to url-encoded form be done safely?
    let info_hash_str = unsafe { str::from_utf8_unchecked(info_hash.as_ref()) };
    // TODO this needs to be calculated based on what we have
    let total_len = metainfo_file.info().files().fold(0, |acc, nex| acc + nex.length());

    let mut url = Url::parse(metainfo_file.main_tracker().unwrap()).unwrap();
    url.query_pairs_mut()
        .append_pair("info_hash", info_hash_str)
        .append_pair("peer_id", peer_id)
        .append_pair("port", &(port.to_string()))
        // TODO parametrize this
        .append_pair("uploaded", "0")
        // TODO parametrize this
        .append_pair("downloaded", "0")
        // TODO see note on total_len above
        .append_pair("left", &(total_len.to_string()))
        .append_pair("compact", "1")
        .append_pair("event", "started")
        .append_pair("supportcrypto", "0");
    trace!("URL {:?}", url);

    let client = Client::new();
    let mut res = client.get(url).header(Connection::close()).send().unwrap();
    let mut buffer = Vec::new();
    res.read_to_end(&mut buffer).unwrap();
    debug!("{:?}", res);
    let bencode = Bencode::decode(&buffer).unwrap();
    trace!("{:?}", bencode);
    let (_, peers) = CompactPeersV4::from_bytes(bencode.dict()
            .unwrap()
            .lookup("peers")
            .unwrap()
            .bytes()
            .unwrap())
        .unwrap();
    trace!("{:?}", peers);
    let mut ip_ports: Vec<String> = Vec::new();
    for peer in peers.iter() {
        debug!("{:?}", peer);
        ip_ports.push(peer.to_string());
    }
    Ok((ip_ports, info_hash_str.to_string()))
}

fn handshake_peer(peer_ip_port: &str, info_hash: &str, peer_id: &str) -> Result<(), String> {
    let mut buf = vec![0u8; PEER_HANDSHAKE_STRUCT_SZ];
    let mut ph = MutablePeerHandshakePacket::new(&mut buf).unwrap();
    ph.set_pstrlen("BitTorrent protocol".len() as u8);
    ph.set_pstr(&String::from("BitTorrent protocol").into_bytes());
    ph.set_reserved(&[0; 8]);
    ph.set_info_hash(info_hash.as_bytes());
    ph.set_peer_id(peer_id.as_bytes());
    match TcpStream::connect(peer_ip_port) {
        Ok(mut stream) => {
            debug!("Connection to peer {:?} successful!", peer_ip_port);
            match stream.write(ph.packet()) {
                Ok(_) => {
                    debug!("Sending message successful!");
                    Ok(())
                }
                Err(_) => {
                    error!("Sending message failed!");
                    Err("Sending message failed!".to_owned())
                }
            }
        }
        Err(e) => {
            error!("Connection to peer {:?} failed! {:?}", peer_ip_port, e);
            Err("Connection to peer failed!".to_owned())
        }
    }
}

fn main() {
    pretty_env_logger::init();

    let mut rl = Editor::<()>::new();
    if rl.load_history(HISTORY_FILE).is_err() {
        info!("No previous history!");
    }

    let now = SystemTime::now();
    let duration = now.duration_since(UNIX_EPOCH).unwrap();
    let client_id = "-bittorrent-rs-".to_owned() + &format!("{}", duration.as_secs() % 100_000);

    loop {
        let readline = rl.readline("> ");
        match readline {
            Ok(cmd) => {
                rl.add_history_entry(&cmd);

                let cmd = cmd.trim().split(' ').collect::<Vec<&str>>();

                match cmd[0] {
                    "parse" => {
                        if cmd.len() != 2 {
                            error!("usage: parse <torrent file>");
                        } else {
                            let path = cmd[1];
                            debug!("MetainfoFile: {:?}", path);

                            match File::open(path) {
                                Ok(mut f) => {
                                    let mut bytes: Vec<u8> = Vec::new();
                                    f.read_to_end(&mut bytes).unwrap();
                                    print_metainfo_overview(&bytes);
                                }
                                Err(e) => error!("{:?}", e),
                            }
                        }
                    }
                    "connect" => {
                        if cmd.len() != 2 {
                            error!("usage: connect <torrent file>");
                        } else {
                            let path = cmd[1];
                            match File::open(path) {
                                Ok(mut f) => {
                                    let mut bytes: Vec<u8> = Vec::new();
                                    f.read_to_end(&mut bytes).unwrap();

                                    // TODO: generate peer ID
                                    let result =
                                        connect_to_tracker(MetainfoFile::from_bytes(&bytes)
                                                               .unwrap(),
                                                           &client_id,
                                                           6882)
                                            .unwrap();
                                    for peer_ip_port in result.0 {
                                        handshake_peer(&peer_ip_port, &result.1, &client_id)
                                            .unwrap();
                                    }
                                }
                                Err(e) => error!("{:?}", e),
                            }
                        }
                    }
                    _ => {}
                }
            }
            Err(ReadlineError::Interrupted) |
            Err(ReadlineError::Eof) => {
                break;
            }
            Err(err) => {
                error!("Error: {:?}", err);
                break;
            }
        }
    }
    rl.save_history(HISTORY_FILE).unwrap();
}
<|endoftext|>


<commit_before>//! Parser main file

use std::env;
use std::process;
use std::io::stderr;
use std::io::Write;

enum Token {
    Digit{character: char},
    Plus,
    Minus,
    Unknown
}

/// Lexical analyze of one character and return a token for parsing.
///
/// # Arguments:
///
/// * `character` - character to check
fn get_token_from_character(character: char) -> Token {

    match character {
        '0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9' =>
            Token::Digit{character: character},
        '+' => Token::Plus,
        '-' => Token::Minus,
        _ => Token::Unknown
    }
}

fn main() {

    let args: Vec<_> = env::args().collect();

    if args.len() != 2 {
        writeln!(&mut stderr(), "No input.").unwrap();
        process::exit(1);
    }

    let mut output = String::from(
r#"
bits 64

segment .text
    global _start

_start:
"#
    );

    let mut previous: Vec<Token> = Vec::new();

    for character in args[1].chars() {
        let token: Token = get_token_from_character(character);

        match token {
            Token::Digit{character} => {
                output.push_str("mov eax, ");
                output.push(character);
                output.push('\n');

                // TODO: won't work with numbers, must be improved
                match previous.last() {
                    Some(symbol) => {
                        match *symbol {
                            Token::Plus => {
                                output.push_str("add eax, ebx\n");
                            }
                            Token::Minus => {
                                output.push_str("sub eax, ebx\n");
                            }
                            _ => {}
                        }
                    }
                    None => {}
                }
            }
            Token::Plus | Token::Minus => {
                output.push_str("mov ebx, eax\n");
            }
            _ => {}
        }

        previous.push(token);
    }

    output +=
r#"
mov eax, 1
int 0x80
"#;

    print!("{}", output);
}
<commit_msg>remove useless indentation from the generated assembly, global simply means that _start can be called from the outside of the module/file/compilation unit<commit_after>//! Parser main file

use std::env;
use std::process;
use std::io::stderr;
use std::io::Write;

enum Token {
    Digit{character: char},
    Plus,
    Minus,
    Unknown
}

/// Lexical analyze of one character and return a token for parsing.
///
/// # Arguments:
///
/// * `character` - character to check
fn get_token_from_character(character: char) -> Token {

    match character {
        '0'|'1'|'2'|'3'|'4'|'5'|'6'|'7'|'8'|'9' =>
            Token::Digit{character: character},
        '+' => Token::Plus,
        '-' => Token::Minus,
        _ => Token::Unknown
    }
}

fn main() {

    let args: Vec<_> = env::args().collect();

    if args.len() != 2 {
        writeln!(&mut stderr(), "No input.").unwrap();
        process::exit(1);
    }

    let mut output = String::from(
r#"
bits 64

segment .text
global _start

_start:
"#
    );

    let mut previous: Vec<Token> = Vec::new();

    for character in args[1].chars() {
        let token: Token = get_token_from_character(character);

        match token {
            Token::Digit{character} => {
                output.push_str("mov eax, ");
                output.push(character);
                output.push('\n');

                // TODO: won't work with numbers, must be improved
                match previous.last() {
                    Some(symbol) => {
                        match *symbol {
                            Token::Plus => {
                                output.push_str("add eax, ebx\n");
                            }
                            Token::Minus => {
                                output.push_str("sub eax, ebx\n");
                            }
                            _ => {}
                        }
                    }
                    None => {}
                }
            }
            Token::Plus | Token::Minus => {
                output.push_str("mov ebx, eax\n");
            }
            _ => {}
        }

        previous.push(token);
    }

    output +=
r#"
mov eax, 1
int 0x80
"#;

    print!("{}", output);
}
<|endoftext|>


<commit_before>#![feature(core)]
#![feature(path)]

extern crate git2;
extern crate "rustc-serialize" as rustc_serialize;
extern crate docopt;

use git2::{Repository, Branch, BranchType, DiffLine,
    Commit, Diff, DiffFormat, DiffDelta, DiffHunk, Error, Oid};
use docopt::Docopt;
use std::old_io as io;
use std::old_io::BufferedReader;
use std::old_io::File;
use std::str;

// Write the Docopt usage string.
static USAGE: &'static str = "
Usage: transit <repo> [<old> <new>]

If no commits are given, transit will revwalk from latest to oldest.
";

#[derive(RustcDecodable, Debug)]
struct Args {
    arg_repo: String,
    arg_old: Option<String>,
    arg_new: Option<String>,
}

fn main() {
    // Parse the args above or die.
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.decode())
        .unwrap_or_else(|e| e.exit());
    // Pull up the revwalk.
    let path = Path::new(args.arg_repo);
    let repo = Repository::discover(&path)
        .ok().expect("Unable to find repo.");
    // If we can destructures the two optional args into real things.
    if let (Some(old_string), Some(new_string)) = (args.arg_old, args.arg_new) {
        // Compare a specific commit pair.
        // Fist, get the commits. (Error checked)
        let old = Oid::from_str(&old_string[]).and_then(|oid| repo.find_commit(oid));
        let new = Oid::from_str(&new_string[]).and_then(|oid| repo.find_commit(oid));
        if old.is_ok() && new.is_ok() {
            let output = find_moves(&repo, &old.unwrap(), &new.unwrap()).unwrap();
            make_output(output);
        } else {
            panic!("Commit ids were not valid.");
        }
    } else {
        // Revwalk.
        let mut revwalk = repo.revwalk()
            .ok().expect("Unable to get revwalk.");
        // Setup some options.
        revwalk.simplify_first_parent(); // TODO: Maybe remove?
        let mut flags = git2::Sort::empty();
        flags.insert(git2::SORT_TIME);
        flags.insert(git2::SORT_TOPOLOGICAL);
        revwalk.set_sorting(flags);
        // Push HEAD to the revwalk.
        revwalk.push_head()
            .ok().expect("Unable to push HEAD.");
        // We sadly must collect here to use `.windows()`
        let history = revwalk.filter_map(|id| repo.find_commit(id).ok())
            .collect::<Vec<Commit>>();
        // Walk through each pair of commits.
        for pair in history.windows(2) {let (old, new) = (&pair[1], &pair[0]);
			let output = find_moves(&repo, old.clone(), new.clone()).unwrap();
			// mangle the vectors here to make pretty output
			make_output(output);
		}
	}
}

fn make_output(output: Vec<Output>) {
	println!("make_output:");
    println!("\toutput.len()={}", output.len());
    for i in range(0, output.len()) {
            println!("\told_commit={}",         output[i].old_commit);
            println!("\tnew_commit={}",         output[i].new_commit);
            println!("\torigin_line={}",        output[i].origin_line);
            println!("\tdestintation_line={}",  output[i].destination_line);
            println!("\tnum_lines={}",          output[i].num_lines);
    }
}

fn find_moves(repo: &Repository, old: &Commit, new: &Commit) -> Result<Vec<Output>, Error> {

    println!("\nFIND MOVES---------------------");

	let old_tree = try!(old.tree());
	let new_tree = try!(new.tree());
	// Build up a diff of the two trees.
	let diff = try!(Diff::tree_to_tree(repo, Some(&old_tree), Some(&new_tree), None));
	// State. TODO: Don't just use a u64.
	//let moved = 0;

    //let mut results: Vec<Output> = Vec::new();

    let mut has_addition = false;
    let mut has_deletion = false;

	//let mut current_hunk: Vec<String> = Vec::new();
	// Read about this function in http://alexcrichton.com/git2-rs/git2/struct.Diff.html#method.print
	// It's a bit weird, but I think it will provide the necessary information.
	diff.print(DiffFormat::Patch, |delta, maybe_hunk, line| -> bool {
		// Thinking:
		//  * If is not a hunk, keep going.
		//  * If it's a hunk, do regex magic.
		//  * Stick regex output into a hashmap as a hash.
		//  * Later, we will iterate through and output pased on the values.
		// Filter out all the boring context lines.
		// If we're not interested in this line just return since it will iterate to the next.
		if maybe_hunk.is_none() { return true }; // Return early.

        println!("");
        println!("line.old_lineno()={:?}", line.old_lineno());
        println!("line.new_lineno()={:?}", line.new_lineno());
        println!("line.num_lines()={}",  line.num_lines());
        println!("line.content_offset={}", line.content_offset());
        println!("|line.origin()|=|{}|", line.origin());  // Wrap in |'s to detect space characters.
        print!("line.content()={}", str::from_utf8(line.content()).unwrap());

        println!("delta.nfiles()={}", delta.nfiles());
        println!("delta.status()={:?}", delta.status());    // :? is for debug trait.
        println!("delta.old_file():\n\tid={}\n\tpath_bytes=TODO\n\tpath=TODO\n\tsize={}", delta.old_file().id(), delta.old_file().size());
        println!("delta.new_file():\n\tid={}\n\tpath_bytes=TODO\n\tpath=TODO\n\tsize={}", delta.new_file().id(), delta.new_file().size());

		match line.origin() {
			// Context
			' ' | '=' => {
                print!("= {}", str::from_utf8(line.content()).unwrap());
                true
            },
			// Headers
			'F' | 'H' => {
                print!("F {}", str::from_utf8(line.content()).unwrap());
                true
            },
			// Additions
			'+' | '>' => {
				print!("+ {}", str::from_utf8(line.content()).unwrap());
                has_addition = true;
				true
			},
			// Deletions
			'-' | '<' => {
				print!("- {}", str::from_utf8(line.content()).unwrap());
                has_deletion = true;
				true
			},
			// Other (We don't care about these.)
			_         => {
                print!("_ {}", str::from_utf8(line.content()).unwrap());
                true
            }
		}
			// Look at that match statement, what a hunk. So hunky.
			// match maybe_hunk {
			//     Some(hunk) => unimplemented!(),
			//     None => unimplemented!(),
			// }
	});

    println!("\nhas_addition={}, has_deletion={}", has_addition, has_deletion);

   // if has_addition && has_deletion {
/*
        results.push(Output {
		    old_commit: old.id(),
		    new_commit: new.id(),
		    origin_line: 0,
		    destination_line: 0,
		    num_lines: 0
        });
*/
    //}

    if !has_addition || !has_deletion {
        println!("Does not have addition or deletion.");
        Ok(vec![])  // Return empty vector.
    } else {

	    Ok(vec![Output {
		    old_commit: old.id(),
		    new_commit: new.id(),
		    origin_line: 0,
		    destination_line: 0,
		    num_lines: 0
	    }])
    }

   // Ok(results)
}

#[derive(Show)]
struct Output {
    old_commit: Oid,
    new_commit: Oid,
    origin_line: u32,
    destination_line: u32,
    num_lines: u32,
}
<commit_msg>Make diffline printout more compact.<commit_after>#![feature(core)]
#![feature(path)]

extern crate git2;
extern crate "rustc-serialize" as rustc_serialize;
extern crate docopt;

use git2::{Repository, Branch, BranchType, DiffLine,
    Commit, Diff, DiffFormat, DiffDelta, DiffHunk, Error, Oid};
use docopt::Docopt;
use std::old_io as io;
use std::old_io::BufferedReader;
use std::old_io::File;
use std::str;

// Write the Docopt usage string.
static USAGE: &'static str = "
Usage: transit <repo> [<old> <new>]

If no commits are given, transit will revwalk from latest to oldest.
";

#[derive(RustcDecodable, Debug)]
struct Args {
    arg_repo: String,
    arg_old: Option<String>,
    arg_new: Option<String>,
}

fn main() {
    // Parse the args above or die.
    let args: Args = Docopt::new(USAGE)
        .and_then(|d| d.decode())
        .unwrap_or_else(|e| e.exit());
    // Pull up the revwalk.
    let path = Path::new(args.arg_repo);
    let repo = Repository::discover(&path)
        .ok().expect("Unable to find repo.");
    // If we can destructures the two optional args into real things.
    if let (Some(old_string), Some(new_string)) = (args.arg_old, args.arg_new) {
        // Compare a specific commit pair.
        // Fist, get the commits. (Error checked)
        let old = Oid::from_str(&old_string[]).and_then(|oid| repo.find_commit(oid));
        let new = Oid::from_str(&new_string[]).and_then(|oid| repo.find_commit(oid));
        if old.is_ok() && new.is_ok() {
            let output = find_moves(&repo, &old.unwrap(), &new.unwrap()).unwrap();
            make_output(output);
        } else {
            panic!("Commit ids were not valid.");
        }
    } else {
        // Revwalk.
        let mut revwalk = repo.revwalk()
            .ok().expect("Unable to get revwalk.");
        // Setup some options.
        revwalk.simplify_first_parent(); // TODO: Maybe remove?
        let mut flags = git2::Sort::empty();
        flags.insert(git2::SORT_TIME);
        flags.insert(git2::SORT_TOPOLOGICAL);
        revwalk.set_sorting(flags);
        // Push HEAD to the revwalk.
        revwalk.push_head()
            .ok().expect("Unable to push HEAD.");
        // We sadly must collect here to use `.windows()`
        let history = revwalk.filter_map(|id| repo.find_commit(id).ok())
            .collect::<Vec<Commit>>();
        // Walk through each pair of commits.
        for pair in history.windows(2) {let (old, new) = (&pair[1], &pair[0]);
			let output = find_moves(&repo, old.clone(), new.clone()).unwrap();
			// mangle the vectors here to make pretty output
			make_output(output);
		}
	}
}

fn make_output(output: Vec<Output>) {
	println!("make_output:");
    println!("\toutput.len()={}", output.len());
    for i in range(0, output.len()) {
            println!("\told_commit={}",         output[i].old_commit);
            println!("\tnew_commit={}",         output[i].new_commit);
            println!("\torigin_line={}",        output[i].origin_line);
            println!("\tdestintation_line={}",  output[i].destination_line);
            println!("\tnum_lines={}",          output[i].num_lines);
    }
}

fn find_moves(repo: &Repository, old: &Commit, new: &Commit) -> Result<Vec<Output>, Error> {

    println!("\nFIND MOVES---------------------");

	let old_tree = try!(old.tree());
	let new_tree = try!(new.tree());
	// Build up a diff of the two trees.
	let diff = try!(Diff::tree_to_tree(repo, Some(&old_tree), Some(&new_tree), None));
	// State. TODO: Don't just use a u64.
	//let moved = 0;

    //let mut results: Vec<Output> = Vec::new();

    let mut has_addition = false;
    let mut has_deletion = false;

	//let mut current_hunk: Vec<String> = Vec::new();
	// Read about this function in http://alexcrichton.com/git2-rs/git2/struct.Diff.html#method.print
	// It's a bit weird, but I think it will provide the necessary information.
	diff.print(DiffFormat::Patch, |delta, maybe_hunk, line| -> bool {
		// Thinking:
		//  * If is not a hunk, keep going.
		//  * If it's a hunk, do regex magic.
		//  * Stick regex output into a hashmap as a hash.
		//  * Later, we will iterate through and output pased on the values.
		// Filter out all the boring context lines.
		// If we're not interested in this line just return since it will iterate to the next.
		if maybe_hunk.is_none() { return true }; // Return early.

        // 'origin' is wrapped in pipes to ease displaying space characters.
        print!("line: old={:?} new={:?} offset={} |origin|=|{}|\n      content={}",
                 line.old_lineno(), line.new_lineno(), line.content_offset(),
                 line.origin(), str::from_utf8(line.content()).unwrap());

        println!("delta.nfiles()={}", delta.nfiles());
        println!("delta.status()={:?}", delta.status());    // :? is for debug trait.
        println!("delta.old_file():\n\tid={}\n\tpath_bytes=TODO\n\tpath=TODO\n\tsize={}", delta.old_file().id(), delta.old_file().size());
        println!("delta.new_file():\n\tid={}\n\tpath_bytes=TODO\n\tpath=TODO\n\tsize={}", delta.new_file().id(), delta.new_file().size());

		match line.origin() {
			// Context
			' ' | '=' => {
                print!("= {}", str::from_utf8(line.content()).unwrap());
                true
            },
			// Headers
			'F' | 'H' => {
                print!("F {}", str::from_utf8(line.content()).unwrap());
                true
            },
			// Additions
			'+' | '>' => {
				print!("+ {}", str::from_utf8(line.content()).unwrap());
                has_addition = true;
				true
			},
			// Deletions
			'-' | '<' => {
				print!("- {}", str::from_utf8(line.content()).unwrap());
                has_deletion = true;
				true
			},
			// Other (We don't care about these.)
			_         => {
                print!("_ {}", str::from_utf8(line.content()).unwrap());
                true
            }
		}
			// Look at that match statement, what a hunk. So hunky.
			// match maybe_hunk {
			//     Some(hunk) => unimplemented!(),
			//     None => unimplemented!(),
			// }
	});

    println!("\nhas_addition={}, has_deletion={}", has_addition, has_deletion);

   // if has_addition && has_deletion {
/*
        results.push(Output {
		    old_commit: old.id(),
		    new_commit: new.id(),
		    origin_line: 0,
		    destination_line: 0,
		    num_lines: 0
        });
*/
    //}

    if !has_addition || !has_deletion {
        println!("Does not have addition or deletion.");
        Ok(vec![])  // Return empty vector.
    } else {

	    Ok(vec![Output {
		    old_commit: old.id(),
		    new_commit: new.id(),
		    origin_line: 0,
		    destination_line: 0,
		    num_lines: 0
	    }])
    }

   // Ok(results)
}

#[derive(Show)]
struct Output {
    old_commit: Oid,
    new_commit: Oid,
    origin_line: u32,
    destination_line: u32,
    num_lines: u32,
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate glium;
use glium::glutin;

use std::collections::HashMap;

#[macro_use]
mod support;

enum Shape {
    Clear([f32; 4]),
    Polygon(Vec<(f32, f32)>, [f32; 4]),
    Line(f32, f32, f32, f32, [f32; 4]),
}

pub struct Window {
    display: glium::Display,
    events_loop: glium::glutin::EventsLoop,
    color: [f32; 4],
    shapes: Vec<Shape>,
    keys: HashMap<glutin::VirtualKeyCode, bool>,
}

impl Window {
    pub fn new(title: &str, width: u32, height: u32) -> Self {
        let events_loop = glutin::EventsLoop::new();
        let window = glutin::WindowBuilder::new()
            .with_title(title)
            .with_dimensions(width, height);
        let context = glutin::ContextBuilder::new();
        let display = glium::Display::new(window, context, &events_loop).unwrap();

        Window {
            display: display,
            events_loop: events_loop,
            color: [1.0, 1.0, 1.0, 1.0],
            shapes: Vec::new(),
            keys: HashMap::new(),
        }
    }

    pub fn start_loop<F>(&mut self, mut callback: F)
    where
        F: FnMut(&mut Window, f32) -> support::Action,
    {
        let program = support::shaders::load_program(&self.display).unwrap();
        let params = glium::DrawParameters {
            blend: glium::draw_parameters::Blend::alpha_blending(),
            ..Default::default()
        };

        use glium::Surface;
        support::start_loop(|delta| {

            let mut target = self.display.draw();

            let mut rtn = callback(self, delta);
            for shape in self.shapes.iter() {
                match shape {
                    &Shape::Clear(color) => {
                        target.clear_color(color[0], color[1], color[2], color[3])
                    }
                    &Shape::Line(x1, y1, x2, y2, color) => {
                        let vert_buff =
                            support::buffer::line_vert_buff(&self.display, x1, y1, x2, y2, color)
                                .unwrap();
                        let indices =
                            glium::index::NoIndices(glium::index::PrimitiveType::LineStrip);
                        target
                            .draw(
                                &vert_buff,
                                &indices,
                                &program,
                                &glium::uniforms::EmptyUniforms,
                                &params,
                            )
                            .unwrap();
                    }
                    &Shape::Polygon(ref points, color) => {
                        let vert_buff =
                            support::buffer::poly_vert_buffer(&self.display, &points, color)
                                .unwrap();
                        let indices =
                            glium::index::NoIndices(glium::index::PrimitiveType::TriangleFan);
                        target
                            .draw(
                                &vert_buff,
                                &indices,
                                &program,
                                &glium::uniforms::EmptyUniforms,
                                &params,
                            )
                            .unwrap();
                    }
                }
            }

            self.shapes.clear();

            target.finish().unwrap();

            let mut keys: HashMap<glutin::VirtualKeyCode, bool> = HashMap::new();
            self.events_loop.poll_events(|ev| match ev {
                glium::glutin::Event::WindowEvent { event, .. } => {
                    match event {
                        glutin::WindowEvent::Closed => rtn = support::Action::Stop,
                        glutin::WindowEvent::KeyboardInput { input, .. } => {
                            match input.virtual_keycode {
                                Some(key) => {
                                    keys.insert(
                                        key,
                                        match input.state {
                                            glutin::ElementState::Pressed => true,
                                            glutin::ElementState::Released => false,
                                        },
                                    );
                                }
                                None => (),
                            }
                        }
                        _ => (),
                    }
                }
                _ => (),
            });

            for (key, value) in keys {
                self.keys.insert(key, value);
            }

            rtn
        });
    }

    pub fn clear_color(&mut self, red: f32, green: f32, blue: f32, alpha: f32) {
        let shape = Shape::Clear([red, green, blue, alpha]);
        self.shapes.push(shape);
    }

    pub fn set_color(&mut self, red: f32, green: f32, blue: f32, alpha: f32) {
        self.color = [red, green, blue, alpha];
    }

    pub fn draw_line(&mut self, x1: f32, y1: f32, x2: f32, y2: f32) {
        let shape = Shape::Line(x1, y1, x2, y2, self.color);
        self.shapes.push(shape);
    }

    pub fn draw(&mut self, points: &[(f32, f32)]) {
        let shape = Shape::Polygon(Vec::from(points), self.color);
        self.shapes.push(shape);
    }
}

fn main() {
    let mut window = Window::new("Hello World", 640, 480);

    window.start_loop(|app, delta| {
        app.clear_color(0.1, 0.3, 0.2, 1.0);

        app.set_color(0.3, 0.1, 0.2, 1.0);
        app.draw(&[(0.0, 0.0), (10.0, 10.0)]);

        app.set_color(1.0, 0.0, 0.0, 1.0);
        app.draw_line(0.0, 0.0, 1.0, 1.0);

        app.set_color(0.0, 0.0, 1.0, 0.3);
        app.draw(&[(0.0, 0.0), (1.0, 1.0), (1.0, 0.0)]);

        app.set_color(0.0, 1.0, 0.0, 0.3);
        app.draw(&[(0.0, 0.0), (0.0, 1.0), (1.0, 1.0)]);

        let circle: Vec<(f32, f32)> = (0..360)
            .map(|d| {
                let r = (d as f32).to_radians();
                (r.cos(), r.sin())
            })
            .collect();
        app.set_color(1.0, 0.0, 0.0, 0.3);
        app.draw(&circle);

        support::Action::Continue
    });
}
<commit_msg>Added html color support, re-implemented draw_rect<commit_after>#[macro_use]
extern crate glium;
use glium::glutin;

use std::collections::HashMap;

#[macro_use]
mod support;

pub type Color = [f32; 4];

enum Shape {
    Clear(Color),
    Polygon(Vec<(f32, f32)>, Color),
    Line(f32, f32, f32, f32, Color),
}

pub struct Window {
    display: glium::Display,
    events_loop: glium::glutin::EventsLoop,
    color: [f32; 4],
    shapes: Vec<Shape>,
    keys: HashMap<glutin::VirtualKeyCode, bool>,
}

impl Window {
    pub fn new(title: &str, width: u32, height: u32) -> Self {
        let events_loop = glutin::EventsLoop::new();
        let window = glutin::WindowBuilder::new()
            .with_title(title)
            .with_dimensions(width, height);
        let context = glutin::ContextBuilder::new();
        let display = glium::Display::new(window, context, &events_loop).unwrap();

        Window {
            display: display,
            events_loop: events_loop,
            color: [1.0, 1.0, 1.0, 1.0],
            shapes: Vec::new(),
            keys: HashMap::new(),
        }
    }

    pub fn start_loop<F>(&mut self, mut callback: F)
    where
        F: FnMut(&mut Window, f32) -> support::Action,
    {
        let program = support::shaders::load_program(&self.display).unwrap();
        let params = glium::DrawParameters {
            blend: glium::draw_parameters::Blend::alpha_blending(),
            ..Default::default()
        };

        use glium::Surface;
        support::start_loop(|delta| {

            let mut target = self.display.draw();

            let mut rtn = callback(self, delta);
            for shape in self.shapes.iter() {
                match shape {
                    &Shape::Clear(color) => {
                        target.clear_color(color[0], color[1], color[2], color[3])
                    }
                    &Shape::Line(x1, y1, x2, y2, color) => {
                        let vert_buff =
                            support::buffer::line_vert_buff(&self.display, x1, y1, x2, y2, color)
                                .unwrap();
                        let indices =
                            glium::index::NoIndices(glium::index::PrimitiveType::LineStrip);
                        target
                            .draw(
                                &vert_buff,
                                &indices,
                                &program,
                                &glium::uniforms::EmptyUniforms,
                                &params,
                            )
                            .unwrap();
                    }
                    &Shape::Polygon(ref points, color) => {
                        let vert_buff =
                            support::buffer::poly_vert_buffer(&self.display, &points, color)
                                .unwrap();
                        let indices =
                            glium::index::NoIndices(glium::index::PrimitiveType::TriangleFan);
                        target
                            .draw(
                                &vert_buff,
                                &indices,
                                &program,
                                &glium::uniforms::EmptyUniforms,
                                &params,
                            )
                            .unwrap();
                    }
                }
            }

            self.shapes.clear();

            target.finish().unwrap();

            let mut keys: HashMap<glutin::VirtualKeyCode, bool> = HashMap::new();
            self.events_loop.poll_events(|ev| match ev {
                glium::glutin::Event::WindowEvent { event, .. } => {
                    match event {
                        glutin::WindowEvent::Closed => rtn = support::Action::Stop,
                        glutin::WindowEvent::KeyboardInput { input, .. } => {
                            match input.virtual_keycode {
                                Some(key) => {
                                    keys.insert(
                                        key,
                                        match input.state {
                                            glutin::ElementState::Pressed => true,
                                            glutin::ElementState::Released => false,
                                        },
                                    );
                                }
                                None => (),
                            }
                        }
                        _ => (),
                    }
                }
                _ => (),
            });

            for (key, value) in keys {
                self.keys.insert(key, value);
            }

            rtn
        });
    }

    pub fn clear_color(&mut self, red: f32, green: f32, blue: f32, alpha: f32) {
        let shape = Shape::Clear([red, green, blue, alpha]);
        self.shapes.push(shape);
    }

    pub fn set_color(&mut self, red: f32, green: f32, blue: f32, alpha: f32) {
        self.color = [red, green, blue, alpha];
    }

    pub fn set_color_html(&mut self, color: &str) {
        let mut bytes = color.as_bytes();
        if bytes[0] == b'#' {
            bytes = &bytes[1..];
        }

        use std::str::from_utf8;
        use std::u8;

        if bytes.len() == 3 {
            let r = u8::from_str_radix(from_utf8(&vec![bytes[0], bytes[0]]).unwrap(), 16).unwrap();
            let g = u8::from_str_radix(from_utf8(&vec![bytes[1], bytes[1]]).unwrap(), 16).unwrap();
            let b = u8::from_str_radix(from_utf8(&vec![bytes[2], bytes[2]]).unwrap(), 16).unwrap();
            self.set_color(
                (r as f32) / 255.0,
                (g as f32) / 255.0,
                (b as f32) / 255.0,
                1.0,
            );
        } else if bytes.len() == 6 {
            let r = u8::from_str_radix(from_utf8(&bytes[0..2]).unwrap(), 16).unwrap();
            let g = u8::from_str_radix(from_utf8(&bytes[2..4]).unwrap(), 16).unwrap();
            let b = u8::from_str_radix(from_utf8(&bytes[4..6]).unwrap(), 16).unwrap();
            self.set_color(
                (r as f32) / 255.0,
                (g as f32) / 255.0,
                (b as f32) / 255.0,
                1.0,
            );
        }
    }

    pub fn draw_rect(&mut self, p1: (f32, f32), p2: (f32, f32)) {
        let shape = Shape::Polygon(
            vec![(p1.0, p1.1), (p1.0, p2.1), (p2.0, p2.1), (p2.0, p1.1)],
            self.color,
        );
        self.shapes.push(shape);
    }

    pub fn draw_line(&mut self, x1: f32, y1: f32, x2: f32, y2: f32) {
        let shape = Shape::Line(x1, y1, x2, y2, self.color);
        self.shapes.push(shape);
    }

    pub fn draw(&mut self, points: &[(f32, f32)]) {
        let shape = Shape::Polygon(Vec::from(points), self.color);
        self.shapes.push(shape);
    }
}

fn main() {
    let mut window = Window::new("Hello World", 640, 480);

    window.start_loop(|app, delta| {
        app.clear_color(0.1, 0.3, 0.2, 1.0);

        app.set_color_html("312");
        app.draw_rect((-0.5, -0.5), (0.5, 0.5));

        app.set_color_html("#033112");
        app.draw_rect((0.0, 0.0), (-1.0, -1.0));

        app.set_color(1.0, 0.0, 0.0, 1.0);
        app.draw_line(0.0, 0.0, 1.0, 1.0);

        app.set_color(0.0, 0.0, 1.0, 0.3);
        app.draw(&[(0.0, 0.0), (1.0, 1.0), (1.0, 0.0)]);

        app.set_color(0.0, 1.0, 0.0, 0.3);
        app.draw(&[(0.0, 0.0), (0.0, 1.0), (1.0, 1.0)]);

        let circle: Vec<(f32, f32)> = (0..360)
            .map(|d| {
                let r = (d as f32).to_radians();
                (r.cos(), r.sin())
            })
            .collect();
        app.set_color(1.0, 0.0, 0.0, 0.3);
        app.draw(&circle);

        support::Action::Continue
    });
}
<|endoftext|>


<commit_before>#![cfg_attr(feature = "deny-warnings", deny(warnings))]

use rustc_tools_util::VersionInfo;
use std::env;
use std::ffi::OsString;
use std::path::PathBuf;
use std::process::{self, Command};

const CARGO_CLIPPY_HELP: &str = r#"Checks a package to catch common mistakes and improve your Rust code.

Usage:
    cargo clippy [options] [--] [<opts>...]

Common options:
    -h, --help               Print this message
    -V, --version            Print version info and exit

Other options are the same as `cargo check`.

To allow or deny a lint from the command line you can use `cargo clippy --`
with:

    -W --warn OPT       Set lint warnings
    -A --allow OPT      Set lint allowed
    -D --deny OPT       Set lint denied
    -F --forbid OPT     Set lint forbidden

You can use tool lints to allow or deny lints from your code, eg.:

    #[allow(clippy::needless_lifetimes)]
"#;

fn show_help() {
    println!("{}", CARGO_CLIPPY_HELP);
}

fn show_version() {
    let version_info = rustc_tools_util::get_version_info!();
    println!("{}", version_info);
}

pub fn main() {
    // Check for version and help flags even when invoked as 'cargo-clippy'
    if env::args().any(|a| a == "--help" || a == "-h") {
        show_help();
        return;
    }

    if env::args().any(|a| a == "--version" || a == "-V") {
        show_version();
        return;
    }

    if let Err(code) = process(env::args().skip(2)) {
        process::exit(code);
    }
}

struct ClippyCmd {
    unstable_options: bool,
    cargo_subcommand: &'static str,
    args: Vec<String>,
    clippy_args: String,
}

impl ClippyCmd {
    fn new<I>(mut old_args: I) -> Self
    where
        I: Iterator<Item = String>,
    {
        let mut cargo_subcommand = "check";
        let mut unstable_options = false;
        let mut args = vec![];

        for arg in old_args.by_ref() {
            match arg.as_str() {
                "--fix" => {
                    cargo_subcommand = "fix";
                    continue;
                }
                "--" => break,
                // Cover -Zunstable-options and -Z unstable-options
                s if s.ends_with("unstable-options") => unstable_options = true,
                _ => {}
            }

            args.push(arg);
        }

        if cargo_subcommand == "fix" && !unstable_options {
            panic!("Usage of `--fix` requires `-Z unstable-options`");
        }

        // Run the dogfood tests directly on nightly cargo. This is required due
        // to a bug in rustup.rs when running cargo on custom toolchains. See issue #3118.
        if env::var_os("CLIPPY_DOGFOOD").is_some() && cfg!(windows) {
            args.insert(0, "+nightly".to_string());
        }

        let clippy_args: String = old_args.map(|arg| format!("{}__CLIPPY_HACKERY__", arg)).collect();

        ClippyCmd {
            unstable_options,
            cargo_subcommand,
            args,
            clippy_args,
        }
    }

    fn path_env(&self) -> &'static str {
        if self.unstable_options {
            "RUSTC_WORKSPACE_WRAPPER"
        } else {
            "RUSTC_WRAPPER"
        }
    }

    fn path(&self) -> PathBuf {
        let mut path = env::current_exe()
            .expect("current executable path invalid")
            .with_file_name("clippy-driver");

        if cfg!(windows) {
            path.set_extension("exe");
        }

        path
    }

    fn target_dir() -> Option<(&'static str, OsString)> {
        env::var_os("CLIPPY_DOGFOOD")
            .map(|_| {
                env::var_os("CARGO_MANIFEST_DIR").map_or_else(
                    || std::ffi::OsString::from("clippy_dogfood"),
                    |d| {
                        std::path::PathBuf::from(d)
                            .join("target")
                            .join("dogfood")
                            .into_os_string()
                    },
                )
            })
            .map(|p| ("CARGO_TARGET_DIR", p))
    }

    fn to_std_cmd(self) -> Command {
        let mut cmd = Command::new("cargo");

        cmd.env(self.path_env(), self.path())
            .envs(ClippyCmd::target_dir())
            .env("CLIPPY_ARGS", self.clippy_args)
            .arg(self.cargo_subcommand)
            .args(&self.args);

        cmd
    }
}

fn process<I>(old_args: I) -> Result<(), i32>
where
    I: Iterator<Item = String>,
{
    let cmd = ClippyCmd::new(old_args);

    let mut cmd = cmd.to_std_cmd();

    let exit_status = cmd
        .spawn()
        .expect("could not run cargo")
        .wait()
        .expect("failed to wait for cargo?");

    if exit_status.success() {
        Ok(())
    } else {
        Err(exit_status.code().unwrap_or(-1))
    }
}

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

    #[test]
    #[should_panic]
    fn fix_without_unstable() {
        let args = "cargo clippy --fix".split_whitespace().map(ToString::to_string);
        let _ = ClippyCmd::new(args);
    }

    #[test]
    fn fix_unstable() {
        let args = "cargo clippy --fix -Zunstable-options"
            .split_whitespace()
            .map(ToString::to_string);
        let cmd = ClippyCmd::new(args);
        assert_eq!("fix", cmd.cargo_subcommand);
        assert_eq!("RUSTC_WORKSPACE_WRAPPER", cmd.path_env());
        assert!(cmd.args.iter().find(|arg| arg.ends_with("unstable-options")).is_some());
    }

    #[test]
    fn check() {
        let args = "cargo clippy".split_whitespace().map(ToString::to_string);
        let cmd = ClippyCmd::new(args);
        assert_eq!("check", cmd.cargo_subcommand);
        assert_eq!("RUSTC_WRAPPER", cmd.path_env());
    }

    #[test]
    fn check_unstable() {
        let args = "cargo clippy -Zunstable-options"
            .split_whitespace()
            .map(ToString::to_string);
        let cmd = ClippyCmd::new(args);
        assert_eq!("check", cmd.cargo_subcommand);
        assert_eq!("RUSTC_WORKSPACE_WRAPPER", cmd.path_env());
    }
}
<commit_msg>manually fixing formatting at this point lol<commit_after>#![cfg_attr(feature = "deny-warnings", deny(warnings))]

use rustc_tools_util::VersionInfo;
use std::env;
use std::ffi::OsString;
use std::path::PathBuf;
use std::process::{self, Command};

const CARGO_CLIPPY_HELP: &str = r#"Checks a package to catch common mistakes and improve your Rust code.

Usage:
    cargo clippy [options] [--] [<opts>...]

Common options:
    -h, --help               Print this message
    -V, --version            Print version info and exit

Other options are the same as `cargo check`.

To allow or deny a lint from the command line you can use `cargo clippy --`
with:

    -W --warn OPT       Set lint warnings
    -A --allow OPT      Set lint allowed
    -D --deny OPT       Set lint denied
    -F --forbid OPT     Set lint forbidden

You can use tool lints to allow or deny lints from your code, eg.:

    #[allow(clippy::needless_lifetimes)]
"#;

fn show_help() {
    println!("{}", CARGO_CLIPPY_HELP);
}

fn show_version() {
    let version_info = rustc_tools_util::get_version_info!();
    println!("{}", version_info);
}

pub fn main() {
    // Check for version and help flags even when invoked as 'cargo-clippy'
    if env::args().any(|a| a == "--help" || a == "-h") {
        show_help();
        return;
    }

    if env::args().any(|a| a == "--version" || a == "-V") {
        show_version();
        return;
    }

    if let Err(code) = process(env::args().skip(2)) {
        process::exit(code);
    }
}

struct ClippyCmd {
    unstable_options: bool,
    cargo_subcommand: &'static str,
    args: Vec<String>,
    clippy_args: String,
}

impl ClippyCmd {
    fn new<I>(mut old_args: I) -> Self
    where
        I: Iterator<Item = String>,
    {
        let mut cargo_subcommand = "check";
        let mut unstable_options = false;
        let mut args = vec![];

        for arg in old_args.by_ref() {
            match arg.as_str() {
                "--fix" => {
                    cargo_subcommand = "fix";
                    continue;
                },
                "--" => break,
                // Cover -Zunstable-options and -Z unstable-options
                s if s.ends_with("unstable-options") => unstable_options = true,
                _ => {},
            }

            args.push(arg);
        }

        if cargo_subcommand == "fix" && !unstable_options {
            panic!("Usage of `--fix` requires `-Z unstable-options`");
        }

        // Run the dogfood tests directly on nightly cargo. This is required due
        // to a bug in rustup.rs when running cargo on custom toolchains. See issue #3118.
        if env::var_os("CLIPPY_DOGFOOD").is_some() && cfg!(windows) {
            args.insert(0, "+nightly".to_string());
        }

        let clippy_args: String = old_args.map(|arg| format!("{}__CLIPPY_HACKERY__", arg)).collect();

        ClippyCmd {
            unstable_options,
            cargo_subcommand,
            args,
            clippy_args,
        }
    }

    fn path_env(&self) -> &'static str {
        if self.unstable_options {
            "RUSTC_WORKSPACE_WRAPPER"
        } else {
            "RUSTC_WRAPPER"
        }
    }

    fn path(&self) -> PathBuf {
        let mut path = env::current_exe()
            .expect("current executable path invalid")
            .with_file_name("clippy-driver");

        if cfg!(windows) {
            path.set_extension("exe");
        }

        path
    }

    fn target_dir() -> Option<(&'static str, OsString)> {
        env::var_os("CLIPPY_DOGFOOD")
            .map(|_| {
                env::var_os("CARGO_MANIFEST_DIR").map_or_else(
                    || std::ffi::OsString::from("clippy_dogfood"),
                    |d| {
                        std::path::PathBuf::from(d)
                            .join("target")
                            .join("dogfood")
                            .into_os_string()
                    },
                )
            })
            .map(|p| ("CARGO_TARGET_DIR", p))
    }

    fn to_std_cmd(self) -> Command {
        let mut cmd = Command::new("cargo");

        cmd.env(self.path_env(), self.path())
            .envs(ClippyCmd::target_dir())
            .env("CLIPPY_ARGS", self.clippy_args)
            .arg(self.cargo_subcommand)
            .args(&self.args);

        cmd
    }
}

fn process<I>(old_args: I) -> Result<(), i32>
where
    I: Iterator<Item = String>,
{
    let cmd = ClippyCmd::new(old_args);

    let mut cmd = cmd.to_std_cmd();

    let exit_status = cmd
        .spawn()
        .expect("could not run cargo")
        .wait()
        .expect("failed to wait for cargo?");

    if exit_status.success() {
        Ok(())
    } else {
        Err(exit_status.code().unwrap_or(-1))
    }
}

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

    #[test]
    #[should_panic]
    fn fix_without_unstable() {
        let args = "cargo clippy --fix".split_whitespace().map(ToString::to_string);
        let _ = ClippyCmd::new(args);
    }

    #[test]
    fn fix_unstable() {
        let args = "cargo clippy --fix -Zunstable-options"
            .split_whitespace()
            .map(ToString::to_string);
        let cmd = ClippyCmd::new(args);
        assert_eq!("fix", cmd.cargo_subcommand);
        assert_eq!("RUSTC_WORKSPACE_WRAPPER", cmd.path_env());
        assert!(cmd.args.iter().find(|arg| arg.ends_with("unstable-options")).is_some());
    }

    #[test]
    fn check() {
        let args = "cargo clippy".split_whitespace().map(ToString::to_string);
        let cmd = ClippyCmd::new(args);
        assert_eq!("check", cmd.cargo_subcommand);
        assert_eq!("RUSTC_WRAPPER", cmd.path_env());
    }

    #[test]
    fn check_unstable() {
        let args = "cargo clippy -Zunstable-options"
            .split_whitespace()
            .map(ToString::to_string);
        let cmd = ClippyCmd::new(args);
        assert_eq!("check", cmd.cargo_subcommand);
        assert_eq!("RUSTC_WORKSPACE_WRAPPER", cmd.path_env());
    }
}
<|endoftext|>


<commit_before>extern crate chrono;
extern crate docopt;
extern crate dotenv;
extern crate hyper;
extern crate nourish_bot;
extern crate rustc_serialize;
extern crate slack_hook;

use std::env;
use std::io::prelude::*;

use chrono::Local;
use docopt::Docopt;
use hyper::Client;
use hyper::header::Connection;
use slack_hook::{Slack, Payload, PayloadTemplate};

const USAGE: &'static str = r"
Nourishbot!

Usage:
    nourishbot help
    nourishbot print
    nourishbot post <slack-channel>...

Subcommands:
    help                   Show this screen.
    print                  Print the Nourish menu.
    post                   Post the menu to the given Slack channels.
";

#[derive(Debug, RustcDecodable)]
struct Args {
    arg_slack_channel: Vec<String>,
}

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

    let url = nourish_bot::url_for_date(&Local::today().naive_local());

    let menu = {
        let client = Client::new();

        let mut res = client.get(url)
                            .header(Connection::close())
                            .send()
                            .unwrap();

        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();

        nourish_bot::parse_menu(&body)
    };

    println!("{}", menu.to_markdown());

    for channel in &args.arg_slack_channel {
        let slack = Slack::new(&env::var("WEBHOOK_URL").expect("WEBHOOK_URL is not set"));
        let p = Payload::new(PayloadTemplate::Complete {
            text: Some(&menu.to_markdown()),
            channel: Some(channel),
            username: Some("nourishbot"),
            icon_url: None,
            icon_emoji: Some(":athena:"),
            attachments: None,
            unfurl_links: Some(false),
            link_names: Some(false),
        });

        match slack.send(&p) {
            Ok(()) => println!("Posted to {}", channel),
            Err(err) => println!("Error posting to {}: {}", channel, err),
        }
    }
}
<commit_msg>allow menu response to contain invalid UTF-8<commit_after>extern crate chrono;
extern crate docopt;
extern crate dotenv;
extern crate hyper;
extern crate nourish_bot;
extern crate rustc_serialize;
extern crate slack_hook;

use std::env;
use std::io::prelude::*;

use chrono::Local;
use docopt::Docopt;
use hyper::Client;
use hyper::header::Connection;
use slack_hook::{Slack, Payload, PayloadTemplate};

const USAGE: &'static str = r"
Nourishbot!

Usage:
    nourishbot help
    nourishbot print
    nourishbot post <slack-channel>...

Subcommands:
    help                   Show this screen.
    print                  Print the Nourish menu.
    post                   Post the menu to the given Slack channels.
";

#[derive(Debug, RustcDecodable)]
struct Args {
    arg_slack_channel: Vec<String>,
}

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

    let url = nourish_bot::url_for_date(&Local::today().naive_local());

    let menu = {
        let client = Client::new();

        let mut res = client.get(url)
            .header(Connection::close())
            .send()
            .unwrap();

        let mut bytes = vec![];
        res.read_to_end(&mut bytes).unwrap();
        let body = String::from_utf8_lossy(&bytes);

        nourish_bot::parse_menu(&body)
    };

    println!("{}", menu.to_markdown());

    for channel in &args.arg_slack_channel {
        let slack = Slack::new(&env::var("WEBHOOK_URL").expect("WEBHOOK_URL is not set"));
        let p = Payload::new(PayloadTemplate::Complete {
            text: Some(&menu.to_markdown()),
            channel: Some(channel),
            username: Some("nourishbot"),
            icon_url: None,
            icon_emoji: Some(":athena:"),
            attachments: None,
            unfurl_links: Some(false),
            link_names: Some(false),
        });

        match slack.send(&p) {
            Ok(()) => println!("Posted to {}", channel),
            Err(err) => println!("Error posting to {}: {}", channel, err),
        }
    }
}
<|endoftext|>