<commit_before>// Copyright 2015-2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

//! Runtime type information.

use glib_sys;
use gobject_sys;
use translate::{
    from_glib, from_glib_none, FromGlib, FromGlibContainerAsVec, ToGlib, ToGlibContainerFromSlice,
    ToGlibPtr, ToGlibPtrMut,
};
use value::{FromValue, FromValueOptional, SetValue, Value};

use std::fmt;
use std::mem;
use std::ptr;

/// A GLib or GLib-based library type
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum Type {
    /// An invalid `Type` used as error return value in some functions
    Invalid,
    /// The fundamental type corresponding to the unit type `()`
    Unit,
    /// The fundamental type corresponding to `i8`
    I8,
    /// The fundamental type corresponding to `u8`
    U8,
    /// The fundamental type corresponding to `bool`
    Bool,
    /// The fundamental type corresponding to `i32`
    I32,
    /// The fundamental type corresponding to `u32`
    U32,
    /// The fundamental type corresponding to C `long`
    ILong,
    /// The fundamental type corresponding to C `unsigned long`
    ULong,
    /// The fundamental type corresponding to `i64`
    I64,
    /// The fundamental type corresponding to `u64`
    U64,
    /// The fundamental type corresponding to `f32`
    F32,
    /// The fundamental type corresponding to `f64`
    F64,
    /// The fundamental type corresponding to `String`
    String,
    /// The fundamental type corresponding to a pointer
    Pointer,
    /// The fundamental type of GVariant
    Variant,
    /// The fundamental type from which all interfaces are derived
    BaseInterface,
    /// The fundamental type from which all enumeration types are derived
    BaseEnum,
    /// The fundamental type from which all flags types are derived
    BaseFlags,
    /// The fundamental type from which all boxed types are derived
    BaseBoxed,
    /// The fundamental type from which all `GParamSpec` types are derived
    BaseParamSpec,
    /// The fundamental type from which all objects are derived
    BaseObject,
    /// A non-fundamental type identified by value of type `usize`
    Other(usize),
}

impl Type {
    pub fn name(&self) -> String {
        unsafe { from_glib_none(gobject_sys::g_type_name(self.to_glib())) }
    }

    pub fn qname(&self) -> ::Quark {
        unsafe { from_glib(gobject_sys::g_type_qname(self.to_glib())) }
    }

    pub fn is_a(&self, other: &Type) -> bool {
        unsafe { from_glib(gobject_sys::g_type_is_a(self.to_glib(), other.to_glib())) }
    }

    pub fn parent(&self) -> Option<Self> {
        unsafe {
            let parent = gobject_sys::g_type_parent(self.to_glib());
            if parent == gobject_sys::G_TYPE_INVALID {
                None
            } else {
                Some(from_glib(parent))
            }
        }
    }

    pub fn children(&self) -> Vec<Self> {
        unsafe {
            let mut n_children = 0u32;
            let children = gobject_sys::g_type_children(self.to_glib(), &mut n_children);

            FromGlibContainerAsVec::from_glib_full_num_as_vec(children, n_children as usize)
        }
    }

    pub fn interfaces(&self) -> Vec<Self> {
        unsafe {
            let mut n_interfaces = 0u32;
            let interfaces = gobject_sys::g_type_interfaces(self.to_glib(), &mut n_interfaces);

            FromGlibContainerAsVec::from_glib_full_num_as_vec(interfaces, n_interfaces as usize)
        }
    }
    pub fn interface_prerequisites(&self) -> Vec<Self> {
        unsafe {
            let mut n_prereqs = 0u32;
            let prereqs =
                gobject_sys::g_type_interface_prerequisites(self.to_glib(), &mut n_prereqs);

            FromGlibContainerAsVec::from_glib_full_num_as_vec(prereqs, n_prereqs as usize)
        }
    }

    pub fn from_name<'a, P: Into<&'a str>>(name: P) -> Option<Self> {
        unsafe {
            let type_ = gobject_sys::g_type_from_name(name.into().to_glib_none().0);
            if type_ == gobject_sys::G_TYPE_INVALID {
                None
            } else {
                Some(from_glib(type_))
            }
        }
    }
}

impl fmt::Debug for Type {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(&self.name())
    }
}

impl fmt::Display for Type {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(&self.name())
    }
}

/// Types that are supported by GLib dynamic typing.
pub trait StaticType {
    /// Returns the type identifier of `Self`.
    fn static_type() -> Type;
}

impl StaticType for Type {
    fn static_type() -> Type {
        unsafe { from_glib(gobject_sys::g_gtype_get_type()) }
    }
}

impl<'a> FromValueOptional<'a> for Type {
    unsafe fn from_value_optional(value: &'a Value) -> Option<Self> {
        Some(from_glib(gobject_sys::g_value_get_gtype(
            value.to_glib_none().0,
        )))
    }
}

impl<'a> FromValue<'a> for Type {
    unsafe fn from_value(value: &'a Value) -> Self {
        from_glib(gobject_sys::g_value_get_gtype(value.to_glib_none().0))
    }
}

impl SetValue for Type {
    unsafe fn set_value(value: &mut Value, this: &Self) {
        gobject_sys::g_value_set_gtype(value.to_glib_none_mut().0, this.to_glib())
    }
}

impl<'a, T: ?Sized + StaticType> StaticType for &'a T {
    fn static_type() -> Type {
        T::static_type()
    }
}

impl<'a, T: ?Sized + StaticType> StaticType for &'a mut T {
    fn static_type() -> Type {
        T::static_type()
    }
}

macro_rules! builtin {
    ($name:ident, $val:ident) => {
        impl StaticType for $name {
            fn static_type() -> Type {
                Type::$val
            }
        }
    };
}

builtin!(bool, Bool);
builtin!(i8, I8);
builtin!(u8, U8);
builtin!(i32, I32);
builtin!(u32, U32);
builtin!(i64, I64);
builtin!(u64, U64);
builtin!(f32, F32);
builtin!(f64, F64);
builtin!(str, String);
builtin!(String, String);

impl<'a> StaticType for [&'a str] {
    fn static_type() -> Type {
        unsafe { from_glib(glib_sys::g_strv_get_type()) }
    }
}

impl StaticType for Vec<String> {
    fn static_type() -> Type {
        unsafe { from_glib(glib_sys::g_strv_get_type()) }
    }
}

#[inline]
#[allow(clippy::missing_safety_doc)]
pub unsafe fn instance_of<C: StaticType>(ptr: glib_sys::gconstpointer) -> bool {
    from_glib(gobject_sys::g_type_check_instance_is_a(
        ptr as *mut _,
        <C as StaticType>::static_type().to_glib(),
    ))
}

impl FromGlib<glib_sys::GType> for Type {
    #[inline]
    fn from_glib(val: glib_sys::GType) -> Type {
        use self::Type::*;
        match val {
            gobject_sys::G_TYPE_INVALID => Invalid,
            gobject_sys::G_TYPE_NONE => Unit,
            gobject_sys::G_TYPE_INTERFACE => BaseInterface,
            gobject_sys::G_TYPE_CHAR => I8,
            gobject_sys::G_TYPE_UCHAR => U8,
            gobject_sys::G_TYPE_BOOLEAN => Bool,
            gobject_sys::G_TYPE_INT => I32,
            gobject_sys::G_TYPE_UINT => U32,
            gobject_sys::G_TYPE_LONG => ILong,
            gobject_sys::G_TYPE_ULONG => ULong,
            gobject_sys::G_TYPE_INT64 => I64,
            gobject_sys::G_TYPE_UINT64 => U64,
            gobject_sys::G_TYPE_ENUM => BaseEnum,
            gobject_sys::G_TYPE_FLAGS => BaseFlags,
            gobject_sys::G_TYPE_FLOAT => F32,
            gobject_sys::G_TYPE_DOUBLE => F64,
            gobject_sys::G_TYPE_STRING => String,
            gobject_sys::G_TYPE_POINTER => Pointer,
            gobject_sys::G_TYPE_BOXED => BaseBoxed,
            gobject_sys::G_TYPE_PARAM => BaseParamSpec,
            gobject_sys::G_TYPE_OBJECT => BaseObject,
            gobject_sys::G_TYPE_VARIANT => Variant,
            x => Other(x as usize),
        }
    }
}

impl ToGlib for Type {
    type GlibType = glib_sys::GType;

    fn to_glib(&self) -> glib_sys::GType {
        use self::Type::*;
        match *self {
            Invalid => gobject_sys::G_TYPE_INVALID,
            Unit => gobject_sys::G_TYPE_NONE,
            BaseInterface => gobject_sys::G_TYPE_INTERFACE,
            I8 => gobject_sys::G_TYPE_CHAR,
            U8 => gobject_sys::G_TYPE_UCHAR,
            Bool => gobject_sys::G_TYPE_BOOLEAN,
            I32 => gobject_sys::G_TYPE_INT,
            U32 => gobject_sys::G_TYPE_UINT,
            ILong => gobject_sys::G_TYPE_LONG,
            ULong => gobject_sys::G_TYPE_ULONG,
            I64 => gobject_sys::G_TYPE_INT64,
            U64 => gobject_sys::G_TYPE_UINT64,
            BaseEnum => gobject_sys::G_TYPE_ENUM,
            BaseFlags => gobject_sys::G_TYPE_FLAGS,
            F32 => gobject_sys::G_TYPE_FLOAT,
            F64 => gobject_sys::G_TYPE_DOUBLE,
            String => gobject_sys::G_TYPE_STRING,
            Pointer => gobject_sys::G_TYPE_POINTER,
            BaseBoxed => gobject_sys::G_TYPE_BOXED,
            BaseParamSpec => gobject_sys::G_TYPE_PARAM,
            BaseObject => gobject_sys::G_TYPE_OBJECT,
            Variant => gobject_sys::G_TYPE_VARIANT,
            Other(x) => x as glib_sys::GType,
        }
    }
}

impl<'a> ToGlibContainerFromSlice<'a, *mut glib_sys::GType> for Type {
    type Storage = Option<Vec<glib_sys::GType>>;

    fn to_glib_none_from_slice(t: &'a [Type]) -> (*mut glib_sys::GType, Self::Storage) {
        let mut vec = t.iter().map(ToGlib::to_glib).collect::<Vec<_>>();

        (vec.as_mut_ptr(), Some(vec))
    }

    fn to_glib_container_from_slice(t: &'a [Type]) -> (*mut glib_sys::GType, Self::Storage) {
        (Self::to_glib_full_from_slice(t), None)
    }

    fn to_glib_full_from_slice(t: &[Type]) -> *mut glib_sys::GType {
        if t.is_empty() {
            return ptr::null_mut();
        }

        unsafe {
            let res = glib_sys::g_malloc0(mem::size_of::<glib_sys::GType>() * (t.len() + 1))
                as *mut glib_sys::GType;
            for (i, v) in t.iter().enumerate() {
                *res.add(i) = v.to_glib();
            }
            res
        }
    }
}

impl FromGlibContainerAsVec<Type, *const glib_sys::GType> for Type {
    unsafe fn from_glib_none_num_as_vec(ptr: *const glib_sys::GType, num: usize) -> Vec<Self> {
        if num == 0 || ptr.is_null() {
            return Vec::new();
        }

        let mut res = Vec::with_capacity(num);
        for i in 0..num {
            res.push(from_glib(*ptr.add(i)));
        }
        res
    }

