<commit_before>use libc::{c_char, c_uint};
use ffi::prelude::{LLVMBuilderRef, LLVMValueRef};
use ffi::{core, LLVMBuilder, LLVMRealPredicate, LLVMIntPredicate};
use cbox::{CSemiBox, DisposeRef};
use std::mem;
use block::BasicBlock;
use context::Context;
use ty::Type;
use value::{Function, Value, Predicate};

static NULL_NAME:[c_char; 1] = [0];

/// This provides a uniform API for creating instructions and inserting them into a basic block.
pub struct Builder;
native_ref!(&Builder = LLVMBuilderRef);
macro_rules! bin_op(
    ($name:ident, $func:ident) => (
        pub fn $name(&self, left: &Value, right: &Value) -> &Value {
            unsafe { core::$func(self.into(), left.into(), right.into(), NULL_NAME.as_ptr()) }.into()
        }
    );
    ($name:ident, $ifunc:ident, $ffunc:ident) => (
        pub fn $name(&self, left: &Value, right: &Value) -> &Value {
            let ty = left.get_type();
            unsafe {
                (if ty.is_integer() {
                    core::$ifunc
                } else {
                    core::$ffunc
                })(self.into(), left.into(), right.into(), NULL_NAME.as_ptr()).into()
            }
        }
    );
);
macro_rules! un_op(
    ($name:ident, $func:ident) => (
        pub fn $name(&self, value: &Value) -> &Value {
            unsafe { core::$func(self.into(), value.into(), NULL_NAME.as_ptr() as *const c_char) }.into()
        }
    );
);
impl Builder {
    /// Create a new builder in the context given.
    pub fn new(context: &Context) -> CSemiBox<Builder> {
        CSemiBox::new(unsafe { core::LLVMCreateBuilderInContext(context.into()) }.into())
    }
    /// Position the builder at the end of `block`.
    pub fn position_at_end(&self, block: &BasicBlock) {
        unsafe { core::LLVMPositionBuilderAtEnd(self.into(), block.into()) }
    }
    /// Build an instruction that returns from the function with void.
    pub fn build_ret_void(&self) -> &Value {
        unsafe { core::LLVMBuildRetVoid(self.into()) }.into()
    }
    /// Build an instruction that returns from the function with `value`.
    pub fn build_ret(&self, value: &Value) -> &Value {
        unsafe { core::LLVMBuildRet(self.into(), value.into()) }.into()
    }
    /// Build an instruction that allocates an array with the element type `elem` and the size `size`.
    ///
    /// The size of this array will be the size of `elem` times `size`.
    pub fn build_array_alloca(&self, elem: &Type, size: &Value) -> &Value {
        unsafe { core::LLVMBuildArrayAlloca(self.into(), elem.into(), size.into(), NULL_NAME.as_ptr() as *const c_char) }.into()
    }
    /// Build an instruction that allocates a pointer to fit the size of `ty` then returns this pointer.
    ///
    /// Make sure to call `build_free` with the pointer value when you're done with it, or you're
    /// gonna have a bad time.
    pub fn build_alloca(&self, ty: &Type) -> &Value {
        unsafe { core::LLVMBuildAlloca(self.into(), ty.into(), NULL_NAME.as_ptr() as *const c_char) }.into()
    }
    /// Build an instruction that frees the `val`, which _MUST_ be a pointer that was returned
    /// from `build_alloca`.
    pub fn build_free(&self, val: &Value) -> &Value {
        unsafe { core::LLVMBuildFree(self.into(), val.into()) }.into()
    }
    /// Build an instruction that store the value `val` in the pointer `ptr`.
    pub fn build_store(&self, val: &Value, ptr: &Value) -> &Value {
        unsafe { core::LLVMBuildStore(self.into(), val.into(), ptr.into()) }.into()
    }
    /// Build an instruction that branches to the block `dest`.
    pub fn build_br(&self, dest: &BasicBlock) -> &Value {
        unsafe { core::LLVMBuildBr(self.into(), dest.into()).into() }
    }
    /// Build an instruction that branches to `if_block` if `cond` evaluates to true, and `else_block` otherwise.
    pub fn build_cond_br(&self, cond: &Value, if_block: &BasicBlock, else_block: Option<&BasicBlock>) -> &Value {
        unsafe { core::LLVMBuildCondBr(self.into(), cond.into(), if_block.into(), mem::transmute(else_block)).into() }
    }
    /// Build an instruction that calls the function `func` with the arguments `args`.
    ///
    /// This will return the return value of the function.
    pub fn build_call(&self, func: &Function, args: &[&Value]) -> &Value {
        unsafe {
            let call = core::LLVMBuildCall(self.into(), func.into(), args.as_ptr() as *mut LLVMValueRef, args.len() as c_uint, NULL_NAME.as_ptr());
            core::LLVMSetTailCall(call, 0);
            call.into()
        }
    }
    /// Build an instruction that calls the function `func` with the arguments `args`.
    ///
    /// This will return the return value of the function.
    pub fn build_tail_call(&self, func: &Function, args: &[&Value]) -> &Value {
        unsafe {
            let call = core::LLVMBuildCall(self.into(), func.into(), args.as_ptr() as *mut LLVMValueRef, args.len() as c_uint, NULL_NAME.as_ptr());
            core::LLVMSetTailCall(call, 1);
            call.into()
        }
    }
    /// Build an instruction that yields to `true_val` if `cond` is equal to `1`, and `false_val` otherwise.
    pub fn build_select(&self, cond: &Value, true_val: &Value, false_val: &Value) -> &Value {
        unsafe { core::LLVMBuildSelect(self.into(), cond.into(), true_val.into(), false_val.into(), NULL_NAME.as_ptr()).into() }
    }
    /// Build an instruction that casts a value into a certain type.
    pub fn build_bit_cast(&self, value: &Value, dest: &Type) -> &Value {
        unsafe { core::LLVMBuildBitCast(self.into(), value.into(), dest.into(), NULL_NAME.as_ptr()).into() }
    }
    /// Build an instruction that inserts a value into an aggregate data value.
    pub fn build_insert_value(&self, agg: &Value, elem: &Value, index: usize) -> &Value {
        unsafe { core::LLVMBuildInsertValue(self.into(), agg.into(), elem.into(), index as c_uint, NULL_NAME.as_ptr()).into() }
    }
    /// Build an instruction that computes the address of a subelement of an aggregate data structure.
    ///
    /// Basically type-safe pointer arithmetic.
    pub fn build_gep(&self, pointer: &Value, indices: &[&Value]) -> &Value {
        unsafe { core::LLVMBuildInBoundsGEP(self.into(), pointer.into(), indices.as_ptr() as *mut LLVMValueRef, indices.len() as c_uint, NULL_NAME.as_ptr()).into() }
    }
    /// Build an instruction that runs whichever block matches the value, or `default` if none of them matched it.
    pub fn build_switch(&self, value: &Value, default: &BasicBlock, cases: &[(&Value, &BasicBlock)]) -> &Value {
        unsafe {
            let switch = core::LLVMBuildSwitch(self.into(), value.into(), default.into(), cases.len() as c_uint);
            for case in cases {
                core::LLVMAddCase(switch, case.0.into(), case.1.into());
            }
            switch.into()
        }
    }
    un_op!{build_load, LLVMBuildLoad}
    un_op!{build_neg, LLVMBuildNeg}
    un_op!{build_not, LLVMBuildNot}
    bin_op!{build_add, LLVMBuildAdd, LLVMBuildFAdd}
    bin_op!{build_sub, LLVMBuildSub, LLVMBuildFSub}
    bin_op!{build_mul, LLVMBuildMul, LLVMBuildFMul}
    bin_op!{build_div, LLVMBuildSDiv, LLVMBuildFDiv}
    bin_op!{build_shl, LLVMBuildShl}
    bin_op!{build_ashr, LLVMBuildAShr}
    bin_op!{build_and, LLVMBuildAnd}
    bin_op!{build_or, LLVMBuildOr}
    /// Build an instruction to compare two values with the predicate given.
    pub fn build_cmp(&self, a: &Value, b: &Value, pred: Predicate) -> &Value {
        let (at, bt) = (a.get_type(), b.get_type());
        assert_eq!(at, bt);
        if at.is_integer() {
            let pred = match pred {
                Predicate::Equal => LLVMIntPredicate::LLVMIntEQ,
                Predicate::NotEqual => LLVMIntPredicate::LLVMIntNE,
                Predicate::GreaterThan => LLVMIntPredicate::LLVMIntSGT,
                Predicate::GreaterThanOrEqual => LLVMIntPredicate::LLVMIntSGE,
                Predicate::LessThan => LLVMIntPredicate::LLVMIntSLT,
                Predicate::LessThanOrEqual => LLVMIntPredicate::LLVMIntSLE
            };
            unsafe { core::LLVMBuildICmp(self.into(), pred, a.into(), b.into(), NULL_NAME.as_ptr()) }.into()
        } else if at.is_float() {
            let pred = match pred {
                Predicate::Equal => LLVMRealPredicate::LLVMRealOEQ,
                Predicate::NotEqual => LLVMRealPredicate::LLVMRealONE,
                Predicate::GreaterThan => LLVMRealPredicate::LLVMRealOGT,
                Predicate::GreaterThanOrEqual => LLVMRealPredicate::LLVMRealOGE,
                Predicate::LessThan => LLVMRealPredicate::LLVMRealOLT,
                Predicate::LessThanOrEqual => LLVMRealPredicate::LLVMRealOLE
            };
            unsafe { core::LLVMBuildFCmp(self.into(), pred, a.into(), b.into(), NULL_NAME.as_ptr()) }.into()
        } else {
            panic!("expected numbers, got {:?}", at)
        }
    }
}

impl DisposeRef for Builder {
    type RefTo = LLVMBuilder;
    #[inline(always)]
    unsafe fn dispose(ptr: LLVMBuilderRef) {
        core::LLVMDisposeBuilder(ptr)
    }
}
<commit_msg>Add build_trunc to Builder.<commit_after>use libc::{c_char, c_uint};
use ffi::prelude::{LLVMBuilderRef, LLVMValueRef};
use ffi::{core, LLVMBuilder, LLVMRealPredicate, LLVMIntPredicate};
use cbox::{CSemiBox, DisposeRef};
use std::mem;
use block::BasicBlock;
use context::Context;
use ty::Type;
use value::{Function, Value, Predicate};

static NULL_NAME:[c_char; 1] = [0];

