<commit_before>extern crate config;
use self::config::types::{Config, ScalarValue, Value};

use std::env::home_dir;
use std::process::Command;

fn expand_home(path: &String) -> String {
    if path.starts_with("~/") {
        match home_dir() {
            Some(home) => format!("{}/{}", home.display(), &path[2..]),
            _ => format!("{}", path)
        }
    } else {
        format!("{}", path)
    }
}

fn make_command_vec(vec: &Vec<Value>) -> Result<Command, String> {
    if vec.is_empty() {
        return Err(format!("empty execution vector"));
    }

    let mut prog_args = vec![];
    for v in vec {
        match v {
            &Value::Svalue(ref sv) => {
                match sv {
                    &ScalarValue::Str(ref s) => prog_args.push(s),
                    _ => {
                        return Err(format!("non-string program value"));
                    }
                }
            },
            _ => {
                return Err(format!("non-string program value"));
            }
        }
    }

    let (prog, args) = prog_args.split_at(1);
    let mut cmd = Command::new(expand_home(prog[0]));
    cmd.args(args);

    Ok(cmd)
}

fn make_command_str(string: &String) -> Result<Command, String> {
    if string.is_empty() {
        Err(format!("empty execution string"))
    } else {
        Ok(Command::new(expand_home(string)))
    }
}

pub fn run_config_program(conf: &Config, path: &str) -> Result<(), String> {
    let val = conf.lookup(path);
    if val.is_none() {
        return Ok(());
    }

    let cmd = try!(match val.unwrap() {
        &Value::Array(ref a) => make_command_vec(a),
        &Value::Svalue(ref sv) => {
            match sv {
                &ScalarValue::Str(ref s) => make_command_str(s),
                _ => Err(format!("unsupported type for {}", path))
            }
        },
        _ => Err(format!("unsupported type for {}", path))
    }).output();

    match cmd {
        Ok(output) => {
            if output.status.success() {
                Ok(())
            } else {
                Err(format!("failed to execute process ({:?}):\noutput:\n{}\nerror:{}",
                            output.status.code(),
                            String::from_utf8_lossy(&output.stdout),
                            String::from_utf8_lossy(&output.stderr)))
            }
        },
        _ => Err(format!("failed to execute process"))
    }
}
<commit_msg>exec: use a.clone() rather than format!("{}", a)<commit_after>extern crate config;
use self::config::types::{Config, ScalarValue, Value};

use std::env::home_dir;
use std::process::Command;

fn expand_home(path: &String) -> String {
    if path.starts_with("~/") {
        match home_dir() {
            Some(home) => format!("{}/{}", home.display(), &path[2..]),
            _ => path.clone()
        }
    } else {
        path.clone()
    }
}

fn make_command_vec(vec: &Vec<Value>) -> Result<Command, String> {
    if vec.is_empty() {
        return Err(format!("empty execution vector"));
    }

    let mut prog_args = vec![];
    for v in vec {
        match v {
            &Value::Svalue(ref sv) => {
                match sv {
                    &ScalarValue::Str(ref s) => prog_args.push(s),
                    _ => {
                        return Err(format!("non-string program value"));
                    }
                }
            },
            _ => {
                return Err(format!("non-string program value"));
            }
        }
    }

    let (prog, args) = prog_args.split_at(1);
    let mut cmd = Command::new(expand_home(prog[0]));
    cmd.args(args);

    Ok(cmd)
}

fn make_command_str(string: &String) -> Result<Command, String> {
    if string.is_empty() {
        Err(format!("empty execution string"))
    } else {
        Ok(Command::new(expand_home(string)))
    }
}

pub fn run_config_program(conf: &Config, path: &str) -> Result<(), String> {
    let val = conf.lookup(path);
    if val.is_none() {
        return Ok(());
    }

    let cmd = try!(match val.unwrap() {
        &Value::Array(ref a) => make_command_vec(a),
        &Value::Svalue(ref sv) => {
            match sv {
                &ScalarValue::Str(ref s) => make_command_str(s),
                _ => Err(format!("unsupported type for {}", path))
            }
        },
        _ => Err(format!("unsupported type for {}", path))
    }).output();

    match cmd {
        Ok(output) => {
            if output.status.success() {
                Ok(())
            } else {
                Err(format!("failed to execute process ({:?}):\noutput:\n{}\nerror:{}",
                            output.status.code(),
                            String::from_utf8_lossy(&output.stdout),
                            String::from_utf8_lossy(&output.stderr)))
            }
        },
        _ => Err(format!("failed to execute process"))
    }
}
<|endoftext|>


<commit_before>use std::sync::mpsc;
use std::thread;
use std::path::PathBuf;
use std::fs::{File, OpenOptions};
use std::io::{Seek, SeekFrom, Write, Read};

pub struct Writer {
    thread: thread::JoinHandle<()>,
    tx: mpsc::SyncSender<WriteMsg>,
}

pub struct Reader {
    pub rx: mpsc::Receiver<ReadMsg>,
}

pub enum WriteMsg {
    Seek(SeekFrom),
    Write(Vec<u8>),
    Finish,
}

pub enum ReadMsg {
    Read(Vec<u8>),
    Finish,
    Error,
}

impl Writer {
    pub fn new(filename: PathBuf) -> Writer {
        let (tx, rx) = mpsc::sync_channel(1024);
        let builder = thread::Builder::new().name("file_writer".into());
        let t = builder.spawn(move || {
            let mut f = OpenOptions::new()
                .write(true)
                .create(true)
                .truncate(false)
                .open(filename)
                .unwrap();

            loop {
                match rx.recv().unwrap() {
                    WriteMsg::Seek(from) => {
                        f.seek(from).unwrap();
                    }
                    WriteMsg::Write(buf) => {
                        f.write_all(&buf[..]).unwrap();
                    }
                    WriteMsg::Finish => {
                        break;
                    }
                }
            }
        }).unwrap();
        Writer {
            thread: t,
            tx: tx,
        }
    }

    pub fn seek(&self, from: SeekFrom) {
        self.tx.send(WriteMsg::Seek(from)).unwrap();
    }

    pub fn write_all(&self, buf: Vec<u8>) {
        self.tx.send(WriteMsg::Write(buf)).unwrap();
    }

    pub fn close(self) {
        self.tx.send(WriteMsg::Finish).unwrap_or_else(|e| error!("{:?}", e));
        if let Err(e) = self.thread.join() {
            error!("\n\n{:?}\n\n", e);
        }
    }
}

impl Reader {
    pub fn new(filename: String) -> Reader {
        let (tx, rx) = mpsc::sync_channel(1024);
        let builder = thread::Builder::new().name("file_reader".into());
        let _ = builder.spawn(move || {
            let mut f = File::open(filename).unwrap();
            let mut payload = vec![0; 1350];
            f.seek(SeekFrom::Start(0)).unwrap();
            loop {
                match f.read(&mut payload) {
                    Ok(0) => {
                        tx.send(ReadMsg::Finish).unwrap();
                        break;
                    }
                    Ok(read) => {
                        let mut owned = Vec::with_capacity(read);
                        owned.extend_from_slice(&payload[..read]);
                        tx.send(ReadMsg::Read(owned)).unwrap();
                    }
                    Err(_) => {
                        tx.send(ReadMsg::Error).unwrap();
                        panic!("ruh roh");
                    }
                }
            }
        });

        Reader {
            rx: rx,
        }
    }
}

<commit_msg>make file i/o buffers more like 10mb than 1mb<commit_after>use std::sync::mpsc;
use std::thread;
use std::path::PathBuf;
use std::fs::{File, OpenOptions};
use std::io::{Seek, SeekFrom, Write, Read};

pub struct Writer {
    thread: thread::JoinHandle<()>,
    tx: mpsc::SyncSender<WriteMsg>,
}

pub struct Reader {
    pub rx: mpsc::Receiver<ReadMsg>,
}

pub enum WriteMsg {
    Seek(SeekFrom),
    Write(Vec<u8>),
    Finish,
}

pub enum ReadMsg {
    Read(Vec<u8>),
    Finish,
    Error,
}

impl Writer {
    pub fn new(filename: PathBuf) -> Writer {
        let (tx, rx) = mpsc::sync_channel(1024*10);
        let builder = thread::Builder::new().name("file_writer".into());
        let t = builder.spawn(move || {
            let mut f = OpenOptions::new()
                .write(true)
                .create(true)
                .truncate(false)
                .open(filename)
                .unwrap();

            loop {
                match rx.recv().unwrap() {
                    WriteMsg::Seek(from) => {
                        f.seek(from).unwrap();
                    }
                    WriteMsg::Write(buf) => {
                        f.write_all(&buf[..]).unwrap();
                    }
                    WriteMsg::Finish => {
                        break;
                    }
                }
            }
        }).unwrap();
        Writer {
            thread: t,
            tx: tx,
        }
    }

    pub fn seek(&self, from: SeekFrom) {
        self.tx.send(WriteMsg::Seek(from)).unwrap();
    }

    pub fn write_all(&self, buf: Vec<u8>) {
        self.tx.send(WriteMsg::Write(buf)).unwrap();
    }

    pub fn close(self) {
        self.tx.send(WriteMsg::Finish).unwrap_or_else(|e| error!("{:?}", e));
        if let Err(e) = self.thread.join() {
            error!("\n\n{:?}\n\n", e);
        }
    }
}

impl Reader {
    pub fn new(filename: String) -> Reader {
        let (tx, rx) = mpsc::sync_channel(1024*10);
        let builder = thread::Builder::new().name("file_reader".into());
        let _ = builder.spawn(move || {
            let mut f = File::open(filename).unwrap();
            let mut payload = vec![0; 1350];
            f.seek(SeekFrom::Start(0)).unwrap();
            loop {
                match f.read(&mut payload) {
                    Ok(0) => {
                        tx.send(ReadMsg::Finish).unwrap();
                        break;
                    }
                    Ok(read) => {
                        let mut owned = Vec::with_capacity(read);
                        owned.extend_from_slice(&payload[..read]);
                        tx.send(ReadMsg::Read(owned)).unwrap();
                    }
                    Err(_) => {
                        tx.send(ReadMsg::Error).unwrap();
                        panic!("ruh roh");
                    }
                }
            }
        });

        Reader {
            rx: rx,
        }
    }
}

<|endoftext|>


<commit_before>//! GC heap allocator.

use std::cell::RefCell;
use std::collections::HashMap;
use std::marker::PhantomData;
use std::{fmt, mem, ptr};
use bit_vec::BitVec;

// What does this do? You'll never guess!
type HeapId<'a> = PhantomData<::std::cell::Cell<&'a mut ()>>;

/// Total number of Pair objects that can be allocated in a Heap at once.
///
/// XXX BOGUS: At present, this is number is carefully selected (with insider
/// knowledge of both `size_of::<PairStorage>()` on my platform and the `Box`
/// allocator's behavior) so that a HeapStorage object fits in a page and thus
/// the assertions below about HEAP_STORAGE_ALIGN pass.
pub const HEAP_SIZE: usize = 125;

/// We rely on all bits to the right of this bit being 0 in addresses of
/// HeapStorage instances.
const HEAP_STORAGE_ALIGN: usize = 0x1000;

// The heap is (for now) just a big array of Pairs
struct HeapStorage<'a> {
    mark_bits: BitVec,
    objects: [PairStorage<'a>; HEAP_SIZE]
}

impl<'a> HeapStorage<'a> {
    unsafe fn new() -> HeapStorage<'a> {
        HeapStorage {
            mark_bits: BitVec::from_elem(HEAP_SIZE, false),
            objects: mem::uninitialized()
        }
    }
}

pub struct Heap<'a> {
    id: HeapId<'a>,
    storage: Box<HeapStorage<'a>>,
    freelist: *mut PairStorage<'a>,
    pins: RefCell<HashMap<*mut PairStorage<'a>, usize>>
}