    unsafe fn from_glib_container_num_as_vec(_: *const glib_sys::GType, _: usize) -> Vec<Self> {
        // Can't really free a *const
        unimplemented!();
    }

    unsafe fn from_glib_full_num_as_vec(_: *const glib_sys::GType, _: usize) -> Vec<Self> {
        // Can't really free a *const
        unimplemented!();
    }
}

impl FromGlibContainerAsVec<Type, *mut glib_sys::GType> for Type {
    unsafe fn from_glib_none_num_as_vec(ptr: *mut glib_sys::GType, num: usize) -> Vec<Self> {
        FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr as *const _, num)
    }

    unsafe fn from_glib_container_num_as_vec(ptr: *mut glib_sys::GType, num: usize) -> Vec<Self> {
        let res = FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, num);
        glib_sys::g_free(ptr as *mut _);
        res
    }

    unsafe fn from_glib_full_num_as_vec(ptr: *mut glib_sys::GType, num: usize) -> Vec<Self> {
        FromGlibContainerAsVec::from_glib_container_num_as_vec(ptr, num)
    }
}
<commit_msg>types: fix crashes on Type::Invalid API<commit_after>// Copyright 2015-2016, The Gtk-rs Project Developers.
// See the COPYRIGHT file at the top-level directory of this distribution.
// Licensed under the MIT license, see the LICENSE file or <http://opensource.org/licenses/MIT>

//! Runtime type information.

use glib_sys;
use gobject_sys;
use translate::{
    from_glib, from_glib_none, FromGlib, FromGlibContainerAsVec, ToGlib, ToGlibContainerFromSlice,
    ToGlibPtr, ToGlibPtrMut,
};
use value::{FromValue, FromValueOptional, SetValue, Value};

use std::fmt;
use std::mem;
use std::ptr;

/// A GLib or GLib-based library type
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum Type {
    /// An invalid `Type` used as error return value in some functions
    Invalid,
    /// The fundamental type corresponding to the unit type `()`
    Unit,
    /// The fundamental type corresponding to `i8`
    I8,
    /// The fundamental type corresponding to `u8`
    U8,
    /// The fundamental type corresponding to `bool`
    Bool,
    /// The fundamental type corresponding to `i32`
    I32,
    /// The fundamental type corresponding to `u32`
    U32,
    /// The fundamental type corresponding to C `long`
    ILong,
    /// The fundamental type corresponding to C `unsigned long`
    ULong,
    /// The fundamental type corresponding to `i64`
    I64,
    /// The fundamental type corresponding to `u64`
    U64,
    /// The fundamental type corresponding to `f32`
    F32,
    /// The fundamental type corresponding to `f64`
    F64,
    /// The fundamental type corresponding to `String`
    String,
    /// The fundamental type corresponding to a pointer
    Pointer,
    /// The fundamental type of GVariant
    Variant,
    /// The fundamental type from which all interfaces are derived
    BaseInterface,
    /// The fundamental type from which all enumeration types are derived
    BaseEnum,
    /// The fundamental type from which all flags types are derived
    BaseFlags,
    /// The fundamental type from which all boxed types are derived
    BaseBoxed,
    /// The fundamental type from which all `GParamSpec` types are derived
    BaseParamSpec,
    /// The fundamental type from which all objects are derived
    BaseObject,
    /// A non-fundamental type identified by value of type `usize`
    Other(usize),
}

impl Type {
    pub fn name(&self) -> String {
        match self {
            Type::Invalid => "<invalid>".to_string(),
            _ => unsafe { from_glib_none(gobject_sys::g_type_name(self.to_glib())) },
        }
    }

    pub fn qname(&self) -> ::Quark {
        match self {
            Type::Invalid => ::Quark::from_string("<invalid>"),
            _ => unsafe { from_glib(gobject_sys::g_type_qname(self.to_glib())) },
        }
    }

    pub fn is_a(&self, other: &Type) -> bool {
        unsafe { from_glib(gobject_sys::g_type_is_a(self.to_glib(), other.to_glib())) }
    }

    pub fn parent(&self) -> Option<Self> {
        unsafe {
            let parent = gobject_sys::g_type_parent(self.to_glib());
            if parent == gobject_sys::G_TYPE_INVALID {
                None
            } else {
                Some(from_glib(parent))
            }
        }
    }

    pub fn children(&self) -> Vec<Self> {
        unsafe {
            let mut n_children = 0u32;
            let children = gobject_sys::g_type_children(self.to_glib(), &mut n_children);

            FromGlibContainerAsVec::from_glib_full_num_as_vec(children, n_children as usize)
        }
    }

    pub fn interfaces(&self) -> Vec<Self> {
        unsafe {
            let mut n_interfaces = 0u32;
            let interfaces = gobject_sys::g_type_interfaces(self.to_glib(), &mut n_interfaces);

            FromGlibContainerAsVec::from_glib_full_num_as_vec(interfaces, n_interfaces as usize)
        }
    }
    pub fn interface_prerequisites(&self) -> Vec<Self> {
        match self {
            t if !t.is_a(&Type::BaseInterface) => vec![],
            _ => unsafe {
                let mut n_prereqs = 0u32;
                let prereqs =
                    gobject_sys::g_type_interface_prerequisites(self.to_glib(), &mut n_prereqs);

                FromGlibContainerAsVec::from_glib_full_num_as_vec(prereqs, n_prereqs as usize)
            },
        }
    }

    pub fn from_name<'a, P: Into<&'a str>>(name: P) -> Option<Self> {
        unsafe {
            let type_ = gobject_sys::g_type_from_name(name.into().to_glib_none().0);
            if type_ == gobject_sys::G_TYPE_INVALID {
                None
            } else {
                Some(from_glib(type_))
            }
        }
    }
}

impl fmt::Debug for Type {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(&self.name())
    }
}

impl fmt::Display for Type {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str(&self.name())
    }
}

/// Types that are supported by GLib dynamic typing.
pub trait StaticType {
    /// Returns the type identifier of `Self`.
    fn static_type() -> Type;
}

impl StaticType for Type {
    fn static_type() -> Type {
        unsafe { from_glib(gobject_sys::g_gtype_get_type()) }
    }
}

impl<'a> FromValueOptional<'a> for Type {
    unsafe fn from_value_optional(value: &'a Value) -> Option<Self> {
        Some(from_glib(gobject_sys::g_value_get_gtype(
            value.to_glib_none().0,
        )))
    }
}

impl<'a> FromValue<'a> for Type {
    unsafe fn from_value(value: &'a Value) -> Self {
        from_glib(gobject_sys::g_value_get_gtype(value.to_glib_none().0))
    }
}

impl SetValue for Type {
    unsafe fn set_value(value: &mut Value, this: &Self) {
        gobject_sys::g_value_set_gtype(value.to_glib_none_mut().0, this.to_glib())
    }
}

impl<'a, T: ?Sized + StaticType> StaticType for &'a T {
    fn static_type() -> Type {
        T::static_type()
    }
}

impl<'a, T: ?Sized + StaticType> StaticType for &'a mut T {
    fn static_type() -> Type {
        T::static_type()
    }
}

macro_rules! builtin {
    ($name:ident, $val:ident) => {
        impl StaticType for $name {
            fn static_type() -> Type {
                Type::$val
            }
        }
    };
}

builtin!(bool, Bool);
builtin!(i8, I8);
builtin!(u8, U8);
builtin!(i32, I32);
builtin!(u32, U32);
builtin!(i64, I64);
builtin!(u64, U64);
builtin!(f32, F32);
builtin!(f64, F64);
builtin!(str, String);
builtin!(String, String);

impl<'a> StaticType for [&'a str] {
    fn static_type() -> Type {
        unsafe { from_glib(glib_sys::g_strv_get_type()) }
    }
}

impl StaticType for Vec<String> {
    fn static_type() -> Type {
        unsafe { from_glib(glib_sys::g_strv_get_type()) }
    }
}

#[inline]
#[allow(clippy::missing_safety_doc)]
pub unsafe fn instance_of<C: StaticType>(ptr: glib_sys::gconstpointer) -> bool {
    from_glib(gobject_sys::g_type_check_instance_is_a(
        ptr as *mut _,
        <C as StaticType>::static_type().to_glib(),
    ))
}

impl FromGlib<glib_sys::GType> for Type {
    #[inline]
    fn from_glib(val: glib_sys::GType) -> Type {
        use self::Type::*;
        match val {
            gobject_sys::G_TYPE_INVALID => Invalid,
            gobject_sys::G_TYPE_NONE => Unit,
            gobject_sys::G_TYPE_INTERFACE => BaseInterface,
            gobject_sys::G_TYPE_CHAR => I8,
            gobject_sys::G_TYPE_UCHAR => U8,
            gobject_sys::G_TYPE_BOOLEAN => Bool,
            gobject_sys::G_TYPE_INT => I32,
            gobject_sys::G_TYPE_UINT => U32,
            gobject_sys::G_TYPE_LONG => ILong,
            gobject_sys::G_TYPE_ULONG => ULong,
            gobject_sys::G_TYPE_INT64 => I64,
            gobject_sys::G_TYPE_UINT64 => U64,
            gobject_sys::G_TYPE_ENUM => BaseEnum,
            gobject_sys::G_TYPE_FLAGS => BaseFlags,
            gobject_sys::G_TYPE_FLOAT => F32,
            gobject_sys::G_TYPE_DOUBLE => F64,
            gobject_sys::G_TYPE_STRING => String,
            gobject_sys::G_TYPE_POINTER => Pointer,
            gobject_sys::G_TYPE_BOXED => BaseBoxed,
            gobject_sys::G_TYPE_PARAM => BaseParamSpec,
            gobject_sys::G_TYPE_OBJECT => BaseObject,
            gobject_sys::G_TYPE_VARIANT => Variant,
            x => Other(x as usize),
        }
    }
}

impl ToGlib for Type {
    type GlibType = glib_sys::GType;

    fn to_glib(&self) -> glib_sys::GType {
        use self::Type::*;
        match *self {
            Invalid => gobject_sys::G_TYPE_INVALID,
            Unit => gobject_sys::G_TYPE_NONE,
            BaseInterface => gobject_sys::G_TYPE_INTERFACE,
            I8 => gobject_sys::G_TYPE_CHAR,
            U8 => gobject_sys::G_TYPE_UCHAR,
            Bool => gobject_sys::G_TYPE_BOOLEAN,
            I32 => gobject_sys::G_TYPE_INT,
            U32 => gobject_sys::G_TYPE_UINT,
            ILong => gobject_sys::G_TYPE_LONG,
            ULong => gobject_sys::G_TYPE_ULONG,
            I64 => gobject_sys::G_TYPE_INT64,
            U64 => gobject_sys::G_TYPE_UINT64,
            BaseEnum => gobject_sys::G_TYPE_ENUM,
            BaseFlags => gobject_sys::G_TYPE_FLAGS,
            F32 => gobject_sys::G_TYPE_FLOAT,
            F64 => gobject_sys::G_TYPE_DOUBLE,
            String => gobject_sys::G_TYPE_STRING,
            Pointer => gobject_sys::G_TYPE_POINTER,
            BaseBoxed => gobject_sys::G_TYPE_BOXED,
            BaseParamSpec => gobject_sys::G_TYPE_PARAM,
            BaseObject => gobject_sys::G_TYPE_OBJECT,
            Variant => gobject_sys::G_TYPE_VARIANT,
            Other(x) => x as glib_sys::GType,
        }
    }
}

