<commit_before>//! An enum mapping type.
//!
//! It is implemented using an array type, so using it is as fast as using Rust
//! arrays.
//!
//! # Examples
//!
//! ```
//! #[macro_use]
//! extern crate enum_map;
//!
//! use enum_map::EnumMap;
//!
//! #[derive(Debug, EnumMap)]
//! enum Example {
//!     A,
//!     B,
//!     C,
//! }
//!
//! fn main() {
//!     let mut map = enum_map! {
//!         Example::A => 1,
//!         Example::B => 2,
//!         Example::C => 3,
//!     };
//!     map[Example::C] = 4;
//!
//!     assert_eq!(map[Example::A], 1);
//!
//!     for (key, &value) in &map {
//!         println!("{:?} has {} as value.", key, value);
//!     }
//! }
//! ```

#![no_std]
#![deny(missing_docs)]

#[macro_use]
extern crate array_macro;
// This allows to quiet "proc macro crates and `#[no_link]` crates have no
// effect without `#[macro_use]`" warning. Just using extern DOES have
// an effect of letting me export the macro.
#[allow(unused_imports)]
#[macro_use]
extern crate enum_map_derive;

mod enummap_impls;
mod internal;
mod iter;
mod serde;

pub use internal::Internal;
pub use iter::{Iter, IterMut};
// `*` here means re-exporting a derive procedural macro.
pub use enum_map_derive::*;

use core::slice;

/// An enum mapping.
///
/// This internally uses an array which stores a value for each possible
/// enum value. To work, it requires implementation of internal (private,
/// although public due to macro limitations) trait which allows extracting
/// information about an enum, which can be automatically generated using
/// `#[derive(EnumMap)]` from `enum_map_derive` crate.
///
/// Additionally, `bool` and `u8` automatically derives from `EnumMap`. While
/// `u8` is not technically an enum, it's convenient to consider it like one.
/// In particular, [reverse-complement in benchmark game] could be using `u8`
/// as an enum.
///
/// # Examples
///
/// ```
/// #[macro_use]
/// extern crate enum_map;
///
/// use enum_map::EnumMap;
///
/// #[derive(EnumMap)]
/// enum Example {
///     A,
///     B,
///     C,
/// }
///
/// fn main() {
///     let mut map = EnumMap::new();
///     // new initializes map with default values
///     assert_eq!(map[Example::A], 0);
///     map[Example::A] = 3;
///     assert_eq!(map[Example::A], 3);
/// }
/// ```
///
/// [reverse-complement in benchmark game]:
///     http://benchmarksgame.alioth.debian.org/u64q/program.php?test=revcomp&lang=rust&id=2
#[derive(Debug)]
pub struct EnumMap<K: Internal<V>, V> {
    array: K::Array,
}

impl<K: Internal<V>, V: Default> EnumMap<K, V>
where
    K::Array: Default,
{
    /// Creates an enum map with default values.
    ///
    /// ```
    /// #[macro_use]
    /// extern crate enum_map;
    ///
    /// use enum_map::EnumMap;
    ///
    /// #[derive(EnumMap)]
    /// enum Example {
    ///     A,
    /// }
    ///
    /// fn main() {
    ///     let enum_map = EnumMap::<_, i32>::new();
    ///     assert_eq!(enum_map[Example::A], 0);
    /// }
    /// ```
    pub fn new() -> Self {
        EnumMap::default()
    }
}

impl<K: Internal<V>, V> EnumMap<K, V> {
    /// Returns number of elements in enum map.
    pub fn len(&self) -> usize {
        self.as_slice().len()
    }

    /// Returns whether the enum variant set is empty.
    ///
    /// This isn't particularly useful, as there is no real reason to use
    /// enum map for enums without variants. However, it is provided for
    /// consistency with data structures providing len method (and I will
    /// admit, to avoid clippy warnings).
    ///
    /// # Examples
    ///
    /// ```
    /// #[macro_use]
    /// extern crate enum_map;
    ///
    /// use enum_map::EnumMap;
    ///
    /// #[derive(EnumMap)]
    /// enum Void {}
    ///
    /// #[derive(EnumMap)]
    /// enum SingleVariant {
    ///     Variant,
    /// }
    ///
    /// fn main() {
    ///     assert_eq!(EnumMap::<Void, ()>::new().is_empty(), true);
    ///     assert_eq!(EnumMap::<SingleVariant, ()>::new().is_empty(), false);
    /// }
    pub fn is_empty(&self) -> bool {
        self.as_slice().is_empty()
    }

    /// Returns an iterator over enum map.
    pub fn iter(&self) -> Iter<K, V> {
        self.into_iter()
    }

    /// Returns a mutable iterator over enum map.
    pub fn iter_mut(&mut self) -> IterMut<K, V> {
        self.into_iter()
    }

    /// Swaps two indexes.
    ///
    /// # Examples
    ///
    /// ```
    /// #[macro_use]
    /// extern crate enum_map;
    ///
    /// fn main() {
    ///     let mut map = enum_map! { false => 0, true => 1 };
    ///     map.swap(false, true);
    ///     assert_eq!(map[false], 1);
    ///     assert_eq!(map[true], 0);
    /// }
    /// ```
    pub fn swap(&mut self, a: K, b: K) {
        self.as_mut_slice().swap(a.to_usize(), b.to_usize())
    }

    /// An iterator visiting all values. The iterator type is `&V`.
    ///
    /// # Examples
    ///
    /// ```
    /// #[macro_use]
    /// extern crate enum_map;
    ///
    /// fn main() {
    ///     let map = enum_map! { false => 3, true => 4 };
    ///     let mut values = map.values();
    ///     assert_eq!(values.next(), Some(&3));
    ///     assert_eq!(values.next(), Some(&4));
    ///     assert_eq!(values.next(), None);
    /// }
    /// ```
    pub fn values(&self) -> slice::Iter<V> {
        self.as_slice().iter()
    }

    /// An iterator visiting all values mutably. The iterator type is `&mut V`.
    ///
    /// # Examples
    ///
    /// ```
    /// #[macro_use]
    /// extern crate enum_map;
    ///
    /// fn main() {
    ///     let mut map = enum_map! { _ => 2 };
    ///     for value in map.values_mut() {
    ///         *value += 2;
    ///     }
    ///     assert_eq!(map[false], 4);
    ///     assert_eq!(map[true], 4);
    /// }
    /// ```
    pub fn values_mut(&mut self) -> slice::IterMut<V> {
        self.as_mut_slice().iter_mut()
    }

    /// Converts an enum map to a slice representing values.
    pub fn as_slice(&self) -> &[V] {
        K::slice(&self.array)
    }

    /// Converts a mutable enum map to a mutable slice representing values.
    pub fn as_mut_slice(&mut self) -> &mut [V] {
        K::slice_mut(&mut self.array)
    }

    /// Returns a raw pointer to the enum map's buffer.
    ///
    /// The caller must ensure that the slice outlives the pointer this
    /// function returns, or else it will end up pointing to garbage.
    ///
    /// Modifying the container referenced by this slice may cause its buffer
    /// to be reallocated, which would also make any pointers to it invalid.
    ///
    /// # Examples
    ///
    /// ```
    /// #[macro_use]
    /// extern crate enum_map;
    ///
    /// use enum_map::EnumMap;
    ///
    /// fn main() {
    ///     let map = enum_map! { 5 => 42, _ => 0 };
    ///     assert_eq!(unsafe { *map.as_ptr().offset(5) }, 42);
    /// }
    /// ```
    pub fn as_ptr(&self) -> *const V {
        self.as_slice().as_ptr()
    }

    /// Returns an unsafe mutable pointer to the enum map's buffer.
    ///
    /// The caller must ensure that the slice outlives the pointer this
    /// function returns, or else it will end up pointing to garbage.
    ///
    /// Modifying the container referenced by this slice may cause its buffer
    /// to be reallocated, which would also make any pointers to it invalid.
    ///
    /// # Examples
    ///
    /// ```
    /// #[macro_use]
    /// extern crate enum_map;
    ///
    /// use enum_map::EnumMap;
    ///
    /// fn main() {
    ///     let mut map = enum_map! { _ => 0 };
    ///     unsafe {
    ///         *map.as_mut_ptr().offset(11) = 23
    ///     };
    ///     assert_eq!(map[11], 23);
    /// }
    /// ```
    pub fn as_mut_ptr(&mut self) -> *mut V {
        self.as_mut_slice().as_mut_ptr()
    }
}

impl<F: FnMut(K) -> V, K: Internal<V>, V> From<F> for EnumMap<K, V> {
    fn from(f: F) -> Self {
        EnumMap { array: K::from_function(f) }
    }
}

/// Enum map constructor.
///
/// This macro allows to create a new enum map in a type safe way. It takes
/// a list of `,` separated pairs separated by `=>`. Left side is `|`
/// separated list of enum keys, or `_` to match all unmatched enum keys,
/// while right side is a value.
///
/// # Examples
///
/// ```
/// #[macro_use]
/// extern crate enum_map;
///
/// #[derive(EnumMap)]
/// enum Example {
///     A,
///     B,
///     C,
///     D,
/// }
///
/// fn main() {
///     let enum_map = enum_map! {
///         Example::A | Example::B => 1,
///         Example::C => 2,
///         _ => 3,
///     };
///     assert_eq!(enum_map[Example::A], 1);
///     assert_eq!(enum_map[Example::B], 1);
///     assert_eq!(enum_map[Example::C], 2);
///     assert_eq!(enum_map[Example::D], 3);
/// }
/// ```
#[macro_export]
macro_rules! enum_map {
    {$($t:tt)*} => {
        $crate::EnumMap::from(|k| match k { $($t)* })
    };
}
<commit_msg>Also add Examples header to EnumMap::new<commit_after>//! An enum mapping type.
//!
//! It is implemented using an array type, so using it is as fast as using Rust
//! arrays.
//!
//! # Examples
//!
//! ```
//! #[macro_use]
//! extern crate enum_map;
//!
//! use enum_map::EnumMap;
//!
//! #[derive(Debug, EnumMap)]
//! enum Example {
//!     A,
//!     B,
//!     C,
//! }
//!
//! fn main() {
//!     let mut map = enum_map! {
//!         Example::A => 1,
//!         Example::B => 2,
//!         Example::C => 3,
//!     };
//!     map[Example::C] = 4;
//!
//!     assert_eq!(map[Example::A], 1);
//!
//!     for (key, &value) in &map {
//!         println!("{:?} has {} as value.", key, value);
//!     }
//! }
//! ```

#![no_std]
#![deny(missing_docs)]

#[macro_use]
extern crate array_macro;
// This allows to quiet "proc macro crates and `#[no_link]` crates have no
// effect without `#[macro_use]`" warning. Just using extern DOES have
// an effect of letting me export the macro.
#[allow(unused_imports)]
#[macro_use]
extern crate enum_map_derive;

mod enummap_impls;
mod internal;
mod iter;
mod serde;

pub use internal::Internal;
pub use iter::{Iter, IterMut};
// `*` here means re-exporting a derive procedural macro.
pub use enum_map_derive::*;

use core::slice;

/// An enum mapping.
///
/// This internally uses an array which stores a value for each possible
/// enum value. To work, it requires implementation of internal (private,
/// although public due to macro limitations) trait which allows extracting
/// information about an enum, which can be automatically generated using
/// `#[derive(EnumMap)]` from `enum_map_derive` crate.
///
/// Additionally, `bool` and `u8` automatically derives from `EnumMap`. While
/// `u8` is not technically an enum, it's convenient to consider it like one.
/// In particular, [reverse-complement in benchmark game] could be using `u8`
/// as an enum.
///
/// # Examples
///
/// ```
/// #[macro_use]
/// extern crate enum_map;
///
/// use enum_map::EnumMap;
///
/// #[derive(EnumMap)]
/// enum Example {
///     A,
///     B,
///     C,
/// }
///
/// fn main() {
///     let mut map = EnumMap::new();
///     // new initializes map with default values
///     assert_eq!(map[Example::A], 0);
///     map[Example::A] = 3;
///     assert_eq!(map[Example::A], 3);
/// }
/// ```
///
/// [reverse-complement in benchmark game]:
///     http://benchmarksgame.alioth.debian.org/u64q/program.php?test=revcomp&lang=rust&id=2
#[derive(Debug)]
pub struct EnumMap<K: Internal<V>, V> {
    array: K::Array,
}