/// Create a heap, pass it to a callback, then destroy the heap.
///
/// The heap's lifetime is directly tied to this function call, for safety. (So
/// the API is a little wonky --- but how many heaps were you planning on
/// creating?)
pub fn with_heap<F, O>(f: F) -> O
    where F: for<'a> FnOnce(&mut Heap<'a>) -> O
{
    f(&mut Heap::new())
}

/// Trait implemented by all types that can be stored directly in the GC heap:
/// the `Storage` types associated with any `HeapInline` or `HeapRef` type.
///
/// XXX maybe this should not be its own trait - fold into HeapInline?
///
pub unsafe trait Mark<'a> {
    unsafe fn mark(ptr: *mut Self);
}

/// Trait implemented by all types that can be stored in fields of structs (or,
/// eventually, elements of GCVecs) that are stored in the GC heap.
pub unsafe trait HeapInline<'a> {
    /// The type of the value when it is physically stored in the heap.
    type Storage;

    /// Extract the value from the heap. Do not under any circumstances call
    /// this.  It is for macro-generated code to call; it is impossible for
    /// ordinary users to call this safely, because `ptr` must be a direct,
    /// unwrapped reference to a value stored in the GC heap, which ordinary
    /// users cannot obtain.
    ///
    /// This turns any raw pointers in the `Storage` value into safe
    /// references, so while it's a dangerous function, the result of a correct
    /// call can be safely handed out to user code.
    ///
    unsafe fn from_heap(heap: &Heap<'a>, ptr: &Self::Storage) -> Self;

    /// Convert the value to the form it should have in the heap.
    /// This is for macro-generated code to call.
    fn to_heap(self) -> Self::Storage;
}

impl<'a> Heap<'a> {
    fn new() -> Heap<'a> {
        let mut h = Heap {
            id: PhantomData,
            storage: Box::new(unsafe { HeapStorage::new() }),
            freelist: ptr::null_mut(),
            pins: RefCell::new(HashMap::new())
        };

        // These assertions will likely fail on 32-bit platforms or if someone
        // is somehow using a custom Box allocator. If either one fails, this
        // GC will not work.
        assert_eq!(&mut *h.storage as *mut HeapStorage<'a> as usize & (HEAP_STORAGE_ALIGN - 1), 0);
        assert!(mem::size_of::<HeapStorage<'a>>() <= HEAP_STORAGE_ALIGN);

        for i in 0 .. HEAP_SIZE {
            let p = &mut h.storage.objects[i] as *mut PairStorage<'a>;
            unsafe {
                h.add_to_free_list(p);
            }
        }
        h
    }

    fn pin(&self, p: *mut PairStorage<'a>) {
        let mut pins = self.pins.borrow_mut();
        let entry = pins.entry(p).or_insert(0);
        *entry += 1;
    }

    fn unpin(&self, p: *mut PairStorage<'a>) {
        let mut pins = self.pins.borrow_mut();
        if {
            let entry = pins.entry(p).or_insert(0);
            assert!(*entry != 0);
            *entry -= 1;
            *entry == 0
        } {
            pins.remove(&p);
        }
    }

    unsafe fn add_to_free_list(&mut self, p: *mut PairStorage<'a>) {
        let listp = p as *mut *mut PairStorage<'a>;
        *listp = self.freelist;
        assert_eq!(*listp, self.freelist);
        self.freelist = p;
    }

    pub fn try_alloc(&mut self, pair: (Value<'a>, Value<'a>)) -> Option<Pair<'a>> {
        if self.freelist.is_null() {
            unsafe {
                self.gc();
            }
            if self.freelist.is_null() {
                return None;
            }
        }

        let p = self.freelist;
        unsafe {
            let listp = p as *mut *mut PairStorage<'a>;
            self.freelist = *listp;

            let (h, t) = pair;
            *p = PairStorage {
                head: h.to_heap(),
                tail: t.to_heap()
            };
            Some(Pair(PinnedRef::new(self, p)))
        }
    }

    unsafe fn find_mark_bit<T>(_ptr: *const T) -> (*mut BitVec, usize) {
        assert_eq!(mem::size_of::<T>(), mem::size_of::<PairStorage<'a>>());
        let storage_addr = _ptr as usize & !(HEAP_STORAGE_ALIGN - 1);
        let storage = storage_addr as *mut HeapStorage<'a>;
        let objects_addr = &mut (*storage).objects[0] as *mut PairStorage<'a> as usize;
        let index = (_ptr as usize - objects_addr) / mem::size_of::<PairStorage<'a>>();
        (&mut (*storage).mark_bits as *mut BitVec, index)
    }

    pub unsafe fn get_mark_bit<T>(_ptr: *const T) -> bool {
        let (bits, index) = Heap::find_mark_bit(_ptr);
        (*bits)[index]
    }

    pub unsafe fn set_mark_bit<T>(_ptr: *const T) {
        let (bits, index) = Heap::find_mark_bit(_ptr);
        (*bits).set(index, true);
    }

    pub fn alloc(&mut self, pair: (Value<'a>, Value<'a>)) -> Pair<'a> {
        self.try_alloc(pair).expect("out of memory (gc did not collect anything)")
    }

    pub fn alloc_null(&mut self) -> Pair<'a> {
        self.alloc((Value::Null, Value::Null))
    }

    unsafe fn gc(&mut self) {
        // mark phase
        self.storage.mark_bits.clear();
        for (&p, _) in self.pins.borrow().iter() {
            Mark::mark(p);
        }

        // sweep phase
        self.freelist = ptr::null_mut();
        for i in 0 .. HEAP_SIZE {
            let p = &mut self.storage.objects[i] as *mut PairStorage<'a>;
            if !self.storage.mark_bits[i] {
                self.add_to_free_list(p);
            }
        }
    }

    #[cfg(test)]
    pub fn force_gc(&mut self) {
        unsafe { self.gc(); }
    }
}

pub struct PinnedRef<'a, T> {
    ptr: *mut T,
    heap: *const Heap<'a>,
    heap_id: HeapId<'a>
}

impl<'a, T> PinnedRef<'a, T> {
    unsafe fn new(heap: &Heap<'a>, p: *mut T) -> PinnedRef<'a, T> {
        heap.pin(p as *mut PairStorage<'a>);  // XXX BOGUS
        PinnedRef {
            ptr: p,
            heap: heap as *const Heap<'a>,
            heap_id: heap.id
        }
    }
}

impl<'a, T> Drop for PinnedRef<'a, T> {
    fn drop(&mut self) {
        unsafe {
            (*self.heap).unpin(self.ptr as *mut PairStorage<'a>);  // XXX BOGUS
        }
    }
}

impl<'a, T> Clone for PinnedRef<'a, T> {
    fn clone(&self) -> PinnedRef<'a, T> {
        let &PinnedRef { ptr, heap, heap_id } = self;
        unsafe {
            (*heap).pin(ptr as *mut PairStorage<'a>);  // XXX BOGUS
        }
        PinnedRef {
            ptr: ptr,
            heap: heap,
            heap_id: heap_id
        }
    }
}

impl<'a, T> fmt::Debug for PinnedRef<'a, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "PinnedRef {{ ptr: {:p} }}", self.ptr)
    }
}

impl<'a, T> PartialEq for PinnedRef<'a, T> {
    fn eq(&self, other: &PinnedRef<'a, T>) -> bool {
        self.ptr == other.ptr
    }
}

impl<'a, T> Eq for PinnedRef<'a, T> {}

pub trait GCRef {
    #[cfg(test)]
    fn address(&self) -> usize;
}

// === Pair, the reference type

gc_ref_type! {
    pub struct Pair / PairStorage<'a> {
        head / set_head: Value<'a>,
        tail / set_tail: Value<'a>
    }
}

// === Values (a heap-inline enum)

use std::rc::Rc;

// Values inside the heap (GC heap-to-heap cross-references) (private)
enum ValueStorage<'a> {
    Null,
    Int(i32),
    Str(Rc<String>),
    Pair(*mut PairStorage<'a>)
}

unsafe impl<'a> Mark<'a> for ValueStorage<'a> {
    unsafe fn mark(ptr: *mut ValueStorage<'a>) {
        match *ptr {
            ValueStorage::Pair(p) => Mark::mark(p),
            _ => {}
        }
    }
}

#[derive(Debug, Clone, PartialEq)]
pub enum Value<'a> {
    Null,
    Int(i32),
    Str(Rc<String>),  // <-- equality is by value
    Pair(Pair<'a>)  // <-- equality is by pointer
}

unsafe impl<'a> HeapInline<'a> for Value<'a> {
    type Storage = ValueStorage<'a>;

    fn to_heap(self) -> ValueStorage<'a> {
        match self {
            Value::Null => ValueStorage::Null,
            Value::Int(n) => ValueStorage::Int(n),
            Value::Str(rcstr) => ValueStorage::Str(rcstr),
            Value::Pair(pair) => ValueStorage::Pair(HeapInline::<'a>::to_heap(pair))
        }
    }

    unsafe fn from_heap(heap: &Heap<'a>, v: &ValueStorage<'a>) -> Value<'a> {
        match v {
            &ValueStorage::Null => Value::Null,
            &ValueStorage::Int(n) => Value::Int(n),
            &ValueStorage::Str(ref rcstr) => Value::Str(rcstr.clone()),
            &ValueStorage::Pair(ref ptr) => Value::Pair(HeapInline::<'a>::from_heap(heap, ptr))
        }
    }
}

unsafe impl<'a, T: Copy + 'static> Mark<'a> for T {
    unsafe fn mark(_ptr: *mut T) {}
}

unsafe impl<'a, T: Copy + 'static> HeapInline<'a> for T {
    type Storage = Self;

    fn to_heap(self) -> T { self }

    unsafe fn from_heap(_heap: &Heap<'a>, v: &T) -> T { *v }
}
<commit_msg>Add "mark entry point" functions.<commit_after>//! GC heap allocator.

use std::cell::RefCell;
use std::collections::HashMap;
use std::marker::PhantomData;
use std::{fmt, mem, ptr};
use bit_vec::BitVec;

// What does this do? You'll never guess!
type HeapId<'a> = PhantomData<::std::cell::Cell<&'a mut ()>>;

/// Total number of Pair objects that can be allocated in a Heap at once.
///
/// XXX BOGUS: At present, this is number is carefully selected (with insider
/// knowledge of both `size_of::<PairStorage>()` on my platform and the `Box`
/// allocator's behavior) so that a HeapStorage object fits in a page and thus
/// the assertions below about HEAP_STORAGE_ALIGN pass.
pub const HEAP_SIZE: usize = 125;

/// We rely on all bits to the right of this bit being 0 in addresses of
/// HeapStorage instances.
const HEAP_STORAGE_ALIGN: usize = 0x1000;

// The heap is (for now) just a big array of Pairs
struct HeapStorage<'a> {
    mark_bits: BitVec,
    mark_entry_point: unsafe fn(*mut ()),
    objects: [PairStorage<'a>; HEAP_SIZE]
}

impl<'a> HeapStorage<'a> {
    unsafe fn new() -> HeapStorage<'a> {
        HeapStorage {
            mark_bits: BitVec::from_elem(HEAP_SIZE, false),
            mark_entry_point: mark_entry_point::<PairStorage>,
            objects: mem::uninitialized()
        }
    }
}

pub struct Heap<'a> {
    id: HeapId<'a>,
    storage: Box<HeapStorage<'a>>,
    freelist: *mut PairStorage<'a>,
    pins: RefCell<HashMap<*mut (), usize>>
}