impl<'a> ToGlibContainerFromSlice<'a, *mut glib_sys::GType> for Type {
    type Storage = Option<Vec<glib_sys::GType>>;

    fn to_glib_none_from_slice(t: &'a [Type]) -> (*mut glib_sys::GType, Self::Storage) {
        let mut vec = t.iter().map(ToGlib::to_glib).collect::<Vec<_>>();

        (vec.as_mut_ptr(), Some(vec))
    }

    fn to_glib_container_from_slice(t: &'a [Type]) -> (*mut glib_sys::GType, Self::Storage) {
        (Self::to_glib_full_from_slice(t), None)
    }

    fn to_glib_full_from_slice(t: &[Type]) -> *mut glib_sys::GType {
        if t.is_empty() {
            return ptr::null_mut();
        }

        unsafe {
            let res = glib_sys::g_malloc0(mem::size_of::<glib_sys::GType>() * (t.len() + 1))
                as *mut glib_sys::GType;
            for (i, v) in t.iter().enumerate() {
                *res.add(i) = v.to_glib();
            }
            res
        }
    }
}

impl FromGlibContainerAsVec<Type, *const glib_sys::GType> for Type {
    unsafe fn from_glib_none_num_as_vec(ptr: *const glib_sys::GType, num: usize) -> Vec<Self> {
        if num == 0 || ptr.is_null() {
            return Vec::new();
        }

        let mut res = Vec::with_capacity(num);
        for i in 0..num {
            res.push(from_glib(*ptr.add(i)));
        }
        res
    }

    unsafe fn from_glib_container_num_as_vec(_: *const glib_sys::GType, _: usize) -> Vec<Self> {
        // Can't really free a *const
        unimplemented!();
    }

    unsafe fn from_glib_full_num_as_vec(_: *const glib_sys::GType, _: usize) -> Vec<Self> {
        // Can't really free a *const
        unimplemented!();
    }
}

impl FromGlibContainerAsVec<Type, *mut glib_sys::GType> for Type {
    unsafe fn from_glib_none_num_as_vec(ptr: *mut glib_sys::GType, num: usize) -> Vec<Self> {
        FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr as *const _, num)
    }

    unsafe fn from_glib_container_num_as_vec(ptr: *mut glib_sys::GType, num: usize) -> Vec<Self> {
        let res = FromGlibContainerAsVec::from_glib_none_num_as_vec(ptr, num);
        glib_sys::g_free(ptr as *mut _);
        res
    }

    unsafe fn from_glib_full_num_as_vec(ptr: *mut glib_sys::GType, num: usize) -> Vec<Self> {
        FromGlibContainerAsVec::from_glib_container_num_as_vec(ptr, num)
    }
}

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

    #[test]
    fn invalid() {
        let invalid = Type::Invalid;

        assert_eq!(invalid.name(), "<invalid>");
        assert_eq!(invalid.qname(), ::Quark::from_string("<invalid>"));
        assert!(invalid.is_a(&Type::Invalid));
        assert!(!invalid.is_a(&Type::String));
        assert_eq!(invalid.parent(), None);
        assert_eq!(invalid.children(), vec![]);
        assert_eq!(invalid.interfaces(), vec![]);
        assert_eq!(invalid.interface_prerequisites(), vec![]);
        dbg!(&invalid);
    }
}
<|endoftext|>


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

//! Implements parallel traversal over the DOM tree.
//!
//! This code is highly unsafe. Keep this file small and easy to audit.

#![allow(unsafe_code)]

use dom::{OpaqueNode, TNode, UnsafeNode};
use std::mem;
use std::sync::atomic::Ordering;
use traversal::DomTraversalContext;
use workqueue::{WorkQueue, WorkUnit, WorkerProxy};

#[allow(dead_code)]
fn static_assertion(node: UnsafeNode) {
    unsafe {
        let _: UnsafeNodeList = mem::transmute(node);
    }
}

pub type UnsafeNodeList = (Box<Vec<UnsafeNode>>, OpaqueNode);

pub const CHUNK_SIZE: usize = 64;

pub struct WorkQueueData(usize, usize);

pub fn run_queue_with_custom_work_data_type<To, F, SharedContext: Sync>(
        queue: &mut WorkQueue<SharedContext, WorkQueueData>,
        callback: F,
        shared: &SharedContext)
        where To: 'static + Send, F: FnOnce(&mut WorkQueue<SharedContext, To>) {
    let queue: &mut WorkQueue<SharedContext, To> = unsafe {
        mem::transmute(queue)
    };
    callback(queue);
    queue.run(shared);
}

pub fn traverse_dom<N, C>(root: N,
                          queue_data: &C::SharedContext,
                          queue: &mut WorkQueue<C::SharedContext, WorkQueueData>)
                          where N: TNode, C: DomTraversalContext<N> {
    run_queue_with_custom_work_data_type(queue, |queue| {
        queue.push(WorkUnit {
            fun: top_down_dom::<N, C>,
            data: (Box::new(vec![root.to_unsafe()]), root.opaque()),
        });
    }, queue_data);
}

/// A parallel top-down DOM traversal.
#[inline(always)]
fn top_down_dom<N, C>(unsafe_nodes: UnsafeNodeList,
                      proxy: &mut WorkerProxy<C::SharedContext, UnsafeNodeList>)
                      where N: TNode, C: DomTraversalContext<N> {
    let context = C::new(proxy.user_data(), unsafe_nodes.1);

    let mut discovered_child_nodes = vec![];
    for unsafe_node in *unsafe_nodes.0 {
        // Get a real layout node.
        let node = unsafe { N::from_unsafe(&unsafe_node) };

        if !context.should_process(node) {
            continue;
        }

        // Perform the appropriate traversal.
        context.process_preorder(node);

        // Possibly enqueue the children.
        let mut children_to_process = 0isize;
        for kid in node.children() {
            context.pre_process_child_hook(node, kid);
            if context.should_process(kid) {
                children_to_process += 1;
                discovered_child_nodes.push(kid.to_unsafe())
            }
        }

        // Reset the count of children.
        {
            let data = node.mutate_data().unwrap();
            data.parallel.children_to_process
                         .store(children_to_process,
                                Ordering::Relaxed);
        }

        // If there were no more children, start walking back up.
        if children_to_process == 0 {
            bottom_up_dom::<N, C>(unsafe_nodes.1, unsafe_node, proxy)
        }
    }

    for chunk in discovered_child_nodes.chunks(CHUNK_SIZE) {
        proxy.push(WorkUnit {
            fun:  top_down_dom::<N, C>,
            data: (Box::new(chunk.iter().cloned().collect()), unsafe_nodes.1),
        });
    }
}

/// Process current node and potentially traverse its ancestors.
///
/// If we are the last child that finished processing, recursively process
/// our parent. Else, stop. Also, stop at the root.
///
/// Thus, if we start with all the leaves of a tree, we end up traversing
/// the whole tree bottom-up because each parent will be processed exactly
/// once (by the last child that finishes processing).
///
/// The only communication between siblings is that they both
/// fetch-and-subtract the parent's children count.
fn bottom_up_dom<N, C>(root: OpaqueNode,
                       unsafe_node: UnsafeNode,
                       proxy: &mut WorkerProxy<C::SharedContext, UnsafeNodeList>)
                       where N: TNode, C: DomTraversalContext<N> {
    let context = C::new(proxy.user_data(), root);

    // Get a real layout node.
    let mut node = unsafe { N::from_unsafe(&unsafe_node) };
    loop {
        // Perform the appropriate operation.
        context.process_postorder(node);

        let parent = match node.layout_parent_node(root) {
            None => break,
            Some(parent) => parent,
        };

        let parent_data = unsafe {
            &*parent.borrow_data_unchecked().unwrap()
        };

        if parent_data
            .parallel
            .children_to_process
            .fetch_sub(1, Ordering::Relaxed) != 1 {
            // Get out of here and find another node to work on.
            break
        }

        // We were the last child of our parent. Construct flows for our parent.
        node = parent;
    }
}
<commit_msg>style: Add a comment about pre_process_children_hook.<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/. */

//! Implements parallel traversal over the DOM tree.
//!
//! This code is highly unsafe. Keep this file small and easy to audit.

#![allow(unsafe_code)]

use dom::{OpaqueNode, TNode, UnsafeNode};
use std::mem;
use std::sync::atomic::Ordering;
use traversal::DomTraversalContext;
use workqueue::{WorkQueue, WorkUnit, WorkerProxy};

#[allow(dead_code)]
fn static_assertion(node: UnsafeNode) {
    unsafe {
        let _: UnsafeNodeList = mem::transmute(node);
    }
}

pub type UnsafeNodeList = (Box<Vec<UnsafeNode>>, OpaqueNode);

pub const CHUNK_SIZE: usize = 64;

pub struct WorkQueueData(usize, usize);

pub fn run_queue_with_custom_work_data_type<To, F, SharedContext: Sync>(
        queue: &mut WorkQueue<SharedContext, WorkQueueData>,
        callback: F,
        shared: &SharedContext)
        where To: 'static + Send, F: FnOnce(&mut WorkQueue<SharedContext, To>) {
    let queue: &mut WorkQueue<SharedContext, To> = unsafe {
        mem::transmute(queue)
    };
    callback(queue);
    queue.run(shared);
}

pub fn traverse_dom<N, C>(root: N,
                          queue_data: &C::SharedContext,
                          queue: &mut WorkQueue<C::SharedContext, WorkQueueData>)
                          where N: TNode, C: DomTraversalContext<N> {
    run_queue_with_custom_work_data_type(queue, |queue| {
        queue.push(WorkUnit {
            fun: top_down_dom::<N, C>,
            data: (Box::new(vec![root.to_unsafe()]), root.opaque()),
        });
    }, queue_data);
}

/// A parallel top-down DOM traversal.
#[inline(always)]
fn top_down_dom<N, C>(unsafe_nodes: UnsafeNodeList,
                      proxy: &mut WorkerProxy<C::SharedContext, UnsafeNodeList>)
                      where N: TNode, C: DomTraversalContext<N> {
    let context = C::new(proxy.user_data(), unsafe_nodes.1);

    let mut discovered_child_nodes = vec![];
    for unsafe_node in *unsafe_nodes.0 {
        // Get a real layout node.
        let node = unsafe { N::from_unsafe(&unsafe_node) };

        if !context.should_process(node) {
            continue;
        }

        // Perform the appropriate traversal.
        context.process_preorder(node);

        // Possibly enqueue the children.
        let mut children_to_process = 0isize;
        for kid in node.children() {
            // Trigger the hook pre-adding the kid to the list. This can (and in
            // fact uses to) change the result of the should_process operation.
            //
            // As of right now, this hook takes care of propagating the restyle
            // flag down the tree. In the future, more accurate behavior is
            // probably going to be needed.
            context.pre_process_child_hook(node, kid);
            if context.should_process(kid) {
                children_to_process += 1;
                discovered_child_nodes.push(kid.to_unsafe())
            }
        }

        // Reset the count of children.
        {
            let data = node.mutate_data().unwrap();
            data.parallel.children_to_process
                         .store(children_to_process,
                                Ordering::Relaxed);
        }

        // If there were no more children, start walking back up.
        if children_to_process == 0 {
            bottom_up_dom::<N, C>(unsafe_nodes.1, unsafe_node, proxy)
        }
    }

    for chunk in discovered_child_nodes.chunks(CHUNK_SIZE) {
        proxy.push(WorkUnit {
            fun:  top_down_dom::<N, C>,
            data: (Box::new(chunk.iter().cloned().collect()), unsafe_nodes.1),
        });
    }
}

