<commit_before>// Copyright 2013-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>

use std::borrow::Borrow;
use std::fmt;
use std::marker::PhantomData;
use std::mem;

use object::{Downcast, IsA, Object};
use translate::*;
use types::StaticType;

use glib_ffi;
use gobject_ffi;

/// A generic value capable of carrying various types.
///
/// Once created the type of the value can't be changed.
///
/// Some types (e.g. `String` and objects) support `None` values while others
/// (e.g. numeric types) don't.
pub struct Value(Box<gobject_ffi::GValue>);

impl Value {
    /// Tries to return a typed borrow of the value.
    ///
    /// Returns `Some(TypedValue<T>)` if the value carries a type corresponding
    /// to `T` and `None` otherwise.
    pub fn typed<T: FromValueOptional>(&self) -> Option<TypedValue<T>> {
        unsafe {
            let ok = gobject_ffi::g_type_check_value_holds(mut_override(self.to_glib_none().0),
                T::static_type().to_glib());
            some_if(ok, || TypedValue(self, PhantomData))
        }
    }

    /// Tries to return a typed mutable borrow of the value.
    ///
    /// Returns `Some(TypedValueMut<T>)` if the value carries a type
    /// corresponding to `T` and `None` otherwise.
    pub fn typed_mut<T: FromValueOptional + SetValue>(&mut self) -> Option<TypedValueMut<T>> {
        unsafe {
            let ok = gobject_ffi::g_type_check_value_holds(self.to_glib_none_mut().0,
                T::static_type().to_glib());
            some_if(ok, move || TypedValueMut(self, PhantomData))
        }
    }

    /// Tries to get a value of type `T`.
    ///
    /// Returns `Some` if the type is correct and the value is not `None`.
    ///
    /// This function doesn't distinguish between type mismatches and correctly
    /// typed `None` values. Use `typed` and `typed_mut` for that.
    pub fn get<T: FromValueOptional>(&self) -> Option<T> {
        self.typed::<T>().and_then(|v| v.get())
    }
}

impl Clone for Value {
    fn clone(&self) -> Self {
        unsafe {
            // FIXME: make this safer by making GValue::g_type public
            let type_ = *(&*self.0 as *const gobject_ffi::GValue as *const glib_ffi::GType);
            let mut ret = Value(Box::new(mem::zeroed()));
            gobject_ffi::g_value_init(ret.to_glib_none_mut().0, type_);
            gobject_ffi::g_value_copy(self.to_glib_none().0, ret.to_glib_none_mut().0);
            ret
        }
    }
}

impl Drop for Value {
    fn drop(&mut self) {
        unsafe { gobject_ffi::g_value_unset(self.to_glib_none_mut().0) }
    }
}

impl fmt::Debug for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        unsafe {
            let s: String = from_glib_full(
                gobject_ffi::g_strdup_value_contents(self.to_glib_none().0));
            write!(f, "{}", s)
        }
    }
}

impl<T: SetValueOptional> From<Option<T>> for Value {
    fn from(value: Option<T>) -> Value {
        unsafe {
            let mut ret = Value::uninitialized();
            gobject_ffi::g_value_init(ret.to_glib_none_mut().0, T::static_type().to_glib());
            T::set_value_optional(&mut ret, value);
            ret
        }
    }
}

impl<T: SetValue> From<T> for Value {
    fn from(value: T) -> Value {
        unsafe {
            let mut ret = Value::uninitialized();
            gobject_ffi::g_value_init(ret.to_glib_none_mut().0, T::static_type().to_glib());
            T::set_value(&mut ret, value);
            ret
        }
    }
}

impl Uninitialized for Value {
    unsafe fn uninitialized() -> Value {
        Value(Box::new(mem::zeroed()))
    }
}

impl<'a> ToGlibPtr<'a, *const gobject_ffi::GValue> for Value {
    type Storage = &'a Value;

    fn to_glib_none(&'a self) -> Stash<'a, *const gobject_ffi::GValue, Self> {
        Stash(&*self.0, self)
    }
}

impl<'a> ToGlibPtrMut<'a, *mut gobject_ffi::GValue> for Value {
    type Storage = &'a mut Value;

    fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut gobject_ffi::GValue, Self> {
        StashMut(&mut *self.0, self)
    }
}

/// A typed borrow of a `Value`.
pub struct TypedValue<'a, T>(&'a Value, PhantomData<*const T>);

impl<'a, T: FromValueOptional> TypedValue<'a, T> {
    /// Returns the value.
    ///
    /// Types that don't support a `None` value always return `Some`. See
    /// `get_some`.
    pub fn get(&self) -> Option<T> {
        unsafe { T::from_value_optional(self.0) }
    }

    /// Returns the value.
    ///
    /// This method is only available for types that don't support a `None`
    /// value.
    pub fn get_some(&self) -> T where T: FromValue {
        unsafe { T::from_value(self.0) }
    }
}

pub struct TypedValueMut<'a, T>(&'a mut Value, PhantomData<*const T>);

impl<'a, T: FromValueOptional + SetValue> TypedValueMut<'a, T> {
    /// Returns the value.
    ///
    /// Types that don't support a `None` value always return `Some`. See
    /// `get_some`.
    pub fn get(&self) -> Option<T> {
        unsafe { T::from_value_optional(self.0) }
    }

    /// Returns the value.
    ///
    /// This method is only available for types that don't support a `None`
    /// value.
    pub fn get_some(&self) -> T where T: FromValue {
        unsafe { T::from_value(self.0) }
    }

    /// Sets the value.
    ///
    /// This method is only available for types that support a `None` value.
    pub fn set<'x, U: ?Sized>(&mut self, value: Option<&'x U>)
    where T: Borrow<U>, &'x U: SetValueOptional {
        unsafe { SetValueOptional::set_value_optional(self.0, value) }
    }

    /// Sets the value to `None`.
    ///
    /// This method is only available for types that support a `None` value.
    pub fn set_none(&mut self) where T: SetValueOptional {
        unsafe { T::set_value_optional(self.0, None) }
    }

    /// Sets the value.
    pub fn set_some<'x, U: ?Sized>(&mut self, value: &'x U)
    where T: Borrow<U>, &'x U: SetValue {
        unsafe { SetValue::set_value(self.0, value) }
    }
}

/// Extracts a value.
///
/// Types that don't support a `None` value always return `Some`.
pub trait FromValueOptional: StaticType + Sized {
    unsafe fn from_value_optional(&Value) -> Option<Self>;
}

/// Extracts a value.
///
/// Only implemented for types that don't support a `None` value.
pub trait FromValue: FromValueOptional {
    unsafe fn from_value(&Value) -> Self;
}

/// Sets a value.
///
/// Only implemented for types that support a `None` value.
pub trait SetValueOptional: SetValue {
    unsafe fn set_value_optional(&mut Value, Option<Self>);
}

/// Sets a value.
pub trait SetValue: StaticType + Sized {
    unsafe fn set_value(&mut Value, Self);
}

impl FromValueOptional for String {
    unsafe fn from_value_optional(value: &Value) -> Option<Self> {
        from_glib_none(gobject_ffi::g_value_get_string(value.to_glib_none().0))
    }
}

impl<'a> SetValue for &'a str {
    unsafe fn set_value(value: &mut Value, this: Self) {
        gobject_ffi::g_value_take_string(value.to_glib_none_mut().0, this.to_glib_full())
    }
}

impl<'a> SetValueOptional for &'a str {
    unsafe fn set_value_optional(value: &mut Value, this: Option<Self>) {
        gobject_ffi::g_value_take_string(value.to_glib_none_mut().0, this.to_glib_full())
    }
}

impl SetValue for String {
    unsafe fn set_value(value: &mut Value, this: Self) {
        gobject_ffi::g_value_take_string(value.to_glib_none_mut().0, this.to_glib_full())
    }
}

impl SetValueOptional for String {
    unsafe fn set_value_optional(value: &mut Value, this: Option<Self>) {
        gobject_ffi::g_value_take_string(value.to_glib_none_mut().0, this.to_glib_full())
    }
}

impl<T: IsA<Object>> FromValueOptional for T {
    unsafe fn from_value_optional(value: &Value) -> Option<Self> {
        Option::<Object>::from_glib_full(gobject_ffi::g_value_dup_object(value.to_glib_none().0))
            .map(|o| o.downcast_unchecked())
    }
}

impl<T: IsA<Object>> SetValue for T {
    unsafe fn set_value(value: &mut Value, this: Self) {
        gobject_ffi::g_value_set_object(value.to_glib_none_mut().0, this.to_glib_none().0)
    }
}

impl<T: IsA<Object>> SetValueOptional for T {
    unsafe fn set_value_optional(value: &mut Value, this: Option<Self>) {
        gobject_ffi::g_value_set_object(value.to_glib_none_mut().0, this.to_glib_none().0)
    }
}

impl<'a, T: IsA<Object>> SetValue for &'a T {
    unsafe fn set_value(value: &mut Value, this: Self) {
        gobject_ffi::g_value_set_object(value.to_glib_none_mut().0, this.to_glib_none().0)
    }
}

impl<'a, T: IsA<Object>> SetValueOptional for &'a T {
    unsafe fn set_value_optional(value: &mut Value, this: Option<Self>) {
        gobject_ffi::g_value_set_object(value.to_glib_none_mut().0, this.to_glib_none().0)
    }
}

impl FromValueOptional for bool {
    unsafe fn from_value_optional(value: &Value) -> Option<Self> {
        Some(from_glib(gobject_ffi::g_value_get_boolean(value.to_glib_none().0)))
    }
}

impl FromValue for bool {
    unsafe fn from_value(value: &Value) -> Self {
        from_glib(gobject_ffi::g_value_get_boolean(value.to_glib_none().0))
    }
}

impl SetValue for bool {
    unsafe fn set_value(value: &mut Value, this: Self) {
        gobject_ffi::g_value_set_boolean(value.to_glib_none_mut().0, this.to_glib())
    }
}

macro_rules! numeric {
    ($name:ident, $get:ident, $set:ident) => {
        impl FromValueOptional for $name {
            unsafe fn from_value_optional(value: &Value) -> Option<Self> {
                Some(gobject_ffi::$get(value.to_glib_none().0))
            }
        }

        impl FromValue for $name {
            unsafe fn from_value(value: &Value) -> Self {
                gobject_ffi::$get(value.to_glib_none().0)
            }
        }

        impl SetValue for $name {
            unsafe fn set_value(value: &mut Value, this: Self) {
                gobject_ffi::$set(value.to_glib_none_mut().0, this)
            }
        }

        impl<'a> SetValue for &'a $name {
            unsafe fn set_value(value: &mut Value, this: Self) {
                gobject_ffi::$set(value.to_glib_none_mut().0, *this)
            }
        }
    }
}