impl<K: Internal<V>, V: Default> EnumMap<K, V>
where
    K::Array: Default,
{
    /// Creates an enum map with default values.
    ///
    /// # Examples
    ///
    /// ```
    /// #[macro_use]
    /// extern crate enum_map;
    ///
    /// use enum_map::EnumMap;
    ///
    /// #[derive(EnumMap)]
    /// enum Example {
    ///     A,
    /// }
    ///
    /// fn main() {
    ///     let enum_map = EnumMap::<_, i32>::new();
    ///     assert_eq!(enum_map[Example::A], 0);
    /// }
    /// ```
    pub fn new() -> Self {
        EnumMap::default()
    }
}

impl<K: Internal<V>, V> EnumMap<K, V> {
    /// Returns number of elements in enum map.
    pub fn len(&self) -> usize {
        self.as_slice().len()
    }

    /// Returns whether the enum variant set is empty.
    ///
    /// This isn't particularly useful, as there is no real reason to use
    /// enum map for enums without variants. However, it is provided for
    /// consistency with data structures providing len method (and I will
    /// admit, to avoid clippy warnings).
    ///
    /// # Examples
    ///
    /// ```
    /// #[macro_use]
    /// extern crate enum_map;
    ///
    /// use enum_map::EnumMap;
    ///
    /// #[derive(EnumMap)]
    /// enum Void {}
    ///
    /// #[derive(EnumMap)]
    /// enum SingleVariant {
    ///     Variant,
    /// }
    ///
    /// fn main() {
    ///     assert_eq!(EnumMap::<Void, ()>::new().is_empty(), true);
    ///     assert_eq!(EnumMap::<SingleVariant, ()>::new().is_empty(), false);
    /// }
    pub fn is_empty(&self) -> bool {
        self.as_slice().is_empty()
    }

    /// Returns an iterator over enum map.
    pub fn iter(&self) -> Iter<K, V> {
        self.into_iter()
    }

    /// Returns a mutable iterator over enum map.
    pub fn iter_mut(&mut self) -> IterMut<K, V> {
        self.into_iter()
    }

    /// Swaps two indexes.
    ///
    /// # Examples
    ///
    /// ```
    /// #[macro_use]
    /// extern crate enum_map;
    ///
    /// fn main() {
    ///     let mut map = enum_map! { false => 0, true => 1 };
    ///     map.swap(false, true);
    ///     assert_eq!(map[false], 1);
    ///     assert_eq!(map[true], 0);
    /// }
    /// ```
    pub fn swap(&mut self, a: K, b: K) {
        self.as_mut_slice().swap(a.to_usize(), b.to_usize())
    }

    /// An iterator visiting all values. The iterator type is `&V`.
    ///
    /// # Examples
    ///
    /// ```
    /// #[macro_use]
    /// extern crate enum_map;
    ///
    /// fn main() {
    ///     let map = enum_map! { false => 3, true => 4 };
    ///     let mut values = map.values();
    ///     assert_eq!(values.next(), Some(&3));
    ///     assert_eq!(values.next(), Some(&4));
    ///     assert_eq!(values.next(), None);
    /// }
    /// ```
    pub fn values(&self) -> slice::Iter<V> {
        self.as_slice().iter()
    }

    /// An iterator visiting all values mutably. The iterator type is `&mut V`.
    ///
    /// # Examples
    ///
    /// ```
    /// #[macro_use]
    /// extern crate enum_map;
    ///
    /// fn main() {
    ///     let mut map = enum_map! { _ => 2 };
    ///     for value in map.values_mut() {
    ///         *value += 2;
    ///     }
    ///     assert_eq!(map[false], 4);
    ///     assert_eq!(map[true], 4);
    /// }
    /// ```
    pub fn values_mut(&mut self) -> slice::IterMut<V> {
        self.as_mut_slice().iter_mut()
    }

    /// Converts an enum map to a slice representing values.
    pub fn as_slice(&self) -> &[V] {
        K::slice(&self.array)
    }

    /// Converts a mutable enum map to a mutable slice representing values.
    pub fn as_mut_slice(&mut self) -> &mut [V] {
        K::slice_mut(&mut self.array)
    }

    /// Returns a raw pointer to the enum map's buffer.
    ///
    /// The caller must ensure that the slice outlives the pointer this
    /// function returns, or else it will end up pointing to garbage.
    ///
    /// Modifying the container referenced by this slice may cause its buffer
    /// to be reallocated, which would also make any pointers to it invalid.
    ///
    /// # Examples
    ///
    /// ```
    /// #[macro_use]
    /// extern crate enum_map;
    ///
    /// use enum_map::EnumMap;
    ///
    /// fn main() {
    ///     let map = enum_map! { 5 => 42, _ => 0 };
    ///     assert_eq!(unsafe { *map.as_ptr().offset(5) }, 42);
    /// }
    /// ```
    pub fn as_ptr(&self) -> *const V {
        self.as_slice().as_ptr()
    }

    /// Returns an unsafe mutable pointer to the enum map's buffer.
    ///
    /// The caller must ensure that the slice outlives the pointer this
    /// function returns, or else it will end up pointing to garbage.
    ///
    /// Modifying the container referenced by this slice may cause its buffer
    /// to be reallocated, which would also make any pointers to it invalid.
    ///
    /// # Examples
    ///
    /// ```
    /// #[macro_use]
    /// extern crate enum_map;
    ///
    /// use enum_map::EnumMap;
    ///
    /// fn main() {
    ///     let mut map = enum_map! { _ => 0 };
    ///     unsafe {
    ///         *map.as_mut_ptr().offset(11) = 23
    ///     };
    ///     assert_eq!(map[11], 23);
    /// }
    /// ```
    pub fn as_mut_ptr(&mut self) -> *mut V {
        self.as_mut_slice().as_mut_ptr()
    }
}

impl<F: FnMut(K) -> V, K: Internal<V>, V> From<F> for EnumMap<K, V> {
    fn from(f: F) -> Self {
        EnumMap { array: K::from_function(f) }
    }
}

/// Enum map constructor.
///
/// This macro allows to create a new enum map in a type safe way. It takes
/// a list of `,` separated pairs separated by `=>`. Left side is `|`
/// separated list of enum keys, or `_` to match all unmatched enum keys,
/// while right side is a value.
///
/// # Examples
///
/// ```
/// #[macro_use]
/// extern crate enum_map;
///
/// #[derive(EnumMap)]
/// enum Example {
///     A,
///     B,
///     C,
///     D,
/// }
///
/// fn main() {
///     let enum_map = enum_map! {
///         Example::A | Example::B => 1,
///         Example::C => 2,
///         _ => 3,
///     };
///     assert_eq!(enum_map[Example::A], 1);
///     assert_eq!(enum_map[Example::B], 1);
///     assert_eq!(enum_map[Example::C], 2);
///     assert_eq!(enum_map[Example::D], 3);
/// }
/// ```
#[macro_export]
macro_rules! enum_map {
    {$($t:tt)*} => {
        $crate::EnumMap::from(|k| match k { $($t)* })
    };
}
<|endoftext|>


<commit_before>#![feature(plugin)]

#![plugin(clippy)]

#![deny(clippy)]
#![deny(clippy_pedantic)]
#![allow(print_stdout)]
#![allow(clone_on_copy)]
#![allow(many_single_char_names)]

#![allow(use_debug)]

#[derive(Debug)]
struct Moo{
    a:i32, //I guess no one else can access these fields(unless marked pub) except me from within here
    b:i32,
    c:String
}

fn main() {
    let mut a = [1, 2, 3, 4, 5];

    //implicit copying OR moving - the bane of Rust :)
    let first = a[0]; //can I prevent this Copy from happening? a lint for it? eg. I actually wanted &a[0] or a move
    let oldfirst = a[0].clone();//this is acceptable! but implicitly copy like above isn't! TODO: find a way to disable Copy trait!

    a[0] = 7;
    let reffirst:&i32 = &a[0]; //TODO: find out how to keep a ref and still allow assignment - eg. move this line above the assignment line a[0]=7; and have it work!

    println!("The value of first is: {} {} {}", first, oldfirst, reffirst);

    //same syntax can do either an implicity copy or an implicit move - i'd rather have one or the
    //other! if not at least warn me?
    let a1 = [1,2,3];
    let first1 = a[0]; // implicit copy
    let second = a[1];
    let b = [String::from("1"),String::from("2"),String::from("3")];
//    let fb=b[0]; // this wants to do an implicit move
//    let sb=b[1];

    let meh = String::from("meh");
    let mut x=Moo{a:1,b:2,c:meh};
//    println!("{}",meh);//meh was moved! awesome! i approve
//    let y=x;//moved!
    let y=x.a;//copy!
    x.a=3;//bye bye stale value y, right now.
    println!("{:?} {}",x,y);

    let z=&x.a;//borrowed! eg.temp moved!
//    x.a=4;//can't do this! this is great!
//    TODO: how do I do explicit move tho?
    println!("{:?} {}",x,y);
    {
        let mut q=x.c;//implicitly moved.
    //    println!("{:?}",x);//can't do this: use of partially moved value!
        q.push_str("something");
    //    but can still access the other fields meanwhile. hmm...
        let somethingelse=x.a;//hmm, maybe this isn't as bad as I thought...or is it? I'm unsure... will get back to this after I know more!
        x.c=q;//move it back!
//        x.c=String::from("meh2");//or, assign new stuff instead - so it's not partially moved
//        value anymore!
    }//block has no effect, I just have to move it back manually! obv.
    println!("{:?}",x);

//    let a=1;
//    let a=2;//not allowed by clippy - this is why I love it! hehe
}
<commit_msg> #goodgirlclippy<commit_after>#![feature(plugin)]

#![plugin(clippy)]

#![deny(clippy)]
#![deny(clippy_pedantic)]
#![allow(print_stdout)]
#![allow(clone_on_copy)]
#![allow(many_single_char_names)]

#![allow(use_debug)]

#[derive(Debug)]
struct Moo{
    a:i32, //I guess no one else can access these fields(unless marked pub) except me from within here
    b:i32,
    c:String
}

fn main() {
    let mut a = [1, 2, 3, 4, 5];

    //implicit copying OR moving - the bane of Rust :)
    let first = a[0]; //can I prevent this Copy from happening? a lint for it? eg. I actually wanted &a[0] or a move
    let oldfirst = a[0].clone();//this is acceptable! but implicitly copy like above isn't! TODO: find a way to disable Copy trait!

    a[0] = 7;
    let reffirst:&i32 = &a[0]; //TODO: find out how to keep a ref and still allow assignment - eg. move this line above the assignment line a[0]=7; and have it work!

    println!("The value of first is: {} {} {}", first, oldfirst, reffirst);

    //same syntax can do either an implicity copy or an implicit move - i'd rather have one or the
    //other! if not at least warn me?
    let a1 = [1,2,3];
    let first1 = a[0]; // implicit copy
    let second = a[1];
    let b = [String::from("1"),String::from("2"),String::from("3")];
//    let fb=b[0]; // this wants to do an implicit move
//    let sb=b[1];

    let meh = String::from("meh");
    let mut x=Moo{a:1,b:2,c:meh};
//    println!("{}",meh);//meh was moved! awesome! i approve
//    let y=x;//moved!
    let y=x.a;//copy!
    x.a=3;//bye bye stale value y, right now.
    println!("{:?} {}",x,y);

    let z=&x.a;//borrowed! eg.temp moved!
//    x.a=4;//can't do this! this is great!
//    TODO: how do I do explicit move tho?
    println!("{:?} {}",x,y);
    {
        let mut q=x.c;//implicitly moved.
    //    println!("{:?}",x);//can't do this: use of partially moved value!
        q.push_str("something");
    //    but can still access the other fields meanwhile. hmm...
        let somethingelse=x.a;//hmm, maybe this isn't as bad as I thought...or is it? I'm unsure... will get back to this after I know more!
        x.c=q;//move it back!
//        x.c=String::from("meh2");//or, assign new stuff instead - so it's not partially moved
//        value anymore!
    }//block has no effect, I just have to move it back manually! obv.
    println!("{:?}",x);

//    let a=1;
//    let a=2;//not allowed by clippy - this is why I love it! hehe
//
    //1; // #goodgirlclippy
    //2;
    //3;
}
<|endoftext|>


