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

pub enum Value {
  Str(String),
  Hash(HashMap<String, Value>, Option<String>)
}

pub enum Entry {
  Entity {id: String, value: Value}
}

pub struct Parser<'a> {
  source: std::str::Chars<'a>,
  ch: Option<char>,
  pos: u16
}

impl<'a> Parser<'a> {
  pub fn new(source: &'a str) -> Parser<'a> {
    Parser {
      source: source.chars(),
      ch: None,
      pos: 0
    }
  }

  fn bump(&mut self) {
    self.ch = self.source.next();

    self.pos += 1;
  }

  fn ch_is(&self, ch: char) -> bool {
    self.ch == Some(ch)
  }

  fn parse_whitespace(&mut self) {
    while self.ch_is(' ') ||
          self.ch_is('\n') ||
          self.ch_is('\t') ||
          self.ch_is('\r') { self.bump(); }
  }

  pub fn parse(&mut self) -> Vec<Entry> {
    let mut entries: Vec<Entry> = Vec::new();

    self.parse_whitespace();

    self.bump();

    loop {
      if self.ch == None {
        break;
      }

      entries.push(self.parse_entry());
      self.parse_whitespace();
    }
    entries
  }

  fn parse_entry(&mut self) -> Entry {
    let val = self.parse_entity();

    val
  }

  fn parse_entity(&mut self) -> Entry {
    let id = self.parse_identifier();
    self.parse_whitespace();

    if !self.ch_is('=') {
      panic!();
    }
    self.bump();

    self.parse_whitespace();

    let value = self.parse_pattern();

    Entry::Entity{id: id, value:value}
  }

  fn parse_identifier(&mut self) -> String {
    let mut id = String::new();

    loop {
      let ch = match self.ch {
        Some(c) => c,
        None => break,
      };

      match ch {
        'a'...'z' | 'A'...'Z' | '0'...'9' | '_' => id.push(ch),
        _ => break,
      }
      self.bump();
    }

    id
  }

  fn parse_pattern(&mut self) -> Value {
    let mut s = String::new();

    loop {
      self.bump();
      match self.ch {
        Some(c) if c == '\n' => { self.bump(); break },
        Some(c) => s.push(c),
        None => { break }
      }
    }
    Value::Str(s)
  }
}
<commit_msg>Build a Pattern<commit_after>pub enum Expression {
  IdentifierExpression {name: String}
}

pub enum PatternElement {
  TextElement {value: String},
  Placeable {expressions: Vec<Expression>}
}

pub enum Value {
  Pattern {source: String, elements: Vec<PatternElement>}
}

pub enum Entry {
  Entity {id: String, value: Value}
}

pub struct Parser<'a> {
  source: std::str::Chars<'a>,
  ch: Option<char>,
  pos: u16
}

impl<'a> Parser<'a> {
  pub fn new(source: &'a str) -> Parser<'a> {
    Parser {
      source: source.chars(),
      ch: None,
      pos: 0
    }
  }

  fn bump(&mut self) {
    self.ch = self.source.next();

    self.pos += 1;
  }

  fn ch_is(&self, ch: char) -> bool {
    self.ch == Some(ch)
  }

  fn parse_whitespace(&mut self) {
    while self.ch_is(' ') ||
          self.ch_is('\n') ||
          self.ch_is('\t') ||
          self.ch_is('\r') { self.bump(); }
  }

  pub fn parse(&mut self) -> Vec<Entry> {
    let mut entries: Vec<Entry> = Vec::new();

    self.parse_whitespace();

    self.bump();

    loop {
      if self.ch == None {
        break;
      }

      entries.push(self.parse_entry());
      self.parse_whitespace();
    }
    entries
  }

  fn parse_entry(&mut self) -> Entry {
    let val = self.parse_entity();

    val
  }

  fn parse_entity(&mut self) -> Entry {
    let id = self.parse_identifier();
    self.parse_whitespace();

    if !self.ch_is('=') {
      panic!();
    }
    self.bump();

    self.parse_whitespace();

    let value = self.parse_pattern();

    Entry::Entity{id: id, value:value}
  }

  fn parse_identifier(&mut self) -> String {
    let mut id = String::new();

    loop {
      let ch = match self.ch {
        Some(c) => c,
        None => break,
      };

      match ch {
        'a'...'z' | 'A'...'Z' | '0'...'9' | '_' => id.push(ch),
        _ => break,
      }
      self.bump();
    }

    id
  }

  fn parse_pattern(&mut self) -> Value {
    let mut s = String::new();
    let mut elements = vec![];

    loop {
      self.bump();
      match self.ch {
        Some(c) if c == '\n' => { self.bump(); break },
        Some(c) => s.push(c),
        None => { break }
      }
    }

    elements.push(PatternElement::TextElement {value: s.clone()});

    Value::Pattern{source: s, elements: elements}
  }
}
<|endoftext|>


<commit_before>// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![unstable(feature = "heap_api",
            reason = "the precise API and guarantees it provides may be tweaked \
                      slightly, especially to possibly take into account the \
                      types being stored to make room for a future \
                      tracing garbage collector",
            issue = "27700")]

use core::{isize, usize};
use core::intrinsics::{min_align_of_val, size_of_val};

#[allow(improper_ctypes)]
extern "C" {
    #[allocator]
    fn __rust_allocate(size: usize, align: usize) -> *mut u8;
    fn __rust_allocate_zeroed(size: usize, align: usize) -> *mut u8;
    fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize);
    fn __rust_reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8;
    fn __rust_reallocate_inplace(ptr: *mut u8,
                                 old_size: usize,
                                 size: usize,
                                 align: usize)
                                 -> usize;
    fn __rust_usable_size(size: usize, align: usize) -> usize;
}

#[inline(always)]
fn check_size_and_alignment(size: usize, align: usize) {
    debug_assert!(size != 0);
    debug_assert!(size <= isize::MAX as usize,
                  "Tried to allocate too much: {} bytes",
                  size);
    debug_assert!(usize::is_power_of_two(align),
                  "Invalid alignment of allocation: {}",
                  align);
}

// FIXME: #13996: mark the `allocate` and `reallocate` return value as `noalias`

/// Return a pointer to `size` bytes of memory aligned to `align`.
///
/// On failure, return a null pointer.
///
/// Behavior is undefined if the requested size is 0 or the alignment is not a
/// power of 2. The alignment must be no larger than the largest supported page
/// size on the platform.
#[inline]
pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 {
    check_size_and_alignment(size, align);
    __rust_allocate(size, align)
}

/// Return a pointer to `size` bytes of memory aligned to `align` and
/// initialized to zeroes.
///
/// On failure, return a null pointer.
///
/// Behavior is undefined if the requested size is 0 or the alignment is not a
/// power of 2. The alignment must be no larger than the largest supported page
/// size on the platform.
#[inline]
pub unsafe fn allocate_zeroed(size: usize, align: usize) -> *mut u8 {
    check_size_and_alignment(size, align);
    __rust_allocate_zeroed(size, align)
}

/// Resize the allocation referenced by `ptr` to `size` bytes.
///
/// On failure, return a null pointer and leave the original allocation intact.
///
/// If the allocation was relocated, the memory at the passed-in pointer is
/// undefined after the call.
///
/// Behavior is undefined if the requested size is 0 or the alignment is not a
/// power of 2. The alignment must be no larger than the largest supported page
/// size on the platform.
///
/// The `old_size` and `align` parameters are the parameters that were used to
/// create the allocation referenced by `ptr`. The `old_size` parameter may be
/// any value in range_inclusive(requested_size, usable_size).
#[inline]
pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8 {
    check_size_and_alignment(size, align);
    __rust_reallocate(ptr, old_size, size, align)
}

/// Resize the allocation referenced by `ptr` to `size` bytes.
///
/// If the operation succeeds, it returns `usable_size(size, align)` and if it
/// fails (or is a no-op) it returns `usable_size(old_size, align)`.
///
/// Behavior is undefined if the requested size is 0 or the alignment is not a
/// power of 2. The alignment must be no larger than the largest supported page
/// size on the platform.
///
/// The `old_size` and `align` parameters are the parameters that were used to
/// create the allocation referenced by `ptr`. The `old_size` parameter may be
/// any value in range_inclusive(requested_size, usable_size).
#[inline]
pub unsafe fn reallocate_inplace(ptr: *mut u8,
                                 old_size: usize,
                                 size: usize,
                                 align: usize)
                                 -> usize {
    check_size_and_alignment(size, align);
    __rust_reallocate_inplace(ptr, old_size, size, align)
}

/// Deallocates the memory referenced by `ptr`.
///
/// The `ptr` parameter must not be null.
///
/// The `old_size` and `align` parameters are the parameters that were used to
/// create the allocation referenced by `ptr`. The `old_size` parameter may be
/// any value in range_inclusive(requested_size, usable_size).
#[inline]
pub unsafe fn deallocate(ptr: *mut u8, old_size: usize, align: usize) {
    __rust_deallocate(ptr, old_size, align)
}

/// Returns the usable size of an allocation created with the specified the
/// `size` and `align`.
#[inline]
pub fn usable_size(size: usize, align: usize) -> usize {
    unsafe { __rust_usable_size(size, align) }
}

/// An arbitrary non-null address to represent zero-size allocations.
///
/// This preserves the non-null invariant for types like `Box<T>`. The address
/// may overlap with non-zero-size memory allocations.
#[rustc_deprecated(since = "1.19", reason = "Use Unique/Shared::empty() instead")]
#[unstable(feature = "heap_api", issue = "27700")]
pub const EMPTY: *mut () = 1 as *mut ();

/// The allocator for unique pointers.
// This function must not unwind. If it does, MIR trans will fail.
#[cfg(not(test))]
#[lang = "exchange_malloc"]
#[inline]
unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
    if size == 0 {
        align as *mut u8
    } else {
        let ptr = allocate(size, align);
        if ptr.is_null() {
            ::oom()
        }
        ptr
    }
}

#[cfg_attr(not(test), lang = "box_free")]
#[inline]
pub(crate) unsafe fn box_free<T: ?Sized>(ptr: *mut T) {
    let size = size_of_val(&*ptr);
    let align = min_align_of_val(&*ptr);
    // We do not allocate for Box<T> when T is ZST, so deallocation is also not necessary.
    if size != 0 {
        deallocate(ptr as *mut u8, size, align);
    }
}

#[cfg(test)]
mod tests {
    extern crate test;
    use self::test::Bencher;
    use boxed::Box;
    use heap;

    #[test]
    fn allocate_zeroed() {
        unsafe {
            let size = 1024;
            let ptr = heap::allocate_zeroed(size, 1);
            if ptr.is_null() {
                ::oom()
            }

            let end = ptr.offset(size as isize);
            let mut i = ptr;
            while i < end {
                assert_eq!(*i, 0);
                i = i.offset(1);
            }
            heap::deallocate(ptr, size, 1);
        }
    }

