<commit_before>extern crate byteorder;

use std::io::{Write};

use byteorder::{WriteBytesExt};

#[derive(Clone)]
pub struct ObjectIdentifier {
    data: Vec<u8>
}

fn encode_base128_int(data: &mut Vec<u8>, n: u32) {
    if n == 0 {
        data.push(0);
        return;
    }
    let mut l = 0;
    let mut i = n;
    while i > 0 {
        l += 1;
        i >>= 7;
    }

    for i in (0..l).rev() {
        let mut o = (n >> (i * 7)) as u8;
        o &= 0x7f;
        if i != 0 {
            o |= 0x80;
        }
        data.push(o);
    }
}

impl ObjectIdentifier {
    pub fn new(oid: Vec<u32>) -> Option<ObjectIdentifier> {
        if oid.len() < 2 || oid[0] > 2 || (oid[0] < 2 && oid[1] >= 40) {
            return None;
        }

        let mut data = Vec::new();
        encode_base128_int(&mut data, 40 * oid[0] + oid[1]);
        for el in oid.iter().skip(2) {
            encode_base128_int(&mut data, *el);
        }
        return Some(ObjectIdentifier {
            data: data
        });
    }
}

pub struct Serializer<'a> {
    writer: &'a mut Vec<u8>
}

impl<'a> Serializer<'a> {
    pub fn new(writer: &'a mut Vec<u8>) -> Serializer<'a> {
        return Serializer {
            writer: writer,
        }
    }

    fn _write_length(&mut self, length: usize) {
        assert!(length < 128);
        self.writer.write_u8(length as u8).unwrap();
    }

    fn _write_with_tag<F>(&mut self, tag: u8, body: F) where F: Fn() -> Vec<u8> {
        self.writer.write_u8(tag).unwrap();
        let body = body();
        self._write_length(body.len());
        self.writer.write_all(&body).unwrap();
    }

    pub fn write_bool(&mut self, v: bool) {
        return self._write_with_tag(1, || {
            if v {
                return b"\xff".to_vec();
            } else {
                return b"\x00".to_vec();
            }
        })
    }

    fn _int_length(&self, v: i64) -> usize {
        let mut num_bytes = 1;
        let mut i = v;

        while i > 127 || i < -128 {
            num_bytes += 1;
            i >>= 8;
        }
        return num_bytes;
    }

    pub fn write_int(&mut self, v: i64) {
        let n = self._int_length(v);
        return self._write_with_tag(2, || {
            let mut result = Vec::with_capacity(n);
            for i in (1..n+1).rev() {
                result.push((v >> ((i - 1) * 8)) as u8);
            }
            return result;
        })
    }

    pub fn write_octet_string(&mut self, v: &Vec<u8>) {
        return self._write_with_tag(4, || {
            return v.to_vec();
        })
    }

    pub fn write_object_identifier(&mut self, v: ObjectIdentifier) {
        return self._write_with_tag(6, || {
            return v.data.to_vec();
        })
    }

    pub fn write_sequence<F>(&mut self, v: F) where F: Fn(&mut Serializer) {
        return self._write_with_tag(48, || {
            return to_vec(&v);
        });
    }
}

pub fn to_vec<F>(f: F) -> Vec<u8> where F: Fn(&mut Serializer) {
    let mut out = Vec::new();
    {
        let mut serializer = Serializer::new(&mut out);
        f(&mut serializer);
    }
    return out;
}

#[cfg(test)]
mod tests {
    use super::{ObjectIdentifier, Serializer, to_vec};

    fn assert_serializes<T, F>(values: Vec<(T, Vec<u8>)>, f: F)
            where T: Clone,  F: Fn(&mut Serializer, T) {
        for (value, expected) in values {
            let out = to_vec(|s| f(s, value.clone()));
            assert_eq!(out, expected);
        }
    }

    #[test]
    fn test_write_bool() {
        assert_serializes(vec![
            (true, b"\x01\x01\xff".to_vec()),
            (false, b"\x01\x01\x00".to_vec()),
        ], |serializer, v| {
            serializer.write_bool(v);
        });
    }

    #[test]
    fn test_write_int() {
        assert_serializes(vec![
            (0, b"\x02\x01\x00".to_vec()),
            (127, b"\x02\x01\x7f".to_vec()),
            (128, b"\x02\x02\x00\x80".to_vec()),
            (256, b"\x02\x02\x01\x00".to_vec()),
            (-128, b"\x02\x01\x80".to_vec()),
            (-129, b"\x02\x02\xff\x7f".to_vec()),
        ], |serializer, v| {
            serializer.write_int(v);
        })
    }

    #[test]
    fn test_write_octet_string() {
        assert_serializes(vec![
            (b"\x01\x02\x03".to_vec(), b"\x04\x03\x01\x02\x03".to_vec()),
        ], |serializer, v| {
            serializer.write_octet_string(&v);
        })
    }

    #[test]
    fn test_write_sequence() {
        assert_serializes(vec![
            ((1, 2), b"\x30\x06\x02\x01\x01\x02\x01\x02".to_vec()),
        ], |serializer, (x, y)| {
            serializer.write_sequence(|s| {
                s.write_int(x);
                s.write_int(y);
            });
        })
    }

    #[test]
    fn test_write_object_identifier() {
        assert_serializes(vec![
            (
                ObjectIdentifier::new(vec![1, 2, 840, 113549]).unwrap(),
                b"\x06\x06\x2a\x86\x48\x86\xf7\x0d".to_vec()
            ),
            (
                ObjectIdentifier::new(vec![1, 2, 3, 4]).unwrap(),
                b"\x06\x03\x2a\x03\x04".to_vec(),
            ),
            (
                ObjectIdentifier::new(vec![1, 2, 840, 133549, 1, 1, 5]).unwrap(),
                b"\x06\x09\x2a\x86\x48\x88\x93\x2d\x01\x01\x05".to_vec(),
            ),
            (
                ObjectIdentifier::new(vec![2, 100, 3]).unwrap(),
                b"\x06\x03\x81\x34\x03".to_vec(),
            ),
        ], |serializer, oid| {
            serializer.write_object_identifier(oid);
        })
    }
}
<commit_msg>organize file better<commit_after>extern crate byteorder;

use std::io::{Write};

use byteorder::{WriteBytesExt};

#[derive(Clone)]
pub struct ObjectIdentifier {
    data: Vec<u8>
}

fn encode_base128_int(data: &mut Vec<u8>, n: u32) {
    if n == 0 {
        data.push(0);
        return;
    }
    let mut l = 0;
    let mut i = n;
    while i > 0 {
        l += 1;
        i >>= 7;
    }

    for i in (0..l).rev() {
        let mut o = (n >> (i * 7)) as u8;
        o &= 0x7f;
        if i != 0 {
            o |= 0x80;
        }
        data.push(o);
    }
}

impl ObjectIdentifier {
    pub fn new(oid: Vec<u32>) -> Option<ObjectIdentifier> {
        if oid.len() < 2 || oid[0] > 2 || (oid[0] < 2 && oid[1] >= 40) {
            return None;
        }

        let mut data = Vec::new();
        encode_base128_int(&mut data, 40 * oid[0] + oid[1]);
        for el in oid.iter().skip(2) {
            encode_base128_int(&mut data, *el);
        }
        return Some(ObjectIdentifier {
            data: data
        });
    }
}

pub struct Serializer<'a> {
    writer: &'a mut Vec<u8>
}

impl<'a> Serializer<'a> {
    pub fn new(writer: &'a mut Vec<u8>) -> Serializer<'a> {
        return Serializer {
            writer: writer,
        }
    }

    fn _write_length(&mut self, length: usize) {
        assert!(length < 128);
        self.writer.write_u8(length as u8).unwrap();
    }

    fn _write_with_tag<F>(&mut self, tag: u8, body: F) where F: Fn() -> Vec<u8> {
        self.writer.write_u8(tag).unwrap();
        let body = body();
        self._write_length(body.len());
        self.writer.write_all(&body).unwrap();
    }

    pub fn write_bool(&mut self, v: bool) {
        return self._write_with_tag(1, || {
            if v {
                return b"\xff".to_vec();
            } else {
                return b"\x00".to_vec();
            }
        })
    }

    fn _int_length(&self, v: i64) -> usize {
        let mut num_bytes = 1;
        let mut i = v;

        while i > 127 || i < -128 {
            num_bytes += 1;
            i >>= 8;
        }
        return num_bytes;
    }

    pub fn write_int(&mut self, v: i64) {
        let n = self._int_length(v);
        return self._write_with_tag(2, || {
            let mut result = Vec::with_capacity(n);
            for i in (1..n+1).rev() {
                result.push((v >> ((i - 1) * 8)) as u8);
            }
            return result;
        })
    }

    pub fn write_octet_string(&mut self, v: &Vec<u8>) {
        return self._write_with_tag(4, || {
            return v.to_vec();
        })
    }

    pub fn write_object_identifier(&mut self, v: ObjectIdentifier) {
        return self._write_with_tag(6, || {
            return v.data.to_vec();
        })
    }

    pub fn write_sequence<F>(&mut self, v: F) where F: Fn(&mut Serializer) {
        return self._write_with_tag(48, || {
            return to_vec(&v);
        });
    }
}

pub fn to_vec<F>(f: F) -> Vec<u8> where F: Fn(&mut Serializer) {
    let mut out = Vec::new();
    {
        let mut serializer = Serializer::new(&mut out);
        f(&mut serializer);
    }
    return out;
}

#[cfg(test)]
mod tests {
    use super::{ObjectIdentifier, Serializer, to_vec};

    fn assert_serializes<T, F>(values: Vec<(T, Vec<u8>)>, f: F)
            where T: Clone,  F: Fn(&mut Serializer, T) {
        for (value, expected) in values {
            let out = to_vec(|s| f(s, value.clone()));
            assert_eq!(out, expected);
        }
    }

    #[test]
    fn test_write_bool() {
        assert_serializes(vec![
            (true, b"\x01\x01\xff".to_vec()),
            (false, b"\x01\x01\x00".to_vec()),
        ], |serializer, v| {
            serializer.write_bool(v);
        });
    }

    #[test]
    fn test_write_int() {
        assert_serializes(vec![
            (0, b"\x02\x01\x00".to_vec()),
            (127, b"\x02\x01\x7f".to_vec()),
            (128, b"\x02\x02\x00\x80".to_vec()),
            (256, b"\x02\x02\x01\x00".to_vec()),
            (-128, b"\x02\x01\x80".to_vec()),
            (-129, b"\x02\x02\xff\x7f".to_vec()),
        ], |serializer, v| {
            serializer.write_int(v);
        })
    }

    #[test]
    fn test_write_octet_string() {
        assert_serializes(vec![
            (b"\x01\x02\x03".to_vec(), b"\x04\x03\x01\x02\x03".to_vec()),
        ], |serializer, v| {
            serializer.write_octet_string(&v);
        })
    }

    #[test]
    fn test_write_object_identifier() {
        assert_serializes(vec![
            (
                ObjectIdentifier::new(vec![1, 2, 840, 113549]).unwrap(),
                b"\x06\x06\x2a\x86\x48\x86\xf7\x0d".to_vec()
            ),
            (
                ObjectIdentifier::new(vec![1, 2, 3, 4]).unwrap(),
                b"\x06\x03\x2a\x03\x04".to_vec(),
            ),
            (
                ObjectIdentifier::new(vec![1, 2, 840, 133549, 1, 1, 5]).unwrap(),
                b"\x06\x09\x2a\x86\x48\x88\x93\x2d\x01\x01\x05".to_vec(),
            ),
            (
                ObjectIdentifier::new(vec![2, 100, 3]).unwrap(),
                b"\x06\x03\x81\x34\x03".to_vec(),
            ),
        ], |serializer, oid| {
            serializer.write_object_identifier(oid);
        })
    }

