<commit_before>//! System Mutexes
//!
//! The Windows implementation of mutexes is a little odd and it may not be
//! immediately obvious what's going on. The primary oddness is that SRWLock is
//! used instead of CriticalSection, and this is done because:
//!
//! 1. SRWLock is several times faster than CriticalSection according to
//!    benchmarks performed on both Windows 8 and Windows 7.
//!
//! 2. CriticalSection allows recursive locking while SRWLock deadlocks. The
//!    Unix implementation deadlocks so consistency is preferred. See #19962 for
//!    more details.
//!
//! 3. While CriticalSection is fair and SRWLock is not, the current Rust policy
//!    is that there are no guarantees of fairness.
//!
//! The downside of this approach, however, is that SRWLock is not available on
//! Windows XP, so we continue to have a fallback implementation where
//! CriticalSection is used and we keep track of who's holding the mutex to
//! detect recursive locks.

use crate::cell::{Cell, UnsafeCell};
use crate::mem::{self, MaybeUninit};
use crate::sync::atomic::{AtomicUsize, Ordering};
use crate::sys::c;
use crate::sys::compat;

pub struct Mutex {
    // This is either directly an SRWLOCK (if supported), or a Box<Inner> otherwise.
    lock: AtomicUsize,
}

unsafe impl Send for Mutex {}
unsafe impl Sync for Mutex {}

struct Inner {
    remutex: ReentrantMutex,
    held: Cell<bool>,
}

#[derive(Clone, Copy)]
enum Kind {
    SRWLock = 1,
    CriticalSection = 2,
}

#[inline]
pub unsafe fn raw(m: &Mutex) -> c::PSRWLOCK {
    debug_assert!(mem::size_of::<c::SRWLOCK>() <= mem::size_of_val(&m.lock));
    &m.lock as *const _ as *mut _
}

impl Mutex {
    pub const fn new() -> Mutex {
        Mutex {
            // This works because SRWLOCK_INIT is 0 (wrapped in a struct), so we are also properly
            // initializing an SRWLOCK here.
            lock: AtomicUsize::new(0),
        }
    }
    #[inline]
    pub unsafe fn init(&mut self) {}
    pub unsafe fn lock(&self) {
        match kind() {
            Kind::SRWLock => c::AcquireSRWLockExclusive(raw(self)),
            Kind::CriticalSection => {
                let inner = &mut *self.inner();
                inner.remutex.lock();
                if inner.held.replace(true) {
                    // It was already locked, so we got a recursive lock which we do not want.
                    inner.remutex.unlock();
                    panic!("cannot recursively lock a mutex");
                }
            }
        }
    }
    pub unsafe fn try_lock(&self) -> bool {
        match kind() {
            Kind::SRWLock => c::TryAcquireSRWLockExclusive(raw(self)) != 0,
            Kind::CriticalSection => {
                let inner = &mut *self.inner();
                if !inner.remutex.try_lock() {
                    false
                } else if inner.held.replace(true) {
                    // It was already locked, so we got a recursive lock which we do not want.
                    inner.remutex.unlock();
                    false
                } else {
                    true
                }
            }
        }
    }
    pub unsafe fn unlock(&self) {
        match kind() {
            Kind::SRWLock => c::ReleaseSRWLockExclusive(raw(self)),
            Kind::CriticalSection => {
                let inner = &mut *(self.lock.load(Ordering::SeqCst) as *mut Inner);
                inner.held.set(false);
                inner.remutex.unlock();
            }
        }
    }
    pub unsafe fn destroy(&self) {
        match kind() {
            Kind::SRWLock => {}
            Kind::CriticalSection => match self.lock.load(Ordering::SeqCst) {
                0 => {}
                n => {
                    Box::from_raw(n as *mut Inner).remutex.destroy();
                }
            },
        }
    }

    unsafe fn inner(&self) -> *mut Inner {
        match self.lock.load(Ordering::SeqCst) {
            0 => {}
            n => return n as *mut _,
        }
        let inner = box Inner { remutex: ReentrantMutex::uninitialized(), held: Cell::new(false) };
        inner.remutex.init();
        let inner = Box::into_raw(inner);
        match self.lock.compare_and_swap(0, inner as usize, Ordering::SeqCst) {
            0 => inner,
            n => {
                Box::from_raw(inner).remutex.destroy();
                n as *mut _
            }
        }
    }
}

fn kind() -> Kind {
    static KIND: AtomicUsize = AtomicUsize::new(0);

    let val = KIND.load(Ordering::SeqCst);
    if val == Kind::SRWLock as usize {
        return Kind::SRWLock;
    } else if val == Kind::CriticalSection as usize {
        return Kind::CriticalSection;
    }

    let ret = match compat::lookup("kernel32", "AcquireSRWLockExclusive") {
        None => Kind::CriticalSection,
        Some(..) => Kind::SRWLock,
    };
    KIND.store(ret as usize, Ordering::SeqCst);
    ret
}

pub struct ReentrantMutex {
    inner: UnsafeCell<MaybeUninit<c::CRITICAL_SECTION>>,
}

unsafe impl Send for ReentrantMutex {}
unsafe impl Sync for ReentrantMutex {}

impl ReentrantMutex {
    pub const fn uninitialized() -> ReentrantMutex {
        ReentrantMutex { inner: UnsafeCell::new(MaybeUninit::uninit()) }
    }

    pub unsafe fn init(&self) {
        c::InitializeCriticalSection((&mut *self.inner.get()).as_mut_ptr());
    }

    pub unsafe fn lock(&self) {
        c::EnterCriticalSection((&mut *self.inner.get()).as_mut_ptr());
    }

    #[inline]
    pub unsafe fn try_lock(&self) -> bool {
        c::TryEnterCriticalSection((&mut *self.inner.get()).as_mut_ptr()) != 0
    }

    pub unsafe fn unlock(&self) {
        c::LeaveCriticalSection((&mut *self.inner.get()).as_mut_ptr());
    }

    pub unsafe fn destroy(&self) {
        c::DeleteCriticalSection((&mut *self.inner.get()).as_mut_ptr());
    }
}
<commit_msg>Don't use `mut` in Windows Mutex.<commit_after>//! System Mutexes
//!
//! The Windows implementation of mutexes is a little odd and it may not be
//! immediately obvious what's going on. The primary oddness is that SRWLock is
//! used instead of CriticalSection, and this is done because:
//!
//! 1. SRWLock is several times faster than CriticalSection according to
//!    benchmarks performed on both Windows 8 and Windows 7.
//!
//! 2. CriticalSection allows recursive locking while SRWLock deadlocks. The
//!    Unix implementation deadlocks so consistency is preferred. See #19962 for
//!    more details.
//!
//! 3. While CriticalSection is fair and SRWLock is not, the current Rust policy
//!    is that there are no guarantees of fairness.
//!
//! The downside of this approach, however, is that SRWLock is not available on
//! Windows XP, so we continue to have a fallback implementation where
//! CriticalSection is used and we keep track of who's holding the mutex to
//! detect recursive locks.

use crate::cell::{Cell, UnsafeCell};
use crate::mem::{self, MaybeUninit};
use crate::sync::atomic::{AtomicUsize, Ordering};
use crate::sys::c;
use crate::sys::compat;

pub struct Mutex {
    // This is either directly an SRWLOCK (if supported), or a Box<Inner> otherwise.
    lock: AtomicUsize,
}

unsafe impl Send for Mutex {}
unsafe impl Sync for Mutex {}

struct Inner {
    remutex: ReentrantMutex,
    held: Cell<bool>,
}

#[derive(Clone, Copy)]
enum Kind {
    SRWLock = 1,
    CriticalSection = 2,
}

#[inline]
pub unsafe fn raw(m: &Mutex) -> c::PSRWLOCK {
    debug_assert!(mem::size_of::<c::SRWLOCK>() <= mem::size_of_val(&m.lock));
    &m.lock as *const _ as *mut _
}

impl Mutex {
    pub const fn new() -> Mutex {
        Mutex {
            // This works because SRWLOCK_INIT is 0 (wrapped in a struct), so we are also properly
            // initializing an SRWLOCK here.
            lock: AtomicUsize::new(0),
        }
    }
    #[inline]
    pub unsafe fn init(&mut self) {}
    pub unsafe fn lock(&self) {
        match kind() {
            Kind::SRWLock => c::AcquireSRWLockExclusive(raw(self)),
            Kind::CriticalSection => {
                let inner = &*self.inner();
                inner.remutex.lock();
                if inner.held.replace(true) {
                    // It was already locked, so we got a recursive lock which we do not want.
                    inner.remutex.unlock();
                    panic!("cannot recursively lock a mutex");
                }
            }
        }
    }
    pub unsafe fn try_lock(&self) -> bool {
        match kind() {
            Kind::SRWLock => c::TryAcquireSRWLockExclusive(raw(self)) != 0,
            Kind::CriticalSection => {
                let inner = &*self.inner();
                if !inner.remutex.try_lock() {
                    false
                } else if inner.held.replace(true) {
                    // It was already locked, so we got a recursive lock which we do not want.
                    inner.remutex.unlock();
                    false
                } else {
                    true
                }
            }
        }
    }
    pub unsafe fn unlock(&self) {
        match kind() {
            Kind::SRWLock => c::ReleaseSRWLockExclusive(raw(self)),
            Kind::CriticalSection => {
                let inner = &*(self.lock.load(Ordering::SeqCst) as *const Inner);
                inner.held.set(false);
                inner.remutex.unlock();
            }
        }
    }
    pub unsafe fn destroy(&self) {
        match kind() {
            Kind::SRWLock => {}
            Kind::CriticalSection => match self.lock.load(Ordering::SeqCst) {
                0 => {}
                n => Box::from_raw(n as *mut Inner).remutex.destroy(),
            },
        }
    }

    unsafe fn inner(&self) -> *const Inner {
        match self.lock.load(Ordering::SeqCst) {
            0 => {}
            n => return n as *const _,
        }
        let inner = box Inner { remutex: ReentrantMutex::uninitialized(), held: Cell::new(false) };
        inner.remutex.init();
        let inner = Box::into_raw(inner);
        match self.lock.compare_and_swap(0, inner as usize, Ordering::SeqCst) {
            0 => inner,
            n => {
                Box::from_raw(inner).remutex.destroy();
                n as *const _
            }
        }
    }
}

fn kind() -> Kind {
    static KIND: AtomicUsize = AtomicUsize::new(0);

    let val = KIND.load(Ordering::SeqCst);
    if val == Kind::SRWLock as usize {
        return Kind::SRWLock;
    } else if val == Kind::CriticalSection as usize {
        return Kind::CriticalSection;
    }

    let ret = match compat::lookup("kernel32", "AcquireSRWLockExclusive") {
        None => Kind::CriticalSection,
        Some(..) => Kind::SRWLock,
    };
    KIND.store(ret as usize, Ordering::SeqCst);
    ret
}

pub struct ReentrantMutex {
    inner: UnsafeCell<MaybeUninit<c::CRITICAL_SECTION>>,
}

unsafe impl Send for ReentrantMutex {}
unsafe impl Sync for ReentrantMutex {}

impl ReentrantMutex {
    pub const fn uninitialized() -> ReentrantMutex {
        ReentrantMutex { inner: UnsafeCell::new(MaybeUninit::uninit()) }
    }

    pub unsafe fn init(&self) {
        c::InitializeCriticalSection((&mut *self.inner.get()).as_mut_ptr());
    }

    pub unsafe fn lock(&self) {
        c::EnterCriticalSection((&mut *self.inner.get()).as_mut_ptr());
    }

    #[inline]
    pub unsafe fn try_lock(&self) -> bool {
        c::TryEnterCriticalSection((&mut *self.inner.get()).as_mut_ptr()) != 0
    }

    pub unsafe fn unlock(&self) {
        c::LeaveCriticalSection((&mut *self.inner.get()).as_mut_ptr());
    }

    pub unsafe fn destroy(&self) {
        c::DeleteCriticalSection((&mut *self.inner.get()).as_mut_ptr());
    }
}
<|endoftext|>