/// Create a heap, pass it to a callback, then destroy the heap.
///
/// The heap's lifetime is directly tied to this function call, for safety. (So
/// the API is a little wonky --- but how many heaps were you planning on
/// creating?)
pub fn with_heap<F, O>(f: F) -> O
    where F: for<'a> FnOnce(&mut Heap<'a>) -> O
{
    f(&mut Heap::new())
}

/// Trait implemented by all types that can be stored directly in the GC heap:
/// the `Storage` types associated with any `HeapInline` or `HeapRef` type.
///
/// XXX maybe this should not be its own trait - fold into HeapInline?
///
pub unsafe trait Mark<'a> {
    unsafe fn mark(ptr: *mut Self);
}

/// Non-inlined function that serves as an entry point to marking. This is used
/// for marking root set entries.
unsafe fn mark_entry_point<'a, T: Mark<'a>>(addr: *mut ()) {
    Mark::mark(addr as *mut T);
}

/// Trait implemented by all types that can be stored in fields of structs (or,
/// eventually, elements of GCVecs) that are stored in the GC heap.
pub unsafe trait HeapInline<'a> {
    /// The type of the value when it is physically stored in the heap.
    type Storage;

    /// Extract the value from the heap. Do not under any circumstances call
    /// this.  It is for macro-generated code to call; it is impossible for
    /// ordinary users to call this safely, because `ptr` must be a direct,
    /// unwrapped reference to a value stored in the GC heap, which ordinary
    /// users cannot obtain.
    ///
    /// This turns any raw pointers in the `Storage` value into safe
    /// references, so while it's a dangerous function, the result of a correct
    /// call can be safely handed out to user code.
    ///
    unsafe fn from_heap(heap: &Heap<'a>, ptr: &Self::Storage) -> Self;

    /// Convert the value to the form it should have in the heap.
    /// This is for macro-generated code to call.
    fn to_heap(self) -> Self::Storage;
}

impl<'a> Heap<'a> {
    fn new() -> Heap<'a> {
        let mut h = Heap {
            id: PhantomData,
            storage: Box::new(unsafe { HeapStorage::new() }),
            freelist: ptr::null_mut(),
            pins: RefCell::new(HashMap::new())
        };

        // These assertions will likely fail on 32-bit platforms or if someone
        // is somehow using a custom Box allocator. If either one fails, this
        // GC will not work.
        assert_eq!(&mut *h.storage as *mut HeapStorage<'a> as usize & (HEAP_STORAGE_ALIGN - 1), 0);
        assert!(mem::size_of::<HeapStorage<'a>>() <= HEAP_STORAGE_ALIGN);

        for i in 0 .. HEAP_SIZE {
            let p = &mut h.storage.objects[i] as *mut PairStorage<'a>;
            unsafe {
                h.add_to_free_list(p);
            }
        }
        h
    }

    /// Add the object `*p` to the root set, protecting it from GC.
    ///
    /// An object that has been pinned *n* times stays in the root set
    /// until it has been unpinned *n* times.
    ///
    /// (Unsafe because if the argument is garbage, a later GC will
    /// crash. Called only from `impl PinnedRef`.)
    unsafe fn pin<T: Mark<'a>>(&self, p: *mut T) {
        let p = p as *mut ();
        let mut pins = self.pins.borrow_mut();
        let entry = pins.entry(p).or_insert(0);
        *entry += 1;
    }

    /// Unpin an object (see `pin`).
    ///
    /// (Unsafe because unpinning an object that other code is still using
    /// causes dangling pointers. Called only from `impl PinnedRef`.)
    unsafe fn unpin<T: Mark<'a>>(&self, p: *mut T) {
        let p = p as *mut ();
        let mut pins = self.pins.borrow_mut();
        if {
            let entry = pins.entry(p as *mut ()).or_insert(0);
            assert!(*entry != 0);
            *entry -= 1;
            *entry == 0
        } {
            pins.remove(&p);
        }
    }

    unsafe fn add_to_free_list(&mut self, p: *mut PairStorage<'a>) {
        let listp = p as *mut *mut PairStorage<'a>;
        *listp = self.freelist;
        assert_eq!(*listp, self.freelist);
        self.freelist = p;
    }

    pub fn try_alloc(&mut self, pair: (Value<'a>, Value<'a>)) -> Option<Pair<'a>> {
        if self.freelist.is_null() {
            unsafe {
                self.gc();
            }
            if self.freelist.is_null() {
                return None;
            }
        }

        let p = self.freelist;
        unsafe {
            let listp = p as *mut *mut PairStorage<'a>;
            self.freelist = *listp;

            let (h, t) = pair;
            *p = PairStorage {
                head: h.to_heap(),
                tail: t.to_heap()
            };
            Some(Pair(PinnedRef::new(self, p)))
        }
    }

    unsafe fn find_header<T>(_ptr: *const T) -> *mut HeapStorage<'a> {
        let storage_addr = _ptr as usize & !(HEAP_STORAGE_ALIGN - 1);
        storage_addr as *mut HeapStorage<'a>
    }

    unsafe fn find_mark_bit<T>(_ptr: *const T) -> (*mut BitVec, usize) {
        assert_eq!(mem::size_of::<T>(), mem::size_of::<PairStorage<'a>>());
        let storage = Heap::find_header(_ptr);
        let objects_addr = &mut (*storage).objects[0] as *mut PairStorage<'a> as usize;
        let index = (_ptr as usize - objects_addr) / mem::size_of::<PairStorage<'a>>();
        (&mut (*storage).mark_bits as *mut BitVec, index)
    }

    pub unsafe fn get_mark_bit<T>(_ptr: *const T) -> bool {
        let (bits, index) = Heap::find_mark_bit(_ptr);
        (*bits)[index]
    }

    pub unsafe fn set_mark_bit<T>(_ptr: *const T) {
        let (bits, index) = Heap::find_mark_bit(_ptr);
        (*bits).set(index, true);
    }

    pub fn alloc(&mut self, pair: (Value<'a>, Value<'a>)) -> Pair<'a> {
        self.try_alloc(pair).expect("out of memory (gc did not collect anything)")
    }

    pub fn alloc_null(&mut self) -> Pair<'a> {
        self.alloc((Value::Null, Value::Null))
    }

    unsafe fn mark(ptr: *mut ()) {
        let storage = Heap::find_header(ptr);
        let mark_fn = (*storage).mark_entry_point;
        mark_fn(ptr);
    }

    unsafe fn gc(&mut self) {
        // mark phase
        self.storage.mark_bits.clear();
        for (&p, _) in self.pins.borrow().iter() {
            Heap::mark(p);
        }

        // sweep phase
        self.freelist = ptr::null_mut();
        for i in 0 .. HEAP_SIZE {
            let p = &mut self.storage.objects[i] as *mut PairStorage<'a>;
            if !self.storage.mark_bits[i] {
                self.add_to_free_list(p);
            }
        }
    }

    #[cfg(test)]
    pub fn force_gc(&mut self) {
        unsafe { self.gc(); }
    }
}

pub struct PinnedRef<'a, T> {
    ptr: *mut T,
    heap: *const Heap<'a>,
    heap_id: HeapId<'a>
}

impl<'a, T> PinnedRef<'a, T> {
    unsafe fn new(heap: &Heap<'a>, p: *mut T) -> PinnedRef<'a, T> {
        heap.pin(p as *mut PairStorage<'a>);  // XXX BOGUS
        PinnedRef {
            ptr: p,
            heap: heap as *const Heap<'a>,
            heap_id: heap.id
        }
    }
}

impl<'a, T> Drop for PinnedRef<'a, T> {
    fn drop(&mut self) {
        unsafe {
            (*self.heap).unpin(self.ptr as *mut PairStorage<'a>);  // XXX BOGUS
        }
    }
}

impl<'a, T> Clone for PinnedRef<'a, T> {
    fn clone(&self) -> PinnedRef<'a, T> {
        let &PinnedRef { ptr, heap, heap_id } = self;
        unsafe {
            (*heap).pin(ptr as *mut PairStorage<'a>);  // XXX BOGUS
        }
        PinnedRef {
            ptr: ptr,
            heap: heap,
            heap_id: heap_id
        }
    }
}

impl<'a, T> fmt::Debug for PinnedRef<'a, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "PinnedRef {{ ptr: {:p} }}", self.ptr)
    }
}

impl<'a, T> PartialEq for PinnedRef<'a, T> {
    fn eq(&self, other: &PinnedRef<'a, T>) -> bool {
        self.ptr == other.ptr
    }
}

impl<'a, T> Eq for PinnedRef<'a, T> {}

pub trait GCRef {
    #[cfg(test)]
    fn address(&self) -> usize;
}

// === Pair, the reference type

gc_ref_type! {
    pub struct Pair / PairStorage<'a> {
        head / set_head: Value<'a>,
        tail / set_tail: Value<'a>
    }
}

// === Values (a heap-inline enum)

use std::rc::Rc;

// Values inside the heap (GC heap-to-heap cross-references) (private)
enum ValueStorage<'a> {
    Null,
    Int(i32),
    Str(Rc<String>),
    Pair(*mut PairStorage<'a>)
}

unsafe impl<'a> Mark<'a> for ValueStorage<'a> {
    unsafe fn mark(ptr: *mut ValueStorage<'a>) {
        match *ptr {
            ValueStorage::Pair(p) => Mark::mark(p),
            _ => {}
        }
    }
}

#[derive(Debug, Clone, PartialEq)]
pub enum Value<'a> {
    Null,
    Int(i32),
    Str(Rc<String>),  // <-- equality is by value
    Pair(Pair<'a>)  // <-- equality is by pointer
}

unsafe impl<'a> HeapInline<'a> for Value<'a> {
    type Storage = ValueStorage<'a>;

    fn to_heap(self) -> ValueStorage<'a> {
        match self {
            Value::Null => ValueStorage::Null,
            Value::Int(n) => ValueStorage::Int(n),
            Value::Str(rcstr) => ValueStorage::Str(rcstr),
            Value::Pair(pair) => ValueStorage::Pair(HeapInline::<'a>::to_heap(pair))
        }
    }

    unsafe fn from_heap(heap: &Heap<'a>, v: &ValueStorage<'a>) -> Value<'a> {
        match v {
            &ValueStorage::Null => Value::Null,
            &ValueStorage::Int(n) => Value::Int(n),
            &ValueStorage::Str(ref rcstr) => Value::Str(rcstr.clone()),
            &ValueStorage::Pair(ref ptr) => Value::Pair(HeapInline::<'a>::from_heap(heap, ptr))
        }
    }
}

unsafe impl<'a, T: Copy + 'static> Mark<'a> for T {
    unsafe fn mark(_ptr: *mut T) {}
}

unsafe impl<'a, T: Copy + 'static> HeapInline<'a> for T {
    type Storage = Self;

    fn to_heap(self) -> T { self }

    unsafe fn from_heap(_heap: &Heap<'a>, v: &T) -> T { *v }
}
<|endoftext|>


<commit_before>// http://rosettacode.org/wiki/HTTP
use std::io::net::tcp::TcpStream;
use std::io::IoResult;

fn get_index(target: &str) -> IoResult<String> {
    // Create a socket. Mutable so we can write to it.
    let mut socket = TcpStream::connect(target, 80);
    // Write to the socket as bytes.
    // try! and write! are useful macros when working with writers.
    try!(write!(socket, "GET / HTTP/1.1\nHost: {}\n\n", target));
    // Read any response.
    socket.read_to_string()
}

#[cfg(not(test))]
fn main() {
    let target = std::os::args().pop().unwrap();
    println!("Making the request... This might take a minute.");
    match get_index(target.as_slice()) {
        Ok(out) => println!("{}", out),
        Err(e) => println!("Error: {}", e)
    }
}