    #[test]
    fn test_write_sequence() {
        assert_serializes(vec![
            ((1, 2), b"\x30\x06\x02\x01\x01\x02\x01\x02".to_vec()),
        ], |serializer, (x, y)| {
            serializer.write_sequence(|s| {
                s.write_int(x);
                s.write_int(y);
            });
        })
    }
}
<|endoftext|>


<commit_before>#![feature(specialization)]
 #![feature(type_ascription)]
 #![feature(concat_idents)]

extern crate rutorch;
#[macro_use]
extern crate modparse_derive;
#[macro_use]
extern crate derive_builder;

extern crate num;
extern crate rand;
extern crate itertools;

// only needed for torchvision
extern crate curl;
extern crate flate2;
extern crate memmap;

// serialization support
#[macro_use]
extern crate serde_derive;
extern crate rmp;
extern crate rmp_serde as rmps;
extern crate serde;

#[macro_use]
pub mod macros;

pub mod nn;
pub mod autograd;
pub mod optim;
pub mod utils;
pub mod tensor;
pub mod storage;
pub mod torch;
use std::rc::Rc;
use std::cell::RefCell;

// Mutable reference counted T
pub type RcMut<T> = Rc<RefCell<T>>;
// Nullable mutable reference counted T
pub type OptRcMut<T> = Option<RcMut<T>>;
pub type Ix = usize;
/// Array index type (signed)
pub type Ixs = isize;

#[allow(non_snake_case)]
pub fn RcMutNew<T>(arg: T) -> RcMut<T> {
    Rc::new(RefCell::new(arg))
}

#[cfg(test)]
mod tests {

    #[test]
    fn it_works() {}
}
<commit_msg>white space fix<commit_after>#![feature(specialization)]
#![feature(type_ascription)]
#![feature(concat_idents)]

extern crate rutorch;
#[macro_use]
extern crate modparse_derive;
#[macro_use]
extern crate derive_builder;

extern crate num;
extern crate rand;
extern crate itertools;

// only needed for torchvision
extern crate curl;
extern crate flate2;
extern crate memmap;

// serialization support
#[macro_use]
extern crate serde_derive;
extern crate rmp;
extern crate rmp_serde as rmps;
extern crate serde;

#[macro_use]
pub mod macros;

pub mod nn;
pub mod autograd;
pub mod optim;
pub mod utils;
pub mod tensor;
pub mod storage;
pub mod torch;
use std::rc::Rc;
use std::cell::RefCell;

// Mutable reference counted T
pub type RcMut<T> = Rc<RefCell<T>>;
// Nullable mutable reference counted T
pub type OptRcMut<T> = Option<RcMut<T>>;
pub type Ix = usize;
/// Array index type (signed)
pub type Ixs = isize;

#[allow(non_snake_case)]
pub fn RcMutNew<T>(arg: T) -> RcMut<T> {
    Rc::new(RefCell::new(arg))
}

#[cfg(test)]
mod tests {

    #[test]
    fn it_works() {}
}
<|endoftext|>


<commit_before>#![feature(plugin)]
#![feature(core)]
#![feature(io)]

#![plugin(peg_syntax_ext)]

pub mod parser;
pub mod expr_parser;
pub mod span;
pub mod ast;
pub mod opcode;
pub mod program;
pub mod value;
pub mod visit;
pub mod prettyprint;
pub mod check;
pub mod resolve;
<commit_msg>Warnings only now<commit_after>#![feature(plugin, core, io, old_io)]

#![plugin(peg_syntax_ext)]

pub mod parser;
pub mod expr_parser;
pub mod span;
pub mod ast;
pub mod opcode;
pub mod program;
pub mod value;
pub mod visit;
pub mod prettyprint;
pub mod check;
pub mod resolve;
<|endoftext|>


<commit_before>mod errors;
mod fragile;
mod sticky;

pub use errors::InvalidThreadAccess;
pub use fragile::Fragile;
pub use sticky::Sticky;
<commit_msg>Added docs<commit_after>//! This library provides wrapper types that permit sending non `Send` types to
//! other threads and use runtime checks to ensure safety.
//!
//! It provides two types: `Fragile<T>` and `Sticky<T>` which are similar in nature
//! but have different behaviors with regards to how destructors are executed.
//!
//! Both types wrap a value and provide a `Send` bound.  Neither of the types permit
//! access to the enclosed value unless the thread that wrapped the value is attempting
//! to access it.  The difference between the two types starts playing a role once
//! destructors are involved.
//!
//! A `Fragile<T>` will actually send the `T` from thread to thread but will only
//! permit the original thread to invoke the destructor.  If the value gets dropped
//! in a different thread, the destructor will panic.
//!
//! A `Sticky<T>` on the other hand does not actually send the `T` around but keeps
//! it stored in the original thread's thread local storage.  If it gets dropped
//! in the originating thread it gets cleaned up immediately, otherwise it leaks
//! until the thread shuts down naturally.
//!
//! # Example usage
//!
//! ```
//! use std::thread;
//!
//! // creating and using a fragile object in the same thread works
//! let val = Fragile::new(true);
//! assert_eq!(*val.get(), true);
//! assert!(val.try_get().is_ok());
//!
//! // once send to another thread it stops working
//! thread::spawn(move || {
//!     assert!(val.try_get().is_err());
//! }).join()
//!     .unwrap();
//! ```
//!
//! # Why?
//!
//! Most of the time trying to use this crate is going to indicate some code smell.  But
//! there are situations where this is useful.  For instance you might have a bunch of
//! non `Send` types but want to work with a `Send` error type.  In that case the non
//! sendable extra information can be contained within the error and in cases where the
//! error did not cross a thread boundary yet extra information can be obtained.
mod errors;
mod fragile;
mod sticky;

pub use errors::InvalidThreadAccess;
pub use fragile::Fragile;
pub use sticky::Sticky;
<|endoftext|>


<commit_before>
#![feature(unsafe_destructor)]
#[allow(dead_code)]

extern crate libc;
use std::rc::{Rc};
use std::cell::{RefCell};
use std::collections::{HashMap};
use mruby::{mrb_open,mrb_close,mrb_state,mrb_value,Struct_RClass,mrb_int};
mod mruby;

pub type MrbState = Rc<RefCell<*mut mrb_state>>;
pub type MrbClass = Rc<RefCell<*mut Struct_RClass>>;

pub struct Mrb {
    mrb : MrbState,
    clzs : RefCell<HashMap<String,MrbClass>>
}

#[deriving(PartialEq,Clone)]
pub struct Class {
    mrb : MrbState,
    clz : MrbClass
}

/// Traits for objects that has access to mrb_state.
/// Inspired by rust-hl-lua.
pub trait HasState {
    fn get_state(&self) -> *mut mrb_state;
}

impl HasState for Mrb {
    #[inline(always)]
    fn get_state(&self) -> *mut mrb_state {
        *(self.mrb).borrow_mut()
    }
}

impl HasState for Class {
    #[inline(always)]
    fn get_state(&self) -> *mut mrb_state {
        *(self.mrb).borrow_mut()
    }
}

/// Traits for objects that has access to Struct_RClass.
/// Inspired by rust-hl-lua.
pub trait HasClass {
    fn get_class(&self) -> *mut Struct_RClass;
}

impl HasClass for Class {
    #[inline(always)]
    fn get_class(&self) -> *mut Struct_RClass {
        *(self.clz).borrow_mut()
    }
}

impl Mrb {

    pub fn new() -> Mrb {
        let mrb = unsafe {
            mrb_open()
        };
        let state = unsafe { *mrb };
        let clzs : RefCell<HashMap<String,MrbClass>> = RefCell::new(HashMap::new());
        let m = Mrb{ mrb:Rc::new(RefCell::new(mrb)),clzs:clzs };
        m.clzs.borrow_mut().insert(String::from_str("Object"),Rc::new(RefCell::new(state.object_class)));
        m.clzs.borrow_mut().insert(String::from_str("Class"),Rc::new(RefCell::new(state.class_class)));
        m.clzs.borrow_mut().insert(String::from_str("String"),Rc::new(RefCell::new(state.string_class)));
        m.clzs.borrow_mut().insert(String::from_str("Array"),Rc::new(RefCell::new(state.array_class)));
        m.clzs.borrow_mut().insert(String::from_str("Hash"),Rc::new(RefCell::new(state.hash_class)));
        m
    }

    pub fn close(&self) {
        if std::rc::is_unique(&self.mrb) {
            let state = self.get_state();
            unsafe {
                mrb_close(state);
            }
        }
    }

    pub fn get_class(&self,name:&str) -> Option<Class> {
        let mut h = self.clzs.borrow_mut();
        let clzname = String::from_str(name);
        if h.get(&clzname).is_some() {
                return Some(Class{mrb:self.mrb.clone(),clz:h.get(&clzname).unwrap().clone()})
        }
        let mclz = unsafe {
            mruby::mrb_class_get(self.get_state(),
                                 name.as_ptr() as *const libc::c_char)
        };
        if mclz.is_null() {
            None
        } else {
            let class = Class{mrb:self.mrb.clone(),clz:Rc::new(RefCell::new(mclz))};
            h.insert(clzname,class.clz.clone());
            Some(class)
        }
    }

    pub fn load(&self,code:&str) -> mrb_value {
        unsafe {
            let state = self.get_state();
            let mut sjmp = (*state).jmp;
            if sjmp as uint != 0 {
                panic!("jmp not null");
            }
            let jmp = libc::malloc(std::mem::size_of::<mruby::jmp_buf>() as libc::size_t) as *mut mruby::jmp_buf;
            if mruby::setjmp(*jmp) as int == 0 {
                sjmp = jmp;
                let val = mruby::mrb_load_string(state,code.as_ptr() as *const libc::c_char);
                sjmp = 0 as *mut _;
                return val;
            } else {
                mruby::mrb_print_error(state);
                panic!("fail to setjmp");
            }
            libc::free(jmp as *mut _);
        }
    }

    pub fn def_class(&self,name:&str,outer:&str) -> Option<Class> {
        if self.get_class(name).is_some() {
            panic!("class already have");
        }
        match self.get_class(outer) {
            Some(out_clz) => {
                let clz = unsafe {
                    mruby::mrb_define_class(self.get_state(),
                                 name.as_ptr() as *const libc::c_char,
                                 out_clz.get_class()
                                 )
                };
                let class = Class{mrb:self.mrb.clone(),clz:Rc::new(RefCell::new(clz))};
                let mut h = self.clzs.borrow_mut();
                h.insert(String::from_str(name),class.clz.clone());
                Some(class)
            },
            None => {
                None
            }
        }
    }

    pub fn call(&self,v:&mrb_value,method:&str) {
        unsafe {
            mruby::mrb_funcall(self.get_state(),*v,
                                 method.as_ptr() as *const libc::c_char,0 as mrb_int);
        }
    }

    pub fn inspect(&self,v:&mrb_value) {
        self.call(v,"to_s");
    }

}

impl Class {
    fn new(&self) -> mrb_value {
        unsafe {
            mruby::mrb_obj_new(self.get_state(),self.get_class(),0 as mrb_int,0 as *const _)
        }
    }
}
/*
#[unsafe_destructor]
impl Drop for RefCell<*mut mrb_state> {
    fn drop(&mut self) {
        let mrb = *self.borrow_mut();
        if !mrb.is_null() {
            println!("mrb pointer null");
            unsafe {
                mrb_close(mrb);
            }
        }
    }
}
*/

#[test]
fn test_mrb_open() {
    let m = Mrb::new();
    m.close();
}

#[test]
fn test_get_class() {
    let m = Mrb::new();
    let arr_clz = m.get_class("Array").unwrap();
    assert!(m.get_class("Class").is_some());
    assert!(m.get_class("Object").is_some());
    assert!(m.get_class("Hash").is_some());
    assert!(m.get_class("String").is_some());
    m.close();
    assert!(m.get_class("String").is_some());
    assert!(std::rc::strong_count(&arr_clz.mrb) == 2);
}

#[test]
fn test_obj_new() {
    let m = Mrb::new();
    let arr_clz = m.get_class("Array").unwrap();
    let v = arr_clz.new();
    m.inspect(&v);
    assert!(v.is_nil());
    m.close();
}

#[test]
fn test_load_str() {
    let m = Mrb::new();
    let mut v = m.load("def inc(a) a+1 end; return inc(2)");
    assert!(v.is_nil());
    m.call(&v,"to_s");
    m.close();
}

#[test]
fn test_def_class() {
    let m = Mrb::new();
    let hello = m.def_class("Hello","Object");
    assert!(hello.is_some());
    m.close();
}
<commit_msg>add mrbc_context<commit_after>
#![feature(unsafe_destructor)]
#[allow(dead_code)]

extern crate libc;
use std::rc::{Rc};
use std::cell::{RefCell};
use std::collections::{HashMap};
use mruby::{mrb_open,mrb_close,mrb_state,mrb_value,Struct_RClass,mrb_int,Struct_mrbc_context};
mod mruby;

pub type MrbState = Rc<RefCell<*mut mrb_state>>;
pub type MrbClass = Rc<RefCell<*mut Struct_RClass>>;

pub struct Mrb {
    mrb : MrbState,
    clzs : RefCell<HashMap<String,MrbClass>>
}

#[deriving(PartialEq,Clone)]
pub struct Class {
    mrb : MrbState,
    clz : MrbClass
}

pub struct Context {
    mrb : MrbState,
    ctx : *mut Struct_mrbc_context
}

/// Traits for objects that has access to mrb_state.
/// Inspired by rust-hl-lua.
pub trait HasState {
    fn get_state(&self) -> *mut mrb_state;
}

impl HasState for Mrb {
    #[inline(always)]
    fn get_state(&self) -> *mut mrb_state {
        *(self.mrb).borrow_mut()
    }
}

impl HasState for Context {
    #[inline(always)]
    fn get_state(&self) -> *mut mrb_state {
        *(self.mrb).borrow_mut()
    }
}

impl HasState for Class {
    #[inline(always)]
    fn get_state(&self) -> *mut mrb_state {
        *(self.mrb).borrow_mut()
    }
}

/// Traits for objects that has access to Struct_RClass.
/// Inspired by rust-hl-lua.
pub trait HasClass {
    fn get_class(&self) -> *mut Struct_RClass;
}

impl HasClass for Class {
    #[inline(always)]
    fn get_class(&self) -> *mut Struct_RClass {
        *(self.clz).borrow_mut()
    }
}

impl Mrb {