    #[test]
    fn basic_reallocate_inplace_noop() {
        unsafe {
            let size = 4000;
            let ptr = heap::allocate(size, 8);
            if ptr.is_null() {
                ::oom()
            }
            let ret = heap::reallocate_inplace(ptr, size, size, 8);
            heap::deallocate(ptr, size, 8);
            assert_eq!(ret, heap::usable_size(size, 8));
        }
    }

    #[bench]
    fn alloc_owned_small(b: &mut Bencher) {
        b.iter(|| {
            let _: Box<_> = box 10;
        })
    }
}
<commit_msg>Add impl of `Alloc` for the global rust heap.<commit_after>// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![unstable(feature = "heap_api",
            reason = "the precise API and guarantees it provides may be tweaked \
                      slightly, especially to possibly take into account the \
                      types being stored to make room for a future \
                      tracing garbage collector",
            issue = "27700")]

use allocator::{Alloc, AllocErr, CannotReallocInPlace, Layout};
use core::{isize, usize, cmp, ptr};
use core::intrinsics::{min_align_of_val, size_of_val};

#[allow(improper_ctypes)]
extern "C" {
    #[allocator]
    fn __rust_allocate(size: usize, align: usize) -> *mut u8;
    fn __rust_allocate_zeroed(size: usize, align: usize) -> *mut u8;
    fn __rust_deallocate(ptr: *mut u8, old_size: usize, align: usize);
    fn __rust_reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8;
    fn __rust_reallocate_inplace(ptr: *mut u8,
                                 old_size: usize,
                                 size: usize,
                                 align: usize)
                                 -> usize;
    fn __rust_usable_size(size: usize, align: usize) -> usize;
}

#[inline(always)]
fn check_size_and_alignment(size: usize, align: usize) {
    debug_assert!(size != 0);
    debug_assert!(size <= isize::MAX as usize,
                  "Tried to allocate too much: {} bytes",
                  size);
    debug_assert!(usize::is_power_of_two(align),
                  "Invalid alignment of allocation: {}",
                  align);
}

#[derive(Copy, Clone, Default, Debug)]
pub struct HeapAlloc;

unsafe impl Alloc for HeapAlloc {
    unsafe fn alloc(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
        let addr = allocate(layout.size(), layout.align());
        if addr.is_null() {
            Err(AllocErr::Exhausted { request: layout })
        } else {
            Ok(addr)
        }
    }

    unsafe fn alloc_zeroed(&mut self, layout: Layout) -> Result<*mut u8, AllocErr> {
        let addr = allocate_zeroed(layout.size(), layout.align());
        if addr.is_null() {
            Err(AllocErr::Exhausted { request: layout })
        } else {
            Ok(addr)
        }
    }

    unsafe fn dealloc(&mut self, ptr: *mut u8, layout: Layout) {
        deallocate(ptr, layout.size(), layout.align());
    }

    fn usable_size(&self, layout: &Layout) -> (usize, usize) {
        (layout.size(), usable_size(layout.size(), layout.align()))
    }

    unsafe fn realloc(&mut self,
                      ptr: *mut u8,
                      layout: Layout,
                      new_layout: Layout)
                      -> Result<*mut u8, AllocErr>
    {
        let old_size = layout.size();
        let new_size = new_layout.size();
        if layout.align() == new_layout.align() {
            let new_ptr = reallocate(ptr, old_size, new_size, layout.align());
            if new_ptr.is_null() {
                // We assume `reallocate` already tried alloc + copy +
                // dealloc fallback; thus pointless to repeat effort
                Err(AllocErr::Exhausted { request: new_layout })
            } else {
                Ok(new_ptr)
            }
        } else {
            // if alignments don't match, fall back on alloc + copy + dealloc
            let result = self.alloc(new_layout);
            if let Ok(new_ptr) = result {
                ptr::copy_nonoverlapping(ptr as *const u8, new_ptr, cmp::min(old_size, new_size));
                self.dealloc(ptr, layout);
            }
            result
        }
    }

    unsafe fn grow_in_place(&mut self,
                            ptr: *mut u8,
                            layout: Layout,
                            new_layout: Layout)
                            -> Result<(), CannotReallocInPlace>
    {
        // grow_in_place spec requires this, and the spec for reallocate_inplace
        // makes it hard to detect failure if it does not hold.
        debug_assert!(new_layout.size() >= layout.size());

        if layout.align() != new_layout.align() { // reallocate_inplace requires this.
            return Err(CannotReallocInPlace);
        }
        let usable = reallocate_inplace(ptr, layout.size(), new_layout.size(), layout.align());
        if usable >= new_layout.size() { Ok(()) } else { Err(CannotReallocInPlace) }
    }
}

// FIXME: #13996: mark the `allocate` and `reallocate` return value as `noalias`

/// Return a pointer to `size` bytes of memory aligned to `align`.
///
/// On failure, return a null pointer.
///
/// Behavior is undefined if the requested size is 0 or the alignment is not a
/// power of 2. The alignment must be no larger than the largest supported page
/// size on the platform.
#[inline]
pub unsafe fn allocate(size: usize, align: usize) -> *mut u8 {
    check_size_and_alignment(size, align);
    __rust_allocate(size, align)
}

/// Return a pointer to `size` bytes of memory aligned to `align` and
/// initialized to zeroes.
///
/// On failure, return a null pointer.
///
/// Behavior is undefined if the requested size is 0 or the alignment is not a
/// power of 2. The alignment must be no larger than the largest supported page
/// size on the platform.
#[inline]
pub unsafe fn allocate_zeroed(size: usize, align: usize) -> *mut u8 {
    check_size_and_alignment(size, align);
    __rust_allocate_zeroed(size, align)
}

/// Resize the allocation referenced by `ptr` to `size` bytes.
///
/// On failure, return a null pointer and leave the original allocation intact.
///
/// If the allocation was relocated, the memory at the passed-in pointer is
/// undefined after the call.
///
/// Behavior is undefined if the requested size is 0 or the alignment is not a
/// power of 2. The alignment must be no larger than the largest supported page
/// size on the platform.
///
/// The `old_size` and `align` parameters are the parameters that were used to
/// create the allocation referenced by `ptr`. The `old_size` parameter may be
/// any value in range_inclusive(requested_size, usable_size).
#[inline]
pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usize) -> *mut u8 {
    check_size_and_alignment(size, align);
    __rust_reallocate(ptr, old_size, size, align)
}

/// Resize the allocation referenced by `ptr` to `size` bytes.
///
/// If the operation succeeds, it returns `usable_size(size, align)` and if it
/// fails (or is a no-op) it returns `usable_size(old_size, align)`.
///
/// Behavior is undefined if the requested size is 0 or the alignment is not a
/// power of 2. The alignment must be no larger than the largest supported page
/// size on the platform.
///
/// The `old_size` and `align` parameters are the parameters that were used to
/// create the allocation referenced by `ptr`. The `old_size` parameter may be
/// any value in range_inclusive(requested_size, usable_size).
#[inline]
pub unsafe fn reallocate_inplace(ptr: *mut u8,
                                 old_size: usize,
                                 size: usize,
                                 align: usize)
                                 -> usize {
    check_size_and_alignment(size, align);
    __rust_reallocate_inplace(ptr, old_size, size, align)
}

/// Deallocates the memory referenced by `ptr`.
///
/// The `ptr` parameter must not be null.
///
/// The `old_size` and `align` parameters are the parameters that were used to
/// create the allocation referenced by `ptr`. The `old_size` parameter may be
/// any value in range_inclusive(requested_size, usable_size).
#[inline]
pub unsafe fn deallocate(ptr: *mut u8, old_size: usize, align: usize) {
    __rust_deallocate(ptr, old_size, align)
}

/// Returns the usable size of an allocation created with the specified the
/// `size` and `align`.
#[inline]
pub fn usable_size(size: usize, align: usize) -> usize {
    unsafe { __rust_usable_size(size, align) }
}

/// An arbitrary non-null address to represent zero-size allocations.
///
/// This preserves the non-null invariant for types like `Box<T>`. The address
/// may overlap with non-zero-size memory allocations.
#[rustc_deprecated(since = "1.19", reason = "Use Unique/Shared::empty() instead")]
#[unstable(feature = "heap_api", issue = "27700")]
pub const EMPTY: *mut () = 1 as *mut ();

/// The allocator for unique pointers.
// This function must not unwind. If it does, MIR trans will fail.
#[cfg(not(test))]
#[lang = "exchange_malloc"]
#[inline]
unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
    if size == 0 {
        align as *mut u8
    } else {
        let ptr = allocate(size, align);
        if ptr.is_null() {
            ::oom()
        }
        ptr
    }
}

#[cfg_attr(not(test), lang = "box_free")]
#[inline]
pub(crate) unsafe fn box_free<T: ?Sized>(ptr: *mut T) {
    let size = size_of_val(&*ptr);
    let align = min_align_of_val(&*ptr);
    // We do not allocate for Box<T> when T is ZST, so deallocation is also not necessary.
    if size != 0 {
        deallocate(ptr as *mut u8, size, align);
    }
}

#[cfg(test)]
mod tests {
    extern crate test;
    use self::test::Bencher;
    use boxed::Box;
    use heap;

    #[test]
    fn allocate_zeroed() {
        unsafe {
            let size = 1024;
            let ptr = heap::allocate_zeroed(size, 1);
            if ptr.is_null() {
                ::oom()
            }

            let end = ptr.offset(size as isize);
            let mut i = ptr;
            while i < end {
                assert_eq!(*i, 0);
                i = i.offset(1);
            }
            heap::deallocate(ptr, size, 1);
        }
    }

    #[test]
    fn basic_reallocate_inplace_noop() {
        unsafe {
            let size = 4000;
            let ptr = heap::allocate(size, 8);
            if ptr.is_null() {
                ::oom()
            }
            let ret = heap::reallocate_inplace(ptr, size, size, 8);
            heap::deallocate(ptr, size, 8);
            assert_eq!(ret, heap::usable_size(size, 8));
        }
    }

