<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 http://mozilla.org/MPL/2.0/. */

use app_units::Au;
use core_graphics::data_provider::CGDataProvider;
use core_graphics::font::CGFont;
use core_text;
use core_text::font::CTFont;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde::de::{Error, Visitor};
use servo_atoms::Atom;
use servo_url::ServoUrl;
use std::borrow::ToOwned;
use std::collections::HashMap;
use std::fmt;
use std::fs::File;
use std::io::{Read, Error as IoError};
use std::ops::Deref;
use std::sync::Mutex;

/// Platform specific font representation for mac.
/// The identifier is a PostScript font name. The
/// CTFont object is cached here for use by the
/// paint functions that create CGFont references.
#[derive(Deserialize, Serialize, Debug)]
pub struct FontTemplateData {
    /// The `CTFont` object, if present. This is cached here so that we don't have to keep creating
    /// `CTFont` instances over and over. It can always be recreated from the `identifier` and/or
    /// `font_data` fields.
    ///
    /// When sending a `FontTemplateData` instance across processes, this will be cleared out on
    /// the other side, because `CTFont` instances cannot be sent across processes. This is
    /// harmless, however, because it can always be recreated.
    ctfont: CachedCTFont,

    pub identifier: Atom,
    pub font_data: Option<Vec<u8>>
}

unsafe impl Send for FontTemplateData {}
unsafe impl Sync for FontTemplateData {}

impl FontTemplateData {
    pub fn new(identifier: Atom, font_data: Option<Vec<u8>>) -> Result<FontTemplateData, IoError> {
        Ok(FontTemplateData {
            ctfont: CachedCTFont(Mutex::new(HashMap::new())),
            identifier: identifier.to_owned(),
            font_data: font_data
        })
    }

    /// Retrieves the Core Text font instance, instantiating it if necessary.
    pub fn ctfont(&self, pt_size: f64) -> Option<CTFont> {
        let mut ctfonts = self.ctfont.lock().unwrap();
        let pt_size_key = Au::from_f64_px(pt_size);
        if !ctfonts.contains_key(&pt_size_key) {
            // If you pass a zero font size to one of the Core Text APIs, it'll replace it with
            // 12.0. We don't want that! (Issue #10492.)
            let clamped_pt_size = pt_size.max(0.01);
            let ctfont = match self.font_data {
                Some(ref bytes) => {
                    let fontprov = CGDataProvider::from_buffer(bytes);
                    let cgfont_result = CGFont::from_data_provider(fontprov);
                    match cgfont_result {
                        Ok(cgfont) => {
                            Some(core_text::font::new_from_CGFont(&cgfont, clamped_pt_size))
                        }
                        Err(_) => None
                    }
                }
                None => core_text::font::new_from_name(&*self.identifier, clamped_pt_size).ok(),
            };
            if let Some(ctfont) = ctfont {
                ctfonts.insert(pt_size_key, ctfont);
            }
        }
        ctfonts.get(&pt_size_key).map(|ctfont| (*ctfont).clone())
    }

    /// Returns a clone of the data in this font. This may be a hugely expensive
    /// operation (depending on the platform) which performs synchronous disk I/O
    /// and should never be done lightly.
    pub fn bytes(&self) -> Vec<u8> {
        if let Some(font_data) = self.bytes_if_in_memory() {
            return font_data;
        }

        let path = ServoUrl::parse(&*self.ctfont(0.0)
                                    .expect("No Core Text font available!")
                                    .url()
                                    .expect("No URL for Core Text font!")
                                    .get_string()
                                    .to_string()).expect("Couldn't parse Core Text font URL!")
                                                 .as_url().to_file_path()
                                                 .expect("Core Text font didn't name a path!");
        let mut bytes = Vec::new();
        File::open(path).expect("Couldn't open font file!").read_to_end(&mut bytes).unwrap();
        bytes
    }

    /// Returns a clone of the bytes in this font if they are in memory. This function never
    /// performs disk I/O.
    pub fn bytes_if_in_memory(&self) -> Option<Vec<u8>> {
        self.font_data.clone()
    }

    /// Returns the native font that underlies this font template, if applicable.
    pub fn native_font(&self) -> Option<CGFont> {
        self.ctfont(0.0).map(|ctfont| ctfont.copy_to_CGFont())
    }
}

#[derive(Debug)]
pub struct CachedCTFont(Mutex<HashMap<Au, CTFont>>);

impl Deref for CachedCTFont {
    type Target = Mutex<HashMap<Au, CTFont>>;
    fn deref(&self) -> &Mutex<HashMap<Au, CTFont>> {
        &self.0
    }
}

impl Serialize for CachedCTFont {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        serializer.serialize_none()
    }
}

impl Deserialize for CachedCTFont {
    fn deserialize<D>(deserializer: D) -> Result<CachedCTFont, D::Error>
                      where D: Deserializer {
        struct NoneOptionVisitor;

        impl Visitor for NoneOptionVisitor {
            type Value = CachedCTFont;

            fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
                write!(fmt, "none")
            }

            #[inline]
            fn visit_none<E>(self) -> Result<CachedCTFont, E> where E: Error {
                Ok(CachedCTFont(Mutex::new(HashMap::new())))
            }
        }

        deserializer.deserialize_option(NoneOptionVisitor)
    }
}
<commit_msg>Use NativeFontHandle instead of CGFont<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 http://mozilla.org/MPL/2.0/. */

use app_units::Au;
use core_graphics::data_provider::CGDataProvider;
use core_graphics::font::CGFont;
use core_text;
use core_text::font::CTFont;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde::de::{Error, Visitor};
use servo_atoms::Atom;
use servo_url::ServoUrl;
use std::borrow::ToOwned;
use std::collections::HashMap;
use std::fmt;
use std::fs::File;
use std::io::{Read, Error as IoError};
use std::ops::Deref;
use std::sync::Mutex;
use webrender_traits::NativeFontHandle;

/// Platform specific font representation for mac.
/// The identifier is a PostScript font name. The
/// CTFont object is cached here for use by the
/// paint functions that create CGFont references.
#[derive(Deserialize, Serialize, Debug)]
pub struct FontTemplateData {
    /// The `CTFont` object, if present. This is cached here so that we don't have to keep creating
    /// `CTFont` instances over and over. It can always be recreated from the `identifier` and/or
    /// `font_data` fields.
    ///
    /// When sending a `FontTemplateData` instance across processes, this will be cleared out on
    /// the other side, because `CTFont` instances cannot be sent across processes. This is
    /// harmless, however, because it can always be recreated.
    ctfont: CachedCTFont,

    pub identifier: Atom,
    pub font_data: Option<Vec<u8>>
}

unsafe impl Send for FontTemplateData {}
unsafe impl Sync for FontTemplateData {}

impl FontTemplateData {
    pub fn new(identifier: Atom, font_data: Option<Vec<u8>>) -> Result<FontTemplateData, IoError> {
        Ok(FontTemplateData {
            ctfont: CachedCTFont(Mutex::new(HashMap::new())),
            identifier: identifier.to_owned(),
            font_data: font_data
        })
    }

    /// Retrieves the Core Text font instance, instantiating it if necessary.
    pub fn ctfont(&self, pt_size: f64) -> Option<CTFont> {
        let mut ctfonts = self.ctfont.lock().unwrap();
        let pt_size_key = Au::from_f64_px(pt_size);
        if !ctfonts.contains_key(&pt_size_key) {
            // If you pass a zero font size to one of the Core Text APIs, it'll replace it with
            // 12.0. We don't want that! (Issue #10492.)
            let clamped_pt_size = pt_size.max(0.01);
            let ctfont = match self.font_data {
                Some(ref bytes) => {
                    let fontprov = CGDataProvider::from_buffer(bytes);
                    let cgfont_result = CGFont::from_data_provider(fontprov);
                    match cgfont_result {
                        Ok(cgfont) => {
                            Some(core_text::font::new_from_CGFont(&cgfont, clamped_pt_size))
                        }
                        Err(_) => None
                    }
                }
                None => core_text::font::new_from_name(&*self.identifier, clamped_pt_size).ok(),
            };
            if let Some(ctfont) = ctfont {
                ctfonts.insert(pt_size_key, ctfont);
            }
        }
        ctfonts.get(&pt_size_key).map(|ctfont| (*ctfont).clone())
    }

    /// Returns a clone of the data in this font. This may be a hugely expensive
    /// operation (depending on the platform) which performs synchronous disk I/O
    /// and should never be done lightly.
    pub fn bytes(&self) -> Vec<u8> {
        if let Some(font_data) = self.bytes_if_in_memory() {
            return font_data;
        }

        let path = ServoUrl::parse(&*self.ctfont(0.0)
                                    .expect("No Core Text font available!")
                                    .url()
                                    .expect("No URL for Core Text font!")
                                    .get_string()
                                    .to_string()).expect("Couldn't parse Core Text font URL!")
                                                 .as_url().to_file_path()
                                                 .expect("Core Text font didn't name a path!");
        let mut bytes = Vec::new();
        File::open(path).expect("Couldn't open font file!").read_to_end(&mut bytes).unwrap();
        bytes
    }

    /// Returns a clone of the bytes in this font if they are in memory. This function never
    /// performs disk I/O.
    pub fn bytes_if_in_memory(&self) -> Option<Vec<u8>> {
        self.font_data.clone()
    }

    /// Returns the native font that underlies this font template, if applicable.
    pub fn native_font(&self) -> Option<NativeFontHandle> {
        self.ctfont(0.0).map(|ctfont| NativeFontHandle(ctfont.copy_to_CGFont()))
    }
}

#[derive(Debug)]
pub struct CachedCTFont(Mutex<HashMap<Au, CTFont>>);

impl Deref for CachedCTFont {
    type Target = Mutex<HashMap<Au, CTFont>>;
    fn deref(&self) -> &Mutex<HashMap<Au, CTFont>> {
        &self.0
    }
}

impl Serialize for CachedCTFont {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer {
        serializer.serialize_none()
    }
}

impl Deserialize for CachedCTFont {
    fn deserialize<D>(deserializer: D) -> Result<CachedCTFont, D::Error>
                      where D: Deserializer {
        struct NoneOptionVisitor;

        impl Visitor for NoneOptionVisitor {
            type Value = CachedCTFont;

            fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
                write!(fmt, "none")
            }

            #[inline]
            fn visit_none<E>(self) -> Result<CachedCTFont, E> where E: Error {
                Ok(CachedCTFont(Mutex::new(HashMap::new())))
            }
        }

        deserializer.deserialize_option(NoneOptionVisitor)
    }
}
<|endoftext|>


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

/*! Composable internal iterators

Internal iterators are functions implementing the protocol used by the `for` loop.

An internal iterator takes `fn(...) -> bool` as a parameter, with returning `false` used to signal
breaking out of iteration. The adaptors in the module work with any such iterator, not just ones
tied to specific traits. For example:

~~~~
use core::iter::iter_to_vec;
println(iter_to_vec(|f| uint::range(0, 20, f)).to_str());
~~~~

An external iterator object implementing the interface in the `iterator` module can be used as an
internal iterator by calling the `advance` method. For example:

~~~~
use core::iterator::*;

let xs = [0u, 1, 2, 3, 4, 5];
let ys = [30, 40, 50, 60];
let mut it = xs.iter().chain(ys.iter());
for it.advance |&x: &uint| {
    println(x.to_str());
}
~~~~

Internal iterators provide a subset of the functionality of an external iterator. It's not possible
to interleave them to implement algorithms like `zip`, `union` and `merge`. However, they're often
much easier to implement.

*/

pub trait Times {
    fn times(&self, it: &fn() -> bool);
}

/**
 * Transform an internal iterator into an owned vector.
 *
 * # Example:
 *
 * ~~~
 * let xs = ~[1, 2, 3];
 * let ys = do iter_to_vec |f| { xs.each(|x| f(*x)) };
 * assert_eq!(xs, ys);
 * ~~~
 */