<commit_before>extern crate pancurses;
extern crate rand;

use pancurses::*;

use rand::Rng;

const AUS_MAP: [&str; 13] = [
    "                       A ",
    "           AA         AA ",
    "    N.T. AAAAA       AAAA ",
    "     AAAAAAAAAAA  AAAAAAAA ",
    "   AAAAAAAAAAAAAAAAAAAAAAAAA Qld.",
    " AAAAAAAAAAAAAAAAAAAAAAAAAAAA ",
    " AAAAAAAAAAAAAAAAAAAAAAAAAAAAA ",
    " AAAAAAAAAAAAAAAAAAAAAAAAAAAA ",
    "   AAAAAAAAAAAAAAAAAAAAAAAAA N.S.W.",
    "W.A. AAAAAAAAA      AAAAAA Vic.",
    "       AAA   S.A.     AA",
    "                       A  Tas.",
    "",
];

const MESSAGES: [&str; 6] = [
    "Hello from the Land Down Under",
    "The Land of crocs, and a big Red Rock",
    "Where the sunflower runs along the highways",
    "The dusty red roads lead one to loneliness",
    "Blue sky in the morning and",
    "Freezing nights and twinkling stars",
];

fn main() {
    let main_window = initscr();

    start_color();

    use_default_colors();

    cbreak();
    noecho();

    curs_set(0);

    // Refresh stdscr so that reading from it will not cause it to  overwrite the other windows
    // that are being created
    main_window.refresh();

    // Create a drawing window
    let width = 48;
    let height = 15;

    let win = newwin(
        height,
        width,
        (main_window.get_max_y() - height) / 2,
        (main_window.get_max_x() - width) / 2,
    );

    loop {
        init_pair(1, COLOR_WHITE, COLOR_BLUE);
        win.bkgd(COLOR_PAIR(1));
        win.erase();

        init_pair(2, COLOR_RED, COLOR_RED);
        win.attrset(ColorPair(2));
        win.draw_box(' ', ' ');
        win.refresh();

        win.attrset(Attribute::Normal);

        // Do random output of a character

        let mut ch = 'a';

        main_window.nodelay(true);

        let mut rng = rand::thread_rng();

        for i in 0..5000 {
            let x = (rng.gen::<i32>() % (width - 2)).abs() + 1;
            let y = (rng.gen::<i32>() % (height - 2)).abs() + 1;

            assert!(x != 0);
            assert!(y != 0);
            win.mvaddch(y, x, ch);
            win.refresh();

            if main_window.getch().is_some() {
                break;
            }

            if i == 2000 {
                ch = 'b';
                init_pair(3, COLOR_CYAN, COLOR_YELLOW);
                win.attrset(ColorPair(3));
            }
        }

        main_window.nodelay(false);

        sub_win_test(&main_window, &win).unwrap();

        // Erase and draw green window

        init_pair(4, COLOR_YELLOW, COLOR_GREEN);
        win.bkgd(COLOR_PAIR(4));
        win.attrset(Attribute::Bold);
        win.erase();
        win.refresh();

        // Draw RED bounding box

        win.attrset(ColorPair(2));
        win.draw_box(' ', ' ');
        win.refresh();

        // Display Australia map

        win.attrset(Attribute::Bold);

        for (i, s) in AUS_MAP.into_iter().enumerate() {
            win.mvaddstr(i as i32 + 1, 8, s);
            win.refresh();
            napms(100);
        }

        init_pair(5, COLOR_BLUE, COLOR_WHITE);
        win.attrset(ColorPair(5) | Attribute::Blink);
        win.mvaddstr(height - 2, 3, " pancurses - Linux, Win32");
        win.refresh();

        // Draw running messages

        init_pair(6, COLOR_BLACK, COLOR_WHITE);
        win.attrset(ColorPair(6));
        let w = width - 2;
        win.nodelay(true);

        // jbuhler's re-hacked scrolling messages

        for message in &MESSAGES {
            let msg_len = message.len() as i32;
            let mut visbuf = String::with_capacity(w as usize);
            let mut stop = false;

            for i in (0..w + msg_len).rev() {
                visbuf.clear();
                for visbuf_i in 0..visbuf.capacity() {
                    let i = i - msg_len as i32;
                    let char_index = visbuf_i as i32 - i;
                    let ch = if char_index >= 0 && char_index < message.len() as i32 {
                        let char_index = char_index as usize;
                        match message[char_index..char_index + 1].chars().next() {
                            Some(c) => c,
                            None => ' ',
                        }
                    } else {
                        ' '
                    };
                    visbuf.push(ch);
                }

                win.mvaddstr(height / 2, 1, &visbuf);
                win.refresh();

                if win.getch().is_some() {
                    flushinp();
                    stop = true;
                    break;
                }

                napms(100);
            }

            if stop {
                break;
            }
        }

        // Draw running 'A's across in RED

        init_pair(7, COLOR_RED, COLOR_GREEN);
        win.attron(ColorPair(7));

        let mut save: [chtype; 80] = [0; 80];

        for (index, pos) in (2..width - 4).enumerate() {
            let ch = win.mvinch(5, pos);
            save[index] = ch;
            let ch = ch & 0x7F;
            win.mvaddch(5, pos, ch);
        }

        win.refresh();

        // Put a message up; wait for a key

        let i = height - 2;
        win.attrset(ColorPair(5));
        win.mvaddstr(i, 3, "   Type a key to continue or ESC to quit  ");
        win.refresh();

        if wait_for_user(&main_window) {
            break;
        }

        // Restore the old line

        win.attrset(Attribute::Normal);

        for (index, pos) in (2..width - 4).enumerate() {
            win.mvaddch(5, pos, save[index]);
        }

        win.refresh();

        bouncing_balls(&main_window, &win, &mut rng);

        // bouncing_balls() leaves a keystroke in the queue

        if wait_for_user(&main_window) {
            break;
        }
    }

    endwin();
}

fn wait_for_user(main_window: &Window) -> bool {
    main_window.nodelay(true);
    half_delay(50);

    let ch = main_window.getch();

    main_window.nodelay(false);
    nocbreak(); // Reset the halfdelay() value
    cbreak();

    match ch {
        Some(Input::Character('\x1B')) => true,
        _ => false,
    }
}

fn sub_win_test(main_window: &Window, win: &Window) -> Result<(), i32> {
    win.attrset(Attribute::Normal);
    let (h, w) = win.get_max_yx();
    let (by, bx) = win.get_beg_yx();

    let sw = w / 3;
    let sh = h / 3;

    let swin1 = try!(win.derwin(sh, sw, 3, 5));
    let swin2 = try!(win.subwin(sh, sw, by + 4, bx + 8));
    let swin3 = try!(win.subwin(sh, sw, by + 5, bx + 11));

    init_pair(8, COLOR_RED, COLOR_BLUE);
    swin1.bkgd(COLOR_PAIR(8));
    swin1.erase();
    swin1.mvaddstr(0, 3, "Sub-window 1");
    swin1.refresh();

    init_pair(9, COLOR_CYAN, COLOR_MAGENTA);
    swin2.bkgd(COLOR_PAIR(9));
    swin2.erase();
    swin2.mvaddstr(0, 3, "Sub-window 2");
    swin2.refresh();

    init_pair(10, COLOR_YELLOW, COLOR_GREEN);
    swin3.bkgd(COLOR_PAIR(10));
    swin3.erase();
    swin3.mvaddstr(0, 3, "Sub-window 3");
    swin3.refresh();

    swin1.delwin();
    swin2.delwin();
    swin3.delwin();

    wait_for_user(main_window);

    Ok(())
}

fn bouncing_balls<T: Rng>(main_window: &Window, win: &Window, rng: &mut T) {
    curs_set(0);

    win.bkgd(COLOR_PAIR(1));
    win.refresh();
    win.attrset(Attribute::Normal);

    init_pair(11, COLOR_RED, COLOR_GREEN);
    init_pair(12, COLOR_BLUE, COLOR_RED);
    init_pair(13, COLOR_YELLOW, COLOR_WHITE);

    let ball1 = 'O' as chtype | COLOR_PAIR(11);
    let ball2 = '*' as chtype | COLOR_PAIR(12);
    let ball3 = '@' as chtype | COLOR_PAIR(13);

    let (h, w) = win.get_max_yx();

    let mut x1 = 2 + (rng.gen::<i32>() % (w - 4)).abs();
    let mut y1 = 2 + (rng.gen::<i32>() % (h - 4)).abs();
    let mut x2 = 2 + (rng.gen::<i32>() % (w - 4)).abs();
    let mut y2 = 2 + (rng.gen::<i32>() % (h - 4)).abs();
    let mut x3 = 2 + (rng.gen::<i32>() % (w - 4)).abs();
    let mut y3 = 2 + (rng.gen::<i32>() % (h - 4)).abs();

    let mut xd1 = 1;
    let mut yd1 = 1;
    let mut xd2 = 1;
    let mut yd2 = -1;
    let mut xd3 = -1;
    let mut yd3 = 1;

    main_window.nodelay(true);

    let mut c = main_window.getch();
    while c.is_none() {
        x1 += xd1;
        if x1 <= 1 || x1 >= w - 2 {
            xd1 *= -1;
        }

        y1 += yd1;
        if y1 <= 1 || y1 >= h - 2 {
            yd1 *= -1;
        }

        x2 += xd2;
        if x2 <= 1 || x2 >= w - 2 {
            xd2 *= -1;
        }

        y2 += yd2;
        if y2 <= 1 || y2 >= h - 2 {
            yd2 *= -1;
        }

        x3 += xd3;
        if x3 <= 1 || x3 >= w - 2 {
            xd3 *= -1;
        }

        y3 += yd3;
        if y3 <= 1 || y3 >= h - 2 {
            yd3 *= -1;
        }

        let c1 = win.mvinch(y1, x1);
        let c2 = win.mvinch(y2, x2);
        let c3 = win.mvinch(y3, x3);

        win.mvaddch(y1, x1, ball1);
        win.mvaddch(y2, x2, ball2);
        win.mvaddch(y3, x3, ball3);

        win.mv(0, 0);
        win.refresh();

        win.mvaddch(y1, x1, c1);
        win.mvaddch(y2, x2, c2);
        win.mvaddch(y3, x3, c3);

        napms(150);
        c = main_window.getch();
    }

    main_window.nodelay(false);
    c.map(|c| main_window.ungetch(&c));
}
<commit_msg>Remove try! so example compiles with 2018 edition<commit_after>extern crate pancurses;
extern crate rand;

use pancurses::*;

use rand::Rng;

const AUS_MAP: [&str; 13] = [
    "                       A ",
    "           AA         AA ",
    "    N.T. AAAAA       AAAA ",
    "     AAAAAAAAAAA  AAAAAAAA ",
    "   AAAAAAAAAAAAAAAAAAAAAAAAA Qld.",
    " AAAAAAAAAAAAAAAAAAAAAAAAAAAA ",
    " AAAAAAAAAAAAAAAAAAAAAAAAAAAAA ",
    " AAAAAAAAAAAAAAAAAAAAAAAAAAAA ",
    "   AAAAAAAAAAAAAAAAAAAAAAAAA N.S.W.",
    "W.A. AAAAAAAAA      AAAAAA Vic.",
    "       AAA   S.A.     AA",
    "                       A  Tas.",
    "",
];