    #[bench]
    fn alloc_owned_small(b: &mut Bencher) {
        b.iter(|| {
            let _: Box<_> = box 10;
        })
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Traits for working with Errors.
//!
//! # The `Error` trait
//!
//! `Error` is a trait representing the basic expectations for error values,
//! i.e. values of type `E` in `Result<T, E>`. At a minimum, errors must provide
//! a description, but they may optionally provide additional detail (via
//! `Display`) and cause chain information:
//!
//! ```
//! use std::fmt::Display;
//!
//! trait Error: Display {
//!     fn description(&self) -> &str;
//!
//!     fn cause(&self) -> Option<&Error> { None }
//! }
//! ```
//!
//! The `cause` method is generally used when errors cross "abstraction
//! boundaries", i.e.  when a one module must report an error that is "caused"
//! by an error from a lower-level module. This setup makes it possible for the
//! high-level module to provide its own errors that do not commit to any
//! particular implementation, but also reveal some of its implementation for
//! debugging via `cause` chains.
//!
//! # The `FromError` trait
//!
//! `FromError` is a simple trait that expresses conversions between different
//! error types. To provide maximum flexibility, it does not require either of
//! the types to actually implement the `Error` trait, although this will be the
//! common case.
//!
//! The main use of this trait is in the `try!` macro, which uses it to
//! automatically convert a given error to the error specified in a function's
//! return type.
//!
//! For example,
//!
//! ```
//! # #![feature(os, old_io, old_path)]
//! use std::error::FromError;
//! use std::old_io::{File, IoError};
//! use std::os::{MemoryMap, MapError};
//! use std::old_path::Path;
//!
//! enum MyError {
//!     Io(IoError),
//!     Map(MapError)
//! }
//!
//! impl FromError<IoError> for MyError {
//!     fn from_error(err: IoError) -> MyError {
//!         MyError::Io(err)
//!     }
//! }
//!
//! impl FromError<MapError> for MyError {
//!     fn from_error(err: MapError) -> MyError {
//!         MyError::Map(err)
//!     }
//! }
//!
//! #[allow(unused_variables)]
//! fn open_and_map() -> Result<(), MyError> {
//!     let f = try!(File::open(&Path::new("foo.txt")));
//!     let m = try!(MemoryMap::new(0, &[]));
//!     // do something interesting here...
//!     Ok(())
//! }
//! ```

#![stable(feature = "rust1", since = "1.0.0")]

use prelude::*;
use fmt::{Debug, Display};

/// Base functionality for all errors in Rust.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Error: Debug + Display + Send {
    /// A short description of the error.
    ///
    /// The description should not contain newlines or sentence-ending
    /// punctuation, to facilitate embedding in larger user-facing
    /// strings.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn description(&self) -> &str;

    /// The lower-level cause of this error, if any.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn cause(&self) -> Option<&Error> { None }
}

/// A trait for types that can be converted from a given error type `E`.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait FromError<E> {
    /// Perform the conversion.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn from_error(err: E) -> Self;
}

// Any type is convertable from itself
#[stable(feature = "rust1", since = "1.0.0")]
impl<E> FromError<E> for E {
    fn from_error(err: E) -> E {
        err
    }
}
<commit_msg>Make `std::error::Error` not inherit from Send<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Traits for working with Errors.
//!
//! # The `Error` trait
//!
//! `Error` is a trait representing the basic expectations for error values,
//! i.e. values of type `E` in `Result<T, E>`. At a minimum, errors must provide
//! a description, but they may optionally provide additional detail (via
//! `Display`) and cause chain information:
//!
//! ```
//! use std::fmt::Display;
//!
//! trait Error: Display {
//!     fn description(&self) -> &str;
//!
//!     fn cause(&self) -> Option<&Error> { None }
//! }
//! ```
//!
//! The `cause` method is generally used when errors cross "abstraction
//! boundaries", i.e.  when a one module must report an error that is "caused"
//! by an error from a lower-level module. This setup makes it possible for the
//! high-level module to provide its own errors that do not commit to any
//! particular implementation, but also reveal some of its implementation for
//! debugging via `cause` chains.
//!
//! # The `FromError` trait
//!
//! `FromError` is a simple trait that expresses conversions between different
//! error types. To provide maximum flexibility, it does not require either of
//! the types to actually implement the `Error` trait, although this will be the
//! common case.
//!
//! The main use of this trait is in the `try!` macro, which uses it to
//! automatically convert a given error to the error specified in a function's
//! return type.
//!
//! For example,
//!
//! ```
//! # #![feature(os, old_io, old_path)]
//! use std::error::FromError;
//! use std::old_io::{File, IoError};
//! use std::os::{MemoryMap, MapError};
//! use std::old_path::Path;
//!
//! enum MyError {
//!     Io(IoError),
//!     Map(MapError)
//! }
//!
//! impl FromError<IoError> for MyError {
//!     fn from_error(err: IoError) -> MyError {
//!         MyError::Io(err)
//!     }
//! }
//!
//! impl FromError<MapError> for MyError {
//!     fn from_error(err: MapError) -> MyError {
//!         MyError::Map(err)
//!     }
//! }
//!
//! #[allow(unused_variables)]
//! fn open_and_map() -> Result<(), MyError> {
//!     let f = try!(File::open(&Path::new("foo.txt")));
//!     let m = try!(MemoryMap::new(0, &[]));
//!     // do something interesting here...
//!     Ok(())
//! }
//! ```

#![stable(feature = "rust1", since = "1.0.0")]

use prelude::*;
use fmt::{Debug, Display};

/// Base functionality for all errors in Rust.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Error: Debug + Display {
    /// A short description of the error.
    ///
    /// The description should not contain newlines or sentence-ending
    /// punctuation, to facilitate embedding in larger user-facing
    /// strings.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn description(&self) -> &str;

    /// The lower-level cause of this error, if any.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn cause(&self) -> Option<&Error> { None }
}

/// A trait for types that can be converted from a given error type `E`.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait FromError<E> {
    /// Perform the conversion.
    #[stable(feature = "rust1", since = "1.0.0")]
    fn from_error(err: E) -> Self;
}

// Any type is convertable from itself
#[stable(feature = "rust1", since = "1.0.0")]
impl<E> FromError<E> for E {
    fn from_error(err: E) -> E {
        err
    }
}
<|endoftext|>


<commit_before>extern crate iron;
extern crate iron_sessionstorage;
extern crate urlencoded;

use session::Player;
use self::iron_sessionstorage::traits::*;
use self::iron::{Request, IronResult, Response, status};
use self::iron::prelude::*;
use std::path::PathBuf;
use super::dao::*;
use self::urlencoded::{UrlEncodedBody, UrlDecodingError};
use std::boxed::Box;

pub fn start(req: &mut Request) -> IronResult<PathBuf> {
    let player = req.session().get::<Player>()?;
    match player {
        Some(_) => Ok(PathBuf::from("quiz/quiz_question")),
        None => Ok(PathBuf::from("quiz/quiz_start")),
    }
}

pub fn start_post(req: &mut Request) -> IronResult<PathBuf> {
    let player = req.session().get::<Player>()?;
    if player.is_none() {
        req.session().set(Player { id: 0 })?;
    }
    Ok(PathBuf::from("quiz/quiz_question"))
}

pub fn admin_post(req: &mut Request) -> IronResult<PathBuf> {
    let category = {
        let formdata = req.get_ref::<UrlEncodedBody>().map_err(|err| IronError{ error: Box::new(err), response: Response::with(status::BadRequest) })?;
        let categories = formdata.get("category").ok_or(IronError{ error: (Box::new(UrlDecodingError::EmptyQuery)), response: Response::with(status::BadRequest) })?;
        categories[0].to_owned()
    };
    let dao = Dao::new();
    dao.create_category(&category).map_err(|err| IronError{ error: Box::new(err), response: Response::with(status::BadRequest) })?;
    Ok(PathBuf::from("quiz/admin"))
}<commit_msg>Run rustfmt<commit_after>extern crate iron;
extern crate iron_sessionstorage;
extern crate urlencoded;

use session::Player;
use self::iron_sessionstorage::traits::*;
use self::iron::{Request, IronResult, Response, status};
use self::iron::prelude::*;
use std::path::PathBuf;
use super::dao::*;
use self::urlencoded::{UrlEncodedBody, UrlDecodingError};
use std::boxed::Box;

pub fn start(req: &mut Request) -> IronResult<PathBuf> {
    let player = req.session().get::<Player>()?;
    match player {
        Some(_) => Ok(PathBuf::from("quiz/quiz_question")),
        None => Ok(PathBuf::from("quiz/quiz_start")),
    }
}

pub fn start_post(req: &mut Request) -> IronResult<PathBuf> {
    let player = req.session().get::<Player>()?;
    if player.is_none() {
        req.session().set(Player { id: 0 })?;
    }
    Ok(PathBuf::from("quiz/quiz_question"))
}

pub fn admin_post(req: &mut Request) -> IronResult<PathBuf> {
    let category = {
        let formdata = req.get_ref::<UrlEncodedBody>()
            .map_err(|err| {
                         IronError {
                             error: Box::new(err),
                             response: Response::with(status::BadRequest),
                         }
                     })?;
        let categories = formdata.get("category")
            .ok_or(IronError {
                       error: (Box::new(UrlDecodingError::EmptyQuery)),
                       response: Response::with(status::BadRequest),
                   })?;
        categories[0].to_owned()
    };
    let dao = Dao::new();
    dao.create_category(&category)
        .map_err(|err| {
                     IronError {
                         error: Box::new(err),
                         response: Response::with(status::BadRequest),
                     }
                 })?;
    Ok(PathBuf::from("quiz/admin"))
}
<|endoftext|>


<commit_before>//! Transformation of real data.

use number::{Complex, c64};

macro_rules! reinterpret(
    ($data:ident) => (unsafe {
        use std::slice::from_raw_parts_mut;
        let n = power_of_two!($data);
        (from_raw_parts_mut($data.as_mut_ptr() as *mut _, n / 2), n / 2)
    });
);

/// Perform the forward transform.
///
/// The number of points should be a power of two. The data are replaced by the
/// positive frequency half of their complex Fourier transform. The real-valued
/// first and last components of the complex transform are returned as elements
/// `data[0]` and `data[1]`, respectively.
///
/// ## References
///
/// 1. William H. Press, Saul A. Teukolsky, William T. Vetterling, Brian P.
///    Flannery, “Numerical Recipes 3rd Edition: The Art of Scientific
///    Computing,” Cambridge University Press, 2007.
pub fn forward(data: &mut [f64]) {
    let (data, n) = reinterpret!(data);
    ::complex::forward(data);
    compose(data, n, false);
}

/// Perform the backward transform.
///
/// The number of points should be a power of two. The data should be packed as
/// described in `real::forward`.
pub fn backward(data: &mut [f64]) {
    let (data, n) = reinterpret!(data);
    compose(data, n, true);
    ::complex::backward(data);
}

/// Perform the inverse transform.
///
/// The number of points should be a power of two. The data should be packed as
/// described in `real::forward`.
pub fn inverse(data: &mut [f64]) {
    let (data, n) = reinterpret!(data);
    compose(data, n, true);
    ::complex::inverse(data);
}