numeric!(i8, g_value_get_schar, g_value_set_schar);
numeric!(u8, g_value_get_uchar, g_value_set_uchar);
numeric!(i32, g_value_get_int, g_value_set_int);
numeric!(u32, g_value_get_uint, g_value_set_uint);
numeric!(i64, g_value_get_int64, g_value_set_int64);
numeric!(u64, g_value_get_uint64, g_value_set_uint64);
numeric!(f32, g_value_get_float, g_value_set_float);
numeric!(f64, g_value_get_double, g_value_set_double);
<commit_msg>Document `Value`<commit_after>// Copyright 2013-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>

//! `Value` bindings and helper traits.
//!
//! The type of a [`Value`](struct.Value.html) is dynamic in that it generally
//! isn't known at compile time but once created a `Value` can't change its
//! type.
//!
//! Supported types are `bool`, `i8`, `u8`, `i32`, `u32`, `i64`, `u64`, `f32`,
//! `f64`, `String` and objects (`T: IsA<Object>`).
//!
//! # Examples
//!
//! ```
//! use glib::Value;
//!
//! // Value implements From<i32>, From<&str> and From<Option<&str>>.
//! let mut num = Value::from(10);
//! let mut hello = Value::from("Hello!");
//! let none: Option<&str> = None;
//! let none = Value::from(none);
//!
//! // 'get' tries to get a value of specific type and returns None
//! // if the type doesn't match or the value is None.
//! assert_eq!(num.get(), Some(10));
//! assert_eq!(num.get::<String>(), None);
//! assert_eq!(hello.get(), Some(String::from("Hello!")));
//! assert_eq!(hello.get::<String>(), Some(String::from("Hello!")));
//! assert_eq!(none.get::<String>(), None);
//!
//! // `typed` returns a `TypedValue` with some getters.
//! if let Some(val) = hello.typed::<String>() {
//!     assert!(val.get().unwrap() == "Hello!");
//! } else {
//!     panic!("Not a string");
//! }
//! if let Some(val) = none.typed::<String>() {
//!     assert!(val.get() == None);
//! } else {
//!     panic!("Not a string");
//! }
//!
//! // Numeric types can't have value `None`, `get` always returns `Some`.
//! // Such types have `get_some`, which avoids unnecessary `unwrap`ping.
//! if let Some(val) = num.typed::<i32>() {
//!     assert_eq!(val.get().unwrap(), 10);
//!     assert_eq!(val.get_some(), 10);
//! } else {
//!     panic!("Not an i32");
//! }
//!
//! // `num` is not a string.
//! if num.typed::<String>().is_some() {
//!     panic!("Unexpected string");
//! }
//!
//! // `typed_mut` returns a `TypedValueMut`, which also has setters
//! // `set_none` sets the value to `None` if the type supports it.
//! if let Some(mut val) = hello.typed_mut::<String>() {
//!     val.set_none();
//! }
//!
//! // `set` takes an optional reference for types that support `None`.
//! assert!(hello.typed::<String>().unwrap().get().is_none());
//! if let Some(mut val) = hello.typed_mut::<String>() {
//!     val.set(Some("Hello again!"));
//! }
//! assert!(hello.get::<String>().unwrap() == "Hello again!");
//!
//! // `set_some` is the only setter for types that don't support `None`.
//! assert!(hello.get::<String>().unwrap() == "Hello again!");
//! if let Some(mut val) = num.typed_mut::<i32>() {
//!     val.set_some(&20);
//! }
//! assert_eq!(num.get(), Some(20));
//! ```

use std::borrow::Borrow;
use std::fmt;
use std::marker::PhantomData;
use std::mem;

use object::{Downcast, IsA, Object};
use translate::*;
use types::StaticType;

use glib_ffi;
use gobject_ffi;

/// A generic value capable of carrying various types.
///
/// Once created the type of the value can't be changed.
///
/// Some types (e.g. `String` and objects) support `None` values while others
/// (e.g. numeric types) don't.
pub struct Value(Box<gobject_ffi::GValue>);

impl Value {
    /// Tries to return a typed borrow of the value.
    ///
    /// Returns `Some(TypedValue<T>)` if the value carries a type corresponding
    /// to `T` and `None` otherwise.
    pub fn typed<T: FromValueOptional>(&self) -> Option<TypedValue<T>> {
        unsafe {
            let ok = gobject_ffi::g_type_check_value_holds(mut_override(self.to_glib_none().0),
                T::static_type().to_glib());
            some_if(ok, || TypedValue(self, PhantomData))
        }
    }

    /// Tries to return a typed mutable borrow of the value.
    ///
    /// Returns `Some(TypedValueMut<T>)` if the value carries a type
    /// corresponding to `T` and `None` otherwise.
    pub fn typed_mut<T: FromValueOptional + SetValue>(&mut self) -> Option<TypedValueMut<T>> {
        unsafe {
            let ok = gobject_ffi::g_type_check_value_holds(self.to_glib_none_mut().0,
                T::static_type().to_glib());
            some_if(ok, move || TypedValueMut(self, PhantomData))
        }
    }

    /// Tries to get a value of type `T`.
    ///
    /// Returns `Some` if the type is correct and the value is not `None`.
    ///
    /// This function doesn't distinguish between type mismatches and correctly
    /// typed `None` values. Use `typed` and `typed_mut` for that.
    pub fn get<T: FromValueOptional>(&self) -> Option<T> {
        self.typed::<T>().and_then(|v| v.get())
    }
}

impl Clone for Value {
    fn clone(&self) -> Self {
        unsafe {
            // FIXME: make this safer by making GValue::g_type public
            let type_ = *(&*self.0 as *const gobject_ffi::GValue as *const glib_ffi::GType);
            let mut ret = Value(Box::new(mem::zeroed()));
            gobject_ffi::g_value_init(ret.to_glib_none_mut().0, type_);
            gobject_ffi::g_value_copy(self.to_glib_none().0, ret.to_glib_none_mut().0);
            ret
        }
    }
}

impl Drop for Value {
    fn drop(&mut self) {
        unsafe { gobject_ffi::g_value_unset(self.to_glib_none_mut().0) }
    }
}

impl fmt::Debug for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        unsafe {
            let s: String = from_glib_full(
                gobject_ffi::g_strdup_value_contents(self.to_glib_none().0));
            write!(f, "{}", s)
        }
    }
}

impl<T: SetValueOptional> From<Option<T>> for Value {
    fn from(value: Option<T>) -> Value {
        unsafe {
            let mut ret = Value::uninitialized();
            gobject_ffi::g_value_init(ret.to_glib_none_mut().0, T::static_type().to_glib());
            T::set_value_optional(&mut ret, value);
            ret
        }
    }
}

impl<T: SetValue> From<T> for Value {
    fn from(value: T) -> Value {
        unsafe {
            let mut ret = Value::uninitialized();
            gobject_ffi::g_value_init(ret.to_glib_none_mut().0, T::static_type().to_glib());
            T::set_value(&mut ret, value);
            ret
        }
    }
}

impl Uninitialized for Value {
    unsafe fn uninitialized() -> Value {
        Value(Box::new(mem::zeroed()))
    }
}

impl<'a> ToGlibPtr<'a, *const gobject_ffi::GValue> for Value {
    type Storage = &'a Value;

    fn to_glib_none(&'a self) -> Stash<'a, *const gobject_ffi::GValue, Self> {
        Stash(&*self.0, self)
    }
}

impl<'a> ToGlibPtrMut<'a, *mut gobject_ffi::GValue> for Value {
    type Storage = &'a mut Value;

    fn to_glib_none_mut(&'a mut self) -> StashMut<'a, *mut gobject_ffi::GValue, Self> {
        StashMut(&mut *self.0, self)
    }
}

/// A typed borrow of a `Value`.
pub struct TypedValue<'a, T>(&'a Value, PhantomData<*const T>);

impl<'a, T: FromValueOptional> TypedValue<'a, T> {
    /// Returns the value.
    ///
    /// Types that don't support a `None` value always return `Some`. See
    /// `get_some`.
    pub fn get(&self) -> Option<T> {
        unsafe { T::from_value_optional(self.0) }
    }

    /// Returns the value.
    ///
    /// This method is only available for types that don't support a `None`
    /// value.
    pub fn get_some(&self) -> T where T: FromValue {
        unsafe { T::from_value(self.0) }
    }
}

/// A typed mutable borrow of a `Value`.
pub struct TypedValueMut<'a, T>(&'a mut Value, PhantomData<*const T>);

impl<'a, T: FromValueOptional + SetValue> TypedValueMut<'a, T> {
    /// Returns the value.
    ///
    /// Types that don't support a `None` value always return `Some`. See
    /// `get_some`.
    pub fn get(&self) -> Option<T> {
        unsafe { T::from_value_optional(self.0) }
    }

    /// Returns the value.
    ///
    /// This method is only available for types that don't support a `None`
    /// value.
    pub fn get_some(&self) -> T where T: FromValue {
        unsafe { T::from_value(self.0) }
    }

    /// Sets the value.
    ///
    /// This method is only available for types that support a `None` value.
    pub fn set<'x, U: ?Sized>(&mut self, value: Option<&'x U>)
    where T: Borrow<U>, &'x U: SetValueOptional {
        unsafe { SetValueOptional::set_value_optional(self.0, value) }
    }

    /// Sets the value to `None`.
    ///
    /// This method is only available for types that support a `None` value.
    pub fn set_none(&mut self) where T: SetValueOptional {
        unsafe { T::set_value_optional(self.0, None) }
    }

    /// Sets the value.
    pub fn set_some<'x, U: ?Sized>(&mut self, value: &'x U)
    where T: Borrow<U>, &'x U: SetValue {
        unsafe { SetValue::set_value(self.0, value) }
    }
}

/// Extracts a value.
///
/// Types that don't support a `None` value always return `Some`.
pub trait FromValueOptional: StaticType + Sized {
    unsafe fn from_value_optional(&Value) -> Option<Self>;
}

/// Extracts a value.
///
/// Only implemented for types that don't support a `None` value.
pub trait FromValue: FromValueOptional {
    unsafe fn from_value(&Value) -> Self;
}

/// Sets a value.
///
/// Only implemented for types that support a `None` value.
pub trait SetValueOptional: SetValue {
    unsafe fn set_value_optional(&mut Value, Option<Self>);
}

/// Sets a value.
pub trait SetValue: StaticType + Sized {
    unsafe fn set_value(&mut Value, Self);
}

impl FromValueOptional for String {
    unsafe fn from_value_optional(value: &Value) -> Option<Self> {
        from_glib_none(gobject_ffi::g_value_get_string(value.to_glib_none().0))
    }
}