const MESSAGES: [&str; 6] = [
    "Hello from the Land Down Under",
    "The Land of crocs, and a big Red Rock",
    "Where the sunflower runs along the highways",
    "The dusty red roads lead one to loneliness",
    "Blue sky in the morning and",
    "Freezing nights and twinkling stars",
];

fn main() {
    let main_window = initscr();

    start_color();

    use_default_colors();

    cbreak();
    noecho();

    curs_set(0);

    // Refresh stdscr so that reading from it will not cause it to  overwrite the other windows
    // that are being created
    main_window.refresh();

    // Create a drawing window
    let width = 48;
    let height = 15;

    let win = newwin(
        height,
        width,
        (main_window.get_max_y() - height) / 2,
        (main_window.get_max_x() - width) / 2,
    );

    loop {
        init_pair(1, COLOR_WHITE, COLOR_BLUE);
        win.bkgd(COLOR_PAIR(1));
        win.erase();

        init_pair(2, COLOR_RED, COLOR_RED);
        win.attrset(ColorPair(2));
        win.draw_box(' ', ' ');
        win.refresh();

        win.attrset(Attribute::Normal);

        // Do random output of a character

        let mut ch = 'a';

        main_window.nodelay(true);

        let mut rng = rand::thread_rng();

        for i in 0..5000 {
            let x = (rng.gen::<i32>() % (width - 2)).abs() + 1;
            let y = (rng.gen::<i32>() % (height - 2)).abs() + 1;

            assert!(x != 0);
            assert!(y != 0);
            win.mvaddch(y, x, ch);
            win.refresh();

            if main_window.getch().is_some() {
                break;
            }

            if i == 2000 {
                ch = 'b';
                init_pair(3, COLOR_CYAN, COLOR_YELLOW);
                win.attrset(ColorPair(3));
            }
        }

        main_window.nodelay(false);

        sub_win_test(&main_window, &win).unwrap();

        // Erase and draw green window

        init_pair(4, COLOR_YELLOW, COLOR_GREEN);
        win.bkgd(COLOR_PAIR(4));
        win.attrset(Attribute::Bold);
        win.erase();
        win.refresh();

        // Draw RED bounding box

        win.attrset(ColorPair(2));
        win.draw_box(' ', ' ');
        win.refresh();

        // Display Australia map

        win.attrset(Attribute::Bold);

        for (i, s) in AUS_MAP.into_iter().enumerate() {
            win.mvaddstr(i as i32 + 1, 8, s);
            win.refresh();
            napms(100);
        }

        init_pair(5, COLOR_BLUE, COLOR_WHITE);
        win.attrset(ColorPair(5) | Attribute::Blink);
        win.mvaddstr(height - 2, 3, " pancurses - Linux, Win32");
        win.refresh();

        // Draw running messages

        init_pair(6, COLOR_BLACK, COLOR_WHITE);
        win.attrset(ColorPair(6));
        let w = width - 2;
        win.nodelay(true);

        // jbuhler's re-hacked scrolling messages

        for message in &MESSAGES {
            let msg_len = message.len() as i32;
            let mut visbuf = String::with_capacity(w as usize);
            let mut stop = false;

            for i in (0..w + msg_len).rev() {
                visbuf.clear();
                for visbuf_i in 0..visbuf.capacity() {
                    let i = i - msg_len as i32;
                    let char_index = visbuf_i as i32 - i;
                    let ch = if char_index >= 0 && char_index < message.len() as i32 {
                        let char_index = char_index as usize;
                        match message[char_index..char_index + 1].chars().next() {
                            Some(c) => c,
                            None => ' ',
                        }
                    } else {
                        ' '
                    };
                    visbuf.push(ch);
                }

                win.mvaddstr(height / 2, 1, &visbuf);
                win.refresh();

                if win.getch().is_some() {
                    flushinp();
                    stop = true;
                    break;
                }

                napms(100);
            }

            if stop {
                break;
            }
        }

        // Draw running 'A's across in RED

        init_pair(7, COLOR_RED, COLOR_GREEN);
        win.attron(ColorPair(7));

        let mut save: [chtype; 80] = [0; 80];

        for (index, pos) in (2..width - 4).enumerate() {
            let ch = win.mvinch(5, pos);
            save[index] = ch;
            let ch = ch & 0x7F;
            win.mvaddch(5, pos, ch);
        }

        win.refresh();

        // Put a message up; wait for a key

        let i = height - 2;
        win.attrset(ColorPair(5));
        win.mvaddstr(i, 3, "   Type a key to continue or ESC to quit  ");
        win.refresh();

        if wait_for_user(&main_window) {
            break;
        }

        // Restore the old line

        win.attrset(Attribute::Normal);

        for (index, pos) in (2..width - 4).enumerate() {
            win.mvaddch(5, pos, save[index]);
        }

        win.refresh();

        bouncing_balls(&main_window, &win, &mut rng);

        // bouncing_balls() leaves a keystroke in the queue

        if wait_for_user(&main_window) {
            break;
        }
    }

    endwin();
}

fn wait_for_user(main_window: &Window) -> bool {
    main_window.nodelay(true);
    half_delay(50);

    let ch = main_window.getch();

    main_window.nodelay(false);
    nocbreak(); // Reset the halfdelay() value
    cbreak();

    match ch {
        Some(Input::Character('\x1B')) => true,
        _ => false,
    }
}

fn sub_win_test(main_window: &Window, win: &Window) -> Result<(), i32> {
    win.attrset(Attribute::Normal);
    let (h, w) = win.get_max_yx();
    let (by, bx) = win.get_beg_yx();

    let sw = w / 3;
    let sh = h / 3;

    let swin1 = win.derwin(sh, sw, 3, 5)?;
    let swin2 = win.subwin(sh, sw, by + 4, bx + 8)?;
    let swin3 = win.subwin(sh, sw, by + 5, bx + 11)?;

    init_pair(8, COLOR_RED, COLOR_BLUE);
    swin1.bkgd(COLOR_PAIR(8));
    swin1.erase();
    swin1.mvaddstr(0, 3, "Sub-window 1");
    swin1.refresh();

    init_pair(9, COLOR_CYAN, COLOR_MAGENTA);
    swin2.bkgd(COLOR_PAIR(9));
    swin2.erase();
    swin2.mvaddstr(0, 3, "Sub-window 2");
    swin2.refresh();

    init_pair(10, COLOR_YELLOW, COLOR_GREEN);
    swin3.bkgd(COLOR_PAIR(10));
    swin3.erase();
    swin3.mvaddstr(0, 3, "Sub-window 3");
    swin3.refresh();

    swin1.delwin();
    swin2.delwin();
    swin3.delwin();

    wait_for_user(main_window);

    Ok(())
}

fn bouncing_balls<T: Rng>(main_window: &Window, win: &Window, rng: &mut T) {
    curs_set(0);

    win.bkgd(COLOR_PAIR(1));
    win.refresh();
    win.attrset(Attribute::Normal);

    init_pair(11, COLOR_RED, COLOR_GREEN);
    init_pair(12, COLOR_BLUE, COLOR_RED);
    init_pair(13, COLOR_YELLOW, COLOR_WHITE);

    let ball1 = 'O' as chtype | COLOR_PAIR(11);
    let ball2 = '*' as chtype | COLOR_PAIR(12);
    let ball3 = '@' as chtype | COLOR_PAIR(13);

    let (h, w) = win.get_max_yx();

    let mut x1 = 2 + (rng.gen::<i32>() % (w - 4)).abs();
    let mut y1 = 2 + (rng.gen::<i32>() % (h - 4)).abs();
    let mut x2 = 2 + (rng.gen::<i32>() % (w - 4)).abs();
    let mut y2 = 2 + (rng.gen::<i32>() % (h - 4)).abs();
    let mut x3 = 2 + (rng.gen::<i32>() % (w - 4)).abs();
    let mut y3 = 2 + (rng.gen::<i32>() % (h - 4)).abs();

    let mut xd1 = 1;
    let mut yd1 = 1;
    let mut xd2 = 1;
    let mut yd2 = -1;
    let mut xd3 = -1;
    let mut yd3 = 1;

    main_window.nodelay(true);

    let mut c = main_window.getch();
    while c.is_none() {
        x1 += xd1;
        if x1 <= 1 || x1 >= w - 2 {
            xd1 *= -1;
        }

        y1 += yd1;
        if y1 <= 1 || y1 >= h - 2 {
            yd1 *= -1;
        }

        x2 += xd2;
        if x2 <= 1 || x2 >= w - 2 {
            xd2 *= -1;
        }

        y2 += yd2;
        if y2 <= 1 || y2 >= h - 2 {
            yd2 *= -1;
        }

        x3 += xd3;
        if x3 <= 1 || x3 >= w - 2 {
            xd3 *= -1;
        }

        y3 += yd3;
        if y3 <= 1 || y3 >= h - 2 {
            yd3 *= -1;
        }

        let c1 = win.mvinch(y1, x1);
        let c2 = win.mvinch(y2, x2);
        let c3 = win.mvinch(y3, x3);

        win.mvaddch(y1, x1, ball1);
        win.mvaddch(y2, x2, ball2);
        win.mvaddch(y3, x3, ball3);

        win.mv(0, 0);
        win.refresh();

        win.mvaddch(y1, x1, c1);
        win.mvaddch(y2, x2, c2);
        win.mvaddch(y3, x3, c3);

        napms(150);
        c = main_window.getch();
    }

    main_window.nodelay(false);
    c.map(|c| main_window.ungetch(&c));
}
<|endoftext|>


<commit_before>//! An example of using syntect for testing syntax definitions.
//! Basically exactly the same as what Sublime Text can do,
//! but without needing ST installed
extern crate syntect;
extern crate walkdir;
#[macro_use]
extern crate lazy_static;
extern crate regex;
//extern crate onig;
use syntect::parsing::{SyntaxSet, ParseState, ScopeStack, Scope};
use syntect::highlighting::ScopeSelectors;
use syntect::easy::{ScopeRegionIterator};

use std::path::Path;
use std::io::{BufRead, BufReader};
use std::fs::File;
use std::cmp::{min, max};
use walkdir::{DirEntry, WalkDir, WalkDirIterator};
use std::str::FromStr;
use regex::Regex;

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SyntaxTestHeaderError {
    MalformedHeader,
    SyntaxDefinitionNotFound,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SyntaxTestFileResult {
    FailedAssertions(usize, usize),
    Success(usize),
}

lazy_static! {
    pub static ref SYNTAX_TEST_HEADER_PATTERN: Regex = Regex::new(r#"(?xm)
            ^(?P<testtoken_start>\s*\S+)
            \s+SYNTAX\sTEST\s+
            "(?P<syntax_file>[^"]+)"
            \s*(?P<testtoken_end>\S+)?$
        "#).unwrap();
    pub static ref SYNTAX_TEST_ASSERTION_PATTERN: Regex = Regex::new(r#"(?xm)
        \s*(?:
            (?P<begin_of_token><-)|(?P<range>\^+)
        )(.+)$"#).unwrap();
}

#[derive(Debug)]
struct AssertionRange<'a> {
    begin_char: usize,
    end_char: usize,
    scope_selector_text: &'a str,
    is_pure_assertion_line: bool,
}

#[derive(Debug)]
struct ScopedText {
    scope: Vec<Scope>,
    char_start: usize,
    text_len: usize,
}

#[derive(Debug)]
struct RangeTestResult {
    column_begin: usize,
    column_end: usize,
    success: bool,
}