#[test]
fn test_request() {
    let target = "rust-lang.org";
    match get_index(target) {
        Ok(_) => (),
        Err(e) => println!("Error: {}", e)
    }
}
<commit_msg>http: Hint for the server to kill the connection after responding.<commit_after>// http://rosettacode.org/wiki/HTTP
use std::io::net::tcp::TcpStream;
use std::io::IoResult;

fn get_index(target: &str) -> IoResult<String> {
    // Create a socket. Mutable so we can write to it.
    let mut socket = TcpStream::connect(target, 80);
    // Write to the socket as bytes.
    // try! and write! are useful macros when working with writers.
    // We send the `Connection: close` header so the server closes the connection
    // after sending its response. This allows us to use `read_to_string()` which
    // reads until EOF. Alternatively, we could use HTTP/1.0. In the future, this
    // will be handled by a HTTP library.
    try!(write!(socket, "GET / HTTP/1.1\nHost: {}\nConnection: close\n\n", target));
    // Read any response.
    socket.read_to_string()
}

#[cfg(not(test))]
fn main() {
    let target = std::os::args().pop().unwrap();
    println!("Making the request... This might take a minute.");
    match get_index(target.as_slice()) {
        Ok(out) => println!("{}", out),
        Err(e) => println!("Error: {}", e)
    }
}

#[test]
fn test_request() {
    let target = "rust-lang.org";
    match get_index(target) {
        Ok(_) => (),
        Err(e) => fail!("Error: {}", e),
    }
}
<|endoftext|>


<commit_before>use super::game_manager::GameManager;
use super::libcoinche::{bid,cards};

use std::sync::Arc;
use std::str::FromStr;

use rustc_serialize::json;

use iron;
use iron::prelude::*;
use bodyparser;

pub struct Server {
    port: u16,
    manager: Arc<GameManager>,
}

struct Router { manager: Arc<GameManager> }

#[derive(RustcEncodable)]
struct HelpAction {
    href: &'static str,
    method: &'static str,
    help: &'static str,
}

#[derive(RustcEncodable)]
struct HelpMessage {
    title: &'static str,
    actions: Vec<HelpAction>,
}

fn help_message() -> String {

    json::encode(&HelpMessage {
        title: "Help Page",
        actions: vec![
            HelpAction {
                href: "/join",
                method: "POST",
                help: "Join a new game.",
            },
            HelpAction {
                href: "/pass/[PLAYER_ID]",
                method: "POST",
                help: "Pass during auction.",
            },
            HelpAction {
                href: "/coinche/[PLAYER_ID]",
                method: "POST",
                help: "Coinche the opponent's bid during auction.",
            },
            HelpAction {
                href: "/bid/[PLAYER_ID]",
                method: "POST",
                help: "Bid a contract during auction.",
            },
            HelpAction {
                href: "/play/[PLAYER_ID]",
                method: "POST",
                help: "Play a card.",
            },
            HelpAction {
                href: "/hand/[PLAYER_ID]",
                method: "GET",
                help: "Checks the current hand.",
            },
            HelpAction {
                href: "/trick/[PLAYER_ID]",
                method: "GET",
                help: "Checks the current trick.",
            },
            HelpAction {
                href: "/last_trick/[PLAYER_ID]",
                method: "GET",
                help: "Checks the last complete trick.",
            },
            HelpAction {
                href: "/scores/[PLAYER_ID]",
                method: "GET",
                help: "Get the current scores.",
            },
            HelpAction {
                href: "/pos/[PLAYER_ID]",
                method: "GET",
                help: "Get the player's position on the table.",
            },
            HelpAction {
                href: "/wait/[PLAYER_ID]/[EVENT_ID]",
                method: "GET",
                help: "Wait until the next event, or return it if it already happened.",
            },
        ]
    }).unwrap()
}

fn help_resp() -> IronResult<Response> {
    let content_type: iron::mime::Mime = "application/json".parse::<iron::mime::Mime>().unwrap();
    return Ok(Response::with((content_type,
                              iron::status::NotFound,
                              help_message())));
}

fn err_resp(msg: &str) -> IronResult<Response> {
    let content_type: iron::mime::Mime = "application/json".parse::<iron::mime::Mime>().unwrap();

    #[derive(RustcEncodable)]
    struct Error<'a>{
        error: &'a str,
    }

    return Ok(Response::with((content_type,
                              iron::status::Ok,
                              json::encode(&Error { error: msg }).unwrap(),
                              )));
}

macro_rules! parse_id {
    ( $name:expr, $value:expr ) => {
        {
            match u32::from_str($value) {
                Ok(id) => id,
                Err(e) => return err_resp(&format!("invalid {} ID: `{}` ({})", $name, $value, e)),
            }
        }
    };
}

macro_rules! check_len {
    ( $path:expr, 1 ) => {
        {
            if $path.len() != 1 {
                return err_resp(&format!("incorrect parameters (Usage: /{})", $path[0]));
            }
        }
    };
    ( $path:expr, 2 ) => {
        {
            if $path.len() != 2 {
                return err_resp(&format!("incorrect parameters (Usage: /{}/[PID])", $path[0]));
            }
        }
    };
    ( $path:expr, 3 ) => {
        {
            if $path.len() != 3 {
                return err_resp(&format!("incorrect parameters (Usage: /{}/[PID]/[EID])", $path[0]));
            }
        }
    };
}

macro_rules! my_try {
    ( $x:expr ) => {

        {
            match $x {
                Err(err) => return err_resp(&format!("{}", err)),
                Ok(thing) => thing,
            }
        }
    };
}

macro_rules! try_manager {
    ( $call:expr ) => {
        json::encode(&my_try!($call)).unwrap()
    };
}

macro_rules! read_body {
    ( $x:expr, $name:expr ) => {
        {
            match $x {
                Ok(Some(thing)) => thing,
                Ok(None) => return err_resp(&format!("body expected: {}", $name)),
                Err(err) => return err_resp(&format!("Error parsing {}: {:?}", $name, err)),
            }
        }
    };
}

impl iron::Handler for Router {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {

        if req.url.path.is_empty() {
            // ?!?
            panic!("Empty request path should never happen.");
        }

        // Weird deref trick to go from &String to &str

        let content_type: iron::mime::Mime = "application/json".parse::<iron::mime::Mime>().unwrap();

        match req.method {
            iron::method::Options => {
                let action = &*req.url.path[0];
                if ["hand", "trick", "contracts", "last_trick", "scores"].contains(&action) {
                    Ok(Response::with((iron::modifiers::Header(
                                           iron::headers::Allow(
                                               vec![
                                                   iron::method::Get,
                                                   iron::method::Options])),
                                       iron::status::Ok)))
                } else if ["pass", "coinche", "bid", "play", "join"].contains(&action) {
                    Ok(Response::with((iron::modifiers::Header(
                                           iron::headers::Allow(
                                               vec![
                                                   iron::method::Post,
                                                   iron::method::Options])),
                                       iron::status::Ok)))
                } else {
                    help_resp()
                }
            },
            iron::method::Get => {
                let response = match &*req.url.path[0] {
                    "wait" => {
                        check_len!(req.url.path, 3);
                        let player_id = parse_id!("player", &*req.url.path[1]);
                        let event_id = parse_id!("event", &*req.url.path[2]) as usize;
                        try_manager!(self.manager.wait(player_id, event_id))
                    },
                    "hand" => {
                        check_len!(req.url.path, 2);
                        let player_id = parse_id!("player", &*req.url.path[1]);
                        try_manager!(self.manager.see_hand(player_id))
                    },
                    "trick" => {
                        check_len!(req.url.path, 2);
                        let player_id = parse_id!("player", &*req.url.path[1]);
                        try_manager!(self.manager.see_trick(player_id))
                    },
                    "last_trick" => {
                        check_len!(req.url.path, 2);
                        let player_id = parse_id!("player", &*req.url.path[1]);
                        try_manager!(self.manager.see_last_trick(player_id))
                    },
                    "scores" => {
                        check_len!(req.url.path, 2);
                        let player_id = parse_id!("player", &*req.url.path[1]);
                        try_manager!(self.manager.see_scores(player_id))
                    },
                    "pos" => {
                        check_len!(req.url.path, 2);
                        let player_id = parse_id!("player", &*req.url.path[1]);
                        try_manager!(self.manager.see_pos(player_id))
                    },
                    _ => return help_resp(),
                };

                Ok(Response::with((content_type, iron::status::Ok, response)))

            },
            iron::method::Post => {
                // Read the JSON body
                // ...

                let response = match &*req.url.path[0] {
                    "join" => {
                        check_len!(req.url.path, 1);
                        try_manager!(self.manager.join())
                    },
                    "pass" => {
                        check_len!(req.url.path, 2);
                        let player_id = parse_id!("player", &*req.url.path[1]);
                        try_manager!(self.manager.pass(player_id))
                    },
                    "coinche" => {
                        check_len!(req.url.path, 2);
                        let player_id = parse_id!("player", &*req.url.path[1]);
                        try_manager!(self.manager.coinche(player_id))
                    },
                    "bid" => {
                        check_len!(req.url.path, 2);
                        let player_id = parse_id!("player", &*req.url.path[1]);
                        // Parse the body
                        #[derive(Clone,RustcDecodable)]
                        struct ContractBody {
                            contract: String,
                            suit: u32,
                        }

                        let contract = read_body!(req.get::<bodyparser::Struct<ContractBody>>(), "contract");
                        let target = my_try!(bid::Target::from_str(&contract.contract));
                        let trump = cards::Suit::from_n(contract.suit);
                        try_manager!(self.manager.bid(player_id, (target, trump)))
                    },
                    "play" => {
                        check_len!(req.url.path, 2);
                        let player_id = parse_id!("player", &*req.url.path[1]);
                        // Parse the body
                        #[derive(Clone,RustcDecodable)]
                        struct CardBody {
                            card: u32,
                        }
                        let card = read_body!(req.get::<bodyparser::Struct<CardBody>>(), "card");
                        let card = cards::Card::from_id(card.card);

                        try_manager!(self.manager.play_card(player_id, card))
                    },
                    _ => return help_resp(),
                };

                Ok(Response::with((content_type, iron::status::Ok, response)))
            },
            _ => help_resp(),
        }
    }
}

impl Server {
    pub fn new(port: u16) -> Server {
        Server {
            port: port,
            manager: Arc::new(GameManager::new()),
        }
    }

    pub fn run(self) {
        let port = self.port;
        println!("Listening on port {}", port);

        let router = Router { manager: self.manager.clone() };

        Iron::new(router).http(("localhost", port)).unwrap();

    }
}
<commit_msg>Add leave command<commit_after>use super::game_manager::GameManager;
use super::libcoinche::{bid,cards};

use std::sync::Arc;
use std::str::FromStr;

use rustc_serialize::json;

use iron;
use iron::prelude::*;
use bodyparser;

pub struct Server {
    port: u16,
    manager: Arc<GameManager>,
}

struct Router { manager: Arc<GameManager> }

#[derive(RustcEncodable)]
struct HelpAction {
    href: &'static str,
    method: &'static str,
    help: &'static str,
}

#[derive(RustcEncodable)]
struct HelpMessage {
    title: &'static str,
    actions: Vec<HelpAction>,
}