    pub fn new() -> Mrb {
        let mrb = unsafe {
            mrb_open()
        };
        let state = unsafe { *mrb };
        let clzs : RefCell<HashMap<String,MrbClass>> = RefCell::new(HashMap::new());
        let m = Mrb{ mrb:Rc::new(RefCell::new(mrb)),clzs:clzs };
        m.clzs.borrow_mut().insert(String::from_str("Object"),Rc::new(RefCell::new(state.object_class)));
        m.clzs.borrow_mut().insert(String::from_str("Class"),Rc::new(RefCell::new(state.class_class)));
        m.clzs.borrow_mut().insert(String::from_str("String"),Rc::new(RefCell::new(state.string_class)));
        m.clzs.borrow_mut().insert(String::from_str("Array"),Rc::new(RefCell::new(state.array_class)));
        m.clzs.borrow_mut().insert(String::from_str("Hash"),Rc::new(RefCell::new(state.hash_class)));
        m
    }

    pub fn close(&self) {
        if std::rc::is_unique(&self.mrb) {
            let state = self.get_state();
            unsafe {
                mrb_close(state);
            }
        }
    }

    pub fn get_class(&self,name:&str) -> Option<Class> {
        let mut h = self.clzs.borrow_mut();
        let clzname = String::from_str(name);
        if h.get(&clzname).is_some() {
                return Some(Class{mrb:self.mrb.clone(),clz:h.get(&clzname).unwrap().clone()})
        }
        let mclz = unsafe {
            mruby::mrb_class_get(self.get_state(),
                                 name.as_ptr() as *const libc::c_char)
        };
        if mclz.is_null() {
            None
        } else {
            let class = Class{mrb:self.mrb.clone(),clz:Rc::new(RefCell::new(mclz))};
            h.insert(clzname,class.clz.clone());
            Some(class)
        }
    }

    pub fn load(&self,code:&str) -> mrb_value {
        unsafe {
            let state = self.get_state();
            mruby::mrb_load_string(state,code.as_ptr() as *const libc::c_char)

            /*
            let state = self.get_state();
            let sjmp = (*state).jmp;
            if sjmp as uint != 0 {
                panic!("jmp not null");
            }
            let jmp = libc::malloc(std::mem::size_of::<mruby::jmp_buf>() as libc::size_t) as *mut mruby::jmp_buf;
            if mruby::setjmp(*jmp) as int == 0 {
                (*state).jmp = jmp;
                let val = mruby::mrb_load_string(state,code.as_ptr() as *const libc::c_char);
                (*state).jmp = 0 as *mut _;
                return val;
            } else {
                mruby::mrb_print_error(state);
                panic!("fail to setjmp");
            }
            libc::free(jmp as *mut _);
            */
        }
    }

    pub fn load_str_ctx(&self,code:&str,ctx:&Context) -> mrb_value {
        unsafe {
            let state = self.get_state();
            mruby::mrb_load_string_cxt(state,
                                   code.as_ptr() as *const libc::c_char,
                                   ctx.ctx)
        }
    }

    pub fn def_class(&self,name:&str,outer:&str) -> Option<Class> {
        if self.get_class(name).is_some() {
            panic!("class already have");
        }
        match self.get_class(outer) {
            Some(out_clz) => {
                let clz = unsafe {
                    mruby::mrb_define_class(self.get_state(),
                                 name.as_ptr() as *const libc::c_char,
                                 out_clz.get_class()
                                 )
                };
                let class = Class{mrb:self.mrb.clone(),clz:Rc::new(RefCell::new(clz))};
                let mut h = self.clzs.borrow_mut();
                h.insert(String::from_str(name),class.clz.clone());
                Some(class)
            },
            None => {
                None
            }
        }
    }

    pub fn call(&self,v:&mrb_value,method:&str) {
        unsafe {
            mruby::mrb_funcall(self.get_state(),*v,
                                 method.as_ptr() as *const libc::c_char,0 as mrb_int);
        }
    }

    pub fn inspect(&self,v:&mrb_value) {
        self.call(v,"to_s");
    }

    pub fn new_context(&self) -> Context {
        let ctx = unsafe { mruby::mrbc_context_new(self.get_state()) };
        Context { mrb:self.mrb.clone(),ctx:ctx }
    }

}

impl Class {
    fn new(&self) -> mrb_value {
        unsafe {
            mruby::mrb_obj_new(self.get_state(),self.get_class(),0 as mrb_int,0 as *const _)
        }
    }
}
/*
#[unsafe_destructor]
impl Drop for RefCell<*mut mrb_state> {
    fn drop(&mut self) {
        let mrb = *self.borrow_mut();
        if !mrb.is_null() {
            println!("mrb pointer null");
            unsafe {
                mrb_close(mrb);
            }
        }
    }
}
*/

#[test]
fn test_mrb_open() {
    let m = Mrb::new();
    m.close();
}

#[test]
fn test_get_class() {
    let m = Mrb::new();
    let arr_clz = m.get_class("Array").unwrap();
    assert!(m.get_class("Class").is_some());
    assert!(m.get_class("Object").is_some());
    assert!(m.get_class("Hash").is_some());
    assert!(m.get_class("String").is_some());
    m.close();
    assert!(m.get_class("String").is_some());
    assert!(std::rc::strong_count(&arr_clz.mrb) == 2);
}

#[test]
fn test_obj_new() {
    let m = Mrb::new();
    let arr_clz = m.get_class("Array").unwrap();
    let v = arr_clz.new();
    m.inspect(&v);
    assert!(v.is_nil());
    m.close();
}

#[test]
fn test_load_str() {
    let m = Mrb::new();
    let mut v = m.load("def inc(a) a+1 end;\n a = 3;inc(a)");
    assert!(v.is_nil());
    m.call(&v,"to_s");
    m.close();
}

#[test]
fn test_def_class() {
    let m = Mrb::new();
    let hello = m.def_class("Hello","Object");
    assert!(hello.is_some());
    m.close();
}
<|endoftext|>


<commit_before>// Copyright 2015 Philipp Oppermann
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![feature(no_std, lang_items)]
#![feature(const_fn, unique, core_str_ext, iter_cmp)]
#![no_std]

extern crate rlibc;
extern crate spin;
extern crate multiboot2;

#[macro_use]
mod vga_buffer;
mod memory;

#[no_mangle]
pub extern fn rust_main(multiboot_information_address: usize) {
    // ATTENTION: we have a very small stack and no guard page
    vga_buffer::clear_screen();
    println!("Hello World{}", "!");

    let boot_info = unsafe{ multiboot2::load(multiboot_information_address) };
    let memory_map_tag = boot_info.memory_map_tag().expect("Memory map tag required");
    let elf_sections_tag = boot_info.elf_sections_tag().expect("Memory map tag required");

    println!("memory areas:");
    for area in memory_map_tag.memory_areas() {
        println!("    start: 0x{:x}, length: 0x{:x}", area.base_addr, area.length);
    }

    println!("kernel sections:");
    for section in elf_sections_tag.sections() {
        println!("    addr: 0x{:x}, size: 0x{:x}, flags: 0x{:x}",
            section.addr, section.size, section.flags);
    }

    let kernel_start = elf_sections_tag.sections().map(|s| s.addr).min().unwrap();
    let kernel_end = elf_sections_tag.sections().map(|s| s.addr + s.size).max().unwrap();

    let multiboot_start = multiboot_information_address;
    let multiboot_end = multiboot_start + (boot_info.total_size as usize);

    println!("kernel start: 0x{:x}, kernel end: 0x{:x}", kernel_start, kernel_end);
    println!("multiboot start: 0x{:x}, multiboot end: 0x{:x}", multiboot_start, multiboot_end);

    let mut frame_allocator = memory::AreaFrameAllocator::new(kernel_start as usize,
        kernel_end as usize, multiboot_start, multiboot_end, memory_map_tag.memory_areas());

    loop{}
}

#[cfg(not(test))]
#[lang = "eh_personality"]
extern fn eh_personality() {}

#[cfg(not(test))]
#[lang = "panic_fmt"]
extern fn panic_fmt(fmt: core::fmt::Arguments, file: &str, line: u32) -> ! {
    println!("\n\nPANIC in {} at line {}:", file, line);
    println!("    {}", fmt);
    loop{}
}
<commit_msg>Test: allocate all frames<commit_after>// Copyright 2015 Philipp Oppermann
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![feature(no_std, lang_items)]
#![feature(const_fn, unique, core_str_ext, iter_cmp)]
#![no_std]

extern crate rlibc;
extern crate spin;
extern crate multiboot2;

#[macro_use]
mod vga_buffer;
mod memory;

#[no_mangle]
pub extern fn rust_main(multiboot_information_address: usize) {
    // ATTENTION: we have a very small stack and no guard page
    vga_buffer::clear_screen();
    println!("Hello World{}", "!");

    let boot_info = unsafe{ multiboot2::load(multiboot_information_address) };
    let memory_map_tag = boot_info.memory_map_tag().expect("Memory map tag required");
    let elf_sections_tag = boot_info.elf_sections_tag().expect("Memory map tag required");

    println!("memory areas:");
    for area in memory_map_tag.memory_areas() {
        println!("    start: 0x{:x}, length: 0x{:x}", area.base_addr, area.length);
    }

    println!("kernel sections:");
    for section in elf_sections_tag.sections() {
        println!("    addr: 0x{:x}, size: 0x{:x}, flags: 0x{:x}",
            section.addr, section.size, section.flags);
    }

    let kernel_start = elf_sections_tag.sections().map(|s| s.addr).min().unwrap();
    let kernel_end = elf_sections_tag.sections().map(|s| s.addr + s.size).max().unwrap();

    let multiboot_start = multiboot_information_address;
    let multiboot_end = multiboot_start + (boot_info.total_size as usize);

    println!("kernel start: 0x{:x}, kernel end: 0x{:x}", kernel_start, kernel_end);
    println!("multiboot start: 0x{:x}, multiboot end: 0x{:x}", multiboot_start, multiboot_end);

    let mut frame_allocator = memory::AreaFrameAllocator::new(kernel_start as usize,
        kernel_end as usize, multiboot_start, multiboot_end, memory_map_tag.memory_areas());

    for i in 0.. {
        if let None = frame_allocator.allocate_frame() {
            println!("allocated {} frames", i);
            break;
        }
    }

    loop{}
}

#[cfg(not(test))]
#[lang = "eh_personality"]
extern fn eh_personality() {}

#[cfg(not(test))]
#[lang = "panic_fmt"]
extern fn panic_fmt(fmt: core::fmt::Arguments, file: &str, line: u32) -> ! {
    println!("\n\nPANIC in {} at line {}:", file, line);
    println!("    {}", fmt);
    loop{}
}
<|endoftext|>


<commit_before>#![deny(missing_docs)]
#![feature(unsafe_destructor)]
#![unstable]

//! A library for setting current values for stack scope,
//! such as application structure.

pub use current::{ Current, CurrentGuard };

use std::rc::Rc;
use std::cell::RefCell;

mod current;

/// Used as warning sign for functions
/// that under normal circumstances works with safe code,
/// but in some edge cases are unsafe.
///
/// 1. The function MUST take `DANGER` as first argument.
///
/// 2. The function MUST take ownership of the value.
///
/// 3. The function docs MUST include a notice `### DANGER`
/// describing the edge case.
///
/// It can not be copied, so an unsafe block is required
/// whenever it is used.
#[allow(missing_copy_implementations)]
#[unstable]
pub struct DANGER(());

#[unstable]
impl DANGER {
    /// Creates a new warning sign for functions
    /// that normally works with safe code
    #[unstable]
    pub unsafe fn new() -> DANGER { DANGER(()) }
}

impl<'a, T, U: GetFrom<T>> GetFrom<&'a RefCell<T>> for U {
    #[inline(always)]
    fn get_from(obj: & &'a RefCell<T>) -> U {
        GetFrom::get_from(obj.borrow().deref())
    }
}

impl<T, U: GetFrom<T>> GetFrom<Rc<RefCell<T>>> for U {
    #[inline(always)]
    fn get_from(obj: &Rc<RefCell<T>>) -> U {
        GetFrom::get_from(obj.borrow().deref())
    }
}

impl<'a, F, T: SetAt<F>> SetAt<&'a RefCell<F>> for T {
    #[inline(always)]
    fn set_at(self, obj: &mut &'a RefCell<F>) {
        self.set_at(obj.borrow_mut().deref_mut())
    }
}

impl<F, T: SetAt<F>> SetAt<Rc<RefCell<F>>> for T {
    #[inline(always)]
    fn set_at(self, obj: &mut Rc<RefCell<F>>) {
        self.set_at(obj.borrow_mut().deref_mut())
    }
}

impl<'a, F, T: ActOn<F, U>, U> ActOn<&'a RefCell<F>, U> for T {
    #[inline(always)]
    fn act_on(self, obj: &mut &'a RefCell<F>) -> U {
        self.act_on(obj.borrow_mut().deref_mut())
    }
}

impl<F, T: ActOn<F, U>, U> ActOn<Rc<RefCell<F>>, U> for T {
    #[inline(always)]
    fn act_on(self, obj: &mut Rc<RefCell<F>>) -> U {
        self.act_on(obj.borrow_mut().deref_mut())
    }
}

/// Something that can be set at an object.
#[unstable]
pub trait SetAt<F> {
    /// Modify `F` with self.
    fn set_at(self, &mut F);
}

/// Automatically implemented through the `SetAt` trait.
#[unstable]
pub trait Set<T> {
    /// Set value.
    fn set(mut self, val: T) -> Self;