/// This provides a uniform API for creating instructions and inserting them into a basic block.
pub struct Builder;
native_ref!(&Builder = LLVMBuilderRef);
macro_rules! bin_op(
    ($name:ident, $func:ident) => (
        pub fn $name(&self, left: &Value, right: &Value) -> &Value {
            unsafe { core::$func(self.into(), left.into(), right.into(), NULL_NAME.as_ptr()) }.into()
        }
    );
    ($name:ident, $ifunc:ident, $ffunc:ident) => (
        pub fn $name(&self, left: &Value, right: &Value) -> &Value {
            let ty = left.get_type();
            unsafe {
                (if ty.is_integer() {
                    core::$ifunc
                } else {
                    core::$ffunc
                })(self.into(), left.into(), right.into(), NULL_NAME.as_ptr()).into()
            }
        }
    );
);
macro_rules! un_op(
    ($name:ident, $func:ident) => (
        pub fn $name(&self, value: &Value) -> &Value {
            unsafe { core::$func(self.into(), value.into(), NULL_NAME.as_ptr() as *const c_char) }.into()
        }
    );
);
impl Builder {
    /// Create a new builder in the context given.
    pub fn new(context: &Context) -> CSemiBox<Builder> {
        CSemiBox::new(unsafe { core::LLVMCreateBuilderInContext(context.into()) }.into())
    }
    /// Position the builder at the end of `block`.
    pub fn position_at_end(&self, block: &BasicBlock) {
        unsafe { core::LLVMPositionBuilderAtEnd(self.into(), block.into()) }
    }
    /// Build an instruction that returns from the function with void.
    pub fn build_ret_void(&self) -> &Value {
        unsafe { core::LLVMBuildRetVoid(self.into()) }.into()
    }
    /// Build an instruction that returns from the function with `value`.
    pub fn build_ret(&self, value: &Value) -> &Value {
        unsafe { core::LLVMBuildRet(self.into(), value.into()) }.into()
    }
    /// Build an instruction that allocates an array with the element type `elem` and the size `size`.
    ///
    /// The size of this array will be the size of `elem` times `size`.
    pub fn build_array_alloca(&self, elem: &Type, size: &Value) -> &Value {
        unsafe { core::LLVMBuildArrayAlloca(self.into(), elem.into(), size.into(), NULL_NAME.as_ptr() as *const c_char) }.into()
    }
    /// Build an instruction that allocates a pointer to fit the size of `ty` then returns this pointer.
    ///
    /// Make sure to call `build_free` with the pointer value when you're done with it, or you're
    /// gonna have a bad time.
    pub fn build_alloca(&self, ty: &Type) -> &Value {
        unsafe { core::LLVMBuildAlloca(self.into(), ty.into(), NULL_NAME.as_ptr() as *const c_char) }.into()
    }
    /// Build an instruction that frees the `val`, which _MUST_ be a pointer that was returned
    /// from `build_alloca`.
    pub fn build_free(&self, val: &Value) -> &Value {
        unsafe { core::LLVMBuildFree(self.into(), val.into()) }.into()
    }
    /// Build an instruction that store the value `val` in the pointer `ptr`.
    pub fn build_store(&self, val: &Value, ptr: &Value) -> &Value {
        unsafe { core::LLVMBuildStore(self.into(), val.into(), ptr.into()) }.into()
    }
    /// Build an instruction that branches to the block `dest`.
    pub fn build_br(&self, dest: &BasicBlock) -> &Value {
        unsafe { core::LLVMBuildBr(self.into(), dest.into()).into() }
    }
    /// Build an instruction that branches to `if_block` if `cond` evaluates to true, and `else_block` otherwise.
    pub fn build_cond_br(&self, cond: &Value, if_block: &BasicBlock, else_block: Option<&BasicBlock>) -> &Value {
        unsafe { core::LLVMBuildCondBr(self.into(), cond.into(), if_block.into(), mem::transmute(else_block)).into() }
    }
    /// Build an instruction that calls the function `func` with the arguments `args`.
    ///
    /// This will return the return value of the function.
    pub fn build_call(&self, func: &Function, args: &[&Value]) -> &Value {
        unsafe {
            let call = core::LLVMBuildCall(self.into(), func.into(), args.as_ptr() as *mut LLVMValueRef, args.len() as c_uint, NULL_NAME.as_ptr());
            core::LLVMSetTailCall(call, 0);
            call.into()
        }
    }
    /// Build an instruction that calls the function `func` with the arguments `args`.
    ///
    /// This will return the return value of the function.
    pub fn build_tail_call(&self, func: &Function, args: &[&Value]) -> &Value {
        unsafe {
            let call = core::LLVMBuildCall(self.into(), func.into(), args.as_ptr() as *mut LLVMValueRef, args.len() as c_uint, NULL_NAME.as_ptr());
            core::LLVMSetTailCall(call, 1);
            call.into()
        }
    }
    /// Build an instruction that yields to `true_val` if `cond` is equal to `1`, and `false_val` otherwise.
    pub fn build_select(&self, cond: &Value, true_val: &Value, false_val: &Value) -> &Value {
        unsafe { core::LLVMBuildSelect(self.into(), cond.into(), true_val.into(), false_val.into(), NULL_NAME.as_ptr()).into() }
    }
    /// Build an instruction that casts a value into a certain type.
    pub fn build_bit_cast(&self, value: &Value, dest: &Type) -> &Value {
        unsafe { core::LLVMBuildBitCast(self.into(), value.into(), dest.into(), NULL_NAME.as_ptr()).into() }
    }
    /// Build an instruction that truncates the high-order bits of value to fit into a certain type.
    pub fn build_trunc(&self, value: &Value, dest: &Type) -> &Value {
        unsafe { core::LLVMBuildTrunc(self.into(), value.into(), dest.into(), NULL_NAME.as_ptr()).into() }
    }
    /// Build an instruction that inserts a value into an aggregate data value.
    pub fn build_insert_value(&self, agg: &Value, elem: &Value, index: usize) -> &Value {
        unsafe { core::LLVMBuildInsertValue(self.into(), agg.into(), elem.into(), index as c_uint, NULL_NAME.as_ptr()).into() }
    }
    /// Build an instruction that computes the address of a subelement of an aggregate data structure.
    ///
    /// Basically type-safe pointer arithmetic.
    pub fn build_gep(&self, pointer: &Value, indices: &[&Value]) -> &Value {
        unsafe { core::LLVMBuildInBoundsGEP(self.into(), pointer.into(), indices.as_ptr() as *mut LLVMValueRef, indices.len() as c_uint, NULL_NAME.as_ptr()).into() }
    }
    /// Build an instruction that runs whichever block matches the value, or `default` if none of them matched it.
    pub fn build_switch(&self, value: &Value, default: &BasicBlock, cases: &[(&Value, &BasicBlock)]) -> &Value {
        unsafe {
            let switch = core::LLVMBuildSwitch(self.into(), value.into(), default.into(), cases.len() as c_uint);
            for case in cases {
                core::LLVMAddCase(switch, case.0.into(), case.1.into());
            }
            switch.into()
        }
    }
    un_op!{build_load, LLVMBuildLoad}
    un_op!{build_neg, LLVMBuildNeg}
    un_op!{build_not, LLVMBuildNot}
    bin_op!{build_add, LLVMBuildAdd, LLVMBuildFAdd}
    bin_op!{build_sub, LLVMBuildSub, LLVMBuildFSub}
    bin_op!{build_mul, LLVMBuildMul, LLVMBuildFMul}
    bin_op!{build_div, LLVMBuildSDiv, LLVMBuildFDiv}
    bin_op!{build_shl, LLVMBuildShl}
    bin_op!{build_ashr, LLVMBuildAShr}
    bin_op!{build_and, LLVMBuildAnd}
    bin_op!{build_or, LLVMBuildOr}
    /// Build an instruction to compare two values with the predicate given.
    pub fn build_cmp(&self, a: &Value, b: &Value, pred: Predicate) -> &Value {
        let (at, bt) = (a.get_type(), b.get_type());
        assert_eq!(at, bt);
        if at.is_integer() {
            let pred = match pred {
                Predicate::Equal => LLVMIntPredicate::LLVMIntEQ,
                Predicate::NotEqual => LLVMIntPredicate::LLVMIntNE,
                Predicate::GreaterThan => LLVMIntPredicate::LLVMIntSGT,
                Predicate::GreaterThanOrEqual => LLVMIntPredicate::LLVMIntSGE,
                Predicate::LessThan => LLVMIntPredicate::LLVMIntSLT,
                Predicate::LessThanOrEqual => LLVMIntPredicate::LLVMIntSLE
            };
            unsafe { core::LLVMBuildICmp(self.into(), pred, a.into(), b.into(), NULL_NAME.as_ptr()) }.into()
        } else if at.is_float() {
            let pred = match pred {
                Predicate::Equal => LLVMRealPredicate::LLVMRealOEQ,
                Predicate::NotEqual => LLVMRealPredicate::LLVMRealONE,
                Predicate::GreaterThan => LLVMRealPredicate::LLVMRealOGT,
                Predicate::GreaterThanOrEqual => LLVMRealPredicate::LLVMRealOGE,
                Predicate::LessThan => LLVMRealPredicate::LLVMRealOLT,
                Predicate::LessThanOrEqual => LLVMRealPredicate::LLVMRealOLE
            };
            unsafe { core::LLVMBuildFCmp(self.into(), pred, a.into(), b.into(), NULL_NAME.as_ptr()) }.into()
        } else {
            panic!("expected numbers, got {:?}", at)
        }
    }
}

impl DisposeRef for Builder {
    type RefTo = LLVMBuilder;
    #[inline(always)]
    unsafe fn dispose(ptr: LLVMBuilderRef) {
        core::LLVMDisposeBuilder(ptr)
    }
}
<|endoftext|>


<commit_before>use core::borrow::{Borrow, BorrowMut};
use core::cmp::{self, Ordering};
use core::fmt::{self, Debug};
use core::hash::{Hash, Hasher};
use core::ops::{Deref, DerefMut};

#[cfg(feature = "alloc")]
use alloc::boxed::Box;
#[cfg(feature = "alloc")]
use alloc::string::String;
#[cfg(feature = "alloc")]
use alloc::vec::Vec;

use serde::de::{Deserialize, Deserializer, Error, SeqAccess, Visitor};
use serde::ser::{Serialize, Serializer};

use crate::Bytes;

/// Wrapper around `Vec<u8>` to serialize and deserialize efficiently.
///
/// ```
/// use std::collections::HashMap;
/// use std::io;
///
/// use serde_bytes::ByteBuf;
///
/// fn deserialize_bytebufs() -> bincode::Result<()> {
///     let example_data = [
///         2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 116,
///         119, 111, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 111, 110, 101];
///
///     let map: HashMap<u32, ByteBuf> = bincode::deserialize(&example_data[..])?;
///
///     println!("{:?}", map);
///
///     Ok(())
/// }
/// #
/// # fn main() {
/// #     deserialize_bytebufs().unwrap();
/// # }
/// ```
#[derive(Clone, Default, Eq, Ord)]
pub struct ByteBuf {
    bytes: Vec<u8>,
}

impl ByteBuf {
    /// Construct a new, empty `ByteBuf`.
    pub fn new() -> Self {
        ByteBuf::from(Vec::new())
    }

    /// Construct a new, empty `ByteBuf` with the specified capacity.
    pub fn with_capacity(cap: usize) -> Self {
        ByteBuf::from(Vec::with_capacity(cap))
    }

    /// Wrap existing bytes in a `ByteBuf`.
    pub fn from<T: Into<Vec<u8>>>(bytes: T) -> Self {
        ByteBuf {
            bytes: bytes.into(),
        }
    }

    /// Unwrap the vector of byte underlying this `ByteBuf`.
    pub fn into_vec(self) -> Vec<u8> {
        self.bytes
    }

    #[allow(missing_docs)]
    pub fn into_boxed_bytes(self) -> Box<Bytes> {
        self.bytes.into_boxed_slice().into()
    }
}

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

impl AsRef<[u8]> for ByteBuf {
    fn as_ref(&self) -> &[u8] {
        &self.bytes
    }
}

impl AsMut<[u8]> for ByteBuf {
    fn as_mut(&mut self) -> &mut [u8] {
        &mut self.bytes
    }
}

impl Deref for ByteBuf {
    type Target = Vec<u8>;

    fn deref(&self) -> &Self::Target {
        &self.bytes
    }
}

impl DerefMut for ByteBuf {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.bytes
    }
}

impl Borrow<Bytes> for ByteBuf {
    fn borrow(&self) -> &Bytes {
        Bytes::new(&self.bytes)
    }
}

impl BorrowMut<Bytes> for ByteBuf {
    fn borrow_mut(&mut self) -> &mut Bytes {
        unsafe { &mut *(&mut self.bytes as &mut [u8] as *mut [u8] as *mut Bytes) }
    }
}

impl<Rhs> PartialEq<Rhs> for ByteBuf
where
    Rhs: ?Sized + AsRef<[u8]>,
{
    fn eq(&self, other: &Rhs) -> bool {
        self.as_ref().eq(other.as_ref())
    }
}

impl<Rhs> PartialOrd<Rhs> for ByteBuf
where
    Rhs: ?Sized + AsRef<[u8]>,
{
    fn partial_cmp(&self, other: &Rhs) -> Option<Ordering> {
        self.as_ref().partial_cmp(other.as_ref())
    }
}

impl Hash for ByteBuf {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.bytes.hash(state);
    }
}

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

struct ByteBufVisitor;

impl<'de> Visitor<'de> for ByteBufVisitor {
    type Value = ByteBuf;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("byte array")
    }

    fn visit_seq<V>(self, mut visitor: V) -> Result<ByteBuf, V::Error>
    where
        V: SeqAccess<'de>,
    {
        let len = cmp::min(visitor.size_hint().unwrap_or(0), 4096);
        let mut values = Vec::with_capacity(len);

        while let Some(value) = visitor.next_element()? {
            values.push(value);
        }

        Ok(ByteBuf::from(values))
    }

    fn visit_bytes<E>(self, v: &[u8]) -> Result<ByteBuf, E>
    where
        E: Error,
    {
        Ok(ByteBuf::from(v))
    }

    fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<ByteBuf, E>
    where
        E: Error,
    {
        Ok(ByteBuf::from(v))
    }

    fn visit_str<E>(self, v: &str) -> Result<ByteBuf, E>
    where
        E: Error,
    {
        Ok(ByteBuf::from(v))
    }

    fn visit_string<E>(self, v: String) -> Result<ByteBuf, E>
    where
        E: Error,
    {
        Ok(ByteBuf::from(v))
    }
}

impl<'de> Deserialize<'de> for ByteBuf {
    fn deserialize<D>(deserializer: D) -> Result<ByteBuf, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_byte_buf(ByteBufVisitor)
    }
}
<commit_msg>Make into_boxed_slice bypass Deref<commit_after>use core::borrow::{Borrow, BorrowMut};
use core::cmp::{self, Ordering};
use core::fmt::{self, Debug};
use core::hash::{Hash, Hasher};
use core::ops::{Deref, DerefMut};

#[cfg(feature = "alloc")]
use alloc::boxed::Box;
#[cfg(feature = "alloc")]
use alloc::string::String;
#[cfg(feature = "alloc")]
use alloc::vec::Vec;

use serde::de::{Deserialize, Deserializer, Error, SeqAccess, Visitor};
use serde::ser::{Serialize, Serializer};

use crate::Bytes;

/// Wrapper around `Vec<u8>` to serialize and deserialize efficiently.
///
/// ```
/// use std::collections::HashMap;
/// use std::io;
///
/// use serde_bytes::ByteBuf;
///
/// fn deserialize_bytebufs() -> bincode::Result<()> {
///     let example_data = [
///         2, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 116,
///         119, 111, 1, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 111, 110, 101];
///
///     let map: HashMap<u32, ByteBuf> = bincode::deserialize(&example_data[..])?;
///
///     println!("{:?}", map);
///
///     Ok(())
/// }
/// #
/// # fn main() {
/// #     deserialize_bytebufs().unwrap();
/// # }
/// ```
#[derive(Clone, Default, Eq, Ord)]
pub struct ByteBuf {
    bytes: Vec<u8>,
}