#[inline(always)]
pub fn iter_to_vec<T>(iter: &fn(f: &fn(T) -> bool)) -> ~[T] {
    let mut v = ~[];
    for iter |x| { v.push(x) }
    v
}

/**
 * Return true if `predicate` is true for any values yielded by an internal iterator.
 *
 * Example:
 *
 * ~~~~
 * let xs = ~[1u, 2, 3, 4, 5];
 * assert!(any(|&x: &uint| x > 2, |f| xs.each(f)));
 * assert!(!any(|&x: &uint| x > 5, |f| xs.each(f)));
 * ~~~~
 */
#[inline(always)]
pub fn any<T>(predicate: &fn(T) -> bool, iter: &fn(f: &fn(T) -> bool)) -> bool {
    for iter |x| {
        if predicate(x) {
            return true
        }
    }
    false
}

/**
 * Return true if `predicate` is true for all values yielded by an internal iterator.
 *
 * # Example:
 *
 * ~~~~
 * assert!(all(|&x: &uint| x < 6, |f| uint::range(1, 6, f)));
 * assert!(!all(|&x: &uint| x < 5, |f| uint::range(1, 6, f)));
 * ~~~~
 */
#[inline(always)]
pub fn all<T>(predicate: &fn(T) -> bool, iter: &fn(f: &fn(T) -> bool)) -> bool {
    for iter |x| {
        if !predicate(x) {
            return false
        }
    }
    true
}

#[cfg(test)]
mod tests {
    use super::*;
    use prelude::*;

    #[test]
    fn test_iter_to_vec() {
        let xs = ~[1, 2, 3];
        let ys = do iter_to_vec |f| { xs.each(|x| f(*x)) };
        assert_eq!(xs, ys);
    }

    #[test]
    fn test_any() {
        let xs = ~[1u, 2, 3, 4, 5];
        assert!(any(|&x: &uint| x > 2, |f| xs.each(f)));
        assert!(!any(|&x: &uint| x > 5, |f| xs.each(f)));
    }

    #[test]
    fn test_all() {
        assert!(all(|x: uint| x < 6, |f| uint::range(1, 6, f)));
        assert!(!all(|x: uint| x < 5, |f| uint::range(1, 6, f)));
    }
}
<commit_msg>iter: add a find function<commit_after>// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/*! Composable internal iterators

Internal iterators are functions implementing the protocol used by the `for` loop.

An internal iterator takes `fn(...) -> bool` as a parameter, with returning `false` used to signal
breaking out of iteration. The adaptors in the module work with any such iterator, not just ones
tied to specific traits. For example:

~~~~
use core::iter::iter_to_vec;
println(iter_to_vec(|f| uint::range(0, 20, f)).to_str());
~~~~

An external iterator object implementing the interface in the `iterator` module can be used as an
internal iterator by calling the `advance` method. For example:

~~~~
use core::iterator::*;

let xs = [0u, 1, 2, 3, 4, 5];
let ys = [30, 40, 50, 60];
let mut it = xs.iter().chain(ys.iter());
for it.advance |&x: &uint| {
    println(x.to_str());
}
~~~~

Internal iterators provide a subset of the functionality of an external iterator. It's not possible
to interleave them to implement algorithms like `zip`, `union` and `merge`. However, they're often
much easier to implement.

*/

use option::{Option, Some, None};

pub trait Times {
    fn times(&self, it: &fn() -> bool);
}

/**
 * Transform an internal iterator into an owned vector.
 *
 * # Example:
 *
 * ~~~
 * let xs = ~[1, 2, 3];
 * let ys = do iter_to_vec |f| { xs.each(|x| f(*x)) };
 * assert_eq!(xs, ys);
 * ~~~
 */
#[inline(always)]
pub fn iter_to_vec<T>(iter: &fn(f: &fn(T) -> bool)) -> ~[T] {
    let mut v = ~[];
    for iter |x| { v.push(x) }
    v
}

/**
 * Return true if `predicate` is true for any values yielded by an internal iterator.
 *
 * Example:
 *
 * ~~~~
 * let xs = ~[1u, 2, 3, 4, 5];
 * assert!(any(|&x: &uint| x > 2, |f| xs.each(f)));
 * assert!(!any(|&x: &uint| x > 5, |f| xs.each(f)));
 * ~~~~
 */
#[inline(always)]
pub fn any<T>(predicate: &fn(T) -> bool, iter: &fn(f: &fn(T) -> bool)) -> bool {
    for iter |x| {
        if predicate(x) {
            return true
        }
    }
    false
}

/**
 * Return true if `predicate` is true for all values yielded by an internal iterator.
 *
 * # Example:
 *
 * ~~~~
 * assert!(all(|&x: &uint| x < 6, |f| uint::range(1, 6, f)));
 * assert!(!all(|&x: &uint| x < 5, |f| uint::range(1, 6, f)));
 * ~~~~
 */
#[inline(always)]
pub fn all<T>(predicate: &fn(T) -> bool, iter: &fn(f: &fn(T) -> bool)) -> bool {
    for iter |x| {
        if !predicate(x) {
            return false
        }
    }
    true
}

/**
 * Return the first element where `predicate` returns `true`, otherwise return `Npne` if no element
 * is found.
 *
 * # Example:
 *
 * ~~~~
 * let xs = ~[1u, 2, 3, 4, 5, 6];
 * assert_eq!(*find(|& &x: & &uint| x > 3, |f| xs.each(f)).unwrap(), 4);
 * ~~~~
 */
#[inline(always)]
pub fn find<T>(predicate: &fn(&T) -> bool, iter: &fn(f: &fn(T) -> bool)) -> Option<T> {
    for iter |x| {
        if predicate(&x) {
            return Some(x);
        }
    }
    None
}

#[cfg(test)]
mod tests {
    use super::*;
    use prelude::*;

    #[test]
    fn test_iter_to_vec() {
        let xs = ~[1, 2, 3];
        let ys = do iter_to_vec |f| { xs.each(|x| f(*x)) };
        assert_eq!(xs, ys);
    }

    #[test]
    fn test_any() {
        let xs = ~[1u, 2, 3, 4, 5];
        assert!(any(|&x: &uint| x > 2, |f| xs.each(f)));
        assert!(!any(|&x: &uint| x > 5, |f| xs.each(f)));
    }

    #[test]
    fn test_all() {
        assert!(all(|x: uint| x < 6, |f| uint::range(1, 6, f)));
        assert!(!all(|x: uint| x < 5, |f| uint::range(1, 6, f)));
    }

    #[test]
    fn test_find() {
        let xs = ~[1u, 2, 3, 4, 5, 6];
        assert_eq!(*find(|& &x: & &uint| x > 3, |f| xs.each(f)).unwrap(), 4);
    }
}
<|endoftext|>


<commit_before>use std::libc::*;
use std::cast::transmute;
use std::str::raw;

use ffi;
use types::LuaType;
use status::LuaStatus;
use lua::Lua;

/**
 *  Proxy to Lua state FFI.
 *
 *  The goal is to provide some functions which don't need to be called in unsafe block everytime we want to call them.
 */
pub struct State<'self>
{
    priv L: *ffi::lua_State,
    priv managed: bool,
}

impl<'self> State<'self>
{
    /**
     *  Create a new Lua state, which is managed by this struct.
     *
     *  When this struct is dropped, the state is closed, and is not usable anymore.
     */
    #[fixed_stack_segment]
    pub fn new() -> State
    {
        State {
            L: unsafe {
                ffi::luaL_newstate()
            },
            managed: true,
        }
    }

    /**
     *  Create a new state from an existing Lua state.
     *
     *  Marked as unsafe as we know nothing about this Lua state lifetime.
     */
    pub unsafe fn from_ffi(L: *ffi::lua_State) -> State
    {
        State {
            L: L,
            managed: false,
        }
    }

    /**
     *  Close the Lua state.
     *
     *  Marked as unsafe as the pointer is not usable anymore after this function call.
     */
    #[fixed_stack_segment]
    pub unsafe fn close(&mut self)
    {
        ffi::lua_close(self.L);
    }

    /// Load lua standard libraries.
    #[fixed_stack_segment]
    pub fn load_stdlibs(&self)
    {
        unsafe
        {
            ffi::luaL_openlibs(self.L);
        }
    }

    /// Get type of a stack element at specified index.
    #[fixed_stack_segment]
    pub fn get_type(&self, idx: int) -> LuaType
    {
        let ty = unsafe {
            ffi::lua_type(self.L, idx as c_int)
        };
        LuaType::from_lua(ty)
    }

    /// Pop a stack element specified by his index.
    #[fixed_stack_segment]
    pub fn pop(&self, idx: int)
    {
        unsafe
        {
            ffi::lua_pop(self.L, idx as c_int);
        }
    }

    /// Get global value. Push to the stack.
    #[fixed_stack_segment]
    pub fn get_global(&self, name: &str)
    {
        unsafe
        {
            let c_name = name.to_c_str().unwrap();
            ffi::lua_getglobal(self.L, c_name);
            free(transmute(c_name));
        }
    }

    /// Set global value. Pop from the stack.
    #[fixed_stack_segment]
    pub fn set_global(&self, name: &str)
    {
        unsafe
        {
            let c_name = name.to_c_str().unwrap();
            ffi::lua_setglobal(self.L, c_name);
            free(transmute(c_name));
        }
    }

    /// Get field value. Push to the stack.
    #[fixed_stack_segment]
    pub fn get_field(&self, idx: int, name: &str)
    {
        unsafe
        {
            let c_name = name.to_c_str().unwrap();
            ffi::lua_getfield(self.L, idx as c_int, c_name);
            free(transmute(c_name));
        }
    }

    /// Set field value. Pop from the stack.
    #[fixed_stack_segment]
    pub fn set_field(&self, idx: int, name: &str)
    {
        unsafe
        {
            let c_name = name.to_c_str().unwrap();
            ffi::lua_setfield(self.L, idx as c_int, c_name);
            free(transmute(c_name));
        }
    }

    #[fixed_stack_segment]
    pub fn load_file(&self, filename: &str) -> LuaStatus
    {
        let status = unsafe {
            let filename = filename.to_c_str().unwrap();
            let status = ffi::luaL_loadfile(self.L, filename);
            free(transmute(filename));

            status
        };

        LuaStatus::from_lua(status)
    }

    #[fixed_stack_segment]
    pub fn pcall(&self, nargs: int, nresults: int, errfunc: int) -> LuaStatus
    {
        let status = unsafe {
            ffi::lua_pcall(self.L, nargs as c_int, nresults as c_int, errfunc as c_int)
        };

        LuaStatus::from_lua(status)
    }

    pub fn exec(&self) -> LuaStatus
    {
        self.pcall(0, ffi::LUA_MULTRET as int, 0)
    }

    // Stack functions
    #[fixed_stack_segment]
    pub fn upvalue_index(i: int) -> int
    {
        unsafe
        {
            ffi::lua_upvalueindex(i as c_int) as int
        }
    }

    // Table functions
    #[fixed_stack_segment]
    pub fn new_table(&self, )
    {
        unsafe
        {
            ffi::lua_newtable(self.L);
        }
    }

    #[fixed_stack_segment]
    pub fn create_table(&self, narr: int, nrec: int)
    {
        unsafe
        {
            ffi::lua_createtable(self.L, narr as c_int, nrec as c_int);
        }
    }

    #[fixed_stack_segment]
    pub fn set_table(&self, idx: int)
    {
        unsafe
        {
            ffi::lua_settable(self.L, idx as c_int);
        }
    }

    #[fixed_stack_segment]
    pub fn raw_set(&self, idx: int)
    {
        unsafe
        {
            ffi::lua_rawset(self.L, idx as c_int);
        }
    }