impl<'a> SetValue for &'a str {
    unsafe fn set_value(value: &mut Value, this: Self) {
        gobject_ffi::g_value_take_string(value.to_glib_none_mut().0, this.to_glib_full())
    }
}

impl<'a> SetValueOptional for &'a str {
    unsafe fn set_value_optional(value: &mut Value, this: Option<Self>) {
        gobject_ffi::g_value_take_string(value.to_glib_none_mut().0, this.to_glib_full())
    }
}

impl SetValue for String {
    unsafe fn set_value(value: &mut Value, this: Self) {
        gobject_ffi::g_value_take_string(value.to_glib_none_mut().0, this.to_glib_full())
    }
}

impl SetValueOptional for String {
    unsafe fn set_value_optional(value: &mut Value, this: Option<Self>) {
        gobject_ffi::g_value_take_string(value.to_glib_none_mut().0, this.to_glib_full())
    }
}

impl<T: IsA<Object>> FromValueOptional for T {
    unsafe fn from_value_optional(value: &Value) -> Option<Self> {
        Option::<Object>::from_glib_full(gobject_ffi::g_value_dup_object(value.to_glib_none().0))
            .map(|o| o.downcast_unchecked())
    }
}

impl<T: IsA<Object>> SetValue for T {
    unsafe fn set_value(value: &mut Value, this: Self) {
        gobject_ffi::g_value_set_object(value.to_glib_none_mut().0, this.to_glib_none().0)
    }
}

impl<T: IsA<Object>> SetValueOptional for T {
    unsafe fn set_value_optional(value: &mut Value, this: Option<Self>) {
        gobject_ffi::g_value_set_object(value.to_glib_none_mut().0, this.to_glib_none().0)
    }
}

impl<'a, T: IsA<Object>> SetValue for &'a T {
    unsafe fn set_value(value: &mut Value, this: Self) {
        gobject_ffi::g_value_set_object(value.to_glib_none_mut().0, this.to_glib_none().0)
    }
}

impl<'a, T: IsA<Object>> SetValueOptional for &'a T {
    unsafe fn set_value_optional(value: &mut Value, this: Option<Self>) {
        gobject_ffi::g_value_set_object(value.to_glib_none_mut().0, this.to_glib_none().0)
    }
}

impl FromValueOptional for bool {
    unsafe fn from_value_optional(value: &Value) -> Option<Self> {
        Some(from_glib(gobject_ffi::g_value_get_boolean(value.to_glib_none().0)))
    }
}

impl FromValue for bool {
    unsafe fn from_value(value: &Value) -> Self {
        from_glib(gobject_ffi::g_value_get_boolean(value.to_glib_none().0))
    }
}

impl SetValue for bool {
    unsafe fn set_value(value: &mut Value, this: Self) {
        gobject_ffi::g_value_set_boolean(value.to_glib_none_mut().0, this.to_glib())
    }
}

macro_rules! numeric {
    ($name:ident, $get:ident, $set:ident) => {
        impl FromValueOptional for $name {
            unsafe fn from_value_optional(value: &Value) -> Option<Self> {
                Some(gobject_ffi::$get(value.to_glib_none().0))
            }
        }

        impl FromValue for $name {
            unsafe fn from_value(value: &Value) -> Self {
                gobject_ffi::$get(value.to_glib_none().0)
            }
        }

        impl SetValue for $name {
            unsafe fn set_value(value: &mut Value, this: Self) {
                gobject_ffi::$set(value.to_glib_none_mut().0, this)
            }
        }

        impl<'a> SetValue for &'a $name {
            unsafe fn set_value(value: &mut Value, this: Self) {
                gobject_ffi::$set(value.to_glib_none_mut().0, *this)
            }
        }
    }
}

numeric!(i8, g_value_get_schar, g_value_set_schar);
numeric!(u8, g_value_get_uchar, g_value_set_uchar);
numeric!(i32, g_value_get_int, g_value_set_int);
numeric!(u32, g_value_get_uint, g_value_set_uint);
numeric!(i64, g_value_get_int64, g_value_set_int64);
numeric!(u64, g_value_get_uint64, g_value_set_uint64);
numeric!(f32, g_value_get_float, g_value_set_float);
numeric!(f64, g_value_get_double, g_value_set_double);
<|endoftext|>


<commit_before>//! Types representing for data which will be retrieved from the driver.
//! Currently this data is expected to look like a JSON object but this may be
//! changed in the future. Driver authors must cast the data they retrieve from
//! the driver to these types.

use linear_map::LinearMap;

/// The atomic level of a pointer.
pub type Key = String;

/// Represents a JSON pointer to a document property.
pub type Pointer = Vec<Key>;

/// Various value types. Based on types in the [JSON standard][1] (see section
/// 5).
///
/// [1]: http://ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf
#[derive(PartialEq, Clone, Debug)]
pub enum Value {
  /// The abscense of any value.
  Null,
  /// True or false.
  Boolean(bool),
  /// A numeric value, float, integer, whatever.
  Number(f64),
  /// A list of characters.
  String(String),
  /// A map of key/value pairs. Stored as a vector of tuples for performance
  /// and to maintain key ordering.
  Object(LinearMap<Key, Value>),
  /// A list of values. Just a value, but using *only* integer keys.
  Array(Vec<Value>)
}

impl Value {
  /// Gets a value at a specific point. Helpful for retrieving nested values.
  pub fn get(&self, mut pointer: Pointer) -> Option<Value> {
    match self {
      &Value::Null => if pointer.len() == 0 { Some(Value::Null) } else { None },
      &Value::Boolean(_) => if pointer.len() == 0 { Some(self.clone()) } else { None },
      &Value::Number(_) => if pointer.len() == 0 { Some(self.clone()) } else { None },
      &Value::String(_) => if pointer.len() == 0 { Some(self.clone()) } else { None },
      &Value::Object(ref map) => {
        if pointer.len() == 0 {
          Some(self.clone())
        } else if let Some(value) = map.get(&pointer.remove(0)) {
          value.get(pointer)
        } else {
          None
        }
      },
      &Value::Array(ref vec) => {
        if pointer.len() == 0 {
          Some(self.clone())
        } else if let Some(value) = pointer.remove(0).parse::<usize>().ok().map_or(None, |i| vec.get(i)) {
          value.get(pointer)
        } else {
          None
        }
      }
    }
  }
}

#[cfg(test)]
mod tests {
  #[test]
  fn test_get_primitive() {
    assert_eq!(vnull!().get(point![]), Some(vnull!()));
    assert_eq!(vnull!().get(point!["hello"]), None);
    assert_eq!(vnull!().get(point!["a", "b", "c", "d", "e"]), None);
    assert_eq!(vbool!(true).get(point![]), Some(vbool!(true)));
    assert_eq!(vbool!(true).get(point!["hello"]), None);
    assert_eq!(vnum!(36f64).get(point![]), Some(vnum!(36f64)));
    assert_eq!(vnum!(36f64).get(point!["hello"]), None);
    assert_eq!(vstring!("world").get(point![]), Some(vstring!("world")));
    assert_eq!(vstring!("world").get(point!["hello"]), None);
  }

  #[test]
  fn test_get_object() {
    let object = vobject!{
      "hello" => vbool!(true),
      "world" => vnum!(8f64),
      "5" => vnull!(),
      "moon" => vobject!{
        "hello" => vstring!("yoyo")
      }
    };
    assert_eq!(object.get(point![]), Some(object.clone()));
    assert_eq!(object.get(point!["hello"]), Some(vbool!(true)));
    assert_eq!(object.get(point!["5"]), Some(vnull!()));
    assert_eq!(object.get(point!["world", "hello"]), None);
    assert_eq!(object.get(point!["moon", "hello"]), Some(vstring!("yoyo")));
    assert_eq!(object.get(point!["moon", "nope"]), None);
  }

  #[test]
  fn test_get_array() {
    let array = varray![
      vbool!(false),
      vnum!(64f64),
      vobject!{
        "hello" => vbool!(true),
        "world" => vbool!(false),
        "moon" => vobject!{
          "goodbye" => vstring!("yoyo")
        }
      },
      varray![
        varray![
          vnum!(1f64),
          vnum!(2f64),
          vnum!(3f64)
        ],
        vnum!(4f64),
        vnum!(5f64)
      ]
    ];
    assert_eq!(array.get(point![]), Some(array.clone()));
    assert_eq!(array.get(point!["0"]), Some(vbool!(false)));
    assert_eq!(array.get(point!["1"]), Some(vnum!(64f64)));
    assert_eq!(array.get(point!["2", "hello"]), Some(vbool!(true)));
    assert_eq!(array.get(point!["2", "moon", "goodbye"]), Some(vstring!("yoyo")));
    assert_eq!(array.get(point!["length"]), None);
    assert_eq!(array.get(point!["3", "0", "1"]), Some(vnum!(2f64)));
  }
}
<commit_msg>refactor: clone null in value get<commit_after>//! Types representing for data which will be retrieved from the driver.
//! Currently this data is expected to look like a JSON object but this may be
//! changed in the future. Driver authors must cast the data they retrieve from
//! the driver to these types.

use linear_map::LinearMap;

/// The atomic level of a pointer.
pub type Key = String;

/// Represents a JSON pointer to a document property.
pub type Pointer = Vec<Key>;

/// Various value types. Based on types in the [JSON standard][1] (see section
/// 5).
///
/// [1]: http://ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf
#[derive(PartialEq, Clone, Debug)]
pub enum Value {
  /// The abscense of any value.
  Null,
  /// True or false.
  Boolean(bool),
  /// A numeric value, float, integer, whatever.
  Number(f64),
  /// A list of characters.
  String(String),
  /// A map of key/value pairs. Stored as a vector of tuples for performance
  /// and to maintain key ordering.
  Object(LinearMap<Key, Value>),
  /// A list of values. Just a value, but using *only* integer keys.
  Array(Vec<Value>)
}

impl Value {
  /// Gets a value at a specific point. Helpful for retrieving nested values.
  pub fn get(&self, mut pointer: Pointer) -> Option<Value> {
    match self {
      &Value::Null => if pointer.len() == 0 { Some(self.clone()) } else { None },
      &Value::Boolean(_) => if pointer.len() == 0 { Some(self.clone()) } else { None },
      &Value::Number(_) => if pointer.len() == 0 { Some(self.clone()) } else { None },
      &Value::String(_) => if pointer.len() == 0 { Some(self.clone()) } else { None },
      &Value::Object(ref map) => {
        if pointer.len() == 0 {
          Some(self.clone())
        } else if let Some(value) = map.get(&pointer.remove(0)) {
          value.get(pointer)
        } else {
          None
        }
      },
      &Value::Array(ref vec) => {
        if pointer.len() == 0 {
          Some(self.clone())
        } else if let Some(value) = pointer.remove(0).parse::<usize>().ok().map_or(None, |i| vec.get(i)) {
          value.get(pointer)
        } else {
          None
        }
      }
    }
  }
}