impl ByteBuf {
    /// Construct a new, empty `ByteBuf`.
    pub fn new() -> Self {
        ByteBuf::from(Vec::new())
    }

    /// Construct a new, empty `ByteBuf` with the specified capacity.
    pub fn with_capacity(cap: usize) -> Self {
        ByteBuf::from(Vec::with_capacity(cap))
    }

    /// Wrap existing bytes in a `ByteBuf`.
    pub fn from<T: Into<Vec<u8>>>(bytes: T) -> Self {
        ByteBuf {
            bytes: bytes.into(),
        }
    }

    /// Unwrap the vector of byte underlying this `ByteBuf`.
    pub fn into_vec(self) -> Vec<u8> {
        self.bytes
    }

    #[allow(missing_docs)]
    pub fn into_boxed_bytes(self) -> Box<Bytes> {
        self.bytes.into_boxed_slice().into()
    }

    // This would hit "cannot move out of borrowed content" if invoked through
    // the Deref impl; make it just work.
    #[doc(hidden)]
    pub fn into_boxed_slice(self) -> Box<[u8]> {
        self.bytes.into_boxed_slice()
    }
}

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

impl AsRef<[u8]> for ByteBuf {
    fn as_ref(&self) -> &[u8] {
        &self.bytes
    }
}

impl AsMut<[u8]> for ByteBuf {
    fn as_mut(&mut self) -> &mut [u8] {
        &mut self.bytes
    }
}

impl Deref for ByteBuf {
    type Target = Vec<u8>;

    fn deref(&self) -> &Self::Target {
        &self.bytes
    }
}

impl DerefMut for ByteBuf {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.bytes
    }
}

impl Borrow<Bytes> for ByteBuf {
    fn borrow(&self) -> &Bytes {
        Bytes::new(&self.bytes)
    }
}

impl BorrowMut<Bytes> for ByteBuf {
    fn borrow_mut(&mut self) -> &mut Bytes {
        unsafe { &mut *(&mut self.bytes as &mut [u8] as *mut [u8] as *mut Bytes) }
    }
}

impl<Rhs> PartialEq<Rhs> for ByteBuf
where
    Rhs: ?Sized + AsRef<[u8]>,
{
    fn eq(&self, other: &Rhs) -> bool {
        self.as_ref().eq(other.as_ref())
    }
}

impl<Rhs> PartialOrd<Rhs> for ByteBuf
where
    Rhs: ?Sized + AsRef<[u8]>,
{
    fn partial_cmp(&self, other: &Rhs) -> Option<Ordering> {
        self.as_ref().partial_cmp(other.as_ref())
    }
}

impl Hash for ByteBuf {
    fn hash<H: Hasher>(&self, state: &mut H) {
        self.bytes.hash(state);
    }
}

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

struct ByteBufVisitor;

impl<'de> Visitor<'de> for ByteBufVisitor {
    type Value = ByteBuf;

    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter.write_str("byte array")
    }

    fn visit_seq<V>(self, mut visitor: V) -> Result<ByteBuf, V::Error>
    where
        V: SeqAccess<'de>,
    {
        let len = cmp::min(visitor.size_hint().unwrap_or(0), 4096);
        let mut values = Vec::with_capacity(len);

        while let Some(value) = visitor.next_element()? {
            values.push(value);
        }

        Ok(ByteBuf::from(values))
    }

    fn visit_bytes<E>(self, v: &[u8]) -> Result<ByteBuf, E>
    where
        E: Error,
    {
        Ok(ByteBuf::from(v))
    }

    fn visit_byte_buf<E>(self, v: Vec<u8>) -> Result<ByteBuf, E>
    where
        E: Error,
    {
        Ok(ByteBuf::from(v))
    }

    fn visit_str<E>(self, v: &str) -> Result<ByteBuf, E>
    where
        E: Error,
    {
        Ok(ByteBuf::from(v))
    }

    fn visit_string<E>(self, v: String) -> Result<ByteBuf, E>
    where
        E: Error,
    {
        Ok(ByteBuf::from(v))
    }
}

impl<'de> Deserialize<'de> for ByteBuf {
    fn deserialize<D>(deserializer: D) -> Result<ByteBuf, D::Error>
    where
        D: Deserializer<'de>,
    {
        deserializer.deserialize_byte_buf(ByteBufVisitor)
    }
}
<|endoftext|>


<commit_before>use ffi;
use types::{Result, PortMidiDeviceId, Error};
use io::{InputPort, OutputPort};
use device::DeviceInfo;

/// The elements are static after initializing
pub struct PortMidi {
    device_cnt: i32,
    buffer_size: i32,
}
impl PortMidi {
    /// Initializes the underlying PortMidi C library.
    /// It does not support *hot plugging*, this means
    /// that devices that are connect after calling `new`
    /// are not picked up by PortMidi.
    pub fn new() -> Result<Self> {
        try!(Result::from(unsafe { ffi::Pm_Initialize() }));

        Ok(PortMidi {
            device_cnt: unsafe { ffi::Pm_CountDevices() },
            buffer_size: 1024, // TODO: argument
        })
    }

    /// Return the number of devices. This number will not change during the lifetime
    /// of the program.
    pub fn device_cnt(&self) -> PortMidiDeviceId {
        self.device_cnt
    }

    /// Gets the `PortMidiDeviceId` for the default input, or `None` if
    /// there isn't one
    ///
    /// See the PortMidi documentation for details of how to set the default device
    pub fn default_input_device_id(&self) -> Result<PortMidiDeviceId> {
        match unsafe { ffi::Pm_GetDefaultInputDeviceID() } {
            ffi::PM_NO_DEVICE => Err(Error::NoDefaultDevice),
            id @ _ => Ok(id),
        }
    }

    /// Gets the `PortMidiDeviceId` for the default output, or `None` if
    /// there isn't one
    ///
    /// See the PortMidi documentation for details of how to set the default device
    pub fn default_output_device_id(&self) -> Result<PortMidiDeviceId> {
        match unsafe { ffi::Pm_GetDefaultOutputDeviceID() } {
            ffi::PM_NO_DEVICE => Err(Error::NoDefaultDevice),
            id @ _ => Ok(id),
        }
    }

    pub fn device_info(&self, id: PortMidiDeviceId) -> Result<DeviceInfo> {
        DeviceInfo::new(id)
    }

    pub fn default_input_port(&self) -> Result<InputPort> {
        let info = try!(self.default_input_device_id().and_then(|id| self.device_info(id)));
        InputPort::new(info, self.buffer_size)
    }

    pub fn input_port(&self, device: DeviceInfo) -> Result<InputPort> {
        if device.is_input() {
            InputPort::new(device, self.buffer_size)
        } else {
            Err(Error::Invalid)
        }
    }

    pub fn default_output_port(&self) -> Result<OutputPort> {
        let info = try!(self.default_output_device_id().and_then(|id| self.device_info(id)));
        OutputPort::new(info, self.buffer_size)
    }

    pub fn output_port(&self, device: DeviceInfo) -> Result<InputPort> {
        if device.is_output() {
            InputPort::new(device, self.buffer_size)
        } else {
            Err(Error::Invalid)
        }
    }
}
impl Drop for PortMidi {
    fn drop(&mut self) {
        Result::from(unsafe { ffi::Pm_Terminate() })
            .map_err(|err| println!("Could not terminate library: {}", err));
    }
}
<commit_msg>s/device_info/device/g<commit_after>use ffi;
use types::{Result, PortMidiDeviceId, Error};
use io::{InputPort, OutputPort};
use device::DeviceInfo;

/// The elements are static after initializing
pub struct PortMidi {
    device_cnt: i32,
    buffer_size: i32,
}
impl PortMidi {
    /// Initializes the underlying PortMidi C library.
    /// It does not support *hot plugging*, this means
    /// that devices that are connect after calling `new`
    /// are not picked up by PortMidi.
    pub fn new() -> Result<Self> {
        try!(Result::from(unsafe { ffi::Pm_Initialize() }));

        Ok(PortMidi {
            device_cnt: unsafe { ffi::Pm_CountDevices() },
            buffer_size: 1024, // TODO: argument
        })
    }

    /// Return the number of devices. This number will not change during the lifetime
    /// of the program.
    pub fn device_cnt(&self) -> PortMidiDeviceId {
        self.device_cnt
    }

    /// Gets the `PortMidiDeviceId` for the default input, or `None` if
    /// there isn't one
    ///
    /// See the PortMidi documentation for details of how to set the default device
    pub fn default_input_device_id(&self) -> Result<PortMidiDeviceId> {
        match unsafe { ffi::Pm_GetDefaultInputDeviceID() } {
            ffi::PM_NO_DEVICE => Err(Error::NoDefaultDevice),
            id @ _ => Ok(id),
        }
    }

    /// Gets the `PortMidiDeviceId` for the default output, or `None` if
    /// there isn't one
    ///
    /// See the PortMidi documentation for details of how to set the default device
    pub fn default_output_device_id(&self) -> Result<PortMidiDeviceId> {
        match unsafe { ffi::Pm_GetDefaultOutputDeviceID() } {
            ffi::PM_NO_DEVICE => Err(Error::NoDefaultDevice),
            id @ _ => Ok(id),
        }
    }

    pub fn device(&self, id: PortMidiDeviceId) -> Result<DeviceInfo> {
        DeviceInfo::new(id)
    }

    pub fn default_input_port(&self) -> Result<InputPort> {
        let info = try!(self.default_input_device_id().and_then(|id| self.device(id)));
        InputPort::new(info, self.buffer_size)
    }

    pub fn input_port(&self, device: DeviceInfo) -> Result<InputPort> {
        if device.is_input() {
            InputPort::new(device, self.buffer_size)
        } else {
            Err(Error::Invalid)
        }
    }

    pub fn default_output_port(&self) -> Result<OutputPort> {
        let info = try!(self.default_output_device_id().and_then(|id| self.device(id)));
        OutputPort::new(info, self.buffer_size)
    }

    pub fn output_port(&self, device: DeviceInfo) -> Result<InputPort> {
        if device.is_output() {
            InputPort::new(device, self.buffer_size)
        } else {
            Err(Error::Invalid)
        }
    }
}
impl Drop for PortMidi {
    fn drop(&mut self) {
        Result::from(unsafe { ffi::Pm_Terminate() })
            .map_err(|err| println!("Could not terminate library: {}", err));
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2015, Nathan Zadoks <nathan@nathan7.eu>
// See the LICENSE file included in this distribution.
use core::prelude::*;
use core::marker::PhantomData;
use arch::Registers;
use stack;
use debug::StackId;

#[derive(Debug)]
pub struct Context<'a, Stack: stack::Stack> {
  regs: Registers,
  _stack_id: StackId,
  stack: Stack,
  _ref: PhantomData<&'a ()>
}

unsafe impl<'a, Stack> Send for Context<'a, Stack>
  where Stack: stack::Stack + Send {}

impl<'a, Stack> Context<'a, Stack> where Stack: stack::Stack {
  #[inline]
  pub unsafe fn new<F>(mut stack: Stack, f: F) -> Context<'a, Stack>
    where F: FnOnce() + Send + 'a {
    let stack_id = StackId::register(&mut stack);
    let regs = Registers::new(&mut stack, f);
    Context {
      regs: regs,
      _stack_id: stack_id,
      stack: stack,
      _ref: PhantomData
    }
  }

  #[inline(always)]
  pub unsafe fn swap(&mut self) {
    self.regs.swap()
  }

  #[inline]
  pub unsafe fn destroy(self) -> Stack {
    self.stack
  }
}
<commit_msg>rename Context::destroy to Context::unwrap, in line with lang conventions<commit_after>// Copyright (c) 2015, Nathan Zadoks <nathan@nathan7.eu>
// See the LICENSE file included in this distribution.
use core::prelude::*;
use core::marker::PhantomData;
use arch::Registers;
use stack;
use debug::StackId;

#[derive(Debug)]
pub struct Context<'a, Stack: stack::Stack> {
  regs: Registers,
  _stack_id: StackId,
  stack: Stack,
  _ref: PhantomData<&'a ()>
}

unsafe impl<'a, Stack> Send for Context<'a, Stack>
  where Stack: stack::Stack + Send {}

impl<'a, Stack> Context<'a, Stack> where Stack: stack::Stack {
  #[inline]
  pub unsafe fn new<F>(mut stack: Stack, f: F) -> Context<'a, Stack>
    where F: FnOnce() + Send + 'a {
    let stack_id = StackId::register(&mut stack);
    let regs = Registers::new(&mut stack, f);
    Context {
      regs: regs,
      _stack_id: stack_id,
      stack: stack,
      _ref: PhantomData
    }
  }

  #[inline(always)]
  pub unsafe fn swap(&mut self) {
    self.regs.swap()
  }

  #[inline]
  pub unsafe fn unwrap(self) -> Stack {
    self.stack
  }
}
<|endoftext|>