/// Unpack a compressed representation produced by `real::forward`.
pub fn unpack(data: &[f64]) -> Vec<c64> {
    let n = power_of_two!(data);

    let mut cdata = Vec::with_capacity(n);
    unsafe { cdata.set_len(n) };

    cdata[0] = c64(data[0], 0.0);
    for i in 1..(n / 2) {
        cdata[i] = c64(data[2 * i], data[2 * i + 1]);
    }
    cdata[n / 2] = c64(data[1], 0.0);
    for i in (n / 2 + 1)..n {
        cdata[i] = cdata[n - i].conj();
    }

    cdata
}

fn compose(data: &mut [c64], n: usize, inverse: bool) {
    data[0] = c64(data[0].re() + data[0].im(), data[0].re() - data[0].im());
    if inverse {
        data[0] = data[0] * 0.5;
    }

    let sign = if inverse { 1.0 } else { -1.0 };
    let (multiplier, mut factor) = {
        use std::f64::consts::PI;
        let theta = sign * PI / n as f64;
        let sine = (0.5 * theta).sin();
        (c64(-2.0 * sine * sine, theta.sin()), c64(1.0, 0.0))
    };
    for i in 1..(n / 2) {
        let j = n - i;
        factor = multiplier * factor + factor;
        let part1 = (data[i] + data[j].conj()) * 0.5;
        let part2 = (data[i] - data[j].conj()) * 0.5;
        let product = c64(0.0, sign) * factor * part2;
        data[i] = part1 + product;
        data[j] = (part1 - product).conj();
    }

    data[n / 2] = data[n / 2].conj();
}

#[cfg(test)]
mod tests {
    use number::c64;

    #[test]
    fn unpack() {
        let data = (0..4).map(|i| (i + 1) as f64).collect::<Vec<_>>();
        assert_eq!(super::unpack(&data), vec![
            c64(1.0, 0.0), c64(3.0, 4.0), c64(2.0, 0.0), c64(3.0, -4.0),
        ]);

        let data = (0..8).map(|i| (i + 1) as f64).collect::<Vec<_>>();
        assert_eq!(super::unpack(&data), vec![
            c64(1.0, 0.0), c64(3.0, 4.0), c64(5.0, 6.0), c64(7.0, 8.0),
            c64(2.0, 0.0), c64(7.0, -8.0), c64(5.0, -6.0), c64(3.0, -4.0),
        ]);
    }
}
<commit_msg>Temporarily expose the compse function for testing<commit_after>//! Transformation of real data.

use number::{Complex, c64};

macro_rules! reinterpret(
    ($data:ident) => (unsafe {
        use std::slice::from_raw_parts_mut;
        let n = power_of_two!($data);
        (from_raw_parts_mut($data.as_mut_ptr() as *mut _, n / 2), n / 2)
    });
);

/// Perform the forward transform.
///
/// The number of points should be a power of two. The data are replaced by the
/// positive frequency half of their complex Fourier transform. The real-valued
/// first and last components of the complex transform are returned as elements
/// `data[0]` and `data[1]`, respectively.
///
/// ## References
///
/// 1. William H. Press, Saul A. Teukolsky, William T. Vetterling, Brian P.
///    Flannery, “Numerical Recipes 3rd Edition: The Art of Scientific
///    Computing,” Cambridge University Press, 2007.
pub fn forward(data: &mut [f64]) {
    let (data, n) = reinterpret!(data);
    ::complex::forward(data);
    compose(data, n, false);
}

/// Perform the backward transform.
///
/// The number of points should be a power of two. The data should be packed as
/// described in `real::forward`.
pub fn backward(data: &mut [f64]) {
    let (data, n) = reinterpret!(data);
    compose(data, n, true);
    ::complex::backward(data);
}

/// Perform the inverse transform.
///
/// The number of points should be a power of two. The data should be packed as
/// described in `real::forward`.
pub fn inverse(data: &mut [f64]) {
    let (data, n) = reinterpret!(data);
    compose(data, n, true);
    ::complex::inverse(data);
}

/// Unpack a compressed representation produced by `real::forward`.
pub fn unpack(data: &[f64]) -> Vec<c64> {
    let n = power_of_two!(data);

    let mut cdata = Vec::with_capacity(n);
    unsafe { cdata.set_len(n) };

    cdata[0] = c64(data[0], 0.0);
    for i in 1..(n / 2) {
        cdata[i] = c64(data[2 * i], data[2 * i + 1]);
    }
    cdata[n / 2] = c64(data[1], 0.0);
    for i in (n / 2 + 1)..n {
        cdata[i] = cdata[n - i].conj();
    }

    cdata
}

pub fn compose(data: &mut [c64], n: usize, inverse: bool) {
    data[0] = c64(data[0].re() + data[0].im(), data[0].re() - data[0].im());
    if inverse {
        data[0] = data[0] * 0.5;
    }

    let sign = if inverse { 1.0 } else { -1.0 };
    let (multiplier, mut factor) = {
        use std::f64::consts::PI;
        let theta = sign * PI / n as f64;
        let sine = (0.5 * theta).sin();
        (c64(-2.0 * sine * sine, theta.sin()), c64(1.0, 0.0))
    };
    for i in 1..(n / 2) {
        let j = n - i;
        factor = multiplier * factor + factor;
        let part1 = (data[i] + data[j].conj()) * 0.5;
        let part2 = (data[i] - data[j].conj()) * 0.5;
        let product = c64(0.0, sign) * factor * part2;
        data[i] = part1 + product;
        data[j] = (part1 - product).conj();
    }

    data[n / 2] = data[n / 2].conj();
}

#[cfg(test)]
mod tests {
    use number::c64;

    #[test]
    fn unpack() {
        let data = (0..4).map(|i| (i + 1) as f64).collect::<Vec<_>>();
        assert_eq!(super::unpack(&data), vec![
            c64(1.0, 0.0), c64(3.0, 4.0), c64(2.0, 0.0), c64(3.0, -4.0),
        ]);

        let data = (0..8).map(|i| (i + 1) as f64).collect::<Vec<_>>();
        assert_eq!(super::unpack(&data), vec![
            c64(1.0, 0.0), c64(3.0, 4.0), c64(5.0, 6.0), c64(7.0, 8.0),
            c64(2.0, 0.0), c64(7.0, -8.0), c64(5.0, -6.0), c64(3.0, -4.0),
        ]);
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::collections::hash_map::Entry;
use std::hash::Hash;
use std::rc::Rc;
use std::cell::RefCell;

struct Rlru<K, V>
    where K: Eq + Hash
{
    cache: HashMap<K, Rc<RefCell<Node<V>>>>,
    head: Link<V>,
    tail: Link<V>,
    max_length: u32,
}

struct Node<T> {
    elem: T,
    prev: Link<T>,
    next: Link<T>,
}

impl<T> Node<T> {
    fn new(elem: T) -> Self {
        Node {
            elem: elem,
            prev: None,
            next: None,
        }
    }
}

type Link<T> = Option<Rc<RefCell<Node<T>>>>;

impl<K, V> Rlru<K, V>
    where K: Eq + Hash
{
    pub fn new() -> Self {
        Rlru {
            cache: HashMap::new(),
            head: None,
            tail: None,
            max_length: 0,
        }
    }

    fn length_upkeep(&mut self) -> &mut Self {
        let max = self.max_length as usize;
        match self.cache.len() {
            0...max => self,
            // placeholder. Will pop off LRU key.
            _ => self
        }
    }

    fn splice_node(&mut self, node: Rc<RefCell<Node<V>>>) {
        // update node's prev/next pointers to link to each other
        {
            let node = node.borrow_mut();
            node.prev.map(|prev_node| {
                prev_node.borrow_mut().next = node.next.clone();
            });
            node.next.take().map(|next_node| {
                next_node.borrow_mut().prev = node.prev.take();
            });
        }
        // insert node at head of rlru.
        self.push(node);
    }

    fn push(&mut self, node: Rc<RefCell<Node<V>>>) -> &mut Self {
        self.head.take().map(|prev_head| {
            prev_head.borrow_mut().prev = Some(node.clone());
            node.borrow_mut().next = Some(prev_head);
        });
        self.head = Some(node.clone());
        self
    }

    fn pop(&mut self) {
        self.tail.take().map(|node| {
            if node.borrow_mut().prev.is_none() {
                // have to worry about updating head.
                self.head.take();
            }
            self.tail = node.borrow_mut().prev;
        });
    }

    pub fn get(&mut self, key: K) -> Option<&V> {
        match self.cache.entry(key) {
            Entry::Occupied(entry) => {
                // splice node to front
                let found = entry.get();
                self.splice_node(found.clone());
                Some(&found.as_ref().borrow().elem)
            },
            Entry::Vacant(_) => None
        }
    }

    pub fn set(&mut self, key: K, elem: V) -> &mut Self {
        match self.cache.entry(key) {
            Entry::Occupied(node) => {
                // splice node to front & update value
                self
            },
            Entry::Vacant(_) =>  {
                // insert node to front & do ln upkeep
                self
            }
        }
    }
}
<commit_msg>reference/lifetime cleaning<commit_after>use std::collections::HashMap;
use std::collections::hash_map::Entry;
use std::hash::Hash;
use std::rc::Rc;
use std::cell::RefCell;

struct Rlru<K, V>
    where K: Eq + Hash
{
    cache: HashMap<K, Rc<RefCell<Node<V>>>>,
    head: Link<V>,
    tail: Link<V>,
    max_length: u32,
}

struct Node<T> {
    elem: T,
    prev: Link<T>,
    next: Link<T>,
}

impl<T> Node<T> {
    fn new(elem: T) -> Self {
        Node {
            elem: elem,
            prev: None,
            next: None,
        }
    }
}

type Link<T> = Option<Rc<RefCell<Node<T>>>>;

impl<K, V> Rlru<K, V>
    where K: Eq + Hash
{
    pub fn new() -> Self {
        Rlru {
            cache: HashMap::new(),
            head: None,
            tail: None,
            max_length: 0,
        }
    }

    fn length_upkeep(&mut self) -> &mut Self {
        match self.cache.len() {
            len if len < self.max_length as usize => self,
            // placeholder. Will pop off LRU key.
            _ => self
        }
    }

    fn splice_node(&mut self, node: Rc<RefCell<Node<V>>>) {
        // update node's prev/next pointers to link to each other
        {
            let mut node = node.borrow_mut();

            // First we use cloning via Rc pointers, but will clean up our references via 'take' in the next_node routine
            node.prev.clone().map(|prev_node| {
                prev_node.borrow_mut().next = node.next.clone();
            });

            // here we take the extracted node's remaining pointers.
            node.next.take().map(|next_node| {
                next_node.borrow_mut().prev = node.prev.take();
            });
        }

        // insert node at head of rlru.
        self.push(node);
    }

    fn push(&mut self, node: Rc<RefCell<Node<V>>>) -> &mut Self {
        self.head.take().map(|prev_head| {
            prev_head.borrow_mut().prev = Some(node.clone());
            node.borrow_mut().next = Some(prev_head);
        });
        self.head = Some(node.clone());
        self
    }

    fn pop(&mut self) {
        self.tail.take().map(|node| {
            if node.borrow().prev.is_none() {
                // have to worry about updating head.
                self.head.take();
            }
            self.tail = node.borrow_mut().prev.take();
        });
    }

    pub fn get<'a>(&'a mut self, key: K) -> Option<&'a V> {
        match self.cache.entry(key) {
            Entry::Occupied(entry) => {
                // splice node to front
                let found = entry.get();
                self.splice_node(found.clone());
                Some(&found.as_ref().borrow().elem)
            },
            Entry::Vacant(_) => None
        }
    }