/// Process current node and potentially traverse its ancestors.
///
/// If we are the last child that finished processing, recursively process
/// our parent. Else, stop. Also, stop at the root.
///
/// Thus, if we start with all the leaves of a tree, we end up traversing
/// the whole tree bottom-up because each parent will be processed exactly
/// once (by the last child that finishes processing).
///
/// The only communication between siblings is that they both
/// fetch-and-subtract the parent's children count.
fn bottom_up_dom<N, C>(root: OpaqueNode,
                       unsafe_node: UnsafeNode,
                       proxy: &mut WorkerProxy<C::SharedContext, UnsafeNodeList>)
                       where N: TNode, C: DomTraversalContext<N> {
    let context = C::new(proxy.user_data(), root);

    // Get a real layout node.
    let mut node = unsafe { N::from_unsafe(&unsafe_node) };
    loop {
        // Perform the appropriate operation.
        context.process_postorder(node);

        let parent = match node.layout_parent_node(root) {
            None => break,
            Some(parent) => parent,
        };

        let parent_data = unsafe {
            &*parent.borrow_data_unchecked().unwrap()
        };

        if parent_data
            .parallel
            .children_to_process
            .fetch_sub(1, Ordering::Relaxed) != 1 {
            // Get out of here and find another node to work on.
            break
        }

        // We were the last child of our parent. Construct flows for our parent.
        node = parent;
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate glium;

use glium::Surface;
use glium::texture::buffer_texture::BufferTexture;
use glium::texture::buffer_texture::BufferTextureType;

mod support;

#[test]
fn empty() {
    let display = support::build_display();

    let texture = BufferTexture::empty(&display, 32, BufferTextureType::Float);
    let texture: BufferTexture<(u8, u8, u8, u8)> = match texture {
        Ok(t) => t,
        Err(_) => return
    };

    display.assert_no_error(None);
    drop(texture);
    display.assert_no_error(None);
}

#[test]
fn sample() {
    let display = support::build_display();

    let data = &[(255, 0, 255, 255)];
    let buf_tex = BufferTexture::new(&display, data, BufferTextureType::Float);
    let buf_tex: BufferTexture<(u8, u8, u8, u8)> = match buf_tex {
        Ok(t) => t,
        Err(_) => return
    };

    let (vb, ib) = support::build_rectangle_vb_ib(&display);

    let program = glium::Program::from_source(&display,
        "
            #version 110

            attribute vec2 position;

            void main() {
                gl_Position = vec4(position, 0.0, 1.0);
            }
        ",
        "
            #version 140

            uniform samplerBuffer tex;

            void main() {
                gl_FragColor = texelFetch(tex, 0);
            }
        ",
        None);
    let program = match program {
        Ok(p) => p,
        Err(_) => return
    };

    let output = support::build_renderable_texture(&display);
    output.as_surface().clear_color(0.0, 0.0, 0.0, 0.0);
    output.as_surface().draw(&vb, &ib, &program, &uniform!{ tex: &buf_tex },
                             &Default::default()).unwrap();

    let data: Vec<Vec<(u8, u8, u8, u8)>> = output.read();
    for row in data.iter() {
        for pixel in row.iter() {
            assert_eq!(pixel, &(255, 0, 255, 255));
        }
    }

    display.assert_no_error(None);
}
<commit_msg>Add test for wrong texture buffer type<commit_after>#[macro_use]
extern crate glium;

use glium::Surface;
use glium::texture::buffer_texture::BufferTexture;
use glium::texture::buffer_texture::BufferTextureType;

mod support;

#[test]
fn empty() {
    let display = support::build_display();

    let texture = BufferTexture::empty(&display, 32, BufferTextureType::Float);
    let texture: BufferTexture<(u8, u8, u8, u8)> = match texture {
        Ok(t) => t,
        Err(_) => return
    };

    display.assert_no_error(None);
    drop(texture);
    display.assert_no_error(None);
}

#[test]
fn sample() {
    let display = support::build_display();

    let data = &[(255, 0, 255, 255)];
    let buf_tex = BufferTexture::new(&display, data, BufferTextureType::Float);
    let buf_tex: BufferTexture<(u8, u8, u8, u8)> = match buf_tex {
        Ok(t) => t,
        Err(_) => return
    };

    let (vb, ib) = support::build_rectangle_vb_ib(&display);

    let program = glium::Program::from_source(&display,
        "
            #version 110

            attribute vec2 position;

            void main() {
                gl_Position = vec4(position, 0.0, 1.0);
            }
        ",
        "
            #version 140

            uniform samplerBuffer tex;

            void main() {
                gl_FragColor = texelFetch(tex, 0);
            }
        ",
        None);
    let program = match program {
        Ok(p) => p,
        Err(_) => return
    };

    let output = support::build_renderable_texture(&display);
    output.as_surface().clear_color(0.0, 0.0, 0.0, 0.0);
    output.as_surface().draw(&vb, &ib, &program, &uniform!{ tex: &buf_tex },
                             &Default::default()).unwrap();

    let data: Vec<Vec<(u8, u8, u8, u8)>> = output.read();
    for row in data.iter() {
        for pixel in row.iter() {
            assert_eq!(pixel, &(255, 0, 255, 255));
        }
    }

    display.assert_no_error(None);
}

#[test]
fn wrong_type() {
    let display = support::build_display();

    let data = &[(255, 0, 255, 255)];
    let buf_tex = BufferTexture::new(&display, data, BufferTextureType::Float);
    let buf_tex: BufferTexture<(u8, u8, u8, u8)> = match buf_tex {
        Ok(t) => t,
        Err(_) => return
    };

    let (vb, ib) = support::build_rectangle_vb_ib(&display);

    let program = glium::Program::from_source(&display,
        "
            #version 110

            attribute vec2 position;

            void main() {
                gl_Position = vec4(position, 0.0, 1.0);
            }
        ",
        "
            #version 140

            uniform isamplerBuffer tex;

            void main() {
                gl_FragColor = texelFetch(tex, 0);
            }
        ",
        None);
    let program = match program {
        Ok(p) => p,
        Err(_) => return
    };

    let mut frame = display.draw();
    let result = frame.draw(&vb, &ib, &program, &uniform!{ tex: &buf_tex }, &Default::default());

    match result {
        Err(glium::DrawError::UniformTypeMismatch { .. }) => (),
        _ => panic!()
    };

    frame.finish().unwrap();

    display.assert_no_error(None);
}
<|endoftext|>


<commit_before>import front.ast;
import front.ast.ident;
import front.ast.def;
import front.ast.ann;
import driver.session;
import util.common.span;
import std.map.hashmap;
import std.list.list;
import std.list.nil;
import std.list.cons;
import std.option;
import std.option.some;
import std.option.none;
import std._str;
import std._vec;

tag scope {
    scope_crate(@ast.crate);
    scope_item(@ast.item);
    scope_block(ast.block);
    scope_arm(ast.arm);
}

type env = rec(list[scope] scopes,
               session.session sess);

fn lookup_name(&env e, ast.ident i) -> option.t[def] {

    // log "resolving name " + i;

    fn found_def_item(@ast.item i) -> option.t[def] {
        alt (i.node) {
            case (ast.item_const(_, _, _, ?id, _)) {
                ret some[def](ast.def_const(id));
            }
            case (ast.item_fn(_, _, _, ?id, _)) {
                ret some[def](ast.def_fn(id));
            }
            case (ast.item_mod(_, _, ?id)) {
                ret some[def](ast.def_mod(id));
            }
            case (ast.item_ty(_, _, _, ?id, _)) {
                ret some[def](ast.def_ty(id));
            }
            case (ast.item_tag(_, _, _, ?id)) {
                ret some[def](ast.def_ty(id));
            }
        }
    }

    fn found_decl_stmt(@ast.stmt s) -> option.t[def] {
        alt (s.node) {
            case (ast.stmt_decl(?d)) {
                alt (d.node) {
                    case (ast.decl_local(?loc)) {
                        ret some[def](ast.def_local(loc.id));
                    }
                    case (ast.decl_item(?it)) {
                        ret found_def_item(it);
                    }
                }
            }
        }
        ret none[def];
    }

    fn check_mod(ast.ident i, ast._mod m) -> option.t[def] {
        alt (m.index.find(i)) {
            case (some[ast.mod_index_entry](?ent)) {
                alt (ent) {
                    case (ast.mie_item(?ix)) {
                        ret found_def_item(m.items.(ix));
                    }
                    case (ast.mie_tag_variant(?item_idx, ?variant_idx)) {
                        alt (m.items.(item_idx).node) {
                            case (ast.item_tag(_, ?variants, _, ?tid)) {
                                auto vid = variants.(variant_idx).id;
                                ret some[def](ast.def_variant(tid, vid));
                            }
                            case (_) {
                                log "tag item not actually a tag";
                                fail;
                            }
                        }
                    }
                }
            }
        }
        ret none[def];
    }

    fn in_scope(ast.ident i, &scope s) -> option.t[def] {
        alt (s) {

            case (scope_crate(?c)) {
                ret check_mod(i, c.node.module);
            }

            case (scope_item(?it)) {
                alt (it.node) {
                    case (ast.item_fn(_, ?f, _, _, _)) {
                        for (ast.arg a in f.inputs) {
                            if (_str.eq(a.ident, i)) {
                                ret some[def](ast.def_arg(a.id));
                            }
                        }
                    }
                    case (ast.item_mod(_, ?m, _)) {
                        ret check_mod(i, m);
                    }
                    case (_) { /* fall through */ }
                }
            }

            case (scope_block(?b)) {
                alt (b.node.index.find(i)) {
                    case (some[uint](?ix)) {
                        ret found_decl_stmt(b.node.stmts.(ix));
                    }
                    case (_) { /* fall through */  }
                }
            }

            case (scope_arm(?a)) {
                alt (a.index.find(i)) {
                    case (some[ast.def_id](?did)) {
                        ret some[def](ast.def_binding(did));
                    }
                    case (_) { /* fall through */  }
                }
            }
        }
        ret none[def];
    }

    ret std.list.find[scope,def](e.scopes, bind in_scope(i, _));
}

fn fold_expr_name(&env e, &span sp, &ast.name n,
                  &option.t[def] d, ann a) -> @ast.expr {

    if (_vec.len[@ast.ty](n.node.types) > 0u) {
        e.sess.unimpl("resoling name expr with ty params");
    }

    auto d_ = lookup_name(e, n.node.ident);

    alt (d_) {
        case (some[def](_)) {
            // log "resolved name " + n.node.ident;
        }
        case (none[def]) {
            e.sess.err("unresolved name: " + n.node.ident);
        }
    }

    ret @fold.respan[ast.expr_](sp, ast.expr_name(n, d_, a));
}

fn fold_ty_path(&env e, &span sp, ast.path p,
                &option.t[def] d) -> @ast.ty {

    let uint len = _vec.len[ast.name](p);
    check (len != 0u);
    if (len > 1u) {
        e.sess.unimpl("resoling path ty with >1 component");
    }

    let ast.name n = p.(0);

    if (_vec.len[@ast.ty](n.node.types) > 0u) {
        e.sess.unimpl("resoling path ty with ty params");
    }

    auto d_ = lookup_name(e, n.node.ident);

    alt (d_) {
        case (some[def](_)) {
            // log "resolved name " + n.node.ident;
        }
        case (none[def]) {
            e.sess.err("unresolved name: " + n.node.ident);
        }
    }

    ret @fold.respan[ast.ty_](sp, ast.ty_path(p, d_));
}

fn update_env_for_crate(&env e, @ast.crate c) -> env {
    ret rec(scopes = cons[scope](scope_crate(c), @e.scopes) with e);
}

fn update_env_for_item(&env e, @ast.item i) -> env {
    ret rec(scopes = cons[scope](scope_item(i), @e.scopes) with e);
}

fn update_env_for_block(&env e, &ast.block b) -> env {
    ret rec(scopes = cons[scope](scope_block(b), @e.scopes) with e);
}

fn update_env_for_arm(&env e, &ast.arm p) -> env {
    log "update_env_for_arm";
    ret rec(scopes = cons[scope](scope_arm(p), @e.scopes) with e);
}

fn resolve_crate(session.session sess, @ast.crate crate) -> @ast.crate {

    let fold.ast_fold[env] fld = fold.new_identity_fold[env]();

    fld = @rec( fold_expr_name = bind fold_expr_name(_,_,_,_,_),
                fold_ty_path = bind fold_ty_path(_,_,_,_),
                update_env_for_crate = bind update_env_for_crate(_,_),
                update_env_for_item = bind update_env_for_item(_,_),
                update_env_for_block = bind update_env_for_block(_,_),
                update_env_for_arm = bind update_env_for_arm(_,_)
                with *fld );

    auto e = rec(scopes = nil[scope],
                 sess = sess);

    ret fold.fold_crate[env](e, fld, crate);
}

// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C ../.. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<commit_msg>rustc: Remove "update_env_for_arm" debugging message<commit_after>import front.ast;
import front.ast.ident;
import front.ast.def;
import front.ast.ann;
import driver.session;
import util.common.span;
import std.map.hashmap;
import std.list.list;
import std.list.nil;
import std.list.cons;
import std.option;
import std.option.some;
import std.option.none;
import std._str;
import std._vec;

tag scope {
    scope_crate(@ast.crate);
    scope_item(@ast.item);
    scope_block(ast.block);
    scope_arm(ast.arm);
}

type env = rec(list[scope] scopes,
               session.session sess);

fn lookup_name(&env e, ast.ident i) -> option.t[def] {

    // log "resolving name " + i;

    fn found_def_item(@ast.item i) -> option.t[def] {
        alt (i.node) {
            case (ast.item_const(_, _, _, ?id, _)) {
                ret some[def](ast.def_const(id));
            }
            case (ast.item_fn(_, _, _, ?id, _)) {
                ret some[def](ast.def_fn(id));
            }
            case (ast.item_mod(_, _, ?id)) {
                ret some[def](ast.def_mod(id));
            }
            case (ast.item_ty(_, _, _, ?id, _)) {
                ret some[def](ast.def_ty(id));
            }
            case (ast.item_tag(_, _, _, ?id)) {
                ret some[def](ast.def_ty(id));
            }
        }
    }

    fn found_decl_stmt(@ast.stmt s) -> option.t[def] {
        alt (s.node) {
            case (ast.stmt_decl(?d)) {
                alt (d.node) {
                    case (ast.decl_local(?loc)) {
                        ret some[def](ast.def_local(loc.id));
                    }
                    case (ast.decl_item(?it)) {
                        ret found_def_item(it);
                    }
                }
            }
        }
        ret none[def];
    }

    fn check_mod(ast.ident i, ast._mod m) -> option.t[def] {
        alt (m.index.find(i)) {
            case (some[ast.mod_index_entry](?ent)) {
                alt (ent) {
                    case (ast.mie_item(?ix)) {
                        ret found_def_item(m.items.(ix));
                    }
                    case (ast.mie_tag_variant(?item_idx, ?variant_idx)) {
                        alt (m.items.(item_idx).node) {
                            case (ast.item_tag(_, ?variants, _, ?tid)) {
                                auto vid = variants.(variant_idx).id;
                                ret some[def](ast.def_variant(tid, vid));
                            }
                            case (_) {
                                log "tag item not actually a tag";
                                fail;
                            }
                        }
                    }
                }
            }
        }
        ret none[def];
    }

    fn in_scope(ast.ident i, &scope s) -> option.t[def] {
        alt (s) {

            case (scope_crate(?c)) {
                ret check_mod(i, c.node.module);
            }

            case (scope_item(?it)) {
                alt (it.node) {
                    case (ast.item_fn(_, ?f, _, _, _)) {
                        for (ast.arg a in f.inputs) {
                            if (_str.eq(a.ident, i)) {
                                ret some[def](ast.def_arg(a.id));
                            }
                        }
                    }
                    case (ast.item_mod(_, ?m, _)) {
                        ret check_mod(i, m);
                    }
                    case (_) { /* fall through */ }
                }
            }

            case (scope_block(?b)) {
                alt (b.node.index.find(i)) {
                    case (some[uint](?ix)) {
                        ret found_decl_stmt(b.node.stmts.(ix));
                    }
                    case (_) { /* fall through */  }
                }
            }

            case (scope_arm(?a)) {
                alt (a.index.find(i)) {
                    case (some[ast.def_id](?did)) {
                        ret some[def](ast.def_binding(did));
                    }
                    case (_) { /* fall through */  }
                }
            }
        }
        ret none[def];
    }

    ret std.list.find[scope,def](e.scopes, bind in_scope(i, _));
}

fn fold_expr_name(&env e, &span sp, &ast.name n,
                  &option.t[def] d, ann a) -> @ast.expr {

    if (_vec.len[@ast.ty](n.node.types) > 0u) {
        e.sess.unimpl("resoling name expr with ty params");
    }

    auto d_ = lookup_name(e, n.node.ident);

    alt (d_) {
        case (some[def](_)) {
            // log "resolved name " + n.node.ident;
        }
        case (none[def]) {
            e.sess.err("unresolved name: " + n.node.ident);
        }
    }

    ret @fold.respan[ast.expr_](sp, ast.expr_name(n, d_, a));
}

fn fold_ty_path(&env e, &span sp, ast.path p,
                &option.t[def] d) -> @ast.ty {

    let uint len = _vec.len[ast.name](p);
    check (len != 0u);
    if (len > 1u) {
        e.sess.unimpl("resoling path ty with >1 component");
    }

    let ast.name n = p.(0);

    if (_vec.len[@ast.ty](n.node.types) > 0u) {
        e.sess.unimpl("resoling path ty with ty params");
    }

    auto d_ = lookup_name(e, n.node.ident);

    alt (d_) {
        case (some[def](_)) {
            // log "resolved name " + n.node.ident;
        }
        case (none[def]) {
            e.sess.err("unresolved name: " + n.node.ident);
        }
    }

    ret @fold.respan[ast.ty_](sp, ast.ty_path(p, d_));
}

fn update_env_for_crate(&env e, @ast.crate c) -> env {
    ret rec(scopes = cons[scope](scope_crate(c), @e.scopes) with e);
}

fn update_env_for_item(&env e, @ast.item i) -> env {
    ret rec(scopes = cons[scope](scope_item(i), @e.scopes) with e);
}

fn update_env_for_block(&env e, &ast.block b) -> env {
    ret rec(scopes = cons[scope](scope_block(b), @e.scopes) with e);
}

fn update_env_for_arm(&env e, &ast.arm p) -> env {
    ret rec(scopes = cons[scope](scope_arm(p), @e.scopes) with e);
}

fn resolve_crate(session.session sess, @ast.crate crate) -> @ast.crate {

    let fold.ast_fold[env] fld = fold.new_identity_fold[env]();

    fld = @rec( fold_expr_name = bind fold_expr_name(_,_,_,_,_),
                fold_ty_path = bind fold_ty_path(_,_,_,_),
                update_env_for_crate = bind update_env_for_crate(_,_),
                update_env_for_item = bind update_env_for_item(_,_),
                update_env_for_block = bind update_env_for_block(_,_),
                update_env_for_arm = bind update_env_for_arm(_,_)
                with *fld );

    auto e = rec(scopes = nil[scope],
                 sess = sess);

    ret fold.fold_crate[env](e, fld, crate);
}

// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C ../.. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<|endoftext|>


<commit_before>use std::net::TcpStream;
//use std::time::Duration;
use byteorder::WriteBytesExt;
use net2::TcpStreamExt;

use crate::error;
use crate::fcall::*;
use crate::serialize;

pub type Result<T> = ::std::result::Result<T, error::Error>;

macro_rules! io_err {
    ($kind:ident, $msg:expr) => {
        ::std::io::Error::new(::std::io::ErrorKind::$kind, $msg)
    };
}

macro_rules! res {
    ($err:expr) => {
        Err(From::from($err))
    };
}

macro_rules! otry {
    ($opt:expr) => {
        match $opt {
            Some(val) => val,
            None => return None,
        }
    };
}

pub fn parse_proto(arg: &str) -> Option<(&str, String)> {
    let mut split = arg.split("!");
    let (proto, addr, port) = (
        otry!(split.nth(0)),
        otry!(split.nth(0)),
        otry!(split.nth(0)),
    );

    Some((proto, addr.to_owned() + ":" + port))
}

// See also: diod/libdiod/diod_sock.c
pub fn setup_tcp_stream(stream: &TcpStream) -> ::std::io::Result<()> {
    //TcpStreamExt::set_keepalive(stream, Some(Duration::from_secs(120)))?;
    TcpStreamExt::set_nodelay(stream, true)
}

pub fn respond<WExt: WriteBytesExt>(stream: &mut WExt, tag: u16, body: Fcall) -> Result<()> {
    if MsgType::from(&body).is_t() {
        return res!(io_err!(Other, "Invalid 9P message in this context"));
    };

    let msg = Msg {
        tag: tag,
        body: body,
    };
    serialize::write_msg(stream, &msg)?;

    debug!("\t← {:?}", msg);

    Ok(())
}
<commit_msg>Use try ops for Option<commit_after>use std::net::TcpStream;
//use std::time::Duration;
use byteorder::WriteBytesExt;
use net2::TcpStreamExt;

use crate::error;
use crate::fcall::*;
use crate::serialize;

pub type Result<T> = ::std::result::Result<T, error::Error>;

macro_rules! io_err {
    ($kind:ident, $msg:expr) => {
        ::std::io::Error::new(::std::io::ErrorKind::$kind, $msg)
    };
}

macro_rules! res {
    ($err:expr) => {
        Err(From::from($err))
    };
}

pub fn parse_proto(arg: &str) -> Option<(&str, String)> {
    let mut split = arg.split("!");
    let (proto, addr, port) = (split.nth(0)?, split.nth(0)?, split.nth(0)?);

    Some((proto, addr.to_owned() + ":" + port))
}

// See also: diod/libdiod/diod_sock.c
pub fn setup_tcp_stream(stream: &TcpStream) -> ::std::io::Result<()> {
    //TcpStreamExt::set_keepalive(stream, Some(Duration::from_secs(120)))?;
    TcpStreamExt::set_nodelay(stream, true)
}

pub fn respond<WExt: WriteBytesExt>(stream: &mut WExt, tag: u16, body: Fcall) -> Result<()> {
    if MsgType::from(&body).is_t() {
        return res!(io_err!(Other, "Invalid 9P message in this context"));
    };

    let msg = Msg {
        tag: tag,
        body: body,
    };
    serialize::write_msg(stream, &msg)?;

    debug!("\t← {:?}", msg);

    Ok(())
}
<|endoftext|>


<commit_before><commit_msg>World refactored: removed unused fields, added main_character field, creatures now stored in vector<commit_after><|endoftext|>


<commit_before><commit_msg>Mirror all log levels in the log file<commit_after><|endoftext|>


<commit_before>#[derive(Debug, PartialEq)]
pub struct NumericLiteral(pub f64);

#[derive(Debug, PartialEq)]
pub struct StringLiteral<'a>(pub &'a str);

pub mod parsing {

    use nom::{digit, hex_digit, oct_digit};
    use parser::helpers::parsing::*;
    use parser::js::terminals::*;

    named!(pub numeric_literal<&str, NumericLiteral>, conv!(NumericLiteral(do_parse!(
        take_while_s!(is_whitespace) >>
        numeric_literal: alt!(
            decimal_literal
            |
            hex_integer_literal
            |
            octal_integer_literal
        ) >>
        (numeric_literal)
    ))));

    named!(decimal_literal<&str, f64>, do_parse!(
        dec_lit: recognize!(alt!(
            do_parse!(
                decimal_integer_literal >>
                do_parse!(
                    opt!(complete!(do_parse!(
                        tag_s!(".") >>
                        opt!(complete!(digit)) >>
                        ()
                    ))) >>
                    opt!(complete!(exponential_part)) >>
                    ()
                ) >>
                ()
            )
            |
            do_parse!(
                tag_s!(".") >>
                complete!(digit) >>
                opt!(complete!(exponential_part)) >>
                ()
            )
        )) >>
        (dec_lit.parse::<f64>().unwrap())
    ));

    named!(decimal_integer_literal<&str, &str>, recognize!(alt!(
        do_parse!(
            tag_s!("0") >>
            not!(digit) >>
            not!(tag_s!("x")) >>
            not!(tag_s!("X")) >>
            ()
        )
        |
        do_parse!(
            not!(tag_s!("0")) >>
            digit >>
            ()
        )
    )));

    named!(exponential_part<&str, &str>, recognize!(do_parse!(
        alt!(tag_s!("e") | tag_s!("E")) >>
        opt!(alt!(tag_s!("+") | tag_s!("-"))) >>
        digit >>
        ()
    )));

    named!(hex_integer_literal<&str, f64>, do_parse!(
        alt!(tag_s!("0x") | tag_s!("0X")) >>
        hex: hex_digit >>
        (i64::from_str_radix(hex, 16).unwrap() as f64)
    ));

    named!(octal_integer_literal<&str, f64>, do_parse!(
        tag_s!("0") >>
        octal: oct_digit >>
        (i64::from_str_radix(octal, 8).unwrap() as f64)
    ));

    named!(pub string_literal<&str, StringLiteral>, do_parse!(
        delimiter: alt!(
            keyword!("\"")
            |
            keyword!("'")
        ) >>
        string: take_until_s!(delimiter) >> // TODO: escape chars
        keyword!(delimiter) >>
        (StringLiteral(string))
    ));

    named!(pub identifier<&str, &str>, do_parse!(
        take_while_s!(is_whitespace) >>
        identifier: recognize!(do_parse!(
            xid_start >>
            many0!(complete!(xid_continue)) >>
            ()
        )) >>
        (identifier)
    ));

    named!(pub js_identifier<&str, &str>, alt!(
        keyword!("property")
        |
        keyword!("signal")
        |
        keyword!("readonly")
        |
        keyword!("on")
        |
        keyword!("get")
        |
        keyword!("set")
        |
        identifier
    ));

    named!(pub reserved_identifier<&str, &str>, alt!(
        keyword!("break")
        |
        keyword!("case")
        |
        keyword!("catch")
        |
        keyword!("continue")
        |
        keyword!("default")
        |
        keyword!("delete")
        |
        keyword!("do")
        |
        keyword!("else")
        |
        keyword!("false")
        |
        keyword!("finally")
        |
        keyword!("for")
        |
        keyword!("function")
        |
        keyword!("if")
        |
        keyword!("in")
        |
        keyword!("instanceof")
        |
        keyword!("new")
        |
        keyword!("null")
        |
        keyword!("return")
        |
        keyword!("switch")
        |
        keyword!("this")
        |
        keyword!("throw")
        |
        keyword!("true")
        |
        keyword!("try")
        |
        keyword!("typeof")
        |
        keyword!("var")
        |
        keyword!("void")
        |
        keyword!("while")
        |
        keyword!("const")
        |
        keyword!("debugger")
        |
        keyword!("with")
    ));

    named!(pub property_identifier<&str, &str>, alt!(
        reserved_identifier
        |
        js_identifier
    ));

    named!(pub assignment_operator<&str, &str>, alt!(
        keyword!("=")
        |
        keyword!("*=")
        |
        keyword!("/=")
        |
        keyword!("%=")
        |
        keyword!("+=")
        |
        keyword!("-=")
        |
        keyword!("<<=")
        |
        keyword!(">>>=")
        |
        keyword!(">>=")
        |
        keyword!("&=")
        |
        keyword!("^=")
        |
        keyword!("|=")
    ));

    named!(pub automatic_semicolon<&str, &str>, alt!(
        keyword!(";")
        |
        peek!(line_terminator)
        |
        peek!(keyword!("}"))
        |
        eof
    ));

    named!(eof<&str, &str>, do_parse!(
        take_while_s!(is_whitespace) >>
        eof: eof!() >>
        (eof)
    ));

    named!(pub line_terminator<&str, &str>, alt!(
        tag_s!("\r\n")
        |
        tag_s!("\n")
        |
        tag_s!("\u{2028}")
        |
        tag_s!("\u{2029}")
    ));

    #[cfg(test)]
    mod tests {
        use nom::{ErrorKind, IResult};
        use super::*;

        #[test]
        fn numeric_literal() {
            assert!(super::numeric_literal("").is_incomplete());

            // Decimal
            assert_eq!(super::numeric_literal("42"), IResult::Done("", NumericLiteral(42_f64)));
            assert_eq!(super::numeric_literal(" 42 "), IResult::Done(" ", NumericLiteral(42_f64)));
            assert_eq!(super::numeric_literal("0"), IResult::Done("", NumericLiteral(0_f64)));
            assert_eq!(super::numeric_literal("42.42e-4"), IResult::Done("", NumericLiteral(42.42e-4_f64)));
            assert_eq!(super::numeric_literal(".42"), IResult::Done("", NumericLiteral(0.42_f64)));
            assert_eq!(super::numeric_literal("42."), IResult::Done("", NumericLiteral(42_f64)));

            assert_eq!(super::numeric_literal("+42"), IResult::Error(ErrorKind::Alt)); // Identity is unary expression
            assert_eq!(super::numeric_literal("-42"), IResult::Error(ErrorKind::Alt)); // Negation is unary expression
            assert_eq!(super::numeric_literal("."), IResult::Error(ErrorKind::Alt));

            // Octal
            assert_eq!(super::numeric_literal("042"), IResult::Done("", NumericLiteral(34_f64)));

            // Hex
            assert_eq!(super::numeric_literal("0x42"), IResult::Done("", NumericLiteral(66_f64)));
            assert_eq!(super::numeric_literal("0X42"), IResult::Done("", NumericLiteral(66_f64)));
        }

        #[test]
        fn string_literal() {
            assert!(super::string_literal("").is_incomplete());

            assert_eq!(super::string_literal("\"hi\""), IResult::Done("", StringLiteral("hi")));
            assert_eq!(super::string_literal(" 'hi' "), IResult::Done(" ", StringLiteral("hi")));

            assert_eq!(super::string_literal("\"hi"), IResult::Error(ErrorKind::TakeUntil)); // FIXME: https://github.com/Geal/nom/issues/397
            assert_eq!(super::string_literal("'hi"), IResult::Error(ErrorKind::TakeUntil));
        }

        #[test]
        fn identifier() {
            assert!(super::identifier("").is_incomplete());

            assert_eq!(super::identifier("foo"), IResult::Done("", "foo"));
            assert_eq!(super::identifier(" foo"), IResult::Done("", "foo"));
            assert_eq!(super::identifier("foo bar"), IResult::Done(" bar", "foo"));

            assert_eq!(super::identifier("42foo"), IResult::Error(ErrorKind::Verify));
        }
    }
}<commit_msg>Fix automatic_semicolon to properly detect EOF instead of returning Incomplete<commit_after>#[derive(Debug, PartialEq)]
pub struct NumericLiteral(pub f64);

#[derive(Debug, PartialEq)]
pub struct StringLiteral<'a>(pub &'a str);