<commit_before>use ffi;
use types::{Result, PortMidiDeviceId, Error};
use io::{InputPort, OutputPort};
use device::DeviceInfo;

/// The elements are static after initializing
pub struct PortMidi {
    device_cnt: i32,
    buffer_size: usize,
}
impl PortMidi {
    /// Initializes the underlying PortMidi C library.
    /// It does not support *hot plugging*, this means
    /// that devices that are connect after calling `new`
    /// are not picked up by PortMidi.
    pub fn new() -> Result<Self> {
        try!(Result::from(unsafe { ffi::Pm_Initialize() }));

        Ok(PortMidi {
            device_cnt: unsafe { ffi::Pm_CountDevices() },
            buffer_size: 1024, // TODO: argument
        })
    }

    /// Return the number of devices. This number will not change during the lifetime
    /// of the program.
    pub fn device_cnt(&self) -> PortMidiDeviceId {
        self.device_cnt
    }

    /// Gets the `PortMidiDeviceId` for the default input, or `None` if
    /// there isn't one
    ///
    /// See the PortMidi documentation for details of how to set the default device
    pub fn default_input_device_id(&self) -> Result<PortMidiDeviceId> {
        match unsafe { ffi::Pm_GetDefaultInputDeviceID() } {
            ffi::PM_NO_DEVICE => Err(Error::NoDefaultDevice),
            id @ _ => Ok(id),
        }
    }

    /// Gets the `PortMidiDeviceId` for the default output, or `None` if
    /// there isn't one
    ///
    /// See the PortMidi documentation for details of how to set the default device
    pub fn default_output_device_id(&self) -> Result<PortMidiDeviceId> {
        match unsafe { ffi::Pm_GetDefaultOutputDeviceID() } {
            ffi::PM_NO_DEVICE => Err(Error::NoDefaultDevice),
            id @ _ => Ok(id),
        }
    }

    pub fn device(&self, id: PortMidiDeviceId) -> Result<DeviceInfo> {
        DeviceInfo::new(id)
    }

    pub fn devices(&self) -> Result<Vec<DeviceInfo>> {
        let mut devices = Vec::with_capacity(self.device_cnt() as usize);
        for res in (0..self.device_cnt()).map(|id| self.device(id)) {
            match res {
                Ok(device) => devices.push(device),
                Err(err) => return Err(err),
            }
        }
        Ok(devices)
    }

    pub fn default_input_port(&self) -> Result<InputPort> {
        let info = try!(self.default_input_device_id().and_then(|id| self.device(id)));
        InputPort::new(info, self.buffer_size)
    }

    pub fn input_port(&self, device: DeviceInfo) -> Result<InputPort> {
        if device.is_input() {
            InputPort::new(device, self.buffer_size)
        } else {
            Err(Error::NotAnInputDevice)
        }
    }

    pub fn default_output_port(&self) -> Result<OutputPort> {
        let info = try!(self.default_output_device_id().and_then(|id| self.device(id)));
        OutputPort::new(info, self.buffer_size)
    }

    pub fn output_port(&self, device: DeviceInfo) -> Result<InputPort> {
        if device.is_output() {
            InputPort::new(device, self.buffer_size)
        } else {
            Err(Error::NotAnOutputDevice)
        }
    }
}
impl Drop for PortMidi {
    fn drop(&mut self) {
        Result::from(unsafe { ffi::Pm_Terminate() })
            .map_err(|err| println!("Could not terminate: {}", err));
    }
}
<commit_msg>Pass `buffer_size` on context instantiation<commit_after>use ffi;
use types::{Result, PortMidiDeviceId, Error};
use io::{InputPort, OutputPort};
use device::DeviceInfo;

/// The elements are static after initializing
pub struct PortMidi {
    device_cnt: i32,
    buffer_size: usize,
}
impl PortMidi {
    /// Initializes the underlying PortMidi C library.
    /// It does not support *hot plugging*, this means
    /// that devices that are connect after calling `new`
    /// are not picked up by PortMidi.
    pub fn new(buffer_size: usize) -> Result<Self> {
        try!(Result::from(unsafe { ffi::Pm_Initialize() }));

        Ok(PortMidi {
            device_cnt: unsafe { ffi::Pm_CountDevices() },
            buffer_size: buffer_size,
        })
    }

    /// Return the number of devices. This number will not change during the lifetime
    /// of the program.
    pub fn device_cnt(&self) -> PortMidiDeviceId {
        self.device_cnt
    }

    /// Gets the `PortMidiDeviceId` for the default input, or `None` if
    /// there isn't one
    ///
    /// See the PortMidi documentation for details of how to set the default device
    pub fn default_input_device_id(&self) -> Result<PortMidiDeviceId> {
        match unsafe { ffi::Pm_GetDefaultInputDeviceID() } {
            ffi::PM_NO_DEVICE => Err(Error::NoDefaultDevice),
            id @ _ => Ok(id),
        }
    }

    /// Gets the `PortMidiDeviceId` for the default output, or `None` if
    /// there isn't one
    ///
    /// See the PortMidi documentation for details of how to set the default device
    pub fn default_output_device_id(&self) -> Result<PortMidiDeviceId> {
        match unsafe { ffi::Pm_GetDefaultOutputDeviceID() } {
            ffi::PM_NO_DEVICE => Err(Error::NoDefaultDevice),
            id @ _ => Ok(id),
        }
    }

    pub fn device(&self, id: PortMidiDeviceId) -> Result<DeviceInfo> {
        DeviceInfo::new(id)
    }

    pub fn devices(&self) -> Result<Vec<DeviceInfo>> {
        let mut devices = Vec::with_capacity(self.device_cnt() as usize);
        for res in (0..self.device_cnt()).map(|id| self.device(id)) {
            match res {
                Ok(device) => devices.push(device),
                Err(err) => return Err(err),
            }
        }
        Ok(devices)
    }

    pub fn default_input_port(&self) -> Result<InputPort> {
        let info = try!(self.default_input_device_id().and_then(|id| self.device(id)));
        InputPort::new(info, self.buffer_size)
    }

    pub fn input_port(&self, device: DeviceInfo) -> Result<InputPort> {
        if device.is_input() {
            InputPort::new(device, self.buffer_size)
        } else {
            Err(Error::NotAnInputDevice)
        }
    }

    pub fn default_output_port(&self) -> Result<OutputPort> {
        let info = try!(self.default_output_device_id().and_then(|id| self.device(id)));
        OutputPort::new(info, self.buffer_size)
    }

    pub fn output_port(&self, device: DeviceInfo) -> Result<InputPort> {
        if device.is_output() {
            InputPort::new(device, self.buffer_size)
        } else {
            Err(Error::NotAnOutputDevice)
        }
    }
}
impl Drop for PortMidi {
    fn drop(&mut self) {
        Result::from(unsafe { ffi::Pm_Terminate() })
            .map_err(|err| println!("Could not terminate: {}", err));
    }
}
<|endoftext|>


<commit_before>use types::{OscPacket, OscType, Result, OscMessage, OscMidiMessage, OscColor, OscBundle};
use errors::OscError;
use utils;

use std::{io, char};
use std::io::{Read, BufRead};

use byteorder::{BigEndian, ReadBytesExt};

/// Common MTP size for ethernet
pub const MTP: usize = 1536;

pub fn decode(msg: &[u8]) -> Result<OscPacket> {
    if msg.len() == 0 {
        return Err(OscError::BadPacket("Empty packet."));
    }

    match msg[0] as char {
        '/' => {
            decode_message(msg)
        }
        '#' => {
            decode_bundle(msg)
        }
        _ => Err(OscError::BadPacket("Unknown message format.")),
    }
}

fn decode_message(msg: &[u8]) -> Result<OscPacket> {
    let mut cursor: io::Cursor<&[u8]> = io::Cursor::new(msg);

    let addr: String = try!(read_osc_string(&mut cursor));
    let type_tags: String = try!(read_osc_string(&mut cursor));

    if type_tags.len() > 1 {
        let args: Vec<OscType> = try!(read_osc_args(&mut cursor, type_tags));

        Ok(OscPacket::Message(OscMessage {
            addr: addr,
            args: Some(args),
        }))
    } else {
        Ok(OscPacket::Message(OscMessage {
            addr: addr,
            args: None,
        }))
    }
}

fn decode_bundle(msg: &[u8]) -> Result<OscPacket> {
    let mut cursor: io::Cursor<&[u8]> = io::Cursor::new(msg);

    let bundle_tag = try!(read_osc_string(&mut cursor));
    if bundle_tag != "#bundle" {
        return Err(OscError::BadBundle(format!("Wrong bundle specifier: {}", bundle_tag)));
    }

    let time_tag = try!(read_time_tag(&mut cursor));

    let mut bundle: Vec<OscPacket> = Vec::new();

    let mut elem_size = try!(read_bundle_element_size(&mut cursor));

    while msg.len() >= (cursor.position() as usize) + elem_size {
        let packet = try!(read_bundle_element(&mut cursor, elem_size));
        bundle.push(packet);

        if msg.len() == cursor.position() as usize {
            break;
        }

        elem_size = try!(read_bundle_element_size(&mut cursor));
    }

    Ok(OscPacket::Bundle(OscBundle {
        timetag: time_tag,
        content: bundle,
    }))
}

fn read_bundle_element_size(cursor: &mut io::Cursor<&[u8]>) -> Result<usize> {
    cursor.read_u32::<BigEndian>()
          .map(|size| size as usize)
          .map_err(OscError::ByteOrderError)
}

fn read_bundle_element(cursor: &mut io::Cursor<&[u8]>, elem_size: usize) -> Result<OscPacket> {
    let mut buf: Vec<u8> = Vec::with_capacity(elem_size);

    let mut handle = cursor.take(elem_size as u64);

    let cnt = try!(handle.read_to_end(&mut buf)
                         .map_err(OscError::ReadError));

    if cnt == elem_size {
        decode(&mut buf)
    } else {
        Err(OscError::BadBundle("Bundle shorter than expected!".to_string()))
    }
}

fn read_osc_string(cursor: &mut io::Cursor<&[u8]>) -> Result<String> {
    let mut str_buf: Vec<u8> = Vec::new();
    try!(cursor.read_until(0, &mut str_buf)
               .map_err(OscError::ReadError)); // ignore returned byte count
    pad_cursor(cursor);
    // convert to String and remove nul bytes
    String::from_utf8(str_buf)
        .map_err(|e| OscError::StringError(e))
        .map(|s| {
            s.trim_matches(0u8 as char)
             .to_string()
        })
}

fn read_osc_args(cursor: &mut io::Cursor<&[u8]>, raw_type_tags: String) -> Result<Vec<OscType>> {
    let type_tags: Vec<char> = raw_type_tags.chars()
                                            .skip(1)
                                            .map(|c| c as char)
                                            .collect();

    let mut args: Vec<OscType> = Vec::with_capacity(type_tags.len());
    for tag in type_tags {
        let arg: OscType = try!(read_osc_arg(cursor, tag));
        args.push(arg);
    }
    Ok(args)
}

fn read_osc_arg(cursor: &mut io::Cursor<&[u8]>, tag: char) -> Result<OscType> {
    match tag {
        'f' => {
            cursor.read_f32::<BigEndian>()
                  .map(OscType::Float)
                  .map_err(OscError::ByteOrderError)
        }
        'd' => {
            cursor.read_f64::<BigEndian>()
                  .map(OscType::Double)
                  .map_err(OscError::ByteOrderError)
        }
        'i' => {
            cursor.read_i32::<BigEndian>()
                  .map(OscType::Int)
                  .map_err(OscError::ByteOrderError)
        }
        'h' => {
            cursor.read_i64::<BigEndian>()
                  .map(OscType::Long)
                  .map_err(OscError::ByteOrderError)
        }
        's' => {
            read_osc_string(cursor).map(|s| OscType::String(s))
        }
        't' => {
            read_time_tag(cursor)
        }
        'b' => {
            read_blob(cursor)
        }
        'r' => {
            read_osc_color(cursor)
        }
        'T' => {
            Ok(OscType::Bool(true))
        }
        'F' => {
            Ok(OscType::Bool(false))
        }
        'N' => {
            Ok(OscType::Nil)
        }
        'I' => {
            Ok(OscType::Inf)
        }
        'c' => {
            read_char(cursor)
        }
        'm' => {
            read_midi_message(cursor)
        }
        _ => Err(OscError::BadArg(format!("Type tag \"{}\" is not implemented!", tag))),
    }
}

fn read_char(cursor: &mut io::Cursor<&[u8]>) -> Result<OscType> {
    let opt_char = try!(cursor.read_u32::<BigEndian>()
                              .map(char::from_u32)
                              .map_err(OscError::ByteOrderError));
    match opt_char {
        Some(c) => Ok(OscType::Char(c)),
        None => Err(OscError::BadArg("Argument is not a char!".to_string())),
    }
}