    pub fn set(&mut self, key: K, elem: V) -> &mut Self {
        match self.cache.entry(key) {
            Entry::Occupied(node) => {
                // splice node to front & update value
                self
            },
            Entry::Vacant(_) =>  {
                // insert node to front & do ln upkeep
                self
            }
        }
    }
}
<|endoftext|>


<commit_before>use animation::Animation;
use asset_manager::{AssetManager, AnimationAsset};
use collidable::Collidable;
use rectangle::Rectangle;
use shape::Intersect;

use glm;
use moho::errors::*;
use moho::renderer::Renderer;
use moho::resource_manager::ResourceManager;

pub struct Star {
    body: Rectangle,
    animation: Animation,
    explosion: Animation,
}

impl Star {
    pub fn new(center: glm::IVec2, asset_manager: &AssetManager) -> Self {
        let mut animation = asset_manager.get_animation(AnimationAsset::Star);
        animation.set_center(center);
        let explosion = asset_manager.get_animation(AnimationAsset::ExplosionSmall);

        let body = Rectangle {
            center: glm::to_dvec2(center),
            dims: glm::dvec2(animation.dst_rect().z as f64, animation.dst_rect().w as f64),
        };

        Star {
            body: body,
            explosion: explosion,
            animation: animation,
        }
    }

    pub fn explode(&self) -> Animation {
        let mut explosion = self.explosion.clone();
        explosion.set_center(glm::to_ivec2(self.body.center));
        explosion
    }

    pub fn update(&mut self) {
        self.animation.update();
    }

    pub fn draw<R: Renderer>(&self, renderer: &mut ResourceManager<R>) -> Result<()> {
        self.animation.draw(None, renderer)
    }
}

impl<I: Intersect<Rectangle>> Collidable<Rectangle, I> for Star {
    fn collides(&self, shape: &I) -> bool {
        shape.intersects(&self.body)
    }
}
<commit_msg>make explode method 'move' self to emphasize that the star is finished<commit_after>use animation::Animation;
use asset_manager::{AssetManager, AnimationAsset};
use collidable::Collidable;
use rectangle::Rectangle;
use shape::Intersect;

use glm;
use moho::errors::*;
use moho::renderer::Renderer;
use moho::resource_manager::ResourceManager;

pub struct Star {
    body: Rectangle,
    animation: Animation,
    explosion: Animation,
}

impl Star {
    pub fn new(center: glm::IVec2, asset_manager: &AssetManager) -> Self {
        let mut animation = asset_manager.get_animation(AnimationAsset::Star);
        animation.set_center(center);
        let explosion = asset_manager.get_animation(AnimationAsset::ExplosionSmall);

        let body = Rectangle {
            center: glm::to_dvec2(center),
            dims: glm::dvec2(animation.dst_rect().z as f64, animation.dst_rect().w as f64),
        };

        Star {
            body: body,
            explosion: explosion,
            animation: animation,
        }
    }

    pub fn explode(mut self) -> Animation {
        self.explosion.set_center(glm::to_ivec2(self.body.center));
        self.explosion
    }

    pub fn update(&mut self) {
        self.animation.update();
    }

    pub fn draw<R: Renderer>(&self, renderer: &mut ResourceManager<R>) -> Result<()> {
        self.animation.draw(None, renderer)
    }
}

impl<I: Intersect<Rectangle>> Collidable<Rectangle, I> for Star {
    fn collides(&self, shape: &I) -> bool {
        shape.intersects(&self.body)
    }
}
<|endoftext|>


<commit_before><commit_msg>Fixed windows bug in exec<commit_after><|endoftext|>


<commit_before><commit_msg>Fix lowspeed_limit documentation referring to old parameter name<commit_after><|endoftext|>


<commit_before>// use std::old_io::{TcpListener, TcpStream};
// use std::old_io::{Acceptor, Listener, IoResult, MemReader};
use std::thread::sleep_ms;
use std::io::{Read, Write, Result, BufRead, BufReader, BufWriter};
use std::fs::File;

use std::net::{TcpListener, TcpStream};
use std::mem::size_of;

use std::sync::mpsc::{Sender, Receiver, channel};

use std::thread;
use std::sync::Arc;
use std::mem;

use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};

use communication::{Pushable, BinaryCommunicator, ProcessCommunicator};
use drain::DrainExt;

// TODO : Much of this only relates to BinaryWriter/BinaryReader based communication, not networking.
// TODO : Could be moved somewhere less networking-specific.

#[derive(Copy, Clone)]
pub struct MessageHeader {
    pub graph:      u64,   // graph identifier
    pub channel:    u64,   // index of channel
    pub source:     u64,   // index of worker sending message
    pub target:     u64,   // index of worker receiving message
    pub length:     u64,   // number of bytes in message
}

impl MessageHeader {
    // returns a header when there is enough supporting data
    fn try_read(bytes: &mut &[u8]) -> Option<MessageHeader> {
        if bytes.len() > size_of::<MessageHeader>() {
            // capture original in case we need to rewind
            let original = *bytes;

            // unclear what order struct initializers run in, so ...
            let graph = bytes.read_u64::<LittleEndian>().unwrap();
            let channel = bytes.read_u64::<LittleEndian>().unwrap();
            let source = bytes.read_u64::<LittleEndian>().unwrap();
            let target = bytes.read_u64::<LittleEndian>().unwrap();
            let length = bytes.read_u64::<LittleEndian>().unwrap();

            let header = MessageHeader {
                graph: graph,
                channel: channel,
                source: source,
                target: target,
                length: length,
            };

            if bytes.len() >= header.length as usize {
                Some(header)
            }
            else {
                // rewind the reader
                *bytes = original;
                None
            }
        }
        else { None }
    }

    fn write_to<W: Write>(&self, writer: &mut W) -> Result<()> {
        try!(writer.write_u64::<LittleEndian>(self.graph));
        try!(writer.write_u64::<LittleEndian>(self.channel));
        try!(writer.write_u64::<LittleEndian>(self.source));
        try!(writer.write_u64::<LittleEndian>(self.target));
        try!(writer.write_u64::<LittleEndian>(self.length));
        Ok(())
    }
}

// structure in charge of receiving data from a Reader, for example the network
struct BinaryReceiver<R: Read> {
    reader:     R,          // the generic reader
    buffer:     Vec<u8>,    // current working buffer
    double:     Vec<u8>,    // second working buffer
    staging:    Vec<u8>,    // 1 << 20 of buffer to read into
    targets:    Switchboard<(Sender<Vec<u8>>, Receiver<Vec<u8>>)>,
}

impl<R: Read> BinaryReceiver<R> {
    fn new(reader: R, channels: Receiver<((u64, u64, u64), (Sender<Vec<u8>>, Receiver<Vec<u8>>))>) -> BinaryReceiver<R> {
        BinaryReceiver {

            reader:     reader,
            buffer:     Vec::new(),
            double:     Vec::new(),
            staging:    vec![0u8; 1 << 20],
            targets:    Switchboard::new(channels),
        }
    }

    fn recv_loop(&mut self) {
        loop {

            // attempt to read some more bytes into our buffer
            // TODO : We read in to self.staging because extending a Vec<u8> is hard without
            // TODO : using set_len, which is unsafe.
            let read = self.reader.read(&mut self.staging[..]).unwrap_or(0);
            // self.buffer.write_all(&self.staging[..read]).unwrap(); // <-- shouldn't fail
            //
            // {
            //     // get a view of available bytes
            //     let mut slice = &self.buffer[..];
            //
            //     while let Some(header) = MessageHeader::try_read(&mut slice) {
            //
            //         let h_len = header.length as usize;  // length in bytes
            //         let target = self.targets.ensure(header.target, header.graph, header.channel);
            //         let mut buffer = target.1.try_recv().unwrap_or(Vec::new());
            //
            //         buffer.clear();
            //         buffer.write_all(&slice[..h_len]).unwrap();
            //         slice = &slice[h_len..];
            //
            //         target.0.send(buffer).unwrap();
            //     }
            //
            //     // TODO: way inefficient... =/ Fix! :D
            //     // if slice.len() < self.buffer.len() {
            //         self.double.clear();
            //         self.double.write_all(slice).unwrap();
            //     // }
            // }
            //
            // // if self.double.len() > 0 {
            //     mem::swap(&mut self.buffer, &mut self.double);
            //     // self.double.clear();
            // // }
        }
    }
}

// structure in charge of sending data to a Writer, for example the network
struct BinarySender<W: Write> {
    id:         u64,    // destination process
    writer:     W,
    sources:    Receiver<(MessageHeader, Vec<u8>)>,
    returns:    Switchboard<Sender<Vec<u8>>>,
}

impl<W: Write> BinarySender<W> {
    fn new(id: u64,
           writer: W,
           sources: Receiver<(MessageHeader, Vec<u8>)>,
           channels: Receiver<((u64, u64, u64), Sender<Vec<u8>>)>) -> BinarySender<W> {
        BinarySender {
            id:         id,
            writer:     writer,
            sources:    sources,
            returns: Switchboard::new(channels),
        }
    }

    fn send_loop(&mut self) {
        let mut stash = Vec::new();

        let trash1 = vec![0u8; 40];
        let trash2 = vec![0u8; 1 << 20];

        loop {
            self.writer.write_all(&trash1[..]);
            self.writer.write_all(&trash2[..]);
        }

        // block until data to recv
        while let Ok((header, buffer)) = self.sources.recv() {

            stash.push((header, buffer));

            // collect any additional outstanding data to send
            while let Ok((header, buffer)) = self.sources.try_recv() {
                stash.push((header, buffer));
            }

            // println!("send loop to process {}:\tstarting", self.id);
            for (mut header, mut buffer) in stash.drain_temp() {
                header.length = buffer.len() as u64;    // <-- is this really our job? O.o
                header.write_to(&mut self.writer).unwrap();
                self.writer.write_all(&buffer[..]).unwrap();
                buffer.clear();

                // self.returns.ensure(header.source, header.graph, header.channel).send(buffer).unwrap();
            }

            self.writer.flush().unwrap();    // <-- because writer is buffered
        }
    }
}

