<commit_before>// Copyright 2013-2015, The Rust-GNOME 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>

//! Generic values — A polymorphic type that can hold values of any other type

use std::mem;
use libc::c_char;
use ffi;
use super::{to_bool, to_gboolean};
use types::Type;
use translate::*;

pub trait ValuePublic {
    fn get(gvalue: &Value) -> Self;
    fn set(&self, gvalue: &mut Value);
}

// Possible improvment : store a function pointer inside the struct and make the struct templated
pub struct Value {
    inner: ffi::GValue,
}

impl Value {
    pub fn new() -> Value {
        unsafe { Value { inner: mem::zeroed() } }
    }

    pub fn init(&mut self, _type: Type) {
        unsafe { ffi::g_value_init(&mut self.inner, _type.to_glib()) }
    }

    pub fn reset(&mut self) {
        unsafe { ffi::g_value_reset(&mut self.inner) }
    }

    pub fn unset(&mut self) {
        unsafe { ffi::g_value_unset(&mut self.inner) }
    }

    pub fn strdup_value_contents(&mut self) -> Option<String> {
        unsafe {
            from_glib_full(ffi::g_strdup_value_contents(&mut self.inner) as *const c_char)
        }
    }

    fn set_boolean(&mut self, v_boolean: bool) {
        unsafe { ffi::g_value_set_boolean(&mut self.inner, to_gboolean(v_boolean)) }
    }

    fn get_boolean(&self) -> bool {
        unsafe { to_bool(ffi::g_value_get_boolean(&self.inner)) }
    }

    fn set_schar(&mut self, v_char: i8) {
        unsafe { ffi::g_value_set_schar(&mut self.inner, v_char) }
    }

    fn get_schar(&self) -> i8 {
        unsafe { ffi::g_value_get_schar(&self.inner) }
    }

    fn set_uchar(&mut self, v_uchar: u8) {
        unsafe { ffi::g_value_set_uchar(&mut self.inner, v_uchar) }
    }

    fn get_uchar(&self) -> u8 {
        unsafe { ffi::g_value_get_uchar(&self.inner) }
    }

    fn set_int(&mut self, v_int: i32) {
        unsafe { ffi::g_value_set_int(&mut self.inner, v_int) }
    }

    fn get_int(&self) -> i32 {
        unsafe { ffi::g_value_get_int(&self.inner) }
    }

    fn set_uint(&mut self, v_uint: u32) {
        unsafe { ffi::g_value_set_uint(&mut self.inner, v_uint) }
    }

    fn get_uint(&self) -> u32 {
        unsafe { ffi::g_value_get_uint(&self.inner) }
    }

    pub fn set_long(&mut self, v_long: i64) {
        unsafe { ffi::g_value_set_long(&mut self.inner, v_long as ::libc::c_long) }
    }

    pub fn get_long(&self) -> i64 {
        unsafe { ffi::g_value_get_long(&self.inner) as i64 }
    }

    pub fn set_ulong(&mut self, v_ulong: u64) {
        unsafe { ffi::g_value_set_ulong(&mut self.inner, v_ulong as ::libc::c_ulong) }
    }

    pub fn get_ulong(&self) -> u64 {
        unsafe { ffi::g_value_get_ulong(&self.inner) as u64 }
    }

    fn set_int64(&mut self, v_int64: i64) {
        unsafe { ffi::g_value_set_int64(&mut self.inner, v_int64) }
    }

    fn get_int64(&self) -> i64 {
        unsafe { ffi::g_value_get_int64(&self.inner) }
    }

    fn set_uint64(&mut self, v_uint64: u64) {
        unsafe { ffi::g_value_set_uint64(&mut self.inner, v_uint64) }
    }

    fn get_uint64(&self) -> u64 {
        unsafe { ffi::g_value_get_uint64(&self.inner) }
    }

    fn set_float(&mut self, v_float: f32) {
        unsafe { ffi::g_value_set_float(&mut self.inner, v_float) }
    }

    fn get_float(&self) -> f32 {
        unsafe { ffi::g_value_get_float(&self.inner) }
    }

    fn set_double(&mut self, v_double: f64) {
        unsafe { ffi::g_value_set_double(&mut self.inner, v_double) }
    }

    fn get_double(&self) -> f64 {
        unsafe { ffi::g_value_get_double(&self.inner) }
    }

    // FIXME shouldn't be like that
    pub fn set_enum(&mut self, v_enum: Type) {
        unsafe { ffi::g_value_set_enum(&mut self.inner, v_enum.to_glib()) }
    }

    // FIXME shouldn't be like that
    pub fn get_enum(&self) -> Type {
        unsafe { from_glib(ffi::g_value_get_enum(&self.inner)) }
    }

    // FIXME shouldn't be like that
    pub fn set_flags(&mut self, v_flags: Type) {
        unsafe { ffi::g_value_set_flags(&mut self.inner, v_flags.to_glib()) }
    }

    // FIXME shouldn't be like that
    pub fn get_flags(&self) -> Type {
        unsafe { from_glib(ffi::g_value_get_flags(&self.inner)) }
    }

    fn set_string(&mut self, v_string: &str) {
        unsafe {
            ffi::g_value_set_string(&mut self.inner, v_string.to_glib_none().0);
        }
    }

    pub fn get_string(&self) -> Option<String> {
        unsafe {
            from_glib_none(ffi::g_value_get_string(&self.inner))
        }
    }

    pub fn set_boxed<T>(&mut self, v_box: &T) {
        unsafe { ffi::g_value_set_boxed(&mut self.inner, ::std::mem::transmute(v_box)) }
    }

    /*pub fn take_boxed<T>(&self, v_box: &T) {
        unsafe { ffi::g_value_take_boxed(&mut self.inner, ::std::mem::transmute(v_box)) }
    }*/

    pub fn get_boxed<'r, T>(&'r self) -> &'r T {
        unsafe { ::std::mem::transmute(ffi::g_value_get_boxed(&self.inner)) }
    }

    /*pub fn dup_boxed<'r, T>(&'r self) -> &'r T {
        unsafe { ::std::mem::transmute(ffi::g_value_dup_boxed(&mut self.inner)) }
    }*/

    pub fn set_pointer<T>(&mut self, v_pointer: &T) {
        unsafe { ffi::g_value_set_pointer(&mut self.inner, ::std::mem::transmute(v_pointer)) }
    }

    pub fn get_pointer<'r, T>(&'r self) -> &'r T {
        unsafe { ::std::mem::transmute(ffi::g_value_get_pointer(&self.inner)) }
    }

    pub fn set_object<T>(&mut self, v_object: &T) {
        unsafe { ffi::g_value_set_object(&mut self.inner, ::std::mem::transmute(v_object)) }
    }

    pub fn get_object<'r, T>(&'r self) -> &'r T {
        unsafe { ::std::mem::transmute(ffi::g_value_get_object(&self.inner)) }
    }

    // FIXME shouldn't be like that
    fn set_gtype(&mut self, v_gtype: Type) {
        unsafe { ffi::g_value_set_gtype(&mut self.inner, v_gtype.to_glib()) }
    }

    // FIXME shouldn't be like that
    fn get_gtype(&self) -> Type {
        unsafe { from_glib(ffi::g_value_get_gtype(&self.inner)) }
    }

    pub fn set<T: ValuePublic>(&mut self, val: &T) {
        val.set(self);
    }

    pub fn get<T: ValuePublic>(&self) -> T {
        ValuePublic::get(self)
    }

    pub fn compatible(src_type: Type, dest_type: Type) -> bool {
        unsafe { to_bool(ffi::g_value_type_compatible(src_type.to_glib(), dest_type.to_glib())) }
    }

    pub fn transformable(src_type: Type, dest_type: Type) -> bool {
        unsafe { to_bool(ffi::g_value_type_transformable(src_type.to_glib(), dest_type.to_glib())) }
    }

    pub fn as_ptr(&self) -> *const ffi::GValue {
        &self.inner
    }

    pub fn as_mut_ptr(&mut self) -> *mut ffi::GValue {
        &mut self.inner
    }
}

impl Drop for Value {
    fn drop(&mut self) {
        self.unset();
    }
}

impl ValuePublic for i32 {
    fn get(gvalue: &Value) -> i32 {
        gvalue.get_int()
    }

    fn set(&self, gvalue: &mut Value) {
        gvalue.set_int(*self)
    }
}

impl ValuePublic for u32 {
    fn get(gvalue: &Value) -> u32 {
        gvalue.get_uint()
    }

    fn set(&self, gvalue: &mut Value) {
        gvalue.set_uint(*self)
    }
}

impl ValuePublic for i64 {
    fn get(gvalue: &Value) -> i64 {
        gvalue.get_int64()
    }

    fn set(&self, gvalue: &mut Value) {
        gvalue.set_int64(*self)
    }
}

impl ValuePublic for u64 {
    fn get(gvalue: &Value) -> u64 {
        gvalue.get_uint64()
    }

    fn set(&self, gvalue: &mut Value) {
        gvalue.set_uint64(*self)
    }
}

impl ValuePublic for bool {
    fn get(gvalue: &Value) -> bool {
        gvalue.get_boolean()
    }

    fn set(&self, gvalue: &mut Value) {
        gvalue.set_boolean(*self)
    }
}

impl ValuePublic for i8 {
    fn get(gvalue: &Value) -> i8 {
        gvalue.get_schar()
    }

    fn set(&self, gvalue: &mut Value) {
        gvalue.set_schar(*self)
    }
}

impl ValuePublic for u8 {
    fn get(gvalue: &Value) -> u8 {
        gvalue.get_uchar()
    }

    fn set(&self, gvalue: &mut Value) {
        gvalue.set_uchar(*self)
    }
}

impl ValuePublic for f32 {
    fn get(gvalue: &Value) -> f32 {
        gvalue.get_float()
    }

    fn set(&self, gvalue: &mut Value) {
        gvalue.set_float(*self)
    }
}

impl ValuePublic for f64 {
    fn get(gvalue: &Value) -> f64 {
        gvalue.get_double()
    }

    fn set(&self, gvalue: &mut Value) {
        gvalue.set_double(*self)
    }
}

impl ValuePublic for Type {
    fn get(gvalue: &Value) -> Type {
        gvalue.get_gtype()
    }

    fn set(&self, gvalue: &mut Value) {
        gvalue.set_gtype(*self)
    }
}

impl ValuePublic for String {
    fn get(gvalue: &Value) -> String {
        match gvalue.get_string() {
            Some(s) => s,
            None => String::new()
        }
    }

    fn set(&self, gvalue: &mut Value) {
        gvalue.set_string(self.as_ref())
    }
}
<commit_msg>Add documentation<commit_after>// Copyright 2013-2015, The Rust-GNOME 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>

//! Generic values — A polymorphic type that can hold values of any other type

use std::mem;
use libc::c_char;
use ffi;
use super::{to_bool, to_gboolean};
use types::Type;
use translate::*;

pub trait ValuePublic {
    fn get(gvalue: &Value) -> Self;
    fn set(&self, gvalue: &mut Value);
}

/// Possible improvement : store a function pointer inside the struct and make the struct
/// templated
pub struct Value {
    inner: ffi::GValue,
}

impl Value {
    pub fn new() -> Value {
        unsafe { Value { inner: mem::zeroed() } }
    }

    /// Initializes value with the default value of type .
    pub fn init(&mut self, _type: Type) {
        unsafe { ffi::g_value_init(&mut self.inner, _type.to_glib()) }
    }

    /// Clears the current value in value and resets it to the default value (as if the
    /// value had just been initialized).
    pub fn reset(&mut self) {
        unsafe { ffi::g_value_reset(&mut self.inner) }
    }

    /// Clears the current value in value and "unsets" the type, this releases all resources
    /// associated with this GValue. An unset value is the same as an uninitialized (zero-filled)
    /// GValue structure.
    pub fn unset(&mut self) {
        unsafe { ffi::g_value_unset(&mut self.inner) }
    }

    /// Return a newly allocated string, which describes the contents of a GValue. The main
    /// purpose of this function is to describe GValue contents for debugging output, the way
    /// in which the contents are described may change between different GLib versions.
    pub fn strdup_value_contents(&mut self) -> Option<String> {
        unsafe {
            from_glib_full(ffi::g_strdup_value_contents(&mut self.inner) as *const c_char)
        }
    }

    /// Set the contents of a G_TYPE_BOOLEAN GValue to v_boolean.
    fn set_boolean(&mut self, v_boolean: bool) {
        unsafe { ffi::g_value_set_boolean(&mut self.inner, to_gboolean(v_boolean)) }
    }