fn read_blob(cursor: &mut io::Cursor<&[u8]>) -> Result<OscType> {
    let size: usize = try!(cursor.read_u32::<BigEndian>()
                                 .map_err(OscError::ByteOrderError)) as usize;
    let mut byte_buf: Vec<u8> = Vec::with_capacity(size);

    try!(cursor.take(size as u64)
               .read_to_end(&mut byte_buf)
               .map_err(OscError::ReadError));

    pad_cursor(cursor);

    Ok(OscType::Blob(byte_buf))
}

fn read_time_tag(cursor: &mut io::Cursor<&[u8]>) -> Result<OscType> {
    let date = try!(cursor.read_u32::<BigEndian>()
                          .map_err(OscError::ByteOrderError));
    let frac = try!(cursor.read_u32::<BigEndian>()
                          .map_err(OscError::ByteOrderError));

    Ok(OscType::Time(date, frac))
}

fn read_midi_message(cursor: &mut io::Cursor<&[u8]>) -> Result<OscType> {
    let mut buf: Vec<u8> = Vec::with_capacity(4);
    try!(cursor.take(4).read_to_end(&mut buf).map_err(OscError::ReadError));

    Ok(OscType::Midi(OscMidiMessage {
        port: buf[0],
        status: buf[1],
        data1: buf[2],
        data2: buf[3],
    }))

}

fn read_osc_color(cursor: &mut io::Cursor<&[u8]>) -> Result<OscType> {
    let mut buf: Vec<u8> = Vec::with_capacity(4);
    try!(cursor.take(4).read_to_end(&mut buf).map_err(OscError::ReadError));

    Ok(OscType::Color(OscColor {
        red: buf[0],
        green: buf[1],
        blue: buf[2],
        alpha: buf[3],
    }))
}

fn pad_cursor(cursor: &mut io::Cursor<&[u8]>) {
    let pos = cursor.position();
    cursor.set_position(utils::pad(pos));
}
<commit_msg>Remove unnecessary typecast<commit_after>use types::{OscPacket, OscType, Result, OscMessage, OscMidiMessage, OscColor, OscBundle};
use errors::OscError;
use utils;

use std::{io, char};
use std::io::{Read, BufRead};

use byteorder::{BigEndian, ReadBytesExt};

/// Common MTP size for ethernet
pub const MTP: usize = 1536;

pub fn decode(msg: &[u8]) -> Result<OscPacket> {
    if msg.len() == 0 {
        return Err(OscError::BadPacket("Empty packet."));
    }

    match msg[0] as char {
        '/' => {
            decode_message(msg)
        }
        '#' => {
            decode_bundle(msg)
        }
        _ => Err(OscError::BadPacket("Unknown message format.")),
    }
}

fn decode_message(msg: &[u8]) -> Result<OscPacket> {
    let mut cursor: io::Cursor<&[u8]> = io::Cursor::new(msg);

    let addr: String = try!(read_osc_string(&mut cursor));
    let type_tags: String = try!(read_osc_string(&mut cursor));

    if type_tags.len() > 1 {
        let args: Vec<OscType> = try!(read_osc_args(&mut cursor, type_tags));

        Ok(OscPacket::Message(OscMessage {
            addr: addr,
            args: Some(args),
        }))
    } else {
        Ok(OscPacket::Message(OscMessage {
            addr: addr,
            args: None,
        }))
    }
}

fn decode_bundle(msg: &[u8]) -> Result<OscPacket> {
    let mut cursor: io::Cursor<&[u8]> = io::Cursor::new(msg);

    let bundle_tag = try!(read_osc_string(&mut cursor));
    if bundle_tag != "#bundle" {
        return Err(OscError::BadBundle(format!("Wrong bundle specifier: {}", bundle_tag)));
    }

    let time_tag = try!(read_time_tag(&mut cursor));

    let mut bundle: Vec<OscPacket> = Vec::new();

    let mut elem_size = try!(read_bundle_element_size(&mut cursor));

    while msg.len() >= (cursor.position() as usize) + elem_size {
        let packet = try!(read_bundle_element(&mut cursor, elem_size));
        bundle.push(packet);

        if msg.len() == cursor.position() as usize {
            break;
        }

        elem_size = try!(read_bundle_element_size(&mut cursor));
    }

    Ok(OscPacket::Bundle(OscBundle {
        timetag: time_tag,
        content: bundle,
    }))
}

fn read_bundle_element_size(cursor: &mut io::Cursor<&[u8]>) -> Result<usize> {
    cursor.read_u32::<BigEndian>()
          .map(|size| size as usize)
          .map_err(OscError::ByteOrderError)
}

fn read_bundle_element(cursor: &mut io::Cursor<&[u8]>, elem_size: usize) -> Result<OscPacket> {
    let mut buf: Vec<u8> = Vec::with_capacity(elem_size);

    let mut handle = cursor.take(elem_size as u64);

    let cnt = try!(handle.read_to_end(&mut buf)
                         .map_err(OscError::ReadError));

    if cnt == elem_size {
        decode(&mut buf)
    } else {
        Err(OscError::BadBundle("Bundle shorter than expected!".to_string()))
    }
}

fn read_osc_string(cursor: &mut io::Cursor<&[u8]>) -> Result<String> {
    let mut str_buf: Vec<u8> = Vec::new();
    try!(cursor.read_until(0, &mut str_buf)
               .map_err(OscError::ReadError)); // ignore returned byte count
    pad_cursor(cursor);
    // convert to String and remove nul bytes
    String::from_utf8(str_buf)
        .map_err(|e| OscError::StringError(e))
        .map(|s| {
            s.trim_matches(0u8 as char)
             .to_string()
        })
}

fn read_osc_args(cursor: &mut io::Cursor<&[u8]>, raw_type_tags: String) -> Result<Vec<OscType>> {
    let type_tags: Vec<char> = raw_type_tags.chars()
                                            .skip(1)
                                            .collect();

    let mut args: Vec<OscType> = Vec::with_capacity(type_tags.len());
    for tag in type_tags {
        let arg: OscType = try!(read_osc_arg(cursor, tag));
        args.push(arg);
    }
    Ok(args)
}

fn read_osc_arg(cursor: &mut io::Cursor<&[u8]>, tag: char) -> Result<OscType> {
    match tag {
        'f' => {
            cursor.read_f32::<BigEndian>()
                  .map(OscType::Float)
                  .map_err(OscError::ByteOrderError)
        }
        'd' => {
            cursor.read_f64::<BigEndian>()
                  .map(OscType::Double)
                  .map_err(OscError::ByteOrderError)
        }
        'i' => {
            cursor.read_i32::<BigEndian>()
                  .map(OscType::Int)
                  .map_err(OscError::ByteOrderError)
        }
        'h' => {
            cursor.read_i64::<BigEndian>()
                  .map(OscType::Long)
                  .map_err(OscError::ByteOrderError)
        }
        's' => {
            read_osc_string(cursor).map(|s| OscType::String(s))
        }
        't' => {
            read_time_tag(cursor)
        }
        'b' => {
            read_blob(cursor)
        }
        'r' => {
            read_osc_color(cursor)
        }
        'T' => {
            Ok(OscType::Bool(true))
        }
        'F' => {
            Ok(OscType::Bool(false))
        }
        'N' => {
            Ok(OscType::Nil)
        }
        'I' => {
            Ok(OscType::Inf)
        }
        'c' => {
            read_char(cursor)
        }
        'm' => {
            read_midi_message(cursor)
        }
        _ => Err(OscError::BadArg(format!("Type tag \"{}\" is not implemented!", tag))),
    }
}

fn read_char(cursor: &mut io::Cursor<&[u8]>) -> Result<OscType> {
    let opt_char = try!(cursor.read_u32::<BigEndian>()
                              .map(char::from_u32)
                              .map_err(OscError::ByteOrderError));
    match opt_char {
        Some(c) => Ok(OscType::Char(c)),
        None => Err(OscError::BadArg("Argument is not a char!".to_string())),
    }
}

fn read_blob(cursor: &mut io::Cursor<&[u8]>) -> Result<OscType> {
    let size: usize = try!(cursor.read_u32::<BigEndian>()
                                 .map_err(OscError::ByteOrderError)) as usize;
    let mut byte_buf: Vec<u8> = Vec::with_capacity(size);

    try!(cursor.take(size as u64)
               .read_to_end(&mut byte_buf)
               .map_err(OscError::ReadError));

    pad_cursor(cursor);

    Ok(OscType::Blob(byte_buf))
}

fn read_time_tag(cursor: &mut io::Cursor<&[u8]>) -> Result<OscType> {
    let date = try!(cursor.read_u32::<BigEndian>()
                          .map_err(OscError::ByteOrderError));
    let frac = try!(cursor.read_u32::<BigEndian>()
                          .map_err(OscError::ByteOrderError));

    Ok(OscType::Time(date, frac))
}

fn read_midi_message(cursor: &mut io::Cursor<&[u8]>) -> Result<OscType> {
    let mut buf: Vec<u8> = Vec::with_capacity(4);
    try!(cursor.take(4).read_to_end(&mut buf).map_err(OscError::ReadError));

    Ok(OscType::Midi(OscMidiMessage {
        port: buf[0],
        status: buf[1],
        data1: buf[2],
        data2: buf[3],
    }))

}

fn read_osc_color(cursor: &mut io::Cursor<&[u8]>) -> Result<OscType> {
    let mut buf: Vec<u8> = Vec::with_capacity(4);
    try!(cursor.take(4).read_to_end(&mut buf).map_err(OscError::ReadError));

    Ok(OscType::Color(OscColor {
        red: buf[0],
        green: buf[1],
        blue: buf[2],
        alpha: buf[3],
    }))
}