fn get_line_assertion_details<'a>(testtoken_start: &str, testtoken_end: Option<&str>, line: &'a str) -> Option<AssertionRange<'a>> {
    // if the test start token specified in the test file's header is on the line
    if let Some(index) = line.find(testtoken_start) {
        let (before_token_start, token_and_rest_of_line) = line.split_at(index);

        if let Some(captures) = SYNTAX_TEST_ASSERTION_PATTERN.captures(&token_and_rest_of_line[testtoken_start.len()..]) {
            let mut sst = captures.get(3).unwrap().as_str().trim_right(); // get the scope selector text
            if let Some(token) = testtoken_end { // if there is an end token defined in the test file header
                sst = sst.trim_right_matches(&token); // trim it from the scope selector text
            }
            return Some(AssertionRange {
                begin_char: index + if captures.get(2).is_some() { testtoken_start.len() + captures.get(2).unwrap().start() } else { 0 },
                end_char: index + if captures.get(2).is_some() { testtoken_start.len() + captures.get(2).unwrap().end() } else { 1 },
                scope_selector_text: sst,
                is_pure_assertion_line: before_token_start.trim_left().is_empty(), // if only whitespace precedes the test token on the line, then it is a pure assertion line
            })
        }
    }
    None
}

fn process_assertions(assertion: &AssertionRange, test_against_line_scopes: &Vec<ScopedText>) -> Vec<RangeTestResult> {
    // format the scope selector to include a space at the beginning, because, currently, ScopeSelector expects excludes to begin with " -"
    // and they are sometimes in the syntax test as ^^^-comment, for example
    let selector = ScopeSelectors::from_str(&format!(" {}", &assertion.scope_selector_text)).unwrap();
    // find the scope at the specified start column, and start matching the selector through the rest of the tokens on the line from there until the end column is reached
    let mut results = Vec::new();
    for scoped_text in test_against_line_scopes.iter().skip_while(|s|s.char_start + s.text_len <= assertion.begin_char).take_while(|s|s.char_start < assertion.end_char) {
        let match_value = selector.does_match(scoped_text.scope.as_slice());
        let result = RangeTestResult {
            column_begin: max(scoped_text.char_start, assertion.begin_char),
            column_end: min(scoped_text.char_start + scoped_text.text_len, assertion.end_char),
            success: match_value.is_some()
        };
        results.push(result);
    }
    // don't ignore assertions after the newline, they should be treated as though they are asserting against the newline
    let last = test_against_line_scopes.last().unwrap();
    if last.char_start + last.text_len < assertion.end_char {
        let match_value = selector.does_match(last.scope.as_slice());
        let result = RangeTestResult {
            column_begin: max(last.char_start + last.text_len, assertion.begin_char),
            column_end: assertion.end_char,
            success: match_value.is_some()
        };
        results.push(result);
    }
    results
}

fn test_file(ss: &SyntaxSet, path: &Path, parse_test_lines: bool) -> Result<SyntaxTestFileResult, SyntaxTestHeaderError> {
    let f = File::open(path).unwrap();
    let mut reader = BufReader::new(f);
    let mut line = String::new();

    // read the first line from the file - if we have reached EOF already, it's an invalid file
    if reader.read_line(&mut line).unwrap() == 0 {
        return Err(SyntaxTestHeaderError::MalformedHeader);
    }

    line = line.replace("\r", &"");

    // parse the syntax test header in the first line of the file
    match SYNTAX_TEST_HEADER_PATTERN.captures(&line.to_string()) {
        Some(captures) => {
            let testtoken_start = captures.name("testtoken_start").unwrap().as_str();
            let testtoken_end = captures.name("testtoken_end").map_or(None, |c|Some(c.as_str()));
            let syntax_file = captures.name("syntax_file").unwrap().as_str();

            // find the relevant syntax definition to parse the file with - case is important!
            println!("The test file references syntax definition file: {}", syntax_file);
            let syntax = match ss.find_syntax_by_path(syntax_file) {
                Some(syntax) => syntax,
                None => return Err(SyntaxTestHeaderError::SyntaxDefinitionNotFound)
            };

            let mut state = ParseState::new(syntax);
            let mut stack = ScopeStack::new();

            let mut current_line_number = 1;
            let mut test_against_line_number = 1;
            let mut scopes_on_line_being_tested = Vec::new();
            let mut previous_non_assertion_line = line.to_string();

            let mut assertion_failures: usize = 0;
            let mut total_assertions: usize = 0;

            loop {
                let mut line_only_has_assertion = false;
                let mut line_has_assertion = false;
                if let Some(assertion) = get_line_assertion_details(testtoken_start, testtoken_end, &line) {
                    let result = process_assertions(&assertion, &scopes_on_line_being_tested);
                    total_assertions += &assertion.end_char - &assertion.begin_char;
                    for failure in result.iter().filter(|r|!r.success) {
                        let chars: Vec<char> = previous_non_assertion_line.chars().skip(failure.column_begin).take(failure.column_end - failure.column_begin).collect();
                        println!("  Assertion selector {:?} \
                            from line {:?} failed against line {:?}, column range {:?}-{:?} \
                            (with text {:?}) \
                            has scope {:?}",
                            assertion.scope_selector_text.trim(),
                            current_line_number, test_against_line_number, failure.column_begin, failure.column_end,
                            chars,
                            scopes_on_line_being_tested.iter().skip_while(|s|s.char_start + s.text_len <= failure.column_begin).next().unwrap_or(scopes_on_line_being_tested.last().unwrap()).scope
                        );
                        assertion_failures += failure.column_end - failure.column_begin;
                    }
                    line_only_has_assertion = assertion.is_pure_assertion_line;
                    line_has_assertion = true;
                }
                if !line_only_has_assertion || parse_test_lines {
                    if !line_has_assertion { // ST seems to ignore lines that have assertions when calculating which line the assertion tests against
                        scopes_on_line_being_tested.clear();
                        test_against_line_number = current_line_number;
                        previous_non_assertion_line = line.to_string();
                    }
                    let ops = state.parse_line(&line);
                    let mut col: usize = 0;
                    for (s, op) in ScopeRegionIterator::new(&ops, &line) {
                        stack.apply(op);
                        if s.is_empty() { // in this case we don't care about blank tokens
                            continue;
                        } else if !line_has_assertion {
                            // if the line has no assertions on it, remember the scopes on the line so we can test against them later
                            let len = s.chars().count();
                            scopes_on_line_being_tested.push(
                                ScopedText {
                                    char_start: col,
                                    text_len: len,
                                    scope: stack.as_slice().to_vec()
                                }
                            );
                            // TODO: warn when there are duplicate adjacent (non-meta?) scopes, as it is almost always undesired
                            col += len;
                        }
                    }
                }

                line.clear();
                current_line_number += 1;
                if reader.read_line(&mut line).unwrap() == 0 {
                    break;
                }
                line = line.replace("\r", &"");
            }
            Ok(
                if assertion_failures > 0 {
                    SyntaxTestFileResult::FailedAssertions(assertion_failures, total_assertions)
                } else {
                    SyntaxTestFileResult::Success(total_assertions)
                }
            )
        },
        None => Err(SyntaxTestHeaderError::MalformedHeader)
    }
}

fn main() {
    let args: Vec<String> = std::env::args().collect();
    let tests_path = if args.len() < 2 {
        "."
    } else {
        &args[1]
    };
    let syntaxes_path = if args.len() == 3 {
        &args[2]
    } else {
        ""
    };

    // load the syntaxes from disk if told to
    // (as opposed to from the binary dumps)
    // this helps to ensure that a recompile isn't needed
    // when using this for syntax development
    let mut ss = if syntaxes_path.is_empty() {
        SyntaxSet::load_defaults_newlines() // note we load the version with newlines
    } else {
        SyntaxSet::new()
    };
    if !syntaxes_path.is_empty() {
        println!("loading syntax definitions from {}", syntaxes_path);
        ss.load_syntaxes(&syntaxes_path, true).unwrap(); // note that we load the version with newlines
        ss.link_syntaxes();
    }

    let exit_code = recursive_walk(&ss, &tests_path);
    println!("exiting with code {}", exit_code);
    std::process::exit(exit_code);

}

fn recursive_walk(ss: &SyntaxSet, path: &str) -> i32 {
    let mut exit_code: i32 = 0; // exit with code 0 by default, if all tests pass
    let walker = WalkDir::new(path).into_iter();
    for entry in walker.filter_entry(|e|e.file_type().is_dir() || is_a_syntax_test_file(e)) {
        let entry = entry.unwrap();
        if entry.file_type().is_file() {
            println!("Testing file {}", entry.path().display());
            let result = test_file(&ss, entry.path(), true);
            println!("{:?}", result);
            if exit_code != 2 { // leave exit code 2 if there was an error
                if let Err(_) = result { // set exit code 2 if there was an error
                    exit_code = 2;
                } else if let Ok(ok) = result {
                    if let SyntaxTestFileResult::FailedAssertions(_, _) = ok {
                        exit_code = 1; // otherwise, if there were failures, exit with code 1
                    }
                }
            }
        }
    }
    exit_code
}

fn is_a_syntax_test_file(entry: &DirEntry) -> bool {
    entry.file_name()
         .to_str()
         .map(|s| s.starts_with("syntax_test_"))
         .unwrap_or(false)
}
<commit_msg>Clean up syntest.rs example<commit_after>//! An example of using syntect for testing syntax definitions.
//! Basically exactly the same as what Sublime Text can do,
//! but without needing ST installed
extern crate syntect;
extern crate walkdir;
#[macro_use]
extern crate lazy_static;
extern crate regex;
//extern crate onig;
use syntect::parsing::{SyntaxSet, ParseState, ScopeStack, Scope};
use syntect::highlighting::ScopeSelectors;
use syntect::easy::{ScopeRegionIterator};

use std::path::Path;
use std::io::{BufRead, BufReader};
use std::fs::File;
use std::cmp::{min, max};
use walkdir::{DirEntry, WalkDir, WalkDirIterator};
use std::str::FromStr;
use regex::Regex;

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SyntaxTestHeaderError {
    MalformedHeader,
    SyntaxDefinitionNotFound,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SyntaxTestFileResult {
    FailedAssertions(usize, usize),
    Success(usize),
}

lazy_static! {
    pub static ref SYNTAX_TEST_HEADER_PATTERN: Regex = Regex::new(r#"(?xm)
            ^(?P<testtoken_start>\s*\S+)
            \s+SYNTAX\sTEST\s+
            "(?P<syntax_file>[^"]+)"
            \s*(?P<testtoken_end>\S+)?$
        "#).unwrap();
    pub static ref SYNTAX_TEST_ASSERTION_PATTERN: Regex = Regex::new(r#"(?xm)
        \s*(?:
            (?P<begin_of_token><-)|(?P<range>\^+)
        )(.+)$"#).unwrap();
}

#[derive(Debug)]
struct AssertionRange<'a> {
    begin_char: usize,
    end_char: usize,
    scope_selector_text: &'a str,
    is_pure_assertion_line: bool,
}

#[derive(Debug)]
struct ScopedText {
    scope: Vec<Scope>,
    char_start: usize,
    text_len: usize,
}

#[derive(Debug)]
struct RangeTestResult {
    column_begin: usize,
    column_end: usize,
    success: bool,
}

fn get_line_assertion_details<'a>(testtoken_start: &str, testtoken_end: Option<&str>, line: &'a str) -> Option<AssertionRange<'a>> {
    // if the test start token specified in the test file's header is on the line
    if let Some(index) = line.find(testtoken_start) {
        let (before_token_start, token_and_rest_of_line) = line.split_at(index);

        if let Some(captures) = SYNTAX_TEST_ASSERTION_PATTERN.captures(&token_and_rest_of_line[testtoken_start.len()..]) {
            let mut sst = captures.get(3).unwrap().as_str().trim_right(); // get the scope selector text
            if let Some(token) = testtoken_end { // if there is an end token defined in the test file header
                sst = sst.trim_right_matches(&token); // trim it from the scope selector text
            }
            return Some(AssertionRange {
                begin_char: index + if captures.get(2).is_some() { testtoken_start.len() + captures.get(2).unwrap().start() } else { 0 },
                end_char: index + if captures.get(2).is_some() { testtoken_start.len() + captures.get(2).unwrap().end() } else { 1 },
                scope_selector_text: sst,
                is_pure_assertion_line: before_token_start.trim_left().is_empty(), // if only whitespace precedes the test token on the line, then it is a pure assertion line
            })
        }
    }
    None
}