pub mod parsing {

    use nom::{digit, hex_digit, oct_digit};
    use parser::helpers::parsing::*;
    use parser::js::terminals::*;

    named!(pub numeric_literal<&str, NumericLiteral>, conv!(NumericLiteral(do_parse!(
        take_while_s!(is_whitespace) >>
        numeric_literal: alt!(
            decimal_literal
            |
            hex_integer_literal
            |
            octal_integer_literal
        ) >>
        (numeric_literal)
    ))));

    named!(decimal_literal<&str, f64>, do_parse!(
        dec_lit: recognize!(alt!(
            do_parse!(
                decimal_integer_literal >>
                do_parse!(
                    opt!(complete!(do_parse!(
                        tag_s!(".") >>
                        opt!(complete!(digit)) >>
                        ()
                    ))) >>
                    opt!(complete!(exponential_part)) >>
                    ()
                ) >>
                ()
            )
            |
            do_parse!(
                tag_s!(".") >>
                complete!(digit) >>
                opt!(complete!(exponential_part)) >>
                ()
            )
        )) >>
        (dec_lit.parse::<f64>().unwrap())
    ));

    named!(decimal_integer_literal<&str, &str>, recognize!(alt!(
        do_parse!(
            tag_s!("0") >>
            not!(digit) >>
            not!(tag_s!("x")) >>
            not!(tag_s!("X")) >>
            ()
        )
        |
        do_parse!(
            not!(tag_s!("0")) >>
            digit >>
            ()
        )
    )));