fn pad_cursor(cursor: &mut io::Cursor<&[u8]>) {
    let pos = cursor.position();
    cursor.set_position(utils::pad(pos));
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

#[cfg(target_os = "linux")]
extern crate i2cdev;
extern crate termion;

#[cfg(target_os = "linux")]
use self::i2cdev::core::I2CDevice;
#[cfg(target_os = "linux")]
use self::i2cdev::linux::{LinuxI2CDevice, LinuxI2CError};

use std;
use shared::*;

const MODE_REGISTER: u8 = 0x00;
const FRAME_REGISTER: u8 = 0x01;
const AUTOPLAY1_REGISTER: u8 = 0x02;
const AUTOPLAY2_REGISTER: u8 = 0x03;
const BLINK_REGISTER: u8 = 0x05;
const AUDIOSYNC_REGISTER: u8 = 0x06;
const BREATH1_REGISTER: u8 = 0x08;
const BREATH2_REGISTER: u8 = 0x09;
const SHUTDOWN_REGISTER: u8 = 0x0A;
const GAIN_REGISTER: u8 = 0x0B;
const ADC_REGISTER: u8 = 0x0C;

const CONFIG_BANK: u8 = 0x0B;
const BANK_ADDRESS: u8 = 0xFD;

const PICTURE_MODE: u8 = 0x00;
const AUTOPLAY_MODE: u8 = 0x08;
const AUDIOPLAY_MODE: u8 = 0x18;

const ENABLE_OFFSET: u8 = 0x00;
const BLINK_OFFSET: u8 = 0x12;
const COLOR_OFFSET: u8 = 0x24;

const ADDRESS: u16 = 0x74;

const LED_COLUMNS: usize = 17;
const LED_ROWS: usize = 7;

/// Represents a device capable of displaying a rectangular bitmap buffer.
pub trait Display {
    fn show(&mut self, buffer: &[Column]);
}

#[cfg(target_os = "linux")]
/// A Scroll pHAT HD device connected over I2C bus (e.g. on a Raspberry Pi).
pub struct I2CDisplay {
    device: LinuxI2CDevice,
    frame: u8,
}

#[cfg(target_os = "linux")]
impl I2CDisplay {
    /// Creates a new I2CDisplay device using the I2C device identified by the provided
    /// `device_id` (normally 1 or 2).
    pub fn new(device_id: u8) -> I2CDisplay {
        let device_path = format!("/dev/i2c-{}", device_id);
        let d = LinuxI2CDevice::new(device_path, ADDRESS).unwrap();
        let mut display = I2CDisplay {
            device: d,
            frame: 0,
        };

        display.init_display().unwrap();

        display
    }

    fn bank(&mut self, bank: u8) -> Result<(), LinuxI2CError> {
        self.write_data(BANK_ADDRESS, &[bank])
    }

    fn register(&mut self, bank: u8, register: u8, value: u8) -> Result<(), LinuxI2CError> {
        self.bank(bank);
        self.write_data(register, &[value])
    }

    fn frame(&mut self, frame: u8) -> Result<(), LinuxI2CError> {
        self.register(CONFIG_BANK, FRAME_REGISTER, frame)
    }

    fn write_data(&mut self, base_address: u8, data: &[u8]) -> Result<(), LinuxI2CError> {
        for i in 0..data.len() {
            self.device
                .smbus_write_byte_data(base_address + (i as u8), data[i])?;
        }
        Ok(())
    }

    fn reset_display(&mut self) -> Result<(), LinuxI2CError> {
        self.sleep(true)?;
        std::thread::sleep(std::time::Duration::from_millis(10));
        self.sleep(false)?;
        Ok(())
    }

    fn init_display(&mut self) -> Result<(), LinuxI2CError> {
        self.reset_display()?;

        // Switch to Picture Mode.
        self.register(CONFIG_BANK, MODE_REGISTER, PICTURE_MODE)?;

        // Disable audio sync.
        self.register(CONFIG_BANK, AUDIOSYNC_REGISTER, 0)?;

        // Initialize frames 0 and 1.
        for frame in 0..2 {
            self.write_data(BANK_ADDRESS, &[frame])?;

            // Turn off blinking for all LEDs.
            self.write_data(BLINK_OFFSET, &[0; LED_COLUMNS])?;

            // Set the PWM duty cycle for all LEDs to 0%.
            self.write_data(COLOR_OFFSET, &[0; LED_COLUMNS * LED_ROWS])?;

            // Turn all LEDs "on".
            self.write_data(ENABLE_OFFSET, &[127; LED_COLUMNS])?;
        }

        Ok(())
    }

    fn sleep(&mut self, value: bool) -> Result<(), LinuxI2CError> {
        self.register(CONFIG_BANK, SHUTDOWN_REGISTER, if value { 0 } else { 1 })
    }
}

#[cfg(target_os = "linux")]
impl Display for I2CDisplay {
    fn show(&mut self, buffer: &[Column]) {
        let new_frame = (self.frame + 1) % 2;
        self.bank(new_frame);
        for y in 0..DISPLAY_HEIGHT {
            for x in 0..DISPLAY_WIDTH {
                let offset = if x >= 8 {
                    (x - 8) * 16 + y
                } else {
                    (8 - x) * 16 - (y + 2)
                };
                let value = match buffer.get(x as usize) {
                    Some(column) => column[y as usize],
                    None => 0,
                };
                self.write_data(COLOR_OFFSET + offset as u8, &[value]);
            }
        }
        self.frame(new_frame);
        self.frame = new_frame;
    }
}

/// A virtual display that outputs its buffer to the terminal from which the binary is attached.
///
/// Useful for debugging or prototyping, as it does not require a physical display to be connected.
pub struct TermDisplay {}

impl TermDisplay {
    pub fn new() -> TermDisplay {
        TermDisplay {}
    }
}

impl Display for TermDisplay {
    fn show(&mut self, buffer: &[Column]) {
        print!("{}", termion::clear::All);
        for x in 0..buffer.len() {
            let col = &buffer[x];
            for y in 0..col.len() {
                let c = col[y];
                let v = if c == 0 { ' ' } else { '#' };
                println!("{}{}", termion::cursor::Goto(x as u16 + 1, y as u16 + 1), v);
            }
        }
    }
}

/// A virtual display that outputs its buffer to the terminal from which the binary is attached.
///
/// Useful for debugging or prototyping, as it does not require a physical display to be connected.
pub struct UnicodeDisplay {}

impl UnicodeDisplay {
    pub fn new() -> UnicodeDisplay {
        UnicodeDisplay {}
    }
}

impl Display for UnicodeDisplay {
    fn show(&mut self, buffer: &[Column]) {
        print!("{}", termion::clear::All);

        let col = &buffer[0];

        println!("{}╔", termion::cursor::Goto(1, 1));
        for y in 0..col.len() {
            println!("{}║", termion::cursor::Goto(1, y as u16 + 2));
        }
        println!("{}╚", termion::cursor::Goto(1, col.len() as u16 + 2));

        for x in 0..buffer.len() {
            let col = &buffer[x];
            println!("{}═", termion::cursor::Goto(x as u16 + 2, 1));
            for y in 0..col.len() {
                let c = col[y];
                let v = if c == 0 { '░' } else { '▓' };
                println!("{}{}", termion::cursor::Goto(x as u16 + 2, y as u16 + 2), v);
            }
            println!(
                "{}═",
                termion::cursor::Goto(x as u16 + 2, col.len() as u16 + 2)
            );
        }

        println!("{}╗", termion::cursor::Goto(buffer.len() as u16 + 1, 1));
        for y in 0..col.len() {
            println!(
                "{}║",
                termion::cursor::Goto(buffer.len() as u16 + 1, y as u16 + 2)
            );
        }
        println!(
            "{}╝",
            termion::cursor::Goto(buffer.len() as u16 + 1, col.len() as u16 + 2)
        );
    }
}
<commit_msg>Actually initialise all LEDs<commit_after>#![allow(dead_code)]

#[cfg(target_os = "linux")]
extern crate i2cdev;
extern crate termion;

#[cfg(target_os = "linux")]
use self::i2cdev::core::I2CDevice;
#[cfg(target_os = "linux")]
use self::i2cdev::linux::{LinuxI2CDevice, LinuxI2CError};

use std;
use shared::*;

const MODE_REGISTER: u8 = 0x00;
const FRAME_REGISTER: u8 = 0x01;
const AUTOPLAY1_REGISTER: u8 = 0x02;
const AUTOPLAY2_REGISTER: u8 = 0x03;
const BLINK_REGISTER: u8 = 0x05;
const AUDIOSYNC_REGISTER: u8 = 0x06;
const BREATH1_REGISTER: u8 = 0x08;
const BREATH2_REGISTER: u8 = 0x09;
const SHUTDOWN_REGISTER: u8 = 0x0A;
const GAIN_REGISTER: u8 = 0x0B;
const ADC_REGISTER: u8 = 0x0C;

const CONFIG_BANK: u8 = 0x0B;
const BANK_ADDRESS: u8 = 0xFD;

const PICTURE_MODE: u8 = 0x00;
const AUTOPLAY_MODE: u8 = 0x08;
const AUDIOPLAY_MODE: u8 = 0x18;

const ENABLE_OFFSET: u8 = 0x00;
const BLINK_OFFSET: u8 = 0x12;
const COLOR_OFFSET: u8 = 0x24;

const ADDRESS: u16 = 0x74;

const LED_COLUMNS: usize = 17;
const LED_ROWS: usize = 7;

/// Represents a device capable of displaying a rectangular bitmap buffer.
pub trait Display {
    fn show(&mut self, buffer: &[Column]);
}

#[cfg(target_os = "linux")]
/// A Scroll pHAT HD device connected over I2C bus (e.g. on a Raspberry Pi).
pub struct I2CDisplay {
    device: LinuxI2CDevice,
    frame: u8,
}

#[cfg(target_os = "linux")]
impl I2CDisplay {
    /// Creates a new I2CDisplay device using the I2C device identified by the provided
    /// `device_id` (normally 1 or 2).
    pub fn new(device_id: u8) -> I2CDisplay {
        let device_path = format!("/dev/i2c-{}", device_id);
        let d = LinuxI2CDevice::new(device_path, ADDRESS).unwrap();
        let mut display = I2CDisplay {
            device: d,
            frame: 0,
        };

        display.init_display().unwrap();

        display
    }

    fn bank(&mut self, bank: u8) -> Result<(), LinuxI2CError> {
        self.write_data(BANK_ADDRESS, &[bank])
    }

    fn register(&mut self, bank: u8, register: u8, value: u8) -> Result<(), LinuxI2CError> {
        self.bank(bank);
        self.write_data(register, &[value])
    }

    fn frame(&mut self, frame: u8) -> Result<(), LinuxI2CError> {
        self.register(CONFIG_BANK, FRAME_REGISTER, frame)
    }

    fn write_data(&mut self, base_address: u8, data: &[u8]) -> Result<(), LinuxI2CError> {
        for i in 0..data.len() {
            self.device
                .smbus_write_byte_data(base_address + (i as u8), data[i])?;
        }
        Ok(())
    }

    fn reset_display(&mut self) -> Result<(), LinuxI2CError> {
        self.sleep(true)?;
        std::thread::sleep(std::time::Duration::from_millis(10));
        self.sleep(false)?;
        Ok(())
    }

    fn init_display(&mut self) -> Result<(), LinuxI2CError> {
        self.reset_display()?;

        // Switch to Picture Mode.
        self.register(CONFIG_BANK, MODE_REGISTER, PICTURE_MODE)?;

        // Disable audio sync.
        self.register(CONFIG_BANK, AUDIOSYNC_REGISTER, 0)?;

        // Initialize frames 0 and 1.
        for frame in 0..2 {
            self.write_data(BANK_ADDRESS, &[frame])?;

            // Turn off blinking for all LEDs.
            self.write_data(BLINK_OFFSET, &[0; LED_COLUMNS * LED_ROWS])?;

            // Set the PWM duty cycle for all LEDs to 0%.
            self.write_data(COLOR_OFFSET, &[0; LED_COLUMNS * LED_ROWS])?;

            // Turn all LEDs "on".
            self.write_data(ENABLE_OFFSET, &[127; LED_COLUMNS * LED_ROWS])?;
        }

        Ok(())
    }

    fn sleep(&mut self, value: bool) -> Result<(), LinuxI2CError> {
        self.register(CONFIG_BANK, SHUTDOWN_REGISTER, if value { 0 } else { 1 })
    }
}

#[cfg(target_os = "linux")]
impl Display for I2CDisplay {
    fn show(&mut self, buffer: &[Column]) {
        // Double buffering with frames 0 and 1.
        let new_frame = (self.frame + 1) % 2;
        self.bank(new_frame);
        for y in 0..DISPLAY_HEIGHT {
            for x in 0..DISPLAY_WIDTH {
                let offset = if x >= 8 {
                    (x - 8) * 16 + y
                } else {
                    (8 - x) * 16 - (y + 2)
                };
                let value = match buffer.get(x as usize) {
                    Some(column) => column[y as usize],
                    None => 0,
                };
                self.write_data(COLOR_OFFSET + offset as u8, &[value]);
            }
        }
        self.frame(new_frame);
        self.frame = new_frame;
    }
}

/// A virtual display that outputs its buffer to the terminal from which the binary is attached.
///
/// Useful for debugging or prototyping, as it does not require a physical display to be connected.
pub struct TermDisplay {}

impl TermDisplay {
    pub fn new() -> TermDisplay {
        TermDisplay {}
    }
}

impl Display for TermDisplay {
    fn show(&mut self, buffer: &[Column]) {
        print!("{}", termion::clear::All);
        for x in 0..buffer.len() {
            let col = &buffer[x];
            for y in 0..col.len() {
                let c = col[y];
                let v = if c == 0 { ' ' } else { '#' };
                println!("{}{}", termion::cursor::Goto(x as u16 + 1, y as u16 + 1), v);
            }
        }
    }
}

/// A virtual display that outputs its buffer to the terminal from which the binary is attached.
///
/// Useful for debugging or prototyping, as it does not require a physical display to be connected.
pub struct UnicodeDisplay {}

impl UnicodeDisplay {
    pub fn new() -> UnicodeDisplay {
        UnicodeDisplay {}
    }
}

impl Display for UnicodeDisplay {
    fn show(&mut self, buffer: &[Column]) {
        print!("{}", termion::clear::All);

        let col = &buffer[0];

        println!("{}╔", termion::cursor::Goto(1, 1));
        for y in 0..col.len() {
            println!("{}║", termion::cursor::Goto(1, y as u16 + 2));
        }
        println!("{}╚", termion::cursor::Goto(1, col.len() as u16 + 2));

        for x in 0..buffer.len() {
            let col = &buffer[x];
            println!("{}═", termion::cursor::Goto(x as u16 + 2, 1));
            for y in 0..col.len() {
                let c = col[y];
                let v = if c == 0 { '░' } else { '▓' };
                println!("{}{}", termion::cursor::Goto(x as u16 + 2, y as u16 + 2), v);
            }
            println!(
                "{}═",
                termion::cursor::Goto(x as u16 + 2, col.len() as u16 + 2)
            );
        }

        println!("{}╗", termion::cursor::Goto(buffer.len() as u16 + 1, 1));
        for y in 0..col.len() {
            println!(
                "{}║",
                termion::cursor::Goto(buffer.len() as u16 + 1, y as u16 + 2)
            );
        }
        println!(
            "{}╝",
            termion::cursor::Goto(buffer.len() as u16 + 1, col.len() as u16 + 2)
        );
    }
}
<|endoftext|>


<commit_before>use std::collections::{HashMap, HashSet};
use std::fs::File;
use std::fmt;
use std::io;
use std::io::BufReader;
use std::io::prelude::*;
use std::result::Result;
use std::convert::From;
use std::ascii::AsciiExt;
use rand;
use rand::Rng;
use grid;
use grid::Grid;
use item::{Item};
use point::{Point};
use tile::{Tile};

// A dungeon level.
pub struct Level {
    depth: u8,
    tiles: Grid<Tile>,
    items: HashMap<Point, Item>,
    visible: HashSet<Point>,
}

pub type Dungeon = [Level; 256];

pub enum MapError {
    ShapeError(usize),    // funny map shape at given line
    TileError(usize, u8), // bad tile (u8) on given map (usize)
    StairError(usize),    // not enough stairs on given map
    IoError(io::Error)
}

impl fmt::Display for MapError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            MapError::ShapeError(line) =>
                write!(f, "map error: misshapen map at line {}", line),
            MapError::TileError(whichmap, tile) =>
                write!(f, "map error: unknown tile '{}' on map {}",
                    tile as char, whichmap),
            MapError::StairError(whichmap) =>
                write!(f, "map error: not enough stairs on map {}", whichmap),
            MapError::IoError(ref e) => e.fmt(f)
        }
    }
}