fn process_assertions(assertion: &AssertionRange, test_against_line_scopes: &Vec<ScopedText>) -> Vec<RangeTestResult> {
    // format the scope selector to include a space at the beginning, because, currently, ScopeSelector expects excludes to begin with " -"
    // and they are sometimes in the syntax test as ^^^-comment, for example
    let selector = ScopeSelectors::from_str(&format!(" {}", &assertion.scope_selector_text)).unwrap();
    // find the scope at the specified start column, and start matching the selector through the rest of the tokens on the line from there until the end column is reached
    let mut results = Vec::new();
    for scoped_text in test_against_line_scopes.iter().skip_while(|s|s.char_start + s.text_len <= assertion.begin_char).take_while(|s|s.char_start < assertion.end_char) {
        let match_value = selector.does_match(scoped_text.scope.as_slice());
        let result = RangeTestResult {
            column_begin: max(scoped_text.char_start, assertion.begin_char),
            column_end: min(scoped_text.char_start + scoped_text.text_len, assertion.end_char),
            success: match_value.is_some()
        };
        results.push(result);
    }
    // don't ignore assertions after the newline, they should be treated as though they are asserting against the newline
    let last = test_against_line_scopes.last().unwrap();
    if last.char_start + last.text_len < assertion.end_char {
        let match_value = selector.does_match(last.scope.as_slice());
        let result = RangeTestResult {
            column_begin: max(last.char_start + last.text_len, assertion.begin_char),
            column_end: assertion.end_char,
            success: match_value.is_some()
        };
        results.push(result);
    }
    results
}

/// If `parse_test_lines` is `false` then lines that only contain assertions are not parsed
fn test_file(ss: &SyntaxSet, path: &Path, parse_test_lines: bool) -> Result<SyntaxTestFileResult, SyntaxTestHeaderError> {
    let f = File::open(path).unwrap();
    let mut reader = BufReader::new(f);
    let mut line = String::new();

    // read the first line from the file - if we have reached EOF already, it's an invalid file
    if reader.read_line(&mut line).unwrap() == 0 {
        return Err(SyntaxTestHeaderError::MalformedHeader);
    }

    line = line.replace("\r", &"");

    // parse the syntax test header in the first line of the file
    let header_line = line.clone();
    let search_result = SYNTAX_TEST_HEADER_PATTERN.captures(&header_line);
    let captures = try!(search_result.ok_or(SyntaxTestHeaderError::MalformedHeader));

    let testtoken_start = captures.name("testtoken_start").unwrap().as_str();
    let testtoken_end = captures.name("testtoken_end").map_or(None, |c|Some(c.as_str()));
    let syntax_file = captures.name("syntax_file").unwrap().as_str();

    // find the relevant syntax definition to parse the file with - case is important!
    println!("The test file references syntax definition file: {}", syntax_file);
    let syntax = try!(ss.find_syntax_by_path(syntax_file).ok_or(SyntaxTestHeaderError::SyntaxDefinitionNotFound));

    // iterate over the lines of the file, testing them
    let mut state = ParseState::new(syntax);
    let mut stack = ScopeStack::new();

    let mut current_line_number = 1;
    let mut test_against_line_number = 1;
    let mut scopes_on_line_being_tested = Vec::new();
    let mut previous_non_assertion_line = line.to_string();

    let mut assertion_failures: usize = 0;
    let mut total_assertions: usize = 0;

    loop { // over lines of file, starting with the header line
        let mut line_only_has_assertion = false;
        let mut line_has_assertion = false;
        if let Some(assertion) = get_line_assertion_details(testtoken_start, testtoken_end, &line) {
            let result = process_assertions(&assertion, &scopes_on_line_being_tested);
            total_assertions += &assertion.end_char - &assertion.begin_char;
            for failure in result.iter().filter(|r|!r.success) {
                let chars = &previous_non_assertion_line[failure.column_begin..failure.column_end];
                println!("  Assertion selector {:?} \
                    from line {:?} failed against line {:?}, column range {:?}-{:?} \
                    (with text {:?}) \
                    has scope {:?}",
                    assertion.scope_selector_text.trim(),
                    current_line_number, test_against_line_number, failure.column_begin, failure.column_end,
                    chars,
                    scopes_on_line_being_tested.iter().skip_while(|s|s.char_start + s.text_len <= failure.column_begin).next().unwrap_or(scopes_on_line_being_tested.last().unwrap()).scope
                );
                assertion_failures += failure.column_end - failure.column_begin;
            }
            line_only_has_assertion = assertion.is_pure_assertion_line;
            line_has_assertion = true;
        }
        if !line_only_has_assertion || parse_test_lines {
            if !line_has_assertion { // ST seems to ignore lines that have assertions when calculating which line the assertion tests against
                scopes_on_line_being_tested.clear();
                test_against_line_number = current_line_number;
                previous_non_assertion_line = line.to_string();
            }
            let ops = state.parse_line(&line);
            let mut col: usize = 0;
            for (s, op) in ScopeRegionIterator::new(&ops, &line) {
                stack.apply(op);
                if s.is_empty() { // in this case we don't care about blank tokens
                    continue;
                }
                if !line_has_assertion {
                    // if the line has no assertions on it, remember the scopes on the line so we can test against them later
                    let len = s.chars().count();
                    scopes_on_line_being_tested.push(
                        ScopedText {
                            char_start: col,
                            text_len: len,
                            scope: stack.as_slice().to_vec()
                        }
                    );
                    // TODO: warn when there are duplicate adjacent (non-meta?) scopes, as it is almost always undesired
                    col += len;
                }
            }
        }

        line.clear();
        current_line_number += 1;
        if reader.read_line(&mut line).unwrap() == 0 {
            break;
        }
        line = line.replace("\r", &"");
    }
    if assertion_failures > 0 {
        Ok(SyntaxTestFileResult::FailedAssertions(assertion_failures, total_assertions))
    } else {
        Ok(SyntaxTestFileResult::Success(total_assertions))
    }
}

fn main() {
    let args: Vec<String> = std::env::args().collect();
    let tests_path = if args.len() < 2 {
        "."
    } else {
        &args[1]
    };
    let syntaxes_path = if args.len() == 3 {
        &args[2]
    } else {
        ""
    };

    // load the syntaxes from disk if told to
    // (as opposed to from the binary dumps)
    // this helps to ensure that a recompile isn't needed
    // when using this for syntax development
    let mut ss = if syntaxes_path.is_empty() {
        SyntaxSet::load_defaults_newlines() // note we load the version with newlines
    } else {
        SyntaxSet::new()
    };
    if !syntaxes_path.is_empty() {
        println!("loading syntax definitions from {}", syntaxes_path);
        ss.load_syntaxes(&syntaxes_path, true).unwrap(); // note that we load the version with newlines
        ss.link_syntaxes();
    }

    let exit_code = recursive_walk(&ss, &tests_path);
    println!("exiting with code {}", exit_code);
    std::process::exit(exit_code);

}

fn recursive_walk(ss: &SyntaxSet, path: &str) -> i32 {
    let mut exit_code: i32 = 0; // exit with code 0 by default, if all tests pass
    let walker = WalkDir::new(path).into_iter();
    for entry in walker.filter_entry(|e|e.file_type().is_dir() || is_a_syntax_test_file(e)) {
        let entry = entry.unwrap();
        if entry.file_type().is_file() {
            println!("Testing file {}", entry.path().display());
            let result = test_file(&ss, entry.path(), true);
            println!("{:?}", result);
            if exit_code != 2 { // leave exit code 2 if there was an error
                if let Err(_) = result { // set exit code 2 if there was an error
                    exit_code = 2;
                } else if let Ok(ok) = result {
                    if let SyntaxTestFileResult::FailedAssertions(_, _) = ok {
                        exit_code = 1; // otherwise, if there were failures, exit with code 1
                    }
                }
            }
        }
    }
    exit_code
}

fn is_a_syntax_test_file(entry: &DirEntry) -> bool {
    entry.file_name()
         .to_str()
         .map(|s| s.starts_with("syntax_test_"))
         .unwrap_or(false)
}
<|endoftext|>


<commit_before>#![feature(plugin, custom_derive, custom_attribute)]
#![plugin(rocket_codegen)]
extern crate rocket;
extern crate serde;
extern crate itertools;

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

#[cfg(test)]
extern crate serde_json;

use rocket_contrib::Json;

use std::io;
use std::path::{Path, PathBuf};

use rocket::response::NamedFile;

mod automata;
use automata::{Nfa, Dfa, Unsanitary};

#[get("/")]
fn index() -> io::Result<NamedFile> {
    NamedFile::open("../frontend/build/index.html")
}

#[get("/<file..>")]
fn files(file: PathBuf) -> Option<NamedFile> {
    NamedFile::open(Path::new("../frontend/build/").join(file)).ok()
}

#[post("/submit", format="application/json", data="<data>")]
fn submit_nfa(data: Json<Nfa<Unsanitary>>) -> Json<Dfa> {
    Json(data.into_inner().check().unwrap().make_deterministic())
}

fn main() {
    rocket::ignite().mount("/", routes![index, submit_nfa, files]).launch();
}

#[cfg(test)]
mod test {
    use super::rocket;
    use rocket::local::Client;
    use rocket::http::Status;

    #[test]
    fn test_one() {
        let rocket = rocket::ignite();
        let client = Client::new(rocket).expect("valid rocket instance");
        let mut response = client.get("/").dispatch();

        //assert_eq!(response.status(), Status::Ok);
        //assert_eq!(response.content_type(), Some(ContentType::Plain));
        //assert!(response.headers().get_one("X-Special").is_some());
        //assert_eq!(response.body_string(), Some("Expected Body.".into()));
    }
}
<commit_msg>testing index<commit_after>#![feature(plugin, custom_derive, custom_attribute)]
#![plugin(rocket_codegen)]
extern crate rocket;
extern crate serde;
extern crate itertools;

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

#[cfg(test)]
extern crate serde_json;

use rocket_contrib::Json;

use std::io;
use std::path::{Path, PathBuf};

use rocket::response::NamedFile;

mod automata;
use automata::{Nfa, Dfa, Unsanitary};

#[get("/")]
fn index() -> io::Result<NamedFile> {
    NamedFile::open("../frontend/build/index.html")
}

#[get("/<file..>")]
fn files(file: PathBuf) -> Option<NamedFile> {
    NamedFile::open(Path::new("../frontend/build/").join(file)).ok()
}

#[post("/submit", format="application/json", data="<data>")]
fn submit_nfa(data: Json<Nfa<Unsanitary>>) -> Json<Dfa> {
    Json(data.into_inner().check().unwrap().make_deterministic())
}

fn rocket() -> rocket::Rocket {
    rocket::ignite().mount("/", routes![index, submit_nfa, files])
}

fn main() {
    rocket().launch();
}

#[cfg(test)]
mod test {
    use super::rocket;
    use rocket::local::Client;
    use rocket::http::Status;
    use rocket::http::ContentType;

    #[test]
    fn test_index() {
        let rocket = rocket();
        let client = Client::new(rocket).expect("valid rocket instance");
        let mut response = client.get("/").dispatch();

        assert_eq!(response.status(), Status::Ok);
        assert_eq!(response.content_type(), Some(ContentType::HTML));
        //assert!(response.headers().get_one("X-Special").is_some());
        //assert_eq!(response.body_string(), Some("Expected Body.".into()));
    }
}
<|endoftext|>