<commit_before>#![crate_type = "lib"]
#![feature(macro_rules)]

#[cfg(not(test))]
pub use base::{Node, ParseState, Children, NodeContents};

// macro_escape makes macros from annotated module visible in the "super"
// module... and thus in the children of the "super" module as well.
#[macro_escape]
mod macros;

#[macro_escape]
mod base;

macro_rules! rule(
  (
    $name:ident <- $body:expr
  ) => (
    pub fn $name<'a>( parse_state: &base::ParseState<'a> )
         -> std::option::Option< base::ParseResult<'a> > {
      use base::Expression;
      use base::Node;
      use base::ParseResult;
      use std::clone::Clone;
      use std::option::{Some, None};

      #[allow(dead_code)]
      static node_name : &'static str = stringify!( $name );

      match $body.apply( parse_state ) {
        Some( result ) => {
          let state = result.parse_state.clone();
          Some( ParseResult::oneNode(
              Node::newParent( node_name, result.nodes ), state ) )
        }
        _ => None
      }
    }
  );
)

#[cfg(not(test))]
pub fn parse<'a>( input: &'a [u8] ) -> Option< Node<'a> > {
  static root_name : &'static str = "NailedRoot";
  let parse_state = ParseState { input: input, offset: 0 };
  match rules::Grammar( &parse_state ) {
    Some( result ) => Some( Node::newParent( root_name, result.nodes ) ),
    _ => None
  }
}

mod rules {
  #![no_implicit_prelude]

  use base;
  use std;