    /// Get the contents of a G_TYPE_BOOLEAN GValue.
    fn get_boolean(&self) -> bool {
        unsafe { to_bool(ffi::g_value_get_boolean(&self.inner)) }
    }

    /// Set the contents of a G_TYPE_CHAR GValue to v_char .
    fn set_schar(&mut self, v_char: i8) {
        unsafe { ffi::g_value_set_schar(&mut self.inner, v_char) }
    }

    /// Get the contents of a G_TYPE_CHAR GValue.
    fn get_schar(&self) -> i8 {
        unsafe { ffi::g_value_get_schar(&self.inner) }
    }

    /// Set the contents of a G_TYPE_UCHAR GValue to v_uchar .
    fn set_uchar(&mut self, v_uchar: u8) {
        unsafe { ffi::g_value_set_uchar(&mut self.inner, v_uchar) }
    }

    /// Get the contents of a G_TYPE_UCHAR GValue.
    fn get_uchar(&self) -> u8 {
        unsafe { ffi::g_value_get_uchar(&self.inner) }
    }

    /// Set the contents of a G_TYPE_INT GValue to v_int.
    fn set_int(&mut self, v_int: i32) {
        unsafe { ffi::g_value_set_int(&mut self.inner, v_int) }
    }

    /// Get the contents of a G_TYPE_INT GValue.
    fn get_int(&self) -> i32 {
        unsafe { ffi::g_value_get_int(&self.inner) }
    }

    /// Set the contents of a G_TYPE_UINT GValue to v_uint .
    fn set_uint(&mut self, v_uint: u32) {
        unsafe { ffi::g_value_set_uint(&mut self.inner, v_uint) }
    }

    /// Get the contents of a G_TYPE_UINT GValue.
    fn get_uint(&self) -> u32 {
        unsafe { ffi::g_value_get_uint(&self.inner) }
    }

    /// Set the contents of a G_TYPE_LONG GValue to v_long .
    pub fn set_long(&mut self, v_long: i64) {
        unsafe { ffi::g_value_set_long(&mut self.inner, v_long as ::libc::c_long) }
    }

    /// Get the contents of a G_TYPE_LONG GValue.
    pub fn get_long(&self) -> i64 {
        unsafe { ffi::g_value_get_long(&self.inner) as i64 }
    }

    /// Set the contents of a G_TYPE_ULONG GValue to v_ulong .
    pub fn set_ulong(&mut self, v_ulong: u64) {
        unsafe { ffi::g_value_set_ulong(&mut self.inner, v_ulong as ::libc::c_ulong) }
    }

    /// Get the contents of a G_TYPE_ULONG GValue.
    pub fn get_ulong(&self) -> u64 {
        unsafe { ffi::g_value_get_ulong(&self.inner) as u64 }
    }

    /// Set the contents of a G_TYPE_INT64 GValue to v_int64 .
    fn set_int64(&mut self, v_int64: i64) {
        unsafe { ffi::g_value_set_int64(&mut self.inner, v_int64) }
    }

    /// Get the contents of a G_TYPE_INT64 GValue.
    fn get_int64(&self) -> i64 {
        unsafe { ffi::g_value_get_int64(&self.inner) }
    }

    /// Set the contents of a G_TYPE_UINT64 GValue to v_uint64 .
    fn set_uint64(&mut self, v_uint64: u64) {
        unsafe { ffi::g_value_set_uint64(&mut self.inner, v_uint64) }
    }

    /// Get the contents of a G_TYPE_UINT64 GValue.
    fn get_uint64(&self) -> u64 {
        unsafe { ffi::g_value_get_uint64(&self.inner) }
    }

    /// Set the contents of a G_TYPE_FLOAT GValue to v_float .
    fn set_float(&mut self, v_float: f32) {
        unsafe { ffi::g_value_set_float(&mut self.inner, v_float) }
    }

    /// Get the contents of a G_TYPE_FLOAT GValue.
    fn get_float(&self) -> f32 {
        unsafe { ffi::g_value_get_float(&self.inner) }
    }

    /// Set the contents of a G_TYPE_DOUBLE GValue to v_double .
    fn set_double(&mut self, v_double: f64) {
        unsafe { ffi::g_value_set_double(&mut self.inner, v_double) }
    }

    /// Get the contents of a G_TYPE_DOUBLE GValue.
    fn get_double(&self) -> f64 {
        unsafe { ffi::g_value_get_double(&self.inner) }
    }

    /// Set the contents of a G_TYPE_ENUM GValue to v_enum .
    // FIXME shouldn't be like that
    pub fn set_enum(&mut self, v_enum: Type) {
        unsafe { ffi::g_value_set_enum(&mut self.inner, v_enum.to_glib()) }
    }

    /// Get the contents of a G_TYPE_ENUM GValue.
    // FIXME shouldn't be like that
    pub fn get_enum(&self) -> Type {
        unsafe { from_glib(ffi::g_value_get_enum(&self.inner)) }
    }

    /// Set the contents of a G_TYPE_FLAGS GValue to v_flags .
    // FIXME shouldn't be like that
    pub fn set_flags(&mut self, v_flags: Type) {
        unsafe { ffi::g_value_set_flags(&mut self.inner, v_flags.to_glib()) }
    }

    /// Get the contents of a G_TYPE_FLAGS GValue.
    // FIXME shouldn't be like that
    pub fn get_flags(&self) -> Type {
        unsafe { from_glib(ffi::g_value_get_flags(&self.inner)) }
    }

    /// Set the contents of a G_TYPE_STRING GValue to v_string .
    fn set_string(&mut self, v_string: &str) {
        unsafe {
            ffi::g_value_set_string(&mut self.inner, v_string.to_glib_none().0);
        }
    }

    /// Get the contents of a G_TYPE_STRING GValue.
    pub fn get_string(&self) -> Option<String> {
        unsafe {
            from_glib_none(ffi::g_value_get_string(&self.inner))
        }
    }

    /// Set the contents of a G_TYPE_BOXED derived GValue to v_boxed .
    pub fn set_boxed<T>(&mut self, v_box: &T) {
        unsafe { ffi::g_value_set_boxed(&mut self.inner, ::std::mem::transmute(v_box)) }
    }

    /*pub fn take_boxed<T>(&self, v_box: &T) {
        unsafe { ffi::g_value_take_boxed(&mut self.inner, ::std::mem::transmute(v_box)) }
    }*/

    /// Get the contents of a G_TYPE_BOXED derived GValue.
    pub fn get_boxed<'r, T>(&'r self) -> &'r T {
        unsafe { ::std::mem::transmute(ffi::g_value_get_boxed(&self.inner)) }
    }

    /*pub fn dup_boxed<'r, T>(&'r self) -> &'r T {
        unsafe { ::std::mem::transmute(ffi::g_value_dup_boxed(&mut self.inner)) }
    }*/

    /// Set the contents of a pointer GValue to v_pointer .
    pub fn set_pointer<T>(&mut self, v_pointer: &T) {
        unsafe { ffi::g_value_set_pointer(&mut self.inner, ::std::mem::transmute(v_pointer)) }
    }

    /// Get the contents of a pointer GValue.
    pub fn get_pointer<'r, T>(&'r self) -> &'r T {
        unsafe { ::std::mem::transmute(ffi::g_value_get_pointer(&self.inner)) }
    }

    /// Set the contents of a G_TYPE_OBJECT derived GValue to v_object .
    ///
    /// g_value_set_object() increases the reference count of v_object (the GValue holds a reference
    /// to v_object ). If you do not wish to increase the reference count of the object (i.e. you
    /// wish to pass your current reference to the GValue because you no longer need it), use
    /// g_value_take_object() instead.
    ///
    /// It is important that your GValue holds a reference to v_object (either its own, or one it
    /// has taken) to ensure that the object won't be destroyed while the GValue still exists).
    pub fn set_object<T>(&mut self, v_object: &T) {
        unsafe { ffi::g_value_set_object(&mut self.inner, ::std::mem::transmute(v_object)) }
    }

    /// Get the contents of a G_TYPE_OBJECT derived GValue.
    pub fn get_object<'r, T>(&'r self) -> &'r T {
        unsafe { ::std::mem::transmute(ffi::g_value_get_object(&self.inner)) }
    }

    /// Set the contents of a G_TYPE_GTYPE GValue to v_gtype .
    // FIXME shouldn't be like that
    fn set_gtype(&mut self, v_gtype: Type) {
        unsafe { ffi::g_value_set_gtype(&mut self.inner, v_gtype.to_glib()) }
    }

    /// Get the contents of a G_TYPE_GTYPE GValue.
    // FIXME shouldn't be like that
    fn get_gtype(&self) -> Type {
        unsafe { from_glib(ffi::g_value_get_gtype(&self.inner)) }
    }

    pub fn set<T: ValuePublic>(&mut self, val: &T) {
        val.set(self);
    }

    pub fn get<T: ValuePublic>(&self) -> T {
        ValuePublic::get(self)
    }

    /// Returns whether a GValue of type src_type can be copied into a GValue of type dest_type .
    pub fn compatible(src_type: Type, dest_type: Type) -> bool {
        unsafe { to_bool(ffi::g_value_type_compatible(src_type.to_glib(), dest_type.to_glib())) }
    }

    /// Check whether g_value_transform() is able to transform values of type src_type into
    /// values of type dest_type . Note that for the types to be transformable, they must be
    /// compatible and a transform function must be registered.
    pub fn transformable(src_type: Type, dest_type: Type) -> bool {
        unsafe { to_bool(ffi::g_value_type_transformable(src_type.to_glib(), dest_type.to_glib())) }
    }

    pub fn as_ptr(&self) -> *const ffi::GValue {
        &self.inner
    }

    pub fn as_mut_ptr(&mut self) -> *mut ffi::GValue {
        &mut self.inner
    }
}

impl Drop for Value {
    fn drop(&mut self) {
        self.unset();
    }
}

impl ValuePublic for i32 {
    fn get(gvalue: &Value) -> i32 {
        gvalue.get_int()
    }

    fn set(&self, gvalue: &mut Value) {
        gvalue.set_int(*self)
    }
}

impl ValuePublic for u32 {
    fn get(gvalue: &Value) -> u32 {
        gvalue.get_uint()
    }

    fn set(&self, gvalue: &mut Value) {
        gvalue.set_uint(*self)
    }
}

impl ValuePublic for i64 {
    fn get(gvalue: &Value) -> i64 {
        gvalue.get_int64()
    }

    fn set(&self, gvalue: &mut Value) {
        gvalue.set_int64(*self)
    }
}

impl ValuePublic for u64 {
    fn get(gvalue: &Value) -> u64 {
        gvalue.get_uint64()
    }

    fn set(&self, gvalue: &mut Value) {
        gvalue.set_uint64(*self)
    }
}

impl ValuePublic for bool {
    fn get(gvalue: &Value) -> bool {
        gvalue.get_boolean()
    }

    fn set(&self, gvalue: &mut Value) {
        gvalue.set_boolean(*self)
    }
}

impl ValuePublic for i8 {
    fn get(gvalue: &Value) -> i8 {
        gvalue.get_schar()
    }

    fn set(&self, gvalue: &mut Value) {
        gvalue.set_schar(*self)
    }
}

impl ValuePublic for u8 {
    fn get(gvalue: &Value) -> u8 {
        gvalue.get_uchar()
    }

    fn set(&self, gvalue: &mut Value) {
        gvalue.set_uchar(*self)
    }
}

impl ValuePublic for f32 {
    fn get(gvalue: &Value) -> f32 {
        gvalue.get_float()
    }

    fn set(&self, gvalue: &mut Value) {
        gvalue.set_float(*self)
    }
}

impl ValuePublic for f64 {
    fn get(gvalue: &Value) -> f64 {
        gvalue.get_double()
    }

    fn set(&self, gvalue: &mut Value) {
        gvalue.set_double(*self)
    }
}

impl ValuePublic for Type {
    fn get(gvalue: &Value) -> Type {
        gvalue.get_gtype()
    }

    fn set(&self, gvalue: &mut Value) {
        gvalue.set_gtype(*self)
    }
}

impl ValuePublic for String {
    fn get(gvalue: &Value) -> String {
        match gvalue.get_string() {
            Some(s) => s,
            None => String::new()
        }
    }

    fn set(&self, gvalue: &mut Value) {
        gvalue.set_string(self.as_ref())
    }
}
<|endoftext|>


<commit_before>#[derive(Clone, Debug, PartialEq)]
pub enum Integer {
    /// Every non-negative integer is treated as u64, even if it fits in i64.
    U64(u64),
    /// Every negative integer is treated as i64.
    I64(i64),
}