    #[fixed_stack_segment]
    pub fn raw_set_index(&self, idx: int, i: int)
    {
        unsafe
        {
            ffi::lua_rawseti(self.L, idx as c_int, i as c_int);
        }
    }

    // Push functions

    #[fixed_stack_segment]
    pub fn push_nil(&self)
    {
        unsafe
        {
            ffi::lua_pushnil(self.L);
        }
    }

    #[fixed_stack_segment]
    pub fn push_float(&self, n: f64)
    {
        unsafe
        {
            ffi::lua_pushnumber(self.L, n as ffi::lua_Number);
        }
    }

    #[fixed_stack_segment]
    pub fn push_int(&self, n: int)
    {
        unsafe
        {
            ffi::lua_pushinteger(self.L, n as ffi::lua_Integer);
        }
    }

    #[fixed_stack_segment]
    pub fn push_uint(&self, n: uint)
    {
        unsafe
        {
            ffi::lua_pushunsigned(self.L, n as ffi::lua_Unsigned);
        }
    }

    #[fixed_stack_segment]
    pub fn push_str(&self, s: &str)
    {
        unsafe
        {
            let c_str = s.to_c_str().unwrap();
            ffi::lua_pushstring(self.L, c_str);
            free(transmute(c_str));
        }
    }

    #[fixed_stack_segment]
    pub fn push_bool(&self, b: bool)
    {
        unsafe
        {
            let n = if b { 1 } else { 0 };
            ffi::lua_pushboolean(self.L, n);
        }
    }

    #[fixed_stack_segment]
    pub fn push_userdata<T>(&self, p: *T)
    {
        unsafe
        {
            ffi::lua_pushlightuserdata(self.L, transmute(p));
        }
    }

    #[fixed_stack_segment]
    pub fn push_cclosure(&self, f: ffi::lua_CFunction, n: int)
    {
        unsafe
        {
            ffi::lua_pushcclosure(self.L, f, n as c_int);
        }
    }

    #[fixed_stack_segment]
    pub fn push_cfunction(&self, f: ffi::lua_CFunction)
    {
        unsafe
        {
            ffi::lua_pushcfunction(self.L, f);
        }
    }