#[cfg(test)]
mod tests {
  #[test]
  fn test_get_primitive() {
    assert_eq!(vnull!().get(point![]), Some(vnull!()));
    assert_eq!(vnull!().get(point!["hello"]), None);
    assert_eq!(vnull!().get(point!["a", "b", "c", "d", "e"]), None);
    assert_eq!(vbool!(true).get(point![]), Some(vbool!(true)));
    assert_eq!(vbool!(true).get(point!["hello"]), None);
    assert_eq!(vnum!(36f64).get(point![]), Some(vnum!(36f64)));
    assert_eq!(vnum!(36f64).get(point!["hello"]), None);
    assert_eq!(vstring!("world").get(point![]), Some(vstring!("world")));
    assert_eq!(vstring!("world").get(point!["hello"]), None);
  }

  #[test]
  fn test_get_object() {
    let object = vobject!{
      "hello" => vbool!(true),
      "world" => vnum!(8f64),
      "5" => vnull!(),
      "moon" => vobject!{
        "hello" => vstring!("yoyo")
      }
    };
    assert_eq!(object.get(point![]), Some(object.clone()));
    assert_eq!(object.get(point!["hello"]), Some(vbool!(true)));
    assert_eq!(object.get(point!["5"]), Some(vnull!()));
    assert_eq!(object.get(point!["world", "hello"]), None);
    assert_eq!(object.get(point!["moon", "hello"]), Some(vstring!("yoyo")));
    assert_eq!(object.get(point!["moon", "nope"]), None);
  }

  #[test]
  fn test_get_array() {
    let array = varray![
      vbool!(false),
      vnum!(64f64),
      vobject!{
        "hello" => vbool!(true),
        "world" => vbool!(false),
        "moon" => vobject!{
          "goodbye" => vstring!("yoyo")
        }
      },
      varray![
        varray![
          vnum!(1f64),
          vnum!(2f64),
          vnum!(3f64)
        ],
        vnum!(4f64),
        vnum!(5f64)
      ]
    ];
    assert_eq!(array.get(point![]), Some(array.clone()));
    assert_eq!(array.get(point!["0"]), Some(vbool!(false)));
    assert_eq!(array.get(point!["1"]), Some(vnum!(64f64)));
    assert_eq!(array.get(point!["2", "hello"]), Some(vbool!(true)));
    assert_eq!(array.get(point!["2", "moon", "goodbye"]), Some(vstring!("yoyo")));
    assert_eq!(array.get(point!["length"]), None);
    assert_eq!(array.get(point!["3", "0", "1"]), Some(vnum!(2f64)));
  }
}
<|endoftext|>


<commit_before>// Copyright 2015 The Rust-Windows Project Developers. See the
// COPYRIGHT file at the top-level directory of this distribution.
//
// 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.

use std::mem;
use std::fmt;
use std::fmt::Display;
use std::vec::Vec;

// Helper struct for *u16 manipulation.
#[allow(missing_copy_implementations)]
pub struct CU16String {
    buf: *const u16,
    /// length of buffer, including null
    len: usize,
}

impl CU16String {
    /// Create a CU16String from a pointer.
    pub unsafe fn new(buf: *const u16) -> CU16String {
        CU16String {
            buf: buf,
            len: {
                let mut length_counter = 0;
                loop {
                    if *buf.offset(length_counter)==0 {
                        break;
                    }
                    length_counter += 1;
                }
		length_counter += 1;
                length_counter as usize
            }
        }
    }

    /// Converts the CU16String into a `&[u16]` without copying.
    /// NULL is not included.
    ///
    /// # Failure
    ///
    /// Fails if the CU16String is null.
    #[inline]
    pub fn as_u16_vec<'a>(&'a self) -> &'a [u16] {
        if self.buf.is_null() { panic!("CU16String is null!"); }
        unsafe {
            mem::transmute((self.buf, self.len - 1))
        }
    }
}

impl fmt::Display for CU16String {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let s = if self.buf.is_null() {
            "".to_string()
        } else {
            String::from_utf16_lossy(self.as_u16_vec())
        };
        s.fmt(f)
    }
}

/// Parses a C utf-16 "multistring".
/// See `std::c_str::from_c_multistring` for detailed explanation.
pub unsafe fn from_c_u16_multistring<F>(buf: *const u16, count: Option<usize>, mut f: F) -> usize
    where F: FnMut(&[u16]) {
    let mut curr_ptr: usize = buf as usize;
    let mut ctr = 0;
    let (limited_count, limit) = match count {
        Some(limit) => (true, limit),
        None => (false, 0)
    };
    while ((limited_count && ctr < limit) || !limited_count)
          && *(curr_ptr as *const u16) != 0 as u16 {
        let cstr = CU16String::new(curr_ptr as *const u16);
        f(cstr.as_u16_vec());
        curr_ptr += cstr.len * 2;
        ctr += 1;
    }
    return ctr;
}

/// A generic trait for converting a value to a `CU16String`, like `ToCStr`.
pub trait ToCU16Str {
    fn to_c_u16(&self) -> Vec<u16>;
}

impl<'a> ToCU16Str for &'a str {
    fn to_c_u16(&self) -> Vec<u16> {
        let mut t : Vec<u16> = self.utf16_units().collect();
        t.push(0u16);
        t
    }
}

impl ToCU16Str for String {
    fn to_c_u16(&self) -> Vec<u16> {
        let x : &str = &self;
        x.to_c_u16()
    }
}

impl ToCU16Str for Option<String> {
    fn to_c_u16(&self) -> Vec<u16> {
        match self {
            &None => Vec::new(),
            &Some(ref s) => (&s).to_c_u16(),
        }
    }
}

#[cfg(test)]
mod test {
    use super::CU16String;
    use super::from_c_u16_multistring;

    #[test]
    fn test_as_u16_vec() {
        let u16s: &[u16] = &[
            0xac00, 0x20, 0xac00, 0x00,
        ];

        let cu = unsafe { CU16String::new(u16s.as_ptr()) };
        let v = cu.as_u16_vec();
        assert_eq!(v, &u16s[..u16s.len() - 1]);
    }

    #[test]
    fn test_from_c_u16_multistring() {
        let test: &[u16] = &[
            0xac00, 0x00,
            0xac00, 0xac00, 0x00,
            0xac00, 0xac00, 0xac00, 0x00,
            0xac00, 0xac00, 0xac00, 0xac02, 0x00,
            0x00,
        ];
        let compare = [
            "가",
            "가가",
            "가가가",
            "가가가갂",
        ];
        let mut i = 0;
        let buf = test.as_ptr();
        unsafe {
            from_c_u16_multistring(buf, None, |p| {
                let b = String::from_utf16(p).unwrap();
		println!("{:?}", p);
                assert_eq!(b, compare[i].to_owned());
                assert_eq!(b.chars().count(), i + 1);
                i += 1;
            });
        }
        assert_eq!(i, 4);
    }
}
<commit_msg>Fix formatting<commit_after>// Copyright 2015 The Rust-Windows Project Developers. See the
// COPYRIGHT file at the top-level directory of this distribution.
//
// 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.

use std::mem;
use std::fmt;
use std::fmt::Display;
use std::vec::Vec;

// Helper struct for *u16 manipulation.
#[allow(missing_copy_implementations)]
pub struct CU16String {
    buf: *const u16,
    /// length of buffer, including null
    len: usize,
}

impl CU16String {
    /// Create a CU16String from a pointer.
    pub unsafe fn new(buf: *const u16) -> CU16String {
        CU16String {
            buf: buf,
            len: {
                let mut length_counter = 0;
                loop {
                    if *buf.offset(length_counter)==0 {
                        break;
                    }
                    length_counter += 1;
                }
                length_counter += 1;
                length_counter as usize
            }
        }
    }

    /// Converts the CU16String into a `&[u16]` without copying.
    /// NULL is not included.
    ///
    /// # Failure
    ///
    /// Fails if the CU16String is null.
    #[inline]
    pub fn as_u16_vec<'a>(&'a self) -> &'a [u16] {
        if self.buf.is_null() { panic!("CU16String is null!"); }
        unsafe {
            mem::transmute((self.buf, self.len - 1))
        }
    }
}

impl fmt::Display for CU16String {
    #[inline]
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let s = if self.buf.is_null() {
            "".to_string()
        } else {
            String::from_utf16_lossy(self.as_u16_vec())
        };
        s.fmt(f)
    }
}

/// Parses a C utf-16 "multistring".
/// See `std::c_str::from_c_multistring` for detailed explanation.
pub unsafe fn from_c_u16_multistring<F>(buf: *const u16, count: Option<usize>, mut f: F) -> usize
    where F: FnMut(&[u16]) {
    let mut curr_ptr: usize = buf as usize;
    let mut ctr = 0;
    let (limited_count, limit) = match count {
        Some(limit) => (true, limit),
        None => (false, 0)
    };
    while ((limited_count && ctr < limit) || !limited_count)
          && *(curr_ptr as *const u16) != 0 as u16 {
        let cstr = CU16String::new(curr_ptr as *const u16);
        f(cstr.as_u16_vec());
        curr_ptr += cstr.len * 2;
        ctr += 1;
    }
    return ctr;
}

/// A generic trait for converting a value to a `CU16String`, like `ToCStr`.
pub trait ToCU16Str {
    fn to_c_u16(&self) -> Vec<u16>;
}

impl<'a> ToCU16Str for &'a str {
    fn to_c_u16(&self) -> Vec<u16> {
        let mut t : Vec<u16> = self.utf16_units().collect();
        t.push(0u16);
        t
    }
}

impl ToCU16Str for String {
    fn to_c_u16(&self) -> Vec<u16> {
        let x : &str = &self;
        x.to_c_u16()
    }
}

impl ToCU16Str for Option<String> {
    fn to_c_u16(&self) -> Vec<u16> {
        match self {
            &None => Vec::new(),
            &Some(ref s) => (&s).to_c_u16(),
        }
    }
}

#[cfg(test)]
mod test {
    use super::CU16String;
    use super::from_c_u16_multistring;

    #[test]
    fn test_as_u16_vec() {
        let u16s: &[u16] = &[
            0xac00, 0x20, 0xac00, 0x00,
        ];

        let cu = unsafe { CU16String::new(u16s.as_ptr()) };
        let v = cu.as_u16_vec();
        assert_eq!(v, &u16s[..u16s.len() - 1]);
    }