fn help_message() -> String {

    json::encode(&HelpMessage {
        title: "Help Page",
        actions: vec![
            HelpAction {
                href: "/join",
                method: "POST",
                help: "Join a new game.",
            },
            HelpAction {
                href: "/leave/[PLAYER_ID]",
                method: "POST",
                help: "Leave the current game.",
            },
            HelpAction {
                href: "/pass/[PLAYER_ID]",
                method: "POST",
                help: "Pass during auction.",
            },
            HelpAction {
                href: "/coinche/[PLAYER_ID]",
                method: "POST",
                help: "Coinche the opponent's bid during auction.",
            },
            HelpAction {
                href: "/bid/[PLAYER_ID]",
                method: "POST",
                help: "Bid a contract during auction.",
            },
            HelpAction {
                href: "/play/[PLAYER_ID]",
                method: "POST",
                help: "Play a card.",
            },
            HelpAction {
                href: "/hand/[PLAYER_ID]",
                method: "GET",
                help: "Checks the current hand.",
            },
            HelpAction {
                href: "/trick/[PLAYER_ID]",
                method: "GET",
                help: "Checks the current trick.",
            },
            HelpAction {
                href: "/last_trick/[PLAYER_ID]",
                method: "GET",
                help: "Checks the last complete trick.",
            },
            HelpAction {
                href: "/scores/[PLAYER_ID]",
                method: "GET",
                help: "Get the current scores.",
            },
            HelpAction {
                href: "/pos/[PLAYER_ID]",
                method: "GET",
                help: "Get the player's position on the table.",
            },
            HelpAction {
                href: "/wait/[PLAYER_ID]/[EVENT_ID]",
                method: "GET",
                help: "Wait until the next event, or return it if it already happened.",
            },
        ]
    }).unwrap()
}

fn help_resp() -> IronResult<Response> {
    let content_type: iron::mime::Mime = "application/json".parse::<iron::mime::Mime>().unwrap();
    return Ok(Response::with((content_type,
                              iron::status::NotFound,
                              help_message())));
}

fn err_resp(msg: &str) -> IronResult<Response> {
    let content_type: iron::mime::Mime = "application/json".parse::<iron::mime::Mime>().unwrap();

    #[derive(RustcEncodable)]
    struct Error<'a>{
        error: &'a str,
    }

    return Ok(Response::with((content_type,
                              iron::status::Ok,
                              json::encode(&Error { error: msg }).unwrap(),
                              )));
}

macro_rules! parse_id {
    ( $name:expr, $value:expr ) => {
        {
            match u32::from_str($value) {
                Ok(id) => id,
                Err(e) => return err_resp(&format!("invalid {} ID: `{}` ({})", $name, $value, e)),
            }
        }
    };
}

macro_rules! check_len {
    ( $path:expr, 1 ) => {
        {
            if $path.len() != 1 {
                return err_resp(&format!("incorrect parameters (Usage: /{})", $path[0]));
            }
        }
    };
    ( $path:expr, 2 ) => {
        {
            if $path.len() != 2 {
                return err_resp(&format!("incorrect parameters (Usage: /{}/[PID])", $path[0]));
            }
        }
    };
    ( $path:expr, 3 ) => {
        {
            if $path.len() != 3 {
                return err_resp(&format!("incorrect parameters (Usage: /{}/[PID]/[EID])", $path[0]));
            }
        }
    };
}

macro_rules! my_try {
    ( $x:expr ) => {

        {
            match $x {
                Err(err) => return err_resp(&format!("{}", err)),
                Ok(thing) => thing,
            }
        }
    };
}

macro_rules! try_manager {
    ( $call:expr ) => {
        json::encode(&my_try!($call)).unwrap()
    };
}

macro_rules! read_body {
    ( $x:expr, $name:expr ) => {
        {
            match $x {
                Ok(Some(thing)) => thing,
                Ok(None) => return err_resp(&format!("body expected: {}", $name)),
                Err(err) => return err_resp(&format!("Error parsing {}: {:?}", $name, err)),
            }
        }
    };
}

impl iron::Handler for Router {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {

        if req.url.path.is_empty() {
            // ?!?
            panic!("Empty request path should never happen.");
        }

        // Weird deref trick to go from &String to &str

        let content_type: iron::mime::Mime = "application/json".parse::<iron::mime::Mime>().unwrap();

        match req.method {
            iron::method::Options => {
                let action = &*req.url.path[0];
                if ["hand", "trick", "last_trick", "scores", "pos"].contains(&action) {
                    Ok(Response::with((iron::modifiers::Header(
                                           iron::headers::Allow(
                                               vec![
                                                   iron::method::Get,
                                                   iron::method::Options])),
                                       iron::status::Ok)))
                } else if ["pass", "coinche", "bid", "play", "join", "leave"].contains(&action) {
                    Ok(Response::with((iron::modifiers::Header(
                                           iron::headers::Allow(
                                               vec![
                                                   iron::method::Post,
                                                   iron::method::Options])),
                                       iron::status::Ok)))
                } else {
                    help_resp()
                }
            },
            iron::method::Get => {
                let response = match &*req.url.path[0] {
                    "wait" => {
                        check_len!(req.url.path, 3);
                        let player_id = parse_id!("player", &*req.url.path[1]);
                        let event_id = parse_id!("event", &*req.url.path[2]) as usize;
                        try_manager!(self.manager.wait(player_id, event_id))
                    },
                    "hand" => {
                        check_len!(req.url.path, 2);
                        let player_id = parse_id!("player", &*req.url.path[1]);
                        try_manager!(self.manager.see_hand(player_id))
                    },
                    "trick" => {
                        check_len!(req.url.path, 2);
                        let player_id = parse_id!("player", &*req.url.path[1]);
                        try_manager!(self.manager.see_trick(player_id))
                    },
                    "last_trick" => {
                        check_len!(req.url.path, 2);
                        let player_id = parse_id!("player", &*req.url.path[1]);
                        try_manager!(self.manager.see_last_trick(player_id))
                    },
                    "scores" => {
                        check_len!(req.url.path, 2);
                        let player_id = parse_id!("player", &*req.url.path[1]);
                        try_manager!(self.manager.see_scores(player_id))
                    },
                    "pos" => {
                        check_len!(req.url.path, 2);
                        let player_id = parse_id!("player", &*req.url.path[1]);
                        try_manager!(self.manager.see_pos(player_id))
                    },
                    _ => return help_resp(),
                };

                Ok(Response::with((content_type, iron::status::Ok, response)))

            },
            iron::method::Post => {
                // Read the JSON body
                // ...

                let response = match &*req.url.path[0] {
                    "join" => {
                        check_len!(req.url.path, 1);
                        try_manager!(self.manager.join())
                    },
                    "leave" => {
                        check_len!(req.url.path, 2);
                        let player_id = parse_id!("player", &*req.url.path[1]);
                        self.manager.pass(player_id);
                        r#""ok""#.to_string()
                    },
                    "pass" => {
                        check_len!(req.url.path, 2);
                        let player_id = parse_id!("player", &*req.url.path[1]);
                        try_manager!(self.manager.pass(player_id))
                    },
                    "coinche" => {
                        check_len!(req.url.path, 2);
                        let player_id = parse_id!("player", &*req.url.path[1]);
                        try_manager!(self.manager.coinche(player_id))
                    },
                    "bid" => {
                        check_len!(req.url.path, 2);
                        let player_id = parse_id!("player", &*req.url.path[1]);
                        // Parse the body
                        #[derive(Clone,RustcDecodable)]
                        struct ContractBody {
                            contract: String,
                            suit: u32,
                        }

                        let contract = read_body!(req.get::<bodyparser::Struct<ContractBody>>(), "contract");
                        let target = my_try!(bid::Target::from_str(&contract.contract));
                        let trump = cards::Suit::from_n(contract.suit);
                        try_manager!(self.manager.bid(player_id, (target, trump)))
                    },
                    "play" => {
                        check_len!(req.url.path, 2);
                        let player_id = parse_id!("player", &*req.url.path[1]);
                        // Parse the body
                        #[derive(Clone,RustcDecodable)]
                        struct CardBody {
                            card: u32,
                        }
                        let card = read_body!(req.get::<bodyparser::Struct<CardBody>>(), "card");
                        let card = cards::Card::from_id(card.card);

                        try_manager!(self.manager.play_card(player_id, card))
                    },
                    _ => return help_resp(),
                };

                Ok(Response::with((content_type, iron::status::Ok, response)))
            },
            _ => help_resp(),
        }
    }
}

impl Server {
    pub fn new(port: u16) -> Server {
        Server {
            port: port,
            manager: Arc::new(GameManager::new()),
        }
    }

    pub fn run(self) {
        let port = self.port;
        println!("Listening on port {}", port);

        let router = Router { manager: self.manager.clone() };

        Iron::new(router).http(("localhost", port)).unwrap();

    }
}
<|endoftext|>


<commit_before>use itertools::Itertools;
use std::hash::Hash;
use std::iter::FromIterator;

use generate::{HashIndexer, IndexVertices, IntoTriangles, IntoVertices, Topological, Triangulate};
use graph::geometry::{Attribute, Geometry};
use graph::storage::{EdgeKey, FaceKey, Key, OpaqueKey, Storage, VertexKey};

#[derive(Clone, Debug)]
pub struct Vertex<T, K>
where
    T: Attribute,
    K: Key,
{
    pub geometry: T,
    pub(super) edge: Option<EdgeKey<K>>,
}

impl<T, K> Vertex<T, K>
where
    T: Attribute,
    K: Key,
{
    fn new() -> Self {
        Vertex::with_geometry(T::default())
    }

    fn with_geometry(geometry: T) -> Self {
        Vertex {
            geometry: geometry,
            edge: None,
        }
    }
}

#[derive(Clone, Debug)]
pub struct Edge<T, K>
where
    T: Attribute,
    K: Key,
{
    pub geometry: T,
    pub(super) opposite: Option<EdgeKey<K>>,
    pub(super) next: Option<EdgeKey<K>>,
    pub(super) vertex: VertexKey<K>,
}

impl<T, K> Edge<T, K>
where
    T: Attribute,
    K: Key,
{
    fn new(vertex: VertexKey<K>) -> Self {
        Edge::with_geometry(vertex, T::default())
    }

    fn with_geometry(vertex: VertexKey<K>, geometry: T) -> Self {
        Edge {
            geometry: geometry,
            opposite: None,
            next: None,
            vertex: vertex,
        }
    }
}

#[derive(Clone, Debug)]
pub struct Face<T, K>
where
    T: Attribute,
    K: Key,
{
    pub geometry: T,
    pub(super) edge: EdgeKey<K>,
}

impl<T, K> Face<T, K>
where
    T: Attribute,
    K: Key,
{
    fn new(edge: EdgeKey<K>) -> Self {
        Face::with_geometry(edge, T::default())
    }

    fn with_geometry(edge: EdgeKey<K>, geometry: T) -> Self {
        Face {
            geometry: geometry,
            edge: edge,
        }
    }
}

pub struct Mesh<G, K = u64>
where
    G: Geometry,
    K: Key,
{
    pub(super) vertices: Storage<K, Vertex<G::Vertex, K>>,
    pub(super) edges: Storage<K, Edge<G::Edge, K>>,
    pub(super) faces: Storage<K, Face<G::Face, K>>,
}

impl<G, K> Mesh<G, K>
where
    G: Geometry,
    K: Key,
{
    pub fn new() -> Self {
        Mesh {
            vertices: Storage::new(),
            edges: Storage::new(),
            faces: Storage::new(),
        }
    }

    fn insert_vertex(&mut self, geometry: G::Vertex) -> VertexKey<K> {
        self.vertices.insert(Vertex::with_geometry(geometry)).into()
    }

    fn insert_edge(
        &mut self,
        vertices: (VertexKey<K>, VertexKey<K>),
        geometry: G::Edge,
    ) -> Result<EdgeKey<K>, ()> {
        let (i, j) = vertices;
        let ij = self.edges.insert(Edge::with_geometry(j, geometry));
        self.vertices.get_mut(&i.to_inner()).unwrap().edge = Some(ij.into());
        Ok(ij.into())
    }

    fn insert_triangle(
        &mut self,
        edges: (EdgeKey<K>, EdgeKey<K>, EdgeKey<K>),
        geometry: G::Face,
    ) -> Result<FaceKey<K>, ()> {
        let (ij, jk, ki) = edges;
        // Link each half-edge with its next half-edge.
        self.edges.get_mut(&ij.to_inner()).unwrap().next = Some(jk.into());
        self.edges.get_mut(&jk.to_inner()).unwrap().next = Some(ki.into());
        self.edges.get_mut(&ki.to_inner()).unwrap().next = Some(ij.into());
        Ok(
            self.faces
                .insert(Face::with_geometry(ij.into(), geometry))
                .into(),
        )
    }
}