struct Switchboard<T:Send> {
    source: Receiver<((u64, u64, u64), T)>,
    buffer: Vec<Vec<Vec<Option<T>>>>,
}

impl<T:Send> Switchboard<T> {
    pub fn new(source: Receiver<((u64, u64, u64), T)>) -> Switchboard<T> {
        Switchboard {
            source: source,
            buffer: Vec::new(),
        }
    }

    pub fn ensure(&mut self, a: u64, b: u64, c: u64) -> &mut T {
        let a = a as usize;
        let b = b as usize;
        let c = c as usize;

        while self.buffer.len() <= a { self.buffer.push(Vec::new()); }
        while self.buffer[a].len() <= b { self.buffer[a].push(Vec::new()); }
        while self.buffer[a][b].len() <= c { self.buffer[a][b].push(None); }

        while let None = self.buffer[a][b][c] {
            let ((x, y, z), s) = self.source.recv().unwrap();

            let x = x as usize;
            let y = y as usize;
            let z = z as usize;

            while self.buffer.len() <= x { self.buffer.push(Vec::new()); }
            while self.buffer[x].len() <= y { self.buffer[x].push(Vec::new()); }
            while self.buffer[x][y].len() <= z { self.buffer[x][y].push(None); }
            self.buffer[x][y][z] = Some(s);
        }

        self.buffer[a][b][c].as_mut().unwrap()
    }
}

pub fn initialize_networking_from_file(filename: &str, my_index: u64, workers: u64) -> Result<Vec<BinaryCommunicator>> {

    let reader = BufReader::new(try!(File::open(filename)));
    let mut addresses = Vec::new();

    for line in reader.lines() {
        addresses.push(try!(line));
    }

    // println!("addresses.len() : {} vs workers : {}", addresses.len(), workers);
    // assert!(addresses.len() as u64 == workers);
    initialize_networking(addresses, my_index, workers)
}

pub fn initialize_networking(addresses: Vec<String>, my_index: u64, workers: u64) -> Result<Vec<BinaryCommunicator>> {

    let processes = addresses.len() as u64;
    let hosts1 = Arc::new(addresses);
    let hosts2 = hosts1.clone();

    let start_task = thread::spawn(move || start_connections(hosts1, my_index));
    let await_task = thread::spawn(move || await_connections(hosts2, my_index));

    let mut results = try!(start_task.join().unwrap());

    results.push(None);
    let mut to_extend = try!(await_task.join().unwrap());
    results.extend(to_extend.drain_temp());

    println!("worker {}:\tinitialization complete", my_index);

    let mut writers = Vec::new();   // handles to the BinarySenders (to present new channels)
    let mut readers = Vec::new();   // handles to the BinaryReceivers (to present new channels)
    let mut senders = Vec::new();   // destinations for serialized data (to send serialized data)

    // for each process, if a stream exists (i.e. not local) ...
    for index in (0..results.len()) {
        if let Some(stream) = results[index].take() {

            let (writer_channels_s, writer_channels_r) = channel();
            let (reader_channels_s, reader_channels_r) = channel();
            let (sender_channels_s, sender_channels_r) = channel();

            writers.push(writer_channels_s);    //
            readers.push(reader_channels_s);    //
            senders.push(sender_channels_s);    //

            let mut sender = BinarySender::new(index as u64, BufWriter::with_capacity(1 << 20, stream.try_clone().unwrap()), sender_channels_r, writer_channels_r);
            let mut recver = BinaryReceiver::new(stream.try_clone().unwrap(), reader_channels_r);

            // start senders and receivers associated with this stream
            thread::Builder::new().name(format!("send thread {}", index))
                                  .spawn(move || sender.send_loop())
                                  .unwrap();
            thread::Builder::new().name(format!("recv thread {}", index))
                                  .spawn(move || recver.recv_loop())
                                  .unwrap();

        }
    }

    let proc_comms = ProcessCommunicator::new_vector(workers);

    let mut results = Vec::new();
    for (index, proc_comm) in proc_comms.into_iter().enumerate() {
        results.push(BinaryCommunicator {
            inner:          proc_comm,
            index:          my_index * workers + index as u64,
            peers:          workers * processes,
            graph:          0,          // TODO : Fix this
            allocated:      0,
            writers:        writers.clone(),
            readers:        readers.clone(),
            senders:        senders.clone(),
        });
    }

    return Ok(results);
}

// result contains connections [0, my_index - 1].
fn start_connections(addresses: Arc<Vec<String>>, my_index: u64) -> Result<Vec<Option<TcpStream>>> {
    let mut results: Vec<_> = (0..my_index).map(|_| None).collect();
    for index in (0..my_index) {
        let mut connected = false;
        while !connected {
            match TcpStream::connect(&addresses[index as usize][..]) {
                Ok(mut stream) => {
                    try!(stream.write_u64::<LittleEndian>(my_index));
                    results[index as usize] = Some(stream);
                    println!("worker {}:\tconnection to worker {}", my_index, index);
                    connected = true;
                },
                Err(error) => {
                    println!("worker {}:\terror connecting to worker {}: {}; retrying", my_index, index, error);
                    sleep_ms(1000);
                },
            }
        }
    }

    return Ok(results);
}

// result contains connections [my_index + 1, addresses.len() - 1].
fn await_connections(addresses: Arc<Vec<String>>, my_index: u64) -> Result<Vec<Option<TcpStream>>> {
    let mut results: Vec<_> = (0..(addresses.len() - my_index as usize - 1)).map(|_| None).collect();
    let listener = try!(TcpListener::bind(&addresses[my_index as usize][..]));

    for _ in (my_index as usize + 1 .. addresses.len()) {
        let mut stream = try!(listener.accept()).0;
        let identifier = try!(stream.read_u64::<LittleEndian>()) as usize;
        results[identifier - my_index as usize - 1] = Some(stream);
        println!("worker {}:\tconnection from worker {}", my_index, identifier);
    }

    return Ok(results);
}
<commit_msg>restored non-spammy networking<commit_after>// use std::old_io::{TcpListener, TcpStream};
// use std::old_io::{Acceptor, Listener, IoResult, MemReader};
use std::thread::sleep_ms;
use std::io::{Read, Write, Result, BufRead, BufReader, BufWriter};
use std::fs::File;

use std::net::{TcpListener, TcpStream};
use std::mem::size_of;

use std::sync::mpsc::{Sender, Receiver, channel};

use std::thread;
use std::sync::Arc;
use std::mem;

use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};

use communication::{Pushable, BinaryCommunicator, ProcessCommunicator};
use drain::DrainExt;

// TODO : Much of this only relates to BinaryWriter/BinaryReader based communication, not networking.
// TODO : Could be moved somewhere less networking-specific.

#[derive(Copy, Clone)]
pub struct MessageHeader {
    pub graph:      u64,   // graph identifier
    pub channel:    u64,   // index of channel
    pub source:     u64,   // index of worker sending message
    pub target:     u64,   // index of worker receiving message
    pub length:     u64,   // number of bytes in message
}

impl MessageHeader {
    // returns a header when there is enough supporting data
    fn try_read(bytes: &mut &[u8]) -> Option<MessageHeader> {
        if bytes.len() > size_of::<MessageHeader>() {
            // capture original in case we need to rewind
            let original = *bytes;

            // unclear what order struct initializers run in, so ...
            let graph = bytes.read_u64::<LittleEndian>().unwrap();
            let channel = bytes.read_u64::<LittleEndian>().unwrap();
            let source = bytes.read_u64::<LittleEndian>().unwrap();
            let target = bytes.read_u64::<LittleEndian>().unwrap();
            let length = bytes.read_u64::<LittleEndian>().unwrap();

            let header = MessageHeader {
                graph: graph,
                channel: channel,
                source: source,
                target: target,
                length: length,
            };

            if bytes.len() >= header.length as usize {
                Some(header)
            }
            else {
                // rewind the reader
                *bytes = original;
                None
            }
        }
        else { None }
    }

    fn write_to<W: Write>(&self, writer: &mut W) -> Result<()> {
        try!(writer.write_u64::<LittleEndian>(self.graph));
        try!(writer.write_u64::<LittleEndian>(self.channel));
        try!(writer.write_u64::<LittleEndian>(self.source));
        try!(writer.write_u64::<LittleEndian>(self.target));
        try!(writer.write_u64::<LittleEndian>(self.length));
        Ok(())
    }
}

// structure in charge of receiving data from a Reader, for example the network
struct BinaryReceiver<R: Read> {
    reader:     R,          // the generic reader
    buffer:     Vec<u8>,    // current working buffer
    double:     Vec<u8>,    // second working buffer
    staging:    Vec<u8>,    // 1 << 20 of buffer to read into
    targets:    Switchboard<(Sender<Vec<u8>>, Receiver<Vec<u8>>)>,
}

impl<R: Read> BinaryReceiver<R> {
    fn new(reader: R, channels: Receiver<((u64, u64, u64), (Sender<Vec<u8>>, Receiver<Vec<u8>>))>) -> BinaryReceiver<R> {
        BinaryReceiver {

            reader:     reader,
            buffer:     Vec::new(),
            double:     Vec::new(),
            staging:    vec![0u8; 1 << 20],
            targets:    Switchboard::new(channels),
        }
    }

    fn recv_loop(&mut self) {
        loop {

            // attempt to read some more bytes into our buffer
            // TODO : We read in to self.staging because extending a Vec<u8> is hard without
            // TODO : using set_len, which is unsafe.
            let read = self.reader.read(&mut self.staging[..]).unwrap_or(0);
            self.buffer.write_all(&self.staging[..read]).unwrap(); // <-- shouldn't fail

            {
                // get a view of available bytes
                let mut slice = &self.buffer[..];

                while let Some(header) = MessageHeader::try_read(&mut slice) {

                    let h_len = header.length as usize;  // length in bytes
                    let target = self.targets.ensure(header.target, header.graph, header.channel);
                    let mut buffer = target.1.try_recv().unwrap_or(Vec::new());

                    buffer.clear();
                    buffer.write_all(&slice[..h_len]).unwrap();
                    slice = &slice[h_len..];

                    target.0.send(buffer).unwrap();
                }

                // TODO: way inefficient... =/ Fix! :D
                // if slice.len() < self.buffer.len() {
                    self.double.clear();
                    self.double.write_all(slice).unwrap();
                // }
            }

            // if self.double.len() > 0 {
                mem::swap(&mut self.buffer, &mut self.double);
                // self.double.clear();
            // }
        }
    }
}