  rule!( Grammar <- seq!( ex!( Spacing ),
                          plus!( ex!( Definition ) ),
                          ex!( EndOfFile ) ) )
  rule!( Definition <- seq!( ex!( Identifier ),
                            ex!( LEFTARROW ),
                            ex!( Expression ) ) )
  rule!( Expression <- seq!( ex!( Sequence ),
                            star!( seq!( ex!( SLASH ), ex!( Sequence ) ) ) ) )
  rule!( Sequence <- star!( ex!( Prefix ) ) )
  rule!( Prefix <- seq!( opt!( or!( ex!( AND ),
                                    ex!( NOT ) ) ),
                        ex!( Suffix ) ) )
  rule!( Suffix <- seq!( ex!( Primary ),
                        opt!( or!( ex!( QUESTION ),
                                    ex!( STAR ),
                                    ex!( PLUS ) ) ) ) )
  rule!( Primary <- or!( seq!( ex!( Identifier ),
                              not!( ex!( LEFTARROW ) ) ),
                        seq!( ex!( OPEN ),
                              ex!( Expression ),
                              ex!( CLOSE ) ),
                        ex!( Literal ),
                        ex!( Class ),
                        ex!( DOT ) ) )
  rule!( Identifier <- seq!( ex!( IdentStart ),
                            star!( ex!( IdentCont ) ),
                            ex!( Spacing ) ) )
  rule!( IdentStart <- class!( "a-zA-Z_" ) )
  rule!( IdentCont <- or!( ex!( IdentStart ), class!( "0-9" ) ) )
  rule!( Literal <- or!( seq!( class!( "'" ),
                              star!( seq!( not!( class!( "'" ) ),
                                            ex!( Char ) ) ),
                              class!( "'" ),
                              ex!( Spacing ) ),
                        seq!( class!( "\"" ),
                              star!( seq!( not!( class!( "\"" ) ),
                                            ex!( Char ) ) ),
                              class!( "\"" ),
                              ex!( Spacing ) ) ) )
  rule!( Class <- seq!( lit!( "[" ),
                        star!( seq!( not!( lit!( "]" ) ), ex!( Range ) ) ),
                        lit!( "]" ),
                        ex!( Spacing ) ) )
  rule!( Range <- or!( seq!( ex!( Char ), lit!( "-" ), ex!( Char ) ),
                      ex!( Char ) ) )
  rule!( Char <- or!( seq!( lit!( r"\" ),
                            class!( r#"nrt'"[]\"# ) ),
                      seq!( lit!( r"\" ),
                            class!( "0-2" ),
                            class!( "0-7" ),
                            class!( "0-7" ) ),
                      seq!( lit!( r"\" ),
                            class!( "0-7" ),
                            opt!( class!( "0-7" ) ) ),
                      seq!( not!( lit!( r"\" ) ),
                            base::Dot ) ) )
  rule!( LEFTARROW <- seq!( lit!( "<-" ), ex!( Spacing ) ) )
  rule!( SLASH <- seq!( lit!( "/" ), ex!( Spacing ) ) )
  rule!( AND <- seq!( lit!( "&" ), ex!( Spacing ) ) )
  rule!( NOT <- seq!( lit!( "!" ), ex!( Spacing ) ) )
  rule!( QUESTION <- seq!( lit!( "?" ), ex!( Spacing ) ) )
  rule!( STAR <- seq!( lit!( "*" ), ex!( Spacing ) ) )
  rule!( PLUS <- seq!( lit!( "+" ), ex!( Spacing ) ) )
  rule!( OPEN <- seq!( lit!( "(" ), ex!( Spacing ) ) )
  rule!( CLOSE <- seq!( lit!( ")" ), ex!( Spacing ) ) )
  rule!( DOT <- seq!( lit!( "." ), ex!( Spacing ) ) )
  rule!( Spacing <- star!( or!( ex!( Space ), ex!( Comment ) ) ) )
  rule!( Comment <- seq!( lit!( "#" ),
                          star!( seq!( not!( ex!( EndOfLine ) ), base::Dot ) ),
                          ex!( EndOfLine ) ) )
  rule!( Space <- or!( lit!( " " ), lit!( "\t" ), ex!( EndOfLine ) ) )
  rule!( EndOfLine <- or!( lit!( "\r\n" ), lit!( "\n" ), lit!( "\r" ) ) )
  rule!( EndOfFile <- not!( base::Dot ) )

  #[cfg(test)]
  mod tests {
    use super::{EndOfFile, EndOfLine, Space, Comment, Spacing, Char, Range,
                Class, Literal, Identifier, Definition};

    macro_rules! consumes(
      (
        $name:ident, $input:expr
      ) => (
        {
          use base::ParseResult;
          use std::option::Some;
          use std::container::Container;

          match $name( &input_state!( $input ) ) {
            Some( ParseResult{ nodes: _,
                              parse_state: parse_state } ) => {
              parse_state.input.is_empty()
            }
            _ => false
          }
        }
      );
    )

    macro_rules! matches(
      (
        $name:ident, $input:expr
      ) => (
        $name( &input_state!( $input ) ).is_some()
      );
    )

    #[test]
    fn Definition_Works() {
      assert!( consumes!( Definition,
                          "Grammar <- Spacing Definition+ EndOfFile" ) )
      assert!( consumes!( Definition,
                          r#"Char <- '\\' [nrt'"\[\]\\] /
                                    '\\' [0-2][0-7][0-7] /
                                    '\\' [0-7][0-7]? /
                                    !'\\' ."# ) )
    }

    #[test]
    fn Identifier_Works() {
      assert!( consumes!( Identifier, "abc" ) );
      assert!( consumes!( Identifier, "a" ) );
      assert!( consumes!( Identifier, "_" ) );
      assert!( consumes!( Identifier, "a123" ) );
      assert!( consumes!( Identifier, "a  \n" ) );

      assert!( !consumes!( Identifier, "1a" ) );
      assert!( !consumes!( Identifier, "1" ) );
      assert!( !consumes!( Identifier, "Ć" ) );
    }

    #[test]
    fn Literal_Works() {
      assert!( consumes!( Literal, "'abc'" ) );
      assert!( consumes!( Literal, r#""abc""# ) );
      assert!( consumes!( Literal, "'abc'  \n" ) );
      assert!( !consumes!( Literal, "'abc''bb'" ) );
    }

    #[test]
    fn Class_Works() {
      assert!( consumes!( Class, "[a-z]" ) );
      assert!( consumes!( Class, "[a-z]  \n" ) );
      assert!( consumes!( Class, "[abc]" ) );
      assert!( consumes!( Class, "[abc0-9g]" ) );
    }

    #[test]
    fn Range_Works() {
      assert!( consumes!( Range, "a-z" ) );
      assert!( consumes!( Range, "a" ) );
    }

    #[test]
    fn Char_Works() {
      assert!( consumes!( Char, r"\n" ) );
      assert!( consumes!( Char, r"\]" ) );
      assert!( consumes!( Char, r"\\" ) );
      assert!( consumes!( Char, r"\'" ) );
      assert!( consumes!( Char, "a" ) );
      assert!( consumes!( Char, "x" ) );
      assert!( consumes!( Char, "Ć" ) );
      assert!( consumes!( Char, "€" ) );
      assert!( consumes!( Char, r"\277" ) );
      assert!( consumes!( Char, r"\77" ) );
      assert!( consumes!( Char, r"\7" ) );

      assert!( !consumes!( Char, "aa" ) );
    }

    #[test]
    fn Spacing_Works() {
      assert!( consumes!( Spacing, "  \t #g\n" ) );
      assert!( consumes!( Spacing, "#a\n  #1\n" ) );

      // Spacing DOES match here because at the top level, it is a star
      // expression which can match consuming nothing.
      assert!( matches!( Spacing, "" ) );
      assert!( !consumes!( Spacing, "#" ) );
      assert!( !consumes!( Spacing, "a" ) );
    }

    #[test]
    fn Comment_Works() {
      assert!( consumes!( Comment, "#\n" ) );
      assert!( consumes!( Comment, "# foo! \n" ) );
      assert!( !matches!( Comment, "\n" ) );
      assert!( !matches!( Comment, "#" ) );
      assert!( !matches!( Comment, "a" ) );
    }

    #[test]
    fn Space_Works() {
      assert!( consumes!( Space, " " ) );
      assert!( consumes!( Space, "\t" ) );
      assert!( consumes!( Space, "\n" ) );
      assert!( !matches!( Space, "a" ) );
    }

    #[test]
    fn EndOfLine_Works() {
      assert!( consumes!( EndOfLine, "\n" ) );
      assert!( consumes!( EndOfLine, "\r" ) );
      assert!( consumes!( EndOfLine, "\r\n" ) );
      assert!( !matches!( EndOfLine, "a" ) );
    }

    #[test]
    fn EndOfFile_Works() {
      assert!( consumes!( EndOfFile, "" ) );
      assert!( !matches!( EndOfFile, "a" ) );
    }
  }
}
<commit_msg>Added test for Grammar rule<commit_after>#![crate_type = "lib"]
#![feature(macro_rules)]

#[cfg(not(test))]
pub use base::{Node, ParseState, Children, NodeContents};

// macro_escape makes macros from annotated module visible in the "super"
// module... and thus in the children of the "super" module as well.
#[macro_escape]
mod macros;

#[macro_escape]
mod base;

macro_rules! rule(
  (
    $name:ident <- $body:expr
  ) => (
    pub fn $name<'a>( parse_state: &base::ParseState<'a> )
         -> std::option::Option< base::ParseResult<'a> > {
      use base::Expression;
      use base::Node;
      use base::ParseResult;
      use std::clone::Clone;
      use std::option::{Some, None};

      #[allow(dead_code)]
      static node_name : &'static str = stringify!( $name );

      match $body.apply( parse_state ) {
        Some( result ) => {
          let state = result.parse_state.clone();
          Some( ParseResult::oneNode(
              Node::newParent( node_name, result.nodes ), state ) )
        }
        _ => None
      }
    }
  );
)

#[cfg(not(test))]
pub fn parse<'a>( input: &'a [u8] ) -> Option< Node<'a> > {
  static root_name : &'static str = "NailedRoot";
  let parse_state = ParseState { input: input, offset: 0 };
  match rules::Grammar( &parse_state ) {
    Some( result ) => Some( Node::newParent( root_name, result.nodes ) ),
    _ => None
  }
}

mod rules {
  #![no_implicit_prelude]

  use base;
  use std;

  rule!( Grammar <- seq!( ex!( Spacing ),
                          plus!( ex!( Definition ) ),
                          ex!( EndOfFile ) ) )
  rule!( Definition <- seq!( ex!( Identifier ),
                            ex!( LEFTARROW ),
                            ex!( Expression ) ) )
  rule!( Expression <- seq!( ex!( Sequence ),
                            star!( seq!( ex!( SLASH ), ex!( Sequence ) ) ) ) )
  rule!( Sequence <- star!( ex!( Prefix ) ) )
  rule!( Prefix <- seq!( opt!( or!( ex!( AND ),
                                    ex!( NOT ) ) ),
                        ex!( Suffix ) ) )
  rule!( Suffix <- seq!( ex!( Primary ),
                        opt!( or!( ex!( QUESTION ),
                                    ex!( STAR ),
                                    ex!( PLUS ) ) ) ) )
  rule!( Primary <- or!( seq!( ex!( Identifier ),
                              not!( ex!( LEFTARROW ) ) ),
                        seq!( ex!( OPEN ),
                              ex!( Expression ),
                              ex!( CLOSE ) ),
                        ex!( Literal ),
                        ex!( Class ),
                        ex!( DOT ) ) )
  rule!( Identifier <- seq!( ex!( IdentStart ),
                            star!( ex!( IdentCont ) ),
                            ex!( Spacing ) ) )
  rule!( IdentStart <- class!( "a-zA-Z_" ) )
  rule!( IdentCont <- or!( ex!( IdentStart ), class!( "0-9" ) ) )
  rule!( Literal <- or!( seq!( class!( "'" ),
                              star!( seq!( not!( class!( "'" ) ),
                                            ex!( Char ) ) ),
                              class!( "'" ),
                              ex!( Spacing ) ),
                        seq!( class!( "\"" ),
                              star!( seq!( not!( class!( "\"" ) ),
                                            ex!( Char ) ) ),
                              class!( "\"" ),
                              ex!( Spacing ) ) ) )
  rule!( Class <- seq!( lit!( "[" ),
                        star!( seq!( not!( lit!( "]" ) ), ex!( Range ) ) ),
                        lit!( "]" ),
                        ex!( Spacing ) ) )
  rule!( Range <- or!( seq!( ex!( Char ), lit!( "-" ), ex!( Char ) ),
                      ex!( Char ) ) )
  rule!( Char <- or!( seq!( lit!( r"\" ),
                            class!( r#"nrt'"[]\"# ) ),
                      seq!( lit!( r"\" ),
                            class!( "0-2" ),
                            class!( "0-7" ),
                            class!( "0-7" ) ),
                      seq!( lit!( r"\" ),
                            class!( "0-7" ),
                            opt!( class!( "0-7" ) ) ),
                      seq!( not!( lit!( r"\" ) ),
                            base::Dot ) ) )
  rule!( LEFTARROW <- seq!( lit!( "<-" ), ex!( Spacing ) ) )
  rule!( SLASH <- seq!( lit!( "/" ), ex!( Spacing ) ) )
  rule!( AND <- seq!( lit!( "&" ), ex!( Spacing ) ) )
  rule!( NOT <- seq!( lit!( "!" ), ex!( Spacing ) ) )
  rule!( QUESTION <- seq!( lit!( "?" ), ex!( Spacing ) ) )
  rule!( STAR <- seq!( lit!( "*" ), ex!( Spacing ) ) )
  rule!( PLUS <- seq!( lit!( "+" ), ex!( Spacing ) ) )
  rule!( OPEN <- seq!( lit!( "(" ), ex!( Spacing ) ) )
  rule!( CLOSE <- seq!( lit!( ")" ), ex!( Spacing ) ) )
  rule!( DOT <- seq!( lit!( "." ), ex!( Spacing ) ) )
  rule!( Spacing <- star!( or!( ex!( Space ), ex!( Comment ) ) ) )
  rule!( Comment <- seq!( lit!( "#" ),
                          star!( seq!( not!( ex!( EndOfLine ) ), base::Dot ) ),
                          ex!( EndOfLine ) ) )
  rule!( Space <- or!( lit!( " " ), lit!( "\t" ), ex!( EndOfLine ) ) )
  rule!( EndOfLine <- or!( lit!( "\r\n" ), lit!( "\n" ), lit!( "\r" ) ) )
  rule!( EndOfFile <- not!( base::Dot ) )

  #[cfg(test)]
  mod tests {
    use super::{EndOfFile, EndOfLine, Space, Comment, Spacing, Char, Range,
                Class, Literal, Identifier, Definition, Grammar};

    macro_rules! consumes(
      (
        $name:ident, $input:expr
      ) => (
        {
          use base::ParseResult;
          use std::option::Some;
          use std::container::Container;

          match $name( &input_state!( $input ) ) {
            Some( ParseResult{ nodes: _,
                              parse_state: parse_state } ) => {
              parse_state.input.is_empty()
            }
            _ => false
          }
        }
      );
    )

    macro_rules! matches(
      (
        $name:ident, $input:expr
      ) => (
        $name( &input_state!( $input ) ).is_some()
      );
    )

    #[test]
    fn Grammar_Works() {
      assert!( consumes!( Grammar,
                          r#"
        h16           <- HEXDIGIT (HEXDIGIT (HEXDIGIT HEXDIGIT?)?)?
        ls32          <- h16 ":" h16 / IPv4address
        IPv4address   <- dec_octet "." dec_octet "." dec_octet "." dec_octet"#
        ) )
    }

    #[test]
    fn Definition_Works() {
      assert!( consumes!( Definition,
                          "Grammar <- Spacing Definition+ EndOfFile" ) )
      assert!( consumes!( Definition,
                          r#"Char <- '\\' [nrt'"\[\]\\] /
                                    '\\' [0-2][0-7][0-7] /
                                    '\\' [0-7][0-7]? /
                                    !'\\' ."# ) )
    }

    #[test]
    fn Identifier_Works() {
      assert!( consumes!( Identifier, "abc" ) );
      assert!( consumes!( Identifier, "a" ) );
      assert!( consumes!( Identifier, "_" ) );
      assert!( consumes!( Identifier, "a123" ) );
      assert!( consumes!( Identifier, "a  \n" ) );

      assert!( !consumes!( Identifier, "1a" ) );
      assert!( !consumes!( Identifier, "1" ) );
      assert!( !consumes!( Identifier, "Ć" ) );
    }

    #[test]
    fn Literal_Works() {
      assert!( consumes!( Literal, "'abc'" ) );
      assert!( consumes!( Literal, r#""abc""# ) );
      assert!( consumes!( Literal, "'abc'  \n" ) );
      assert!( !consumes!( Literal, "'abc''bb'" ) );
    }

    #[test]
    fn Class_Works() {
      assert!( consumes!( Class, "[a-z]" ) );
      assert!( consumes!( Class, "[a-z]  \n" ) );
      assert!( consumes!( Class, "[abc]" ) );
      assert!( consumes!( Class, "[abc0-9g]" ) );
    }

    #[test]
    fn Range_Works() {
      assert!( consumes!( Range, "a-z" ) );
      assert!( consumes!( Range, "a" ) );
    }

    #[test]
    fn Char_Works() {
      assert!( consumes!( Char, r"\n" ) );
      assert!( consumes!( Char, r"\]" ) );
      assert!( consumes!( Char, r"\\" ) );
      assert!( consumes!( Char, r"\'" ) );
      assert!( consumes!( Char, "a" ) );
      assert!( consumes!( Char, "x" ) );
      assert!( consumes!( Char, "Ć" ) );
      assert!( consumes!( Char, "€" ) );
      assert!( consumes!( Char, r"\277" ) );
      assert!( consumes!( Char, r"\77" ) );
      assert!( consumes!( Char, r"\7" ) );

      assert!( !consumes!( Char, "aa" ) );
    }

    #[test]
    fn Spacing_Works() {
      assert!( consumes!( Spacing, "  \t #g\n" ) );
      assert!( consumes!( Spacing, "#a\n  #1\n" ) );

      // Spacing DOES match here because at the top level, it is a star
      // expression which can match consuming nothing.
      assert!( matches!( Spacing, "" ) );
      assert!( !consumes!( Spacing, "#" ) );
      assert!( !consumes!( Spacing, "a" ) );
    }

    #[test]
    fn Comment_Works() {
      assert!( consumes!( Comment, "#\n" ) );
      assert!( consumes!( Comment, "# foo! \n" ) );
      assert!( !matches!( Comment, "\n" ) );
      assert!( !matches!( Comment, "#" ) );
      assert!( !matches!( Comment, "a" ) );
    }

    #[test]
    fn Space_Works() {
      assert!( consumes!( Space, " " ) );
      assert!( consumes!( Space, "\t" ) );
      assert!( consumes!( Space, "\n" ) );
      assert!( !matches!( Space, "a" ) );
    }

    #[test]
    fn EndOfLine_Works() {
      assert!( consumes!( EndOfLine, "\n" ) );
      assert!( consumes!( EndOfLine, "\r" ) );
      assert!( consumes!( EndOfLine, "\r\n" ) );
      assert!( !matches!( EndOfLine, "a" ) );
    }

    #[test]
    fn EndOfFile_Works() {
      assert!( consumes!( EndOfFile, "" ) );
      assert!( !matches!( EndOfFile, "a" ) );
    }
  }
}
<|endoftext|>


<commit_before>mod moduletype;

use std::path::Path;
use std::rc::Rc;
use thiserror::Error;

use witx::{self, Id, Module};

pub use self::moduletype::{ImportFunc, ModuleType};
pub use wasmparser::FuncType;
pub use witx::{AtomType, Document, WitxError};

#[derive(Debug, Error)]
pub enum Error {
    #[error("WebAssembly validation error at offset {1}: {0}")]
    WasmValidation(String, usize),
    #[error("Unsupported: {0}")]
    Unsupported(String),
    #[error("Module not found: {0}")]
    ModuleNotFound(String),
    #[error("Import not found: {module}::{field}")]
    ImportNotFound { module: String, field: String },
    #[error("Export not found: {field}")]
    ExportNotFound { field: String },
    #[error("Import type error: for {module}::{field}, expected {expected:?}, got {got:?}")]
    ImportTypeError {
        module: String,
        field: String,
        expected: FuncType,
        got: FuncType,
    },
    #[error("Export type error: for {field}, expected {expected:?}, got {got:?}")]
    ExportTypeError {
        field: String,
        expected: FuncType,
        got: FuncType,
    },
}

impl From<wasmparser::BinaryReaderError> for Error {
    fn from(e: wasmparser::BinaryReaderError) -> Error {
        Error::WasmValidation(e.message().to_owned(), e.offset())
    }
}

#[derive(Debug, Clone)]
pub struct Validator {
    witx: Document,
    wasi_exe: bool,
}

impl Validator {
    pub fn new(witx: Document, wasi_exe: bool) -> Self {
        Self { witx, wasi_exe }
    }

    pub fn parse(source: &str) -> Result<Self, WitxError> {
        let witx = witx::parse(source)?;
        Ok(Self {
            witx,
            wasi_exe: false,
        })
    }

    pub fn load<P: AsRef<Path>>(source_paths: &[P]) -> Result<Self, WitxError> {
        let witx = witx::load(source_paths)?;
        Ok(Self {
            witx,
            wasi_exe: false,
        })
    }

    pub fn wasi_exe(&mut self, check: bool) {
        self.wasi_exe = check;
    }

    pub fn with_wasi_exe(mut self, check: bool) -> Self {
        self.wasi_exe(check);
        self
    }

    pub fn validate(&self, module_contents: &[u8]) -> Result<(), Error> {
        wasmparser::validate(module_contents, None)?;

        let moduletype = ModuleType::parse_wasm(module_contents)?;

        for import in moduletype.imports() {
            let func = self
                .witx_module(&import.module)?
                .func(&Id::new(&import.field))
                .ok_or_else(|| Error::ImportNotFound {
                    module: import.module.clone(),
                    field: import.field.clone(),
                })?;
            let spec_type = witx_to_functype(&func.core_type());
            if spec_type != import.ty {
                return Err(Error::ImportTypeError {
                    module: import.module,
                    field: import.field,
                    got: import.ty,
                    expected: spec_type,
                });
            }
        }

        if self.wasi_exe {
            self.check_wasi_start_func(&moduletype)?;
        }

        Ok(())
    }

    pub fn doc(&self) -> &Document {
        &self.witx
    }

    fn witx_module(&self, module: &str) -> Result<Rc<Module>, Error> {
        self.witx
            .module(&Id::new(module))
            .ok_or_else(|| Error::ModuleNotFound(module.to_string()))
    }

    fn check_wasi_start_func(&self, moduletype: &ModuleType) -> Result<(), Error> {
        let start_name = "_start";
        let expected = FuncType {
            params: vec![].into_boxed_slice(),
            returns: vec![].into_boxed_slice(),
        };
        if let Some(startfunc) = moduletype.export(start_name) {
            if startfunc != &expected {
                Err(Error::ExportTypeError {
                    field: start_name.to_string(),
                    expected,
                    got: startfunc.clone(),
                })
            } else {
                Ok(())
            }
        } else {
            Err(Error::ExportNotFound {
                field: start_name.to_string(),
            })
        }
    }
}

fn witx_to_functype(coretype: &witx::CoreFuncType) -> FuncType {
    fn atom_to_type(atom: &witx::AtomType) -> wasmparser::Type {
        match atom {
            witx::AtomType::I32 => wasmparser::Type::I32,
            witx::AtomType::I64 => wasmparser::Type::I64,
            witx::AtomType::F32 => wasmparser::Type::F32,
            witx::AtomType::F64 => wasmparser::Type::F64,
        }
    }
    let params = coretype
        .args
        .iter()
        .map(|a| atom_to_type(&a.repr()))
        .collect::<Vec<_>>()
        .into_boxed_slice();
    let returns = if let Some(ref r) = coretype.ret {
        vec![atom_to_type(&r.repr())].into_boxed_slice()
    } else {
        vec![].into_boxed_slice()
    };
    FuncType { params, returns }
}
<commit_msg>validate: factor<commit_after>mod moduletype;

use std::path::Path;
use std::rc::Rc;
use thiserror::Error;

use witx::{self, Id, Module};

pub use self::moduletype::{ImportFunc, ModuleType};
pub use wasmparser::FuncType;
pub use witx::{AtomType, Document, WitxError};

#[derive(Debug, Error)]
pub enum Error {
    #[error("WebAssembly validation error at offset {1}: {0}")]
    WasmValidation(String, usize),
    #[error("Unsupported: {0}")]
    Unsupported(String),
    #[error("Module not found: {0}")]
    ModuleNotFound(String),
    #[error("Import not found: {module}::{field}")]
    ImportNotFound { module: String, field: String },
    #[error("Export not found: {field}")]
    ExportNotFound { field: String },
    #[error("Import type error: for {module}::{field}, expected {expected:?}, got {got:?}")]
    ImportTypeError {
        module: String,
        field: String,
        expected: FuncType,
        got: FuncType,
    },
    #[error("Export type error: for {field}, expected {expected:?}, got {got:?}")]
    ExportTypeError {
        field: String,
        expected: FuncType,
        got: FuncType,
    },
}

impl From<wasmparser::BinaryReaderError> for Error {
    fn from(e: wasmparser::BinaryReaderError) -> Error {
        Error::WasmValidation(e.message().to_owned(), e.offset())
    }
}

#[derive(Debug, Clone)]
pub struct Validator {
    witx: Document,
    required_exports: Vec<(&'static str, FuncType)>,
}

impl Validator {
    pub fn new(witx: Document, wasi_exe: bool) -> Self {
        Self {
            witx,
            required_exports: vec![],
        }
        .with_wasi_exe(wasi_exe)
    }

    pub fn parse(source: &str) -> Result<Self, WitxError> {
        let witx = witx::parse(source)?;
        Ok(Self::new(witx, false))
    }

    pub fn load<P: AsRef<Path>>(source_paths: &[P]) -> Result<Self, WitxError> {
        let witx = witx::load(source_paths)?;
        Ok(Self::new(witx, false))
    }

    pub fn wasi_exe(&mut self, check: bool) {
        if check {
            self.required_exports = vec![(
                "_start",
                FuncType {
                    params: vec![].into_boxed_slice(),
                    returns: vec![].into_boxed_slice(),
                },
            )];
        } else {
            self.required_exports = vec![];
        }
    }

    pub fn with_wasi_exe(mut self, check: bool) -> Self {
        self.wasi_exe(check);
        self
    }

    pub fn available_import(
        &self,
        module: &str,
        field: &str,
        type_: &FuncType,
    ) -> Result<(), Error> {
        let func = self
            .witx_module(module)?
            .func(&Id::new(field))
            .ok_or_else(|| Error::ImportNotFound {
                module: module.to_owned(),
                field: field.to_owned(),
            })?;
        let spec_type = witx_to_functype(&func.core_type());
        if &spec_type != type_ {
            return Err(Error::ImportTypeError {
                module: module.to_owned(),
                field: field.to_owned(),
                got: type_.clone(),
                expected: spec_type,
            });
        } else {
            Ok(())
        }
    }

    pub fn required_exports(&self) -> &[(&'static str, FuncType)] {
        &self.required_exports
    }

    pub fn validate(&self, module_contents: &[u8]) -> Result<(), Error> {
        wasmparser::validate(module_contents, None)?;

        let moduletype = ModuleType::parse_wasm(module_contents)?;

        for import in moduletype.imports() {
            self.available_import(&import.module, &import.field, &import.ty)?;
        }

        for (name, expected) in self.required_exports.iter() {
            if let Some(e) = moduletype.export(name) {
                if e != expected {
                    return Err(Error::ExportTypeError {
                        field: name.to_string(),
                        expected: expected.clone(),
                        got: e.clone(),
                    });
                }
            } else {
                return Err(Error::ExportNotFound {
                    field: name.to_string(),
                });
            }
        }

        Ok(())
    }

    pub fn doc(&self) -> &Document {
        &self.witx
    }

    fn witx_module(&self, module: &str) -> Result<Rc<Module>, Error> {
        self.witx
            .module(&Id::new(module))
            .ok_or_else(|| Error::ModuleNotFound(module.to_string()))
    }
}

fn witx_to_functype(coretype: &witx::CoreFuncType) -> FuncType {
    fn atom_to_type(atom: &witx::AtomType) -> wasmparser::Type {
        match atom {
            witx::AtomType::I32 => wasmparser::Type::I32,
            witx::AtomType::I64 => wasmparser::Type::I64,
            witx::AtomType::F32 => wasmparser::Type::F32,
            witx::AtomType::F64 => wasmparser::Type::F64,
        }
    }
    let params = coretype
        .args
        .iter()
        .map(|a| atom_to_type(&a.repr()))
        .collect::<Vec<_>>()
        .into_boxed_slice();
    let returns = if let Some(ref r) = coretype.ret {
        vec![atom_to_type(&r.repr())].into_boxed_slice()
    } else {
        vec![].into_boxed_slice()
    };
    FuncType { params, returns }
}
<|endoftext|>


<commit_before>use super::*;
use redox::*;

impl Editor {
    /// Redraw the window
    pub fn redraw(&mut self) {
        // TODO: Only draw when relevant for the window
        let x = self.x();
        let y = self.y();
        // Redraw window
        self.window.set([0, 0, 0, 255]);

        self.window.rect(8 * (x - self.scroll_y) as isize,
                         16 * (y - self.scroll_x) as isize,
                         8,
                         16,
                         [255, 255, 255, 255]);

        for (y, row) in self.text.iter().enumerate() {
            for (x, c) in row.iter().enumerate() {
                if self.x() == x && self.y() == y {
                    self.window.char(8 * (x - self.scroll_y) as isize,
                                     16 * (y - self.scroll_x) as isize,
                                     *c,
                                     [0, 0, 0, 255]);
                } else {
                    self.window.char(8 * (x - self.scroll_y) as isize,
                                     16 * (y - self.scroll_x) as isize,
                                     *c,
                                     [255, 255, 255, 255]);
                }
            }
        }
        let h = self.window.height();
        let w = self.window.width();
        self.window.rect(0, h as isize - 18, w, 18, [74, 74, 74, 255]);

        for (n, c) in (if self.status_bar.mode.len() > w / (8 * 4) {
            self.status_bar.mode.chars().take(w / (8 * 4) - 5).chain(vec!['.', '.', '.']).collect::<Vec<_>>()
        } else {
            self.status_bar.mode.chars().collect()
        }).into_iter().enumerate() {
            self.window.char(n as isize * 8, h as isize - 16 - 1, c, [255, 255, 255, 255]);
        }

        self.window.sync();
    }
}

/// The statubar (showing various info about the current state of the editor)
pub struct StatusBar {
    /// The current mode
    pub mode: String,
    /// The cureent char
    pub file: String,
    /// The current command
    pub cmd: String,
    /// A message (such as an error or other info to the user)
    pub msg: String,
}

impl StatusBar {
    /// Create new status bar
    pub fn new() -> Self {
        StatusBar {
            mode: "Normal".to_string(),
            file: String::new(),
            cmd: String::new(),
            msg: String::new(),
        }
    }
}
<commit_msg>Fix tab insertion<commit_after>use super::*;
use redox::*;

impl Editor {
    /// Redraw the window
    pub fn redraw(&mut self) {
        // TODO: Only draw when relevant for the window
        let x = self.x();
        let y = self.y();
        // Redraw window
        self.window.set([0, 0, 0, 255]);

        self.window.rect(8 * (x - self.scroll_y) as isize,
                         16 * (y - self.scroll_x) as isize,
                         8,
                         16,
                         [255, 255, 255, 255]);

        for (y, row) in self.text.iter().enumerate() {
            for (x, c) in row.iter().enumerate() {
                if self.x() == x && self.y() == y {
                    self.window.char(8 * (x - self.scroll_y) as isize,
                                     16 * (y - self.scroll_x) as isize,
                                     *c,
                                     [0, 0, 0, 255]);
                } else {
                    self.window.char(8 * (x - self.scroll_y) as isize,
                                     16 * (y - self.scroll_x) as isize,
                                     *c,
                                     [255, 255, 255, 255]);
                }
            }
        }
        let h = self.window.height();
        let w = self.window.width();
        self.window.rect(0, h as isize - 18, w, 18, [74, 74, 74, 255]);

        for (n, c) in (if self.status_bar.mode.len() > w / (8 * 4) {
            self.status_bar.mode.chars().take(w / (8 * 4) - 5).chain(vec!['.', '.', '.']).collect::<Vec<_>>()
        } else {
            self.status_bar.mode.chars().collect()
        }).into_iter().enumerate() {
            self.window.char(n as isize * 8, h as isize - 16 - 1, if c == '\t' { ' ' } else { c }, [255, 255, 255, 255]);
        }

        self.window.sync();
    }
}

/// The statubar (showing various info about the current state of the editor)
pub struct StatusBar {
    /// The current mode
    pub mode: String,
    /// The cureent char
    pub file: String,
    /// The current command
    pub cmd: String,
    /// A message (such as an error or other info to the user)
    pub msg: String,
}

impl StatusBar {
    /// Create new status bar
    pub fn new() -> Self {
        StatusBar {
            mode: "Normal".to_string(),
            file: String::new(),
            cmd: String::new(),
            msg: String::new(),
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(custom_inner_attributes)]
#![feature(test)]

// Rustfmt splits macro invocations to shorten lines; in this case longer-lines are more readable
#![rustfmt::skip]

extern crate test;

const RAND_BENCH_N: u64 = 1000;

use std::mem::size_of;
use test::Bencher;

use rand::prelude::*;
use rand_distr::{weighted::WeightedIndex, *};

// At this time, distributions are optimised for 64-bit platforms.
use rand_pcg::Pcg64Mcg;

macro_rules! distr_int {
    ($fnn:ident, $ty:ty, $distr:expr) => {
        #[bench]
        fn $fnn(b: &mut Bencher) {
            let mut rng = Pcg64Mcg::from_entropy();
            let distr = $distr;

            b.iter(|| {
                let mut accum = 0 as $ty;
                for _ in 0..RAND_BENCH_N {
                    let x: $ty = distr.sample(&mut rng);
                    accum = accum.wrapping_add(x);
                }
                accum
            });
            b.bytes = size_of::<$ty>() as u64 * RAND_BENCH_N;
        }
    };
}

macro_rules! distr_float {
    ($fnn:ident, $ty:ty, $distr:expr) => {
        #[bench]
        fn $fnn(b: &mut Bencher) {
            let mut rng = Pcg64Mcg::from_entropy();
            let distr = $distr;

            b.iter(|| {
                let mut accum = 0.0;
                for _ in 0..RAND_BENCH_N {
                    let x: $ty = distr.sample(&mut rng);
                    accum += x;
                }
                accum
            });
            b.bytes = size_of::<$ty>() as u64 * RAND_BENCH_N;
        }
    };
}

macro_rules! distr {
    ($fnn:ident, $ty:ty, $distr:expr) => {
        #[bench]
        fn $fnn(b: &mut Bencher) {
            let mut rng = Pcg64Mcg::from_entropy();
            let distr = $distr;

            b.iter(|| {
                let mut accum = 0u32;
                for _ in 0..RAND_BENCH_N {
                    let x: $ty = distr.sample(&mut rng);
                    accum = accum.wrapping_add(x as u32);
                }
                accum
            });
            b.bytes = size_of::<$ty>() as u64 * RAND_BENCH_N;
        }
    };
}

macro_rules! distr_arr {
    ($fnn:ident, $ty:ty, $distr:expr) => {
        #[bench]
        fn $fnn(b: &mut Bencher) {
            let mut rng = Pcg64Mcg::from_entropy();
            let distr = $distr;

            b.iter(|| {
                let mut accum = 0u32;
                for _ in 0..RAND_BENCH_N {
                    let x: $ty = distr.sample(&mut rng);
                    accum = accum.wrapping_add(x[0] as u32);
                }
                accum
            });
            b.bytes = size_of::<$ty>() as u64 * RAND_BENCH_N;
        }
    };
}

// distributions
distr_float!(distr_exp, f64, Exp::new(1.23 * 4.56).unwrap());
distr_float!(distr_normal, f64, Normal::new(-1.23, 4.56).unwrap());
distr_float!(distr_log_normal, f64, LogNormal::new(-1.23, 4.56).unwrap());
distr_float!(distr_gamma_large_shape, f64, Gamma::new(10., 1.0).unwrap());
distr_float!(distr_gamma_small_shape, f64, Gamma::new(0.1, 1.0).unwrap());
distr_float!(distr_beta_small_param, f64, Beta::new(0.1, 0.1).unwrap());
distr_float!(distr_beta_large_param_similar, f64, Beta::new(101., 95.).unwrap());
distr_float!(distr_beta_large_param_different, f64, Beta::new(10., 1000.).unwrap());
distr_float!(distr_beta_mixed_param, f64, Beta::new(0.5, 100.).unwrap());
distr_float!(distr_cauchy, f64, Cauchy::new(4.2, 6.9).unwrap());
distr_float!(distr_triangular, f64, Triangular::new(0., 1., 0.9).unwrap());
distr_int!(distr_binomial, u64, Binomial::new(20, 0.7).unwrap());
distr_int!(distr_binomial_small, u64, Binomial::new(1000000, 1e-30).unwrap());
distr_int!(distr_poisson, u64, Poisson::new(4.0).unwrap());
distr!(distr_bernoulli, bool, Bernoulli::new(0.18).unwrap());
distr_arr!(distr_circle, [f64; 2], UnitCircle);
distr_arr!(distr_sphere, [f64; 3], UnitSphere);

// Weighted
distr_int!(distr_weighted_i8, usize, WeightedIndex::new(&[1i8, 2, 3, 4, 12, 0, 2, 1]).unwrap());
distr_int!(distr_weighted_u32, usize, WeightedIndex::new(&[1u32, 2, 3, 4, 12, 0, 2, 1]).unwrap());
distr_int!(distr_weighted_f64, usize, WeightedIndex::new(&[1.0f64, 0.001, 1.0/3.0, 4.01, 0.0, 3.3, 22.0, 0.001]).unwrap());
distr_int!(distr_weighted_large_set, usize, WeightedIndex::new((0..10000).rev().chain(1..10001)).unwrap());

distr_int!(distr_weighted_alias_method_i8, usize, weighted::alias_method::WeightedIndex::new(vec![1i8, 2, 3, 4, 12, 0, 2, 1]).unwrap());
distr_int!(distr_weighted_alias_method_u32, usize, weighted::alias_method::WeightedIndex::new(vec![1u32, 2, 3, 4, 12, 0, 2, 1]).unwrap());
distr_int!(distr_weighted_alias_method_f64, usize, weighted::alias_method::WeightedIndex::new(vec![1.0f64, 0.001, 1.0/3.0, 4.01, 0.0, 3.3, 22.0, 0.001]).unwrap());
distr_int!(distr_weighted_alias_method_large_set, usize, weighted::alias_method::WeightedIndex::new((0..10000).rev().chain(1..10001).collect()).unwrap());

#[bench]
fn dist_iter(b: &mut Bencher) {
    let mut rng = Pcg64Mcg::from_entropy();
    let distr = Normal::new(-2.71828, 3.14159).unwrap();
    let mut iter = distr.sample_iter(&mut rng);

    b.iter(|| {
        let mut accum = 0.0;
        for _ in 0..RAND_BENCH_N {
            accum += iter.next().unwrap();
        }
        accum
    });
    b.bytes = size_of::<f64>() as u64 * RAND_BENCH_N;
}

macro_rules! sample_binomial {
    ($name:ident, $n:expr, $p:expr) => {
        #[bench]
        fn $name(b: &mut Bencher) {
            let mut rng = Pcg64Mcg::from_rng(&mut thread_rng()).unwrap();
            let (n, p) = ($n, $p);
            b.iter(|| {
                let d = Binomial::new(n, p).unwrap();
                rng.sample(d)
            })
        }
    };
}

sample_binomial!(misc_binomial_1, 1, 0.9);
sample_binomial!(misc_binomial_10, 10, 0.9);
sample_binomial!(misc_binomial_100, 100, 0.99);
sample_binomial!(misc_binomial_1000, 1000, 0.01);
sample_binomial!(misc_binomial_1e12, 1000_000_000_000, 0.2);
<commit_msg>rand_distr: Fix benchmarks<commit_after>// Copyright 2018 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(custom_inner_attributes)]
#![feature(test)]

// Rustfmt splits macro invocations to shorten lines; in this case longer-lines are more readable
#![rustfmt::skip]

extern crate test;

const RAND_BENCH_N: u64 = 1000;

use std::mem::size_of;
use test::Bencher;

use rand::prelude::*;
use rand_distr::*;

// At this time, distributions are optimised for 64-bit platforms.
use rand_pcg::Pcg64Mcg;

macro_rules! distr_int {
    ($fnn:ident, $ty:ty, $distr:expr) => {
        #[bench]
        fn $fnn(b: &mut Bencher) {
            let mut rng = Pcg64Mcg::from_entropy();
            let distr = $distr;

            b.iter(|| {
                let mut accum = 0 as $ty;
                for _ in 0..RAND_BENCH_N {
                    let x: $ty = distr.sample(&mut rng);
                    accum = accum.wrapping_add(x);
                }
                accum
            });
            b.bytes = size_of::<$ty>() as u64 * RAND_BENCH_N;
        }
    };
}

macro_rules! distr_float {
    ($fnn:ident, $ty:ty, $distr:expr) => {
        #[bench]
        fn $fnn(b: &mut Bencher) {
            let mut rng = Pcg64Mcg::from_entropy();
            let distr = $distr;

            b.iter(|| {
                let mut accum = 0.0;
                for _ in 0..RAND_BENCH_N {
                    let x: $ty = distr.sample(&mut rng);
                    accum += x;
                }
                accum
            });
            b.bytes = size_of::<$ty>() as u64 * RAND_BENCH_N;
        }
    };
}

macro_rules! distr {
    ($fnn:ident, $ty:ty, $distr:expr) => {
        #[bench]
        fn $fnn(b: &mut Bencher) {
            let mut rng = Pcg64Mcg::from_entropy();
            let distr = $distr;

            b.iter(|| {
                let mut accum = 0u32;
                for _ in 0..RAND_BENCH_N {
                    let x: $ty = distr.sample(&mut rng);
                    accum = accum.wrapping_add(x as u32);
                }
                accum
            });
            b.bytes = size_of::<$ty>() as u64 * RAND_BENCH_N;
        }
    };
}

macro_rules! distr_arr {
    ($fnn:ident, $ty:ty, $distr:expr) => {
        #[bench]
        fn $fnn(b: &mut Bencher) {
            let mut rng = Pcg64Mcg::from_entropy();
            let distr = $distr;

            b.iter(|| {
                let mut accum = 0u32;
                for _ in 0..RAND_BENCH_N {
                    let x: $ty = distr.sample(&mut rng);
                    accum = accum.wrapping_add(x[0] as u32);
                }
                accum
            });
            b.bytes = size_of::<$ty>() as u64 * RAND_BENCH_N;
        }
    };
}

// distributions
distr_float!(distr_exp, f64, Exp::new(1.23 * 4.56).unwrap());
distr_float!(distr_normal, f64, Normal::new(-1.23, 4.56).unwrap());
distr_float!(distr_log_normal, f64, LogNormal::new(-1.23, 4.56).unwrap());
distr_float!(distr_gamma_large_shape, f64, Gamma::new(10., 1.0).unwrap());
distr_float!(distr_gamma_small_shape, f64, Gamma::new(0.1, 1.0).unwrap());
distr_float!(distr_beta_small_param, f64, Beta::new(0.1, 0.1).unwrap());
distr_float!(distr_beta_large_param_similar, f64, Beta::new(101., 95.).unwrap());
distr_float!(distr_beta_large_param_different, f64, Beta::new(10., 1000.).unwrap());
distr_float!(distr_beta_mixed_param, f64, Beta::new(0.5, 100.).unwrap());
distr_float!(distr_cauchy, f64, Cauchy::new(4.2, 6.9).unwrap());
distr_float!(distr_triangular, f64, Triangular::new(0., 1., 0.9).unwrap());
distr_int!(distr_binomial, u64, Binomial::new(20, 0.7).unwrap());
distr_int!(distr_binomial_small, u64, Binomial::new(1000000, 1e-30).unwrap());
distr_float!(distr_poisson, f64, Poisson::new(4.0).unwrap());
distr!(distr_bernoulli, bool, Bernoulli::new(0.18).unwrap());
distr_arr!(distr_circle, [f64; 2], UnitCircle);
distr_arr!(distr_sphere, [f64; 3], UnitSphere);

// Weighted
distr_int!(distr_weighted_i8, usize, WeightedIndex::new(&[1i8, 2, 3, 4, 12, 0, 2, 1]).unwrap());
distr_int!(distr_weighted_u32, usize, WeightedIndex::new(&[1u32, 2, 3, 4, 12, 0, 2, 1]).unwrap());
distr_int!(distr_weighted_f64, usize, WeightedIndex::new(&[1.0f64, 0.001, 1.0/3.0, 4.01, 0.0, 3.3, 22.0, 0.001]).unwrap());
distr_int!(distr_weighted_large_set, usize, WeightedIndex::new((0..10000).rev().chain(1..10001)).unwrap());

distr_int!(distr_weighted_alias_method_i8, usize, WeightedAliasIndex::new(vec![1i8, 2, 3, 4, 12, 0, 2, 1]).unwrap());
distr_int!(distr_weighted_alias_method_u32, usize, WeightedAliasIndex::new(vec![1u32, 2, 3, 4, 12, 0, 2, 1]).unwrap());
distr_int!(distr_weighted_alias_method_f64, usize, WeightedAliasIndex::new(vec![1.0f64, 0.001, 1.0/3.0, 4.01, 0.0, 3.3, 22.0, 0.001]).unwrap());
distr_int!(distr_weighted_alias_method_large_set, usize, WeightedAliasIndex::new((0..10000).rev().chain(1..10001).collect()).unwrap());

#[bench]
fn dist_iter(b: &mut Bencher) {
    let mut rng = Pcg64Mcg::from_entropy();
    let distr = Normal::new(-2.71828, 3.14159).unwrap();
    let mut iter = distr.sample_iter(&mut rng);

    b.iter(|| {
        let mut accum = 0.0;
        for _ in 0..RAND_BENCH_N {
            accum += iter.next().unwrap();
        }
        accum
    });
    b.bytes = size_of::<f64>() as u64 * RAND_BENCH_N;
}

macro_rules! sample_binomial {
    ($name:ident, $n:expr, $p:expr) => {
        #[bench]
        fn $name(b: &mut Bencher) {
            let mut rng = Pcg64Mcg::from_rng(&mut thread_rng()).unwrap();
            let (n, p) = ($n, $p);
            b.iter(|| {
                let d = Binomial::new(n, p).unwrap();
                rng.sample(d)
            })
        }
    };
}

sample_binomial!(misc_binomial_1, 1, 0.9);
sample_binomial!(misc_binomial_10, 10, 0.9);
sample_binomial!(misc_binomial_100, 100, 0.99);
sample_binomial!(misc_binomial_1000, 1000, 0.01);
sample_binomial!(misc_binomial_1e12, 1000_000_000_000, 0.2);
<|endoftext|>


<commit_before>extern crate ansi_term;
extern crate rand;

use ansi_term::Colour::*;
use rand::Rng;
use std::io;

enum Card {
    ClubsAce,
    ClubsTen,
    ClubsKing,
    ClubsQueen,
    ClubsJack,
    ClubsNine,
    ClubsEight,
    ClubsSeven,
    SpadesAce,
    SpadesTen,
    SpadesKing,
    SpadesQueen,
    SpadesJack,
    SpadesNine,
    SpadesEight,
    SpadesSeven,
    HeartsAce,
    HeartsTen,
    HeartsKing,
    HeartsQueen,
    HeartsJack,
    HeartsNine,
    HeartsEight,
    HeartsSeven,
    DiamondsAce,
    DiamondsTen,
    DiamondsKing,
    DiamondsQueen,
    DiamondsJack,
    DiamondsNine,
    DiamondsEight,
    DiamondsSeven,
}

enum Game {
    Suit,
    Grand,
    Null,
}

enum Player {
    A,
    B,
    C,
}

fn bid(dealer: u8) -> (u8, u8) {
    let winner: u8 = dealer;
    let highest: u8 = 18;
    // TODO
    (winner, highest)
}

fn deal(dealer: u8) {
    let mut cards: Vec<u8> = Vec::new();
    for n in 0..32 {
        cards.push(n);
    }
    // print clubs
    let club    = "♣";
    let spade   = "♠";
    let heart   = "♥";
    let diamond = "♦";
    for n in 0..8 {
        match n {
            0 => {
                let mut ace = "A".to_string();
                ace.push_str(club);
                print!("{} ", Black.bold().paint(&ace));
            },
            1 => {
                let mut ten = "10".to_string();
                ten.push_str(club);
                print!("{} ", Black.bold().paint(&ten));
            },
            2 => {
                let mut king = "K".to_string();
                king.push_str(club);
                print!("{} ", Black.bold().paint(&king));
            },
            3 => {
                let mut queen = "Q".to_string();
                queen.push_str(club);
                print!("{} ", Black.bold().paint(&queen));
            },
            4 => {
                let mut jack = "J".to_string();
                jack.push_str(club);
                print!("{} ", Black.bold().paint(&jack));
            },
            5 => {
                let mut nine = "9".to_string();
                nine.push_str(club);
                print!("{} ", Black.bold().paint(&nine));
            },
            6 => {
                let mut eight = "8".to_string();
                eight.push_str(club);
                print!("{} ", Black.bold().paint(&eight));
            },
            7 => {
                let mut seven = "7".to_string();
                seven.push_str(club);
                print!("{} ", Black.bold().paint(&seven));
            },
            _ => panic!("Unknown card"),
        }
    };
    println!("");
    for n in 8..16 {
        match n {
            8 => {
                let mut ace = "A".to_string();
                ace.push_str(spade);
                print!("{} ", Green.bold().paint(&ace));
            },
            9 => {
                let mut ten = "10".to_string();
                ten.push_str(spade);
                print!("{} ", Green.bold().paint(&ten));
            },
            10 => {
                let mut king = "K".to_string();
                king.push_str(spade);
                print!("{} ", Green.bold().paint(&king));
            },
            11 => {
                let mut queen = "Q".to_string();
                queen.push_str(spade);
                print!("{} ", Green.bold().paint(&queen));
            },
            12 => {
                let mut jack = "J".to_string();
                jack.push_str(spade);
                print!("{} ", Green.bold().paint(&jack));
            },
            13 => {
                let mut nine = "9".to_string();
                nine.push_str(spade);
                print!("{} ", Green.bold().paint(&nine));
            },
            14 => {
                let mut eight = "8".to_string();
                eight.push_str(spade);
                print!("{} ", Green.bold().paint(&eight));
            },
            15 => {
                let mut seven = "7".to_string();
                seven.push_str(spade);
                print!("{} ", Green.bold().paint(&seven));
            },
            _ => panic!("Unknown card"),
        }
    };
    println!("");
    for n in 16..24 {
        match n {
            16 => {
                let mut ace = "A".to_string();
                ace.push_str(heart);
                print!("{} ", Red.bold().paint(&ace));
            },
            17 => {
                let mut ten = "10".to_string();
                ten.push_str(heart);
                print!("{} ", Red.bold().paint(&ten));
            },
            18 => {
                let mut king = "K".to_string();
                king.push_str(heart);
                print!("{} ", Red.bold().paint(&king));
            },
            19 => {
                let mut queen = "Q".to_string();
                queen.push_str(heart);
                print!("{} ", Red.bold().paint(&queen));
            },
            20 => {
                let mut jack = "J".to_string();
                jack.push_str(heart);
                print!("{} ", Red.bold().paint(&jack));
            },
            21 => {
                let mut nine = "9".to_string();
                nine.push_str(heart);
                print!("{} ", Red.bold().paint(&nine));
            },
            22 => {
                let mut eight = "8".to_string();
                eight.push_str(heart);
                print!("{} ", Red.bold().paint(&eight));
            },
            23 => {
                let mut seven = "7".to_string();
                seven.push_str(heart);
                print!("{} ", Red.bold().paint(&seven));
            },
            _ => panic!("Unknown card"),
        }
    };
    println!("");
    for n in 24..32 {
        match n {
            24 => {
                let mut ace = "A".to_string();
                ace.push_str(diamond);
                print!("{} ", Yellow.bold().paint(&ace));
            },
            25 => {
                let mut ten = "10".to_string();
                ten.push_str(diamond);
                print!("{} ", Yellow.bold().paint(&ten));
            },
            26 => {
                let mut king = "K".to_string();
                king.push_str(diamond);
                print!("{} ", Yellow.bold().paint(&king));
            },
            27 => {
                let mut queen = "Q".to_string();
                queen.push_str(diamond);
                print!("{} ", Yellow.bold().paint(&queen));
            },
            28 => {
                let mut jack = "J".to_string();
                jack.push_str(diamond);
                print!("{} ", Yellow.bold().paint(&jack));
            },
            29 => {
                let mut nine = "9".to_string();
                nine.push_str(diamond);
                print!("{} ", Yellow.bold().paint(&nine));
            },
            30 => {
                let mut eight = "8".to_string();
                eight.push_str(diamond);
                print!("{} ", Yellow.bold().paint(&eight));
            },
            31 => {
                let mut seven = "7".to_string();
                seven.push_str(diamond);
                print!("{} ", Yellow.bold().paint(&seven));
            },
            _ => panic!("Unknown card"),
        }
    };
    println!("");
}

fn announce(player: u8) -> Game {
    Game::Suit
}

fn main() {
    // randomly select player
    let player_number: u8 = rand::thread_rng().gen_range(0, 3);
    match player_number {
        0 => println!("player A:"),
        1 => println!("player B:"),
        2 => println!("player C:"),
        _ => panic!("Unknown player {}", player_number),
    }
    loop {
        // player player_number is dealing
        deal(player_number);
        // bid
        let (player, bid) = bid(player_number);
        // announce
        let game = announce(player);
        // play 10 tricks in a row
        for trick in 0..10 {
            println!("trick #{}:", trick);
            // ask for input
            let mut input = String::new();
            io::stdin().read_line(&mut input)
                .ok()
                .expect("failed to read line");
            let input: u8 = match input.trim().parse() {
                Ok(num) => num,
                Err(_) => break,
            };
            // is input valid?
        };
        println!("New game?");
        let mut input = String::new();
        io::stdin().read_line(&mut input)
            .ok()
            .expect("failed to read line");
        let input: u8 = match input.trim().parse() {
            Ok(num) => num,
            Err(_) => break,
        };
        println!("your input: {}", input);
        if input != 1 {
            break;
        }
    }
}
<commit_msg>Sort functions alphabetically.<commit_after>extern crate ansi_term;
extern crate rand;

use ansi_term::Colour::*;
use rand::Rng;
use std::io;

enum Card {
    ClubsAce,
    ClubsTen,
    ClubsKing,
    ClubsQueen,
    ClubsJack,
    ClubsNine,
    ClubsEight,
    ClubsSeven,
    SpadesAce,
    SpadesTen,
    SpadesKing,
    SpadesQueen,
    SpadesJack,
    SpadesNine,
    SpadesEight,
    SpadesSeven,
    HeartsAce,
    HeartsTen,
    HeartsKing,
    HeartsQueen,
    HeartsJack,
    HeartsNine,
    HeartsEight,
    HeartsSeven,
    DiamondsAce,
    DiamondsTen,
    DiamondsKing,
    DiamondsQueen,
    DiamondsJack,
    DiamondsNine,
    DiamondsEight,
    DiamondsSeven,
}

enum Game {
    Suit,
    Grand,
    Null,
}

enum Player {
    A,
    B,
    C,
}

fn announce(player: u8) -> Game {
    Game::Suit
}

fn bid(dealer: u8) -> (u8, u8) {
    let winner: u8 = dealer;
    let highest: u8 = 18;
    // TODO
    (winner, highest)
}

fn deal(dealer: u8) {
    let mut cards: Vec<u8> = Vec::new();
    for n in 0..32 {
        cards.push(n);
    }
    // print clubs
    let club    = "♣";
    let spade   = "♠";
    let heart   = "♥";
    let diamond = "♦";
    for n in 0..8 {
        match n {
            0 => {
                let mut ace = "A".to_string();
                ace.push_str(club);
                print!("{} ", Black.bold().paint(&ace));
            },
            1 => {
                let mut ten = "10".to_string();
                ten.push_str(club);
                print!("{} ", Black.bold().paint(&ten));
            },
            2 => {
                let mut king = "K".to_string();
                king.push_str(club);
                print!("{} ", Black.bold().paint(&king));
            },
            3 => {
                let mut queen = "Q".to_string();
                queen.push_str(club);
                print!("{} ", Black.bold().paint(&queen));
            },
            4 => {
                let mut jack = "J".to_string();
                jack.push_str(club);
                print!("{} ", Black.bold().paint(&jack));
            },
            5 => {
                let mut nine = "9".to_string();
                nine.push_str(club);
                print!("{} ", Black.bold().paint(&nine));
            },
            6 => {
                let mut eight = "8".to_string();
                eight.push_str(club);
                print!("{} ", Black.bold().paint(&eight));
            },
            7 => {
                let mut seven = "7".to_string();
                seven.push_str(club);
                print!("{} ", Black.bold().paint(&seven));
            },
            _ => panic!("Unknown card"),
        }
    };
    println!("");
    for n in 8..16 {
        match n {
            8 => {
                let mut ace = "A".to_string();
                ace.push_str(spade);
                print!("{} ", Green.bold().paint(&ace));
            },
            9 => {
                let mut ten = "10".to_string();
                ten.push_str(spade);
                print!("{} ", Green.bold().paint(&ten));
            },
            10 => {
                let mut king = "K".to_string();
                king.push_str(spade);
                print!("{} ", Green.bold().paint(&king));
            },
            11 => {
                let mut queen = "Q".to_string();
                queen.push_str(spade);
                print!("{} ", Green.bold().paint(&queen));
            },
            12 => {
                let mut jack = "J".to_string();
                jack.push_str(spade);
                print!("{} ", Green.bold().paint(&jack));
            },
            13 => {
                let mut nine = "9".to_string();
                nine.push_str(spade);
                print!("{} ", Green.bold().paint(&nine));
            },
            14 => {
                let mut eight = "8".to_string();
                eight.push_str(spade);
                print!("{} ", Green.bold().paint(&eight));
            },
            15 => {
                let mut seven = "7".to_string();
                seven.push_str(spade);
                print!("{} ", Green.bold().paint(&seven));
            },
            _ => panic!("Unknown card"),
        }
    };
    println!("");
    for n in 16..24 {
        match n {
            16 => {
                let mut ace = "A".to_string();
                ace.push_str(heart);
                print!("{} ", Red.bold().paint(&ace));
            },
            17 => {
                let mut ten = "10".to_string();
                ten.push_str(heart);
                print!("{} ", Red.bold().paint(&ten));
            },
            18 => {
                let mut king = "K".to_string();
                king.push_str(heart);
                print!("{} ", Red.bold().paint(&king));
            },
            19 => {
                let mut queen = "Q".to_string();
                queen.push_str(heart);
                print!("{} ", Red.bold().paint(&queen));
            },
            20 => {
                let mut jack = "J".to_string();
                jack.push_str(heart);
                print!("{} ", Red.bold().paint(&jack));
            },
            21 => {
                let mut nine = "9".to_string();
                nine.push_str(heart);
                print!("{} ", Red.bold().paint(&nine));
            },
            22 => {
                let mut eight = "8".to_string();
                eight.push_str(heart);
                print!("{} ", Red.bold().paint(&eight));
            },
            23 => {
                let mut seven = "7".to_string();
                seven.push_str(heart);
                print!("{} ", Red.bold().paint(&seven));
            },
            _ => panic!("Unknown card"),
        }
    };
    println!("");
    for n in 24..32 {
        match n {
            24 => {
                let mut ace = "A".to_string();
                ace.push_str(diamond);
                print!("{} ", Yellow.bold().paint(&ace));
            },
            25 => {
                let mut ten = "10".to_string();
                ten.push_str(diamond);
                print!("{} ", Yellow.bold().paint(&ten));
            },
            26 => {
                let mut king = "K".to_string();
                king.push_str(diamond);
                print!("{} ", Yellow.bold().paint(&king));
            },
            27 => {
                let mut queen = "Q".to_string();
                queen.push_str(diamond);
                print!("{} ", Yellow.bold().paint(&queen));
            },
            28 => {
                let mut jack = "J".to_string();
                jack.push_str(diamond);
                print!("{} ", Yellow.bold().paint(&jack));
            },
            29 => {
                let mut nine = "9".to_string();
                nine.push_str(diamond);
                print!("{} ", Yellow.bold().paint(&nine));
            },
            30 => {
                let mut eight = "8".to_string();
                eight.push_str(diamond);
                print!("{} ", Yellow.bold().paint(&eight));
            },
            31 => {
                let mut seven = "7".to_string();
                seven.push_str(diamond);
                print!("{} ", Yellow.bold().paint(&seven));
            },
            _ => panic!("Unknown card"),
        }
    };
    println!("");
}

fn main() {
    // randomly select player
    let player_number: u8 = rand::thread_rng().gen_range(0, 3);
    match player_number {
        0 => println!("player A:"),
        1 => println!("player B:"),
        2 => println!("player C:"),
        _ => panic!("Unknown player {}", player_number),
    }
    loop {
        // player player_number is dealing
        deal(player_number);
        // bid
        let (player, bid) = bid(player_number);
        // announce
        let game = announce(player);
        // play 10 tricks in a row
        for trick in 0..10 {
            println!("trick #{}:", trick);
            // ask for input
            let mut input = String::new();
            io::stdin().read_line(&mut input)
                .ok()
                .expect("failed to read line");
            let input: u8 = match input.trim().parse() {
                Ok(num) => num,
                Err(_) => break,
            };
            // is input valid?
        };
        println!("New game?");
        let mut input = String::new();
        io::stdin().read_line(&mut input)
            .ok()
            .expect("failed to read line");
        let input: u8 = match input.trim().parse() {
            Ok(num) => num,
            Err(_) => break,
        };
        println!("your input: {}", input);
        if input != 1 {
            break;
        }
    }
}
<|endoftext|>


<commit_before>use std::iter::Iterator;
use std::iter::Peekable;
use itertools::Itertools;

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Token {
  LParen,
  RParen,
  Arrow,
  Dot,
  Colon,
  Equal,
  ForAll,
  Variable(String),
}

impl ToString for Token {
  fn to_string(&self) -> String {
    match *self {
      Token::LParen => "(".to_string(),
      Token::RParen => ")".to_string(),
      Token::Arrow => "->".to_string(),
      Token::Dot => ".".to_string(),
      Token::Colon => ":".to_string(),
      Token::Equal => "=".to_string(),
      Token::ForAll => "forall".to_string(),
      Token::Variable(ref name) => name.clone(),
    }
  }
}

pub struct Lexer<I>
  where I: Clone + Iterator<Item = char>
{
  iter: Peekable<I>,
}

impl<I: Clone + Iterator<Item = char>> Lexer<I> {
  fn new(iter: I) -> Lexer<I> {
    Lexer { iter: iter.peekable() }
  }
}

impl<I: Clone + Iterator<Item = char>> Iterator for Lexer<I> {
  type Item = Token;
  fn next(&mut self) -> Option<Token> {
    match *self.iter.peek().unwrap_or(&'\0') {
      '(' => {
        self.iter.next();
        Some(Token::LParen)
      }
      ')' => {
        self.iter.next();
        Some(Token::RParen)
      }
      ':' => {
        self.iter.next();
        Some(Token::Colon)
      }
      '.' => {
        self.iter.next();
        Some(Token::Dot)
      }
      '=' => {
        self.iter.next();
        Some(Token::Equal)
      }
      '-' => {
        self.iter.next();
        if self.iter.peek().unwrap_or(&'\0') == &'>' {
          self.iter.next();
          Some(Token::Arrow)
        } else {
          None
        }
      }
      'A'...'Z' | 'a'...'z' | '_' => {
        let name = self.iter
                       .take_while_ref(|&c| {
                         c.is_lowercase() || c.is_uppercase() || c == '_'
                       })
                       .collect::<String>();
        if name == "forall" {
          Some(Token::ForAll)
        } else {
          Some(Token::Variable(name))
        }
      }
      '\0' => None,
      _ => {
        self.iter.next();
        self.next()
      }
    }
  }
}

pub fn lex<I: Clone + Iterator<Item = char>>(iter: I) -> Lexer<I> {
  Lexer::new(iter)
}

#[test]
fn test_to_string() {
  assert_eq!("(", Token::LParen.to_string());
  assert_eq!(")", Token::RParen.to_string());
  assert_eq!("->", Token::Arrow.to_string());
  assert_eq!(".", Token::Dot.to_string());
  assert_eq!(":", Token::Colon.to_string());
  assert_eq!("=", Token::Equal.to_string());
  assert_eq!("a", Token::Variable("a".to_string()).to_string());
}

#[test]
fn test_lex() {
  let mut l = lex("type = id : forall (a : data) -> a -> a.".chars());
  assert_eq!(l.next(), Some(Token::Variable("type".to_string())));
  assert_eq!(l.next(), Some(Token::Equal));
  assert_eq!(l.next(), Some(Token::Variable("id".to_string())));
  assert_eq!(l.next(), Some(Token::Colon));
  assert_eq!(l.next(), Some(Token::ForAll));
  assert_eq!(l.next(), Some(Token::LParen));
  assert_eq!(l.next(), Some(Token::Variable("a".to_string())));
  assert_eq!(l.next(), Some(Token::Colon));
  assert_eq!(l.next(), Some(Token::Variable("data".to_string())));
  assert_eq!(l.next(), Some(Token::RParen));
  assert_eq!(l.next(), Some(Token::Arrow));
  assert_eq!(l.next(), Some(Token::Variable("a".to_string())));
  assert_eq!(l.next(), Some(Token::Arrow));
  assert_eq!(l.next(), Some(Token::Variable("a".to_string())));
  assert_eq!(l.next(), Some(Token::Dot));
  assert_eq!(l.next(), None);
}
<commit_msg>Rename iter to chars in lexer.<commit_after>use std::iter::Iterator;
use std::iter::Peekable;
use itertools::Itertools;

#[derive(Clone, Debug, Eq, PartialEq)]
pub enum Token {
  LParen,
  RParen,
  Arrow,
  Dot,
  Colon,
  Equal,
  ForAll,
  Variable(String),
}

impl ToString for Token {
  fn to_string(&self) -> String {
    match *self {
      Token::LParen => "(".to_string(),
      Token::RParen => ")".to_string(),
      Token::Arrow => "->".to_string(),
      Token::Dot => ".".to_string(),
      Token::Colon => ":".to_string(),
      Token::Equal => "=".to_string(),
      Token::ForAll => "forall".to_string(),
      Token::Variable(ref name) => name.clone(),
    }
  }
}

pub struct Lexer<I>
  where I: Clone + Iterator<Item = char>
{
  chars: Peekable<I>,
}

impl<I: Clone + Iterator<Item = char>> Lexer<I> {
  fn new(iter: I) -> Lexer<I> {
    Lexer { chars: iter.peekable() }
  }
}

impl<I: Clone + Iterator<Item = char>> Iterator for Lexer<I> {
  type Item = Token;
  fn next(&mut self) -> Option<Token> {
    match *self.chars.peek().unwrap_or(&'\0') {
      '(' => {
        self.chars.next();
        Some(Token::LParen)
      }
      ')' => {
        self.chars.next();
        Some(Token::RParen)
      }
      ':' => {
        self.chars.next();
        Some(Token::Colon)
      }
      '.' => {
        self.chars.next();
        Some(Token::Dot)
      }
      '=' => {
        self.chars.next();
        Some(Token::Equal)
      }
      '-' => {
        self.chars.next();
        if self.chars.peek().unwrap_or(&'\0') == &'>' {
          self.chars.next();
          Some(Token::Arrow)
        } else {
          None
        }
      }
      'A'...'Z' | 'a'...'z' | '_' => {
        let name = self.chars
                       .take_while_ref(|&c| {
                         c.is_lowercase() || c.is_uppercase() || c == '_'
                       })
                       .collect::<String>();
        if name == "forall" {
          Some(Token::ForAll)
        } else {
          Some(Token::Variable(name))
        }
      }
      '\0' => None,
      _ => {
        self.chars.next();
        self.next()
      }
    }
  }
}

pub fn lex<I: Clone + Iterator<Item = char>>(iter: I) -> Lexer<I> {
  Lexer::new(iter)
}

#[test]
fn test_to_string() {
  assert_eq!("(", Token::LParen.to_string());
  assert_eq!(")", Token::RParen.to_string());
  assert_eq!("->", Token::Arrow.to_string());
  assert_eq!(".", Token::Dot.to_string());
  assert_eq!(":", Token::Colon.to_string());
  assert_eq!("=", Token::Equal.to_string());
  assert_eq!("a", Token::Variable("a".to_string()).to_string());
}

#[test]
fn test_lex() {
  let mut l = lex("type = id : forall (a : data) -> a -> a.".chars());
  assert_eq!(l.next(), Some(Token::Variable("type".to_string())));
  assert_eq!(l.next(), Some(Token::Equal));
  assert_eq!(l.next(), Some(Token::Variable("id".to_string())));
  assert_eq!(l.next(), Some(Token::Colon));
  assert_eq!(l.next(), Some(Token::ForAll));
  assert_eq!(l.next(), Some(Token::LParen));
  assert_eq!(l.next(), Some(Token::Variable("a".to_string())));
  assert_eq!(l.next(), Some(Token::Colon));
  assert_eq!(l.next(), Some(Token::Variable("data".to_string())));
  assert_eq!(l.next(), Some(Token::RParen));
  assert_eq!(l.next(), Some(Token::Arrow));
  assert_eq!(l.next(), Some(Token::Variable("a".to_string())));
  assert_eq!(l.next(), Some(Token::Arrow));
  assert_eq!(l.next(), Some(Token::Variable("a".to_string())));
  assert_eq!(l.next(), Some(Token::Dot));
  assert_eq!(l.next(), None);
}
<|endoftext|>


<commit_before>use std::io::Read;
use std::fs::File;
use crc::{crc32, Hasher32};

pub fn verify_file_crc32(file: &Path) -> u32 {
    let file = get!(File::open(file), "An error occured while opening file. (verify_file)");
    let mut digest = crc32::Digest::new(crc32::IEEE);

    for line in file.bytes() {
        digest.write(&[line.unwrap()]);
    }

    digest.sum32()
}
<commit_msg>Missing module<commit_after>use std::err::Error;
use std::io::Read;
use std::fs::File;
use crc::{crc32, Hasher32};

pub fn verify_file_crc32(file: &Path) -> u32 {
    let file = get!(File::open(file), "An error occured while opening file. (verify_file)");
    let mut digest = crc32::Digest::new(crc32::IEEE);

    for line in file.bytes() {
        digest.write(&[line.unwrap()]);
    }

    digest.sum32()
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::fmt;

use device_tree_source::tree::{BootInfo, Node, NodeName, Property, Offset};

#[derive(Debug)]
pub enum Element<'a> {
    Node(&'a Node),
    Prop(&'a Property),
}

impl<'a> Offset for Element<'a> {
    fn get_offset(&self) -> usize {
        match *self {
            Element::Node(n) => n.get_offset(),
            Element::Prop(p) => p.get_offset(),
        }
    }
}

impl<'a> fmt::Display for Element<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Element::Node(node) => write!(f, "{}", node),
            Element::Prop(prop) => write!(f, "{}", prop),
        }
    }
}

#[derive(Debug)]
pub struct LabelStore<'a> {
    paths: HashMap<PathBuf, Vec<Element<'a>>>,
    labels: HashMap<&'a str, PathBuf>,
}

impl<'a> LabelStore<'a> {
    pub fn new() -> LabelStore<'a> {
        LabelStore {
            paths: HashMap::new(),
            labels: HashMap::new(),
        }
    }

    // TODO: somehow keep track of deleted labels so they can be searched for later
    //       while not being used for path lookup during change parsing
    pub fn fill(&mut self, boot_info: &'a BootInfo, amends: &'a [Node]) {
        self.fill_internal(Path::new("/"), &boot_info.root);
        for node in amends {
            match *node {
                Node::Existing { ref name, .. } => {
                    if name.as_str() == "/" || self.labels.contains_key(name.as_str()) {
                        self.fill_internal(Path::new(""), node);
                    } else {
                        unimplemented!();
                    }
                }
                Node::Deleted { ref name, .. } => {
                    if self.labels.contains_key(name.as_str()) {
                        self.fill_internal(Path::new(""), node);
                    } else {
                        unimplemented!();
                    }
                }
            }
        }
    }

    fn fill_internal(&mut self, path: &Path, node: &'a Node) {
        match *node {
            Node::Deleted { ref name, .. } => {
                let node_path = match *name {
                    NodeName::Full(ref name) => path.join(name),
                    NodeName::Ref(ref label) => {
                        self.path_from_label(label).unwrap().to_owned()
                    }
                };

                self.delete_labels(&node_path);

                self.paths
                    .entry(node_path.clone())
                    .or_insert_with(Vec::new)
                    .push(Element::Node(node));

                let paths: Vec<PathBuf> = self.paths
                    .iter()
                    .filter_map(|(key, val)| if key.starts_with(&node_path) {
                        match val.last() {
                            Some(&Element::Node(&Node::Existing { .. })) |
                            Some(&Element::Prop(&Property::Existing { .. })) => {
                                Some(key.to_owned())
                            }
                            _ => None,
                        }
                    } else {
                        None
                    })
                    .collect();

                for path in &paths {
                    self.delete_labels(path);
                    self.paths.get_mut(path).unwrap().push(Element::Node(node));
                }
            }
            Node::Existing { ref name, ref proplist, ref children, ref labels, .. } => {
                let node_path = match *name {
                    NodeName::Full(ref name) => path.join(name),
                    NodeName::Ref(ref label) => {
                        self.path_from_label(label).unwrap().to_owned()
                    }
                };

                self.insert_labels(&node_path, labels);

                for prop in proplist {
                    match *prop {
                        Property::Deleted { ref name, .. } => {
                            let label_path = node_path.join(name);
                            self.delete_labels(&label_path);

                            self.paths
                                .entry(label_path)
                                .or_insert_with(Vec::new)
                                .push(Element::Prop(prop));
                        }
                        Property::Existing { ref name, ref labels, .. } => {
                            let label_path = node_path.join(name);
                            self.insert_labels(&label_path, labels);

                            self.paths
                                .entry(label_path)
                                .or_insert_with(Vec::new)
                                .push(Element::Prop(prop));
                        }
                    }
                }

                for node in children {
                    self.fill_internal(&node_path, node);
                }

                self.paths
                    .entry(node_path)
                    .or_insert_with(Vec::new)
                    .push(Element::Node(node));
            }
        }
    }

    fn delete_labels(&mut self, path: &Path) {
        let mut labels: Vec<&str> = Vec::new();
        for (label, p) in &self.labels {
            if p.starts_with(path) {
                labels.push(label);
            }
        }
        for label in &labels {
            self.labels.remove(label);
        }
    }

    fn insert_labels(&mut self, path: &Path, labels: &'a [String]) {
        for label in labels {
            if !self.labels.contains_key(label.as_str()) {
                self.labels.insert(label, path.to_owned());
            } else if self.labels[label.as_str()] != path {
                // TODO: maybe just print error message and allow user to determine if they should exit
                panic!("Duplicate label \"{}\" at different paths", label);
            }
        }
    }

    pub fn changes_from_path(&self, path: &Path) -> Option<&[Element<'a>]> {
        self.paths.get(path).map(|v| v.as_slice())
    }

    pub fn path_from_label(&self, label: &str) -> Option<&Path> {
        self.labels.get(label).map(|p| p.as_path())
    }
}
<commit_msg>Fix change tracker compilation after prop/child change to Hashmap<commit_after>use std::collections::HashMap;
use std::path::{Path, PathBuf};
use std::fmt;

use device_tree_source::tree::{BootInfo, Node, NodeName, Property, Offset};

#[derive(Debug)]
pub enum Element<'a> {
    Node(&'a Node),
    Prop(&'a Property),
}

impl<'a> Offset for Element<'a> {
    fn get_offset(&self) -> usize {
        match *self {
            Element::Node(n) => n.get_offset(),
            Element::Prop(p) => p.get_offset(),
        }
    }
}

impl<'a> fmt::Display for Element<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Element::Node(node) => write!(f, "{}", node),
            Element::Prop(prop) => write!(f, "{}", prop),
        }
    }
}

#[derive(Debug)]
pub struct LabelStore<'a> {
    paths: HashMap<PathBuf, Vec<Element<'a>>>,
    labels: HashMap<&'a str, PathBuf>,
}

impl<'a> LabelStore<'a> {
    pub fn new() -> LabelStore<'a> {
        LabelStore {
            paths: HashMap::new(),
            labels: HashMap::new(),
        }
    }

    // TODO: somehow keep track of deleted labels so they can be searched for later
    //       while not being used for path lookup during change parsing
    pub fn fill(&mut self, boot_info: &'a BootInfo, amends: &'a [Node]) {
        self.fill_internal(Path::new("/"), &boot_info.root);
        for node in amends {
            match *node {
                Node::Existing { ref name, .. } => {
                    if name.as_str() == "/" || self.labels.contains_key(name.as_str()) {
                        self.fill_internal(Path::new(""), node);
                    } else {
                        unimplemented!();
                    }
                }
                Node::Deleted { ref name, .. } => {
                    if self.labels.contains_key(name.as_str()) {
                        self.fill_internal(Path::new(""), node);
                    } else {
                        unimplemented!();
                    }
                }
            }
        }
    }

    fn fill_internal(&mut self, path: &Path, node: &'a Node) {
        match *node {
            Node::Deleted { ref name, .. } => {
                let node_path = match *name {
                    NodeName::Full(ref name) => path.join(name),
                    NodeName::Ref(ref label) => {
                        self.path_from_label(label).unwrap().to_owned()
                    }
                };

                self.delete_labels(&node_path);

                self.paths
                    .entry(node_path.clone())
                    .or_insert_with(Vec::new)
                    .push(Element::Node(node));

                let paths: Vec<PathBuf> = self.paths
                    .iter()
                    .filter_map(|(key, val)| if key.starts_with(&node_path) {
                        match val.last() {
                            Some(&Element::Node(&Node::Existing { .. })) |
                            Some(&Element::Prop(&Property::Existing { .. })) => {
                                Some(key.to_owned())
                            }
                            _ => None,
                        }
                    } else {
                        None
                    })
                    .collect();

                for path in &paths {
                    self.delete_labels(path);
                    self.paths.get_mut(path).unwrap().push(Element::Node(node));
                }
            }
            Node::Existing { ref name, ref proplist, ref children, ref labels, .. } => {
                let node_path = match *name {
                    NodeName::Full(ref name) => path.join(name),
                    NodeName::Ref(ref label) => {
                        self.path_from_label(label).unwrap().to_owned()
                    }
                };

                self.insert_labels(&node_path, labels);

                for (name, prop) in proplist {
                    let label_path = node_path.join(name);

                    match *prop {
                        Property::Deleted { .. } => {
                            self.delete_labels(&label_path);

                            self.paths
                                .entry(label_path)
                                .or_insert_with(Vec::new)
                                .push(Element::Prop(prop));
                        }
                        Property::Existing { ref labels, .. } => {
                            self.insert_labels(&label_path, labels);

                            self.paths
                                .entry(label_path)
                                .or_insert_with(Vec::new)
                                .push(Element::Prop(prop));
                        }
                    }
                }

                for (_, node) in children {
                    self.fill_internal(&node_path, node);
                }

                self.paths
                    .entry(node_path)
                    .or_insert_with(Vec::new)
                    .push(Element::Node(node));
            }
        }
    }

    fn delete_labels(&mut self, path: &Path) {
        let mut labels: Vec<&str> = Vec::new();
        for (label, p) in &self.labels {
            if p.starts_with(path) {
                labels.push(label);
            }
        }
        for label in &labels {
            self.labels.remove(label);
        }
    }

    fn insert_labels(&mut self, path: &Path, labels: &'a [String]) {
        for label in labels {
            if !self.labels.contains_key(label.as_str()) {
                self.labels.insert(label, path.to_owned());
            } else if self.labels[label.as_str()] != path {
                // TODO: maybe just print error message and allow user to determine if they should exit
                panic!("Duplicate label \"{}\" at different paths", label);
            }
        }
    }

    pub fn changes_from_path(&self, path: &Path) -> Option<&[Element<'a>]> {
        self.paths.get(path).map(|v| v.as_slice())
    }

    pub fn path_from_label(&self, label: &str) -> Option<&Path> {
        self.labels.get(label).map(|p| p.as_path())
    }
}
<|endoftext|>