    #[test]
    fn test_from_c_u16_multistring() {
        let test: &[u16] = &[
            0xac00, 0x00,
            0xac00, 0xac00, 0x00,
            0xac00, 0xac00, 0xac00, 0x00,
            0xac00, 0xac00, 0xac00, 0xac02, 0x00,
            0x00,
        ];
        let compare = [
            "가",
            "가가",
            "가가가",
            "가가가갂",
        ];
        let mut i = 0;
        let buf = test.as_ptr();
        unsafe {
            from_c_u16_multistring(buf, None, |p| {
                let b = String::from_utf16(p).unwrap();
                assert_eq!(b, compare[i].to_owned());
                assert_eq!(b.chars().count(), i + 1);
                i += 1;
            });
        }
        assert_eq!(i, 4);
    }
}
<|endoftext|>


<commit_before>use std::io::{TcpListener, TcpStream};
use std::io::{Acceptor, Listener};
use std::io::BufferedStream;
use std::string::String;

pub const CR: u8 = b'\r';
pub const LF: u8 = b'\n';
pub const SP: u8 = b' ';
pub const CRLF: &'static [u8] = &[CR,LF];

struct RequestedRoute {
    method: String,
    pathname: String
}

fn parse_request_line(header: &str) -> RequestedRoute {
    let mut pathname = String::new();
    let mut method = String::new();
    let mut starting = true;
    let mut found_method = false;

    for ch in header.graphemes(true) {
        let cbyte = ch.as_bytes()[0];

        if starting && cbyte != SP {
            method.push_str(ch);
        }
        if starting && cbyte == SP {
            starting = false;
            found_method = true;
            continue;
        }
        if found_method && cbyte != SP {
            pathname.push_str(ch);
        }
        if found_method && cbyte == SP {
            break;
        }

    }

    return RequestedRoute {method: method, pathname: pathname};
}

fn main () {

    let listener = TcpListener::bind("127.0.0.1:8099").unwrap();
    let mut acceptor = listener.listen().unwrap();

    fn handle_client(mut stream: BufferedStream<TcpStream>) {

        let mut body: String = "
You sent it!
".to_string();

        let mut cur_line: String;
        let mut ii = 0u;
        let mut req: RequestedRoute = RequestedRoute{
            pathname: String::new(),
            method: String::new()
        };

        loop {
            match stream.read_line() { // XXX: strange unwrap like thing
                Ok(line) => cur_line = line,
                Err(_) => break
            }
            if ii == 0u { // the Request-Line is always the first line
                req = parse_request_line(cur_line.as_slice());
                ii += 1;
            }

            body = body + cur_line + "
";
            if cur_line.as_bytes() == CRLF {
                break;
            }
        }
        println!("pathname {} method {}", req.pathname, req.method);

        let body_length = format!("Content-length: {}", body.len());

        stream.write(b"HTTP/1.1 200 OK\r\n").unwrap(); // byte literal
        stream.write(b"Content-type: text/html\r\n").unwrap();
        stream.write(b"X-header: from bytes\r\n").unwrap();
        stream.write(body_length.into_bytes().as_slice()).unwrap();
        stream.write(b"\r\n\r\n").unwrap();
        stream.write(body.into_bytes().as_slice()).unwrap();
        stream.flush().unwrap();

        println!("Handling acceptor");
    }

    for stream in acceptor.incoming() {
        match stream {
            Err(e) => { println!("connection failed: {}", e) }
            Ok(stream) => spawn(proc() {
                let bs = BufferedStream::new(stream);
                handle_client(bs)
            })
        }
    }

    drop(acceptor);
}
<commit_msg>get vec<u8><commit_after>use std::io::{TcpListener, TcpStream};
use std::io::{Acceptor, Listener};
use std::io::{File, BufferedStream};
use std::string::String;

pub const CR: u8 = b'\r';
pub const LF: u8 = b'\n';
pub const SP: u8 = b' ';
pub const CRLF: &'static [u8] = &[CR,LF];

struct RequestedRoute {
    method: String,
    pathname: String
}

fn parse_request_line(header: &str) -> RequestedRoute {
    let mut pathname = String::new();
    let mut method = String::new();
    let mut starting = true;
    let mut found_method = false;

    for ch in header.graphemes(true) {
        let cbyte = ch.as_bytes()[0];

        if starting && cbyte != SP {
            method.push_str(ch);
        }
        if starting && cbyte == SP {
            starting = false;
            found_method = true;
            continue;
        }
        if found_method && cbyte != SP {
            pathname.push_str(ch);
        }
        if found_method && cbyte == SP {
            break;
        }

    }
    return RequestedRoute {method: method, pathname: pathname};
}

fn get_index_body () -> String {
    let path = Path::new("../html/ws1.html");
    let display = path.display();
    let mut file = match File::open(&path) {
        Ok(f) => f,
        Err(err) => panic!("file error: {}", err)
    };

    let content = file.read_to_end(); // this is Result
    println!("{} {}", display, content);

    return String::new();
}

fn main () {

    let listener = TcpListener::bind("127.0.0.1:8099").unwrap();
    let mut acceptor = listener.listen().unwrap();

    fn handle_client(mut stream: BufferedStream<TcpStream>) {

        let mut body: String = "
You sent it!
".to_string();

        let mut cur_line: String;
        let mut ii = 0u;
        let mut req: RequestedRoute = RequestedRoute{
            pathname: String::new(),
            method: String::new()
        };

        loop {
            match stream.read_line() { // XXX: strange unwrap like thing
                Ok(line) => cur_line = line,
                Err(_) => break
            }
            if ii == 0u { // the Request-Line is always the first line
                req = parse_request_line(cur_line.as_slice());
                ii += 1;
            }

            body = body + cur_line + "
";
            if cur_line.as_bytes() == CRLF {
                break;
            }
        }
        println!("pathname {} method {}", req.pathname, req.method);
        get_index_body();

        let body_length = format!("Content-length: {}", body.len());

        stream.write(b"HTTP/1.1 200 OK\r\n").unwrap(); // byte literal
        stream.write(b"Content-type: text/html\r\n").unwrap();
        stream.write(b"X-header: from bytes\r\n").unwrap();
        stream.write(body_length.into_bytes().as_slice()).unwrap();
        stream.write(b"\r\n\r\n").unwrap();
        stream.write(body.into_bytes().as_slice()).unwrap();
        stream.flush().unwrap();

        println!("Handling acceptor");
    }

    for stream in acceptor.incoming() {
        match stream {
            Err(e) => { println!("connection failed: {}", e) }
            Ok(stream) => spawn(proc() {
                let bs = BufferedStream::new(stream);
                handle_client(bs)
            })
        }
    }

    drop(acceptor);
}
<|endoftext|>


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

// The crate store - a central repo for information collected about external
// crates and libraries

use schema;

use rustc::hir::def_id::{CRATE_DEF_INDEX, CrateNum, DefIndex};
use rustc::hir::map::definitions::DefPathTable;
use rustc::hir::svh::Svh;
use rustc::middle::cstore::{DepKind, ExternCrate, MetadataLoader};
use rustc::session::{Session, CrateDisambiguator};
use rustc_back::PanicStrategy;
use rustc_data_structures::indexed_vec::IndexVec;
use rustc::util::nodemap::{FxHashMap, FxHashSet, NodeMap};

use rustc_data_structures::sync::{Lrc, RwLock, Lock};
use syntax::{ast, attr};
use syntax::ext::base::SyntaxExtension;
use syntax::symbol::Symbol;
use syntax_pos;

pub use rustc::middle::cstore::{NativeLibrary, NativeLibraryKind, LinkagePreference};
pub use rustc::middle::cstore::NativeLibraryKind::*;
pub use rustc::middle::cstore::{CrateSource, LibSource};

pub use cstore_impl::{provide, provide_extern};

// A map from external crate numbers (as decoded from some crate file) to
// local crate numbers (as generated during this session). Each external
// crate may refer to types in other external crates, and each has their
// own crate numbers.
pub type CrateNumMap = IndexVec<CrateNum, CrateNum>;

pub use rustc_data_structures::sync::MetadataRef;

pub struct MetadataBlob(pub MetadataRef);

/// Holds information about a syntax_pos::FileMap imported from another crate.
/// See `imported_filemaps()` for more information.
pub struct ImportedFileMap {
    /// This FileMap's byte-offset within the codemap of its original crate
    pub original_start_pos: syntax_pos::BytePos,
    /// The end of this FileMap within the codemap of its original crate
    pub original_end_pos: syntax_pos::BytePos,
    /// The imported FileMap's representation within the local codemap
    pub translated_filemap: Lrc<syntax_pos::FileMap>,
}

pub struct CrateMetadata {
    pub name: Symbol,

    /// Information about the extern crate that caused this crate to
    /// be loaded. If this is `None`, then the crate was injected
    /// (e.g., by the allocator)
    pub extern_crate: Lock<Option<ExternCrate>>,

    pub blob: MetadataBlob,
    pub cnum_map: Lock<CrateNumMap>,
    pub cnum: CrateNum,
    pub codemap_import_info: RwLock<Vec<ImportedFileMap>>,
    pub attribute_cache: Lock<[Vec<Option<Lrc<[ast::Attribute]>>>; 2]>,

    pub root: schema::CrateRoot,

    /// For each public item in this crate, we encode a key.  When the
    /// crate is loaded, we read all the keys and put them in this
    /// hashmap, which gives the reverse mapping.  This allows us to
    /// quickly retrace a `DefPath`, which is needed for incremental
    /// compilation support.
    pub def_path_table: Lrc<DefPathTable>,

    pub trait_impls: FxHashMap<(u32, DefIndex), schema::LazySeq<DefIndex>>,

    pub dep_kind: Lock<DepKind>,
    pub source: CrateSource,

    pub proc_macros: Option<Vec<(ast::Name, Lrc<SyntaxExtension>)>>,
    // Foreign items imported from a dylib (Windows only)
    pub dllimport_foreign_items: FxHashSet<DefIndex>,
}

pub struct CStore {
    metas: RefCell<IndexVec<CrateNum, Option<Lrc<CrateMetadata>>>>,
    /// Map from NodeId's of local extern crate statements to crate numbers
    extern_mod_crate_map: RefCell<NodeMap<CrateNum>>,
    pub metadata_loader: Box<MetadataLoader + Sync>,
}

impl CStore {
    pub fn new(metadata_loader: Box<MetadataLoader + Sync>) -> CStore {
        CStore {
            metas: RefCell::new(IndexVec::new()),
            extern_mod_crate_map: RefCell::new(FxHashMap()),
            metadata_loader,
        }
    }

    pub fn next_crate_num(&self) -> CrateNum {
        CrateNum::new(self.metas.borrow().len() + 1)
    }

    pub fn get_crate_data(&self, cnum: CrateNum) -> Lrc<CrateMetadata> {
        self.metas.borrow()[cnum].clone().unwrap()
    }