// structure in charge of sending data to a Writer, for example the network
struct BinarySender<W: Write> {
    id:         u64,    // destination process
    writer:     W,
    sources:    Receiver<(MessageHeader, Vec<u8>)>,
    returns:    Switchboard<Sender<Vec<u8>>>,
}

impl<W: Write> BinarySender<W> {
    fn new(id: u64,
           writer: W,
           sources: Receiver<(MessageHeader, Vec<u8>)>,
           channels: Receiver<((u64, u64, u64), Sender<Vec<u8>>)>) -> BinarySender<W> {
        BinarySender {
            id:         id,
            writer:     writer,
            sources:    sources,
            returns: Switchboard::new(channels),
        }
    }

    fn send_loop(&mut self) {
        let mut stash = Vec::new();

        // block until data to recv
        while let Ok((header, buffer)) = self.sources.recv() {

            stash.push((header, buffer));

            // collect any additional outstanding data to send
            while let Ok((header, buffer)) = self.sources.try_recv() {
                stash.push((header, buffer));
            }

            // println!("send loop to process {}:\tstarting", self.id);
            for (mut header, mut buffer) in stash.drain_temp() {
                header.length = buffer.len() as u64;    // <-- is this really our job? O.o
                header.write_to(&mut self.writer).unwrap();
                self.writer.write_all(&buffer[..]).unwrap();
                buffer.clear();

                // self.returns.ensure(header.source, header.graph, header.channel).send(buffer).unwrap();
            }

            self.writer.flush().unwrap();    // <-- because writer is buffered
        }
    }
}

struct Switchboard<T:Send> {
    source: Receiver<((u64, u64, u64), T)>,
    buffer: Vec<Vec<Vec<Option<T>>>>,
}

impl<T:Send> Switchboard<T> {
    pub fn new(source: Receiver<((u64, u64, u64), T)>) -> Switchboard<T> {
        Switchboard {
            source: source,
            buffer: Vec::new(),
        }
    }

    pub fn ensure(&mut self, a: u64, b: u64, c: u64) -> &mut T {
        let a = a as usize;
        let b = b as usize;
        let c = c as usize;

        while self.buffer.len() <= a { self.buffer.push(Vec::new()); }
        while self.buffer[a].len() <= b { self.buffer[a].push(Vec::new()); }
        while self.buffer[a][b].len() <= c { self.buffer[a][b].push(None); }

        while let None = self.buffer[a][b][c] {
            let ((x, y, z), s) = self.source.recv().unwrap();

            let x = x as usize;
            let y = y as usize;
            let z = z as usize;

            while self.buffer.len() <= x { self.buffer.push(Vec::new()); }
            while self.buffer[x].len() <= y { self.buffer[x].push(Vec::new()); }
            while self.buffer[x][y].len() <= z { self.buffer[x][y].push(None); }
            self.buffer[x][y][z] = Some(s);
        }

        self.buffer[a][b][c].as_mut().unwrap()
    }
}

pub fn initialize_networking_from_file(filename: &str, my_index: u64, workers: u64) -> Result<Vec<BinaryCommunicator>> {

    let reader = BufReader::new(try!(File::open(filename)));
    let mut addresses = Vec::new();

    for line in reader.lines() {
        addresses.push(try!(line));
    }

    // println!("addresses.len() : {} vs workers : {}", addresses.len(), workers);
    // assert!(addresses.len() as u64 == workers);
    initialize_networking(addresses, my_index, workers)
}

pub fn initialize_networking(addresses: Vec<String>, my_index: u64, workers: u64) -> Result<Vec<BinaryCommunicator>> {

    let processes = addresses.len() as u64;
    let hosts1 = Arc::new(addresses);
    let hosts2 = hosts1.clone();

    let start_task = thread::spawn(move || start_connections(hosts1, my_index));
    let await_task = thread::spawn(move || await_connections(hosts2, my_index));

    let mut results = try!(start_task.join().unwrap());

    results.push(None);
    let mut to_extend = try!(await_task.join().unwrap());
    results.extend(to_extend.drain_temp());

    println!("worker {}:\tinitialization complete", my_index);

    let mut writers = Vec::new();   // handles to the BinarySenders (to present new channels)
    let mut readers = Vec::new();   // handles to the BinaryReceivers (to present new channels)
    let mut senders = Vec::new();   // destinations for serialized data (to send serialized data)

    // for each process, if a stream exists (i.e. not local) ...
    for index in (0..results.len()) {
        if let Some(stream) = results[index].take() {

            let (writer_channels_s, writer_channels_r) = channel();
            let (reader_channels_s, reader_channels_r) = channel();
            let (sender_channels_s, sender_channels_r) = channel();

            writers.push(writer_channels_s);    //
            readers.push(reader_channels_s);    //
            senders.push(sender_channels_s);    //

            let mut sender = BinarySender::new(index as u64, BufWriter::with_capacity(1 << 20, stream.try_clone().unwrap()), sender_channels_r, writer_channels_r);
            let mut recver = BinaryReceiver::new(stream.try_clone().unwrap(), reader_channels_r);

            // start senders and receivers associated with this stream
            thread::Builder::new().name(format!("send thread {}", index))
                                  .spawn(move || sender.send_loop())
                                  .unwrap();
            thread::Builder::new().name(format!("recv thread {}", index))
                                  .spawn(move || recver.recv_loop())
                                  .unwrap();

        }
    }

    let proc_comms = ProcessCommunicator::new_vector(workers);

    let mut results = Vec::new();
    for (index, proc_comm) in proc_comms.into_iter().enumerate() {
        results.push(BinaryCommunicator {
            inner:          proc_comm,
            index:          my_index * workers + index as u64,
            peers:          workers * processes,
            graph:          0,          // TODO : Fix this
            allocated:      0,
            writers:        writers.clone(),
            readers:        readers.clone(),
            senders:        senders.clone(),
        });
    }

    return Ok(results);
}

// result contains connections [0, my_index - 1].
fn start_connections(addresses: Arc<Vec<String>>, my_index: u64) -> Result<Vec<Option<TcpStream>>> {
    let mut results: Vec<_> = (0..my_index).map(|_| None).collect();
    for index in (0..my_index) {
        let mut connected = false;
        while !connected {
            match TcpStream::connect(&addresses[index as usize][..]) {
                Ok(mut stream) => {
                    try!(stream.write_u64::<LittleEndian>(my_index));
                    results[index as usize] = Some(stream);
                    println!("worker {}:\tconnection to worker {}", my_index, index);
                    connected = true;
                },
                Err(error) => {
                    println!("worker {}:\terror connecting to worker {}: {}; retrying", my_index, index, error);
                    sleep_ms(1000);
                },
            }
        }
    }

    return Ok(results);
}

// result contains connections [my_index + 1, addresses.len() - 1].
fn await_connections(addresses: Arc<Vec<String>>, my_index: u64) -> Result<Vec<Option<TcpStream>>> {
    let mut results: Vec<_> = (0..(addresses.len() - my_index as usize - 1)).map(|_| None).collect();
    let listener = try!(TcpListener::bind(&addresses[my_index as usize][..]));

    for _ in (my_index as usize + 1 .. addresses.len()) {
        let mut stream = try!(listener.accept()).0;
        let identifier = try!(stream.read_u64::<LittleEndian>()) as usize;
        results[identifier - my_index as usize - 1] = Some(stream);
        println!("worker {}:\tconnection from worker {}", my_index, identifier);
    }

    return Ok(results);
}
<|endoftext|>


<commit_before>use chan::{Sender, Receiver};
use chan;
use chan_signal::Signal;
use chan_signal;

use std::fmt::{Debug, Formatter};
use std::fmt;
use std::thread::JoinHandle;
use std::thread;
use std::sync::{Arc, Mutex};
use std::time::Duration;

use collectors::Collector;
use collectors::Id;
use bosun::{Bosun, BosunRequest, Sample};

pub fn run(collectors: Vec<Box<Collector + Send>>) -> () {
    let signal = chan_signal::notify(&[Signal::INT, Signal::TERM]);
    let timer = chan::tick(Duration::from_secs(TICK_INTERVAL));
    info!("Scheduler thread started.");

    let (to_main_tx, from_runners_rx) = chan::async();
    let controllers = create_controllers(collectors, to_main_tx);
    info!("Loaded {} collectors: {:#?}", controllers.len(), controllers);

    let (to_bosun_tx, from_main_rx) = chan::async();
    let bosun = Bosun::new(from_main_rx);
    let bosun_thread = bosun.spawn();

    event_loop(&controllers,
               &signal,
               &timer,
               &from_runners_rx,
               &to_bosun_tx);

    // TODO: Generalize tear_down for all threads / JoinHandles
    tear_down(controllers);
    to_bosun_tx.send(BosunRequest::Shutdown);
    let _ = bosun_thread.join();

    info!("Scheduler thread finished.");
}

static TICK_INTERVAL: u64 = 1u64;

#[derive(Debug)]
enum CollectorRequest {
    Helo,
    Shutdown,
    Sample,
}

#[derive(Debug)]
enum CollectorResponse {
    Id(Id),
    Sample(Sample),
}

/**
* Handle for Main Thread to communicate with CollectorRunner
**/
struct CollectorController {
    id: Id,
    runner_tx: Sender<CollectorRequest>,
    runner_thread: Option<JoinHandle<()>>,
}

impl Debug for CollectorController {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "CollectorController {{ id: {:#?} }}", self.id)
    }
}

impl CollectorController {
    fn new(id: Id, runner_tx: Sender<CollectorRequest>) -> CollectorController {
        CollectorController {
            id: id,
            runner_tx: runner_tx,
            runner_thread: None,
        }
    }
}

/**
* Periodically runs the collector <T>
**/
struct CollectorRunner {
    id: Id,
    runner_rx: Receiver<CollectorRequest>,
    controller_tx: Sender<CollectorResponse>,
    collector: Arc<Mutex<Box<Collector + Send>>>,
}

impl CollectorRunner {
    fn new(id: Id,
           runner_rx: Receiver<CollectorRequest>,
           controller_tx: Sender<CollectorResponse>,
           collector: Box<Collector + Send>)
           -> CollectorRunner {
        CollectorRunner {
            id: id,
            runner_rx: runner_rx,
            controller_tx: controller_tx,
            collector: Arc::new(Mutex::new(collector)),
        }
    }