    named!(exponential_part<&str, &str>, recognize!(do_parse!(
        alt!(tag_s!("e") | tag_s!("E")) >>
        opt!(alt!(tag_s!("+") | tag_s!("-"))) >>
        digit >>
        ()
    )));

    named!(hex_integer_literal<&str, f64>, do_parse!(
        alt!(tag_s!("0x") | tag_s!("0X")) >>
        hex: hex_digit >>
        (i64::from_str_radix(hex, 16).unwrap() as f64)
    ));

    named!(octal_integer_literal<&str, f64>, do_parse!(
        tag_s!("0") >>
        octal: oct_digit >>
        (i64::from_str_radix(octal, 8).unwrap() as f64)
    ));

    named!(pub string_literal<&str, StringLiteral>, do_parse!(
        delimiter: alt!(
            keyword!("\"")
            |
            keyword!("'")
        ) >>
        string: take_until_s!(delimiter) >> // TODO: escape chars
        keyword!(delimiter) >>
        (StringLiteral(string))
    ));

    named!(pub identifier<&str, &str>, do_parse!(
        take_while_s!(is_whitespace) >>
        identifier: recognize!(do_parse!(
            xid_start >>
            many0!(complete!(xid_continue)) >>
            ()
        )) >>
        (identifier)
    ));