<commit_before>use capnp;
use capnp::message::MessageBuilder;
use zmq;
use std;
use rand;
use rand::Rng;
use capnp_zmq;
use explorers_capnp::Observation;
use time;

struct Pixel {
    red : u8,
    green : u8,
    blue : u8
}

fn fudge(x : u8) -> u8 {
    let error = rand::task_rng().gen_range::<i16>(-60, 60);
    let y = x as i16 + error;
    if y < 0 { return 0; }
    if y > 255 { return 255; }
    return y as u8;
}

struct Image {
    width : u32,
    height : u32,
    pixels : ~[Pixel]
}

impl Image {

    // quick and dirty parsing of a PPM image
    fn load(file : &std::path::Path) -> std::io::IoResult<Image> {
        use std::io::{Open, Read};
        match std::io::File::open_mode(file, Open, Read) {
            Err(_e) => fail!("could not open"),
            Ok(reader) => {
                let mut buffered = std::io::BufferedReader::new(reader);
                match buffered.read_line() {
                    Ok(s) => {
                        assert!(s.trim() == "P6");
                    }
                    Err(_e) => fail!("premature end of file")
                }
                let (width, height) = match buffered.read_line() {
                    Ok(s) => {
                        let dims : ~[&str] = s.split(' ').collect();
                        if dims.len() != 2 { fail!("could not read dimensions") }
                        (from_str::<u32>(dims[0].trim()).unwrap(), from_str::<u32>(dims[1].trim()).unwrap())
                    }
                    Err(_e) => { fail!("premature end of file") }
                };
                match buffered.read_line() {
                    Ok(s) => { assert!(s.trim() == "255") }
                    Err(_e) => fail!("premature end of file")
                }
                let mut result = Image { width : width, height : height, pixels : ~[] };
                for _ in range(0, width * height) {
                    result.pixels.push(
                        Pixel {
                            red : try!(buffered.read_u8()),
                            green : try!(buffered.read_u8()),
                            blue : try!(buffered.read_u8())
                        });
                }
                return Ok(result);
            }
        }
    }

    fn get_pixel(&self, x : u32, y : u32) -> Pixel {
        assert!(x < self.width);
        assert!(y < self.height);
        self.pixels[((y * self.width) + x)]
    }

    fn take_measurement(&self, x : f32, y : f32, obs : Observation::Builder) {

        assert!(x >= 0.0); assert!(y >= 0.0); assert!(x < 1.0); assert!(y < 1.0);

        obs.set_timestamp(time::now().to_timespec().sec);
        obs.set_x(x);
        obs.set_y(y);

        let pixel = self.get_pixel((x * self.width as f32).floor() as u32,
                                   (y * self.height as f32).floor() as u32);

        obs.set_red(fudge(pixel.red));
        obs.set_green(fudge(pixel.green));
        obs.set_blue(fudge(pixel.blue));

        add_diagnostic(obs);
    }
}

static WORDS : [&'static str, .. 20] = [
   "syntax", "personality", "rhymist", "shopwalker", "gooseskin", "overtask",
    "churme", "heathen", "economiser", "radium", "attainable", "nonius", "knaggy",
    "inframedian", "tamperer", "disentitle", "horary", "morsure", "bonnaz", "alien",
];

// With small probability, add a gibberish warning to the observation.
fn add_diagnostic<'a>(obs : Observation::Builder<'a>) {
    let mut rng = rand::task_rng();
    if rng.gen_range::<u16>(0, 3000) < 2 {
        let mut warning = ~"";
        warning.push_str(rng.choose(WORDS));
        warning.push_str(" ");
        warning.push_str(rng.gen_ascii_str(8));
        warning.push_str(" ");
        warning.push_str(rng.choose(WORDS));
        obs.init_diagnostic().set_warning(warning);
    }
}

pub fn main () {

    let args = std::os::args();
    if args.len() != 3 {
        println!("usage: {} explorer [filename]", args[0]);
        return;
    }

    let image = Image::load(&std::path::Path::new(args[2])).unwrap();

    let mut context = zmq::Context::new();
    let mut publisher = context.socket(zmq::PUB).unwrap();
    assert!(publisher.connect("tcp://localhost:5555").is_ok());

    let mut rng = rand::task_rng();
    let mut x = rng.gen_range::<f32>(0.0, 1.0);
    let mut y = rng.gen_range::<f32>(0.0, 1.0);

    loop {
        x += rng.gen_range::<f32>(-0.01, 0.01);
        y += rng.gen_range::<f32>(-0.01, 0.01);

        if x >= 1.0 { x -= 1.0 }
        if y >= 1.0 { y -= 1.0 }
        if x < 0.0 { x += 1.0 }
        if y < 0.0 { y += 1.0 }

        let mut message = capnp::message::MallocMessageBuilder::new_default();
        let obs = message.init_root::<Observation::Builder>();
        image.take_measurement(x, y, obs);
        capnp_zmq::send(&mut publisher, &mut message).unwrap();

        std::io::timer::sleep(5);
    }

}
<commit_msg>uint index in zmq example<commit_after>use capnp;
use capnp::message::MessageBuilder;
use zmq;
use std;
use rand;
use rand::Rng;
use capnp_zmq;
use explorers_capnp::Observation;
use time;

struct Pixel {
    red : u8,
    green : u8,
    blue : u8
}

fn fudge(x : u8) -> u8 {
    let error = rand::task_rng().gen_range::<i16>(-60, 60);
    let y = x as i16 + error;
    if y < 0 { return 0; }
    if y > 255 { return 255; }
    return y as u8;
}

struct Image {
    width : u32,
    height : u32,
    pixels : ~[Pixel]
}

impl Image {

    // quick and dirty parsing of a PPM image
    fn load(file : &std::path::Path) -> std::io::IoResult<Image> {
        use std::io::{Open, Read};
        match std::io::File::open_mode(file, Open, Read) {
            Err(_e) => fail!("could not open"),
            Ok(reader) => {
                let mut buffered = std::io::BufferedReader::new(reader);
                match buffered.read_line() {
                    Ok(s) => {
                        assert!(s.trim() == "P6");
                    }
                    Err(_e) => fail!("premature end of file")
                }
                let (width, height) = match buffered.read_line() {
                    Ok(s) => {
                        let dims : ~[&str] = s.split(' ').collect();
                        if dims.len() != 2 { fail!("could not read dimensions") }
                        (from_str::<u32>(dims[0].trim()).unwrap(), from_str::<u32>(dims[1].trim()).unwrap())
                    }
                    Err(_e) => { fail!("premature end of file") }
                };
                match buffered.read_line() {
                    Ok(s) => { assert!(s.trim() == "255") }
                    Err(_e) => fail!("premature end of file")
                }
                let mut result = Image { width : width, height : height, pixels : ~[] };
                for _ in range(0, width * height) {
                    result.pixels.push(
                        Pixel {
                            red : try!(buffered.read_u8()),
                            green : try!(buffered.read_u8()),
                            blue : try!(buffered.read_u8())
                        });
                }
                return Ok(result);
            }
        }
    }

    fn get_pixel(&self, x : u32, y : u32) -> Pixel {
        assert!(x < self.width);
        assert!(y < self.height);
        self.pixels[((y * self.width) + x) as uint]
    }

    fn take_measurement(&self, x : f32, y : f32, obs : Observation::Builder) {

        assert!(x >= 0.0); assert!(y >= 0.0); assert!(x < 1.0); assert!(y < 1.0);

        obs.set_timestamp(time::now().to_timespec().sec);
        obs.set_x(x);
        obs.set_y(y);

        let pixel = self.get_pixel((x * self.width as f32).floor() as u32,
                                   (y * self.height as f32).floor() as u32);

        obs.set_red(fudge(pixel.red));
        obs.set_green(fudge(pixel.green));
        obs.set_blue(fudge(pixel.blue));

        add_diagnostic(obs);
    }
}

static WORDS : [&'static str, .. 20] = [
   "syntax", "personality", "rhymist", "shopwalker", "gooseskin", "overtask",
    "churme", "heathen", "economiser", "radium", "attainable", "nonius", "knaggy",
    "inframedian", "tamperer", "disentitle", "horary", "morsure", "bonnaz", "alien",
];

// With small probability, add a gibberish warning to the observation.
fn add_diagnostic<'a>(obs : Observation::Builder<'a>) {
    let mut rng = rand::task_rng();
    if rng.gen_range::<u16>(0, 3000) < 2 {
        let mut warning = ~"";
        warning.push_str(rng.choose(WORDS));
        warning.push_str(" ");
        warning.push_str(rng.gen_ascii_str(8));
        warning.push_str(" ");
        warning.push_str(rng.choose(WORDS));
        obs.init_diagnostic().set_warning(warning);
    }
}

pub fn main () {

    let args = std::os::args();
    if args.len() != 3 {
        println!("usage: {} explorer [filename]", args[0]);
        return;
    }

    let image = Image::load(&std::path::Path::new(args[2])).unwrap();

    let mut context = zmq::Context::new();
    let mut publisher = context.socket(zmq::PUB).unwrap();
    assert!(publisher.connect("tcp://localhost:5555").is_ok());

    let mut rng = rand::task_rng();
    let mut x = rng.gen_range::<f32>(0.0, 1.0);
    let mut y = rng.gen_range::<f32>(0.0, 1.0);

    loop {
        x += rng.gen_range::<f32>(-0.01, 0.01);
        y += rng.gen_range::<f32>(-0.01, 0.01);

        if x >= 1.0 { x -= 1.0 }
        if y >= 1.0 { y -= 1.0 }
        if x < 0.0 { x += 1.0 }
        if y < 0.0 { y += 1.0 }

        let mut message = capnp::message::MallocMessageBuilder::new_default();
        let obs = message.init_root::<Observation::Builder>();
        image.take_measurement(x, y, obs);
        capnp_zmq::send(&mut publisher, &mut message).unwrap();

        std::io::timer::sleep(5);
    }

}
<|endoftext|>


<commit_before>use crate::utils::paths;
use crate::utils::sugg::DiagnosticBuilderExt;
use crate::utils::{get_trait_def_id, implements_trait, return_ty, same_tys, span_lint_hir_and_then};
use if_chain::if_chain;
use rustc::hir;
use rustc::hir::def_id::DefId;
use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass};
use rustc::ty::{self, Ty};
use rustc::util::nodemap::NodeSet;
use rustc::{declare_tool_lint, impl_lint_pass};
use rustc_errors::Applicability;
use syntax::source_map::Span;

declare_clippy_lint! {
    /// **What it does:** Checks for types with a `fn new() -> Self` method and no
    /// implementation of
    /// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html).
    ///
    /// It detects both the case when a manual
    /// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html)
    /// implementation is required and also when it can be created with
    /// `#[derive(Default)]`
    ///
    /// **Why is this bad?** The user might expect to be able to use
    /// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) as the
    /// type can be constructed without arguments.
    ///
    /// **Known problems:** Hopefully none.
    ///
    /// **Example:**
    ///
    /// ```ignore
    /// struct Foo(Bar);
    ///
    /// impl Foo {
    ///     fn new() -> Self {
    ///         Foo(Bar::new())
    ///     }
    /// }
    /// ```
    ///
    /// Instead, use:
    ///
    /// ```ignore
    /// struct Foo(Bar);
    ///
    /// impl Default for Foo {
    ///     fn default() -> Self {
    ///         Foo(Bar::new())
    ///     }
    /// }
    /// ```
    ///
    /// Or, if
    /// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html)
    /// can be derived by `#[derive(Default)]`:
    ///
    /// ```rust
    /// struct Foo;
    ///
    /// impl Foo {
    ///     fn new() -> Self {
    ///         Foo
    ///     }
    /// }
    /// ```
    ///
    /// Instead, use:
    ///
    /// ```rust
    /// #[derive(Default)]
    /// struct Foo;
    ///
    /// impl Foo {
    ///     fn new() -> Self {
    ///         Foo
    ///     }
    /// }
    /// ```
    ///
    /// You can also have `new()` call `Default::default()`.
    pub NEW_WITHOUT_DEFAULT,
    style,
    "`fn new() -> Self` method without `Default` implementation"
}