    /// Set value through mutable reference.
    fn set_mut(&mut self, val: T) -> &mut Self;
}

impl<T, U: SetAt<T>> Set<U> for T {
    #[inline(always)]
    fn set(mut self, val: U) -> T {
        val.set_at(&mut self);
        self
    }

    #[inline(always)]
    fn set_mut(&mut self, val: U) -> &mut T {
        val.set_at(self);
        self
    }
}

/// Something that can be retrieved from another object.
#[unstable]
pub trait GetFrom<T> {
    /// Gets value from object.
    fn get_from(obj: &T) -> Self;
}

/// Automatically implemented through the `GetFrom` trait.
#[unstable]
pub trait Get<T> {
    /// Returns new value.
    fn get(&self) -> T;
}

impl<T, U: GetFrom<T>> Get<U> for T {
    #[inline(always)]
    fn get(&self) -> U {
        GetFrom::get_from(self)
    }
}

/// Does something to an object.
#[unstable]
pub trait ActOn<T, U> {
    /// Does something to an object.
    fn act_on(self, &mut T) -> U;
}

/// Automatically implemented through the `ActOn` trait.
#[unstable]
pub trait Action<T, U> {
    /// Does something.
    fn action(&mut self, val: T) -> U;
}

impl<T, U: ActOn<T, V>, V> Action<U, V> for T {
    #[inline(always)]
    fn action(&mut self, val: U) -> V {
        val.act_on(self)
    }
}

<commit_msg>Removed `DANGER`<commit_after>#![deny(missing_docs)]
#![feature(unsafe_destructor)]
#![unstable]

//! A library for setting current values for stack scope,
//! such as application structure.

pub use current::{ Current, CurrentGuard };

use std::rc::Rc;
use std::cell::RefCell;

mod current;

impl<'a, T, U: GetFrom<T>> GetFrom<&'a RefCell<T>> for U {
    #[inline(always)]
    fn get_from(obj: & &'a RefCell<T>) -> U {
        GetFrom::get_from(obj.borrow().deref())
    }
}

impl<T, U: GetFrom<T>> GetFrom<Rc<RefCell<T>>> for U {
    #[inline(always)]
    fn get_from(obj: &Rc<RefCell<T>>) -> U {
        GetFrom::get_from(obj.borrow().deref())
    }
}

impl<'a, F, T: SetAt<F>> SetAt<&'a RefCell<F>> for T {
    #[inline(always)]
    fn set_at(self, obj: &mut &'a RefCell<F>) {
        self.set_at(obj.borrow_mut().deref_mut())
    }
}

impl<F, T: SetAt<F>> SetAt<Rc<RefCell<F>>> for T {
    #[inline(always)]
    fn set_at(self, obj: &mut Rc<RefCell<F>>) {
        self.set_at(obj.borrow_mut().deref_mut())
    }
}

impl<'a, F, T: ActOn<F, U>, U> ActOn<&'a RefCell<F>, U> for T {
    #[inline(always)]
    fn act_on(self, obj: &mut &'a RefCell<F>) -> U {
        self.act_on(obj.borrow_mut().deref_mut())
    }
}

impl<F, T: ActOn<F, U>, U> ActOn<Rc<RefCell<F>>, U> for T {
    #[inline(always)]
    fn act_on(self, obj: &mut Rc<RefCell<F>>) -> U {
        self.act_on(obj.borrow_mut().deref_mut())
    }
}

/// Something that can be set at an object.
#[unstable]
pub trait SetAt<F> {
    /// Modify `F` with self.
    fn set_at(self, &mut F);
}

/// Automatically implemented through the `SetAt` trait.
#[unstable]
pub trait Set<T> {
    /// Set value.
    fn set(mut self, val: T) -> Self;

    /// Set value through mutable reference.
    fn set_mut(&mut self, val: T) -> &mut Self;
}

impl<T, U: SetAt<T>> Set<U> for T {
    #[inline(always)]
    fn set(mut self, val: U) -> T {
        val.set_at(&mut self);
        self
    }

    #[inline(always)]
    fn set_mut(&mut self, val: U) -> &mut T {
        val.set_at(self);
        self
    }
}

/// Something that can be retrieved from another object.
#[unstable]
pub trait GetFrom<T> {
    /// Gets value from object.
    fn get_from(obj: &T) -> Self;
}

/// Automatically implemented through the `GetFrom` trait.
#[unstable]
pub trait Get<T> {
    /// Returns new value.
    fn get(&self) -> T;
}

impl<T, U: GetFrom<T>> Get<U> for T {
    #[inline(always)]
    fn get(&self) -> U {
        GetFrom::get_from(self)
    }
}

/// Does something to an object.
#[unstable]
pub trait ActOn<T, U> {
    /// Does something to an object.
    fn act_on(self, &mut T) -> U;
}

/// Automatically implemented through the `ActOn` trait.
#[unstable]
pub trait Action<T, U> {
    /// Does something.
    fn action(&mut self, val: T) -> U;
}

impl<T, U: ActOn<T, V>, V> Action<U, V> for T {
    #[inline(always)]
    fn action(&mut self, val: U) -> V {
        val.act_on(self)
    }
}

<|endoftext|>


<commit_before>#![feature(zero_one)]

extern crate libc;

use std::io::{self, Read, Write};
use std::num::One;
use std::ops::Neg;

mod ffi;

macro_rules! unsafe_try {
    ( $x:expr ) => {
        try!($crate::to_result(unsafe { $x }))
    };
}

pub struct Child {
    pid: libc::pid_t
}

impl Child {
    pub fn pid(&self) -> libc::pid_t { self.pid }

    pub fn wait(&self) {
        unsafe { libc::waitpid(self.pid, std::ptr::null(), 0) };
    }
}

pub struct Master {
    fd: libc::c_int
}

impl Master {
    pub fn fd(&self) -> libc::c_int { self.fd }

    pub fn close(&self) {
        unsafe { libc::close(self.fd) };
    }
}

impl Read for Master {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        match to_result(unsafe {
            libc::read(self.fd,
                       buf.as_mut_ptr() as *mut libc::c_void,
                       buf.len() as libc::size_t)
        }) {
            Ok(nread) => Ok(nread as usize),
            Err(_)    => Ok(0 as usize)
        }
    }
}

impl Write for Master {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let ret = unsafe_try!(
            libc::write(self.fd,
                        buf.as_ptr() as *const libc::c_void,
                        buf.len() as libc::size_t)
        );

        Ok(ret as usize)
    }

    fn flush(&mut self) -> io::Result<()> { Ok(()) }
}

impl Copy for Master {}

impl Clone for Master {
    fn clone(&self) -> Master { *self }
}

pub fn fork() -> io::Result<(Child, Master)>
{
    let pty_master = try!(open_ptm());
    let pid        = unsafe_try!(libc::fork());

    if pid == 0 {
        try!(attach_pts(pty_master));

        Ok((Child { pid: pid }, Master { fd: -1 }))
    }
    else {
        Ok((Child { pid: pid }, Master { fd: pty_master }))
    }
}

fn open_ptm() -> io::Result<libc::c_int> {
    let pty_master = unsafe_try!(ffi::posix_openpt(libc::O_RDWR));

    unsafe_try!(ffi::grantpt(pty_master));
    unsafe_try!(ffi::unlockpt(pty_master));

    Ok(pty_master)
}

fn attach_pts(pty_master: libc::c_int) -> io::Result<()> {
    let pts_name = unsafe { ffi::ptsname(pty_master) };

    if (pts_name as *const i32) == std::ptr::null() {
        return Err(io::Error::last_os_error())
    }

    unsafe_try!(libc::close(pty_master));
    unsafe_try!(libc::setsid());

    let pty_slave = unsafe_try!(libc::open(pts_name, libc::O_RDWR, 0));

    unsafe_try!(libc::dup2(pty_slave, libc::STDIN_FILENO));
    unsafe_try!(libc::dup2(pty_slave, libc::STDOUT_FILENO));
    unsafe_try!(libc::dup2(pty_slave, libc::STDERR_FILENO));

    unsafe_try!(libc::close(pty_slave));

    Ok(())
}

#[inline]
fn to_result<T: One + PartialEq + Neg<Output=T>>(t: T) -> io::Result<T> {
    let one: T = T::one();

    if t == -one {
        Err(io::Error::last_os_error())
    } else {
        Ok(t)
    }
}

#[cfg(test)]
mod tests {
    extern crate libc;

    use std::ffi::CString;
    use std::io::Read;
    use std::process::{Command, Stdio};
    use std::ptr;
    use std::string::String;
    use super::fork;

    #[test]
    fn it_fork_with_new_pty() {
        let (child, mut master) = fork().unwrap();

        if child.pid() == 0 {
            let mut ptrs = [CString::new("tty").unwrap().as_ptr(), ptr::null()];

            unsafe { libc::execvp(*ptrs.as_ptr(), ptrs.as_mut_ptr()) };
        }
        else {
            let mut string = String::new();

            match master.read_to_string(&mut string) {
                Ok(_)  => {
                    let output = Command::new("tty").stdin(Stdio::inherit()).output().unwrap().stdout;

                    let parent_tty = String::from_utf8_lossy(&output);
                    let child_tty  = string.trim();

                    assert!(child_tty != "");
                    assert!(child_tty != parent_tty);

                    let mut parent_tty_dir: Vec<&str> = parent_tty.split("/").collect();
                    let mut child_tty_dir:  Vec<&str> = child_tty.split("/").collect();

                    parent_tty_dir.pop();
                    child_tty_dir.pop();

                    assert_eq!(parent_tty_dir, child_tty_dir);
                },
                Err(e) => panic!("{}", e)
            }

            child.wait();
            master.close();
        }
    }
}
<commit_msg>Add a test for read/write<commit_after>#![feature(zero_one)]