impl<G, K> AsRef<Mesh<G, K>> for Mesh<G, K>
where
    G: Geometry,
    K: Key,
{
    fn as_ref(&self) -> &Self {
        self
    }
}

impl<G, K> AsMut<Mesh<G, K>> for Mesh<G, K>
where
    G: Geometry,
    K: Key,
{
    fn as_mut(&mut self) -> &mut Self {
        self
    }
}

impl<G, K, T> FromIterator<T> for Mesh<G, K>
where
    G: Geometry,
    K: Key,
    T: IntoTriangles + IntoVertices + Topological,
    T::Vertex: Eq + Hash + Into<G::Vertex>,
{
    fn from_iter<I>(input: I) -> Self
    where
        I: IntoIterator<Item = T>,
    {
        let mut mesh = Mesh::new();
        let (indeces, vertices) = input
            .into_iter()
            .triangulate()
            .index_vertices(HashIndexer::default());
        let vertices = vertices
            .into_iter()
            .map(|vertex| mesh.insert_vertex(vertex.into()))
            .collect::<Vec<_>>();
        for mut triangle in &indeces.into_iter().chunks(3) {
            // Map from the indeces into the original buffers to the keys
            // referring to the vertices in the mesh.
            let (i, j, k) = (
                vertices[triangle.next().unwrap()],
                vertices[triangle.next().unwrap()],
                vertices[triangle.next().unwrap()],
            );
            let (ij, jk, ki) = (
                mesh.insert_edge((i, j), G::Edge::default()).unwrap(),
                mesh.insert_edge((j, k), G::Edge::default()).unwrap(),
                mesh.insert_edge((k, i), G::Edge::default()).unwrap(),
            );
            mesh.insert_triangle((ij, jk, ki), G::Face::default());
        }
        mesh
    }
}
<commit_msg>Reference faces from edges.<commit_after>use itertools::Itertools;
use std::hash::Hash;
use std::iter::FromIterator;

use generate::{HashIndexer, IndexVertices, IntoTriangles, IntoVertices, Topological, Triangulate};
use graph::geometry::{Attribute, Geometry};
use graph::storage::{EdgeKey, FaceKey, Key, OpaqueKey, Storage, VertexKey};

#[derive(Clone, Debug)]
pub struct Vertex<T, K>
where
    T: Attribute,
    K: Key,
{
    pub geometry: T,
    pub(super) edge: Option<EdgeKey<K>>,
}

impl<T, K> Vertex<T, K>
where
    T: Attribute,
    K: Key,
{
    fn new() -> Self {
        Vertex::with_geometry(T::default())
    }

    fn with_geometry(geometry: T) -> Self {
        Vertex {
            geometry: geometry,
            edge: None,
        }
    }
}

#[derive(Clone, Debug)]
pub struct Edge<T, K>
where
    T: Attribute,
    K: Key,
{
    pub geometry: T,
    pub(super) vertex: VertexKey<K>,
    pub(super) opposite: Option<EdgeKey<K>>,
    pub(super) next: Option<EdgeKey<K>>,
    pub(super) face: Option<FaceKey<K>>,
}

impl<T, K> Edge<T, K>
where
    T: Attribute,
    K: Key,
{
    fn new(vertex: VertexKey<K>) -> Self {
        Edge::with_geometry(vertex, T::default())
    }

    fn with_geometry(vertex: VertexKey<K>, geometry: T) -> Self {
        Edge {
            geometry: geometry,
            vertex: vertex,
            opposite: None,
            next: None,
            face: None,
        }
    }
}

#[derive(Clone, Debug)]
pub struct Face<T, K>
where
    T: Attribute,
    K: Key,
{
    pub geometry: T,
    pub(super) edge: EdgeKey<K>,
}

impl<T, K> Face<T, K>
where
    T: Attribute,
    K: Key,
{
    fn new(edge: EdgeKey<K>) -> Self {
        Face::with_geometry(edge, T::default())
    }

    fn with_geometry(edge: EdgeKey<K>, geometry: T) -> Self {
        Face {
            geometry: geometry,
            edge: edge,
        }
    }
}

pub struct Mesh<G, K = u64>
where
    G: Geometry,
    K: Key,
{
    pub(super) vertices: Storage<K, Vertex<G::Vertex, K>>,
    pub(super) edges: Storage<K, Edge<G::Edge, K>>,
    pub(super) faces: Storage<K, Face<G::Face, K>>,
}

impl<G, K> Mesh<G, K>
where
    G: Geometry,
    K: Key,
{
    pub fn new() -> Self {
        Mesh {
            vertices: Storage::new(),
            edges: Storage::new(),
            faces: Storage::new(),
        }
    }

    fn insert_vertex(&mut self, geometry: G::Vertex) -> VertexKey<K> {
        self.vertices.insert(Vertex::with_geometry(geometry)).into()
    }

    fn insert_edge(
        &mut self,
        vertices: (VertexKey<K>, VertexKey<K>),
        geometry: G::Edge,
    ) -> Result<EdgeKey<K>, ()> {
        let (i, j) = vertices;
        let ij = self.edges.insert(Edge::with_geometry(j, geometry));
        self.vertices.get_mut(&i.to_inner()).unwrap().edge = Some(ij.into());
        Ok(ij.into())
    }

    fn connect_edges_in_face(&mut self, face: FaceKey<K>, edges: (EdgeKey<K>, EdgeKey<K>)) {
        let edge = self.edges.get_mut(&edges.0.to_inner()).unwrap();
        edge.next = edges.1.into();
        edge.face = face.into();
    }

    fn insert_triangle(
        &mut self,
        edges: (EdgeKey<K>, EdgeKey<K>, EdgeKey<K>),
        geometry: G::Face,
    ) -> Result<FaceKey<K>, ()> {
        let (ij, jk, ki) = edges;
        let face = self.faces
            .insert(Face::with_geometry(ij.into(), geometry))
            .into();
        self.connect_edges_in_face(face, (ij, jk));
        self.connect_edges_in_face(face, (jk, ki));
        self.connect_edges_in_face(face, (ki, ij));
        Ok(face)
    }
}

impl<G, K> AsRef<Mesh<G, K>> for Mesh<G, K>
where
    G: Geometry,
    K: Key,
{
    fn as_ref(&self) -> &Self {
        self
    }
}

impl<G, K> AsMut<Mesh<G, K>> for Mesh<G, K>
where
    G: Geometry,
    K: Key,
{
    fn as_mut(&mut self) -> &mut Self {
        self
    }
}

impl<G, K, T> FromIterator<T> for Mesh<G, K>
where
    G: Geometry,
    K: Key,
    T: IntoTriangles + IntoVertices + Topological,
    T::Vertex: Eq + Hash + Into<G::Vertex>,
{
    fn from_iter<I>(input: I) -> Self
    where
        I: IntoIterator<Item = T>,
    {
        let mut mesh = Mesh::new();
        let (indeces, vertices) = input
            .into_iter()
            .triangulate()
            .index_vertices(HashIndexer::default());
        let vertices = vertices
            .into_iter()
            .map(|vertex| mesh.insert_vertex(vertex.into()))
            .collect::<Vec<_>>();
        for mut triangle in &indeces.into_iter().chunks(3) {
            // Map from the indeces into the original buffers to the keys
            // referring to the vertices in the mesh.
            let (i, j, k) = (
                vertices[triangle.next().unwrap()],
                vertices[triangle.next().unwrap()],
                vertices[triangle.next().unwrap()],
            );
            let (ij, jk, ki) = (
                mesh.insert_edge((i, j), G::Edge::default()).unwrap(),
                mesh.insert_edge((j, k), G::Edge::default()).unwrap(),
                mesh.insert_edge((k, i), G::Edge::default()).unwrap(),
            );
            mesh.insert_triangle((ij, jk, ki), G::Face::default());
        }
        mesh
    }
}
<|endoftext|>


<commit_before>use std::net::{TcpListener, TcpStream};

extern crate rust_ofp;
use rust_ofp::ofp_controller::OfpController;
use rust_ofp::ofp_controller::openflow0x01::OF0x01Controller;
use rust_ofp::openflow0x01::{SwitchFeatures, PacketIn, Pattern};
use rust_ofp::openflow0x01::message::{add_flow, Message};

fn main() {
    struct OF0x01;
    impl OF0x01Controller for OF0x01 {
        fn switch_connected(_: u64, _: SwitchFeatures, stream: &mut TcpStream) {
            let prio = 0;
            let pat = Pattern::match_all();
            let message = Message::FlowMod(add_flow(prio, pat, vec![]));
            Self::send_message(1000, message, stream)
        }

        fn switch_disconnected(_: u64) {
        }

        fn packet_in(_: u64, _: u32, _: PacketIn, _: &mut TcpStream) {
        }
    }

    let listener = TcpListener::bind(("127.0.0.1", 6633)).unwrap();
    for stream in listener.incoming() {
        match stream {
            Ok(mut stream) => {
                std::thread::spawn(move || LearningSwitch::handle_client_connected(&mut stream));
            }
            Err(_) => {
                // connection failed
                panic!("Connection failed")
            }
        }
    }
}
<commit_msg>Fix build<commit_after>use std::net::{TcpListener, TcpStream};

extern crate rust_ofp;
use rust_ofp::ofp_controller::OfpController;
use rust_ofp::ofp_controller::openflow0x01::OF0x01Controller;
use rust_ofp::openflow0x01::{SwitchFeatures, PacketIn, Pattern};
use rust_ofp::openflow0x01::message::{add_flow, Message};

fn main() {
    struct OF0x01;
    impl OF0x01Controller for OF0x01 {
        fn switch_connected(_: u64, _: SwitchFeatures, stream: &mut TcpStream) {
            let prio = 0;
            let pat = Pattern::match_all();
            let message = Message::FlowMod(add_flow(prio, pat, vec![]));
            Self::send_message(1000, message, stream)
        }

        fn switch_disconnected(_: u64) {
        }

        fn packet_in(_: u64, _: u32, _: PacketIn, _: &mut TcpStream) {
        }
    }

    let listener = TcpListener::bind(("127.0.0.1", 6633)).unwrap();
    for stream in listener.incoming() {
        match stream {
            Ok(mut stream) => {
                std::thread::spawn(move || OF0x01::handle_client_connected(&mut stream));
            }
            Err(_) => {
                // connection failed
                panic!("Connection failed")
            }
        }
    }
}
<|endoftext|>


<commit_before>// mod args {
//   use argparse;
//
//   pub struct T {
//     pub target_width: u32,
//     pub target_height: u32,
//   }
//
//   /// Parse the command-line arguments
//   pub fn parse_or_exit() -> T {
//     let mut t =
//       T {
//         target_width:  0,
//         target_height: 0,
//       };
//
//     {
//       let mut args = argparse::ArgumentParser::new();
//       args.set_description("Content-aware image resizer");
//       args.refer(&mut t.target_width)
//         .add_option(
//           &["-w", "-width"],
//           argparse::Store,
//           "Target width of the image",
//         );
//       args.refer(&mut t.target_height)
//         .add_option(
//           &["-h", "-height"],
//           argparse::Store,
//           "Target height of the image",
//         );
//
//       args.parse_args_or_exit();
//     }
//
//     t
//   }
// }