    pub fn set_crate_data(&self, cnum: CrateNum, data: Lrc<CrateMetadata>) {
        use rustc_data_structures::indexed_vec::Idx;
        let mut met = self.metas.borrow_mut();
        while met.len() <= cnum.index() {
            met.push(None);
        }
        met[cnum] = Some(data);
    }

    pub fn iter_crate_data<I>(&self, mut i: I)
        where I: FnMut(CrateNum, &Lrc<CrateMetadata>)
    {
        for (k, v) in self.metas.borrow().iter_enumerated() {
            if let &Some(ref v) = v {
                i(k, v);
            }
        }
    }

    pub fn crate_dependencies_in_rpo(&self, krate: CrateNum) -> Vec<CrateNum> {
        let mut ordering = Vec::new();
        self.push_dependencies_in_postorder(&mut ordering, krate);
        ordering.reverse();
        ordering
    }

    pub fn push_dependencies_in_postorder(&self, ordering: &mut Vec<CrateNum>, krate: CrateNum) {
        if ordering.contains(&krate) {
            return;
        }

        let data = self.get_crate_data(krate);
        for &dep in data.cnum_map.borrow().iter() {
            if dep != krate {
                self.push_dependencies_in_postorder(ordering, dep);
            }
        }

        ordering.push(krate);
    }

    pub fn do_postorder_cnums_untracked(&self) -> Vec<CrateNum> {
        let mut ordering = Vec::new();
        for (num, v) in self.metas.borrow().iter_enumerated() {
            if let &Some(_) = v {
                self.push_dependencies_in_postorder(&mut ordering, num);
            }
        }
        return ordering
    }

    pub fn add_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId, cnum: CrateNum) {
        self.extern_mod_crate_map.borrow_mut().insert(emod_id, cnum);
    }

    pub fn do_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<CrateNum> {
        self.extern_mod_crate_map.borrow().get(&emod_id).cloned()
    }
}

impl CrateMetadata {
    pub fn name(&self) -> Symbol {
        self.root.name
    }
    pub fn hash(&self) -> Svh {
        self.root.hash
    }
    pub fn disambiguator(&self) -> CrateDisambiguator {
        self.root.disambiguator
    }

    pub fn needs_allocator(&self, sess: &Session) -> bool {
        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
        attr::contains_name(&attrs, "needs_allocator")
    }

    pub fn has_global_allocator(&self) -> bool {
        self.root.has_global_allocator.clone()
    }

    pub fn has_default_lib_allocator(&self) -> bool {
        self.root.has_default_lib_allocator.clone()
    }

    pub fn is_panic_runtime(&self, sess: &Session) -> bool {
        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
        attr::contains_name(&attrs, "panic_runtime")
    }

    pub fn needs_panic_runtime(&self, sess: &Session) -> bool {
        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
        attr::contains_name(&attrs, "needs_panic_runtime")
    }

    pub fn is_compiler_builtins(&self, sess: &Session) -> bool {
        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
        attr::contains_name(&attrs, "compiler_builtins")
    }

    pub fn is_sanitizer_runtime(&self, sess: &Session) -> bool {
        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
        attr::contains_name(&attrs, "sanitizer_runtime")
    }

    pub fn is_profiler_runtime(&self, sess: &Session) -> bool {
        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
        attr::contains_name(&attrs, "profiler_runtime")
    }

    pub fn is_no_builtins(&self, sess: &Session) -> bool {
        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
        attr::contains_name(&attrs, "no_builtins")
    }

     pub fn has_copy_closures(&self, sess: &Session) -> bool {
        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
        attr::contains_feature_attr(&attrs, "copy_closures")
    }

    pub fn has_clone_closures(&self, sess: &Session) -> bool {
        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
        attr::contains_feature_attr(&attrs, "clone_closures")
    }

    pub fn panic_strategy(&self) -> PanicStrategy {
        self.root.panic_strategy.clone()
    }
}
<commit_msg>Make CStore thread-safe<commit_after>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// The crate store - a central repo for information collected about external
// crates and libraries

use schema;

use rustc::hir::def_id::{CRATE_DEF_INDEX, CrateNum, DefIndex};
use rustc::hir::map::definitions::DefPathTable;
use rustc::hir::svh::Svh;
use rustc::middle::cstore::{DepKind, ExternCrate, MetadataLoader};
use rustc::session::{Session, CrateDisambiguator};
use rustc_back::PanicStrategy;
use rustc_data_structures::indexed_vec::IndexVec;
use rustc::util::nodemap::{FxHashMap, FxHashSet, NodeMap};

use rustc_data_structures::sync::{Lrc, RwLock, Lock};
use syntax::{ast, attr};
use syntax::ext::base::SyntaxExtension;
use syntax::symbol::Symbol;
use syntax_pos;

pub use rustc::middle::cstore::{NativeLibrary, NativeLibraryKind, LinkagePreference};
pub use rustc::middle::cstore::NativeLibraryKind::*;
pub use rustc::middle::cstore::{CrateSource, LibSource};

pub use cstore_impl::{provide, provide_extern};

// A map from external crate numbers (as decoded from some crate file) to
// local crate numbers (as generated during this session). Each external
// crate may refer to types in other external crates, and each has their
// own crate numbers.
pub type CrateNumMap = IndexVec<CrateNum, CrateNum>;

pub use rustc_data_structures::sync::MetadataRef;

pub struct MetadataBlob(pub MetadataRef);

/// Holds information about a syntax_pos::FileMap imported from another crate.
/// See `imported_filemaps()` for more information.
pub struct ImportedFileMap {
    /// This FileMap's byte-offset within the codemap of its original crate
    pub original_start_pos: syntax_pos::BytePos,
    /// The end of this FileMap within the codemap of its original crate
    pub original_end_pos: syntax_pos::BytePos,
    /// The imported FileMap's representation within the local codemap
    pub translated_filemap: Lrc<syntax_pos::FileMap>,
}

pub struct CrateMetadata {
    pub name: Symbol,

    /// Information about the extern crate that caused this crate to
    /// be loaded. If this is `None`, then the crate was injected
    /// (e.g., by the allocator)
    pub extern_crate: Lock<Option<ExternCrate>>,

    pub blob: MetadataBlob,
    pub cnum_map: Lock<CrateNumMap>,
    pub cnum: CrateNum,
    pub codemap_import_info: RwLock<Vec<ImportedFileMap>>,
    pub attribute_cache: Lock<[Vec<Option<Lrc<[ast::Attribute]>>>; 2]>,

    pub root: schema::CrateRoot,

    /// For each public item in this crate, we encode a key.  When the
    /// crate is loaded, we read all the keys and put them in this
    /// hashmap, which gives the reverse mapping.  This allows us to
    /// quickly retrace a `DefPath`, which is needed for incremental
    /// compilation support.
    pub def_path_table: Lrc<DefPathTable>,

    pub trait_impls: FxHashMap<(u32, DefIndex), schema::LazySeq<DefIndex>>,

    pub dep_kind: Lock<DepKind>,
    pub source: CrateSource,

    pub proc_macros: Option<Vec<(ast::Name, Lrc<SyntaxExtension>)>>,
    // Foreign items imported from a dylib (Windows only)
    pub dllimport_foreign_items: FxHashSet<DefIndex>,
}

pub struct CStore {
    metas: RwLock<IndexVec<CrateNum, Option<Lrc<CrateMetadata>>>>,
    /// Map from NodeId's of local extern crate statements to crate numbers
    extern_mod_crate_map: Lock<NodeMap<CrateNum>>,
    pub metadata_loader: Box<MetadataLoader + Sync>,
}

impl CStore {
    pub fn new(metadata_loader: Box<MetadataLoader + Sync>) -> CStore {
        CStore {
            metas: RwLock::new(IndexVec::new()),
            extern_mod_crate_map: Lock::new(FxHashMap()),
            metadata_loader,
        }
    }

    /// You cannot use this function to allocate a CrateNum in a thread-safe manner.
    /// It is currently only used in CrateLoader which is single-threaded code.
    pub fn next_crate_num(&self) -> CrateNum {
        CrateNum::new(self.metas.borrow().len() + 1)
    }

    pub fn get_crate_data(&self, cnum: CrateNum) -> Lrc<CrateMetadata> {
        self.metas.borrow()[cnum].clone().unwrap()
    }

    pub fn set_crate_data(&self, cnum: CrateNum, data: Lrc<CrateMetadata>) {
        use rustc_data_structures::indexed_vec::Idx;
        let mut met = self.metas.borrow_mut();
        while met.len() <= cnum.index() {
            met.push(None);
        }
        met[cnum] = Some(data);
    }

    pub fn iter_crate_data<I>(&self, mut i: I)
        where I: FnMut(CrateNum, &Lrc<CrateMetadata>)
    {
        for (k, v) in self.metas.borrow().iter_enumerated() {
            if let &Some(ref v) = v {
                i(k, v);
            }
        }
    }

    pub fn crate_dependencies_in_rpo(&self, krate: CrateNum) -> Vec<CrateNum> {
        let mut ordering = Vec::new();
        self.push_dependencies_in_postorder(&mut ordering, krate);
        ordering.reverse();
        ordering
    }

    pub fn push_dependencies_in_postorder(&self, ordering: &mut Vec<CrateNum>, krate: CrateNum) {
        if ordering.contains(&krate) {
            return;
        }

        let data = self.get_crate_data(krate);
        for &dep in data.cnum_map.borrow().iter() {
            if dep != krate {
                self.push_dependencies_in_postorder(ordering, dep);
            }
        }

        ordering.push(krate);
    }

    pub fn do_postorder_cnums_untracked(&self) -> Vec<CrateNum> {
        let mut ordering = Vec::new();
        for (num, v) in self.metas.borrow().iter_enumerated() {
            if let &Some(_) = v {
                self.push_dependencies_in_postorder(&mut ordering, num);
            }
        }
        return ordering
    }

    pub fn add_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId, cnum: CrateNum) {
        self.extern_mod_crate_map.borrow_mut().insert(emod_id, cnum);
    }

    pub fn do_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<CrateNum> {
        self.extern_mod_crate_map.borrow().get(&emod_id).cloned()
    }
}

impl CrateMetadata {
    pub fn name(&self) -> Symbol {
        self.root.name
    }
    pub fn hash(&self) -> Svh {
        self.root.hash
    }
    pub fn disambiguator(&self) -> CrateDisambiguator {
        self.root.disambiguator
    }

    pub fn needs_allocator(&self, sess: &Session) -> bool {
        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
        attr::contains_name(&attrs, "needs_allocator")
    }

    pub fn has_global_allocator(&self) -> bool {
        self.root.has_global_allocator.clone()
    }