    fn spawn(mut self) -> JoinHandle<()> {
        thread::spawn(move || {
            info!("CollectorRunner {} thread started.", self.id);
            loop {
                let message = self.runner_rx.recv();
                match message {
                    Some(CollectorRequest::Helo) => {
                        debug!("CollectorRunner {} received 'Helo' message.", &self.id);
                        self.controller_tx.send(CollectorResponse::Id(self.id.clone()));
                    }
                    Some(CollectorRequest::Sample) => {
                        debug!("CollectorRunner {} received 'Sample' message.", &self.id);
                        self.collect_sample();
                    }
                    Some(CollectorRequest::Shutdown) => {
                        debug!("CollectorRunner {} received 'Shutdown' message.", &self.id);
                        let collector = self.collector.clone();
                        let collector = collector.lock().unwrap();
                        collector.shutdown();
                        self.controller_tx.send(CollectorResponse::Id(self.id.clone()));
                        break;
                    }
                    None => {
                        break;
                    }
                }
            }
            info!("CollectorRunner {} thread finished.", self.id);
        })
    }

    fn collect_sample(&mut self) {
        let collector = self.collector.clone();
        let lock = collector.try_lock();
        match lock {
            Ok(_) => {
                let id = self.id.clone();
                let tx = self.controller_tx.clone();
                let collector = self.collector.clone();
                thread::spawn(move || {
                    debug!("CollectorRunner {} spawned sample thread.", &id);
                    let ref collector = *collector.lock().unwrap();
                    let sample = collector.collect();
                    tx.send(CollectorResponse::Sample(sample));
                    debug!("CollectorRunner {} finished sample thread.", &id);
                });
            }
            Err(_) => {
                trace!("CollectorRunner {} sampling already running ...", &self.id);
            }
        }
    }
}

fn create_controllers(
    collectors: Vec<Box<Collector + Send>>,
    runners_to_main_tx: Sender<CollectorResponse>) -> Vec<CollectorController> {
    let mut controllers: Vec<CollectorController> = Vec::new();

    for c in collectors.into_iter() {
        let (to_runner_tx, from_controller_rx) = chan::async();
        let mut controller = CollectorController::new(c.id().clone(), to_runner_tx);
        let runner = CollectorRunner::new(c.id().clone(),
                                          from_controller_rx,
                                          runners_to_main_tx.clone(),
                                          c);
        let runner_thread = runner.spawn();

        controller.runner_thread = Some(runner_thread);
        controllers.push(controller);
    }

    controllers
}

fn event_loop(threads: &Vec<CollectorController>,
              signal_rx: &Receiver<Signal>,
              timer: &Receiver<Sender<()>>,
              collectors_rx: &Receiver<CollectorResponse>,
              bosun_tx: &Sender<BosunRequest>)
              -> () {
    info!("Scheduler thread entering event loop.");
    loop {
        debug!("Scheduler thread event loop.");
        chan_select! {
            signal_rx.recv() => {
                break
            },
            timer.recv() => {
                trace!("Scheduler: I've been ticked.");
                for cc in threads.iter() {
                    cc.runner_tx.send(CollectorRequest::Sample)
                }
            },
            collectors_rx.recv() -> message => {
                match message {
                    Some(CollectorResponse::Id(id)) => {
                        debug!("Scheduler received 'Helo' from collector {}.", id);
                    }
                    Some(CollectorResponse::Sample(sample)) => {
                        debug!("Scheduler received sample {}.", sample.time);
                        bosun_tx.send(BosunRequest::Sample(sample));
                    }
                    None => {
                        error!("Channel unexpectedly shut down.");
                    }
                }
            }
        };
    }
}

fn tear_down(threads: Vec<CollectorController>) -> () {
    info!("Scheduler thread shutting down ...");
    for cc in threads.iter() {
        cc.runner_tx.send(CollectorRequest::Shutdown)
    }

    info!("Scheduler thread waiting for collector threads to finish ...");
    for cc in threads.into_iter() {
        let jh = cc.runner_thread.unwrap();
        let _ = jh.join();
    }
}
<commit_msg>Bugfix -- terminate if collectors_rx is closed<commit_after>use chan::{Sender, Receiver};
use chan;
use chan_signal::Signal;
use chan_signal;

use std::fmt::{Debug, Formatter};
use std::fmt;
use std::thread::JoinHandle;
use std::thread;
use std::sync::{Arc, Mutex};
use std::time::Duration;

use collectors::Collector;
use collectors::Id;
use bosun::{Bosun, BosunRequest, Sample};

pub fn run(collectors: Vec<Box<Collector + Send>>) -> () {
    let signal = chan_signal::notify(&[Signal::INT, Signal::TERM]);
    let timer = chan::tick(Duration::from_secs(TICK_INTERVAL));
    info!("Scheduler thread started.");

    let (to_main_tx, from_runners_rx) = chan::async();
    let controllers = create_controllers(collectors, to_main_tx);
    info!("Loaded {} collectors: {:#?}", controllers.len(), controllers);

    let (to_bosun_tx, from_main_rx) = chan::async();
    let bosun = Bosun::new(from_main_rx);
    let bosun_thread = bosun.spawn();

    event_loop(&controllers,
               &signal,
               &timer,
               &from_runners_rx,
               &to_bosun_tx);

    // TODO: Generalize tear_down for all threads / JoinHandles
    tear_down(controllers);
    to_bosun_tx.send(BosunRequest::Shutdown);
    let _ = bosun_thread.join();

    info!("Scheduler thread finished.");
}

static TICK_INTERVAL: u64 = 1u64;

#[derive(Debug)]
enum CollectorRequest {
    Helo,
    Shutdown,
    Sample,
}

#[derive(Debug)]
enum CollectorResponse {
    Id(Id),
    Sample(Sample),
}

/**
* Handle for Main Thread to communicate with CollectorRunner
**/
struct CollectorController {
    id: Id,
    runner_tx: Sender<CollectorRequest>,
    runner_thread: Option<JoinHandle<()>>,
}

impl Debug for CollectorController {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "CollectorController {{ id: {:#?} }}", self.id)
    }
}

impl CollectorController {
    fn new(id: Id, runner_tx: Sender<CollectorRequest>) -> CollectorController {
        CollectorController {
            id: id,
            runner_tx: runner_tx,
            runner_thread: None,
        }
    }
}

/**
* Periodically runs the collector <T>
**/
struct CollectorRunner {
    id: Id,
    runner_rx: Receiver<CollectorRequest>,
    controller_tx: Sender<CollectorResponse>,
    collector: Arc<Mutex<Box<Collector + Send>>>,
}

impl CollectorRunner {
    fn new(id: Id,
           runner_rx: Receiver<CollectorRequest>,
           controller_tx: Sender<CollectorResponse>,
           collector: Box<Collector + Send>)
           -> CollectorRunner {
        CollectorRunner {
            id: id,
            runner_rx: runner_rx,
            controller_tx: controller_tx,
            collector: Arc::new(Mutex::new(collector)),
        }
    }

    fn spawn(mut self) -> JoinHandle<()> {
        thread::spawn(move || {
            info!("CollectorRunner {} thread started.", self.id);
            loop {
                let message = self.runner_rx.recv();
                match message {
                    Some(CollectorRequest::Helo) => {
                        debug!("CollectorRunner {} received 'Helo' message.", &self.id);
                        self.controller_tx.send(CollectorResponse::Id(self.id.clone()));
                    }
                    Some(CollectorRequest::Sample) => {
                        debug!("CollectorRunner {} received 'Sample' message.", &self.id);
                        self.collect_sample();
                    }
                    Some(CollectorRequest::Shutdown) => {
                        debug!("CollectorRunner {} received 'Shutdown' message.", &self.id);
                        let collector = self.collector.clone();
                        let collector = collector.lock().unwrap();
                        collector.shutdown();
                        self.controller_tx.send(CollectorResponse::Id(self.id.clone()));
                        break;
                    }
                    None => {
                        break;
                    }
                }
            }
            info!("CollectorRunner {} thread finished.", self.id);
        })
    }

    fn collect_sample(&mut self) {
        let collector = self.collector.clone();
        let lock = collector.try_lock();
        match lock {
            Ok(_) => {
                let id = self.id.clone();
                let tx = self.controller_tx.clone();
                let collector = self.collector.clone();
                thread::spawn(move || {
                    debug!("CollectorRunner {} spawned sample thread.", &id);
                    let ref collector = *collector.lock().unwrap();
                    let sample = collector.collect();
                    tx.send(CollectorResponse::Sample(sample));
                    debug!("CollectorRunner {} finished sample thread.", &id);
                });
            }
            Err(_) => {
                trace!("CollectorRunner {} sampling already running ...", &self.id);
            }
        }
    }
}

fn create_controllers(
    collectors: Vec<Box<Collector + Send>>,
    runners_to_main_tx: Sender<CollectorResponse>) -> Vec<CollectorController> {
    let mut controllers: Vec<CollectorController> = Vec::new();

    for c in collectors.into_iter() {
        let (to_runner_tx, from_controller_rx) = chan::async();
        let mut controller = CollectorController::new(c.id().clone(), to_runner_tx);
        let runner = CollectorRunner::new(c.id().clone(),
                                          from_controller_rx,
                                          runners_to_main_tx.clone(),
                                          c);
        let runner_thread = runner.spawn();

        controller.runner_thread = Some(runner_thread);
        controllers.push(controller);
    }

    controllers
}

fn event_loop(threads: &Vec<CollectorController>,
              signal_rx: &Receiver<Signal>,
              timer: &Receiver<Sender<()>>,
              collectors_rx: &Receiver<CollectorResponse>,
              bosun_tx: &Sender<BosunRequest>)
              -> () {
    info!("Scheduler thread entering event loop.");
    loop {
        debug!("Scheduler thread event loop.");
        chan_select! {
            signal_rx.recv() => {
                break
            },
            timer.recv() => {
                trace!("Scheduler: I've been ticked.");
                for cc in threads.iter() {
                    cc.runner_tx.send(CollectorRequest::Sample)
                }
            },
            collectors_rx.recv() -> message => {
                match message {
                    Some(CollectorResponse::Id(id)) => {
                        debug!("Scheduler received 'Helo' from collector {}.", id);
                    }
                    Some(CollectorResponse::Sample(sample)) => {
                        debug!("Scheduler received sample {}.", sample.time);
                        bosun_tx.send(BosunRequest::Sample(sample));
                    }
                    None => {
                        error!("Channel unexpectedly shut down.");
                        break
                    }
                }
            }
        };
    }
}

fn tear_down(threads: Vec<CollectorController>) -> () {
    info!("Scheduler thread shutting down ...");
    for cc in threads.iter() {
        cc.runner_tx.send(CollectorRequest::Shutdown)
    }

    info!("Scheduler thread waiting for collector threads to finish ...");
    for cc in threads.into_iter() {
        let jh = cc.runner_thread.unwrap();
        let _ = jh.join();
    }
}
<|endoftext|>