use std;
use env_logger;
use image;
use image::{GenericImage, ImageDecoder};

use pixel;
use resize;
use vec2d;

fn resize(data: &vec2d::T<pixel::T>) -> vec2d::T<pixel::T> {
  let mut data = data.clone();

  let shrink_amount = 1;
  for i in 1 .. shrink_amount + 1 {
    data = resize::highlight_y_paths(&data);
    debug!("Decremented width {}", i);
  }

  data
}

fn load_input() -> image::ImageResult<vec2d::T<pixel::T>> {
  let input = std::io::stdin();
  let decoder = image::jpeg::JPEGDecoder::new(input);
  let image = try!(image::decoder_to_image(decoder));

  let (w, h) = image.dimensions();
  info!("Image is {} by {}", w, h);

  let mut data = vec2d::new(w as usize, h as usize, pixel::empty());

  for x in 0..w {
  for y in 0..h {
    *data.get_mut(x as usize, y as usize) = image.get_pixel(x, y);
  }}

  Ok(data)
}

fn output(data: &vec2d::T<pixel::T>) -> std::io::Result<()> {
  let mut image = image::DynamicImage::new_rgba8(data.width as u32, data.height as u32);

  for x in 0 .. data.width {
  for y in 0 .. data.height {
    image.put_pixel(x as u32, y as u32, *data.get(x, y));
  }}

  let as_vec = image.raw_pixels();

  let mut output = std::io::stdout();
  let mut img_encoder = image::jpeg::JPEGEncoder::new(&mut output);
  try!(img_encoder.encode(&as_vec, data.width as u32, data.height as u32, image.color()));

  Ok(())
}

#[main]
fn main() {
  env_logger::init().unwrap();

  let data = load_input().unwrap();
  let data = resize(&data);
  output(&data).unwrap();
}
<commit_msg>Seems to work!<commit_after>// mod args {
//   use argparse;
//
//   pub struct T {
//     pub target_width: u32,
//     pub target_height: u32,
//   }
//
//   /// Parse the command-line arguments
//   pub fn parse_or_exit() -> T {
//     let mut t =
//       T {
//         target_width:  0,
//         target_height: 0,
//       };
//
//     {
//       let mut args = argparse::ArgumentParser::new();
//       args.set_description("Content-aware image resizer");
//       args.refer(&mut t.target_width)
//         .add_option(
//           &["-w", "-width"],
//           argparse::Store,
//           "Target width of the image",
//         );
//       args.refer(&mut t.target_height)
//         .add_option(
//           &["-h", "-height"],
//           argparse::Store,
//           "Target height of the image",
//         );
//
//       args.parse_args_or_exit();
//     }
//
//     t
//   }
// }

use std;
use env_logger;
use image;
use image::{GenericImage, ImageDecoder};

use pixel;
use resize;
use vec2d;

fn resize(data: &vec2d::T<pixel::T>) -> vec2d::T<pixel::T> {
  let mut data = data.clone();

  let shrink_amount = data.width / 4;
  let iters = shrink_amount + 1;
  for i in 1 .. iters {
    data = resize::decrement_width(&data);
    debug!("Iteration {}/{} done", i, iters);
  }

  data
}

fn load_input() -> image::ImageResult<vec2d::T<pixel::T>> {
  let input = std::io::stdin();
  let decoder = image::jpeg::JPEGDecoder::new(input);
  let image = try!(image::decoder_to_image(decoder));

  let (w, h) = image.dimensions();
  info!("Image is {} by {}", w, h);

  let mut data = vec2d::new(w as usize, h as usize, pixel::empty());

  for x in 0..w {
  for y in 0..h {
    *data.get_mut(x as usize, y as usize) = image.get_pixel(x, y);
  }}

  Ok(data)
}

fn output(data: &vec2d::T<pixel::T>) -> std::io::Result<()> {
  let mut image = image::DynamicImage::new_rgba8(data.width as u32, data.height as u32);

  for x in 0 .. data.width {
  for y in 0 .. data.height {
    image.put_pixel(x as u32, y as u32, *data.get(x, y));
  }}

  let as_vec = image.raw_pixels();

  let mut output = std::io::stdout();
  let mut img_encoder = image::jpeg::JPEGEncoder::new(&mut output);
  try!(img_encoder.encode(&as_vec, data.width as u32, data.height as u32, image.color()));

  Ok(())
}

#[main]
fn main() {
  env_logger::init().unwrap();

  info!("Loading input..");
  let data = load_input().unwrap();
  info!("Performing operations..");
  let data = resize(&data);
  info!("Writing output..");
  output(&data).unwrap();
}
<|endoftext|>


<commit_before>use std::env;
use std::f32;
use std::thread::sleep;
use std::time::Duration;

extern crate getopts;
use getopts::Options;
extern crate rand;
use rand::Rng;
use rand::distributions::{IndependentSample,Range};
extern crate sacn;
use sacn::DmxSource;

const UNIVERSE_SIZE: usize = 510;

const GAMMA: f32 = 2.2;

#[derive(Debug)]
struct Params {
    decay:         f32,
    threshold:     f32,
    max_intensity: f32,
    sleep:         Duration
}

#[derive(Debug)]
#[derive(Clone)]
struct RGB {
    red:   u8,
    green: u8,
    blue:  u8
}

#[derive(Debug)]
#[derive(Clone)]
struct Pixel { intensity: f32, age: u32, temp: u16, rgb: RGB }

struct Zone  { head: u8, body: u8, tail: u8, name: String }

fn build_params () -> Params {
    // seed default params
    let mut params = Params { decay: 0.002, threshold: 0.001, max_intensity: 1_f32, sleep: Duration::new(0, 20_000_000) };

    // parse command line args and adjust params accordingly
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();
    let mut opts = Options::new();
    opts.optopt("d", "decay", "slow decay by this factor, defaults to 2", "DECAY");
    opts.optopt("t", "threshold", "probablity that a pixel lights up, default 0.10", "THRESHOLD");
    opts.optopt("m", "maxintensity", "maximum brightness, 1..255, default 75", "MAX");
    opts.optopt("s", "sleep", "sleep interval in seconds, default 1.5", "SECONDS");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m }
        Err(f) => { panic!(f.to_string()) }
    };
    if matches.opt_present("d") {
        params.decay = matches.opt_str("d").unwrap().parse::<f32>().unwrap();
    }
    if matches.opt_present("t") {
        params.threshold = matches.opt_str("t").unwrap().parse::<f32>().unwrap();
    }
    if matches.opt_present("m") {
        let max: u8 = matches.opt_str("m").unwrap().parse::<u8>().unwrap();
        params.max_intensity = (max as f32)/255_f32
    }
    if matches.opt_present("s") {
        // take float seconds
        // convert to int seconds and nanoseconds to make Duration happy
        let seconds: f32 = matches.opt_str("s").unwrap().parse::<f32>().unwrap();
        let whole_seconds: u64 = seconds as u64;
        let nano_seconds: u32 = ((seconds - whole_seconds as f32) * 1_000_000_000_f32) as u32;
        params.sleep = Duration::new(whole_seconds, nano_seconds);
    }
    return params;
}

fn kelvin (mut temp: u16) -> RGB {
    // http://www.tannerhelland.com/4435/convert-temperature-rgb-algorithm-code/
    temp /= 100;

    let mut rgb: RGB = RGB { red: 0, green: 0, blue: 0 };
    // calculate red
    if temp <= 66 {
        rgb.red = 255;
    } else {
        let red: f32 = (temp - 60) as f32;
        rgb.red = (329.698727446 * red.powf(-0.1332047592)).round() as u8;
    }
    // calculate green
    if temp <= 66 {
        let green: f32 = temp as f32;
        rgb.green = (99.4708025861 * green.ln() - 161.1195681661).round() as u8;
    } else {
        let green: f32 = (temp - 60) as f32;
        rgb.green = (288.1221695283 * green.powf(-0.0755148492)).round() as u8;
    }
    // calculate blue
    if temp >= 66 {
        rgb.blue = 255;
    } else {
        if temp <= 19 {
            rgb.blue = 0;
        } else {
            let blue: f32 = (temp - 10) as f32;
            rgb.blue = (138.5177312231 * blue.ln() - 305.0447927307).round() as u8;
        }
    }
    return rgb;
}

fn gamma_correct(rgb: &RGB) -> RGB {
    let mut c: RGB = RGB {red: 0, green: 0, blue: 0 };
    c.red   = (255_f32 * (rgb.red   as f32 / 255_f32).powf(GAMMA)) as u8;
    c.green = (255_f32 * (rgb.green as f32 / 255_f32).powf(GAMMA)) as u8;
    c.blue  = (255_f32 * (rgb.blue  as f32 / 255_f32).powf(GAMMA)) as u8;
    return c;
}

fn scale_rgb(rgb: RGB, intensity: f32, params: &Params) -> RGB {
    let i: f32 = intensity * params.max_intensity;
    let scaled: RGB = RGB {
        red:   (rgb.red   as f32 * i).round() as u8,
        green: (rgb.green as f32 * i).round() as u8,
        blue:  (rgb.blue  as f32 * i).round() as u8
    };
    return scaled;
}

fn main() {
    let params = build_params();

    let dmx = DmxSource::new("Controller").unwrap();

    let zones: [Zone; 6] = [
        Zone { head: 0, body: 44, tail: 3, name: "10".to_string() },
        Zone { head: 2, body: 91, tail: 3, name: "11a".to_string() },
        Zone { head: 2, body: 92, tail: 2, name: "11b".to_string() },
        Zone { head: 2, body: 90, tail: 3, name: "12a".to_string() },
        Zone { head: 2, body: 91, tail: 3, name: "12b".to_string() },
        Zone { head: 2, body: 43, tail: 0, name: "13".to_string() }
    ];

    let mut lights: Vec<Pixel> = vec![];
    // TODO: probably a more idiomatic way to built the default state
    for zone in zones.iter() {
        for i in 1..zone.body {
            let pixel = Pixel {
                intensity: 0_f32,
                age: 0,
                temp: 0,
                rgb: RGB { red: 0, green: 0, blue: 0 },
            };
            lights.push(pixel);
        }
    }

    let mut rng = rand::thread_rng();
    let zero_to_one = Range::new(0_f32, 1_f32);
    let temp_range = Range::new(2700_f32, 5500_f32);

    loop {
        for light in lights.iter_mut() {
            if light.intensity == 0_f32 {
                // light is currently dark
                // test to see if we want to light it
                if zero_to_one.ind_sample(&mut rng) < params.threshold {
                    // we do, so pick a random
                    light.intensity = zero_to_one.ind_sample(&mut rng) as f32;
                    light.age += 1;
                    light.temp = temp_range.ind_sample(&mut rng).round() as u16;
                    light.rgb = scale_rgb(kelvin(light.temp), light.intensity, &params);
                }
            } else {
                // light is lit
                // test to see if we rise or fall
                // probability of falling should go up as light ages
                if zero_to_one.ind_sample(&mut rng) > 1.0/(light.age as f32) {
                    // falling
                    light.intensity -= (zero_to_one.ind_sample(&mut rng) * params.decay) as f32;
                    light.age += 1;
                    // test to see if we bottomed out
                    if light.intensity <= 0_f32 {
                        light.intensity = 0_f32;
                        light.age = 0;
                        light.temp = 0;
                        light.rgb.red = 0;
                        light.rgb.green = 0;
                        light.rgb.blue = 0;
                    }
                } else {
                    // rising
                    light.intensity += zero_to_one.ind_sample(&mut rng) * params.decay * (params.max_intensity - light.intensity);

                    light.age += 1;
                    light.rgb = scale_rgb(kelvin(light.temp), light.intensity, &params);
                }
            }
        }
        render(&lights, &zones, &dmx);
        sleep(params.sleep);
    }
    dmx.terminate_stream(1);
}