    pub fn has_default_lib_allocator(&self) -> bool {
        self.root.has_default_lib_allocator.clone()
    }

    pub fn is_panic_runtime(&self, sess: &Session) -> bool {
        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
        attr::contains_name(&attrs, "panic_runtime")
    }

    pub fn needs_panic_runtime(&self, sess: &Session) -> bool {
        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
        attr::contains_name(&attrs, "needs_panic_runtime")
    }

    pub fn is_compiler_builtins(&self, sess: &Session) -> bool {
        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
        attr::contains_name(&attrs, "compiler_builtins")
    }

    pub fn is_sanitizer_runtime(&self, sess: &Session) -> bool {
        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
        attr::contains_name(&attrs, "sanitizer_runtime")
    }

    pub fn is_profiler_runtime(&self, sess: &Session) -> bool {
        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
        attr::contains_name(&attrs, "profiler_runtime")
    }

    pub fn is_no_builtins(&self, sess: &Session) -> bool {
        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
        attr::contains_name(&attrs, "no_builtins")
    }

     pub fn has_copy_closures(&self, sess: &Session) -> bool {
        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
        attr::contains_feature_attr(&attrs, "copy_closures")
    }

    pub fn has_clone_closures(&self, sess: &Session) -> bool {
        let attrs = self.get_item_attrs(CRATE_DEF_INDEX, sess);
        attr::contains_feature_attr(&attrs, "clone_closures")
    }

    pub fn panic_strategy(&self) -> PanicStrategy {
        self.root.panic_strategy.clone()
    }
}
<|endoftext|>


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

use syntax_pos::symbol::Symbol;
use back::write::create_target_machine;
use llvm;
use rustc::session::Session;
use rustc::session::config::PrintRequest;
use libc::{c_int, c_char};
use std::ffi::CString;

use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Once;

pub fn init(sess: &Session) {
    unsafe {
        // Before we touch LLVM, make sure that multithreading is enabled.
        static POISONED: AtomicBool = AtomicBool::new(false);
        static INIT: Once = Once::new();
        INIT.call_once(|| {
            if llvm::LLVMStartMultithreaded() != 1 {
                // use an extra bool to make sure that all future usage of LLVM
                // cannot proceed despite the Once not running more than once.
                POISONED.store(true, Ordering::SeqCst);
            }

            configure_llvm(sess);
        });

        if POISONED.load(Ordering::SeqCst) {
            bug!("couldn't enable multi-threaded LLVM");
        }
    }
}

unsafe fn configure_llvm(sess: &Session) {
    let mut llvm_c_strs = Vec::new();
    let mut llvm_args = Vec::new();

    {
        let mut add = |arg: &str| {
            let s = CString::new(arg).unwrap();
            llvm_args.push(s.as_ptr());
            llvm_c_strs.push(s);
        };
        add("rustc"); // fake program name
        if sess.time_llvm_passes() { add("-time-passes"); }
        if sess.print_llvm_passes() { add("-debug-pass=Structure"); }

        for arg in &sess.opts.cg.llvm_args {
            add(&(*arg));
        }
    }

    llvm::LLVMInitializePasses();

    llvm::initialize_available_targets();

    llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int,
                                 llvm_args.as_ptr());
}

// WARNING: the features must be known to LLVM or the feature
// detection code will walk past the end of the feature array,
// leading to crashes.

const ARM_WHITELIST: &'static [&'static str] = &["neon\0", "vfp2\0", "vfp3\0", "vfp4\0"];

const AARCH64_WHITELIST: &'static [&'static str] = &["neon\0"];

const X86_WHITELIST: &'static [&'static str] = &["avx\0", "avx2\0", "bmi\0", "bmi2\0", "sse\0",
                                                 "sse2\0", "sse3\0", "sse4.1\0", "sse4.2\0",
                                                 "ssse3\0", "tbm\0", "lzcnt\0", "popcnt\0",
                                                 "sse4a\0", "rdrnd\0", "rdseed\0", "fma\0"];

const HEXAGON_WHITELIST: &'static [&'static str] = &["hvx\0", "hvx-double\0"];

const POWERPC_WHITELIST: &'static [&'static str] = &["altivec\0",
                                                     "power8-altivec\0", "power9-altivec\0",
                                                     "power8-vector\0", "power9-vector\0",
                                                     "vsx\0"];

pub fn target_features(sess: &Session) -> Vec<Symbol> {
    let target_machine = create_target_machine(sess);

    let whitelist = match &*sess.target.target.arch {
        "arm" => ARM_WHITELIST,
        "aarch64" => AARCH64_WHITELIST,
        "x86" | "x86_64" => X86_WHITELIST,
        "hexagon" => HEXAGON_WHITELIST,
        "powerpc" | "powerpc64" => POWERPC_WHITELIST,
        _ => &[],
    };

    let mut features = Vec::new();
    for feat in whitelist {
        assert_eq!(feat.chars().last(), Some('\0'));
        if unsafe { llvm::LLVMRustHasFeature(target_machine, feat.as_ptr() as *const c_char) } {
            features.push(Symbol::intern(&feat[..feat.len() - 1]));
        }
    }
    features
}

pub fn print_version() {
    unsafe {
        println!("LLVM version: {}.{}",
                 llvm::LLVMRustVersionMajor(), llvm::LLVMRustVersionMinor());
    }
}

pub fn print_passes() {
    unsafe { llvm::LLVMRustPrintPasses(); }
}

pub fn print(req: PrintRequest, sess: &Session) {
    let tm = create_target_machine(sess);
    unsafe {
        match req {
            PrintRequest::TargetCPUs => llvm::LLVMRustPrintTargetCPUs(tm),
            PrintRequest::TargetFeatures => llvm::LLVMRustPrintTargetFeatures(tm),
            _ => bug!("rustc_trans can't handle print request: {:?}", req),
        }
    }
}

pub fn enable_llvm_debug() {
    unsafe { llvm::LLVMRustSetDebug(1); }
}
<commit_msg>Auto merge of #45761 - gnzlbg:xsave_feature, r=alexcrichton<commit_after>// Copyright 2017 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.

use syntax_pos::symbol::Symbol;
use back::write::create_target_machine;
use llvm;
use rustc::session::Session;
use rustc::session::config::PrintRequest;
use libc::{c_int, c_char};
use std::ffi::CString;

use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Once;

pub fn init(sess: &Session) {
    unsafe {
        // Before we touch LLVM, make sure that multithreading is enabled.
        static POISONED: AtomicBool = AtomicBool::new(false);
        static INIT: Once = Once::new();
        INIT.call_once(|| {
            if llvm::LLVMStartMultithreaded() != 1 {
                // use an extra bool to make sure that all future usage of LLVM
                // cannot proceed despite the Once not running more than once.
                POISONED.store(true, Ordering::SeqCst);
            }

            configure_llvm(sess);
        });

        if POISONED.load(Ordering::SeqCst) {
            bug!("couldn't enable multi-threaded LLVM");
        }
    }
}

unsafe fn configure_llvm(sess: &Session) {
    let mut llvm_c_strs = Vec::new();
    let mut llvm_args = Vec::new();

    {
        let mut add = |arg: &str| {
            let s = CString::new(arg).unwrap();
            llvm_args.push(s.as_ptr());
            llvm_c_strs.push(s);
        };
        add("rustc"); // fake program name
        if sess.time_llvm_passes() { add("-time-passes"); }
        if sess.print_llvm_passes() { add("-debug-pass=Structure"); }

        for arg in &sess.opts.cg.llvm_args {
            add(&(*arg));
        }
    }

    llvm::LLVMInitializePasses();

    llvm::initialize_available_targets();

    llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int,
                                 llvm_args.as_ptr());
}

// WARNING: the features must be known to LLVM or the feature
// detection code will walk past the end of the feature array,
// leading to crashes.

const ARM_WHITELIST: &'static [&'static str] = &["neon\0", "vfp2\0", "vfp3\0", "vfp4\0"];

const AARCH64_WHITELIST: &'static [&'static str] = &["neon\0"];

const X86_WHITELIST: &'static [&'static str] = &["avx\0", "avx2\0", "bmi\0", "bmi2\0", "sse\0",
                                                 "sse2\0", "sse3\0", "sse4.1\0", "sse4.2\0",
                                                 "ssse3\0", "tbm\0", "lzcnt\0", "popcnt\0",
                                                 "sse4a\0", "rdrnd\0", "rdseed\0", "fma\0",
                                                 "xsave\0", "xsaveopt\0", "xsavec\0",
                                                 "xsaves\0"];

const HEXAGON_WHITELIST: &'static [&'static str] = &["hvx\0", "hvx-double\0"];

const POWERPC_WHITELIST: &'static [&'static str] = &["altivec\0",
                                                     "power8-altivec\0", "power9-altivec\0",
                                                     "power8-vector\0", "power9-vector\0",
                                                     "vsx\0"];

pub fn target_features(sess: &Session) -> Vec<Symbol> {
    let target_machine = create_target_machine(sess);

    let whitelist = match &*sess.target.target.arch {
        "arm" => ARM_WHITELIST,
        "aarch64" => AARCH64_WHITELIST,
        "x86" | "x86_64" => X86_WHITELIST,
        "hexagon" => HEXAGON_WHITELIST,
        "powerpc" | "powerpc64" => POWERPC_WHITELIST,
        _ => &[],
    };

    let mut features = Vec::new();
    for feat in whitelist {
        assert_eq!(feat.chars().last(), Some('\0'));
        if unsafe { llvm::LLVMRustHasFeature(target_machine, feat.as_ptr() as *const c_char) } {
            features.push(Symbol::intern(&feat[..feat.len() - 1]));
        }
    }
    features
}

pub fn print_version() {
    unsafe {
        println!("LLVM version: {}.{}",
                 llvm::LLVMRustVersionMajor(), llvm::LLVMRustVersionMinor());
    }
}

pub fn print_passes() {
    unsafe { llvm::LLVMRustPrintPasses(); }
}

pub fn print(req: PrintRequest, sess: &Session) {
    let tm = create_target_machine(sess);
    unsafe {
        match req {
            PrintRequest::TargetCPUs => llvm::LLVMRustPrintTargetCPUs(tm),
            PrintRequest::TargetFeatures => llvm::LLVMRustPrintTargetFeatures(tm),
            _ => bug!("rustc_trans can't handle print request: {:?}", req),
        }
    }
}

pub fn enable_llvm_debug() {
    unsafe { llvm::LLVMRustSetDebug(1); }
}
<|endoftext|>


<commit_before>// src/models/transaction_model.rs

/// Transaction Model

// Import Modules
// External
use ::bson::oid::ObjectId;
use ::chrono::{DateTime, Duration, Local, TimeZone};
use ::chrono::offset::utc::UTC;
// Utilities
use ::common::validation::validators as Validators;
use ::common::validation::validation_result::{ValidationResult};