impl From<io::Error> for MapError {
    fn from(e: io::Error) -> Self {
        MapError::IoError(e)
    }
}

// TODO: make early levels easy, handle special case for level 255
pub fn build() -> Result<Vec<Grid<Tile>>, MapError> {
    let mut schemes = read_maps()?;

    // until we have 255 distinct levels, make do with duplicates
    let distinct_schemes = schemes.len();
    while schemes.len() < 255 {
        let which = rand::thread_rng().gen_range(0, distinct_schemes);
        let duplicate = schemes[which].clone();
        schemes.push(duplicate)
    }

    let mut maps: Vec<Grid<Tile>> = Vec::with_capacity(255);
    for (whichmap, scheme) in schemes.iter().enumerate() {
        let mut map = build_map(whichmap, scheme)?;
        flip_randomly(&mut map);
        maps.push(map)
    }

    rand::thread_rng().shuffle(&mut maps[..]);

    Ok(maps)
}

type Lines<'a> = &'a mut Iterator<Item=io::Result<String>>;

fn read_maps() -> Result<Vec<Grid<u8>>, MapError> {
    let file = File::open("data/maps.txt")?;
    let reader = BufReader::new(file);
    let mut lines = reader.lines();
    let mut maps: Vec<Grid<u8>> = Vec::with_capacity(255);

    let mut linecount: usize = 1;
    loop {
        if lines.next().is_none() {
            return Ok(maps)
        }
        linecount += 1;
        maps.push(read_map(&mut linecount, &mut lines)?);
    }
}

fn read_map(linecount: &mut usize, lines: Lines) -> Result<Grid<u8>, MapError> {
    let mut grid = Grid::empty();
    for _ in 0..13 {
        match lines.next() {
            Some(Ok(ref row)) if row.len() == 19 =>
                grid.grid.extend(row.bytes()),
            Some(Err(e)) => return Err(MapError::IoError(e)),
            _ => return Err(MapError::ShapeError(*linecount))
        }
        *linecount = *linecount + 1
    }

    Ok(grid)
}

fn build_map(whichmap: usize, scheme: &Grid<u8>) -> Result<Grid<Tile>, MapError> {
    let mut map = Grid::empty();

    // preliminary pass: figure out where to place stairs
    let stairtotal = scheme.grid.iter().filter(|&&t| t == b'<').count();
    if stairtotal < 2 {
        return Err(MapError::StairError(whichmap))
    }
    let upstairs = rand::thread_rng().gen_range(0, stairtotal);
    let mut downstairs = upstairs;
    while downstairs == upstairs {
        downstairs = rand::thread_rng().gen_range(0, stairtotal)
    }

    // a HashMap to keep track of which tile (floor or wall) to use for
    // each letter A-Z in the map scheme (and the inverse for a-z)
    let mut tilechoices: HashMap<u8, bool> = HashMap::new();

    let mut staircount = 0;

    for &srctile in scheme.grid.iter() {
        map.grid.push(match srctile {
            b'.' => Tile::Floor,
            b'#' => Tile::Wall,
            b'+' => Tile::Door,
            b'<' => {
                let tile = if staircount == upstairs {
                    Tile::StairsUp
                } else if staircount == downstairs {
                    Tile::StairsDown
                } else {
                    Tile::Floor
                };
                staircount += 1;
                tile
            }
            b'A' ... b'Z' | b'a' ... b'z' => {
                let normalized = srctile.to_ascii_uppercase();
                let selection = *tilechoices.entry(normalized).or_insert_with(||
                    rand::thread_rng().gen() );
                // flip selection for lowercase letters
                // TODO: use srctile.is_ascii_uppercase()
                // once ascii_ctype is stable
                if selection == (srctile == normalized) {
                    Tile::Wall
                } else {
                    Tile::Floor
                }
            }
            _ => return Err(MapError::TileError(whichmap, srctile))
        })
    }

    Ok(map)
}

fn flip_randomly<T>(map: &mut Grid<T>) {
    if rand::thread_rng().gen() {
        // flip horizontally
        for row in map.grid.chunks_mut(grid::WIDTH) {
            row.reverse()
        }
    }
    if rand::thread_rng().gen() {
        // flip both horizontally and vertically
        map.grid.reverse()
    }
}
<commit_msg>don't hardcode map size in read_map<commit_after>use std::collections::{HashMap, HashSet};
use std::fs::File;
use std::fmt;
use std::io;
use std::io::BufReader;
use std::io::prelude::*;
use std::result::Result;
use std::convert::From;
use std::ascii::AsciiExt;
use rand;
use rand::Rng;
use grid;
use grid::Grid;
use item::{Item};
use point::{Point};
use tile::{Tile};

// A dungeon level.
pub struct Level {
    depth: u8,
    tiles: Grid<Tile>,
    items: HashMap<Point, Item>,
    visible: HashSet<Point>,
}

pub type Dungeon = [Level; 256];

pub enum MapError {
    ShapeError(usize),    // funny map shape at given line
    TileError(usize, u8), // bad tile (u8) on given map (usize)
    StairError(usize),    // not enough stairs on given map
    IoError(io::Error)
}

impl fmt::Display for MapError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            MapError::ShapeError(line) =>
                write!(f, "map error: misshapen map at line {}", line),
            MapError::TileError(whichmap, tile) =>
                write!(f, "map error: unknown tile '{}' on map {}",
                    tile as char, whichmap),
            MapError::StairError(whichmap) =>
                write!(f, "map error: not enough stairs on map {}", whichmap),
            MapError::IoError(ref e) => e.fmt(f)
        }
    }
}

impl From<io::Error> for MapError {
    fn from(e: io::Error) -> Self {
        MapError::IoError(e)
    }
}

// TODO: make early levels easy, handle special case for level 255
pub fn build() -> Result<Vec<Grid<Tile>>, MapError> {
    let mut schemes = read_maps()?;

    // until we have 255 distinct levels, make do with duplicates
    let distinct_schemes = schemes.len();
    while schemes.len() < 255 {
        let which = rand::thread_rng().gen_range(0, distinct_schemes);
        let duplicate = schemes[which].clone();
        schemes.push(duplicate)
    }

    let mut maps: Vec<Grid<Tile>> = Vec::with_capacity(255);
    for (whichmap, scheme) in schemes.iter().enumerate() {
        let mut map = build_map(whichmap, scheme)?;
        flip_randomly(&mut map);
        maps.push(map)
    }

    rand::thread_rng().shuffle(&mut maps[..]);

    Ok(maps)
}

type Lines<'a> = &'a mut Iterator<Item=io::Result<String>>;

fn read_maps() -> Result<Vec<Grid<u8>>, MapError> {
    let file = File::open("data/maps.txt")?;
    let reader = BufReader::new(file);
    let mut lines = reader.lines();
    let mut maps: Vec<Grid<u8>> = Vec::with_capacity(255);

    let mut linecount: usize = 1;
    loop {
        if lines.next().is_none() {
            return Ok(maps)
        }
        linecount += 1;
        maps.push(read_map(&mut linecount, &mut lines)?);
    }
}

fn read_map(linecount: &mut usize, lines: Lines) -> Result<Grid<u8>, MapError> {
    let mut grid = Grid::empty();
    for _ in 0..grid::HEIGHT {
        match lines.next() {
            Some(Ok(ref row)) if row.len() == grid::WIDTH =>
                grid.grid.extend(row.bytes()),
            Some(Err(e)) => return Err(MapError::IoError(e)),
            _ => return Err(MapError::ShapeError(*linecount))
        }
        *linecount = *linecount + 1
    }

    Ok(grid)
}

fn build_map(whichmap: usize, scheme: &Grid<u8>) -> Result<Grid<Tile>, MapError> {
    let mut map = Grid::empty();

    // preliminary pass: figure out where to place stairs
    let stairtotal = scheme.grid.iter().filter(|&&t| t == b'<').count();
    if stairtotal < 2 {
        return Err(MapError::StairError(whichmap))
    }
    let upstairs = rand::thread_rng().gen_range(0, stairtotal);
    let mut downstairs = upstairs;
    while downstairs == upstairs {
        downstairs = rand::thread_rng().gen_range(0, stairtotal)
    }

    // a HashMap to keep track of which tile (floor or wall) to use for
    // each letter A-Z in the map scheme (and the inverse for a-z)
    let mut tilechoices: HashMap<u8, bool> = HashMap::new();

    let mut staircount = 0;

    for &srctile in scheme.grid.iter() {
        map.grid.push(match srctile {
            b'.' => Tile::Floor,
            b'#' => Tile::Wall,
            b'+' => Tile::Door,
            b'<' => {
                let tile = if staircount == upstairs {
                    Tile::StairsUp
                } else if staircount == downstairs {
                    Tile::StairsDown
                } else {
                    Tile::Floor
                };
                staircount += 1;
                tile
            }
            b'A' ... b'Z' | b'a' ... b'z' => {
                let normalized = srctile.to_ascii_uppercase();
                let selection = *tilechoices.entry(normalized).or_insert_with(||
                    rand::thread_rng().gen() );
                // flip selection for lowercase letters
                // TODO: use srctile.is_ascii_uppercase()
                // once ascii_ctype is stable
                if selection == (srctile == normalized) {
                    Tile::Wall
                } else {
                    Tile::Floor
                }
            }
            _ => return Err(MapError::TileError(whichmap, srctile))
        })
    }

    Ok(map)
}

fn flip_randomly<T>(map: &mut Grid<T>) {
    if rand::thread_rng().gen() {
        // flip horizontally
        for row in map.grid.chunks_mut(grid::WIDTH) {
            row.reverse()
        }
    }
    if rand::thread_rng().gen() {
        // flip both horizontally and vertically
        map.grid.reverse()
    }
}
<|endoftext|>


<commit_before>use types::{Result, OscType, OscPacket, OscBundle, OscMessage};
use errors::OscError;
use utils;

use byteorder::{ByteOrder, BigEndian};
use std::iter;

pub fn encode_packet(packet: &OscPacket) -> Result<Vec<u8>> {
    match *packet {
        OscPacket::Message(ref msg) => encode_message(msg),
        OscPacket::Bundle(ref bundle) => encode_bundle(bundle),
    }
}

fn encode_message(msg: &OscMessage) -> Result<Vec<u8>> {
    let mut msg_bytes: Vec<u8> = Vec::new();

    msg_bytes.extend(encode_string(&msg.addr));
    let mut type_tags: Vec<char> = vec![','];
    let mut arg_bytes: Vec<u8> = Vec::new();

    if msg.args.is_some() {
        let args = msg.args.as_ref().unwrap();
        // Possible optimization: write this as iterator
        for arg in args {
            let (bytes, tag): (Option<Vec<u8>>, char) = try!(encode(arg));

            type_tags.push(tag);
            if bytes.is_some() {
                arg_bytes.extend(bytes.unwrap());
            }
        }
    }

    msg_bytes.extend(encode_string(&type_tags.iter()
                                             .cloned()
                                             .collect::<String>()));
    if arg_bytes.len() > 0 {
        msg_bytes.extend(arg_bytes);
    }
    Ok(msg_bytes)
}

fn encode_bundle(bundle: &OscBundle) -> Result<Vec<u8>> {
    Err(OscError::Unimplemented)
}

fn encode(arg: &OscType) -> Result<(Option<Vec<u8>>, char)> {
    match arg {
        &OscType::Int(ref x) => {
            let mut bytes = vec![0u8; 4];
            BigEndian::write_i32(&mut bytes, *x);
            Ok((Some(bytes), 'i'))
        }
        &OscType::Long(ref x) => {
            let mut bytes = vec![0u8; 8];
            BigEndian::write_i64(&mut bytes, *x);
            Ok((Some(bytes), 'h'))
        }
        &OscType::Float(ref x) => {
            let mut bytes = vec![0u8; 4];
            BigEndian::write_f32(&mut bytes, *x);
            Ok((Some(bytes), 'f'))
        }
        &OscType::Double(ref x) => {
            let mut bytes = vec![0u8; 8];
            BigEndian::write_f64(&mut bytes, *x);
            Ok((Some(bytes), 'd'))
        }
        &OscType::Char(ref x) => {
            let mut bytes = vec![0u8; 4];
            BigEndian::write_u32(&mut bytes, *x as u32);
            Ok((Some(bytes), 'c'))
        }
        &OscType::String(ref x) => {
            Ok((Some(encode_string(&x)), 's'))
        }
        &OscType::Blob(ref x) => {
            // let mut bytes = x.clone();
            let padded_blob_length: usize = utils::pad(x.len() as u64) as usize;
            let mut bytes = vec![0u8; 4 + padded_blob_length];
            // write length
            BigEndian::write_i32(&mut bytes[..4], x.len() as i32);
            for (i, v) in x.iter().enumerate() {
                bytes[i + 4] = *v;
            }
            Ok((Some(bytes), 'b'))
        }
        &OscType::Time(ref x, ref y) => {
            Ok((Some(encode_time_tag(*x, *y)), 't'))
        }
        &OscType::Midi(ref x) => {
            Ok((Some(vec![x.port, x.status, x.data1, x.data2]), 'm'))
        }
        &OscType::Bool(ref x) => {
            if *x {
                Ok((None, 'T'))
            } else {
                Ok((None, 'F'))
            }
        }
        &OscType::Nil => {
            Ok((None, 'N'))
        }
        &OscType::Inf => {
            Ok((None, 'I'))
        }
        _ => Err(OscError::Unimplemented),
    }
}