// debug, rendor output to console
// fn render( lights: &[Pixel], zones: &[Zone], dmx: &DmxSource ) {
//    let mut out: Vec<i16> = vec![];
//    for light in lights {
//        out.push(light.level);
//   }
//    println!("{:?}", out)
//     let mut lit: u16 = 0;
//     let mut level: i16 = 0;
//     for light in lights {
//         if light.level > 0 {
//             lit += 1;
//             level += light.level;
//         }
//     }
//     println!("{} pixels, {} lit, {} avg level", lights.len(), lit, (level as f32)/(lit as f32));
// }

// output to lighting controller via sACN
fn render( lights: &[Pixel], zones: &[Zone], dmx: &DmxSource ) {
    let mut out: Vec<u8> = vec![];
    let mut copy: Vec<Pixel> = vec![];
    copy.extend_from_slice(lights);
    let mut idx: usize = 0;
    for zone in zones {
        // null pixels at head
        for i in 1..zone.head {
            out.push(0); // Red
            out.push(0); // Green
            out.push(0); // Blue
        }
        // set via light.level in the body
        for i in 0..(zone.body - 1) {
            let ref rgb = copy[idx].rgb;
            let gc = gamma_correct(&rgb);
            out.push(gc.red);
            out.push(gc.green);
            out.push(gc.blue);
            idx += 1;
        }
        // null pixels at tail
        for i in 1..zone.tail {
            out.push(0); // Red
            out.push(0); // Green
            out.push(0); // Blue
        }
    }
    let mut universes = Vec::new();
    while out.len() > UNIVERSE_SIZE {
        let u = out.split_off(UNIVERSE_SIZE);
        universes.push(out);
        out = u;
    }
    universes.push(out);
    let mut universe: u16 = 1;
    for u in universes {
        dmx.send(universe, &u);
        universe += 1;
    }
}

<commit_msg>trying (so far in vain) to detect bottoming out to red<commit_after>use std::env;
use std::f32;
use std::thread::sleep;
use std::time::Duration;

extern crate getopts;
use getopts::Options;
extern crate rand;
use rand::Rng;
use rand::distributions::{IndependentSample,Range};
extern crate sacn;
use sacn::DmxSource;

const UNIVERSE_SIZE: usize = 510;

const GAMMA: f32 = 2.2;

#[derive(Debug)]
struct Params {
    decay:         f32,
    threshold:     f32,
    max_intensity: f32,
    sleep:         Duration
}

#[derive(Debug)]
#[derive(Clone)]
struct RGB {
    red:   u8,
    green: u8,
    blue:  u8
}

#[derive(Debug)]
#[derive(Clone)]
struct Pixel { intensity: f32, age: u32, temp: u16, rgb: RGB }

struct Zone  { head: u8, body: u8, tail: u8, name: String }

fn build_params () -> Params {
    // seed default params
    let mut params = Params { decay: 0.002, threshold: 0.001, max_intensity: 1_f32, sleep: Duration::new(0, 20_000_000) };

    // parse command line args and adjust params accordingly
    let args: Vec<String> = env::args().collect();
    let program = args[0].clone();
    let mut opts = Options::new();
    opts.optopt("d", "decay", "slow decay by this factor, defaults to 2", "DECAY");
    opts.optopt("t", "threshold", "probablity that a pixel lights up, default 0.10", "THRESHOLD");
    opts.optopt("m", "maxintensity", "maximum brightness, 1..255, default 75", "MAX");
    opts.optopt("s", "sleep", "sleep interval in seconds, default 1.5", "SECONDS");
    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m }
        Err(f) => { panic!(f.to_string()) }
    };
    if matches.opt_present("d") {
        params.decay = matches.opt_str("d").unwrap().parse::<f32>().unwrap();
    }
    if matches.opt_present("t") {
        params.threshold = matches.opt_str("t").unwrap().parse::<f32>().unwrap();
    }
    if matches.opt_present("m") {
        let max: u8 = matches.opt_str("m").unwrap().parse::<u8>().unwrap();
        params.max_intensity = (max as f32)/255_f32
    }
    if matches.opt_present("s") {
        // take float seconds
        // convert to int seconds and nanoseconds to make Duration happy
        let seconds: f32 = matches.opt_str("s").unwrap().parse::<f32>().unwrap();
        let whole_seconds: u64 = seconds as u64;
        let nano_seconds: u32 = ((seconds - whole_seconds as f32) * 1_000_000_000_f32) as u32;
        params.sleep = Duration::new(whole_seconds, nano_seconds);
    }
    return params;
}

fn kelvin (mut temp: u16) -> RGB {
    // http://www.tannerhelland.com/4435/convert-temperature-rgb-algorithm-code/
    temp /= 100;

    let mut rgb: RGB = RGB { red: 0, green: 0, blue: 0 };
    // calculate red
    if temp <= 66 {
        rgb.red = 255;
    } else {
        let red: f32 = (temp - 60) as f32;
        rgb.red = (329.698727446 * red.powf(-0.1332047592)).round() as u8;
    }
    // calculate green
    if temp <= 66 {
        let green: f32 = temp as f32;
        rgb.green = (99.4708025861 * green.ln() - 161.1195681661).round() as u8;
    } else {
        let green: f32 = (temp - 60) as f32;
        rgb.green = (288.1221695283 * green.powf(-0.0755148492)).round() as u8;
    }
    // calculate blue
    if temp >= 66 {
        rgb.blue = 255;
    } else {
        if temp <= 19 {
            rgb.blue = 0;
        } else {
            let blue: f32 = (temp - 10) as f32;
            rgb.blue = (138.5177312231 * blue.ln() - 305.0447927307).round() as u8;
        }
    }
    return rgb;
}

fn gamma_correct(rgb: &RGB) -> RGB {
    let mut c: RGB = RGB {red: 0, green: 0, blue: 0 };
    c.red   = (255_f32 * (rgb.red   as f32 / 255_f32).powf(GAMMA)) as u8;
    c.green = (255_f32 * (rgb.green as f32 / 255_f32).powf(GAMMA)) as u8;
    c.blue  = (255_f32 * (rgb.blue  as f32 / 255_f32).powf(GAMMA)) as u8;
    return c;
}

fn scale_rgb(rgb: RGB, intensity: f32, params: &Params) -> RGB {
    let i: f32 = intensity * params.max_intensity;
    let scaled: RGB = RGB {
        red:   (rgb.red   as f32 * i).round() as u8,
        green: (rgb.green as f32 * i).round() as u8,
        blue:  (rgb.blue  as f32 * i).round() as u8
    };
    return scaled;
}

fn main() {
    let params = build_params();

    let dmx = DmxSource::new("Controller").unwrap();

    let zones: [Zone; 6] = [
        Zone { head: 0, body: 44, tail: 3, name: "10".to_string() },
        Zone { head: 2, body: 91, tail: 3, name: "11a".to_string() },
        Zone { head: 2, body: 92, tail: 2, name: "11b".to_string() },
        Zone { head: 2, body: 90, tail: 3, name: "12a".to_string() },
        Zone { head: 2, body: 91, tail: 3, name: "12b".to_string() },
        Zone { head: 2, body: 43, tail: 0, name: "13".to_string() }
    ];

    let mut lights: Vec<Pixel> = vec![];
    // TODO: probably a more idiomatic way to built the default state
    for zone in zones.iter() {
        for i in 1..zone.body {
            let pixel = Pixel {
                intensity: 0_f32,
                age: 0,
                temp: 0,
                rgb: RGB { red: 0, green: 0, blue: 0 },
            };
            lights.push(pixel);
        }
    }

    let mut rng = rand::thread_rng();
    let zero_to_one = Range::new(0_f32, 1_f32);
    let temp_range = Range::new(2700_f32, 5500_f32);

    loop {
        for light in lights.iter_mut() {
            if light.intensity == 0_f32 {
                // light is currently dark
                // test to see if we want to light it
                if zero_to_one.ind_sample(&mut rng) < params.threshold {
                    // we do, so pick a random
                    light.intensity = zero_to_one.ind_sample(&mut rng) as f32;
                    light.age += 1;
                    light.temp = temp_range.ind_sample(&mut rng).round() as u16;
                    light.rgb = scale_rgb(kelvin(light.temp), light.intensity, &params);
                }
            } else {
                // light is lit
                // test to see if we rise or fall
                // probability of falling should go up as light ages
                if zero_to_one.ind_sample(&mut rng) > 1.0/(light.age as f32) {
                    // falling
                    light.intensity -= (zero_to_one.ind_sample(&mut rng) * params.decay) as f32;
                    light.age += 1;
                    // test to see if we bottomed out
                    // check if intensity fell below zero
                    if light.intensity <= 0_f32 {
                        light.intensity = 0_f32;
                        light.age = 0;
                        light.temp = 0;
                        light.rgb.red = 0;
                        light.rgb.green = 0;
                        light.rgb.blue = 0;
                    }
                    // count zeroes, to avoid single-color output
                    //   when gamma-correct bottoms out, usually with red
                    let mut zeroes: u8 = 0;
                    if light.rgb.red == 0 { zeroes += 1 };
                    if light.rgb.green == 0 { zeroes += 1 };
                    if light.rgb.blue == 0 { zeroes += 1 };
                    if zeroes >= 2 {
                        light.intensity = 0_f32;
                        light.age = 0;
                        light.temp = 0;
                        light.rgb.red = 0;
                        light.rgb.green = 0;
                        light.rgb.blue = 0;
                    }
                } else {
                    // rising
                    light.intensity += zero_to_one.ind_sample(&mut rng) * params.decay * (params.max_intensity - light.intensity);

                    light.age += 1;
                    light.rgb = scale_rgb(kelvin(light.temp), light.intensity, &params);
                }
            }
        }
        render(&lights, &zones, &dmx);
        sleep(params.sleep);
    }
    dmx.terminate_stream(1);
}

// debug, rendor output to console
// fn render( lights: &[Pixel], zones: &[Zone], dmx: &DmxSource ) {
//    let mut out: Vec<i16> = vec![];
//    for light in lights {
//        out.push(light.level);
//   }
//    println!("{:?}", out)
//     let mut lit: u16 = 0;
//     let mut level: i16 = 0;
//     for light in lights {
//         if light.level > 0 {
//             lit += 1;
//             level += light.level;
//         }
//     }
//     println!("{} pixels, {} lit, {} avg level", lights.len(), lit, (level as f32)/(lit as f32));
// }

// output to lighting controller via sACN
fn render( lights: &[Pixel], zones: &[Zone], dmx: &DmxSource ) {
    let mut out: Vec<u8> = vec![];
    let mut copy: Vec<Pixel> = vec![];
    copy.extend_from_slice(lights);
    let mut idx: usize = 0;
    for zone in zones {
        // null pixels at head
        for i in 1..zone.head {
            out.push(0); // Red
            out.push(0); // Green
            out.push(0); // Blue
        }
        // set via light.level in the body
        for i in 0..(zone.body - 1) {
            let ref rgb = copy[idx].rgb;
            let gc = gamma_correct(&rgb);
            out.push(gc.red);
            out.push(gc.green);
            out.push(gc.blue);
            idx += 1;
        }
        // null pixels at tail
        for i in 1..zone.tail {
            out.push(0); // Red
            out.push(0); // Green
            out.push(0); // Blue
        }
    }
    let mut universes = Vec::new();
    while out.len() > UNIVERSE_SIZE {
        let u = out.split_off(UNIVERSE_SIZE);
        universes.push(out);
        out = u;
    }
    universes.push(out);
    let mut universe: u16 = 1;
    for u in universes {
        dmx.send(universe, &u);
        universe += 1;
    }
}

<|endoftext|>