extern crate libc;

use std::io::{self, Read, Write};
use std::num::One;
use std::ops::Neg;

mod ffi;

macro_rules! unsafe_try {
    ( $x:expr ) => {
        try!($crate::to_result(unsafe { $x }))
    };
}

pub struct Child {
    pid: libc::pid_t
}

impl Child {
    pub fn pid(&self) -> libc::pid_t { self.pid }

    pub fn wait(&self) {
        unsafe { libc::waitpid(self.pid, std::ptr::null(), 0) };
    }
}

pub struct Master {
    fd: libc::c_int
}

impl Master {
    pub fn fd(&self) -> libc::c_int { self.fd }

    pub fn close(&self) {
        unsafe { libc::close(self.fd) };
    }
}

impl Read for Master {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        match to_result(unsafe {
            libc::read(self.fd,
                       buf.as_mut_ptr() as *mut libc::c_void,
                       buf.len() as libc::size_t)
        }) {
            Ok(nread) => Ok(nread as usize),
            Err(_)    => Ok(0 as usize)
        }
    }
}

impl Write for Master {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let ret = unsafe_try!(
            libc::write(self.fd,
                        buf.as_ptr() as *const libc::c_void,
                        buf.len() as libc::size_t)
        );

        Ok(ret as usize)
    }

    fn flush(&mut self) -> io::Result<()> { Ok(()) }
}

impl Copy for Master {}

impl Clone for Master {
    fn clone(&self) -> Master { *self }
}

pub fn fork() -> io::Result<(Child, Master)>
{
    let pty_master = try!(open_ptm());
    let pid        = unsafe_try!(libc::fork());

    if pid == 0 {
        try!(attach_pts(pty_master));

        Ok((Child { pid: pid }, Master { fd: -1 }))
    }
    else {
        Ok((Child { pid: pid }, Master { fd: pty_master }))
    }
}

fn open_ptm() -> io::Result<libc::c_int> {
    let pty_master = unsafe_try!(ffi::posix_openpt(libc::O_RDWR));

    unsafe_try!(ffi::grantpt(pty_master));
    unsafe_try!(ffi::unlockpt(pty_master));

    Ok(pty_master)
}

fn attach_pts(pty_master: libc::c_int) -> io::Result<()> {
    let pts_name = unsafe { ffi::ptsname(pty_master) };

    if (pts_name as *const i32) == std::ptr::null() {
        return Err(io::Error::last_os_error())
    }

    unsafe_try!(libc::close(pty_master));
    unsafe_try!(libc::setsid());

    let pty_slave = unsafe_try!(libc::open(pts_name, libc::O_RDWR, 0));

    unsafe_try!(libc::dup2(pty_slave, libc::STDIN_FILENO));
    unsafe_try!(libc::dup2(pty_slave, libc::STDOUT_FILENO));
    unsafe_try!(libc::dup2(pty_slave, libc::STDERR_FILENO));

    unsafe_try!(libc::close(pty_slave));

    Ok(())
}

#[inline]
fn to_result<T: One + PartialEq + Neg<Output=T>>(t: T) -> io::Result<T> {
    let one: T = T::one();

    if t == -one {
        Err(io::Error::last_os_error())
    } else {
        Ok(t)
    }
}

#[cfg(test)]
mod tests {
    extern crate libc;

    use std::ffi::CString;
    use std::io::{Read, Write};
    use std::process::{Command, Stdio};
    use std::ptr;
    use std::string::String;
    use super::fork;

    #[test]
    fn it_fork_with_new_pty() {
        let (child, mut master) = fork().unwrap();

        if child.pid() == 0 {
            let mut ptrs = [CString::new("tty").unwrap().as_ptr(), ptr::null()];

            unsafe { libc::execvp(*ptrs.as_ptr(), ptrs.as_mut_ptr()) };
        }
        else {
            let mut string = String::new();

            match master.read_to_string(&mut string) {
                Ok(_)  => {
                    let output = Command::new("tty").stdin(Stdio::inherit()).output().unwrap().stdout;

                    let parent_tty = String::from_utf8_lossy(&output);
                    let child_tty  = string.trim();

                    assert!(child_tty != "");
                    assert!(child_tty != parent_tty);

                    let mut parent_tty_dir: Vec<&str> = parent_tty.split("/").collect();
                    let mut child_tty_dir:  Vec<&str> = child_tty.split("/").collect();

                    parent_tty_dir.pop();
                    child_tty_dir.pop();

                    assert_eq!(parent_tty_dir, child_tty_dir);
                },
                Err(e) => panic!("{}", e)
            }

            child.wait();
            master.close();
        }
    }

    #[test]
    fn it_can_read_write() {
        let (child, mut master) = fork().unwrap();

        if child.pid() == 0 {
            let mut ptrs = [CString::new("bash").unwrap().as_ptr(), ptr::null()];

            print!(" "); // FIXME I'm not sure but this is needed to prevent read-block.

            unsafe { libc::execvp(*ptrs.as_ptr(), ptrs.as_mut_ptr()) };
        }
        else {
            let _ = master.write("echo readme!\n".to_string().as_bytes());

            let mut string = String::new();

            match master.read_to_string(&mut string) {
                Ok(_)  => {
                    assert!(string.contains("readme!"));
                },
                Err(e) => panic!("{}", e)
            }

            let _ = master.write("exit\n".to_string().as_bytes());

            child.wait();
            master.close();
        }
    }
}
<|endoftext|>


<commit_before>//! An implementation of [FLAC](https://xiph.org/flac), free lossless audio
//! codec, written in Rust.
//!
//! # Examples
//!
//! Basic decoding from a file.
//!
//! ```
//! use flac::{Stream, ReadStream};
//! use std::fs::File;
//!
//! match Stream::<ReadStream<File>>::from_file("path/to/file.flac") {
//!   Ok(mut stream) => {
//!     // Copy of `StreamInfo` to help convert to a different audio format.
//!     let info = stream.info();
//!
//!     for sample in stream.iter() {
//!       // Iterate over each decoded sample
//!     }
//!   }
//!   Err(error)     => println!("{}", error),
//! }
//! ```

#[macro_use]
extern crate nom;

#[macro_use]
mod utility;
mod frame;
mod subframe;
pub mod metadata;
pub mod stream;

pub use metadata::Metadata;
pub use stream::Stream;
pub use utility::{StreamProducer, ReadStream, ByteStream};
<commit_msg>Add GitHub link within the documentation<commit_after>//! An implementation of [FLAC](https://xiph.org/flac), free lossless audio
//! codec, written in Rust.
//!
//! The code is available on [GitHub](https://github.com/sourrust/flac).
//!
//! # Examples
//!
//! Basic decoding from a file.
//!
//! ```
//! use flac::{Stream, ReadStream};
//! use std::fs::File;
//!
//! match Stream::<ReadStream<File>>::from_file("path/to/file.flac") {
//!   Ok(mut stream) => {
//!     // Copy of `StreamInfo` to help convert to a different audio format.
//!     let info = stream.info();
//!
//!     for sample in stream.iter() {
//!       // Iterate over each decoded sample
//!     }
//!   }
//!   Err(error)     => println!("{}", error),
//! }
//! ```

#[macro_use]
extern crate nom;

#[macro_use]
mod utility;
mod frame;
mod subframe;
pub mod metadata;
pub mod stream;

pub use metadata::Metadata;
pub use stream::Stream;
pub use utility::{StreamProducer, ReadStream, ByteStream};
<|endoftext|>


<commit_before>#[cfg(feature = "parsing")]
#[macro_use]
extern crate nom;

#[cfg(feature = "printing")]
extern crate quote;

#[macro_use]
mod do_parse;

#[macro_use]
mod helper;

mod attr;
pub use attr::{
    Attribute,
    MetaItem,
};

mod generics;
pub use generics::{
    Generics,
    Lifetime,
    LifetimeDef,
    TraitBoundModifier,
    TyParam,
    TyParamBound,
    WhereBoundPredicate,
    WhereClause,
    WherePredicate,
    WhereRegionPredicate,
};

mod ident;
pub use ident::{
    Ident,
};

mod item;
pub use item::{
    Body,
    Field,
    Item,
    Variant,
    VariantData,
    Visibility,
};

mod ty;
pub use ty::{
    AngleBracketedParameterData,
    BareFnTy,
    FnArg,
    FnDecl,
    FunctionRetTy,
    MutTy,
    Mutability,
    ParenthesizedParameterData,
    Path,
    PathParameters,
    PathSegment,
    PolyTraitRef,
    QSelf,
    Ty,
    TypeBinding,
};

#[cfg(feature = "aster")]
pub mod aster;

#[cfg(feature = "visit")]
pub mod visit;

#[cfg(feature = "parsing")]
pub use parsing::*;

#[cfg(feature = "parsing")]
mod parsing {
    use super::*;
    use {generics, item, ty};
    use nom;

    pub fn parse_item(input: &str) -> Result<Item, String> {
        unwrap("item", item::parsing::item(input))
    }

    pub fn parse_path(input: &str) -> Result<Path, String> {
        unwrap("path", ty::parsing::path(input))
    }

    pub fn parse_where_clause(input: &str) -> Result<WhereClause, String> {
        unwrap("where clause", generics::parsing::where_clause(input))
    }

    fn unwrap<T>(name: &'static str, ires: nom::IResult<&str, T>) -> Result<T, String> {
        return match ires {
            nom::IResult::Done(rest, t) => {
                if rest.is_empty() {
                    Ok(t)
                } else {
                    Err(format!("remaining tokens after {}: {:?}", name, rest))
                }
            }
            nom::IResult::Error(err) => Err(root_cause(err)),
            nom::IResult::Incomplete(_) => Err(format!("incomplete {}", name)),
        };

        fn root_cause(mut err: nom::Err<&str>) -> String {
            loop {
                match err {
                    nom::Err::Code(kind) => {
                        return format!("failed to parse {:?}", kind);
                    }
                    nom::Err::Position(kind, pos) => {
                        return format!("failed to parse {:?}: {:?}", kind, pos);
                    }
                    nom::Err::Node(_, next) |
                    nom::Err::NodePosition(_, _, next) => {
                        err = *next;
                    }
                }
            }
        }
    }
}
<commit_msg>Public type parser<commit_after>#[cfg(feature = "parsing")]
#[macro_use]
extern crate nom;

#[cfg(feature = "printing")]
extern crate quote;

#[macro_use]
mod do_parse;

#[macro_use]
mod helper;

mod attr;
pub use attr::{
    Attribute,
    MetaItem,
};

mod generics;
pub use generics::{
    Generics,
    Lifetime,
    LifetimeDef,
    TraitBoundModifier,
    TyParam,
    TyParamBound,
    WhereBoundPredicate,
    WhereClause,
    WherePredicate,
    WhereRegionPredicate,
};

mod ident;
pub use ident::{
    Ident,
};

mod item;
pub use item::{
    Body,
    Field,
    Item,
    Variant,
    VariantData,
    Visibility,
};

mod ty;
pub use ty::{
    AngleBracketedParameterData,
    BareFnTy,
    FnArg,
    FnDecl,
    FunctionRetTy,
    MutTy,
    Mutability,
    ParenthesizedParameterData,
    Path,
    PathParameters,
    PathSegment,
    PolyTraitRef,
    QSelf,
    Ty,
    TypeBinding,
};

#[cfg(feature = "aster")]
pub mod aster;

#[cfg(feature = "visit")]
pub mod visit;

#[cfg(feature = "parsing")]
pub use parsing::*;

#[cfg(feature = "parsing")]
mod parsing {
    use super::*;
    use {generics, item, ty};
    use nom;

    pub fn parse_item(input: &str) -> Result<Item, String> {
        unwrap("item", item::parsing::item(input))
    }

    pub fn parse_type(input: &str) -> Result<Ty, String> {
        unwrap("type", ty::parsing::ty(input))
    }