    pub fn push_function(&self, f: fn(l: &'self Lua) -> int)
    {
        self.push_userdata(f as *());
        self.push_cclosure(_lua_state_closure, 1);
    }

    // Get functions

    #[fixed_stack_segment]
    pub fn get_float(&self, idx: int) -> f64
    {
        unsafe
        {
            ffi::lua_tonumber(self.L, idx as c_int) as f64
        }
    }

    #[fixed_stack_segment]
    pub fn get_int(&self, idx: int) -> int
    {
        unsafe
        {
            ffi::lua_tointeger(self.L, idx as c_int) as int
        }
    }

    #[fixed_stack_segment]
    pub fn get_uint(&self, idx: int) -> uint
    {
        unsafe
        {
            ffi::lua_tounsigned(self.L, idx as c_int) as uint
        }
    }

    #[fixed_stack_segment]
    pub fn get_str(&self, idx: int) -> ~str
    {
        unsafe
        {
            let c_str = ffi::lua_tostring(self.L, idx as c_int);
            raw::from_c_str(c_str)
        }
    }

    #[fixed_stack_segment]
    pub fn get_bool(&self, idx: int) -> bool
    {
        unsafe
        {
            ffi::lua_toboolean(self.L, idx as c_int) != 0
        }
    }

    #[fixed_stack_segment]
    pub fn get_userdata<T>(&self, idx: int) -> *T
    {
        unsafe
        {
            transmute(ffi::lua_touserdata(self.L, idx as c_int))
        }
    }

    #[fixed_stack_segment]
    pub fn get_cfunction(&self, idx: int) -> ffi::lua_CFunction
    {
        unsafe
        {
            ffi::lua_tocfunction(self.L, idx as c_int)
        }
    }

    // Function related functions

    #[fixed_stack_segment]
    pub fn register(&self, name: &str, f: ffi::lua_CFunction)
    {
        unsafe
        {
            let c_name = name.to_c_str().unwrap();
            ffi::lua_register(self.L, c_name, f);
            free(transmute(c_name));
        }
    }
}

extern "C" fn _lua_state_closure(L: *ffi::lua_State) -> c_int
{
    let lua = Lua {
        state: unsafe {
            State::from_ffi(L)
        },
    };
    let f: fn(l: &Lua) -> int = match lua.get_arg(0) {
        Some(p) => p,
        None => fail!("I'm sorry Dave I'm afraid I can't do that."),
    };

    f(&lua) as c_int
}

impl<'self> Drop for State<'self>
{
    fn drop(&mut self)
    {
        if self.managed
        {
            unsafe
            {
                self.close();
            }
        }
    }
}
<commit_msg>Add some methods to lua::state::State.<commit_after>use std::libc::*;
use std::cast::transmute;
use std::str::raw;

use ffi;
use types::LuaType;
use status::LuaStatus;
use lua::Lua;

/**
 *  Proxy to Lua state FFI.
 *
 *  The goal is to provide some functions which don't need to be called in unsafe block everytime we want to call them.
 */
pub struct State<'self>
{
    priv L: *ffi::lua_State,
    priv managed: bool,
}

impl<'self> State<'self>
{
    /**
     *  Create a new Lua state, which is managed by this struct.
     *
     *  When this struct is dropped, the state is closed, and is not usable anymore.
     */
    #[fixed_stack_segment]
    pub fn new() -> State
    {
        State {
            L: unsafe {
                ffi::luaL_newstate()
            },
            managed: true,
        }
    }

    /**
     *  Create a new state from an existing Lua state.
     *
     *  Marked as unsafe as we know nothing about this Lua state lifetime.
     */
    pub unsafe fn from_ffi(L: *ffi::lua_State) -> State
    {
        State {
            L: L,
            managed: false,
        }
    }

    /**
     *  Close the Lua state.
     *
     *  Marked as unsafe as the pointer is not usable anymore after this function call.
     */
    #[fixed_stack_segment]
    pub unsafe fn close(&mut self)
    {
        ffi::lua_close(self.L);
    }

    /// Load lua standard libraries.
    #[fixed_stack_segment]
    pub fn load_stdlibs(&self)
    {
        unsafe
        {
            ffi::luaL_openlibs(self.L);
        }
    }

    /// Get type of a stack element at specified index.
    #[fixed_stack_segment]
    pub fn get_type(&self, idx: int) -> LuaType
    {
        let ty = unsafe {
            ffi::lua_type(self.L, idx as c_int)
        };
        LuaType::from_lua(ty)
    }

    /// Create a new Lua thread.
    #[fixed_stack_segment]
    pub fn new_thread(&self) -> State
    {
        unsafe
        {
            State::from_ffi(ffi::lua_newthread(self.L))
        }
    }

    /// Get Lua version.
    #[fixed_stack_segment]
    pub fn version(&self) -> int
    {
        unsafe
        {
            ffi::lua_version(self.L) as int
        }
    }

    /// Pop a stack element specified by his index.
    #[fixed_stack_segment]
    pub fn pop(&self, idx: int)
    {
        unsafe
        {
            ffi::lua_pop(self.L, idx as c_int);
        }
    }

    /// Get global value. Push to the stack.
    #[fixed_stack_segment]
    pub fn get_global(&self, name: &str)
    {
        unsafe
        {
            let c_name = name.to_c_str().unwrap();
            ffi::lua_getglobal(self.L, c_name);
            free(transmute(c_name));
        }
    }

    /// Set global value. Pop from the stack.
    #[fixed_stack_segment]
    pub fn set_global(&self, name: &str)
    {
        unsafe
        {
            let c_name = name.to_c_str().unwrap();
            ffi::lua_setglobal(self.L, c_name);
            free(transmute(c_name));
        }
    }

    /// Get field value. Push to the stack.
    #[fixed_stack_segment]
    pub fn get_field(&self, idx: int, name: &str)
    {
        unsafe
        {
            let c_name = name.to_c_str().unwrap();
            ffi::lua_getfield(self.L, idx as c_int, c_name);
            free(transmute(c_name));
        }
    }

    /// Set field value. Pop from the stack.
    #[fixed_stack_segment]
    pub fn set_field(&self, idx: int, name: &str)
    {
        unsafe
        {
            let c_name = name.to_c_str().unwrap();
            ffi::lua_setfield(self.L, idx as c_int, c_name);
            free(transmute(c_name));
        }
    }

    #[fixed_stack_segment]
    pub fn load_file(&self, filename: &str) -> LuaStatus
    {
        let status = unsafe {
            let filename = filename.to_c_str().unwrap();
            let status = ffi::luaL_loadfile(self.L, filename);
            free(transmute(filename));

            status
        };

        LuaStatus::from_lua(status)
    }

    #[fixed_stack_segment]
    pub fn pcall(&self, nargs: int, nresults: int, errfunc: int) -> LuaStatus
    {
        let status = unsafe {
            ffi::lua_pcall(self.L, nargs as c_int, nresults as c_int, errfunc as c_int)
        };

        LuaStatus::from_lua(status)
    }

    pub fn exec(&self) -> LuaStatus
    {
        self.pcall(0, ffi::LUA_MULTRET as int, 0)
    }

    // Stack functions
    #[fixed_stack_segment]
    pub fn upvalue_index(i: int) -> int
    {
        unsafe
        {
            ffi::lua_upvalueindex(i as c_int) as int
        }
    }

    /// Get index of the stack's top.
    #[fixed_stack_segment]
    pub fn get_top(&self) -> int
    {
        unsafe
        {
            ffi::lua_gettop(self.L) as int
        }
    }

    /// Set index of the stack's top.
    #[fixed_stack_segment]
    pub fn set_top(&self, idx: int)
    {
        unsafe
        {
            ffi::lua_settop(self.L, idx as c_int);
        }
    }

    /// Removes the element at the given valid index.
    #[fixed_stack_segment]
    pub fn remove(&self, idx: int)
    {
        unsafe
        {
            ffi::lua_remove(self.L, idx as c_int);
        }
    }

    // Table functions
    #[fixed_stack_segment]
    pub fn new_table(&self, )
    {
        unsafe
        {
            ffi::lua_newtable(self.L);
        }
    }

    #[fixed_stack_segment]
    pub fn create_table(&self, narr: int, nrec: int)
    {
        unsafe
        {
            ffi::lua_createtable(self.L, narr as c_int, nrec as c_int);
        }
    }

    #[fixed_stack_segment]
    pub fn set_table(&self, idx: int)
    {
        unsafe
        {
            ffi::lua_settable(self.L, idx as c_int);
        }
    }

    #[fixed_stack_segment]
    pub fn raw_set(&self, idx: int)
    {
        unsafe
        {
            ffi::lua_rawset(self.L, idx as c_int);
        }
    }

    #[fixed_stack_segment]
    pub fn raw_set_index(&self, idx: int, i: int)
    {
        unsafe
        {
            ffi::lua_rawseti(self.L, idx as c_int, i as c_int);
        }
    }

    // Push functions

    #[fixed_stack_segment]
    pub fn push_nil(&self)
    {
        unsafe
        {
            ffi::lua_pushnil(self.L);
        }
    }

    #[fixed_stack_segment]
    pub fn push_float(&self, n: f64)
    {
        unsafe
        {
            ffi::lua_pushnumber(self.L, n as ffi::lua_Number);
        }
    }

    #[fixed_stack_segment]
    pub fn push_int(&self, n: int)
    {
        unsafe
        {
            ffi::lua_pushinteger(self.L, n as ffi::lua_Integer);
        }
    }

    #[fixed_stack_segment]
    pub fn push_uint(&self, n: uint)
    {
        unsafe
        {
            ffi::lua_pushunsigned(self.L, n as ffi::lua_Unsigned);
        }
    }

    #[fixed_stack_segment]
    pub fn push_str(&self, s: &str)
    {
        unsafe
        {
            let c_str = s.to_c_str().unwrap();
            ffi::lua_pushstring(self.L, c_str);
            free(transmute(c_str));
        }
    }

    #[fixed_stack_segment]
    pub fn push_bool(&self, b: bool)
    {
        unsafe
        {
            let n = if b { 1 } else { 0 };
            ffi::lua_pushboolean(self.L, n);
        }
    }

    #[fixed_stack_segment]
    pub fn push_userdata<T>(&self, p: *T)
    {
        unsafe
        {
            ffi::lua_pushlightuserdata(self.L, transmute(p));
        }
    }

    #[fixed_stack_segment]
    pub fn push_cclosure(&self, f: ffi::lua_CFunction, n: int)
    {
        unsafe
        {
            ffi::lua_pushcclosure(self.L, f, n as c_int);
        }
    }

    #[fixed_stack_segment]
    pub fn push_cfunction(&self, f: ffi::lua_CFunction)
    {
        unsafe
        {
            ffi::lua_pushcfunction(self.L, f);
        }
    }

    pub fn push_function(&self, f: fn(l: &'self Lua) -> int)
    {
        self.push_userdata(f as *());
        self.push_cclosure(_lua_state_closure, 1);
    }

    // Get functions

    #[fixed_stack_segment]
    pub fn get_float(&self, idx: int) -> f64
    {
        unsafe
        {
            ffi::lua_tonumber(self.L, idx as c_int) as f64
        }
    }

    #[fixed_stack_segment]
    pub fn get_int(&self, idx: int) -> int
    {
        unsafe
        {
            ffi::lua_tointeger(self.L, idx as c_int) as int
        }
    }

    #[fixed_stack_segment]
    pub fn get_uint(&self, idx: int) -> uint
    {
        unsafe
        {
            ffi::lua_tounsigned(self.L, idx as c_int) as uint
        }
    }

    #[fixed_stack_segment]
    pub fn get_str(&self, idx: int) -> ~str
    {
        unsafe
        {
            let c_str = ffi::lua_tostring(self.L, idx as c_int);
            raw::from_c_str(c_str)
        }
    }

    #[fixed_stack_segment]
    pub fn get_bool(&self, idx: int) -> bool
    {
        unsafe
        {
            ffi::lua_toboolean(self.L, idx as c_int) != 0
        }
    }

    #[fixed_stack_segment]
    pub fn get_userdata<T>(&self, idx: int) -> *T
    {
        unsafe
        {
            transmute(ffi::lua_touserdata(self.L, idx as c_int))
        }
    }

    #[fixed_stack_segment]
    pub fn get_cfunction(&self, idx: int) -> ffi::lua_CFunction
    {
        unsafe
        {
            ffi::lua_tocfunction(self.L, idx as c_int)
        }
    }

    // Function related functions
    #[fixed_stack_segment]
    pub fn register(&self, name: &str, f: ffi::lua_CFunction)
    {
        unsafe
        {
            let c_name = name.to_c_str().unwrap();
            ffi::lua_register(self.L, c_name, f);
            free(transmute(c_name));
        }
    }

    // Misc functions
    #[fixed_stack_segment]
    pub fn error(&self) -> int
    {
        unsafe
        {
            ffi::lua_error(self.L) as int
        }
    }
}

extern "C" fn _lua_state_closure(L: *ffi::lua_State) -> c_int
{
    let lua = Lua {
        state: unsafe {
            State::from_ffi(L)
        },
    };
    let f: fn(l: &Lua) -> int = match lua.get_arg(0) {
        Some(p) => p,
        None => fail!("I'm sorry Dave I'm afraid I can't do that."),
    };

    f(&lua) as c_int
}

impl<'self> Drop for State<'self>
{
    fn drop(&mut self)
    {
        if self.managed
        {
            unsafe
            {
                self.close();
            }
        }
    }
}
<|endoftext|>


<commit_before>use syntax::ast::*;
use syntax::codemap::{Span, Spanned};
use syntax::ext::base::{Annotatable, ExtCtxt};
use syntax::ext::build::AstBuilder;
use syntax::ext::quote::rt::ExtParseUtils;
use syntax::ptr::P;

pub fn expand(cx: &mut ExtCtxt, span: Span, item: &Annotatable,
                          push: &mut FnMut(Annotatable), trait_name: &str) {
    let trait_name = trait_name.to_string();
    let method_name = trait_name.to_lowercase();
    let method_ident = cx.ident_of(&method_name);
    // Get the that is wrapped by the newtype and do some checks
    let result = match *item {
        Annotatable::Item(ref x) => {
            match x.node {
                ItemKind::Struct(VariantData::Tuple(ref fields, _), _) => {
                    Some((x.ident, cx.ty_ident(span, x.ident), tuple_content(cx, span, x, fields, method_name)))
                },

                ItemKind::Struct(VariantData::Struct(ref fields, _), _) => {
                    Some((x.ident, cx.ty_ident(span, x.ident), struct_content(cx, span, x, fields, method_name)))
                },

                ItemKind::Enum(ref definition, _) => {
                    let input_type = x.ident;
                    Some((x.ident, quote_ty!(cx, Result<$input_type, &'static str>), enum_content(cx, span, x, definition, method_name)))
                },

                _ => None,
            }
        },
        _ => None,
    };

    let (input_type, output_type, block) = match result {
        Some(x) => x,
        _ => {
            cx.span_fatal(span, &format!("only structs can use `derive({})`", trait_name))
        },
    };

    let trait_path = cx.path_global(span, cx.std_path(&["ops", &trait_name]));

    let code = quote_item!(cx,
        impl $trait_path for $input_type {
            type Output = $output_type;
            fn $method_ident(self, rhs: $input_type) -> $output_type {
                $block
            }
        }
    ).unwrap();

    push(Annotatable::Item(code));

}

fn tuple_content(cx: &mut ExtCtxt, span: Span, item: &P<Item>, fields: &Vec<StructField>, method_name: String) -> P<Expr> {
    let type_name = item.ident;
    let mut exprs: Vec<P<Expr>>= vec![];

    for i in 0..fields.len() {
        let i = &i.to_string();
        exprs.push(cx.parse_expr(format!("self.{}.{}(rhs.{})", i, method_name, i)));
    }

    cx.expr_call_ident(span, type_name, exprs)
}

fn struct_content(cx: &mut ExtCtxt, span: Span, item: &P<Item>, fields: &Vec<StructField>, method_name: String) -> P<Expr> {
    let type_name = item.ident;
    let mut filled_fields = vec![];

    for field in fields {
        let (field_id, field_name) = match field.ident {
            Some(x) => (x, x.name.as_str()),
            _ => unreachable!(),
        };
        filled_fields.push(cx.field_imm(span, field_id,
                                        cx.parse_expr(format!("self.{}.{}(rhs.{})", field_name, method_name, field_name))));
    }

    cx.expr_struct_ident(span, type_name, filled_fields)
}

fn enum_content(cx: &mut ExtCtxt, span: Span, item: &P<Item>, enum_def: &EnumDef, method_name: String) -> P<Expr> {
    let mut matches: Vec<Arm> = vec![];
    let enum_ident = item.ident;

    // Add paterns for the same enum types for self and rhs
    for variant in &enum_def.variants {
        let ident = variant.node.name;
        let type_path = quote_path!(cx, $enum_ident::$ident);

        match variant.node.data {
            VariantData::Tuple(ref fields, _)  => {
                // The patern that is outputted should look like this:
                // (TypePath(left_vars), TypePath(right_vars) => Ok(TypePath(exprs))
                let mut left_vars = vec![];
                let mut right_vars = vec![];
                let mut exprs = vec![];

                for i in 0..fields.len() {
                    left_vars.push(cx.pat_ident(span, cx.ident_of(&format!("__l_{}", i))));
                    right_vars.push(cx.pat_ident(span, cx.ident_of(&format!("__r_{}", i))));
                    exprs.push(cx.parse_expr(format!("__l_{}.{}(__r_{})", i, method_name, i)));
                }

                let left_patern = cx.pat_enum(span, type_path.clone(), left_vars);
                let right_patern = cx.pat_enum(span, type_path.clone(), right_vars);
                let new_tuple = cx.expr_call(span, cx.expr_path(type_path.clone()), exprs);
                matches.push(quote_arm!(cx, ($left_patern, $right_patern) => Ok($new_tuple),));
            },
            VariantData::Struct(ref fields, _) => {
                // The patern that is outputted should look like this:
                // (TypePath{left_vars}, TypePath{right_vars} => Ok(TypePath{filled_fields})
                let mut left_vars = vec![];
                let mut right_vars = vec![];
                let mut filled_fields = vec![];

                for field in fields {
                    let (field_id, field_name) = match field.ident {
                        Some(x) => (x, x.name.as_str()),
                        _ => unreachable!(),
                    };
                    filled_fields.push(cx.field_imm(
                            span, field_id,
                            cx.parse_expr(format!("__l_{}.{}(__r_{})", field_name, method_name, field_name))));
                    left_vars.push(fieldpat_str(cx, span, field_id, &format!("__l_{}", field_name)));
                    right_vars.push(fieldpat_str(cx, span, field_id, &format!("__r_{}", field_name)));
                }

                let left_patern = cx.pat_struct(span, type_path.clone(), left_vars);
                let right_patern = cx.pat_struct(span, type_path.clone(), right_vars);
                let new_tuple = cx.expr_struct(span, type_path.clone(), filled_fields);
                matches.push(quote_arm!(cx, ($left_patern, $right_patern) => Ok($new_tuple),));
            }
            VariantData::Unit(_) =>  {
                matches.push(quote_arm!(cx, ($type_path, $type_path) => Err("Cannot add unit types together"), ));
            }

        }
    }

    // Other combinations should result in an error
    matches.push(quote_arm!(cx, _ => Err("Trying to add mismatched enum types"), ));
    quote_expr!(cx, match (self, rhs) { $matches })
}

fn fieldpat_str(cx: &mut ExtCtxt, span: Span, field_id: Ident, pat: &str) -> Spanned<FieldPat> {
    Spanned{
        span: span,
        node: FieldPat{
            ident: field_id,
            pat: cx.pat_ident(span, cx.ident_of(pat)),
            is_shorthand: false,
        },
    }
}
<commit_msg>Change pat_enum to new pat_tuple_struct<commit_after>use syntax::ast::*;
use syntax::codemap::{Span, Spanned};
use syntax::ext::base::{Annotatable, ExtCtxt};
use syntax::ext::build::AstBuilder;
use syntax::ext::quote::rt::ExtParseUtils;
use syntax::ptr::P;

pub fn expand(cx: &mut ExtCtxt, span: Span, item: &Annotatable,
                          push: &mut FnMut(Annotatable), trait_name: &str) {
    let trait_name = trait_name.to_string();
    let method_name = trait_name.to_lowercase();
    let method_ident = cx.ident_of(&method_name);
    // Get the that is wrapped by the newtype and do some checks
    let result = match *item {
        Annotatable::Item(ref x) => {
            match x.node {
                ItemKind::Struct(VariantData::Tuple(ref fields, _), _) => {
                    Some((x.ident, cx.ty_ident(span, x.ident), tuple_content(cx, span, x, fields, method_name)))
                },

                ItemKind::Struct(VariantData::Struct(ref fields, _), _) => {
                    Some((x.ident, cx.ty_ident(span, x.ident), struct_content(cx, span, x, fields, method_name)))
                },

                ItemKind::Enum(ref definition, _) => {
                    let input_type = x.ident;
                    Some((x.ident, quote_ty!(cx, Result<$input_type, &'static str>), enum_content(cx, span, x, definition, method_name)))
                },

                _ => None,
            }
        },
        _ => None,
    };

    let (input_type, output_type, block) = match result {
        Some(x) => x,
        _ => {
            cx.span_fatal(span, &format!("only structs can use `derive({})`", trait_name))
        },
    };

    let trait_path = cx.path_global(span, cx.std_path(&["ops", &trait_name]));

    let code = quote_item!(cx,
        impl $trait_path for $input_type {
            type Output = $output_type;
            fn $method_ident(self, rhs: $input_type) -> $output_type {
                $block
            }
        }
    ).unwrap();

    push(Annotatable::Item(code));

}

fn tuple_content(cx: &mut ExtCtxt, span: Span, item: &P<Item>, fields: &Vec<StructField>, method_name: String) -> P<Expr> {
    let type_name = item.ident;
    let mut exprs: Vec<P<Expr>>= vec![];

    for i in 0..fields.len() {
        let i = &i.to_string();
        exprs.push(cx.parse_expr(format!("self.{}.{}(rhs.{})", i, method_name, i)));
    }

    cx.expr_call_ident(span, type_name, exprs)
}

fn struct_content(cx: &mut ExtCtxt, span: Span, item: &P<Item>, fields: &Vec<StructField>, method_name: String) -> P<Expr> {
    let type_name = item.ident;
    let mut filled_fields = vec![];

    for field in fields {
        let (field_id, field_name) = match field.ident {
            Some(x) => (x, x.name.as_str()),
            _ => unreachable!(),
        };
        filled_fields.push(cx.field_imm(span, field_id,
                                        cx.parse_expr(format!("self.{}.{}(rhs.{})", field_name, method_name, field_name))));
    }

    cx.expr_struct_ident(span, type_name, filled_fields)
}

fn enum_content(cx: &mut ExtCtxt, span: Span, item: &P<Item>, enum_def: &EnumDef, method_name: String) -> P<Expr> {
    let mut matches: Vec<Arm> = vec![];
    let enum_ident = item.ident;

    // Add paterns for the same enum types for self and rhs
    for variant in &enum_def.variants {
        let ident = variant.node.name;
        let type_path = quote_path!(cx, $enum_ident::$ident);

        match variant.node.data {
            VariantData::Tuple(ref fields, _)  => {
                // The patern that is outputted should look like this:
                // (TypePath(left_vars), TypePath(right_vars) => Ok(TypePath(exprs))
                let mut left_vars = vec![];
                let mut right_vars = vec![];
                let mut exprs = vec![];

                for i in 0..fields.len() {
                    left_vars.push(cx.pat_ident(span, cx.ident_of(&format!("__l_{}", i))));
                    right_vars.push(cx.pat_ident(span, cx.ident_of(&format!("__r_{}", i))));
                    exprs.push(cx.parse_expr(format!("__l_{}.{}(__r_{})", i, method_name, i)));
                }

                let left_patern = cx.pat_tuple_struct(span, type_path.clone(), left_vars);
                let right_patern = cx.pat_tuple_struct(span, type_path.clone(), right_vars);
                let new_tuple = cx.expr_call(span, cx.expr_path(type_path.clone()), exprs);
                matches.push(quote_arm!(cx, ($left_patern, $right_patern) => Ok($new_tuple),));
            },
            VariantData::Struct(ref fields, _) => {
                // The patern that is outputted should look like this:
                // (TypePath{left_vars}, TypePath{right_vars} => Ok(TypePath{filled_fields})
                let mut left_vars = vec![];
                let mut right_vars = vec![];
                let mut filled_fields = vec![];

                for field in fields {
                    let (field_id, field_name) = match field.ident {
                        Some(x) => (x, x.name.as_str()),
                        _ => unreachable!(),
                    };
                    filled_fields.push(cx.field_imm(
                            span, field_id,
                            cx.parse_expr(format!("__l_{}.{}(__r_{})", field_name, method_name, field_name))));
                    left_vars.push(fieldpat_str(cx, span, field_id, &format!("__l_{}", field_name)));
                    right_vars.push(fieldpat_str(cx, span, field_id, &format!("__r_{}", field_name)));
                }

                let left_patern = cx.pat_struct(span, type_path.clone(), left_vars);
                let right_patern = cx.pat_struct(span, type_path.clone(), right_vars);
                let new_tuple = cx.expr_struct(span, type_path.clone(), filled_fields);
                matches.push(quote_arm!(cx, ($left_patern, $right_patern) => Ok($new_tuple),));
            }
            VariantData::Unit(_) =>  {
                matches.push(quote_arm!(cx, ($type_path, $type_path) => Err("Cannot add unit types together"), ));
            }

        }
    }

    // Other combinations should result in an error
    matches.push(quote_arm!(cx, _ => Err("Trying to add mismatched enum types"), ));
    quote_expr!(cx, match (self, rhs) { $matches })
}

fn fieldpat_str(cx: &mut ExtCtxt, span: Span, field_id: Ident, pat: &str) -> Spanned<FieldPat> {
    Spanned{
        span: span,
        node: FieldPat{
            ident: field_id,
            pat: cx.pat_ident(span, cx.ident_of(pat)),
            is_shorthand: false,
        },
    }
}
<|endoftext|>


<commit_before>#[macro_use]
pub mod macros;
pub mod error;
pub mod arguments;
pub mod configuration;
pub mod engines;

extern crate std;
extern crate config;

use std::io::prelude::*;
use std::fs::File;
use std::path::Path;
use std::collections::HashMap;
use config::types::Config;
use bins::error::*;
use bins::arguments::Arguments;
use bins::engines::Engine;
use bins::engines::gist::Gist;
use bins::engines::hastebin::Hastebin;
use bins::engines::pastie::Pastie;
use bins::engines::pastebin::Pastebin;

#[derive(Clone)]
pub struct PasteFile {
  pub name: String,
  pub data: String
}

impl PasteFile {
  fn new(name: String, data: String) -> Self {
    PasteFile { name: name, data: data }
  }
}

pub struct Bins {
  pub config: Config,
  pub arguments: Arguments
}

impl Bins {
  pub fn new(config: Config, arguments: Arguments) -> Self {
    Bins {
      config: config,
      arguments: arguments
    }
  }

  pub fn get_engine(&self) -> Result<Box<Engine>> {
    let service = match self.arguments.service {
      Some(ref s) => s,
      None => return Err("no service was specified and no default service was set.".into())
    };
    match service.to_lowercase().as_ref() {
      "gist" => Ok(Box::new(Gist::new())),
      "hastebin" => Ok(Box::new(Hastebin::new())),
      "pastie" => Ok(Box::new(Pastie::new())),
      "pastebin" => Ok(Box::new(Pastebin::new())),
      _ => Err(format!("unknown service \"{}\"", service).into())
    }
  }

  fn read_file<P: AsRef<Path>>(&self, p: P) -> Result<String> {
    let path = p.as_ref();
    let name = match path.to_str() {
      Some(s) => s,
      None => return Err(String::from("file name was not valid unicode").into())
    };
    if !path.exists() {
      return Err(format!("{} does not exist", name).into());
    }
    if !path.is_file() {
      return Err(format!("{} is not a file", name).into());
    }
    let mut file = match File::open(path) {
      Ok(f) => f,
      Err(e) => {
        return Err(format!("could not open {}: {}", name, e).into());
      }
    };
    let mut s = String::new();
    if let Err(e) = file.read_to_string(&mut s) {
      return Err(format!("could not read {}: {}", name, e).into());
    }
    Ok(s)
  }

  fn read_file_to_pastefile<P: AsRef<Path>>(&self, p: P) -> Result<PasteFile> {
    let path = p.as_ref();
    match self.read_file(path) {
      Ok(s) => {
        let n = match path.file_name() {
          Some(x) => x,
          None => return Err("not a valid file name".into())
        };
        Ok(PasteFile::new(n.to_string_lossy().into_owned(), s))
      },
      Err(s) => return Err(s)
    }
  }

  pub fn get_to_paste(&self) -> Result<Vec<PasteFile>> {
    let arguments = &self.arguments;
    let message = &arguments.message;
    let paste_files: Vec<PasteFile> = if !message.is_empty() {
      vec![PasteFile::new(String::from("message"), message.to_owned())]
    } else if !arguments.files.is_empty() {
      let files = arguments.files.clone();
      let results = files.iter()
        .map(|s| Path::new(s))
        .map(|p| self.read_file_to_pastefile(p))
        .map(|r| r.map_err(|e| e.iter().map(|x| x.to_string()).collect::<Vec<_>>().join("\n")))
        .collect::<Vec<_>>();
      for res in results.iter().cloned() {
        if res.is_err() {
          return Err(res.err().unwrap().into());
        }
      }
      let mut pastes = results.iter().cloned().map(|r| r.unwrap()).collect::<Vec<_>>();
      self.handle_duplicate_file_names(&mut pastes);
      pastes
    } else {
      let mut buffer = String::new();
      if let Err(e) = std::io::stdin().read_to_string(&mut buffer) {
        return Err(format!("error reading stdin: {}", e).into());
      }
      vec![PasteFile::new(String::from("stdin"), buffer)]
    };
    Ok(paste_files)
  }

  fn handle_duplicate_file_names(&self, pastes: &mut Vec<PasteFile>) {
    let clone = pastes.clone();
    let names = clone.iter().map(|p| &p.name).collect::<Vec<_>>();
    let mut names_map: HashMap<String, i32> = HashMap::new();
    for mut paste in pastes {
      let name = paste.name.clone();
      if names.contains(&&name) {
        let number = names_map.entry(name.clone()).or_insert(1);
        paste.name = format!("{}_{}", name, number);
        *number += 1;
      }
    }
  }
}
<commit_msg>fix(bins): do not add a number to the first file when checking for a conflict<commit_after>#[macro_use]
pub mod macros;
pub mod error;
pub mod arguments;
pub mod configuration;
pub mod engines;

extern crate std;
extern crate config;

use std::io::prelude::*;
use std::fs::File;
use std::path::Path;
use std::collections::HashMap;
use config::types::Config;
use bins::error::*;
use bins::arguments::Arguments;
use bins::engines::Engine;
use bins::engines::gist::Gist;
use bins::engines::hastebin::Hastebin;
use bins::engines::pastie::Pastie;
use bins::engines::pastebin::Pastebin;

#[derive(Clone)]
pub struct PasteFile {
  pub name: String,
  pub data: String
}

impl PasteFile {
  fn new(name: String, data: String) -> Self {
    PasteFile { name: name, data: data }
  }
}

pub struct Bins {
  pub config: Config,
  pub arguments: Arguments
}

impl Bins {
  pub fn new(config: Config, arguments: Arguments) -> Self {
    Bins {
      config: config,
      arguments: arguments
    }
  }

  pub fn get_engine(&self) -> Result<Box<Engine>> {
    let service = match self.arguments.service {
      Some(ref s) => s,
      None => return Err("no service was specified and no default service was set.".into())
    };
    match service.to_lowercase().as_ref() {
      "gist" => Ok(Box::new(Gist::new())),
      "hastebin" => Ok(Box::new(Hastebin::new())),
      "pastie" => Ok(Box::new(Pastie::new())),
      "pastebin" => Ok(Box::new(Pastebin::new())),
      _ => Err(format!("unknown service \"{}\"", service).into())
    }
  }

  fn read_file<P: AsRef<Path>>(&self, p: P) -> Result<String> {
    let path = p.as_ref();
    let name = match path.to_str() {
      Some(s) => s,
      None => return Err(String::from("file name was not valid unicode").into())
    };
    if !path.exists() {
      return Err(format!("{} does not exist", name).into());
    }
    if !path.is_file() {
      return Err(format!("{} is not a file", name).into());
    }
    let mut file = match File::open(path) {
      Ok(f) => f,
      Err(e) => {
        return Err(format!("could not open {}: {}", name, e).into());
      }
    };
    let mut s = String::new();
    if let Err(e) = file.read_to_string(&mut s) {
      return Err(format!("could not read {}: {}", name, e).into());
    }
    Ok(s)
  }

  fn read_file_to_pastefile<P: AsRef<Path>>(&self, p: P) -> Result<PasteFile> {
    let path = p.as_ref();
    match self.read_file(path) {
      Ok(s) => {
        let n = match path.file_name() {
          Some(x) => x,
          None => return Err("not a valid file name".into())
        };
        Ok(PasteFile::new(n.to_string_lossy().into_owned(), s))
      },
      Err(s) => return Err(s)
    }
  }

  pub fn get_to_paste(&self) -> Result<Vec<PasteFile>> {
    let arguments = &self.arguments;
    let message = &arguments.message;
    let paste_files: Vec<PasteFile> = if !message.is_empty() {
      vec![PasteFile::new(String::from("message"), message.to_owned())]
    } else if !arguments.files.is_empty() {
      let files = arguments.files.clone();
      let results = files.iter()
        .map(|s| Path::new(s))
        .map(|p| self.read_file_to_pastefile(p))
        .map(|r| r.map_err(|e| e.iter().map(|x| x.to_string()).collect::<Vec<_>>().join("\n")))
        .collect::<Vec<_>>();
      for res in results.iter().cloned() {
        if res.is_err() {
          return Err(res.err().unwrap().into());
        }
      }
      let mut pastes = results.iter().cloned().map(|r| r.unwrap()).collect::<Vec<_>>();
      self.handle_duplicate_file_names(&mut pastes);
      pastes
    } else {
      let mut buffer = String::new();
      if let Err(e) = std::io::stdin().read_to_string(&mut buffer) {
        return Err(format!("error reading stdin: {}", e).into());
      }
      vec![PasteFile::new(String::from("stdin"), buffer)]
    };
    Ok(paste_files)
  }

  fn handle_duplicate_file_names(&self, pastes: &mut Vec<PasteFile>) {
    let mut names_map: HashMap<String, i32> = HashMap::new();
    for mut paste in pastes {
      let name = paste.name.clone();
      if names_map.contains_key(&name) {
        let number = names_map.entry(name.clone()).or_insert(1);
        paste.name = format!("{}_{}", name, number);
        *number += 1;
      }
      names_map.entry(name.clone()).or_insert(1);
    }
  }
}
<|endoftext|>


<commit_before>#![allow(unused_variables)]
use autograd::{Function, FuncIntf, FuncDelegate, FIWrap};
use tensor::{TensorKindList, OptTensorKindList, TensorKind, NumLimits};

#[builder(pattern="owned")]
#[derive(Builder, Clone)]
pub struct DropoutArgs {
    #[builder(default="0.5")]
    pub p: f64,
    #[builder(default="false")]
    pub training: bool,
    #[builder(default="false")]
    pub inplace: bool,
}

impl Default for DropoutArgs {
    fn default() -> Self {
        DropoutArgsBuilder::default().build().unwrap()
    }
}

impl_func_args!(Dropout1d, DropoutArgs);
impl_func_args!(Dropout2d, DropoutArgs);

trait Noise: FuncIntf {
    fn make_noise(&self, input: &TensorKind) -> TensorKind;
}

trait Dropout: Noise + FuncIntf {
    fn dropout_forward(&mut self,
                       input: &mut TensorKindList,
                       args: &DropoutArgs)
                       -> TensorKindList {
        let mut output = if args.inplace {
            self.mark_dirty(input);
            input[0].clone()
        } else {
            input[0].copy()
        };
        if args.p > 0. && args.training {
            let noise = self.make_noise(&input[0])
                .bernoulli_(1. - args.p)
                .div_(1. - args.p)
                .expand_as(&input[0]);
            self.save_for_backward(&vec![noise.clone()]);
            output.mult_(&noise);
        }
        vec![output]
    }
    fn dropout_backward(&mut self,
                        grad_output_: &mut OptTensorKindList,
                        args: &DropoutArgs)
                        -> OptTensorKindList {
        match grad_output_[0] {
            None => return vec![None],
            Some(ref mut grad_output) => {
                if args.p > 0. && args.training {
                    let noise = &self.saved_tensors()[0];
                    vec![Some(grad_output.mult_(noise).clone())]
                } else {
                    vec![Some(grad_output.clone())]
                }
            }
        }
    }
}

impl Dropout for Dropout1d {}
impl Dropout for Dropout2d {}
impl Noise for Dropout1d {
    fn make_noise(&self, input: &TensorKind) -> TensorKind {
        input.new(())
    }
}
impl Noise for Dropout2d {
    fn make_noise(&self, input: &TensorKind) -> TensorKind {
        let mut v = vec![input.size()[0], input.size()[1]];
        for _ in 0..input.dim() - 2 {
            v.push(1)
        }
        input.new(v)
    }
}
impl FuncIntf for Dropout1d {
    fn forward(&mut self, input: &mut TensorKindList) -> TensorKindList {
        let args = self.args.clone();
        self.dropout_forward(input, &args)
    }
    fn backward(&mut self, grad_output: &mut OptTensorKindList) -> OptTensorKindList {
        let args = self.args.clone();
        self.dropout_backward(grad_output, &args)
    }
}
impl FuncIntf for Dropout2d {
    fn forward(&mut self, input: &mut TensorKindList) -> TensorKindList {
        let args = self.args.clone();
        self.dropout_forward(input, &args)
    }
    fn backward(&mut self, grad_output: &mut OptTensorKindList) -> OptTensorKindList {
        let args = self.args.clone();
        self.dropout_backward(grad_output, &args)
    }
}
<commit_msg>don't save noise with save_for_backward<commit_after>#![allow(unused_variables)]
use autograd::{Function, FuncIntf, FuncDelegate, FIWrap};
use tensor::{TensorKindList, OptTensorKindList, TensorKind, NumLimits};

#[builder(pattern="owned")]
#[derive(Builder, Clone)]
pub struct DropoutArgs {
    #[builder(default="0.5")]
    pub p: f64,
    #[builder(default="false")]
    pub training: bool,
    #[builder(default="false")]
    pub inplace: bool,
}

impl Default for DropoutArgs {
    fn default() -> Self {
        DropoutArgsBuilder::default().build().unwrap()
    }
}

impl_func_args!(Dropout1d, DropoutArgs);
impl_func_args!(Dropout2d, DropoutArgs);

trait Noise: FuncIntf {
    fn make_noise(&self, input: &TensorKind) -> TensorKind;
}

trait Dropout: Noise + FuncIntf {
    fn dropout_forward(&mut self,
                       input: &mut TensorKindList,
                       args: &DropoutArgs)
                       -> TensorKindList {
        let mut output = if args.inplace {
            self.mark_dirty(input);
            input[0].clone()
        } else {
            input[0].copy()
        };
        if args.p > 0. && args.training {
            let noise = self.make_noise(&input[0])
                .bernoulli_(1. - args.p)
                .div_(1. - args.p)
                .expand_as(&input[0]);
            output.mult_(&noise);
            vec![noise, output]
        } else {
            vec![output]
        }
    }
    fn dropout_backward(&mut self,
                        grad_output_: &mut OptTensorKindList,
                        args: &DropoutArgs)
                        -> OptTensorKindList {
        match grad_output_[0] {
            None => return vec![None],
            Some(ref mut grad_output) => {
                if args.p > 0. && args.training {
                    let noise = &self.saved_tensors()[0];
                    vec![Some(grad_output.mult_(noise).clone())]
                } else {
                    vec![Some(grad_output.clone())]
                }
            }
        }
    }
}

impl Dropout for Dropout1d {}
impl Dropout for Dropout2d {}
impl Noise for Dropout1d {
    fn make_noise(&self, input: &TensorKind) -> TensorKind {
        input.new(())
    }
}
impl Noise for Dropout2d {
    fn make_noise(&self, input: &TensorKind) -> TensorKind {
        let mut v = vec![input.size()[0], input.size()[1]];
        for _ in 0..input.dim() - 2 {
            v.push(1)
        }
        input.new(v)
    }
}
impl FuncIntf for Dropout1d {
    fn forward(&mut self, input: &mut TensorKindList) -> TensorKindList {
        let args = self.args.clone();
        let mut result = self.dropout_forward(input, &args);
        if self.args.p > 0. && args.training {
            self.saved_tensors.push(result.remove(0))
        }
        result
    }
    fn backward(&mut self, grad_output: &mut OptTensorKindList) -> OptTensorKindList {
        let args = self.args.clone();
        self.dropout_backward(grad_output, &args)
    }
}
impl FuncIntf for Dropout2d {
    fn forward(&mut self, input: &mut TensorKindList) -> TensorKindList {
        let args = self.args.clone();
        let mut result = self.dropout_forward(input, &args);
        if self.args.p > 0. && args.training {
            self.saved_tensors.push(result.remove(0))
        }
        result
    }
    fn backward(&mut self, grad_output: &mut OptTensorKindList) -> OptTensorKindList {
        let args = self.args.clone();
        self.dropout_backward(grad_output, &args)
    }
}
<|endoftext|>


<commit_before>/// Application Program Status Register
pub struct APSR;

#[cfg(any(not(target_feature = thumb-mode), target_feature = v6t2))]
rsr!(APSR);
<commit_msg>add the double quotes<commit_after>/// Application Program Status Register
pub struct APSR;

#[cfg(any(not(target_feature = thumb-mode), target_feature = "v6t2"))]
rsr!(APSR);
<|endoftext|>


<commit_before>//! Back-end module for the task queue. The back-end is running
//! on a separate thread. All it does is listening to a command
//! channel and starting new tasks when the time comes.

use std::boxed::FnBox;
use std::collections::HashMap;
use std::sync::Mutex;
use std::thread;
use pulse::{Pulse, Trigger, Select, Barrier};

use {Handle, Wait};

struct Pending {
    task: Box<FnBox() + Send>,
    done: Trigger
}

struct Inner {
    exit: Option<Trigger>,
    exit_method: Wait,

    pending_select: Select,
    pending: HashMap<usize, Pending>,

    active_select: Select,
    active: HashMap<usize, thread::JoinHandle<()>>
}

/// Task queue back-end.
pub struct Backend {
    inner: Mutex<Inner>
}

impl Backend {
    /// Create a new back-end.
    pub fn new() -> Backend {
        Backend {
            inner: Mutex::new(Inner{
                exit: None,
                exit_method: Wait::None,
                pending_select: Select::new(),
                pending: HashMap::new(),
                active_select: Select::new(),
                active: HashMap::new(),
            })
        }
    }

    fn launch(&self, pending: Pending) {
        let (p, t0) = Pulse::new();
        let Pending {
            task,
            done: t1
        } = pending;

        let thread = thread::spawn(move|| {
            (task)();
            t0.trigger();
            t1.trigger();
        });

        let mut guard = self.inner.lock().unwrap();
        let id = guard.active_select.add(p);
        guard.active.insert(id, thread);
    }

    pub fn start(&self, deps: Vec<Handle>, task: Box<FnBox() + Send>) -> Handle {
        let barrier = Barrier::new(deps);
        let pulse = barrier.pulse();

        let (p, t) = Pulse::new();
        let pending = Pending {
            task: task,
            done: t
        };
        if pulse.is_pending() {
            let mut guard = self.inner.lock().unwrap();
            let id = guard.pending_select.add(pulse);
            guard.pending.insert(id, pending);
        } else {
            self.launch(pending);
        }
        p
    }

    pub fn exit(&self, wait: Wait) {
        let mut guard = self.inner.lock().unwrap();
        guard.exit_method = wait;
        let t = guard.exit.take().unwrap();
        t.trigger();
    }

    pub fn run(&self, ack: Trigger) {
        let (exit_p, exit) = Pulse::new();
        let mut select = Select::new();
        let exit_id = select.add(exit_p);
        let (mut pending_id, mut active_id) = {
            let mut guard = self.inner.lock().unwrap();
            guard.exit = Some(exit);
            (select.add(guard.pending_select.pulse()),
             select.add(guard.active_select.pulse()))
        };

        ack.trigger();

        let mut exit_method = None;
        while let Some(pulse) = select.next() {
            if pulse.id() == pending_id {
                let mut guard = self.inner.lock().unwrap();
                pending_id = select.add(guard.pending_select.pulse());
                if let Some(pending) = guard.pending_select.try_next() {
                    let task = guard.pending.remove(&pending.id()).unwrap();
                    drop(guard);
                    if exit_method != Some(Wait::Active) {
                        self.launch(task);
                    }
                }
            } else if pulse.id() == active_id {
                let mut guard = self.inner.lock().unwrap();
                active_id = select.add(guard.active_select.pulse());
                if let Some(active) = guard.active_select.try_next() {
                    let task = guard.active.remove(&active.id()).unwrap();
                    let count = guard.active.len();
                    task.join().unwrap();
                    drop(guard);
                    if count == 0 {
                        match exit_method {
                            Some(Wait::Active) |
                            Some(Wait::Pending) => break,
                            _ => ()
                        }
                    }
                };
            } else if exit_id == pulse.id() {
                let guard = self.inner.lock().unwrap();
                exit_method = Some(guard.exit_method);
                if exit_method == Some(Wait::None) {
                    break;
                }
            }
        }
    }
}
<commit_msg>Only use barrier if two or more deps<commit_after>//! Back-end module for the task queue. The back-end is running
//! on a separate thread. All it does is listening to a command
//! channel and starting new tasks when the time comes.

use std::boxed::FnBox;
use std::collections::HashMap;
use std::sync::Mutex;
use std::thread;
use pulse::{Pulse, Trigger, Select, Barrier};

use {Handle, Wait};

struct Pending {
    task: Box<FnBox() + Send>,
    trigger: Trigger,
    done: Pulse
}

struct Inner {
    exit: Option<Trigger>,
    exit_method: Wait,

    pending_select: Select,
    pending: HashMap<usize, Pending>,

    active_select: Select,
    active: HashMap<usize, thread::JoinHandle<()>>
}

/// Task queue back-end.
pub struct Backend {
    inner: Mutex<Inner>
}

impl Backend {
    /// Create a new back-end.
    pub fn new() -> Backend {
        Backend {
            inner: Mutex::new(Inner{
                exit: None,
                exit_method: Wait::None,
                pending_select: Select::new(),
                pending: HashMap::new(),
                active_select: Select::new(),
                active: HashMap::new(),
            })
        }
    }

    fn launch(&self, pending: Pending) {
        let Pending {
            task,
            trigger,
            done: p
        } = pending;

        let thread = thread::spawn(move|| {
            (task)();
            trigger.trigger();
        });

        let mut guard = self.inner.lock().unwrap();
        let id = guard.active_select.add(p);
        guard.active.insert(id, thread);
    }

    pub fn start(&self, mut deps: Vec<Handle>, task: Box<FnBox() + Send>) -> Handle {
        let (p, t) = Pulse::new();
        let pending = Pending {
            task: task,
            done: p.clone(),
            trigger: t
        };

        let pulse = if deps.len() == 0 {
            // If no dependencies we should just start the task now
            self.launch(pending);
            return p;
        } else if deps.len() == 1 {
            // If only one, we can just use the handle in it's raw form
            deps.pop().unwrap()
        } else {
            let barrier = Barrier::new(deps);
            barrier.pulse()
        };

        if pulse.is_pending() {
            let mut guard = self.inner.lock().unwrap();
            let id = guard.pending_select.add(pulse);
            guard.pending.insert(id, pending);
        } else {
            self.launch(pending);
        }
        p
    }

    pub fn exit(&self, wait: Wait) {
        let mut guard = self.inner.lock().unwrap();
        guard.exit_method = wait;
        let t = guard.exit.take().unwrap();
        t.trigger();
    }

    pub fn run(&self, ack: Trigger) {
        let (exit_p, exit) = Pulse::new();
        let mut select = Select::new();
        let exit_id = select.add(exit_p);
        let (mut pending_id, mut active_id) = {
            let mut guard = self.inner.lock().unwrap();
            guard.exit = Some(exit);
            (select.add(guard.pending_select.pulse()),
             select.add(guard.active_select.pulse()))
        };

        ack.trigger();

        let mut exit_method = None;
        while let Some(pulse) = select.next() {
            if pulse.id() == pending_id {
                let mut guard = self.inner.lock().unwrap();
                pending_id = select.add(guard.pending_select.pulse());
                if let Some(pending) = guard.pending_select.try_next() {
                    let task = guard.pending.remove(&pending.id()).unwrap();
                    drop(guard);
                    if exit_method != Some(Wait::Active) {
                        self.launch(task);
                    }
                }
            } else if pulse.id() == active_id {
                let mut guard = self.inner.lock().unwrap();
                active_id = select.add(guard.active_select.pulse());
                if let Some(active) = guard.active_select.try_next() {
                    let task = guard.active.remove(&active.id()).unwrap();
                    let count = guard.active.len();
                    task.join().unwrap();
                    drop(guard);
                    if count == 0 {
                        match exit_method {
                            Some(Wait::Active) |
                            Some(Wait::Pending) => break,
                            _ => ()
                        }
                    }
                };
            } else if exit_id == pulse.id() {
                let guard = self.inner.lock().unwrap();
                exit_method = Some(guard.exit_method);
                if exit_method == Some(Wait::None) {
                    break;
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use core::hashmap::linear::LinearMap;
use core::str::raw::from_c_str;

// trait Result {
//   fn is_error(&self) -> bool;
// }

// trait DocumentResult : Result {
// }

// struct ParseError {
//   error: bool
// }

// impl Result for ParseError {
//   fn is_error(&self) -> bool {
//     true
//   }
// }

// struct Document {
//   map: @mut LinearMap<~str, ~BsonElement>
// }

// impl Document {
//   fn new() -> @Document {
//     @Document {map: @mut LinearMap::new()}
//   }
// }

// impl Result for Document {
//   fn is_error(&self) -> bool {
//     false
//   }
// }

// impl DocumentResult for Document {
// }

// Available Result values
enum Result {
  Document(@mut LinearMap<~str, ~BsonElement>),
  ParseError(bool)
}

// Available Bson Element types
enum BsonElement {
  Int32(i32),
  Int64(i64)
}

struct BsonParser;
struct ParserState {
  index: u32,
  size: u32,
  document: @Result
}

// //
// // Int 32 element
// struct Int32Element {
//   number: i32
// }

// impl BsonElement for Int32Element {
//   fn typeof() -> BsonType {
//     Int32
//   }
// }

// //
// // Int 64 element
// struct Int64Element {
//   number: i64
// }

// impl BsonElement for Int64Element {
//   fn typeof() -> BsonType {
//     Int64
//   }
// }

impl BsonParser {
  fn deserialize(&self, data: &[i8]) -> @Result {
    // Get the initial state of the parsing
    let size = data[0] as u32;
    // Return an error if we the sizes of the message are not the same
    if size != data.len() as u32 {
      // return @ParseError {error: true} as @Result;
      return @ParseError(true);
    }

    // If we have zero elements (special case)
    if(size == 5) {
      // return Document::new() as @Result;
      return @Document(@mut LinearMap::new());
    }

    let document = @Document(@mut LinearMap::new());
    let state = @mut ParserState {index: 4, size: size, document: document};

    // Let's go, Match on the type
    match data[state.index] as u8 {
      0x02 => io::println("string"),
      0x10 => BsonParser::parseInt32(state, data),
      0x12 => BsonParser::parseInt64(state, data),
      _ => io::println("unknown type")
    }

// io::println("==================================");

    // while state.index <

    // Decode the size of the total message
    // let size : Option<i32> = i32::parse_bytes(vec::slice(data, 0, 4), 10u);

    // let number_data = to_bytes(~"123");
    // let number_data = vec::slice(data, 0, 4) as &i32;
    // let number_data = ~[0x0c, 0, 0];
    // let size = match i32::parse_bytes(number_data, 10u) {
    //   Some(cn) => cn as int,
    //   None => fail!(fmt!("internal error: parse_def_id: crate number \
    //                            expected, but found %?", number_data))
    // };

    // let number_data = vec::slice(data, 0, 4);
    // let size = number_data[0] as i32;

    // io::println(fmt!("data :: %?", number_data));
    // io::println(fmt!("size :: %?", size));
    // io::println(fmt!("state :: %?", state));
    // io::println(fmt!("length :: %?", data.len()));

    // let error = @ParseError {error: false};
    // let mut map = ~LinearMap::new();
    // let mut document = ~Document {map: map};
    // let element = ~Int32Element {number: 1};
    // document.insert(~"hello", element as ~BsonElement);

    // document.map.insert(~"hello", element as ~BsonElement);
    // map.insert(~"hello", ~"world");

    // document as @Result
    document
  }

  fn parseInt32(state:&mut ParserState, data: &[i8]) {
    state.index = state.index + 1;

    // Unpack the cstring
    unsafe {
      // Unpack the name of the field
      let name:~str = from_c_str(&data[state.index]);
      // Adjust the index
      state.index += name.len() as u32 + 1;
      // Unpack the i32 value
      let value = ~Int32(data[state.index] as i32);
      // Adjust index
      state.index += 4;
      // Add to the map
      match *state.document {
        Document(map) => map.insert(name, value),
        _ => false
      };

      // // Save field in the document
      // state.document.map.insert(name, value);
    }
  }

  fn parseInt64(state:&mut ParserState, data: &[i8]) {
    state.index = state.index + 1;

    // Unpack the cstring
    unsafe {
      // Unpack the name of the field
      let name:~str = from_c_str(&data[state.index]);
      // Adjust the index
      state.index += name.len() as u32 + 1;
      // Unpack the i64 value
      let value = ~Int64(data[state.index] as i64);
      // Adjust index
      state.index += 8;
      // Add to the map
      match *state.document {
        Document(map) => map.insert(name, value),
        _ => false
      };
    }
  }
}

// #[test]
// fn simple_int32_test() {
//   let parser:BsonParser = BsonParser;
//   let result = parser.deserialize(@[0x0c, 0x00, 0x00, 0x00, 0x10, 0x61, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00]);
//   io::println(fmt!("result :: %?", result.is_error()));
// }

#[test]
fn simple_int64_test() {
  let parser:BsonParser = BsonParser;
  let result = parser.deserialize(@[0x10, 0x00, 0x00, 0x00, 0x12, 0x61, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
  // io::println(fmt!("result :: %?", result));

  io::println("++++++++++++++++++++++++++++++++++++++++++++++");
  match result {
    @Document(map) => io::println(fmt!("got document :: %?", map)),
    @ParseError(result) => io::println(fmt!("got error :: %?", result))
  }
  // assert_eq!(false, result.is_error());
  // Convert to a document
  // let document = result as @Document;
}
<commit_msg>Just some more tests<commit_after>use core::hashmap::linear::LinearMap;
use core::str::raw::from_c_str;

// trait Result {
//   fn is_error(&self) -> bool;
// }

// trait DocumentResult : Result {
// }

// struct ParseError {
//   error: bool
// }

// impl Result for ParseError {
//   fn is_error(&self) -> bool {
//     true
//   }
// }

// struct Document {
//   map: @mut LinearMap<~str, ~BsonElement>
// }

// impl Document {
//   fn new() -> @Document {
//     @Document {map: @mut LinearMap::new()}
//   }
// }

// impl Result for Document {
//   fn is_error(&self) -> bool {
//     false
//   }
// }

// impl DocumentResult for Document {
// }

// Available Result values
enum Result {
  Document(@mut LinearMap<~str, ~BsonElement>),
  ParseError(bool)
}

// Available Bson Element types
enum BsonElement {
  Int32(i32),
  Int64(i64)
}

struct BsonParser;
struct ParserState {
  index: u32,
  size: u32,
  document: @Result
}

// //
// // Int 32 element
// struct Int32Element {
//   number: i32
// }

// impl BsonElement for Int32Element {
//   fn typeof() -> BsonType {
//     Int32
//   }
// }

// //
// // Int 64 element
// struct Int64Element {
//   number: i64
// }

// impl BsonElement for Int64Element {
//   fn typeof() -> BsonType {
//     Int64
//   }
// }

impl BsonParser {
  fn deserialize(&self, data: &[i8]) -> @Result {
    // Get the initial state of the parsing
    let size = data[0] as u32;
    // Return an error if we the sizes of the message are not the same
    if size != data.len() as u32 {
      // return @ParseError {error: true} as @Result;
      return @ParseError(true);
    }

    // If we have zero elements (special case)
    if(size == 5) {
      return @Document(@mut LinearMap::new());
    }

    // Create a document
    let document = @Document(@mut LinearMap::new());
    // Create a parser state
    let state = @mut ParserState {index: 4, size: size, document: document};

    while(state.index < state.size - 1) {
      // Let's go, Match on the type
      match data[state.index] as u8 {
        0x02 => io::println("string"),
        0x10 => BsonParser::parseInt32(state, data),
        0x12 => BsonParser::parseInt64(state, data),
        _ => io::println("unknown type")
      }
    }

    // return the document
    document
  }

  fn parseInt32(state:&mut ParserState, data: &[i8]) {
    state.index = state.index + 1;

    // Unpack the cstring
    unsafe {
      // Unpack the name of the field
      let name:~str = from_c_str(&data[state.index]);
      // Adjust the index
      state.index += name.len() as u32 + 1;
      // Unpack the i32 value
      let value = ~Int32(data[state.index] as i32);
      // Adjust index
      state.index += 4;
      // Add to the map
      match *state.document {
        Document(map) => map.insert(name, value),
        _ => false
      };
    }
  }

  fn parseInt64(state:&mut ParserState, data: &[i8]) {
    state.index = state.index + 1;

    // Unpack the cstring
    unsafe {
      // Unpack the name of the field
      let name:~str = from_c_str(&data[state.index]);
      // Adjust the index
      state.index += name.len() as u32 + 1;
      // Unpack the i64 value
      let value = ~Int64(data[state.index] as i64);
      // Adjust index
      state.index += 8;
      // Add to the map
      match *state.document {
        Document(map) => map.insert(name, value),
        _ => false
      };
    }
  }
}

#[test]
fn simple_int32_test() {
  let parser:BsonParser = BsonParser;
  let result = parser.deserialize(@[0x0c, 0x00, 0x00, 0x00, 0x10, 0x61, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00]);

  fn process_map(map: @mut LinearMap<~str, ~BsonElement>) {
    match map.find(&~"a") {
      Some(&~Int32(number)) => assert_eq!(number, 1),
      _ => ()
    }
  }

  match result {
    @Document(map) => process_map(map),
    @ParseError(_) => ()
  }
}

#[test]
fn two_value_document_test() {
  let parser:BsonParser = BsonParser;
  let result = parser.deserialize(@[0x17, 0x00, 0x00, 0x00, 0x12, 0x61, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x62, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00]);

  fn process_map(map: @mut LinearMap<~str, ~BsonElement>) {
    match map.find(&~"a") {
      Some(&~Int64(number)) => assert_eq!(number, 2),
      _ => ()
    }

    match map.find(&~"b") {
      Some(&~Int32(number)) => assert_eq!(number, 1),
      _ => ()
    }
  }

  match result {
    @Document(map) => process_map(map),
    @ParseError(_) => ()
  }
}

// fn process_map(map: @mut LinearMap<~str, ~BsonElement>) {
//   for map.each_key |key| {
//     let value = map.find(key);
//     io::println(fmt!(" %?", value));

//     match map.find(key) {
//       Some(&~Int64(number)) => assert_eq!(2, number),
//       _ => io::println("found nothing"),
//     }
//   }
// }
<|endoftext|>


<commit_before>/// Wrapper for values where C functions expect a plain C `char`
///
/// Consider the following C function prototype from glib:
///
/// ```C
/// void g_key_file_set_list_separator (GKeyFile *key_file, gchar separator);
/// ```
///
/// This function plainly expects a byte as the `separator` argument.  However,
/// having this function exposed to Rust as the following would be inconvenient:
///
/// ```ignore
/// impl KeyFile {
///     pub fn set_list_separator(&self, separator: i8) { }
/// }
/// ```
///
/// This would be inconvenient because users would have to do the conversion from a Rust `char` to an `i8` by hand.  It would be the same case for `libc::c_char`, which is just a type alias
/// for `i8`.
///
/// This `Char` type is a wrapper over an `i8`, so that we can pass it to Glib or C functions.
/// The check for whether a Rust `char` (a Unicode scalar value) actually fits in a `i8` is
/// done in the `new` function; see its documentation for details.
///
/// The inner `i8` (which is equivalent to `libc::c_char` can be extracted with `.0`, or
/// by calling `i8::from(my_char)`.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct Char(pub i8);

impl Char {
    /// Creates a `Some(Char)` if the given `char` is representable as an `i8`
    ///
    /// # Example
    /// ```ignore
    /// extern "C" fn have_a_byte(b: libc::c_char);
    ///
    /// let a = Char::new('a').unwrap();
    /// assert!(a.0 == 65);
    /// have_a_byte(i8::from(a));
    ///
    /// let not_representable = Char::new('☔');
    /// assert!(not_representable.is_none());
    /// ```
    pub fn new(c: char) -> Option<Char> {
        if c as u32 > 255 {
            None
        } else {
            Some(Char(c as i8))
        }
    }
}

impl From<Char> for i8 {
    fn from(c: Char) -> i8 {
        c.0
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn converts_single_byte_chars() {
        assert_eq!(Char::new(0 as char), Some(Char(0)));
        assert_eq!(Char::new(255 as char), Some(Char(-1)));
        assert_eq!(Char::new('ñ'), Some(Char(241 as u8 as i8)));
    }

    #[test]
    fn refuses_multibyte_chars() {
        assert_eq!(Char::new('☔'), None); // no umbrella for you
    }

    #[test]
    fn into_i8() {
        assert_eq!(i8::from(Char::new('A').unwrap()), 65i8);
    }
}
<commit_msg>Add UChar, glib traits and conversion to char<commit_after>use libc::{c_char, c_uchar};
use translate::FromGlib;
use translate::ToGlib;

/// Wrapper for values where C functions expect a plain C `char`
///
/// Consider the following C function prototype from glib:
///
/// ```C
/// void g_key_file_set_list_separator (GKeyFile *key_file, gchar separator);
/// ```
///
/// This function plainly expects a byte as the `separator` argument.  However,
/// having this function exposed to Rust as the following would be inconvenient:
///
/// ```ignore
/// impl KeyFile {
///     pub fn set_list_separator(&self, separator: i8) { }
/// }
/// ```
///
/// This would be inconvenient because users would have to do the conversion from a Rust `char` to an `i8` by hand.  It would be the same case for `libc::c_char`, which is just a type alias
/// for `i8`.
///
/// This `Char` type is a wrapper over an `i8`, so that we can pass it to Glib or C functions.
/// The check for whether a Rust `char` (a Unicode scalar value) actually fits in a `i8` is
/// done in the `new` function; see its documentation for details.
///
/// The inner `i8` (which is equivalent to `libc::c_char` can be extracted with `.0`, or
/// by calling `my_char.to_glib()`.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct Char(pub i8);

impl Char {
    /// Creates a `Some(Char)` if the given `char` is representable as an `i8`
    ///
    /// # Example
    /// ```ignore
    /// extern "C" fn have_a_byte(b: libc::c_char);
    ///
    /// let a = Char::new('a').unwrap();
    /// assert!(a.0 == 65);
    /// have_a_byte(a.to_glib());
    ///
    /// let not_representable = Char::new('☔');
    /// assert!(not_representable.is_none());
    /// ```
    pub fn new(c: char) -> Option<Char> {
        if c as u32 > 255 {
            None
        } else {
            Some(Char(c as i8))
        }
    }
}

impl From<Char> for char {
    fn from(c: Char) -> char {
        c.0 as u8 as char
    }
}

#[doc(hidden)]
impl FromGlib<c_char> for Char {
    fn from_glib(value: c_char) -> Self {
        Char(value)
    }
}

#[doc(hidden)]
impl ToGlib for Char {
    type GlibType = c_char;

    fn to_glib(&self) -> c_char {
        self.0
    }
}

/// Wrapper for values where C functions expect a plain C `unsigned char`
///
/// This `UChar` type is a wrapper over an `u8`, so that we can pass it to Glib or C functions.
/// The check for whether a Rust `char` (a Unicode scalar value) actually fits in a `u8` is
/// done in the `new` function; see its documentation for details.
///
/// The inner `u8` (which is equivalent to `libc::c_uchar` can be extracted with `.0`, or
/// by calling `my_char.to_glib()`.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub struct UChar(pub u8);

impl UChar {
    /// Creates a `Some(UChar)` if the given `char` is representable as an `u8`
    ///
    /// # Example
    /// ```ignore
    /// extern "C" fn have_a_byte(b: libc::c_uchar);
    ///
    /// let a = Char::new('a').unwrap();
    /// assert!(a.0 == 65);
    /// have_a_byte(a.to_glib());
    ///
    /// let not_representable = Char::new('☔');
    /// assert!(not_representable.is_none());
    /// ```
    pub fn new(c: char) -> Option<UChar> {
        if c as u32 > 255 {
            None
        } else {
            Some(UChar(c as u8))
        }
    }
}

impl From<UChar> for char {
    fn from(c: UChar) -> char {
        c.0 as char
    }
}

#[doc(hidden)]
impl FromGlib<c_uchar> for UChar {
    fn from_glib(value: c_uchar) -> Self {
        UChar(value)
    }
}

#[doc(hidden)]
impl ToGlib for UChar {
    type GlibType = c_uchar;

    fn to_glib(&self) -> c_uchar {
        self.0
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use translate::from_glib;

    #[test]
    fn converts_single_byte_chars() {
        assert_eq!(Char::new(0 as char), Some(Char(0)));
        assert_eq!(Char::new(255 as char), Some(Char(-1)));
        assert_eq!(Char::new('ñ'), Some(Char(241 as u8 as i8)));
        assert_eq!(UChar::new(0 as char), Some(UChar(0)));
        assert_eq!(UChar::new(255 as char), Some(UChar(255)));
        assert_eq!(UChar::new('ñ'), Some(UChar(241 as u8)));
    }

    #[test]
    fn refuses_multibyte_chars() {
        assert_eq!(Char::new('☔'), None); // no umbrella for you
        assert_eq!(UChar::new('☔'), None);
    }

    #[test]
    fn into_i8() {
        assert_eq!(Char::new('A').unwrap().to_glib(), 65i8);
    }

    #[test]
    fn into_u8() {
        assert_eq!(UChar::new('A').unwrap().to_glib(), 65u8);
    }

    #[test]
    fn into_char() {
        assert_eq!(char::from(Char(65i8)), 'A');
        assert_eq!('ñ', UChar(241u8).into());
    }

    #[test]
    fn convert_from_glib() {
        assert_eq!(Char(65i8), from_glib(65i8));
        assert_eq!(UChar(241u8), from_glib(241u8));
    }
}
<|endoftext|>