/// Transaction
#[derive(Clone)]
pub struct TransactionModel {
    pub id: Option<ObjectId>,
    pub money_map_id: Option<ObjectId>,
    pub account_id: Option<ObjectId>,
    pub datetime: Option<DateTime<UTC>>,
    pub payee: Option<String>,
    pub description: Option<String>,
    pub category_id: Option<ObjectId>,
    pub amount: Option<f64>,
    pub transaction_type: Option<String>,
    pub status: Option<String>
}

#[derive(RustcDecodable, RustcEncodable)]
pub struct PubTransactionModel {
    pub id: Option<ObjectId>,
    pub money_map_id: Option<ObjectId>,
    pub account_id: Option<ObjectId>,
    pub datetime: Option<String>,
    pub payee: Option<String>,
    pub description: Option<String>,
    pub category_id: Option<ObjectId>,
    pub amount: Option<f64>,
    pub transaction_type: Option<String>,
    pub status: Option<String>
}

// Transaction Model Methods
impl TransactionModel{

    /// Get ID
    ///
    /// # Arguments
    /// &self
    ///
    /// # Returns
    /// 'Option<ObjectId>' - id
    pub fn get_id(&self) -> Option<ObjectId>{
        self.id.clone()
    }

    /// Set ID
    ///
    /// # Arguments
    /// &self
    pub fn set_id(&mut self, id: ObjectId) {
        self.id = Some(id);
    }

    /// Get Payee
    ///
    /// # Arguments
    /// &self
    ///
    /// # Returns
    /// 'Option<String>' - Entity
    pub fn get_payee(&self) -> Option<String>{
        self.payee.clone()
    }

    /// Get Description
    ///
    /// # Arguments
    /// &self
    ///
    /// # Returns
    /// 'Option<String>' - description
    pub fn get_description(&self) -> Option<String>{
        self.description.clone()
    }

    /// Validate Transaction
    ///
    /// # Arguments
    /// self
    ///
    /// # Returns
    /// 'ValidationResult' - validation result
    pub fn validate(&self) -> ValidationResult{

        //validate Transaction
        let mut validation_result = ValidationResult::new();
        if !Validators::not_empty_string(self.payee.clone()){
            validation_result.add_error("payee".to_string(), "Payee is required.".to_string());
        }

        validation_result
    }//end validate
}
<commit_msg>Add transaction model getter methods<commit_after>// src/models/transaction_model.rs

/// Transaction Model

// Import Modules
// External
use ::bson::oid::ObjectId;
use ::chrono::{DateTime, Duration, Local, TimeZone};
use ::chrono::offset::utc::UTC;
// Utilities
use ::common::validation::validators as Validators;
use ::common::validation::validation_result::{ValidationResult};

/// Transaction
#[derive(Clone)]
pub struct TransactionModel {
    pub id: Option<ObjectId>,
    pub money_map_id: Option<ObjectId>,
    pub account_id: Option<ObjectId>,
    pub datetime: Option<DateTime<UTC>>,
    pub payee: Option<String>,
    pub description: Option<String>,
    pub category_id: Option<ObjectId>,
    pub amount: Option<f64>,
    pub transaction_type: Option<String>,
    pub status: Option<String>
}

#[derive(RustcDecodable, RustcEncodable)]
pub struct PubTransactionModel {
    pub id: Option<ObjectId>,
    pub money_map_id: Option<ObjectId>,
    pub account_id: Option<ObjectId>,
    pub datetime: Option<String>,
    pub payee: Option<String>,
    pub description: Option<String>,
    pub category_id: Option<ObjectId>,
    pub amount: Option<f64>,
    pub transaction_type: Option<String>,
    pub status: Option<String>
}

// Transaction Model Methods
impl TransactionModel{

    /// Create TransactionModel from PubTransactionModel
    ///
    /// # Arguments
    /// account - PubTransactionModel
    ///
    /// # Returns
    /// 'TransactionModel'
    pub fn new(mut transaction: PubTransactionModel) -> TransactionModel{
        TransactionModel{
            id: transaction.get_id(),
            money_map_id: transaction.get_money_map_id(),
            account_id: transaction.get_account_id(),
            datetime: None,
            payee: transaction.get_payee(),
            description: transaction.get_description(),
            category_id: transaction.get_category_id(),
            amount: transaction.get_amount(),
            transaction_type: transaction.get_transaction_type(),
            status: transaction.get_status()
        }
    }

    /// Get ID
    ///
    /// # Arguments
    /// &self
    ///
    /// # Returns
    /// 'Option<ObjectId>' - ID
    pub fn get_id(&self) -> Option<ObjectId>{
        self.id.clone()
    }

    /// Set ID
    ///
    /// # Arguments
    /// &self
    pub fn set_id(&mut self, id: ObjectId) {
        self.id = Some(id);
    }

    /// Get Money Map ID
    ///
    /// # Arguments
    /// &self
    ///
    /// # Returns
    /// 'Option<ObjectId>' - Money Map ID
    pub fn get_money_map_id(&self) -> Option<ObjectId>{
        self.money_map_id.clone()
    }

    /// Get Account ID
    ///
    /// # Arguments
    /// &self
    ///
    /// # Returns
    /// 'Option<ObjectId>' - Account ID
    pub fn get_account_id(&self) -> Option<ObjectId>{
        self.account_id.clone()
    }

    /// Get Datetime
    ///
    /// # Arguments
    /// &self
    ///
    /// # Returns
    /// 'Option<DateTime<UTC>>' - Datetime
    pub fn get_datetime(&self) -> Option<DateTime<UTC>>{
        self.datetime.clone()
    }

    /// Get Payee
    ///
    /// # Arguments
    /// &self
    ///
    /// # Returns
    /// 'Option<String>' - Entity
    pub fn get_payee(&self) -> Option<String>{
        self.payee.clone()
    }

    /// Get Description
    ///
    /// # Arguments
    /// &self
    ///
    /// # Returns
    /// 'Option<String>' - description
    pub fn get_description(&self) -> Option<String>{
        self.description.clone()
    }

    /// Get Category ID
    ///
    /// # Arguments
    /// &self
    ///
    /// # Returns
    /// 'Option<ObjectId>' - Category ID
    pub fn get_category_id(&self) -> Option<ObjectId>{
        self.category_id.clone()
    }

    /// Get Amount
    ///
    /// # Arguments
    /// &self
    ///
    /// # Returns
    /// 'Option<f64>' - Amount
    pub fn get_amount(&self) -> Option<f64>{
        self.amount.clone()
    }

    /// Get Transaction Type
    ///
    /// # Arguments
    /// &self
    ///
    /// # Returns
    /// 'Option<String>' - Transaction Type
    pub fn get_transaction_type(&self) -> Option<String>{
        self.transaction_type.clone()
    }

    /// Get Status
    ///
    /// # Arguments
    /// &self
    ///
    /// # Returns
    /// 'Option<String>' - Status
    pub fn get_status(&self) -> Option<String>{
        self.status.clone()
    }
}

// Pub Transaction Model Methods
impl PubTransactionModel{

    /// Create PubTransactionModel from TransactionModel
    ///
    /// # Arguments
    /// account - TransactionModel
    ///
    /// # Returns
    /// 'PubTransactionModel'
    pub fn new(mut transaction: TransactionModel) -> PubTransactionModel{
        PubTransactionModel{
            id: transaction.get_id(),
            money_map_id: transaction.get_id(),
            account_id: transaction.get_id(),
            datetime: match transaction.get_datetime(){
                Some(timestamp) => {
                    Some(timestamp.to_string())
                },
                None => None
            },
            payee: transaction.get_payee(),
            description: transaction.get_description(),
            category_id: transaction.get_category_id(),
            amount: transaction.get_amount(),
            transaction_type: transaction.get_transaction_type(),
            status: transaction.get_status()
        }
    }

    /// Get ID
    ///
    /// # Arguments
    /// &self
    ///
    /// # Returns
    /// 'Option<ObjectId>' - ID
    pub fn get_id(&self) -> Option<ObjectId>{
        self.id.clone()
    }

    /// Get Money Map ID
    ///
    /// # Arguments
    /// &self
    ///
    /// # Returns
    /// 'Option<ObjectId>' - Money Map ID
    pub fn get_money_map_id(&self) -> Option<ObjectId>{
        self.money_map_id.clone()
    }

    /// Get Account ID
    ///
    /// # Arguments
    /// &self
    ///
    /// # Returns
    /// 'Option<ObjectId>' - Account ID
    pub fn get_account_id(&self) -> Option<ObjectId>{
        self.account_id.clone()
    }

    /// Get Datetime
    ///
    /// # Arguments
    /// &self
    ///
    /// # Returns
    /// 'Option<String>' - Datetime
    pub fn get_datetime(&self) -> Option<String>{
        self.datetime.clone()
    }

    /// Get Payee
    ///
    /// # Arguments
    /// &self
    ///
    /// # Returns
    /// 'Option<String>' - Entity
    pub fn get_payee(&self) -> Option<String>{
        self.payee.clone()
    }

    /// Get Description
    ///
    /// # Arguments
    /// &self
    ///
    /// # Returns
    /// 'Option<String>' - description
    pub fn get_description(&self) -> Option<String>{
        self.description.clone()
    }

    /// Get Category ID
    ///
    /// # Arguments
    /// &self
    ///
    /// # Returns
    /// 'Option<ObjectId>' - Category ID
    pub fn get_category_id(&self) -> Option<ObjectId>{
        self.category_id.clone()
    }

    /// Get Amount
    ///
    /// # Arguments
    /// &self
    ///
    /// # Returns
    /// 'Option<f64>' - Amount
    pub fn get_amount(&self) -> Option<f64>{
        self.amount.clone()
    }

    /// Get Transaction Type
    ///
    /// # Arguments
    /// &self
    ///
    /// # Returns
    /// 'Option<String>' - Transaction Type
    pub fn get_transaction_type(&self) -> Option<String>{
        self.transaction_type.clone()
    }

    /// Get Status
    ///
    /// # Arguments
    /// &self
    ///
    /// # Returns
    /// 'Option<String>' - Status
    pub fn get_status(&self) -> Option<String>{
        self.status.clone()
    }

    /// Validate Transaction
    ///
    /// # Arguments
    /// self
    ///
    /// # Returns
    /// 'ValidationResult' - validation result
    pub fn validate(&self) -> ValidationResult{

        //validate Transaction
        let mut validation_result = ValidationResult::new();
        if !Validators::not_empty_string(self.payee.clone()){
            validation_result.add_error("payee".to_string(), "Payee is required.".to_string());
        }

        validation_result
    }//end validate
}
<|endoftext|>