    pub fn parse_path(input: &str) -> Result<Path, String> {
        unwrap("path", ty::parsing::path(input))
    }

    pub fn parse_where_clause(input: &str) -> Result<WhereClause, String> {
        unwrap("where clause", generics::parsing::where_clause(input))
    }

    fn unwrap<T>(name: &'static str, ires: nom::IResult<&str, T>) -> Result<T, String> {
        return match ires {
            nom::IResult::Done(rest, t) => {
                if rest.is_empty() {
                    Ok(t)
                } else {
                    Err(format!("remaining tokens after {}: {:?}", name, rest))
                }
            }
            nom::IResult::Error(err) => Err(root_cause(err)),
            nom::IResult::Incomplete(_) => Err(format!("incomplete {}", name)),
        };

        fn root_cause(mut err: nom::Err<&str>) -> String {
            loop {
                match err {
                    nom::Err::Code(kind) => {
                        return format!("failed to parse {:?}", kind);
                    }
                    nom::Err::Position(kind, pos) => {
                        return format!("failed to parse {:?}: {:?}", kind, pos);
                    }
                    nom::Err::Node(_, next) |
                    nom::Err::NodePosition(_, _, next) => {
                        err = *next;
                    }
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>//! This crate provides a generate that constructs random name strings suitable
//! for use in container instances, project names, application instances, etc.
//!
//! The name `Generator` implements the `Iterator` trait so it can be used with
//! adapters, consumers, and in loops.
//!
//! # Usage
//!
//! This crate is [on crates.io](https://crates.io/crates/names) and can be
//! used by adding `names` to your dependencies in your project's `Cargo.toml`
//! file:
//!
//! ```toml
//! [dependencies]
//! names = "0.9.0"
//! ```
//!
//! and this to your crate root:
//!
//! ```
//! extern crate names;
//! ```
//!
//! # Example: painless defaults
//!
//! The easiest way to get started is to use the default `Generator` to return
//! a name:
//!
//! ```
//! use names::Generator;
//!
//! let mut generator = Generator::default();
//! println!("Your project is: {}", generator.next().unwrap());
//! // #=> "Your project is: rusty-nail"
//! ```
//!
//! If more randomness is required, you can generate a name with a trailing
//! 4-digit number:
//!
//! ```
//! use names::{Generator, Name};
//!
//! let mut generator = Generator::with_naming(Name::Numbered);
//! println!("Your project is: {}", generator.next().unwrap());
//! // #=> "Your project is: pushy-pencil-5602"
//! ```
//!
//! # Example: with custom dictionaries
//!
//! If you would rather supply your own custom adjective and noun word lists,
//! you can provide your own by supplying 2 string slices. For example,
//! this returns only one result:
//!
//! ```
//! use names::{Generator, Name};
//!
//! let adjectives = &["imaginary"];
//! let nouns = &["roll"];
//! let mut generator = Generator::new(adjectives, nouns, Name::default());
//!
//! assert_eq!("imaginary-roll", generator.next().unwrap());
//! ```

extern crate rand;

use rand::Rng;

pub const ADJECTIVES: &'static [&'static str] = &include!(concat!(env!("OUT_DIR"),
                                                                  "/adjectives.rs"));

pub const NOUNS: &'static [&'static str] = &include!(concat!(env!("OUT_DIR"), "/nouns.rs"));

/// A naming strategy for the `Generator`
pub enum Name {
    /// This represents a plain naming strategy of the form `"ADJECTIVE-NOUN"`
    Plain,
    /// This represents a naming strategy with a random number appended to the
    /// end, of the form `"ADJECTIVE-NOUN-NUMBER"`
    Numbered,
}

impl Default for Name {
    fn default() -> Self {
        Name::Plain
    }
}

/// A random name generator which combines an adjective, a noun, and an
/// optional number
///
/// A `Generator` takes a slice of adjective and noun words strings and has
/// a naming strategy (with or without a number appended).
pub struct Generator<'a> {
    adjectives: &'a [&'a str],
    nouns: &'a [&'a str],
    naming: Name,
}

impl<'a> Generator<'a> {
    /// Constructs a new `Generator<'a>`
    ///
    /// # Examples
    ///
    /// ```
    /// use names::{Generator, Name};
    ///
    /// let adjectives = &["sassy"];
    /// let nouns = &["clocks"];
    /// let naming = Name::Plain;
    ///
    /// let mut generator = Generator::new(adjectives, nouns, naming);
    ///
    /// assert_eq!("sassy-clocks", generator.next().unwrap());
    /// ```
    pub fn new(adjectives: &'a [&'a str], nouns: &'a [&'a str], naming: Name) -> Self {
        Generator {
            adjectives: adjectives,
            nouns: nouns,
            naming: naming,
        }
    }

    /// Construct and returns a default `Generator<'a>` containing a large
    /// collection of adjectives and nouns
    ///
    /// ```
    /// use names::{Generator, Name};
    ///
    /// let mut generator = Generator::with_naming(Name::Plain);
    ///
    /// println!("My new name is: {}", generator.next().unwrap());
    /// ```
    pub fn with_naming(naming: Name) -> Self {
        Generator::new(ADJECTIVES, NOUNS, naming)
    }

    fn rand_adj(&self) -> &str {
        rand::thread_rng().choose(self.adjectives).unwrap()
    }

    fn rand_noun(&self) -> &str {
        rand::thread_rng().choose(self.nouns).unwrap()
    }

    fn rand_num(&self) -> u16 {
        rand::thread_rng().gen_range(1, 10000)
    }
}

impl<'a> Default for Generator<'a> {
    fn default() -> Self {
        Generator::new(ADJECTIVES, NOUNS, Name::default())
    }
}

impl<'a> Iterator for Generator<'a> {
    type Item = String;

    fn next(&mut self) -> Option<String> {
        let adj = self.rand_adj();
        let noun = self.rand_noun();

        Some(match self.naming {
            Name::Plain => format!("{}-{}", adj, noun),
            Name::Numbered => format!("{}-{}-{:04}", adj, noun, self.rand_num()),
        })
    }
}
<commit_msg>[lint] Update formatting due to Rustfmt 0.9.0.<commit_after>//! This crate provides a generate that constructs random name strings suitable
//! for use in container instances, project names, application instances, etc.
//!
//! The name `Generator` implements the `Iterator` trait so it can be used with
//! adapters, consumers, and in loops.
//!
//! # Usage
//!
//! This crate is [on crates.io](https://crates.io/crates/names) and can be
//! used by adding `names` to your dependencies in your project's `Cargo.toml`
//! file:
//!
//! ```toml
//! [dependencies]
//! names = "0.9.0"
//! ```
//!
//! and this to your crate root:
//!
//! ```
//! extern crate names;
//! ```
//!
//! # Example: painless defaults
//!
//! The easiest way to get started is to use the default `Generator` to return
//! a name:
//!
//! ```
//! use names::Generator;
//!
//! let mut generator = Generator::default();
//! println!("Your project is: {}", generator.next().unwrap());
//! // #=> "Your project is: rusty-nail"
//! ```
//!
//! If more randomness is required, you can generate a name with a trailing
//! 4-digit number:
//!
//! ```
//! use names::{Generator, Name};
//!
//! let mut generator = Generator::with_naming(Name::Numbered);
//! println!("Your project is: {}", generator.next().unwrap());
//! // #=> "Your project is: pushy-pencil-5602"
//! ```
//!
//! # Example: with custom dictionaries
//!
//! If you would rather supply your own custom adjective and noun word lists,
//! you can provide your own by supplying 2 string slices. For example,
//! this returns only one result:
//!
//! ```
//! use names::{Generator, Name};
//!
//! let adjectives = &["imaginary"];
//! let nouns = &["roll"];
//! let mut generator = Generator::new(adjectives, nouns, Name::default());
//!
//! assert_eq!("imaginary-roll", generator.next().unwrap());
//! ```

extern crate rand;

use rand::Rng;

pub const ADJECTIVES: &'static [&'static str] =
    &include!(concat!(env!("OUT_DIR"), "/adjectives.rs"));

pub const NOUNS: &'static [&'static str] = &include!(concat!(env!("OUT_DIR"), "/nouns.rs"));

/// A naming strategy for the `Generator`
pub enum Name {
    /// This represents a plain naming strategy of the form `"ADJECTIVE-NOUN"`
    Plain,
    /// This represents a naming strategy with a random number appended to the
    /// end, of the form `"ADJECTIVE-NOUN-NUMBER"`
    Numbered,
}

impl Default for Name {
    fn default() -> Self {
        Name::Plain
    }
}

/// A random name generator which combines an adjective, a noun, and an
/// optional number
///
/// A `Generator` takes a slice of adjective and noun words strings and has
/// a naming strategy (with or without a number appended).
pub struct Generator<'a> {
    adjectives: &'a [&'a str],
    nouns: &'a [&'a str],
    naming: Name,
}

impl<'a> Generator<'a> {
    /// Constructs a new `Generator<'a>`
    ///
    /// # Examples
    ///
    /// ```
    /// use names::{Generator, Name};
    ///
    /// let adjectives = &["sassy"];
    /// let nouns = &["clocks"];
    /// let naming = Name::Plain;
    ///
    /// let mut generator = Generator::new(adjectives, nouns, naming);
    ///
    /// assert_eq!("sassy-clocks", generator.next().unwrap());
    /// ```
    pub fn new(adjectives: &'a [&'a str], nouns: &'a [&'a str], naming: Name) -> Self {
        Generator {
            adjectives: adjectives,
            nouns: nouns,
            naming: naming,
        }
    }

    /// Construct and returns a default `Generator<'a>` containing a large
    /// collection of adjectives and nouns
    ///
    /// ```
    /// use names::{Generator, Name};
    ///
    /// let mut generator = Generator::with_naming(Name::Plain);
    ///
    /// println!("My new name is: {}", generator.next().unwrap());
    /// ```
    pub fn with_naming(naming: Name) -> Self {
        Generator::new(ADJECTIVES, NOUNS, naming)
    }

    fn rand_adj(&self) -> &str {
        rand::thread_rng().choose(self.adjectives).unwrap()
    }

    fn rand_noun(&self) -> &str {
        rand::thread_rng().choose(self.nouns).unwrap()
    }

    fn rand_num(&self) -> u16 {
        rand::thread_rng().gen_range(1, 10000)
    }
}

impl<'a> Default for Generator<'a> {
    fn default() -> Self {
        Generator::new(ADJECTIVES, NOUNS, Name::default())
    }
}

impl<'a> Iterator for Generator<'a> {
    type Item = String;

    fn next(&mut self) -> Option<String> {
        let adj = self.rand_adj();
        let noun = self.rand_noun();

        Some(match self.naming {
            Name::Plain => format!("{}-{}", adj, noun),
            Name::Numbered => format!("{}-{}-{:04}", adj, noun, self.rand_num()),
        })
    }
}
<|endoftext|>


<commit_before>//! A collection of synchronization primitives that build on the primitives available in the
//! standard library.

mod util;

use std::sync::{Mutex, Condvar};
use std::time::Duration;

/// A synchronization primitive that signals when its count reaches zero.
///
/// With a `CountdownEvent`, it's possible to cause one thread to wait on a set of computations
/// occurring in other threads by making the other threads interact with the counter as they perform
/// their work.
///
/// The main limitation of a CountdownEvent is that once its counter reaches zero (even by starting
/// there), any attempts to update the counter will return `CountdownError::AlreadySet` until the
/// counter is reset by calling `reset` or `reset_to_count`.
///
/// # Example
///
/// ```
/// use synchronoise::CountdownEvent;
/// use std::sync::Arc;
/// use std::thread;
/// use std::time::Duration;
///
/// let counter = Arc::new(CountdownEvent::new(5));
///
/// for i in 0..5 {
///     let signal = counter.clone();
///     thread::spawn(move || {
///         thread::sleep(Duration::from_secs(3));
///         println!("thread {} activated!", i);
///         signal.decrement();
///     });
/// }
///
/// counter.wait();
///
/// println!("all done!");
/// ```
pub struct CountdownEvent {
    initial: isize,
    counter: Mutex<isize>,
    lock: Condvar,
}