#[derive(Clone, Default)]
pub struct NewWithoutDefault {
    impling_types: Option<NodeSet>,
}

impl_lint_pass!(NewWithoutDefault => [NEW_WITHOUT_DEFAULT]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault {
    fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item) {
        if let hir::ItemKind::Impl(_, _, _, _, None, _, ref items) = item.node {
            for assoc_item in items {
                if let hir::AssocItemKind::Method { has_self: false } = assoc_item.kind {
                    let impl_item = cx.tcx.hir().impl_item(assoc_item.id);
                    if in_external_macro(cx.sess(), impl_item.span) {
                        return;
                    }
                    if let hir::ImplItemKind::Method(ref sig, _) = impl_item.node {
                        let name = impl_item.ident.name;
                        let id = impl_item.hir_id;
                        if sig.header.constness == hir::Constness::Const {
                            // can't be implemented by default
                            return;
                        }
                        if sig.header.unsafety == hir::Unsafety::Unsafe {
                            // can't be implemented for unsafe new
                            return;
                        }
                        if impl_item.generics.params.iter().any(|gen| match gen.kind {
                            hir::GenericParamKind::Type { .. } => true,
                            _ => false,
                        }) {
                            // when the result of `new()` depends on a type parameter we should not require
                            // an
                            // impl of `Default`
                            return;
                        }
                        if sig.decl.inputs.is_empty() && name == sym!(new) && cx.access_levels.is_reachable(id) {
                            let self_did = cx.tcx.hir().local_def_id_from_hir_id(cx.tcx.hir().get_parent_item(id));
                            let self_ty = cx.tcx.type_of(self_did);
                            if_chain! {
                                if same_tys(cx, self_ty, return_ty(cx, id));
                                if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT);
                                then {
                                    if self.impling_types.is_none() {
                                        let mut impls = NodeSet::default();
                                        cx.tcx.for_each_impl(default_trait_id, |d| {
                                            if let Some(ty_def) = cx.tcx.type_of(d).ty_adt_def() {
                                                if let Some(node_id) = cx.tcx.hir().as_local_node_id(ty_def.did) {
                                                    impls.insert(node_id);
                                                }
                                            }
                                        });
                                        self.impling_types = Some(impls);
                                    }

                                    // Check if a Default implementation exists for the Self type, regardless of
                                    // generics
                                    if_chain! {
                                        if let Some(ref impling_types) = self.impling_types;
                                        if let Some(self_def) = cx.tcx.type_of(self_did).ty_adt_def();
                                        if self_def.did.is_local();
                                        then {
                                            let self_id = cx.tcx.hir().local_def_id_to_hir_id(self_def.did.to_local());
                                            let node_id = cx.tcx.hir().hir_to_node_id(self_id);
                                            if impling_types.contains(&node_id) {
                                                return;
                                            }
                                        }
                                    }

                                    if let Some(sp) = can_derive_default(self_ty, cx, default_trait_id) {
                                        span_lint_hir_and_then(
                                            cx,
                                            NEW_WITHOUT_DEFAULT,
                                            id,
                                            impl_item.span,
                                            &format!(
                                                "you should consider deriving a `Default` implementation for `{}`",
                                                self_ty
                                            ),
                                            |db| {
                                                db.suggest_item_with_attr(
                                                    cx,
                                                    sp,
                                                    "try this",
                                                    "#[derive(Default)]",
                                                    Applicability::MaybeIncorrect,
                                                );
                                            });
                                    } else {
                                        span_lint_hir_and_then(
                                            cx,
                                            NEW_WITHOUT_DEFAULT,
                                            id,
                                            impl_item.span,
                                            &format!(
                                                "you should consider adding a `Default` implementation for `{}`",
                                                self_ty
                                            ),
                                            |db| {
                                                db.suggest_prepend_item(
                                                    cx,
                                                    item.span,
                                                    "try this",
                                                    &create_new_without_default_suggest_msg(self_ty),
                                                    Applicability::MaybeIncorrect,
                                                );
                                            },
                                        );
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

fn create_new_without_default_suggest_msg(ty: Ty<'_>) -> String {
    #[rustfmt::skip]
    format!(
"impl Default for {} {{
    fn default() -> Self {{
        Self::new()
    }}
}}", ty)
}

fn can_derive_default<'t, 'c>(ty: Ty<'t>, cx: &LateContext<'c, 't>, default_trait_id: DefId) -> Option<Span> {
    match ty.sty {
        ty::Adt(adt_def, substs) if adt_def.is_struct() => {
            for field in adt_def.all_fields() {
                let f_ty = field.ty(cx.tcx, substs);
                if !implements_trait(cx, f_ty, default_trait_id, &[]) {
                    return None;
                }
            }
            Some(cx.tcx.def_span(adt_def.did))
        },
        _ => None,
    }
}
<commit_msg>Auto merge of #4216 - phansch:replace_nodeset, r=matthiaskrgr<commit_after>use crate::utils::paths;
use crate::utils::sugg::DiagnosticBuilderExt;
use crate::utils::{get_trait_def_id, implements_trait, return_ty, same_tys, span_lint_hir_and_then};
use if_chain::if_chain;
use rustc::hir;
use rustc::hir::def_id::DefId;
use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass};
use rustc::ty::{self, Ty};
use rustc::util::nodemap::HirIdSet;
use rustc::{declare_tool_lint, impl_lint_pass};
use rustc_errors::Applicability;
use syntax::source_map::Span;

declare_clippy_lint! {
    /// **What it does:** Checks for types with a `fn new() -> Self` method and no
    /// implementation of
    /// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html).
    ///
    /// It detects both the case when a manual
    /// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html)
    /// implementation is required and also when it can be created with
    /// `#[derive(Default)]`
    ///
    /// **Why is this bad?** The user might expect to be able to use
    /// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html) as the
    /// type can be constructed without arguments.
    ///
    /// **Known problems:** Hopefully none.
    ///
    /// **Example:**
    ///
    /// ```ignore
    /// struct Foo(Bar);
    ///
    /// impl Foo {
    ///     fn new() -> Self {
    ///         Foo(Bar::new())
    ///     }
    /// }
    /// ```
    ///
    /// Instead, use:
    ///
    /// ```ignore
    /// struct Foo(Bar);
    ///
    /// impl Default for Foo {
    ///     fn default() -> Self {
    ///         Foo(Bar::new())
    ///     }
    /// }
    /// ```
    ///
    /// Or, if
    /// [`Default`](https://doc.rust-lang.org/std/default/trait.Default.html)
    /// can be derived by `#[derive(Default)]`:
    ///
    /// ```rust
    /// struct Foo;
    ///
    /// impl Foo {
    ///     fn new() -> Self {
    ///         Foo
    ///     }
    /// }
    /// ```
    ///
    /// Instead, use:
    ///
    /// ```rust
    /// #[derive(Default)]
    /// struct Foo;
    ///
    /// impl Foo {
    ///     fn new() -> Self {
    ///         Foo
    ///     }
    /// }
    /// ```
    ///
    /// You can also have `new()` call `Default::default()`.
    pub NEW_WITHOUT_DEFAULT,
    style,
    "`fn new() -> Self` method without `Default` implementation"
}

#[derive(Clone, Default)]
pub struct NewWithoutDefault {
    impling_types: Option<HirIdSet>,
}

impl_lint_pass!(NewWithoutDefault => [NEW_WITHOUT_DEFAULT]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault {
    fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item) {
        if let hir::ItemKind::Impl(_, _, _, _, None, _, ref items) = item.node {
            for assoc_item in items {
                if let hir::AssocItemKind::Method { has_self: false } = assoc_item.kind {
                    let impl_item = cx.tcx.hir().impl_item(assoc_item.id);
                    if in_external_macro(cx.sess(), impl_item.span) {
                        return;
                    }
                    if let hir::ImplItemKind::Method(ref sig, _) = impl_item.node {
                        let name = impl_item.ident.name;
                        let id = impl_item.hir_id;
                        if sig.header.constness == hir::Constness::Const {
                            // can't be implemented by default
                            return;
                        }
                        if sig.header.unsafety == hir::Unsafety::Unsafe {
                            // can't be implemented for unsafe new
                            return;
                        }
                        if impl_item.generics.params.iter().any(|gen| match gen.kind {
                            hir::GenericParamKind::Type { .. } => true,
                            _ => false,
                        }) {
                            // when the result of `new()` depends on a type parameter we should not require
                            // an
                            // impl of `Default`
                            return;
                        }
                        if sig.decl.inputs.is_empty() && name == sym!(new) && cx.access_levels.is_reachable(id) {
                            let self_did = cx.tcx.hir().local_def_id_from_hir_id(cx.tcx.hir().get_parent_item(id));
                            let self_ty = cx.tcx.type_of(self_did);
                            if_chain! {
                                if same_tys(cx, self_ty, return_ty(cx, id));
                                if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT);
                                then {
                                    if self.impling_types.is_none() {
                                        let mut impls = HirIdSet::default();
                                        cx.tcx.for_each_impl(default_trait_id, |d| {
                                            if let Some(ty_def) = cx.tcx.type_of(d).ty_adt_def() {
                                                if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(ty_def.did) {
                                                    impls.insert(hir_id);
                                                }
                                            }
                                        });
                                        self.impling_types = Some(impls);
                                    }

                                    // Check if a Default implementation exists for the Self type, regardless of
                                    // generics
                                    if_chain! {
                                        if let Some(ref impling_types) = self.impling_types;
                                        if let Some(self_def) = cx.tcx.type_of(self_did).ty_adt_def();
                                        if self_def.did.is_local();
                                        then {
                                            let self_id = cx.tcx.hir().local_def_id_to_hir_id(self_def.did.to_local());
                                            if impling_types.contains(&self_id) {
                                                return;
                                            }
                                        }
                                    }

                                    if let Some(sp) = can_derive_default(self_ty, cx, default_trait_id) {
                                        span_lint_hir_and_then(
                                            cx,
                                            NEW_WITHOUT_DEFAULT,
                                            id,
                                            impl_item.span,
                                            &format!(
                                                "you should consider deriving a `Default` implementation for `{}`",
                                                self_ty
                                            ),
                                            |db| {
                                                db.suggest_item_with_attr(
                                                    cx,
                                                    sp,
                                                    "try this",
                                                    "#[derive(Default)]",
                                                    Applicability::MaybeIncorrect,
                                                );
                                            });
                                    } else {
                                        span_lint_hir_and_then(
                                            cx,
                                            NEW_WITHOUT_DEFAULT,
                                            id,
                                            impl_item.span,
                                            &format!(
                                                "you should consider adding a `Default` implementation for `{}`",
                                                self_ty
                                            ),
                                            |db| {
                                                db.suggest_prepend_item(
                                                    cx,
                                                    item.span,
                                                    "try this",
                                                    &create_new_without_default_suggest_msg(self_ty),
                                                    Applicability::MaybeIncorrect,
                                                );
                                            },
                                        );
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

fn create_new_without_default_suggest_msg(ty: Ty<'_>) -> String {
    #[rustfmt::skip]
    format!(
"impl Default for {} {{
    fn default() -> Self {{
        Self::new()
    }}
}}", ty)
}

fn can_derive_default<'t, 'c>(ty: Ty<'t>, cx: &LateContext<'c, 't>, default_trait_id: DefId) -> Option<Span> {
    match ty.sty {
        ty::Adt(adt_def, substs) if adt_def.is_struct() => {
            for field in adt_def.all_fields() {
                let f_ty = field.ty(cx.tcx, substs);
                if !implements_trait(cx, f_ty, default_trait_id, &[]) {
                    return None;
                }
            }
            Some(cx.tcx.def_span(adt_def.did))
        },
        _ => None,
    }
}
<|endoftext|>