#[derive(Clone, Debug, PartialEq)]
pub enum Float {
    F32(f32),
    F64(f64),
}

#[derive(Clone, Debug, PartialEq)]
pub enum Value {
    /// Nil represents nil.
    Nil,
    /// Boolean represents true or false.
    Boolean(bool),
    /// Integer represents an integer.
    Integer(Integer),
    /// Float represents a floating point number.
    Float(Float),
    /// String extending Raw type represents a UTF-8 string.
    String(String),
    /// Binary extending Raw type represents a byte array.
    Binary(Vec<u8>),
    /// Array represents a sequence of objects.
    Array(Vec<Value>),
    /// Map represents key-value pairs of objects.
    Map(Vec<(Value, Value)>),
    /// Extended implements Extension interface: represents a tuple of type information and a byte
    /// array where type information is an integer whose meaning is defined by applications.
    Ext(i8, Vec<u8>),
}

#[derive(Clone, Debug, PartialEq)]
pub enum ValueRef<'a> {
    /// Nil represents nil.
    Nil,
    /// Boolean represents true or false.
    Boolean(bool),
    /// Integer represents an integer.
    Integer(Integer),
    /// Float represents a floating point number.
    Float(Float),
    /// String extending Raw type represents a UTF-8 string.
    String(&'a str),
    /// Binary extending Raw type represents a byte array.
    Binary(&'a [u8]),
    /// Array represents a sequence of objects.
    Array(&'a [ValueRef<'a>]),
    /// Map represents key-value pairs of objects.
    Map(&'a [(ValueRef<'a>, ValueRef<'a>)]),
    /// Extended implements Extension interface: represents a tuple of type information and a byte
    /// array where type information is an integer whose meaning is defined by applications.
    Ext(i8, &'a [u8]),
}
<commit_msg>[Common] Temporary hide value ref ADT.<commit_after>#[derive(Clone, Debug, PartialEq)]
pub enum Integer {
    /// Every non-negative integer is treated as u64, even if it fits in i64.
    U64(u64),
    /// Every negative integer is treated as i64.
    I64(i64),
}

#[derive(Clone, Debug, PartialEq)]
pub enum Float {
    F32(f32),
    F64(f64),
}

#[derive(Clone, Debug, PartialEq)]
pub enum Value {
    /// Nil represents nil.
    Nil,
    /// Boolean represents true or false.
    Boolean(bool),
    /// Integer represents an integer.
    Integer(Integer),
    /// Float represents a floating point number.
    Float(Float),
    /// String extending Raw type represents a UTF-8 string.
    String(String),
    /// Binary extending Raw type represents a byte array.
    Binary(Vec<u8>),
    /// Array represents a sequence of objects.
    Array(Vec<Value>),
    /// Map represents key-value pairs of objects.
    Map(Vec<(Value, Value)>),
    /// Extended implements Extension interface: represents a tuple of type information and a byte
    /// array where type information is an integer whose meaning is defined by applications.
    Ext(i8, Vec<u8>),
}

#[derive(Clone, Debug, PartialEq)]
enum ValueRef<'a> {
    /// Nil represents nil.
    Nil,
    /// Boolean represents true or false.
    Boolean(bool),
    /// Integer represents an integer.
    Integer(Integer),
    /// Float represents a floating point number.
    Float(Float),
    /// String extending Raw type represents a UTF-8 string.
    String(&'a str),
    /// Binary extending Raw type represents a byte array.
    Binary(&'a [u8]),
    /// Array represents a sequence of objects.
    Array(&'a [ValueRef<'a>]),
    /// Map represents key-value pairs of objects.
    Map(&'a [(ValueRef<'a>, ValueRef<'a>)]),
    /// Extended implements Extension interface: represents a tuple of type information and a byte
    /// array where type information is an integer whose meaning is defined by applications.
    Ext(i8, &'a [u8]),
}
<|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/. */

use dom::bindings::codegen::Bindings::FormDataBinding::FormDataMethods;
use dom::bindings::error::{Error, Fallible};
use dom::bindings::reflector::DomObject;
use dom::bindings::root::DomRoot;
use dom::bindings::str::USVString;
use dom::blob::{Blob, BlobImpl};
use dom::formdata::FormData;
use dom::globalscope::GlobalScope;
use dom::promise::Promise;
use js::jsapi::JSContext;
use js::jsapi::JS_ClearPendingException;
use js::jsapi::JS_ParseJSON;
use js::jsapi::Value as JSValue;
use js::jsval::UndefinedValue;
use mime::{Mime, TopLevel, SubLevel};
use std::cell::Ref;
use std::rc::Rc;
use std::str;
use url::form_urlencoded;

#[derive(Clone, Copy, JSTraceable, MallocSizeOf)]
pub enum BodyType {
    Blob,
    FormData,
    Json,
    Text,
    ArrayBuffer
}

pub enum FetchedData {
    Text(String),
    Json(JSValue),
    BlobData(DomRoot<Blob>),
    FormData(DomRoot<FormData>),
}

// https://fetch.spec.whatwg.org/#concept-body-consume-body
#[allow(unrooted_must_root)]
pub fn consume_body<T: BodyOperations + DomObject>(object: &T, body_type: BodyType) -> Rc<Promise> {
    let promise = Promise::new(&object.global());

    // Step 1
    if object.get_body_used() || object.is_locked() {
        promise.reject_error(Error::Type(
            "The response's stream is disturbed or locked".to_string(),
        ));
        return promise;
    }

    object.set_body_promise(&promise, body_type);

    // Steps 2-4
    // TODO: Body does not yet have a stream.

    consume_body_with_promise(object, body_type, &promise);

    promise
}

// https://fetch.spec.whatwg.org/#concept-body-consume-body
#[allow(unrooted_must_root)]
pub fn consume_body_with_promise<T: BodyOperations + DomObject>(object: &T,
                                                                body_type: BodyType,
                                                                promise: &Promise) {
    // Step 5
    let body = match object.take_body() {
        Some(body) => body,
        None => return,
    };

    let pkg_data_results = run_package_data_algorithm(object,
                                                      body,
                                                      body_type,
                                                      object.get_mime_type());

    match pkg_data_results {
        Ok(results) => {
            match results {
                FetchedData::Text(s) => promise.resolve_native(&USVString(s)),
                FetchedData::Json(j) => promise.resolve_native(&j),
                FetchedData::BlobData(b) => promise.resolve_native(&b),
                FetchedData::FormData(f) => promise.resolve_native(&f),
            };
        },
        Err(err) => promise.reject_error(err),
    }
}

// https://fetch.spec.whatwg.org/#concept-body-package-data
#[allow(unsafe_code)]
fn run_package_data_algorithm<T: BodyOperations + DomObject>(object: &T,
                                                             bytes: Vec<u8>,
                                                             body_type: BodyType,
                                                             mime_type: Ref<Vec<u8>>)
                                                             -> Fallible<FetchedData> {
    let global = object.global();
    let cx = global.get_cx();
    let mime = &*mime_type;
    match body_type {
        BodyType::Text => run_text_data_algorithm(bytes),
        BodyType::Json => run_json_data_algorithm(cx, bytes),
        BodyType::Blob => run_blob_data_algorithm(&global, bytes, mime),
        BodyType::FormData => run_form_data_algorithm(&global, bytes, mime),
    }
}

fn run_text_data_algorithm(bytes: Vec<u8>) -> Fallible<FetchedData> {
    Ok(FetchedData::Text(String::from_utf8_lossy(&bytes).into_owned()))
}

#[allow(unsafe_code)]
fn run_json_data_algorithm(cx: *mut JSContext,
                           bytes: Vec<u8>) -> Fallible<FetchedData> {
    let json_text = String::from_utf8_lossy(&bytes);
    let json_text: Vec<u16> = json_text.encode_utf16().collect();
    rooted!(in(cx) let mut rval = UndefinedValue());
    unsafe {
        if !JS_ParseJSON(cx,
                         json_text.as_ptr(),
                         json_text.len() as u32,
                         rval.handle_mut()) {
            JS_ClearPendingException(cx);
            // TODO: See issue #13464. Exception should be thrown instead of cleared.
            return Err(Error::Type("Failed to parse JSON".to_string()));
        }
        Ok(FetchedData::Json(rval.get()))
    }
}

fn run_blob_data_algorithm(root: &GlobalScope,
                           bytes: Vec<u8>,
                           mime: &[u8]) -> Fallible<FetchedData> {
    let mime_string = if let Ok(s) = String::from_utf8(mime.to_vec()) {
        s
    } else {
        "".to_string()
    };
    let blob = Blob::new(root, BlobImpl::new_from_bytes(bytes), mime_string);
    Ok(FetchedData::BlobData(blob))
}

fn run_form_data_algorithm(root: &GlobalScope, bytes: Vec<u8>, mime: &[u8]) -> Fallible<FetchedData> {
    let mime_str = if let Ok(s) = str::from_utf8(mime) {
        s
    } else {
        ""
    };
    let mime: Mime = mime_str.parse().map_err(
        |_| Error::Type("Inappropriate MIME-type for Body".to_string()))?;
    match mime {
        // TODO
        // ... Parser for Mime(TopLevel::Multipart, SubLevel::FormData, _)
        // ... is not fully determined yet.
        Mime(TopLevel::Application, SubLevel::WwwFormUrlEncoded, _) => {
            let entries = form_urlencoded::parse(&bytes);
            let formdata = FormData::new(None, root);
            for (k, e) in entries {
                formdata.Append(USVString(k.into_owned()), USVString(e.into_owned()));
            }
            return Ok(FetchedData::FormData(formdata));
        },
        _ => return Err(Error::Type("Inappropriate MIME-type for Body".to_string())),
    }
}

pub trait BodyOperations {
    fn get_body_used(&self) -> bool;
    fn set_body_promise(&self, p: &Rc<Promise>, body_type: BodyType);
    /// Returns `Some(_)` if the body is complete, `None` if there is more to
    /// come.
    fn take_body(&self) -> Option<Vec<u8>>;
    fn is_locked(&self) -> bool;
    fn get_mime_type(&self) -> Ref<Vec<u8>>;
}
<commit_msg>feat(consume_body): implement consume_body accepts arraybuffer<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::Bindings::FormDataBinding::FormDataMethods;
use dom::bindings::error::{Error, Fallible};
use dom::bindings::reflector::DomObject;
use dom::bindings::root::DomRoot;
use dom::bindings::str::USVString;
use dom::bindings::trace::RootedTraceableBox;
use dom::blob::{Blob, BlobImpl};
use dom::formdata::FormData;
use dom::globalscope::GlobalScope;
use dom::promise::Promise;
use js::jsapi::Heap;
use js::jsapi::JSContext;
use js::jsapi::JSObject;
use js::jsapi::JS_ClearPendingException;
use js::jsapi::JS_ParseJSON;
use js::jsapi::Value as JSValue;
use js::jsval::UndefinedValue;
use js::typedarray::{ArrayBuffer, CreateWith};
use mime::{Mime, TopLevel, SubLevel};
use std::cell::Ref;
use std::ptr;
use std::rc::Rc;
use std::str;
use url::form_urlencoded;

#[derive(Clone, Copy, JSTraceable, MallocSizeOf)]
pub enum BodyType {
    Blob,
    FormData,
    Json,
    Text,
    ArrayBuffer
}

pub enum FetchedData {
    Text(String),
    Json(JSValue),
    BlobData(DomRoot<Blob>),
    FormData(DomRoot<FormData>),
    ArrayBuffer(RootedTraceableBox<Heap<*mut JSObject>>),
}

// https://fetch.spec.whatwg.org/#concept-body-consume-body
#[allow(unrooted_must_root)]
pub fn consume_body<T: BodyOperations + DomObject>(object: &T, body_type: BodyType) -> Rc<Promise> {
    let promise = Promise::new(&object.global());

    // Step 1
    if object.get_body_used() || object.is_locked() {
        promise.reject_error(Error::Type(
            "The response's stream is disturbed or locked".to_string(),
        ));
        return promise;
    }

    object.set_body_promise(&promise, body_type);

    // Steps 2-4
    // TODO: Body does not yet have a stream.

    consume_body_with_promise(object, body_type, &promise);

    promise
}

// https://fetch.spec.whatwg.org/#concept-body-consume-body
#[allow(unrooted_must_root)]
pub fn consume_body_with_promise<T: BodyOperations + DomObject>(object: &T,
                                                                body_type: BodyType,
                                                                promise: &Promise) {
    // Step 5
    let body = match object.take_body() {
        Some(body) => body,
        None => return,
    };

    let pkg_data_results = run_package_data_algorithm(object,
                                                      body,
                                                      body_type,
                                                      object.get_mime_type());

    match pkg_data_results {
        Ok(results) => {
            match results {
                FetchedData::Text(s) => promise.resolve_native(&USVString(s)),
                FetchedData::Json(j) => promise.resolve_native(&j),
                FetchedData::BlobData(b) => promise.resolve_native(&b),
                FetchedData::FormData(f) => promise.resolve_native(&f),
                FetchedData::ArrayBuffer(a) => promise.resolve_native(&a)
            };
        },
        Err(err) => promise.reject_error(err),
    }
}

// https://fetch.spec.whatwg.org/#concept-body-package-data
#[allow(unsafe_code)]
fn run_package_data_algorithm<T: BodyOperations + DomObject>(object: &T,
                                                             bytes: Vec<u8>,
                                                             body_type: BodyType,
                                                             mime_type: Ref<Vec<u8>>)
                                                             -> Fallible<FetchedData> {
    let global = object.global();
    let cx = global.get_cx();
    let mime = &*mime_type;
    match body_type {
        BodyType::Text => run_text_data_algorithm(bytes),
        BodyType::Json => run_json_data_algorithm(cx, bytes),
        BodyType::Blob => run_blob_data_algorithm(&global, bytes, mime),
        BodyType::FormData => run_form_data_algorithm(&global, bytes, mime),
        BodyType::ArrayBuffer => unsafe {
            run_array_buffer_data_algorithm(cx, bytes)
        }
    }
}

fn run_text_data_algorithm(bytes: Vec<u8>) -> Fallible<FetchedData> {
    Ok(FetchedData::Text(String::from_utf8_lossy(&bytes).into_owned()))
}

#[allow(unsafe_code)]
fn run_json_data_algorithm(cx: *mut JSContext,
                           bytes: Vec<u8>) -> Fallible<FetchedData> {
    let json_text = String::from_utf8_lossy(&bytes);
    let json_text: Vec<u16> = json_text.encode_utf16().collect();
    rooted!(in(cx) let mut rval = UndefinedValue());
    unsafe {
        if !JS_ParseJSON(cx,
                         json_text.as_ptr(),
                         json_text.len() as u32,
                         rval.handle_mut()) {
            JS_ClearPendingException(cx);
            // TODO: See issue #13464. Exception should be thrown instead of cleared.
            return Err(Error::Type("Failed to parse JSON".to_string()));
        }
        Ok(FetchedData::Json(rval.get()))
    }
}

fn run_blob_data_algorithm(root: &GlobalScope,
                           bytes: Vec<u8>,
                           mime: &[u8]) -> Fallible<FetchedData> {
    let mime_string = if let Ok(s) = String::from_utf8(mime.to_vec()) {
        s
    } else {
        "".to_string()
    };
    let blob = Blob::new(root, BlobImpl::new_from_bytes(bytes), mime_string);
    Ok(FetchedData::BlobData(blob))
}

fn run_form_data_algorithm(root: &GlobalScope, bytes: Vec<u8>, mime: &[u8]) -> Fallible<FetchedData> {
    let mime_str = if let Ok(s) = str::from_utf8(mime) {
        s
    } else {
        ""
    };
    let mime: Mime = mime_str.parse().map_err(
        |_| Error::Type("Inappropriate MIME-type for Body".to_string()))?;
    match mime {
        // TODO
        // ... Parser for Mime(TopLevel::Multipart, SubLevel::FormData, _)
        // ... is not fully determined yet.
        Mime(TopLevel::Application, SubLevel::WwwFormUrlEncoded, _) => {
            let entries = form_urlencoded::parse(&bytes);
            let formdata = FormData::new(None, root);
            for (k, e) in entries {
                formdata.Append(USVString(k.into_owned()), USVString(e.into_owned()));
            }
            return Ok(FetchedData::FormData(formdata));
        },
        _ => return Err(Error::Type("Inappropriate MIME-type for Body".to_string())),
    }
}

#[allow(unsafe_code)]
unsafe fn run_array_buffer_data_algorithm(cx: *mut JSContext, bytes: Vec<u8>) -> Fallible<FetchedData> {
    rooted!(in(cx) let mut array_buffer_ptr = ptr::null_mut::<JSObject>());
    let arraybuffer = ArrayBuffer::create(cx, CreateWith::Slice(&bytes), array_buffer_ptr.handle_mut());
    if arraybuffer.is_err() {
        return Err(Error::JSFailed);
    }
    let rooted_heap = RootedTraceableBox::from_box(Heap::boxed(array_buffer_ptr.get()));
    Ok(FetchedData::ArrayBuffer(rooted_heap))
}

pub trait BodyOperations {
    fn get_body_used(&self) -> bool;
    fn set_body_promise(&self, p: &Rc<Promise>, body_type: BodyType);
    /// Returns `Some(_)` if the body is complete, `None` if there is more to
    /// come.
    fn take_body(&self) -> Option<Vec<u8>>;
    fn is_locked(&self) -> bool;
    fn get_mime_type(&self) -> Ref<Vec<u8>>;
}
<|endoftext|>


<commit_before>use std::sync::Arc;
use super::{
    ClientDB,
    DBError,
};
use super::BLOCKS_DB_COLUMN as DB_COLUMN;

pub struct BlockStore<T>
    where T: ClientDB
{
    db: Arc<T>,
}

impl<T: ClientDB> BlockStore<T> {
    pub fn new(db: Arc<T>) -> Self {
        Self {
            db,
        }
    }

    pub fn put_block(&self, hash: &[u8], ssz: &[u8])
        -> Result<(), DBError>
    {
        self.db.put(DB_COLUMN, hash, ssz)
    }

    pub fn get_block(&self, hash: &[u8])
        -> Result<Option<Vec<u8>>, DBError>
    {
        self.db.get(DB_COLUMN, hash)
    }

    pub fn block_exists(&self, hash: &[u8])
        -> Result<bool, DBError>
    {
        self.db.exists(DB_COLUMN, hash)
    }

    pub fn block_exists_in_canonical_chain(&self, hash: &[u8])
        -> Result<bool, DBError>
    {
        // TODO: implement logic for canonical chain
        self.db.exists(DB_COLUMN, hash)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use super::super::super::MemoryDB;
    use std::thread;
    use std::sync::Arc;

    #[test]
    fn test_block_store_on_disk_db() {
        let db = Arc::new(MemoryDB::open());
        let bs = Arc::new(BlockStore::new(db.clone()));

        let thread_count = 10;
        let write_count = 10;

        // We're expecting the product of these numbers to fit in one byte.
        assert!(thread_count * write_count <= 255);

        let mut handles = vec![];
        for t in 0..thread_count {
            let wc = write_count;
            let bs = bs.clone();
            let handle = thread::spawn(move || {
                for w in 0..wc {
                    let key = (t * w) as u8;
                    let val = 42;
                    bs.put_block(&vec![key], &vec![val]).unwrap();
                }
            });
            handles.push(handle);
        }

        for handle in handles {
            handle.join().unwrap();
        }

        for t in 0..thread_count {
            for w in 0..write_count {
                let key = (t * w) as u8;
                assert!(bs.block_exists(&vec![key]).unwrap());
                let val = bs.get_block(&vec![key]).unwrap().unwrap();
                assert_eq!(vec![42], val);
            }
        }
    }
}
<commit_msg>Rename block_store functions<commit_after>use std::sync::Arc;
use super::{
    ClientDB,
    DBError,
};
use super::BLOCKS_DB_COLUMN as DB_COLUMN;

pub struct BlockStore<T>
    where T: ClientDB
{
    db: Arc<T>,
}

impl<T: ClientDB> BlockStore<T> {
    pub fn new(db: Arc<T>) -> Self {
        Self {
            db,
        }
    }

    pub fn put_serialized_block(&self, hash: &[u8], ssz: &[u8])
        -> Result<(), DBError>
    {
        self.db.put(DB_COLUMN, hash, ssz)
    }

    pub fn get_serialized_block(&self, hash: &[u8])
        -> Result<Option<Vec<u8>>, DBError>
    {
        self.db.get(DB_COLUMN, hash)
    }

    pub fn block_exists(&self, hash: &[u8])
        -> Result<bool, DBError>
    {
        self.db.exists(DB_COLUMN, hash)
    }

    pub fn block_exists_in_canonical_chain(&self, hash: &[u8])
        -> Result<bool, DBError>
    {
        // TODO: implement logic for canonical chain
        self.db.exists(DB_COLUMN, hash)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use super::super::super::MemoryDB;
    use std::thread;
    use std::sync::Arc;

    #[test]
    fn test_block_store_on_disk_db() {
        let db = Arc::new(MemoryDB::open());
        let bs = Arc::new(BlockStore::new(db.clone()));

        let thread_count = 10;
        let write_count = 10;

        // We're expecting the product of these numbers to fit in one byte.
        assert!(thread_count * write_count <= 255);

        let mut handles = vec![];
        for t in 0..thread_count {
            let wc = write_count;
            let bs = bs.clone();
            let handle = thread::spawn(move || {
                for w in 0..wc {
                    let key = (t * w) as u8;
                    let val = 42;
                    bs.put_serialized_block(&vec![key], &vec![val]).unwrap();
                }
            });
            handles.push(handle);
        }

        for handle in handles {
            handle.join().unwrap();
        }

        for t in 0..thread_count {
            for w in 0..write_count {
                let key = (t * w) as u8;
                assert!(bs.block_exists(&vec![key]).unwrap());
                let val = bs.get_serialized_block(&vec![key]).unwrap().unwrap();
                assert_eq!(vec![42], val);
            }
        }
    }
}
<|endoftext|>


<commit_before>//! A CLI tool for inspecting the contents of a DICOM file
//! by printing it in a human readable format.
use dicom::object::open_file;
use dicom_dump::{ColorMode, DumpOptions};
use snafu::ErrorCompat;
use std::io::ErrorKind;
use std::path::PathBuf;
use structopt::StructOpt;

/// Exit code for when an error emerged while reading the DICOM file.
const ERROR_READ: i32 = -2;
/// Exit code for when an error emerged while dumping the file.
const ERROR_PRINT: i32 = -3;

#[cfg(windows)]
fn os_compatibility() -> Result<(), ()> {
    control::set_virtual_terminal(true)
}

#[cfg(not(windows))]
fn os_compatibility() -> Result<(), ()> {
    Ok(())
}

/// Dump the contents of DICOM files
#[derive(Debug, StructOpt)]
struct App {
    /// The DICOM file(s) to read
    files: Vec<PathBuf>,
    /// whether text value width limit is disabled
    /// (limited to `width` by default)
    #[structopt(long = "no-text-limit")]
    no_text_limit: bool,
    /// the width of the display
    /// (default is to check automatically)
    #[structopt(short = "w", long = "width")]
    width: Option<u32>,
    /// color mode
    #[structopt(long = "color", default_value = "auto")]
    color: ColorMode,
}

fn main() {
    os_compatibility().unwrap_or_else(|_| {
        eprintln!("Error setting OS compatibility for colored output");
    });

    let App {
        files: filenames,
        no_text_limit,
        width,
        color,
    } = App::from_args();

    let width = width
        .or_else(|| term_size::dimensions().map(|(width, _)| width as u32))
        .unwrap_or(120);

    let mut options = DumpOptions::new();

    for filename in filenames {
        let obj = open_file(filename).unwrap_or_else(|e| {
            report(e);
            std::process::exit(ERROR_READ);
        });

        match options
            .no_text_limit(no_text_limit)
            .width(width)
            .color_mode(color)
            .dump_file(&obj)
        {
            Err(ref e) if e.kind() == ErrorKind::BrokenPipe => {
                // handle broken pipe separately with a no-op
            }
            Err(e) => {
                eprintln!("[ERROR] {}", e);
                std::process::exit(ERROR_PRINT);
            }
            _ => {} // all good
        }
    }
}

fn report<E: 'static>(err: E)
where
    E: std::error::Error,
    E: ErrorCompat,
{
    eprintln!("[ERROR] {}", err);
    if let Some(source) = err.source() {
        eprintln!();
        eprintln!("Caused by:");
        for (i, e) in std::iter::successors(Some(source), |e| e.source()).enumerate() {
            eprintln!("   {}: {}", i, e);
        }
    }

    let env_backtrace = std::env::var("RUST_BACKTRACE").unwrap_or_default();
    let env_lib_backtrace = std::env::var("RUST_LIB_BACKTRACE").unwrap_or_default();
    if env_lib_backtrace == "1" || (env_backtrace == "1" && env_lib_backtrace != "0") {
        if let Some(backtrace) = ErrorCompat::backtrace(&err) {
            eprintln!();
            eprintln!("Backtrace:");
            eprintln!("{}", backtrace);
        }
    }
}
<commit_msg>Improvements: - files now a required parameter - options set once - additional flag for optional exit on error<commit_after>//! A CLI tool for inspecting the contents of a DICOM file
//! by printing it in a human readable format.
use dicom::object::open_file;
use dicom_dump::{ColorMode, DumpOptions};
use snafu::ErrorCompat;
use std::io::ErrorKind;
use std::path::PathBuf;
use structopt::StructOpt;

/// Exit code for when an error emerged while reading the DICOM file.
const ERROR_READ: i32 = -2;
/// Exit code for when an error emerged while dumping the file.
const ERROR_PRINT: i32 = -3;

#[cfg(windows)]
fn os_compatibility() -> Result<(), ()> {
    control::set_virtual_terminal(true)
}

#[cfg(not(windows))]
fn os_compatibility() -> Result<(), ()> {
    Ok(())
}

/// Dump the contents of DICOM files
#[derive(Debug, StructOpt)]
struct App {
    /// The DICOM file(s) to read
    #[structopt(required = true)]
    files: Vec<PathBuf>,
    /// whether text value width limit is disabled
    /// (limited to `width` by default)
    #[structopt(long = "no-text-limit")]
    no_text_limit: bool,
    /// the width of the display
    /// (default is to check automatically)
    #[structopt(short = "w", long = "width")]
    width: Option<u32>,
    /// color mode
    #[structopt(long = "color", default_value = "auto")]
    color: ColorMode,
    /// fail if any errors are encountered
    #[structopt(long = "fail-first")]
    fail_first: bool,
}

fn main() {
    os_compatibility().unwrap_or_else(|_| {
        eprintln!("Error setting OS compatibility for colored output");
    });

    let App {
        files: filenames,
        no_text_limit,
        width,
        color,
        fail_first,
    } = App::from_args();

    let width = width
        .or_else(|| term_size::dimensions().map(|(width, _)| width as u32))
        .unwrap_or(120);

    let mut options = DumpOptions::new();
    options.no_text_limit(no_text_limit)
            .width(width)
            .color_mode(color);

    let mut errors = vec![];

    for filename in &filenames {
        println!("{}: ", filename.display());
        match open_file(filename) {
            Err(e) => {
                report(e);
                if fail_first {
                    std::process::exit(ERROR_READ);
                }
                errors.push((filename,ERROR_READ));
            },
            Ok(obj) => {
                if let Err(ref e) = options.dump_file(&obj) {
                    if e.kind() == ErrorKind::BrokenPipe {
                        // handle broken pipe separately with a no-op
                    } else {
                        eprintln!("[ERROR] {}", e);
                        if fail_first {
                        std::process::exit(ERROR_PRINT);
                        }
                    }
                    errors.push((filename,ERROR_PRINT))
                } // else all good
            }
        };
    }
}

fn report<E: 'static>(err: E)
where
    E: std::error::Error,
    E: ErrorCompat,
{
    eprintln!("[ERROR] {}", err);
    if let Some(source) = err.source() {
        eprintln!();
        eprintln!("Caused by:");
        for (i, e) in std::iter::successors(Some(source), |e| e.source()).enumerate() {
            eprintln!("   {}: {}", i, e);
        }
    }

    let env_backtrace = std::env::var("RUST_BACKTRACE").unwrap_or_default();
    let env_lib_backtrace = std::env::var("RUST_LIB_BACKTRACE").unwrap_or_default();
    if env_lib_backtrace == "1" || (env_backtrace == "1" && env_lib_backtrace != "0") {
        if let Some(backtrace) = ErrorCompat::backtrace(&err) {
            eprintln!();
            eprintln!("Backtrace:");
            eprintln!("{}", backtrace);
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 The Servo 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::sync::mpsc;
use std::sync::{Arc, Mutex, Condvar};
use std::collections::hash_map::HashMap;
use std::cell::{RefCell};
use std::slice;
use std::fmt::{self, Debug, Formatter};
use std::cmp::{PartialEq};
use std::ops::Deref;
use std::mem;

use uuid::Uuid;

struct SenderRecord {
    sender: MpscSender,
    lock: Mutex<bool>,
    condvar: Condvar,
}

impl SenderRecord {
    fn new(sender: MpscSender) -> SenderRecord {
        SenderRecord {
            sender: sender,
            lock: Mutex::new(false),
            condvar: Condvar::new(),
        }
    }

    fn wait_for_acquire(&self) {
        let mut started = self.lock.lock().unwrap();
        while !*started {
            started = self.condvar.wait(started).unwrap();
        }
    }

    fn signal_acquisition(&self) {
        let mut notified = self.lock.lock().unwrap();
        *notified = true;
        self.condvar.notify_one();
    }
}

lazy_static! {
    static ref ONE_SHOT_SENDERS: Mutex<HashMap<String,SenderRecord>> = Mutex::new(HashMap::new());
}

struct MpscChannelMessage(Vec<u8>, Vec<MpscChannel>, Vec<MpscSharedMemory>);

pub fn channel() -> Result<(MpscSender, MpscReceiver),MpscError> {
    let (base_sender, base_receiver) = mpsc::channel::<MpscChannelMessage>();
    Ok((MpscSender::new(base_sender), MpscReceiver::new(base_receiver)))
}

pub struct MpscReceiver {
    receiver: RefCell<Option<mpsc::Receiver<MpscChannelMessage>>>,
}

impl MpscReceiver {
    fn new(receiver: mpsc::Receiver<MpscChannelMessage>) -> MpscReceiver {
        MpscReceiver {
            receiver: RefCell::new(Some(receiver)),
        }
    }

    pub fn consume(&self) -> MpscReceiver {
        let receiver = self.receiver.borrow_mut().take();
        MpscReceiver::new(receiver.unwrap())
    }

    pub fn recv(&self) -> Result<(Vec<u8>, Vec<OpaqueMpscChannel>, Vec<MpscSharedMemory>),MpscError> {
        let r = self.receiver.borrow();
        match r.as_ref().unwrap().recv() {
            Ok(MpscChannelMessage(d,c,s)) => Ok((d,
                                                 c.into_iter().map(OpaqueMpscChannel::new).collect(),
                                                 s)),
            Err(_) => Err(MpscError::ChannelClosedError),
        }
    }

    pub fn try_recv(&self) -> Result<(Vec<u8>, Vec<OpaqueMpscChannel>, Vec<MpscSharedMemory>),MpscError> {
        let r = self.receiver.borrow();
        match r.as_ref().unwrap().try_recv() {
            Ok(MpscChannelMessage(d,c,s)) => Ok((d,
                                                 c.into_iter().map(OpaqueMpscChannel::new).collect(),
                                                 s)),
            Err(_) => Err(MpscError::ChannelClosedError),
        }
    }
}

unsafe impl Send for MpscReceiver { }
unsafe impl Sync for MpscReceiver { }

#[derive(Clone)]
pub struct MpscSender {
    sender: RefCell<mpsc::Sender<MpscChannelMessage>>,
}

unsafe impl Send for MpscSender { }
unsafe impl Sync for MpscSender { }

impl MpscSender {
    fn new(sender: mpsc::Sender<MpscChannelMessage>) -> MpscSender {
        MpscSender {
            sender: RefCell::new(sender),
        }
    }

    pub fn connect(name: String) -> Result<MpscSender,MpscError> {
        let record = ONE_SHOT_SENDERS.lock().unwrap().remove(&name).unwrap();
        record.signal_acquisition();
        Ok(record.sender)
    }

    pub fn send(&self,
                data: &[u8],
                ports: Vec<MpscChannel>,
                shared_memory_regions: Vec<MpscSharedMemory>)
                -> Result<(),MpscError>
    {
        match self.sender.borrow().send(MpscChannelMessage(data.to_vec(), ports, shared_memory_regions)) {
            Err(_) => Err(MpscError::ChannelClosedError),
            Ok(_) => Ok(()),
        }
    }
}

pub struct MpscReceiverSet {
    last_index: usize,
    receiver_ids: Vec<usize>,
    receivers: Vec<MpscReceiver>,
}

impl MpscReceiverSet {
    pub fn new() -> Result<MpscReceiverSet,MpscError> {
        Ok(MpscReceiverSet {
            last_index: 0,
            receiver_ids: vec![],
            receivers: vec![],
        })
    }

    pub fn add(&mut self, receiver: MpscReceiver) -> Result<i64,MpscError> {
        self.last_index += 1;
        self.receiver_ids.push(self.last_index);
        self.receivers.push(receiver.consume());
        Ok(self.last_index as i64)
    }

    pub fn select(&mut self) -> Result<Vec<MpscSelectionResult>,MpscError> {
        let mut receivers: Vec<Option<mpsc::Receiver<MpscChannelMessage>>> = Vec::with_capacity(self.receivers.len());
        let mut r_id: i64 = -1;
        let mut r_index: usize = 0;

        {
            let select = mpsc::Select::new();
            // we *must* allocate exact capacity for this, because the Handles *can't move*
            let mut handles: Vec<mpsc::Handle<MpscChannelMessage>> = Vec::with_capacity(self.receivers.len());

            for r in &self.receivers {
                let inner_r = mem::replace(&mut *r.receiver.borrow_mut(), None);
                receivers.push(inner_r);
            }

            for r in &receivers {
                unsafe {
                    handles.push(select.handle(r.as_ref().unwrap()));
                    handles.last_mut().unwrap().add();
                }
            }

            let id = select.wait();

            for (index,h) in handles.iter().enumerate() {
                if h.id() == id {
                    r_index = index;
                    r_id = self.receiver_ids[index] as i64;
                    break;
                }
            }
        }

        // put the receivers back
        for (index,r) in self.receivers.iter().enumerate() {
            mem::replace(&mut *r.receiver.borrow_mut(), mem::replace(&mut receivers[index], None));
        }

        if r_id == -1 {
            return Err(MpscError::UnknownError);
        }

        let receivers = &mut self.receivers;
        match receivers[r_index].recv() {
            Ok((data, channels, shmems)) =>
                Ok(vec![MpscSelectionResult::DataReceived(r_id, data, channels, shmems)]),
            Err(MpscError::ChannelClosedError) => {
                receivers.remove(r_index);
                self.receiver_ids.remove(r_index);
                Ok(vec![MpscSelectionResult::ChannelClosed(r_id)])
            },
            Err(err) => Err(err),
        }
    }
}

pub enum MpscSelectionResult {
    DataReceived(i64, Vec<u8>, Vec<OpaqueMpscChannel>, Vec<MpscSharedMemory>),
    ChannelClosed(i64),
}

pub struct MpscOneShotServer {
    receiver: RefCell<Option<MpscReceiver>>,
    name: String,
}

impl MpscOneShotServer {
    pub fn new() -> Result<(MpscOneShotServer, String),MpscError> {
        let (sender, receiver) = match channel() {
            Ok((s,r)) => (s,r),
            Err(err) => return Err(err),
        };

        let name = Uuid::new_v4().to_string();
        let record = SenderRecord::new(sender);
        ONE_SHOT_SENDERS.lock().unwrap().insert(name.clone(), record);
        Ok((MpscOneShotServer {
            receiver: RefCell::new(Some(receiver)),
            name: name.clone(),
        },name.clone()))
    }

    pub fn accept(&self) -> Result<(MpscReceiver,
                                    Vec<u8>,
                                    Vec<OpaqueMpscChannel>,
                                    Vec<MpscSharedMemory>),MpscError>
    {
        ONE_SHOT_SENDERS.lock().unwrap().get(&self.name).unwrap().wait_for_acquire();
        let receiver = self.receiver.borrow_mut().take().unwrap();
        let (data, channels, shmems) = receiver.recv().unwrap();
        Ok((receiver, data, channels, shmems))
    }
}

pub enum MpscChannel {
    Sender(MpscSender),
    Receiver(MpscReceiver),
}

pub struct OpaqueMpscChannel {
    channel: RefCell<Option<MpscChannel>>,
}

impl OpaqueMpscChannel {
    fn new(channel: MpscChannel) -> OpaqueMpscChannel {
        OpaqueMpscChannel {
            channel: RefCell::new(Some(channel))
        }
    }

    pub fn to_receiver(&self) -> MpscReceiver {
        match self.channel.borrow_mut().take().unwrap() {
            MpscChannel::Sender(_) => panic!("Opaque channel is not a receiver!"),
            MpscChannel::Receiver(r) => r
        }
    }

    pub fn to_sender(&self) -> MpscSender {
        match self.channel.borrow_mut().take().unwrap() {
            MpscChannel::Sender(s) => s,
            MpscChannel::Receiver(_) => panic!("Opaque channel is not a sender!"),
        }
    }
}

pub struct MpscSharedMemory {
    ptr: *mut u8,
    length: usize,
    data: Arc<Vec<u8>>,
}

unsafe impl Send for MpscSharedMemory {}
unsafe impl Sync for MpscSharedMemory {}

impl Clone for MpscSharedMemory {
    fn clone(&self) -> MpscSharedMemory {
        MpscSharedMemory {
            ptr: self.ptr,
            length: self.length,
            data: self.data.clone(),
        }
    }
}

impl PartialEq for MpscSharedMemory {
    fn eq(&self, other: &MpscSharedMemory) -> bool {
        **self == **other
    }
}

impl Debug for MpscSharedMemory {
    fn fmt(&self, formatter: &mut Formatter) -> Result<(), fmt::Error> {
        (**self).fmt(formatter)
    }
}

impl Deref for MpscSharedMemory {
    type Target = [u8];

    #[inline]
    fn deref(&self) -> &[u8] {
        if self.ptr.is_null() {
            panic!("attempted to access a consumed `MpscSharedMemory`")
        }
        unsafe {
            slice::from_raw_parts(self.ptr, self.length)
        }
    }
}

impl MpscSharedMemory {
    pub fn from_byte(byte: u8, length: usize) -> MpscSharedMemory {
        let mut v = Arc::new(vec![byte; length]);
        MpscSharedMemory {
            ptr: Arc::get_mut(&mut v).unwrap().as_mut_ptr(),
            length: length,
            data: v
        }
    }

    pub fn from_bytes(bytes: &[u8]) -> MpscSharedMemory {
        let mut v = Arc::new(bytes.to_vec());
        MpscSharedMemory {
            ptr: Arc::get_mut(&mut v).unwrap().as_mut_ptr(),
            length: v.len(),
            data: v
        }
    }
}

#[derive(Debug)]
pub enum MpscError {
    ChannelClosedError,
    UnknownError,
}

<commit_msg>Convert to using a channel() instead of mutex/condvar for one shot servers<commit_after>// Copyright 2015 The Servo 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::sync::mpsc;
use std::sync::{Arc, Mutex, Condvar};
use std::collections::hash_map::HashMap;
use std::cell::{RefCell};
use std::slice;
use std::fmt::{self, Debug, Formatter};
use std::cmp::{PartialEq};
use std::ops::Deref;
use std::mem;

use uuid::Uuid;

struct SenderRecord {
    sender: MpscSender,
    conn_sender: mpsc::Sender<bool>,
    conn_receiver: Mutex<mpsc::Receiver<bool>>,
}

impl SenderRecord {
    fn new(sender: MpscSender) -> SenderRecord {
        let (tx, rx) = mpsc::channel::<bool>();
        SenderRecord {
            sender: sender,
            conn_sender: tx,
            conn_receiver: Mutex::new(rx),
        }
    }

    fn accept(&self) {
        self.conn_receiver.lock().unwrap().recv().unwrap();
    }

    fn connect(&self) {
        self.conn_sender.send(true).unwrap();
    }
}

lazy_static! {
    static ref ONE_SHOT_SENDERS: Mutex<HashMap<String,SenderRecord>> = Mutex::new(HashMap::new());
}

struct MpscChannelMessage(Vec<u8>, Vec<MpscChannel>, Vec<MpscSharedMemory>);

pub fn channel() -> Result<(MpscSender, MpscReceiver),MpscError> {
    let (base_sender, base_receiver) = mpsc::channel::<MpscChannelMessage>();
    Ok((MpscSender::new(base_sender), MpscReceiver::new(base_receiver)))
}

pub struct MpscReceiver {
    receiver: RefCell<Option<mpsc::Receiver<MpscChannelMessage>>>,
}

impl MpscReceiver {
    fn new(receiver: mpsc::Receiver<MpscChannelMessage>) -> MpscReceiver {
        MpscReceiver {
            receiver: RefCell::new(Some(receiver)),
        }
    }

    pub fn consume(&self) -> MpscReceiver {
        let receiver = self.receiver.borrow_mut().take();
        MpscReceiver::new(receiver.unwrap())
    }

    pub fn recv(&self) -> Result<(Vec<u8>, Vec<OpaqueMpscChannel>, Vec<MpscSharedMemory>),MpscError> {
        let r = self.receiver.borrow();
        match r.as_ref().unwrap().recv() {
            Ok(MpscChannelMessage(d,c,s)) => Ok((d,
                                                 c.into_iter().map(OpaqueMpscChannel::new).collect(),
                                                 s)),
            Err(_) => Err(MpscError::ChannelClosedError),
        }
    }

    pub fn try_recv(&self) -> Result<(Vec<u8>, Vec<OpaqueMpscChannel>, Vec<MpscSharedMemory>),MpscError> {
        let r = self.receiver.borrow();
        match r.as_ref().unwrap().try_recv() {
            Ok(MpscChannelMessage(d,c,s)) => Ok((d,
                                                 c.into_iter().map(OpaqueMpscChannel::new).collect(),
                                                 s)),
            Err(_) => Err(MpscError::ChannelClosedError),
        }
    }
}

unsafe impl Send for MpscReceiver { }
unsafe impl Sync for MpscReceiver { }

#[derive(Clone)]
pub struct MpscSender {
    sender: RefCell<mpsc::Sender<MpscChannelMessage>>,
}

unsafe impl Send for MpscSender { }
unsafe impl Sync for MpscSender { }

impl MpscSender {
    fn new(sender: mpsc::Sender<MpscChannelMessage>) -> MpscSender {
        MpscSender {
            sender: RefCell::new(sender),
        }
    }

    pub fn connect(name: String) -> Result<MpscSender,MpscError> {
        let record = ONE_SHOT_SENDERS.lock().unwrap().remove(&name).unwrap();
        record.connect();
        Ok(record.sender)
    }

    pub fn send(&self,
                data: &[u8],
                ports: Vec<MpscChannel>,
                shared_memory_regions: Vec<MpscSharedMemory>)
                -> Result<(),MpscError>
    {
        match self.sender.borrow().send(MpscChannelMessage(data.to_vec(), ports, shared_memory_regions)) {
            Err(_) => Err(MpscError::ChannelClosedError),
            Ok(_) => Ok(()),
        }
    }
}

pub struct MpscReceiverSet {
    last_index: usize,
    receiver_ids: Vec<usize>,
    receivers: Vec<MpscReceiver>,
}

impl MpscReceiverSet {
    pub fn new() -> Result<MpscReceiverSet,MpscError> {
        Ok(MpscReceiverSet {
            last_index: 0,
            receiver_ids: vec![],
            receivers: vec![],
        })
    }

    pub fn add(&mut self, receiver: MpscReceiver) -> Result<i64,MpscError> {
        self.last_index += 1;
        self.receiver_ids.push(self.last_index);
        self.receivers.push(receiver.consume());
        Ok(self.last_index as i64)
    }

    pub fn select(&mut self) -> Result<Vec<MpscSelectionResult>,MpscError> {
        let mut receivers: Vec<Option<mpsc::Receiver<MpscChannelMessage>>> = Vec::with_capacity(self.receivers.len());
        let mut r_id: i64 = -1;
        let mut r_index: usize = 0;

        {
            let select = mpsc::Select::new();
            // we *must* allocate exact capacity for this, because the Handles *can't move*
            let mut handles: Vec<mpsc::Handle<MpscChannelMessage>> = Vec::with_capacity(self.receivers.len());

            for r in &self.receivers {
                let inner_r = mem::replace(&mut *r.receiver.borrow_mut(), None);
                receivers.push(inner_r);
            }

            for r in &receivers {
                unsafe {
                    handles.push(select.handle(r.as_ref().unwrap()));
                    handles.last_mut().unwrap().add();
                }
            }

            let id = select.wait();

            for (index,h) in handles.iter().enumerate() {
                if h.id() == id {
                    r_index = index;
                    r_id = self.receiver_ids[index] as i64;
                    break;
                }
            }
        }

        // put the receivers back
        for (index,r) in self.receivers.iter().enumerate() {
            mem::replace(&mut *r.receiver.borrow_mut(), mem::replace(&mut receivers[index], None));
        }

        if r_id == -1 {
            return Err(MpscError::UnknownError);
        }

        let receivers = &mut self.receivers;
        match receivers[r_index].recv() {
            Ok((data, channels, shmems)) =>
                Ok(vec![MpscSelectionResult::DataReceived(r_id, data, channels, shmems)]),
            Err(MpscError::ChannelClosedError) => {
                receivers.remove(r_index);
                self.receiver_ids.remove(r_index);
                Ok(vec![MpscSelectionResult::ChannelClosed(r_id)])
            },
            Err(err) => Err(err),
        }
    }
}

pub enum MpscSelectionResult {
    DataReceived(i64, Vec<u8>, Vec<OpaqueMpscChannel>, Vec<MpscSharedMemory>),
    ChannelClosed(i64),
}

pub struct MpscOneShotServer {
    receiver: RefCell<Option<MpscReceiver>>,
    name: String,
}

impl MpscOneShotServer {
    pub fn new() -> Result<(MpscOneShotServer, String),MpscError> {
        let (sender, receiver) = match channel() {
            Ok((s,r)) => (s,r),
            Err(err) => return Err(err),
        };

        let name = Uuid::new_v4().to_string();
        let record = SenderRecord::new(sender);
        ONE_SHOT_SENDERS.lock().unwrap().insert(name.clone(), record);
        Ok((MpscOneShotServer {
            receiver: RefCell::new(Some(receiver)),
            name: name.clone(),
        },name.clone()))
    }

    pub fn accept(&self) -> Result<(MpscReceiver,
                                    Vec<u8>,
                                    Vec<OpaqueMpscChannel>,
                                    Vec<MpscSharedMemory>),MpscError>
    {
        ONE_SHOT_SENDERS.lock().unwrap().get(&self.name).unwrap().accept();
        let receiver = self.receiver.borrow_mut().take().unwrap();
        let (data, channels, shmems) = receiver.recv().unwrap();
        Ok((receiver, data, channels, shmems))
    }
}

pub enum MpscChannel {
    Sender(MpscSender),
    Receiver(MpscReceiver),
}

pub struct OpaqueMpscChannel {
    channel: RefCell<Option<MpscChannel>>,
}

impl OpaqueMpscChannel {
    fn new(channel: MpscChannel) -> OpaqueMpscChannel {
        OpaqueMpscChannel {
            channel: RefCell::new(Some(channel))
        }
    }

    pub fn to_receiver(&self) -> MpscReceiver {
        match self.channel.borrow_mut().take().unwrap() {
            MpscChannel::Sender(_) => panic!("Opaque channel is not a receiver!"),
            MpscChannel::Receiver(r) => r
        }
    }

    pub fn to_sender(&self) -> MpscSender {
        match self.channel.borrow_mut().take().unwrap() {
            MpscChannel::Sender(s) => s,
            MpscChannel::Receiver(_) => panic!("Opaque channel is not a sender!"),
        }
    }
}

pub struct MpscSharedMemory {
    ptr: *mut u8,
    length: usize,
    data: Arc<Vec<u8>>,
}

unsafe impl Send for MpscSharedMemory {}
unsafe impl Sync for MpscSharedMemory {}

impl Clone for MpscSharedMemory {
    fn clone(&self) -> MpscSharedMemory {
        MpscSharedMemory {
            ptr: self.ptr,
            length: self.length,
            data: self.data.clone(),
        }
    }
}

impl PartialEq for MpscSharedMemory {
    fn eq(&self, other: &MpscSharedMemory) -> bool {
        **self == **other
    }
}

impl Debug for MpscSharedMemory {
    fn fmt(&self, formatter: &mut Formatter) -> Result<(), fmt::Error> {
        (**self).fmt(formatter)
    }
}

impl Deref for MpscSharedMemory {
    type Target = [u8];

    #[inline]
    fn deref(&self) -> &[u8] {
        if self.ptr.is_null() {
            panic!("attempted to access a consumed `MpscSharedMemory`")
        }
        unsafe {
            slice::from_raw_parts(self.ptr, self.length)
        }
    }
}

impl MpscSharedMemory {
    pub fn from_byte(byte: u8, length: usize) -> MpscSharedMemory {
        let mut v = Arc::new(vec![byte; length]);
        MpscSharedMemory {
            ptr: Arc::get_mut(&mut v).unwrap().as_mut_ptr(),
            length: length,
            data: v
        }
    }

    pub fn from_bytes(bytes: &[u8]) -> MpscSharedMemory {
        let mut v = Arc::new(bytes.to_vec());
        MpscSharedMemory {
            ptr: Arc::get_mut(&mut v).unwrap().as_mut_ptr(),
            length: v.len(),
            data: v
        }
    }
}

#[derive(Debug)]
pub enum MpscError {
    ChannelClosedError,
    UnknownError,
}

<|endoftext|>


<commit_before>
#[derive(Show)]
pub enum Exp<'x> {
    Value(int),
    Plus(Box<Exp<'x>>, Box<Exp<'x>>),

    // Meta nodes:
    StepsTo(&'x Exp<'x>,Box<Exp<'x>>), // Expresses a StepsTo Relationship,
    Ref(&'x Exp<'x>), // Refs allow for (non-affine) sharing.
}

mod borrow {
    use super::Exp;

    pub fn step<'x> (e:&'x Exp<'x>) -> Option<Exp<'x>> {
        match *e {
            Exp::Value(_) => None,
            Exp::Ref(e) => step(e),
            Exp::StepsTo(_, ref after) => step(&**after),
            Exp::Plus(ref e1, ref e2) =>
                match **e1 {
                    Exp::Value(n) =>
                        match **e2 {
                            Exp::Value(m) => Some(Exp::Value(n+m)),
                            _ => {
                                let e2_ = step(&**e2) ;
                                match e2_ {
                                    None => panic!("impossible"),
                                    Some(e2_) => Some(Exp::Plus(box Exp::Value(n), box e2_))
                                }
                            }
                        },

                    _ => {
                        let e1_ = step(&**e1) ;
                        match e1_ {
                            None => panic!("impossible"),
                            Some(e1_) => Some(Exp::Plus(box e1_, box Exp::Ref(&**e2)))
                        }
                    }
                }
        }
    }
}

pub fn test1 () {
    let e0 = Exp::Plus(box Exp::Plus(box Exp::Value(0),
                                     box Exp::Value(1)),
                       box Exp::Plus(box Exp::Value(2),
                                     box Exp::Plus(box Exp::Plus(box Exp::Value(0),
                                                                 box Exp::Value(3)),
                                                   box Exp::Plus(box Exp::Value(4),
                                                                 box Exp::Value(5))))) ;
    let e1 = borrow::step(&e0) ;
    match e1 {
        None => (),
        Some(ref e1) => {
            println!("{} --> {}", e0, e1) ;
            let e2 = borrow::step( e1 ) ;
            match e2 {
                None => (),
                Some(ref e2) => {
                    println!("{} --> {}", e1, e2) ;
                    let e3 = borrow::step( e2 ) ;
                    match e3 {
                        None => (),
                        Some(ref e3) => {
                            println!("{} --> {}", e2, e3) ;
                            let e4 = borrow::step( e3 ) ;
                            match e4 {
                                None => (),
                                Some(ref e4) => {
                                    println!("{} --> {}", e3, e4) ;
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

fn step_loop<'x> ( stepcnt : int, exp : Exp<'x> ) {
    let s = borrow::step(&exp) ;
    match s {
        None => (), // exp
        Some(exp_) => {
            println!("{}: {} --> {}\n", stepcnt, exp, exp_) ;
            let step_full = Exp::StepsTo( &exp, box exp_) ;
            step_loop ( stepcnt+1, step_full )
        }
    }
}

pub fn test2 () {
    let e0 = Exp::Plus(box Exp::Value(1),
                       box Exp::Plus(box Exp::Value(2),
                                     box Exp::Plus(box Exp::Value(3),
                                                   box Exp::Plus(box Exp::Value(4),
                                                                 box Exp::Value(5))))) ;
    let e_trace = step_loop ( 0, e0 ) ;
    println!("Final trace: {}", e_trace)
}

pub fn main () {
    if false {
        test1 ()
    }
    else {
        test2 ()
    }
}
<commit_msg>documented problem with using borrowing<commit_after>
#[derive(Show)]
pub enum Exp<'x> {
    Value(int),
    Plus(Box<Exp<'x>>, Box<Exp<'x>>),

    // Meta nodes:
    StepsTo(&'x Exp<'x>,Box<Exp<'x>>), // Expresses a StepsTo Relationship,
    Ref(&'x Exp<'x>), // Refs allow for (non-affine) sharing.
}

mod borrow {
    use super::Exp;

    pub fn step<'x> (e:&'x Exp<'x>) -> Option<Exp<'x>> {
        match *e {
            Exp::Value(_) => None,
            Exp::Ref(e) => step(e),
            Exp::StepsTo(_, ref after) => step(&**after),
            Exp::Plus(ref e1, ref e2) =>
                match **e1 {
                    Exp::Value(n) =>
                        match **e2 {
                            Exp::Value(m) => Some(Exp::Value(n+m)),
                            _ => {
                                let e2_ = step(&**e2) ;
                                match e2_ {
                                    None => panic!("impossible"),
                                    Some(e2_) => Some(Exp::Plus(box Exp::Value(n), box e2_))
                                }
                            }
                        },

                    _ => {
                        let e1_ = step(&**e1) ;
                        match e1_ {
                            None => panic!("impossible"),
                            Some(e1_) => Some(Exp::Plus(box e1_, box Exp::Ref(&**e2)))
                        }
                    }
                }
        }
    }
}

pub fn test1 () {
    let e0 = Exp::Plus(box Exp::Plus(box Exp::Value(0),
                                     box Exp::Value(1)),
                       box Exp::Plus(box Exp::Value(2),
                                     box Exp::Plus(box Exp::Plus(box Exp::Value(0),
                                                                 box Exp::Value(3)),
                                                   box Exp::Plus(box Exp::Value(4),
                                                                 box Exp::Value(5))))) ;
    let e1 = borrow::step(&e0) ;
    match e1 {
        None => (),
        Some(ref e1) => {
            println!("{} --> {}", e0, e1) ;
            let e2 = borrow::step( e1 ) ;
            match e2 {
                None => (),
                Some(ref e2) => {
                    println!("{} --> {}", e1, e2) ;
                    let e3 = borrow::step( e2 ) ;
                    match e3 {
                        None => (),
                        Some(ref e3) => {
                            println!("{} --> {}", e2, e3) ;
                            let e4 = borrow::step( e3 ) ;
                            match e4 {
                                None => (),
                                Some(ref e4) => {
                                    println!("{} --> {}", e3, e4) ;
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

// Stuck: Cannot return the accumulated expression `exp`.
// The lifetime/borrow-checker doe not permit it.
// See exp2.rs for an alternative design that does not use borrowing.
fn step_loop<'x> ( stepcnt : int, exp : Exp<'x> ) {
    let s = borrow::step(&exp) ;
    match s {
        None => (), // Stuck: cannot return `exp` here.
        Some(exp_) => {
            println!("{}: {} --> {}\n", stepcnt, exp, exp_) ;
            let step_full = Exp::StepsTo( &exp, box exp_) ;
            step_loop ( stepcnt+1, step_full )
        }
    }
}

pub fn test2 () {
    let e0 = Exp::Plus(box Exp::Value(1),
                       box Exp::Plus(box Exp::Value(2),
                                     box Exp::Plus(box Exp::Value(3),
                                                   box Exp::Plus(box Exp::Value(4),
                                                                 box Exp::Value(5))))) ;
    let e_trace = step_loop ( 0, e0 ) ;
    println!("Final trace: {}", e_trace)
}

pub fn main () {
    if false {
        test1 ()
    }
    else {
        test2 ()
    }
}
<|endoftext|>


<commit_before>//! You can do fast, single precision, floating point math as well

#![feature(asm)]
#![no_main]
#![no_std]

#[macro_use]
extern crate f3;

#[export_name = "main"]
pub extern "C" fn main() -> ! {
    let x = black_box(2_f32);
    let y = black_box(3_f32);
    let z = black_box(x * y);

    iprintln!("{} * {} = {}", x, y, z);

    loop {}
}

// Magic to prevent optimizations like "constant folding" which is when LLVM
// performs arithmetic at compile time. This is a copy of `test::black_box`.
fn black_box<T>(x: T) -> T {
    unsafe {
        asm!("" :: "r"(&x));
    }

    x
}
<commit_msg>print FP values as integers<commit_after>//! You can do fast, single precision, floating point math as well

#![feature(asm)]
#![no_main]
#![no_std]

#[macro_use]
extern crate f3;

#[export_name = "main"]
pub extern "C" fn main() -> ! {
    let x = black_box(2_f32);
    let y = black_box(3_f32);
    let z = black_box(x * y);

    // FIXME(japaric/rustc-builtins#79) there is a problem with the
    // rustc-builtins (compiler-builtins-snapshot) crate and LTO. Avoid the
    // issue by printing these values as integers because integer formatting
    // doesn't need any intrinsic.
    iprintln!("{} * {} = {}", x as u32, y as u32, z as u32);

    loop {}
}

// Magic to prevent optimizations like "constant folding" which is when LLVM
// performs arithmetic at compile time. This is a copy of `test::black_box`.
fn black_box<T>(x: T) -> T {
    unsafe {
        asm!("" :: "r"(&x));
    }

    x
}
<|endoftext|>


<commit_before>//! Contains Value and ValueRef structs and its conversion traits.

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Integer {
    /// Every non-negative integer is treated as u64, even if it fits in i64.
    U64(u64),
    /// Every negative integer is treated as i64.
    I64(i64),
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Float {
    F32(f32),
    F64(f64),
}

#[derive(Clone, Debug, PartialEq)]
pub enum Value {
    /// Nil represents nil.
    Nil,
    /// Boolean represents true or false.
    Boolean(bool),
    /// Integer represents an integer.
    Integer(Integer),
    /// Float represents a floating point number.
    Float(Float),
    /// String extending Raw type represents a UTF-8 string.
    String(String),
    /// Binary extending Raw type represents a byte array.
    Binary(Vec<u8>),
    /// Array represents a sequence of objects.
    Array(Vec<Value>),
    /// Map represents key-value pairs of objects.
    Map(Vec<(Value, Value)>),
    /// Extended implements Extension interface: represents a tuple of type information and a byte
    /// array where type information is an integer whose meaning is defined by applications.
    Ext(i8, Vec<u8>),
}

#[derive(Clone, Debug, PartialEq)]
pub enum ValueRef<'a> {
   /// Nil represents nil.
   Nil,
   /// Boolean represents true or false.
   Boolean(bool),
   /// Integer represents an integer.
   Integer(Integer),
   /// Float represents a floating point number.
   Float(Float),
   /// String extending Raw type represents a UTF-8 string.
   String(&'a str),
   /// Binary extending Raw type represents a byte array.
   Binary(&'a [u8]),
   /// Array represents a sequence of objects.
   Array(Vec<ValueRef<'a>>),
   /// Map represents key-value pairs of objects.
   Map(Vec<(ValueRef<'a>, ValueRef<'a>)>),
   /// Extended implements Extension interface: represents a tuple of type information and a byte
   /// array where type information is an integer whose meaning is defined by applications.
   Ext(i8, &'a [u8]),
}

impl<'a> ValueRef<'a> {
    /// Converts the current non-owning value to an owned Value.
    ///
    /// This is achieved by deep copying all underlying structures and borrowed buffers.
    ///
    /// # Panics
    ///
    /// Panics in unable to allocate memory to keep all internal structures and buffers.
    ///
    /// # Examples
    /// ```
    /// use rmp::{Value, ValueRef};
    /// use rmp::value::Integer;
    ///
    /// let val = ValueRef::Array(vec![
    ///    ValueRef::Nil,
    ///    ValueRef::Integer(Integer::U64(42)),
    ///    ValueRef::Array(vec![
    ///        ValueRef::String("le message"),
    ///    ])
    /// ]);
    ///
    /// let expected = Value::Array(vec![
    ///     Value::Nil,
    ///     Value::Integer(Integer::U64(42)),
    ///     Value::Array(vec![
    ///         Value::String("le message".to_string())
    ///     ])
    /// ]);
    ///
    /// assert_eq!(expected, val.to_owned());
    /// ```
    pub fn to_owned(&self) -> Value {
        match self {
            &ValueRef::Nil => Value::Nil,
            &ValueRef::Boolean(val) => Value::Boolean(val),
            &ValueRef::Integer(val) => Value::Integer(val),
            &ValueRef::Float(val) => Value::Float(val),
            &ValueRef::String(val) => Value::String(val.to_string()),
            &ValueRef::Binary(val) => Value::Binary(val.to_vec()),
            &ValueRef::Array(ref val) => {
                Value::Array(val.iter().map(|v| v.to_owned()).collect())
            }
            &ValueRef::Map(ref val) => {
                Value::Map(val.iter().map(|&(ref k, ref v)| (k.to_owned(), v.to_owned())).collect())
            }
            &ValueRef::Ext(ty, buf) => Value::Ext(ty, buf.to_vec()),
        }
    }
}

// For some weird reasons I can't implement it manually.
// It gives: conflicting implementations for trait `collections::borrow::ToOwned`
// impl<'a> ToOwned for ValueRef<'a> {
//     type Owned = Value;
// }
<commit_msg>Perf(value): use `to_owned` instead of `to_string`<commit_after>//! Contains Value and ValueRef structs and its conversion traits.

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Integer {
    /// Every non-negative integer is treated as u64, even if it fits in i64.
    U64(u64),
    /// Every negative integer is treated as i64.
    I64(i64),
}

#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Float {
    F32(f32),
    F64(f64),
}

#[derive(Clone, Debug, PartialEq)]
pub enum Value {
    /// Nil represents nil.
    Nil,
    /// Boolean represents true or false.
    Boolean(bool),
    /// Integer represents an integer.
    Integer(Integer),
    /// Float represents a floating point number.
    Float(Float),
    /// String extending Raw type represents a UTF-8 string.
    String(String),
    /// Binary extending Raw type represents a byte array.
    Binary(Vec<u8>),
    /// Array represents a sequence of objects.
    Array(Vec<Value>),
    /// Map represents key-value pairs of objects.
    Map(Vec<(Value, Value)>),
    /// Extended implements Extension interface: represents a tuple of type information and a byte
    /// array where type information is an integer whose meaning is defined by applications.
    Ext(i8, Vec<u8>),
}

#[derive(Clone, Debug, PartialEq)]
pub enum ValueRef<'a> {
   /// Nil represents nil.
   Nil,
   /// Boolean represents true or false.
   Boolean(bool),
   /// Integer represents an integer.
   Integer(Integer),
   /// Float represents a floating point number.
   Float(Float),
   /// String extending Raw type represents a UTF-8 string.
   String(&'a str),
   /// Binary extending Raw type represents a byte array.
   Binary(&'a [u8]),
   /// Array represents a sequence of objects.
   Array(Vec<ValueRef<'a>>),
   /// Map represents key-value pairs of objects.
   Map(Vec<(ValueRef<'a>, ValueRef<'a>)>),
   /// Extended implements Extension interface: represents a tuple of type information and a byte
   /// array where type information is an integer whose meaning is defined by applications.
   Ext(i8, &'a [u8]),
}

impl<'a> ValueRef<'a> {
    /// Converts the current non-owning value to an owned Value.
    ///
    /// This is achieved by deep copying all underlying structures and borrowed buffers.
    ///
    /// # Panics
    ///
    /// Panics in unable to allocate memory to keep all internal structures and buffers.
    ///
    /// # Examples
    /// ```
    /// use rmp::{Value, ValueRef};
    /// use rmp::value::Integer;
    ///
    /// let val = ValueRef::Array(vec![
    ///    ValueRef::Nil,
    ///    ValueRef::Integer(Integer::U64(42)),
    ///    ValueRef::Array(vec![
    ///        ValueRef::String("le message"),
    ///    ])
    /// ]);
    ///
    /// let expected = Value::Array(vec![
    ///     Value::Nil,
    ///     Value::Integer(Integer::U64(42)),
    ///     Value::Array(vec![
    ///         Value::String("le message".to_string())
    ///     ])
    /// ]);
    ///
    /// assert_eq!(expected, val.to_owned());
    /// ```
    pub fn to_owned(&self) -> Value {
        match self {
            &ValueRef::Nil => Value::Nil,
            &ValueRef::Boolean(val) => Value::Boolean(val),
            &ValueRef::Integer(val) => Value::Integer(val),
            &ValueRef::Float(val) => Value::Float(val),
            &ValueRef::String(val) => Value::String(val.to_owned()),
            &ValueRef::Binary(val) => Value::Binary(val.to_vec()),
            &ValueRef::Array(ref val) => {
                Value::Array(val.iter().map(|v| v.to_owned()).collect())
            }
            &ValueRef::Map(ref val) => {
                Value::Map(val.iter().map(|&(ref k, ref v)| (k.to_owned(), v.to_owned())).collect())
            }
            &ValueRef::Ext(ty, buf) => Value::Ext(ty, buf.to_vec()),
        }
    }
}

// For some weird reasons I can't implement it manually.
// It gives: conflicting implementations for trait `collections::borrow::ToOwned`
// impl<'a> ToOwned for ValueRef<'a> {
//     type Owned = Value;
// }
<|endoftext|>


<commit_before>use csv;
use regex::Regex;
use std::result::Result;
use std::str;
use std::process;
use curl::http;
use rustc_serialize::json;

fn get_page(url: String, token: &str) -> http::Response {
    let auth_header = format!("token {}", token);
    let res = http::handle()
                   .get(url)
                   .header("Authorization", &auth_header)
                   .header("User-Agent", "Github-Issues-CLI")
                   .header("Accept", "application/vnd.github.v3+json")
                   .exec()
                   .unwrap_or_else(|e| process::exit(1));

    res
}

fn next_url(link: String) -> Option<String> {
    let re = Regex::new(r"<([^;]+)>;\s*rel=.next.").unwrap();
    match re.captures(&link) {
        None => None,
        Some(cs) => cs.at(1).as_ref().map(|x| x.to_string())
    }
}

fn to_issues(raw: &[u8]) -> Result<Issues, json::DecoderError> {
    match str::from_utf8(raw) {
        Ok(b) => json::decode(b),
        Err(..) => {
            println!("Unable to parse the response from Github");
            process::exit(1)
        }
    }
}

pub fn run(owner: &str,
           repo: &str,
           oauth_token: String,
           labels: Vec<String>,
           output_file: String) {

    let page = 1;
    let url = format!("https://api.github.com/repos/{}/{}/issues?state=all&page={}&labels={}",
                      owner, repo, page, labels.join(","));

    println!("Fetching {:?}", url);
    let res = get_page(url, &oauth_token);
    let mut issues = to_issues(res.get_body()).unwrap();

    // A Link header is not present if the requested collection has less than
    // _pagesize_.
    match res.get_headers().get("link") {
        Some(links) => {
            let mut nurl = next_url(links.first().unwrap().clone());

            while let Some(nu) = nurl {
                println!("Fetching {:?}", nu);
                let r = get_page(nu.to_string(), &oauth_token);
                issues.extend(to_issues(r.get_body()).unwrap());

                let link = r.get_headers().get("link").unwrap()
                                          .first().unwrap()
                                          .clone();
                nurl = next_url(link);
            }
        }
        _ => {}
    }

    // let mut wtr = csv::Writer::from_memory();
    let mut wtr = csv::Writer::from_file(output_file).unwrap();
    let headers = ("number",
                   "title",
                   "state",
                   "created_at",
                   "closed_at",
                   "assignee",
                   "user",
                   "labels",
                   "body");
    wtr.encode(headers);

    println!("Total issues collected: {:?}", issues.len());

    for issue in issues {
        let labels = issue.labels.iter()
                                 .map(|x| x.name.clone())
                                 .collect::<Vec<String>>()
                                 .join(",");
        let user = issue.user;
        let assignee = issue.assignee;

        let row = (issue.number,
                   issue.title,
                   issue.state,
                   issue.created_at,
                   issue.closed_at,
                   assignee,
                   user,
                   labels,
                   issue.body);

        // println!("{:?}", row);
        // let result = wtr.encode(row);
        // println!("{:?}", result.is_ok());
        wtr.encode(row);
    }

    // println!("{:?}", wtr.as_string());
}

#[derive(Debug, RustcDecodable, RustcEncodable)]
struct Issue {
    assignee: Option<User>,
    body: Option<String>,
    created_at: Option<String>,
    closed_at: Option<String>,
    labels: Labels,
    number: u32,
    state: Option<String>,
    title: Option<String>,
    user: Option<User>,
}

type Issues = Vec<Issue>;

type Labels = Vec<Label>;

#[derive(Debug, RustcDecodable, RustcEncodable)]
struct Label {
    color: String,
    name: String,
}

#[derive(Debug, RustcDecodable, RustcEncodable)]
struct User {
    login: String,
}
<commit_msg>Add non-200 error handler<commit_after>use csv;
use regex::Regex;
use std::result::Result;
use std::str;
use std::process;
use curl::http;
use rustc_serialize::json;

fn get_page(url: String, token: &str) -> http::Response {
    println!("Fetching {:?}", url);
    let auth_header = format!("token {}", token);
    let res = http::handle()
                   .get(url)
                   .header("Authorization", &auth_header)
                   .header("User-Agent", "Github-Issues-CLI")
                   .header("Accept", "application/vnd.github.v3+json")
                   .exec()
                   .unwrap_or_else(|e| process::exit(1));

    if res.get_code() != 200 {
        match str::from_utf8(res.get_body()) {
            Ok(b) => {
                println!("{:?}", json::decode::<GithubError>(b).ok());
                process::exit(1)
            }
            Err(..) => {
                println!("Unable to parse the response from Github");
                process::exit(1)
            }
        }
    }

    res
}

fn next_url(link: String) -> Option<String> {
    let re = Regex::new(r"<([^;]+)>;\s*rel=.next.").unwrap();
    match re.captures(&link) {
        None => None,
        Some(cs) => cs.at(1).as_ref().map(|x| x.to_string())
    }
}

fn to_issues(raw: &[u8]) -> Result<Issues, json::DecoderError> {
    match str::from_utf8(raw) {
        Ok(b) => json::decode(b),
        Err(..) => {
            println!("Unable to parse the response from Github");
            process::exit(1)
        }
    }
}

pub fn run(owner: &str,
           repo: &str,
           oauth_token: String,
           labels: Vec<String>,
           output_file: String) {

    let page = 1;
    let url = format!("https://api.github.com/repos/{}/{}/issues?state=all&page={}&labels={}",
                      owner, repo, page, labels.join(","));

    let res = get_page(url, &oauth_token);
    let mut issues = to_issues(res.get_body()).unwrap();

    // A Link header is not present if the requested collection has less than
    // _pagesize_.
    match res.get_headers().get("link") {
        Some(links) => {
            let mut nurl = next_url(links.first().unwrap().clone());

            while let Some(nu) = nurl {
                let r = get_page(nu.to_string(), &oauth_token);
                issues.extend(to_issues(r.get_body()).unwrap());

                let link = r.get_headers().get("link").unwrap()
                                          .first().unwrap()
                                          .clone();
                nurl = next_url(link);
            }
        }
        _ => {}
    }

    // let mut wtr = csv::Writer::from_memory();
    let mut wtr = csv::Writer::from_file(output_file).unwrap();
    let headers = ("number",
                   "title",
                   "state",
                   "created_at",
                   "closed_at",
                   "assignee",
                   "user",
                   "labels",
                   "body");
    wtr.encode(headers);

    println!("Total issues collected: {:?}", issues.len());

    for issue in issues {
        let labels = issue.labels.iter()
                                 .map(|x| x.name.clone())
                                 .collect::<Vec<String>>()
                                 .join(",");
        let user = issue.user;
        let assignee = issue.assignee;

        let row = (issue.number,
                   issue.title,
                   issue.state,
                   issue.created_at,
                   issue.closed_at,
                   assignee,
                   user,
                   labels,
                   issue.body);

        // println!("{:?}", row);
        // let result = wtr.encode(row);
        // println!("{:?}", result.is_ok());
        wtr.encode(row);
    }

    // println!("{:?}", wtr.as_string());
}

#[derive(Debug, RustcDecodable, RustcEncodable)]
struct Issue {
    assignee: Option<User>,
    body: Option<String>,
    created_at: Option<String>,
    closed_at: Option<String>,
    labels: Labels,
    number: u32,
    state: Option<String>,
    title: Option<String>,
    user: Option<User>,
}

type Issues = Vec<Issue>;

type Labels = Vec<Label>;

#[derive(Debug, RustcDecodable, RustcEncodable)]
struct Label {
    color: String,
    name: String,
}

#[derive(Debug, RustcDecodable, RustcEncodable)]
struct User {
    login: String,
}

#[derive(Debug, RustcDecodable, RustcEncodable)]
struct GithubError {
    message: String,
    documentation_url: String,
}
<|endoftext|>