///The collection of errors that can be returned by `CountdownEvent` methods.
pub enum CountdownError {
    ///Returned when adding to a counter would have caused it to overflow.
    SaturatedCounter,
    ///Returned when attempting to signal would have caused the counter to go below zero.
    TooManySignals,
    ///Returned when attempting to modify the counter after it has reached zero.
    AlreadySet,
}

impl CountdownEvent {
    ///Creates a new `CountdownEvent`, initialized to the given count.
    pub fn new(count: isize) -> CountdownEvent {
        CountdownEvent {
            initial: count,
            counter: Mutex::new(count),
            lock: Condvar::new(),
        }
    }

    ///Resets the counter to the count given to `new`.
    ///
    ///This function is safe because the `&mut self` enforces that no other references or locks
    ///exist.
    pub fn reset(&mut self) {
        self.counter = Mutex::new(self.initial);
        self.lock = Condvar::new();
    }

    ///Resets the counter to the given count.
    ///
    ///This function is safe because the `&mut self` enforces that no other references or locks
    ///exist.
    pub fn reset_to_count(&mut self, count: isize) {
        self.initial = count;
        self.reset();
    }

    ///Returns the current counter value.
    pub fn count(&self) -> isize {
        let lock = util::guts(self.counter.lock());

        *lock
    }

    ///Adds the given count to the counter.
    ///
    ///# Errors
    ///
    ///If the counter is already at or below zero, this function will return an error.
    ///
    ///If the given count would overflow an `isize`, this function will return an error.
    pub fn add(&self, count: isize) -> Result<(), CountdownError> {
        let mut lock = util::guts(self.counter.lock());

        if *lock <= 0 {
            return Err(CountdownError::AlreadySet);
        }

        if let Some(new_count) = count.checked_add(*lock) {
            *lock = new_count;
        } else {
            return Err(CountdownError::SaturatedCounter);
        }

        Ok(())
    }

    ///Subtracts the given count to the counter, and returns whether this caused any waiting
    ///threads to wake up.
    ///
    ///# Errors
    ///
    ///If the counter was already at or below zero, this function will return an error.
    ///
    ///If the given count is greater than the current counter, this function will return an error.
    pub fn signal(&self, count: isize) -> Result<bool, CountdownError> {
        let mut lock = util::guts(self.counter.lock());

        if *lock == 0 {
            return Err(CountdownError::AlreadySet);
        }

        if count <= *lock {
            *lock -= count;
        } else {
            return Err(CountdownError::TooManySignals);
        }

        if *lock == 0 {
            self.lock.notify_all();
            Ok(true)
        } else {
            Ok(false)
        }
    }

    ///Adds one to the count.
    ///
    ///# Errors
    ///
    ///See [`add`] for the situations where this function will return an error.
    ///
    ///[`add`]: #method.add
    pub fn increment(&self) -> Result<(), CountdownError> {
        self.add(1)
    }

    ///Subtracts one from the counter, and returns whether this caused any waiting threads to wake
    ///up.
    ///
    ///# Errors
    ///
    ///See [`signal`] for the situations where this function will return an error.
    ///
    ///[`signal`]: #method.signal
    pub fn decrement(&self) -> Result<bool, CountdownError> {
        self.signal(1)
    }

    ///Blocks the current thread until the counter reaches zero.
    ///
    ///This function will block indefinitely until the counter reaches zero. It will return
    ///immediately if it is already at zero.
    pub fn wait(&self) {
        let mut count = util::guts(self.counter.lock());

        while *count > 0 {
            count = util::guts(self.lock.wait(count));
        }
    }

    ///Blocks the current thread until the timer reaches zero, or until the given timeout elapses,
    ///returning the count at the time of wakeup and whether the timeout is known to have elapsed.
    ///
    ///This function will return immediately if the counter was already at zero. Otherwise, it will
    ///block for roughly no longer than `timeout`. Due to limitations in the platform specific
    ///implementation of `std::sync::Condvar`, this method could spuriously wake up both before the timeout
    ///elapsed and without the count being zero.
    pub fn wait_timeout(&self, timeout: Duration) -> (isize, bool) {
        let count = util::guts(self.counter.lock());

        if *count == 0 {
            return (*count, false);
        }

        let (count, status) = util::guts(self.lock.wait_timeout(count, timeout));

        (*count, status.timed_out())
    }
}

///Determines the reset behavior of a `SignalEvent`.
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum SignalKind {
    ///An activated `SignalEvent` automatically resets when a thread is resumed.
    ///
    ///`SignalEvent`s with this kind will only resume one thread at a time.
    Auto,
    ///An activated `SignalEvent` must be manually reset to block threads again.
    ///
    ///`SignalEvent`s with this kind will signal every waiting thread to continue at once.
    Manual,
}

/// A synchronization primitive that allows one or more threads to wait on a signal from another
/// thread.
pub struct SignalEvent {
    reset: SignalKind,
    signal: Mutex<bool>,
    lock: Condvar,
}

impl SignalEvent {
    ///Creates a new `SignalEvent` with the given starting state and reset behavior.
    pub fn new(init_state: bool, signal_kind: SignalKind) -> SignalEvent {
        SignalEvent {
            reset: signal_kind,
            signal: Mutex::new(init_state),
            lock: Condvar::new(),
        }
    }

    ///Returns the current signal status of the `SignalEvent`.
    pub fn status(&self) -> bool {
        let signal = util::guts(self.signal.lock());

        *signal
    }

    ///Sets the signal on this `SignalEvent`, potentially waking up one or all threads waiting on
    ///it.
    pub fn signal(&self) {
        let mut signal = util::guts(self.signal.lock());

        *signal = true;

        match self.reset {
            SignalKind::Auto => self.lock.notify_one(),
            SignalKind::Manual => self.lock.notify_all(),
        }
    }

    ///Resets the signal on this `SignalEvent`, allowing threads that wait on it to block.
    pub fn reset(&self) {
        let mut signal = util::guts(self.signal.lock());

        *signal = false;
    }

    ///Blocks this thread until another thread calls `signal`.
    pub fn wait(&self) {
        let mut signal = util::guts(self.signal.lock());

        while !*signal {
            signal = util::guts(self.lock.wait(signal));
        }

        if self.reset == SignalKind::Auto {
            //don't want to call self.reset() since it would deadlock the mutex
            *signal = false;
        }
    }

    ///Blocks this thread until either another thread calls `signal`, or until the timeout elapses.
    ///
    ///This function returns both the status of the signal when it woke up, and whether the timeout
    ///was known to have elapsed. Note that due to platform-specific implementations of
    ///`std::sync::Condvar`, it's possible for this wait to spuriously wake up when neither the
    ///signal was set nor the timeout had elapsed.
    pub fn wait_timeout(&self, timeout: Duration) -> (bool, bool) {
        let mut signal = util::guts(self.signal.lock());

        if *signal {
            if self.reset == SignalKind::Auto {
                *signal = false;
            }
            return (true, false);
        }

        let (mut signal, status) = util::guts(self.lock.wait_timeout(signal, timeout));
        let ret = *signal;

        if self.reset == SignalKind::Auto {
            *signal = false;
        }

        (ret, status.timed_out())
    }
}
<commit_msg>add note to docs about the name of the crate<commit_after>//! A collection of synchronization primitives that build on the primitives available in the
//! standard library.
//!
//! Name source: http://bulbapedia.bulbagarden.net/wiki/Synchronoise_(move)

mod util;

use std::sync::{Mutex, Condvar};
use std::time::Duration;

/// A synchronization primitive that signals when its count reaches zero.
///
/// With a `CountdownEvent`, it's possible to cause one thread to wait on a set of computations
/// occurring in other threads by making the other threads interact with the counter as they perform
/// their work.
///
/// The main limitation of a CountdownEvent is that once its counter reaches zero (even by starting
/// there), any attempts to update the counter will return `CountdownError::AlreadySet` until the
/// counter is reset by calling `reset` or `reset_to_count`.
///
/// # Example
///
/// ```
/// use synchronoise::CountdownEvent;
/// use std::sync::Arc;
/// use std::thread;
/// use std::time::Duration;
///
/// let counter = Arc::new(CountdownEvent::new(5));
///
/// for i in 0..5 {
///     let signal = counter.clone();
///     thread::spawn(move || {
///         thread::sleep(Duration::from_secs(3));
///         println!("thread {} activated!", i);
///         signal.decrement();
///     });
/// }
///
/// counter.wait();
///
/// println!("all done!");
/// ```
pub struct CountdownEvent {
    initial: isize,
    counter: Mutex<isize>,
    lock: Condvar,
}

///The collection of errors that can be returned by `CountdownEvent` methods.
pub enum CountdownError {
    ///Returned when adding to a counter would have caused it to overflow.
    SaturatedCounter,
    ///Returned when attempting to signal would have caused the counter to go below zero.
    TooManySignals,
    ///Returned when attempting to modify the counter after it has reached zero.
    AlreadySet,
}

impl CountdownEvent {
    ///Creates a new `CountdownEvent`, initialized to the given count.
    pub fn new(count: isize) -> CountdownEvent {
        CountdownEvent {
            initial: count,
            counter: Mutex::new(count),
            lock: Condvar::new(),
        }
    }

    ///Resets the counter to the count given to `new`.
    ///
    ///This function is safe because the `&mut self` enforces that no other references or locks
    ///exist.
    pub fn reset(&mut self) {
        self.counter = Mutex::new(self.initial);
        self.lock = Condvar::new();
    }

    ///Resets the counter to the given count.
    ///
    ///This function is safe because the `&mut self` enforces that no other references or locks
    ///exist.
    pub fn reset_to_count(&mut self, count: isize) {
        self.initial = count;
        self.reset();
    }

    ///Returns the current counter value.
    pub fn count(&self) -> isize {
        let lock = util::guts(self.counter.lock());

        *lock
    }

    ///Adds the given count to the counter.
    ///
    ///# Errors
    ///
    ///If the counter is already at or below zero, this function will return an error.
    ///
    ///If the given count would overflow an `isize`, this function will return an error.
    pub fn add(&self, count: isize) -> Result<(), CountdownError> {
        let mut lock = util::guts(self.counter.lock());

        if *lock <= 0 {
            return Err(CountdownError::AlreadySet);
        }

        if let Some(new_count) = count.checked_add(*lock) {
            *lock = new_count;
        } else {
            return Err(CountdownError::SaturatedCounter);
        }

        Ok(())
    }

    ///Subtracts the given count to the counter, and returns whether this caused any waiting
    ///threads to wake up.
    ///
    ///# Errors
    ///
    ///If the counter was already at or below zero, this function will return an error.
    ///
    ///If the given count is greater than the current counter, this function will return an error.
    pub fn signal(&self, count: isize) -> Result<bool, CountdownError> {
        let mut lock = util::guts(self.counter.lock());

        if *lock == 0 {
            return Err(CountdownError::AlreadySet);
        }

        if count <= *lock {
            *lock -= count;
        } else {
            return Err(CountdownError::TooManySignals);
        }

        if *lock == 0 {
            self.lock.notify_all();
            Ok(true)
        } else {
            Ok(false)
        }
    }

    ///Adds one to the count.
    ///
    ///# Errors
    ///
    ///See [`add`] for the situations where this function will return an error.
    ///
    ///[`add`]: #method.add
    pub fn increment(&self) -> Result<(), CountdownError> {
        self.add(1)
    }

    ///Subtracts one from the counter, and returns whether this caused any waiting threads to wake
    ///up.
    ///
    ///# Errors
    ///
    ///See [`signal`] for the situations where this function will return an error.
    ///
    ///[`signal`]: #method.signal
    pub fn decrement(&self) -> Result<bool, CountdownError> {
        self.signal(1)
    }

    ///Blocks the current thread until the counter reaches zero.
    ///
    ///This function will block indefinitely until the counter reaches zero. It will return
    ///immediately if it is already at zero.
    pub fn wait(&self) {
        let mut count = util::guts(self.counter.lock());

        while *count > 0 {
            count = util::guts(self.lock.wait(count));
        }
    }