    named!(pub js_identifier<&str, &str>, alt!(
        keyword!("property")
        |
        keyword!("signal")
        |
        keyword!("readonly")
        |
        keyword!("on")
        |
        keyword!("get")
        |
        keyword!("set")
        |
        identifier
    ));

    named!(pub reserved_identifier<&str, &str>, alt!(
        keyword!("break")
        |
        keyword!("case")
        |
        keyword!("catch")
        |
        keyword!("continue")
        |
        keyword!("default")
        |
        keyword!("delete")
        |
        keyword!("do")
        |
        keyword!("else")
        |
        keyword!("false")
        |
        keyword!("finally")
        |
        keyword!("for")
        |
        keyword!("function")
        |
        keyword!("if")
        |
        keyword!("in")
        |
        keyword!("instanceof")
        |
        keyword!("new")
        |
        keyword!("null")
        |
        keyword!("return")
        |
        keyword!("switch")
        |
        keyword!("this")
        |
        keyword!("throw")
        |
        keyword!("true")
        |
        keyword!("try")
        |
        keyword!("typeof")
        |
        keyword!("var")
        |
        keyword!("void")
        |
        keyword!("while")
        |
        keyword!("const")
        |
        keyword!("debugger")
        |
        keyword!("with")
    ));

    named!(pub property_identifier<&str, &str>, alt!(
        reserved_identifier
        |
        js_identifier
    ));

    named!(pub assignment_operator<&str, &str>, alt!(
        keyword!("=")
        |
        keyword!("*=")
        |
        keyword!("/=")
        |
        keyword!("%=")
        |
        keyword!("+=")
        |
        keyword!("-=")
        |
        keyword!("<<=")
        |
        keyword!(">>>=")
        |
        keyword!(">>=")
        |
        keyword!("&=")
        |
        keyword!("^=")
        |
        keyword!("|=")
    ));

    named!(pub automatic_semicolon<&str, &str>, alt!(
        eof
        |
        keyword!(";")
        |
        peek!(line_terminator)
        |
        peek!(keyword!("}"))
    ));

    named!(eof<&str, &str>, do_parse!(
        take_while_s!(is_whitespace) >>
        eof: eof!() >>
        (eof)
    ));

    named!(pub line_terminator<&str, &str>, alt!(
        tag_s!("\r\n")
        |
        tag_s!("\n")
        |
        tag_s!("\u{2028}")
        |
        tag_s!("\u{2029}")
    ));

    #[cfg(test)]
    mod tests {
        use nom::{ErrorKind, IResult};
        use super::*;

        #[test]
        fn numeric_literal() {
            assert!(super::numeric_literal("").is_incomplete());

            // Decimal
            assert_eq!(super::numeric_literal("42"), IResult::Done("", NumericLiteral(42_f64)));
            assert_eq!(super::numeric_literal(" 42 "), IResult::Done(" ", NumericLiteral(42_f64)));
            assert_eq!(super::numeric_literal("0"), IResult::Done("", NumericLiteral(0_f64)));
            assert_eq!(super::numeric_literal("42.42e-4"), IResult::Done("", NumericLiteral(42.42e-4_f64)));
            assert_eq!(super::numeric_literal(".42"), IResult::Done("", NumericLiteral(0.42_f64)));
            assert_eq!(super::numeric_literal("42."), IResult::Done("", NumericLiteral(42_f64)));

            assert_eq!(super::numeric_literal("+42"), IResult::Error(ErrorKind::Alt)); // Identity is unary expression
            assert_eq!(super::numeric_literal("-42"), IResult::Error(ErrorKind::Alt)); // Negation is unary expression
            assert_eq!(super::numeric_literal("."), IResult::Error(ErrorKind::Alt));

            // Octal
            assert_eq!(super::numeric_literal("042"), IResult::Done("", NumericLiteral(34_f64)));

            // Hex
            assert_eq!(super::numeric_literal("0x42"), IResult::Done("", NumericLiteral(66_f64)));
            assert_eq!(super::numeric_literal("0X42"), IResult::Done("", NumericLiteral(66_f64)));
        }

        #[test]
        fn string_literal() {
            assert!(super::string_literal("").is_incomplete());

            assert_eq!(super::string_literal("\"hi\""), IResult::Done("", StringLiteral("hi")));
            assert_eq!(super::string_literal(" 'hi' "), IResult::Done(" ", StringLiteral("hi")));

            assert_eq!(super::string_literal("\"hi"), IResult::Error(ErrorKind::TakeUntil)); // FIXME: https://github.com/Geal/nom/issues/397
            assert_eq!(super::string_literal("'hi"), IResult::Error(ErrorKind::TakeUntil));
        }

        #[test]
        fn identifier() {
            assert!(super::identifier("").is_incomplete());

            assert_eq!(super::identifier("foo"), IResult::Done("", "foo"));
            assert_eq!(super::identifier(" foo"), IResult::Done("", "foo"));
            assert_eq!(super::identifier("foo bar"), IResult::Done(" bar", "foo"));

            assert_eq!(super::identifier("42foo"), IResult::Error(ErrorKind::Verify));
        }
    }
}<|endoftext|>


<commit_before>//! PortAudio backend!

use buffer::DspBuffer;
use portaudio::{ types, pa };
use portaudio::error::Error;
use sound_stream::SoundStream;
use sound_stream_settings::SoundStreamSettings;

/// PortAudio Stream Parameters (required to setup stream).
pub struct StreamParamsPA {
    input: types::PaStreamParameters,
    output: types::PaStreamParameters,
}

/// PortAudio Stream (for reading from and writing to real-time audio stream).
pub struct StreamPA {
    stream: pa::PaStream<f32>,
    pub is_streaming: bool
}

fn get_result_text(res: Result<(), Error>) -> String {
    let err = match res {
        Ok(()) => Error::NoError,
        Err(e) => e,
    };
    pa::get_error_text(err)
}

/// The parameters required to set up the PortAudio stream.
impl StreamParamsPA {

    /// Creates the port audio stream parameters.
    pub fn new(channels: u16) -> StreamParamsPA {
        let res = pa::initialize();
        println!("Portaudio init error : {}", get_result_text(res));

        println!("Creating StreamParamsPA");
        let def_input = pa::device::get_default_input();
        let def_output = pa::device::get_default_output();

        println!("Creating input");
        let stream_params_in = types::PaStreamParameters {
            device: def_input,
            channel_count: channels as i32,
            sample_format: types::PaFloat32,
            suggested_latency: pa::device::get_info(def_input).unwrap().default_low_input_latency
        };
        println!("Creating output");
        let stream_params_out = types::PaStreamParameters {
            device: def_output,
            channel_count: channels as i32,
            sample_format: types::PaFloat32,
            suggested_latency: pa::device::get_info(def_output).unwrap().default_low_output_latency
        };

        StreamParamsPA {
            input: stream_params_in,
            output: stream_params_out
        }
    }

}

impl StreamPA {

    /// Constructor for the portaudio stream.
    pub fn new() -> StreamPA {
        StreamPA {
            stream: pa::PaStream::new(types::PaFloat32),
            is_streaming: true
        }
    }

    /// Setup the portaudio stream.
    pub fn setup(&mut self, settings: SoundStreamSettings) {
        let params = StreamParamsPA::new(settings.channels);
        self.stream.open(Some(&params.input),
                         Some(&params.output),
                         settings.samples_per_sec as f64,
                         settings.frames as u32,
                         types::PaClipOff);
    }

    /// Performs the audio read/write.
    pub fn callback<B: DspBuffer, T: SoundStream<B>>
    (&mut self, settings: SoundStreamSettings, stream: &mut T) {
        let mut ready = 0;
        while ready == 0 {
            ready = self.stream.get_stream_write_available();
        }
        //let empty_buffer = Vec::from_elem(settings.buffer_size(), 0f32);
        //let mut read: Vec<f32> = empty_buffer.clone();
        self.read(settings, stream);
        let mut write: B = DspBuffer::zeroed();
        self.write(&mut write, settings, stream);
    }

    /// Read audio in from stream.
    pub fn read<B: DspBuffer, T: SoundStream<B>>
    (&self, settings: SoundStreamSettings, stream: &mut T) {
        match self.stream.read(settings.frames as u32) {
            Ok(in_buffer) => {
                stream.audio_in(&in_buffer, settings);
            },
            Err(err) => {
                panic!(format!("Portaudio error read : {}", pa::get_error_text(err)));
            }
        }
    }

    /// Write audio to stream
    pub fn write<B: DspBuffer, T: SoundStream<B>>
    (&mut self, buffer: &mut B, settings: SoundStreamSettings, stream: &mut T) {
        stream.audio_out(buffer, settings);
        /*
        println!("OUT OF AUDIO_OUT, {}", buffer.len());
        let mut write = Vec::with_capacity(buffer.len());
        println!("OUT OF AUDIO_OUTx, {}", write.capacity());
        for i in range(0u, buffer.len()) {
            println!("z");
            write.push(buffer.val(i));
        }
        */

        //let write: Vec<f32> = buffer.iter().map(|f| { println!("z"); *f }).collect();
        self.stream.write(buffer.to_vec(), settings.frames as u32);
    }

    /// Start the audio stream.
    pub fn start(&mut self) {
        let res = self.stream.start();
        println!("Portaudio Start Stream : {}", get_result_text(res));
    }

    /// Stop the audio stream.
    pub fn stop(&mut self) {
        let mut err = Error::NotInitialized;
        println!("Portaudio [NotInitialized msg] : {}", pa::get_error_text(err));
        let res = self.stream.close();
        println!("Portaudio Closing Stream : {}", get_result_text(res));
        let res = pa::terminate();
        println!("Portaudio Termination Message : {}", get_result_text(res));
    }

}

/// Ensure that the stream closes properly upon object destruction.
impl Drop for StreamPA {
    fn drop(&mut self) {
        if self.is_streaming {
            self.stop();
        }
    }
}

<commit_msg>update to last rust-portaudio api + fix warning for unused results<commit_after>//! PortAudio backend!

use buffer::DspBuffer;
use portaudio::pa::;
use portaudio::pa::error::Error;
use sound_stream::SoundStream;
use sound_stream_settings::SoundStreamSettings;

/// PortAudio Stream Parameters (required to setup stream).
pub struct StreamParamsPA {
    input: pa::StreamParameters,
    output: pa::StreamParameters,
}

/// PortAudio Stream (for reading from and writing to real-time audio stream).
pub struct StreamPA {
    stream: pa::Stream<f32, f32>,
    pub is_streaming: bool
}

fn get_result_text(res: Result<(), Error>) -> String {
    let err = match res {
        Ok(()) => Error::NoError,
        Err(e) => e,
    };
    pa::get_error_text(err)
}