fn encode_string(s: &String) -> Vec<u8> {
    let mut bytes: Vec<u8> = s.as_bytes()
                              .iter()
                              .cloned()
                              .chain(iter::once(0u8))
                              .collect();
    pad_bytes(&mut bytes);
    bytes
}

fn pad_bytes(bytes: &mut Vec<u8>) {
    let padded_lengh = utils::pad(bytes.len() as u64);
    while bytes.len() < padded_lengh as usize {
        bytes.push(0u8)
    }
}

fn encode_time_tag(sec: u32, frac: u32) -> Vec<u8> {
    let mut bytes = vec![0u8; 8];
    BigEndian::write_u32(&mut bytes[..4], sec);
    BigEndian::write_u32(&mut bytes[4..], frac);
    bytes
}
<commit_msg>Make `encode_message` public<commit_after>use types::{Result, OscType, OscPacket, OscBundle, OscMessage};
use errors::OscError;
use utils;

use byteorder::{ByteOrder, BigEndian};
use std::iter;

pub fn encode_packet(packet: &OscPacket) -> Result<Vec<u8>> {
    match *packet {
        OscPacket::Message(ref msg) => encode_message(msg),
        OscPacket::Bundle(ref bundle) => encode_bundle(bundle),
    }
}

pub fn encode_message(msg: &OscMessage) -> Result<Vec<u8>> {
    let mut msg_bytes: Vec<u8> = Vec::new();

    msg_bytes.extend(encode_string(&msg.addr));
    let mut type_tags: Vec<char> = vec![','];
    let mut arg_bytes: Vec<u8> = Vec::new();

    if msg.args.is_some() {
        let args = msg.args.as_ref().unwrap();
        // Possible optimization: write this as iterator
        for arg in args {
            let (bytes, tag): (Option<Vec<u8>>, char) = try!(encode(arg));

            type_tags.push(tag);
            if bytes.is_some() {
                arg_bytes.extend(bytes.unwrap());
            }
        }
    }

    msg_bytes.extend(encode_string(&type_tags.iter()
                                             .cloned()
                                             .collect::<String>()));
    if arg_bytes.len() > 0 {
        msg_bytes.extend(arg_bytes);
    }
    Ok(msg_bytes)
}

fn encode_bundle(bundle: &OscBundle) -> Result<Vec<u8>> {
    Err(OscError::Unimplemented)
}

fn encode(arg: &OscType) -> Result<(Option<Vec<u8>>, char)> {
    match arg {
        &OscType::Int(ref x) => {
            let mut bytes = vec![0u8; 4];
            BigEndian::write_i32(&mut bytes, *x);
            Ok((Some(bytes), 'i'))
        }
        &OscType::Long(ref x) => {
            let mut bytes = vec![0u8; 8];
            BigEndian::write_i64(&mut bytes, *x);
            Ok((Some(bytes), 'h'))
        }
        &OscType::Float(ref x) => {
            let mut bytes = vec![0u8; 4];
            BigEndian::write_f32(&mut bytes, *x);
            Ok((Some(bytes), 'f'))
        }
        &OscType::Double(ref x) => {
            let mut bytes = vec![0u8; 8];
            BigEndian::write_f64(&mut bytes, *x);
            Ok((Some(bytes), 'd'))
        }
        &OscType::Char(ref x) => {
            let mut bytes = vec![0u8; 4];
            BigEndian::write_u32(&mut bytes, *x as u32);
            Ok((Some(bytes), 'c'))
        }
        &OscType::String(ref x) => {
            Ok((Some(encode_string(&x)), 's'))
        }
        &OscType::Blob(ref x) => {
            // let mut bytes = x.clone();
            let padded_blob_length: usize = utils::pad(x.len() as u64) as usize;
            let mut bytes = vec![0u8; 4 + padded_blob_length];
            // write length
            BigEndian::write_i32(&mut bytes[..4], x.len() as i32);
            for (i, v) in x.iter().enumerate() {
                bytes[i + 4] = *v;
            }
            Ok((Some(bytes), 'b'))
        }
        &OscType::Time(ref x, ref y) => {
            Ok((Some(encode_time_tag(*x, *y)), 't'))
        }
        &OscType::Midi(ref x) => {
            Ok((Some(vec![x.port, x.status, x.data1, x.data2]), 'm'))
        }
        &OscType::Bool(ref x) => {
            if *x {
                Ok((None, 'T'))
            } else {
                Ok((None, 'F'))
            }
        }
        &OscType::Nil => {
            Ok((None, 'N'))
        }
        &OscType::Inf => {
            Ok((None, 'I'))
        }
        _ => Err(OscError::Unimplemented),
    }
}

fn encode_string(s: &String) -> Vec<u8> {
    let mut bytes: Vec<u8> = s.as_bytes()
                              .iter()
                              .cloned()
                              .chain(iter::once(0u8))
                              .collect();
    pad_bytes(&mut bytes);
    bytes
}

fn pad_bytes(bytes: &mut Vec<u8>) {
    let padded_lengh = utils::pad(bytes.len() as u64);
    while bytes.len() < padded_lengh as usize {
        bytes.push(0u8)
    }
}

fn encode_time_tag(sec: u32, frac: u32) -> Vec<u8> {
    let mut bytes = vec![0u8; 8];
    BigEndian::write_u32(&mut bytes[..4], sec);
    BigEndian::write_u32(&mut bytes[4..], frac);
    bytes
}
<|endoftext|>


<commit_before>use std::io::Write;

use serde_json;
use serde_json::Value;

use types::{SourceMap, SourceMapIndex};
use jsontypes::{RawSection, RawSectionOffset, RawSourceMap};
use vlq::encode_vlq;
use errors::Result;

pub trait Encodable {
    fn as_raw_sourcemap(&self) -> RawSourceMap;
}

pub fn encode<M: Encodable, W: Write>(sm: &M, mut w: W) -> Result<()> {
    let ty = sm.as_raw_sourcemap();
    try!(serde_json::to_writer(&mut w, &ty));
    Ok(())
}

fn encode_vlq_diff(out: &mut String, a: u32, b: u32) {
    encode_vlq(out, (a as i64) - (b as i64))
}

fn serialize_mappings(sm: &SourceMap) -> String {
    let mut rv = String::new();
    // dst == minified == generated
    let mut prev_dst_line = 0;
    let mut prev_dst_col = 0;
    let mut prev_src_line = 0;
    let mut prev_src_col = 0;
    let mut prev_name_id = 0;
    let mut prev_src_id = 0;

    for (idx, token) in sm.tokens().enumerate() {
        let raw = token.get_raw_token();
        let idx = idx as u32;

        if token.get_dst_line() != prev_dst_line {
            prev_dst_col = 0;
            while token.get_dst_line() != prev_dst_line {
                rv.push(';');
                prev_dst_line += 1;
            }
        } else if idx > 0 {
            if Some(&token) == sm.get_token(idx - 1).as_ref() {
                continue;
            }
            rv.push(',');
        }

        encode_vlq_diff(&mut rv, token.get_dst_col(), prev_dst_col);
        prev_dst_col = token.get_dst_col();

        if token.has_source() {
            encode_vlq_diff(&mut rv, raw.src_id, prev_src_id);
            prev_src_id = raw.src_id;
            encode_vlq_diff(&mut rv, token.get_src_line(), prev_src_line);
            prev_src_line = token.get_src_line();
            encode_vlq_diff(&mut rv, token.get_src_col(), prev_src_col);
            prev_src_col = token.get_src_col();
            if token.has_name() {
                encode_vlq_diff(&mut rv, raw.name_id, prev_name_id);
                prev_name_id = raw.name_id;
            }
        }
    }

    rv
}

impl Encodable for SourceMap {
    fn as_raw_sourcemap(&self) -> RawSourceMap {
        let mut have_contents = false;
        let contents = self.source_contents().map(|contents| {
            if let Some(contents) = contents {
                have_contents = true;
                Some(contents.to_string())
            } else {
                None
            }
        }).collect();
        RawSourceMap {
            version: Some(3),
            file: self.get_file().map(|x| Value::String(x.to_string())),
            sources: Some(self.sources().map(|x| x.to_string()).collect()),
            // XXX: consider setting this to common root
            source_root: None,
            sources_content: if have_contents {
                Some(contents)
            } else {
                None
            },
            sections: None,
            names: Some(self.names().map(|x| Value::String(x.to_string())).collect()),
            mappings: Some(serialize_mappings(self)),
        }
    }
}

impl Encodable for SourceMapIndex {
    fn as_raw_sourcemap(&self) -> RawSourceMap {
        RawSourceMap {
            version: Some(3),
            file: self.get_file().map(|x| Value::String(x.to_string())),
            sources: None,
            source_root: None,
            sources_content: None,
            sections: Some(self.sections().map(|section| {
                RawSection {
                    offset: RawSectionOffset {
                        line: section.get_offset_line(),
                        column: section.get_offset_col(),
                    },
                    url: section.get_url().map(|x| x.to_string()),
                    map: section.get_sourcemap().map(|sm| {
                        Box::new(sm.as_raw_sourcemap())
                    }),
                }
            }).collect()),
            names: None,
            mappings: None,
        }
    }
}
<commit_msg>Stop using raw token in encoder<commit_after>use std::io::Write;

use serde_json;
use serde_json::Value;

use types::{SourceMap, SourceMapIndex};
use jsontypes::{RawSection, RawSectionOffset, RawSourceMap};
use vlq::encode_vlq;
use errors::Result;

pub trait Encodable {
    fn as_raw_sourcemap(&self) -> RawSourceMap;
}

pub fn encode<M: Encodable, W: Write>(sm: &M, mut w: W) -> Result<()> {
    let ty = sm.as_raw_sourcemap();
    try!(serde_json::to_writer(&mut w, &ty));
    Ok(())
}

fn encode_vlq_diff(out: &mut String, a: u32, b: u32) {
    encode_vlq(out, (a as i64) - (b as i64))
}

fn serialize_mappings(sm: &SourceMap) -> String {
    let mut rv = String::new();
    // dst == minified == generated
    let mut prev_dst_line = 0;
    let mut prev_dst_col = 0;
    let mut prev_src_line = 0;
    let mut prev_src_col = 0;
    let mut prev_name_id = 0;
    let mut prev_src_id = 0;

    for (idx, token) in sm.tokens().enumerate() {
        let idx = idx as u32;

        if token.get_dst_line() != prev_dst_line {
            prev_dst_col = 0;
            while token.get_dst_line() != prev_dst_line {
                rv.push(';');
                prev_dst_line += 1;
            }
        } else if idx > 0 {
            if Some(&token) == sm.get_token(idx - 1).as_ref() {
                continue;
            }
            rv.push(',');
        }

        encode_vlq_diff(&mut rv, token.get_dst_col(), prev_dst_col);
        prev_dst_col = token.get_dst_col();

        if token.has_source() {
            encode_vlq_diff(&mut rv, token.get_src_id(), prev_src_id);
            prev_src_id = token.get_src_id();
            encode_vlq_diff(&mut rv, token.get_src_line(), prev_src_line);
            prev_src_line = token.get_src_line();
            encode_vlq_diff(&mut rv, token.get_src_col(), prev_src_col);
            prev_src_col = token.get_src_col();
            if token.has_name() {
                encode_vlq_diff(&mut rv, token.get_name_id(), prev_name_id);
                prev_name_id = token.get_name_id();
            }
        }
    }

    rv
}

impl Encodable for SourceMap {
    fn as_raw_sourcemap(&self) -> RawSourceMap {
        let mut have_contents = false;
        let contents = self.source_contents().map(|contents| {
            if let Some(contents) = contents {
                have_contents = true;
                Some(contents.to_string())
            } else {
                None
            }
        }).collect();
        RawSourceMap {
            version: Some(3),
            file: self.get_file().map(|x| Value::String(x.to_string())),
            sources: Some(self.sources().map(|x| x.to_string()).collect()),
            // XXX: consider setting this to common root
            source_root: None,
            sources_content: if have_contents {
                Some(contents)
            } else {
                None
            },
            sections: None,
            names: Some(self.names().map(|x| Value::String(x.to_string())).collect()),
            mappings: Some(serialize_mappings(self)),
        }
    }
}

impl Encodable for SourceMapIndex {
    fn as_raw_sourcemap(&self) -> RawSourceMap {
        RawSourceMap {
            version: Some(3),
            file: self.get_file().map(|x| Value::String(x.to_string())),
            sources: None,
            source_root: None,
            sources_content: None,
            sections: Some(self.sections().map(|section| {
                RawSection {
                    offset: RawSectionOffset {
                        line: section.get_offset_line(),
                        column: section.get_offset_col(),
                    },
                    url: section.get_url().map(|x| x.to_string()),
                    map: section.get_sourcemap().map(|sm| {
                        Box::new(sm.as_raw_sourcemap())
                    }),
                }
            }).collect()),
            names: None,
            mappings: None,
        }
    }
}
<|endoftext|>