    ///Blocks the current thread until the timer reaches zero, or until the given timeout elapses,
    ///returning the count at the time of wakeup and whether the timeout is known to have elapsed.
    ///
    ///This function will return immediately if the counter was already at zero. Otherwise, it will
    ///block for roughly no longer than `timeout`. Due to limitations in the platform specific
    ///implementation of `std::sync::Condvar`, this method could spuriously wake up both before the timeout
    ///elapsed and without the count being zero.
    pub fn wait_timeout(&self, timeout: Duration) -> (isize, bool) {
        let count = util::guts(self.counter.lock());

        if *count == 0 {
            return (*count, false);
        }

        let (count, status) = util::guts(self.lock.wait_timeout(count, timeout));

        (*count, status.timed_out())
    }
}

///Determines the reset behavior of a `SignalEvent`.
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum SignalKind {
    ///An activated `SignalEvent` automatically resets when a thread is resumed.
    ///
    ///`SignalEvent`s with this kind will only resume one thread at a time.
    Auto,
    ///An activated `SignalEvent` must be manually reset to block threads again.
    ///
    ///`SignalEvent`s with this kind will signal every waiting thread to continue at once.
    Manual,
}

/// A synchronization primitive that allows one or more threads to wait on a signal from another
/// thread.
pub struct SignalEvent {
    reset: SignalKind,
    signal: Mutex<bool>,
    lock: Condvar,
}

impl SignalEvent {
    ///Creates a new `SignalEvent` with the given starting state and reset behavior.
    pub fn new(init_state: bool, signal_kind: SignalKind) -> SignalEvent {
        SignalEvent {
            reset: signal_kind,
            signal: Mutex::new(init_state),
            lock: Condvar::new(),
        }
    }

    ///Returns the current signal status of the `SignalEvent`.
    pub fn status(&self) -> bool {
        let signal = util::guts(self.signal.lock());

        *signal
    }

    ///Sets the signal on this `SignalEvent`, potentially waking up one or all threads waiting on
    ///it.
    pub fn signal(&self) {
        let mut signal = util::guts(self.signal.lock());

        *signal = true;

        match self.reset {
            SignalKind::Auto => self.lock.notify_one(),
            SignalKind::Manual => self.lock.notify_all(),
        }
    }

    ///Resets the signal on this `SignalEvent`, allowing threads that wait on it to block.
    pub fn reset(&self) {
        let mut signal = util::guts(self.signal.lock());

        *signal = false;
    }

    ///Blocks this thread until another thread calls `signal`.
    pub fn wait(&self) {
        let mut signal = util::guts(self.signal.lock());

        while !*signal {
            signal = util::guts(self.lock.wait(signal));
        }

        if self.reset == SignalKind::Auto {
            //don't want to call self.reset() since it would deadlock the mutex
            *signal = false;
        }
    }

    ///Blocks this thread until either another thread calls `signal`, or until the timeout elapses.
    ///
    ///This function returns both the status of the signal when it woke up, and whether the timeout
    ///was known to have elapsed. Note that due to platform-specific implementations of
    ///`std::sync::Condvar`, it's possible for this wait to spuriously wake up when neither the
    ///signal was set nor the timeout had elapsed.
    pub fn wait_timeout(&self, timeout: Duration) -> (bool, bool) {
        let mut signal = util::guts(self.signal.lock());

        if *signal {
            if self.reset == SignalKind::Auto {
                *signal = false;
            }
            return (true, false);
        }

        let (mut signal, status) = util::guts(self.lock.wait_timeout(signal, timeout));
        let ret = *signal;

        if self.reset == SignalKind::Auto {
            *signal = false;
        }

        (ret, status.timed_out())
    }
}
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with
// this file, You can obtain one at https://mozilla.org/MPL/2.0/.

//! A library to localize strings, translating them according to runtime options.
//!
//! Basically, this library allows your project to generate a `lformat!` macro, that behaves
//! similarly to `format!`, except the message string (the first argument) might get translated
//! (if you can find the appropriate string for the language).
//!
//! # Usage
//!
//! First, you'll need to add the following to your `Cargo.toml` file:
//!
//! ```toml
//! build = "build.rs"
//!
//! [build-dependencies]
//! crowbook-intl = "0.1.0"
//!
//! [dependencies]
//! crowbook-intl-runtime = "0.1.0"
//! ```
//!
//! You'll then need to create the `build.rs` file, which can look like this:
//!
//! ```rust,ignore
//! extern crate crowbook_intl;
//! use crowbook_intl::{Localizer, Extractor};
//!
//! fn main() {
//!     // Generate a `lang/default.pot` containing strings used to call `lformat!`
//!     let mut extractor = Extractor::new();
//!     extractor.add_messages_from_dir(concat!(env!("CARGO_MANIFEST_DIR"), "/src")).unwrap();
//!     extractor.write_pot_file(concat!(env!("CARGO_MANIFEST_DIR"), "/lang/default.pot")).unwrap();
//!
//!     // Generate the `localize_macros.rs` file
//!     let mut localizer = Localizer::new(&extractor);
//!     localizer.write_macro_file(concat!(env!("CARGO_MANIFEST_DIR"), "/src/lib/localize_macros.rs")).unwrap();
//! }
//! ```
//!
//! This way, a `localize_macros.rs` file will be created at build time in `src/lib`.
//! To use it, the last step is to modify your `src/lib/lib.rs` file:
//!
//! ```rust,ignore
//! extern crate crowbook_intl_runtime;
//! #[macro_use] mod localize_macros;
//! ```
//!
//! Once this is done, you can start replacing your calls to `format!` with calls to `lformat!`.
//!
//! In order to get translation, you'll need to actually translate the strings in separate
//! files, and set your `build.rs` to load them.
//!
//! E.g., if you have the following code:
//!
//! ```rust,ignore
//! println!("{}", lformat!("Hello, world!"));
//! ```
//! and you want it translated in french, you'll have to create a `lang/fr.po` file
//! from the `lang/default.pot` file containing:
//!
//! ```text
//! msgid "Hello, world!";
//! msgstr "Bonjour le monde !";
//! ```
//!
//! And load it in your `build.rs` file:
//!
//! ```rust,ignore
//! let mut localizer = Localizer::new();
//! localizer.add_lang("fr", include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/lang/fr.mp"))).unwrap();
//! localizer.write_macro_file(concat!(env!("OUT_DIR"), "/localize_macros.rs")).unwrap();
//! ```
//!
//! You'll also need to `include!` the result of this build script into a `localize_macros.rs` file:
//!
//! ```rust,ignore
//! include!(concat!(env!("OUT_DIR"), "/localize_macros.rs"));
//! ```
//!
//! Once *this* is done, you can use the `localize_macros::set_lang` function
//! to switch the language at runtime:
//!
//! ```rust,ignore
//! use localize_macros::set_lang;
//! set_lang("en");
//! println!("{}", lformat!("Hello, world!")); // prints "Hello, world!"
//! set_lang("fr");
//! println!("{}", lformat!("Hello, world!")); // prints "Bonjour le monde !"
//! ```
//!
//! # Updating your translation
//!
//! When you add new strings that need to be translated (by more calls to `lformat!`),
//! or when you change the content of existing strings, you can use [Gettext's `msgmerge` and `msgcmp`](https://www.gnu.org/software/gettext/manual/html_node/msgmerge-Invocation.html)
//! commands to update your translation. While it is not guaranteed that the formats are
//! strictly identical, it should work. (That is, it is a bug if it doesn't; but at this
//! stage, this library is absolutely not guaranteed to be bug-free.)
//!
//! # Warning
//!
//! In case the complexity of the operation didn't discourage you, I should warn you
//! that this library is highly experimental at this time.

extern crate regex;
#[macro_use] extern crate lazy_static;
extern crate walkdir;

mod common;
mod macrogen;
mod lang;
mod error;
mod localizer;
mod message;
mod extractor;

pub use error::{Result, Error};
pub use localizer::Localizer;
pub use extractor::Extractor;
<commit_msg>Update doc in lib.rs<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with
// this file, You can obtain one at https://mozilla.org/MPL/2.0/.

//! A library to localize strings, translating them according to runtime options.
//!
//! Basically, this library allows your project to generate a `lformat!` macro, that behaves
//! similarly to `format!`, except the message string (the first argument) might get translated
//! (if you can find the appropriate string for the language).
//!
//! # Usage
//!
//! First, you'll need to add the following to your `Cargo.toml` file:
//!
//! ```toml
//! build = "build.rs"
//!
//! [build-dependencies]
//! crowbook-intl = "0.1.0"
//!
//! [dependencies]
//! crowbook-intl-runtime = "0.1.0"
//! ```
//!
//! You'll then need to create the `build.rs` file, which can look like this:
//!
//! ```rust,ignore
//! extern crate crowbook_intl;
//! use crowbook_intl::{Localizer, Extractor};
//!
//! fn main() {
//!     // Generate a `lang/default.pot` containing strings used to call `lformat!`
//!     let mut extractor = Extractor::new();
//!     extractor.add_messages_from_dir(concat!(env!("CARGO_MANIFEST_DIR"), "/src")).unwrap();
//!     extractor.write_pot_file(concat!(env!("CARGO_MANIFEST_DIR"), "/lang/default.pot")).unwrap();
//!
//!     // Generate the `localize_macros.rs` file
//!     let mut localizer = Localizer::new(&extractor);
//!     // Use env::var instead of env! to avoid problems when cross-compiling
//!     let dest_path = Path::new(&env::var("OUT_DIR").unwrap())
//!        .join("localize_macros.rs");
//!     localizer.write_macro_file(dest_path.to_str().unwrap()).unwrap();
//! }
//! ```
//!
//! This will create a `localize_macros.rs` at build time somewhere in `OUT_DIR`, containing the `lformat!` macro.
//! To actually use this macro, you have to create a `src/localize_macros.rs` file that includes it:
//!
//! ```rust,ignore
//! include!(concat!(env!("OUT_DIR"), "/localize_macros.rs"));
//! ```
//!
//! //! To use it, the last step is to modify your `src/lib/lib.rs` file:
//!
//! ```rust,ignore
//! extern crate crowbook_intl_runtime;
//! #[macro_use] mod localize_macros;
//! ```
//!
//! Once this is done, you can start replacing your calls to `format!` with calls to `lformat!`.
//!
//! In order to get translation, you'll need to actually translate the strings in separate
//! files, and set your `build.rs` to load them.
//!
//! E.g., if you have the following code:
//!
//! ```rust,ignore
//! println!("{}", lformat!("Hello, world!"));
//! ```
//!
//! and you want it translated in french, you'll have to create a `lang/fr.po` file
//! from the `lang/default.pot` file containing:
//!
//! ```text
//! msgid "Hello, world!";
//! msgstr "Bonjour le monde !";
//! ```
//!
//! And load it in your `build.rs` file:
//!
//! ```rust,ignore
//! let mut localizer = Localizer::new();
//! localizer.add_lang("fr", include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/lang/fr.mp"))).unwrap();
//! (...)
//! ```
//!
//! Once *this* is done, you can use the `localize_macros::set_lang` function
//! to switch the language at runtime:
//!
//! ```rust,ignore
//! use crowbook_intl_runtime::set_lang;
//! set_lang("en");
//! println!("{}", lformat!("Hello, world!")); // prints "Hello, world!"
//! set_lang("fr");
//! println!("{}", lformat!("Hello, world!")); // prints "Bonjour le monde !"
//! ```
//!
//! # Updating your translation
//!
//! When you add new strings that need to be translated (by more calls to `lformat!`),
//! or when you change the content of existing strings, you can use [Gettext's `msgmerge` and `msgcmp`](https://www.gnu.org/software/gettext/manual/html_node/msgmerge-Invocation.html)
//! commands to update your translation. While it is not guaranteed that the formats are
//! strictly identical, it should work. (That is, it is a bug if it doesn't; but at this
//! stage, this library is absolutely not guaranteed to be bug-free.)
//!
//! # Warning
//!
//! In case the complexity of the operation didn't discourage you, I should warn you
//! that this library is highly experimental at this time.

extern crate regex;
#[macro_use] extern crate lazy_static;
extern crate walkdir;

mod common;
mod macrogen;
mod lang;
mod error;
mod localizer;
mod message;
mod extractor;

pub use error::{Result, Error};
pub use localizer::Localizer;
pub use extractor::Extractor;
<|endoftext|>


<commit_before>pub mod logging;
pub mod math;
pub mod window;
<commit_msg>Disabled dead_code warning for the whole crate<commit_after>#![allow(dead_code)]

pub mod logging;
pub mod math;
pub mod window;
<|endoftext|>