/// The parameters required to set up the PortAudio stream.
impl StreamParamsPA {

    /// Creates the port audio stream parameters.
    pub fn new(channels: u16) -> StreamParamsPA {
        let res = pa::initialize();
        println!("Portaudio init error : {}", get_result_text(res));

        println!("Creating StreamParamsPA");
        let def_input = pa::device::get_default_input();
        let def_output = pa::device::get_default_output();

        println!("Creating input");
        let stream_params_in = pa::StreamParameters {
            device: def_input,
            channel_count: channels as i32,
            sample_format: pa::SampleFormat::Float32,
            suggested_latency: pa::device::get_info(def_input).unwrap().default_low_input_latency
        };
        println!("Creating output");
        let stream_params_out = pa::StreamParameters {
            device: def_output,
            channel_count: channels as i32,
            sample_format: pa::SampleFormat::Float32,
            suggested_latency: pa::device::get_info(def_output).unwrap().default_low_output_latency
        };

        StreamParamsPA {
            input: stream_params_in,
            output: stream_params_out
        }
    }

}

impl StreamPA {

    /// Constructor for the portaudio stream.
    pub fn new() -> StreamPA {
        StreamPA {
            stream: pa::Stream::new(),
            is_streaming: true
        }
    }

    /// Setup the portaudio stream.
    pub fn setup(&mut self, settings: SoundStreamSettings) {
        let params = StreamParamsPA::new(settings.channels);
        match self.stream.open(Some(&params.input),
                         Some(&params.output),
                         settings.samples_per_sec as f64,
                         settings.frames as u32,
                         pa::StreamFlags::ClipOff) {
            Ok(_) => {},
            Err(e) => panic!(format!("Portaudio etup error: {}", get_result_text(Err(e))))
        };
    }

    /// Performs the audio read/write.
    pub fn callback<B: DspBuffer, T: SoundStream<B>>
    (&mut self, settings: SoundStreamSettings, stream: &mut T) {
        let mut ready = 0;
        while ready == 0 {
            ready = self.stream.get_stream_write_available();
        }
        //let empty_buffer = Vec::from_elem(settings.buffer_size(), 0f32);
        //let mut read: Vec<f32> = empty_buffer.clone();
        self.read(settings, stream);
        let mut write: B = DspBuffer::zeroed();
        self.write(&mut write, settings, stream);
    }

    /// Read audio in from stream.
    pub fn read<B: DspBuffer, T: SoundStream<B>>
    (&self, settings: SoundStreamSettings, stream: &mut T) {
        match self.stream.read(settings.frames as u32) {
            Ok(in_buffer) => {
                stream.audio_in(&in_buffer, settings);
            },
            Err(err) => {
                panic!(format!("Portaudio error read : {}", pa::get_error_text(err)));
            }
        }
    }

    /// Write audio to stream
    pub fn write<B: DspBuffer, T: SoundStream<B>>
    (&mut self, buffer: &mut B, settings: SoundStreamSettings, stream: &mut T) {
        stream.audio_out(buffer, settings);
        /*
        println!("OUT OF AUDIO_OUT, {}", buffer.len());
        let mut write = Vec::with_capacity(buffer.len());
        println!("OUT OF AUDIO_OUTx, {}", write.capacity());
        for i in range(0u, buffer.len()) {
            println!("z");
            write.push(buffer.val(i));
        }
        */

        //let write: Vec<f32> = buffer.iter().map(|f| { println!("z"); *f }).collect();
        match self.stream.write(buffer.to_vec(), settings.frames as u32) {
            Ok(_) => {},
            Err(e) => {
                panic!(format!("Portaudio write error : {}", pa::get_error_text(e)));
            }
        }
    }

    /// Start the audio stream.
    pub fn start(&mut self) {
        let res = self.stream.start();
        println!("Portaudio Start Stream : {}", get_result_text(res));
    }

    /// Stop the audio stream.
    pub fn stop(&mut self) {
        let err = Error::NotInitialized;
        println!("Portaudio [NotInitialized msg] : {}", pa::get_error_text(err));
        let res = self.stream.close();
        println!("Portaudio Closing Stream : {}", get_result_text(res));
        let res = pa::terminate();
        println!("Portaudio Termination Message : {}", get_result_text(res));
    }

}

/// Ensure that the stream closes properly upon object destruction.
impl Drop for StreamPA {
    fn drop(&mut self) {
        if self.is_streaming {
            self.stop();
        }
    }
}

<|endoftext|>


<commit_before>// Copyright 2016 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.

// This test case tests the incremental compilation hash (ICH) implementation
// for if expressions.

// The general pattern followed here is: Change one thing between rev1 and rev2
// and make sure that the hash has changed, then change nothing between rev2 and
// rev3 and make sure that the hash has not changed.

// must-compile-successfully
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph

#![allow(warnings)]
#![feature(rustc_attrs)]
#![crate_type="rlib"]

// Change condition (if) -------------------------------------------------------
#[cfg(cfail1)]
pub fn change_condition(x: bool) -> u32 {
    if x {
        return 1
    }

    return 0
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn change_condition(x: bool) -> u32 {
    if !x {
        return 1
    }

    return 0
}

// Change then branch (if) -----------------------------------------------------
#[cfg(cfail1)]
pub fn change_then_branch(x: bool) -> u32 {
    if x {
        return 1
    }

    return 0
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")]
#[rustc_clean(cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn change_then_branch(x: bool) -> u32 {
    if x {
        return 2
    }

    return 0
}

// Change else branch (if) -----------------------------------------------------
#[cfg(cfail1)]
pub fn change_else_branch(x: bool) -> u32 {
    if x {
        1
    } else {
        2
    }
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")]
#[rustc_clean(cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn change_else_branch(x: bool) -> u32 {
    if x {
        1
    } else {
        3
    }
}

// Add else branch (if) --------------------------------------------------------
#[cfg(cfail1)]
pub fn add_else_branch(x: bool) -> u32 {
    let mut ret = 1;

    if x {
        ret += 1;
    }

    ret
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="HirBody,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn add_else_branch(x: bool) -> u32 {
    let mut ret = 1;

    if x {
        ret += 1;
    } else {
    }

    ret
}

// Change condition (if let) ---------------------------------------------------
#[cfg(cfail1)]
pub fn change_condition_if_let(x: Option<u32>) -> u32 {
    if let Some(_x) = x {
        return 1
    }

    0
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn change_condition_if_let(x: Option<u32>) -> u32 {
    if let Some(_) = x {
        return 1
    }

    0
}

// Change then branch (if let) -------------------------------------------------
#[cfg(cfail1)]
pub fn change_then_branch_if_let(x: Option<u32>) -> u32 {
    if let Some(x) = x {
        return x
    }

    0
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn change_then_branch_if_let(x: Option<u32>) -> u32 {
    if let Some(x) = x {
        return x + 1
    }

    0
}

// Change else branch (if let) -------------------------------------------------
#[cfg(cfail1)]
pub fn change_else_branch_if_let(x: Option<u32>) -> u32 {
    if let Some(x) = x {
        x
    } else {
        1
    }
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")]
#[rustc_clean(cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn change_else_branch_if_let(x: Option<u32>) -> u32 {
    if let Some(x) = x {
        x
    } else {
        2
    }
}

// Add else branch (if let) ----------------------------------------------------
#[cfg(cfail1)]
pub fn add_else_branch_if_let(x: Option<u32>) -> u32 {
    let mut ret = 1;

    if let Some(x) = x {
        ret += x;
    }

    ret
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="HirBody,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn add_else_branch_if_let(x: Option<u32>) -> u32 {
    let mut ret = 1;

    if let Some(x) = x {
        ret += x;
    } else {
    }

    ret
}
<commit_msg>Remove checked arithmetic from if expression hash tests<commit_after>// Copyright 2016 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.

// This test case tests the incremental compilation hash (ICH) implementation
// for if expressions.

// The general pattern followed here is: Change one thing between rev1 and rev2
// and make sure that the hash has changed, then change nothing between rev2 and
// rev3 and make sure that the hash has not changed.

// must-compile-successfully
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph

#![allow(warnings)]
#![feature(rustc_attrs)]
#![crate_type="rlib"]

// Change condition (if) -------------------------------------------------------
#[cfg(cfail1)]
pub fn change_condition(x: bool) -> u32 {
    if x {
        return 1
    }

    return 0
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn change_condition(x: bool) -> u32 {
    if !x {
        return 1
    }

    return 0
}

// Change then branch (if) -----------------------------------------------------
#[cfg(cfail1)]
pub fn change_then_branch(x: bool) -> u32 {
    if x {
        return 1
    }

    return 0
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")]
#[rustc_clean(cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn change_then_branch(x: bool) -> u32 {
    if x {
        return 2
    }

    return 0
}

// Change else branch (if) -----------------------------------------------------
#[cfg(cfail1)]
pub fn change_else_branch(x: bool) -> u32 {
    if x {
        1
    } else {
        2
    }
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")]
#[rustc_clean(cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn change_else_branch(x: bool) -> u32 {
    if x {
        1
    } else {
        3
    }
}

// Add else branch (if) --------------------------------------------------------
#[cfg(cfail1)]
pub fn add_else_branch(x: bool) -> u32 {
    let mut ret = 1;

    if x {
        ret = 2;
    }

    ret
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="HirBody,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn add_else_branch(x: bool) -> u32 {
    let mut ret = 1;

    if x {
        ret = 2;
    } else {
    }

    ret
}

// Change condition (if let) ---------------------------------------------------
#[cfg(cfail1)]
pub fn change_condition_if_let(x: Option<u32>) -> u32 {
    if let Some(_x) = x {
        return 1
    }

    0
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn change_condition_if_let(x: Option<u32>) -> u32 {
    if let Some(_) = x {
        return 1
    }

    0
}

// Change then branch (if let) -------------------------------------------------
#[cfg(cfail1)]
pub fn change_then_branch_if_let(x: Option<u32>) -> u32 {
    if let Some(x) = x {
        return x
    }

    0
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn change_then_branch_if_let(x: Option<u32>) -> u32 {
    if let Some(x) = x {
        return x + 1
    }

    0
}

// Change else branch (if let) -------------------------------------------------
#[cfg(cfail1)]
pub fn change_else_branch_if_let(x: Option<u32>) -> u32 {
    if let Some(x) = x {
        x
    } else {
        1
    }
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="HirBody,MirValidated,MirOptimized")]
#[rustc_clean(cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn change_else_branch_if_let(x: Option<u32>) -> u32 {
    if let Some(x) = x {
        x
    } else {
        2
    }
}

// Add else branch (if let) ----------------------------------------------------
#[cfg(cfail1)]
pub fn add_else_branch_if_let(x: Option<u32>) -> u32 {
    let mut ret = 1;

    if let Some(x) = x {
        ret = x;
    }

    ret
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="HirBody,TypeckTables")]
#[rustc_clean(cfg="cfail3")]
#[rustc_metadata_clean(cfg="cfail2")]
#[rustc_metadata_clean(cfg="cfail3")]
pub fn add_else_branch_if_let(x: Option<u32>) -> u32 {
    let mut ret = 1;

    if let Some(x) = x {
        ret = x;
    } else {
    }

    ret
}
<|endoftext|>