<commit_before>//! RethinkDB protocol implementation in Rust

extern crate protobuf;
extern crate serde_json;

pub mod proto;

use serde_json::value::{Value, ToJson};
use protobuf::repeated::RepeatedField;
use protobuf::ProtobufEnum;
use proto::{
    Term, Datum,
    Datum_DatumType as DT,
    Term_TermType as TT,
};

pub trait IsDatum {
    fn is_datum(&self) -> bool;
}

pub trait IsEmpty {
    fn is_empty(&self) -> bool;
}

pub trait Encode {
    fn encode(&self) -> String;
}

pub trait ToTerm {
    fn to(&self) -> Term;
}

pub trait FromTerm {
    fn from(t: Term) -> Self;
}

impl IsDatum for Term {
    fn is_datum(&self) -> bool {
        self.get_field_type() == TT::DATUM
    }
}

impl IsEmpty for Term {
    fn is_empty(&self) -> bool {
        *self == Term::new()
    }
}

impl Encode for Datum {
    fn encode(&self) -> String {
        match self.get_field_type() {
            DT::R_NULL => {
                unimplemented!();
            },
            DT::R_BOOL => {
                if self.has_r_bool() {
                    format!("{:?}", self.get_r_bool())
                } else {
                    unimplemented!();
                }
            },
            DT::R_NUM => {
                if self.has_r_num() {
                    format!("{}", self.get_r_num())
                } else {
                    unimplemented!();
                }
            },
            DT::R_STR => {
                if self.has_r_str() {
                    format!("{:?}", self.get_r_str())
                } else {
                    unimplemented!();
                }
            },
            DT::R_ARRAY => {
                let mut args = format!("[{},[", TT::MAKE_ARRAY.value());
                for term in self.get_r_array() {
                    args.push_str(&format!("{},", term.encode()));
                }
                args = args.trim_right_matches(",").to_string();
                args.push_str("]]");
                args
            },
            DT::R_OBJECT => {
                unimplemented!();
            },
            DT::R_JSON => {
                unimplemented!();
            },
        }
    }
}

impl Encode for Term {
    fn encode(&self) -> String {
        let mut res = String::new();
        if !self.is_datum() {
            res.push_str(&format!("[{},", self.get_field_type().value()));
        }
        let terms = self.get_args();
        if !terms.is_empty() {
            let mut args = String::from("[");
            for term in terms {
                args.push_str(&format!("{},", term.encode()));
            }
            args = args.trim_right_matches(",").to_string();
            args.push_str("]");
            res.push_str(&args);
        }
        if self.has_datum() {
            let datum = self.get_datum();
            res.push_str(&datum.encode());
        }
        if !self.is_datum() {
            res.push_str("]");
        }
        res
    }
}

impl<T: ToJson> ToTerm for T {
    fn to(&self) -> Term {
        // Datum
        let mut datum = Datum::new();
        match self.to_json() {
            Value::String(val) => {
                datum.set_field_type(DT::R_STR);
                datum.set_r_str(val);
            },
            Value::Bool(val) => {
                datum.set_field_type(DT::R_BOOL);
                datum.set_r_bool(val);
            },
            Value::I64(val) => {
                datum.set_field_type(DT::R_NUM);
                datum.set_r_num(val as f64);
            },
            Value::U64(val) => {
                datum.set_field_type(DT::R_NUM);
                datum.set_r_num(val as f64);
            },
            Value::F64(val) => {
                datum.set_field_type(DT::R_NUM);
                datum.set_r_num(val);
            },
            Value::Array(_val) => {
                unimplemented!();
            },
            Value::Object(_val) => {
                unimplemented!();
            },
            Value::Null => {
                datum.set_field_type(DT::R_NULL);
            },
        }
        // Term
        let mut term = Term::new();
        term.set_field_type(TT::DATUM);
        term.set_datum(datum);
        term
    }
}

impl ToTerm for Term {
    fn to(&self) -> Term {
        self.clone()
    }
}

impl FromTerm for Term {
    fn from(t: Term) -> Term {
        t
    }
}

macro_rules! command {
    ($T:expr, $cmd:expr, $args:expr, $opts:expr) => {{
        let mut term = Term::new();
        term.set_field_type($T);
        let mut args = Vec::new();
        let cmd = $cmd.to();
        if !cmd.is_empty() {
            args.push(cmd);
        }
        if let Some(list) = $args {
            args.extend(list);
        }
        /*
           if let Some(_opt) = $opts {
           unimplemented!();
           }
           */
        if !args.is_empty() {
            let args = RepeatedField::from_vec(args);
            term.set_args(args);
        }
        FromTerm::from(term)
    }}
}

macro_rules! closure_par {
    () => {{
        // ID
        let mut id = Datum::new();
        id.set_field_type(DT::R_NUM);
        id.set_r_num(1.0);
        // DATUM
        let mut datum = Term::new();
        datum.set_field_type(TT::DATUM);
        datum.set_datum(id);
        // VAR
        let mut var = Term::new();
        var.set_field_type(TT::VAR);
        let args = RepeatedField::from_vec(vec![datum]);
        var.set_args(args);
        FromTerm::from(var)
    }}
}

macro_rules! closure_arg {
    ($res:expr) => {{
        // ID
        let mut id = Datum::new();
        id.set_field_type(DT::R_NUM);
        id.set_r_num(1.0);
        // ARRAY
        let mut array = Datum::new();
        array.set_field_type(DT::R_ARRAY);
        let args = RepeatedField::from_vec(vec![id]);
        array.set_r_array(args);
        // DATUM
        let mut datum = Term::new();
        datum.set_field_type(TT::DATUM);
        datum.set_datum(array);
        // FUNC
        let mut func = Term::new();
        func.set_field_type(TT::FUNC);
        let args = RepeatedField::from_vec(vec![datum, $res.to()]);
        func.set_args(args);
        func
    }}
}

pub trait Command : FromTerm + ToTerm {
    fn expr<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        FromTerm::from(arg.to())
    }

    fn db<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        let arg = arg.to();
        command!(TT::DB, self, Some(vec![arg]), None)
    }

    fn db_create<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        let arg = arg.to();
        command!(TT::DB_CREATE, self, Some(vec![arg]), None)
    }

    fn db_drop<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        let arg = arg.to();
        command!(TT::DB_DROP, self, Some(vec![arg]), None)
    }

    fn table<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        let arg = arg.to();
        command!(TT::TABLE, self, Some(vec![arg]), None)
    }

    fn table_create<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        let arg = arg.to();
        command!(TT::TABLE_CREATE, self, Some(vec![arg]), None)
    }

    fn table_drop<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        let arg = arg.to();
        command!(TT::TABLE_DROP, self, Some(vec![arg]), None)
    }

    fn index_create<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        let arg = arg.to();
        command!(TT::INDEX_CREATE, self, Some(vec![arg]), None)
    }

    fn index_drop<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        let arg = arg.to();
        command!(TT::INDEX_DROP, self, Some(vec![arg]), None)
    }

    fn replace<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        let arg = arg.to();
        command!(TT::REPLACE, self, Some(vec![arg]), None)
    }

    fn update<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        let arg = arg.to();
        command!(TT::UPDATE, self, Some(vec![arg]), None)
    }

    fn order_by<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        let arg = arg.to();
        command!(TT::ORDER_BY, self, Some(vec![arg]), None)
    }

    fn without<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        let arg = arg.to();
        command!(TT::WITHOUT, self, Some(vec![arg]), None)
    }

    fn contains<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        let arg = arg.to();
        command!(TT::CONTAINS, self, Some(vec![arg]), None)
    }

    fn limit<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        let arg = arg.to();
        command!(TT::LIMIT, self, Some(vec![arg]), None)
    }

    fn get<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        let arg = arg.to();
        command!(TT::GET, self, Some(vec![arg]), None)
    }

    fn get_all<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        let arg = arg.to();
        command!(TT::GET_ALL, self, Some(vec![arg]), None)
    }

    fn insert<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        let arg = arg.to();
        command!(TT::INSERT, self, Some(vec![arg]), None)
    }

    fn delete(&self) -> Self
        where Self: Sized
    {
        command!(TT::DELETE, self, None as Option<Vec<Term>>, None)
    }

    fn changes(&self) -> Self
        where Self: Sized
    {
        command!(TT::CHANGES, self, None as Option<Vec<Term>>, None)
    }

    fn has_fields<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        let arg = arg.to();
        command!(TT::HAS_FIELDS, self, Some(vec![arg]), None)
    }

    fn get_field<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        let arg = arg.to();
        command!(TT::GET_FIELD, self, Some(vec![arg]), None)
    }

    fn filter<F>(&self, func: F) -> Self
        where F: Fn(Self) -> Self, Self: Sized
    {
        let res = func(closure_par!());
        let arg = closure_arg!(res);
        command!(TT::FILTER, self, Some(vec![arg]), None)
    }

    fn map<F>(&self, func: F) -> Self
        where F: Fn(Self) -> Self, Self: Sized
    {
        let res = func(closure_par!());
        let arg = closure_arg!(res);
        command!(TT::MAP, self, Some(vec![arg]), None)
    }

    fn branch<T, O>(&self, arg: T) -> Self
        where O: ToTerm + Sized, T: IntoIterator<Item=O>, Self: Sized
    {
        let args: Vec<Term> = arg.into_iter()
            .map(|a| a.to())
            .collect();
        command!(TT::BRANCH, self, Some(args), None)
    }

    fn object<T, O>(&self, arg: T) -> Self
        where O: ToTerm + Sized, T: IntoIterator<Item=O>, Self: Sized
    {
        let args: Vec<Term> = arg.into_iter()
            .map(|a| a.to())
            .collect();
        command!(TT::MAKE_OBJ, self, Some(args), None)
    }

    fn array<T, O>(&self, arg: T) -> Self
        where O: ToTerm + Sized, T: IntoIterator<Item=O>, Self: Sized
    {
        let args: Vec<Term> = arg.into_iter()
            .map(|a| a.to())
            .collect();
        command!(TT::MAKE_ARRAY, self, Some(args), None)
    }
}

#[test]
fn test_commands_can_be_chained() {
    impl Command for Term { }
    let r = Term::new();
    let term = r.db("heroes").table("marvel").map(|row| row.get_field("first_appearance"));
    panic!(format!("{:?}\n\n{}", term, term.encode()));
}
<commit_msg>Refactor commands<commit_after>//! RethinkDB protocol implementation in Rust

extern crate protobuf;
extern crate serde_json;

pub mod proto;

use serde_json::value::{Value, ToJson};
use protobuf::repeated::RepeatedField;
use protobuf::ProtobufEnum;
use proto::{
    Term, Datum,
    Datum_DatumType as DT,
    Term_TermType as TT,
};

pub trait IsDatum {
    fn is_datum(&self) -> bool;
}

pub trait IsEmpty {
    fn is_empty(&self) -> bool;
}

pub trait Encode {
    fn encode(&self) -> String;
}

pub trait ToTerm {
    fn to(&self) -> Term;
}

pub trait FromTerm {
    fn from(t: Term) -> Self;
}

impl IsDatum for Term {
    fn is_datum(&self) -> bool {
        self.get_field_type() == TT::DATUM
    }
}

impl IsEmpty for Term {
    fn is_empty(&self) -> bool {
        *self == Term::new()
    }
}

impl Encode for Datum {
    fn encode(&self) -> String {
        match self.get_field_type() {
            DT::R_NULL => {
                unimplemented!();
            },
            DT::R_BOOL => {
                if self.has_r_bool() {
                    format!("{:?}", self.get_r_bool())
                } else {
                    unimplemented!();
                }
            },
            DT::R_NUM => {
                if self.has_r_num() {
                    format!("{}", self.get_r_num())
                } else {
                    unimplemented!();
                }
            },
            DT::R_STR => {
                if self.has_r_str() {
                    format!("{:?}", self.get_r_str())
                } else {
                    unimplemented!();
                }
            },
            DT::R_ARRAY => {
                let mut args = format!("[{},[", TT::MAKE_ARRAY.value());
                for term in self.get_r_array() {
                    args.push_str(&format!("{},", term.encode()));
                }
                args = args.trim_right_matches(",").to_string();
                args.push_str("]]");
                args
            },
            DT::R_OBJECT => {
                unimplemented!();
            },
            DT::R_JSON => {
                unimplemented!();
            },
        }
    }
}

impl Encode for Term {
    fn encode(&self) -> String {
        let mut res = String::new();
        if !self.is_datum() {
            res.push_str(&format!("[{},", self.get_field_type().value()));
        }
        let terms = self.get_args();
        if !terms.is_empty() {
            let mut args = String::from("[");
            for term in terms {
                args.push_str(&format!("{},", term.encode()));
            }
            args = args.trim_right_matches(",").to_string();
            args.push_str("]");
            res.push_str(&args);
        }
        if self.has_datum() {
            let datum = self.get_datum();
            res.push_str(&datum.encode());
        }
        if !self.is_datum() {
            res.push_str("]");
        }
        res
    }
}

impl<T: ToJson> ToTerm for T {
    fn to(&self) -> Term {
        // Datum
        let mut datum = Datum::new();
        match self.to_json() {
            Value::String(val) => {
                datum.set_field_type(DT::R_STR);
                datum.set_r_str(val);
            },
            Value::Bool(val) => {
                datum.set_field_type(DT::R_BOOL);
                datum.set_r_bool(val);
            },
            Value::I64(val) => {
                datum.set_field_type(DT::R_NUM);
                datum.set_r_num(val as f64);
            },
            Value::U64(val) => {
                datum.set_field_type(DT::R_NUM);
                datum.set_r_num(val as f64);
            },
            Value::F64(val) => {
                datum.set_field_type(DT::R_NUM);
                datum.set_r_num(val);
            },
            Value::Array(_val) => {
                unimplemented!();
            },
            Value::Object(_val) => {
                unimplemented!();
            },
            Value::Null => {
                datum.set_field_type(DT::R_NULL);
            },
        }
        // Term
        let mut term = Term::new();
        term.set_field_type(TT::DATUM);
        term.set_datum(datum);
        term
    }
}

impl ToTerm for Term {
    fn to(&self) -> Term {
        self.clone()
    }
}

impl FromTerm for Term {
    fn from(t: Term) -> Term {
        t
    }
}

macro_rules! command {
    ($T:expr, $cmd:expr, $args:expr, $opts:expr) => {{
        let mut term = Term::new();
        term.set_field_type($T);
        let mut args = Vec::new();
        let cmd = $cmd.to();
        if !cmd.is_empty() {
            args.push(cmd);
        }
        if let Some(list) = $args {
            args.extend(list);
        }
        /*
           if let Some(_opt) = $opts {
           unimplemented!();
           }
           */
        if !args.is_empty() {
            let args = RepeatedField::from_vec(args);
            term.set_args(args);
        }
        FromTerm::from(term)
    }}
}

macro_rules! closure_par {
    () => {{
        // ID
        let mut id = Datum::new();
        id.set_field_type(DT::R_NUM);
        id.set_r_num(1.0);
        // DATUM
        let mut datum = Term::new();
        datum.set_field_type(TT::DATUM);
        datum.set_datum(id);
        // VAR
        let mut var = Term::new();
        var.set_field_type(TT::VAR);
        let args = RepeatedField::from_vec(vec![datum]);
        var.set_args(args);
        FromTerm::from(var)
    }}
}

macro_rules! closure_arg {
    ($res:expr) => {{
        // ID
        let mut id = Datum::new();
        id.set_field_type(DT::R_NUM);
        id.set_r_num(1.0);
        // ARRAY
        let mut array = Datum::new();
        array.set_field_type(DT::R_ARRAY);
        let args = RepeatedField::from_vec(vec![id]);
        array.set_r_array(args);
        // DATUM
        let mut datum = Term::new();
        datum.set_field_type(TT::DATUM);
        datum.set_datum(array);
        // FUNC
        let mut func = Term::new();
        func.set_field_type(TT::FUNC);
        let args = RepeatedField::from_vec(vec![datum, $res.to()]);
        func.set_args(args);
        func
    }}
}

pub trait Command : FromTerm + ToTerm {
    fn expr<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        FromTerm::from(arg.to())
    }

    fn db<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        let term = arg.to();
        command!(TT::DB, self, Some(vec![term]), None)
    }

    fn db_create<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        let term = arg.to();
        command!(TT::DB_CREATE, self, Some(vec![term]), None)
    }

    fn db_drop<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        let term = arg.to();
        command!(TT::DB_DROP, self, Some(vec![term]), None)
    }

    fn table<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        let term = arg.to();
        command!(TT::TABLE, self, Some(vec![term]), None)
    }

    fn table_create<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        let term = arg.to();
        command!(TT::TABLE_CREATE, self, Some(vec![term]), None)
    }

    fn table_drop<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        let term = arg.to();
        command!(TT::TABLE_DROP, self, Some(vec![term]), None)
    }

    fn index_create<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        let term = arg.to();
        command!(TT::INDEX_CREATE, self, Some(vec![term]), None)
    }

    fn index_drop<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        let term = arg.to();
        command!(TT::INDEX_DROP, self, Some(vec![term]), None)
    }

    fn replace<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        let term = arg.to();
        command!(TT::REPLACE, self, Some(vec![term]), None)
    }

    fn update<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        let term = arg.to();
        command!(TT::UPDATE, self, Some(vec![term]), None)
    }

    fn order_by<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        let term = arg.to();
        command!(TT::ORDER_BY, self, Some(vec![term]), None)
    }

    fn without<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        let term = arg.to();
        command!(TT::WITHOUT, self, Some(vec![term]), None)
    }

    fn contains<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        let term = arg.to();
        command!(TT::CONTAINS, self, Some(vec![term]), None)
    }

    fn limit<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        let term = arg.to();
        command!(TT::LIMIT, self, Some(vec![term]), None)
    }

    fn get<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        let term = arg.to();
        command!(TT::GET, self, Some(vec![term]), None)
    }

    fn get_all<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        let term = arg.to();
        command!(TT::GET_ALL, self, Some(vec![term]), None)
    }

    fn insert<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        let term = arg.to();
        command!(TT::INSERT, self, Some(vec![term]), None)
    }

    fn delete(&self) -> Self
        where Self: Sized
    {
        command!(TT::DELETE, self, None as Option<Vec<Term>>, None)
    }

    fn changes(&self) -> Self
        where Self: Sized
    {
        command!(TT::CHANGES, self, None as Option<Vec<Term>>, None)
    }

    fn has_fields<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        let term = arg.to();
        command!(TT::HAS_FIELDS, self, Some(vec![term]), None)
    }

    fn get_field<T>(&self, arg: T) -> Self
        where T: ToTerm, Self: Sized
    {
        let term = arg.to();
        command!(TT::GET_FIELD, self, Some(vec![term]), None)
    }

    fn filter<F>(&self, func: F) -> Self
        where F: Fn(Self) -> Self, Self: Sized
    {
        let res = func(closure_par!());
        let term = closure_arg!(res);
        command!(TT::FILTER, self, Some(vec![term]), None)
    }

    fn map<F>(&self, func: F) -> Self
        where F: Fn(Self) -> Self, Self: Sized
    {
        let res = func(closure_par!());
        let term = closure_arg!(res);
        command!(TT::MAP, self, Some(vec![term]), None)
    }

    fn branch<T, O>(&self, arg: T) -> Self
        where O: ToTerm + Sized, T: IntoIterator<Item=O>, Self: Sized
    {
        let args: Vec<Term> = arg.into_iter()
            .map(|a| a.to())
            .collect();
        command!(TT::BRANCH, self, Some(args), None)
    }

    fn object<T, O>(&self, arg: T) -> Self
        where O: ToTerm + Sized, T: IntoIterator<Item=O>, Self: Sized
    {
        let args: Vec<Term> = arg.into_iter()
            .map(|a| a.to())
            .collect();
        command!(TT::MAKE_OBJ, self, Some(args), None)
    }

    fn array<T, O>(&self, arg: T) -> Self
        where O: ToTerm + Sized, T: IntoIterator<Item=O>, Self: Sized
    {
        let args: Vec<Term> = arg.into_iter()
            .map(|a| a.to())
            .collect();
        command!(TT::MAKE_ARRAY, self, Some(args), None)
    }
}

#[test]
fn test_commands_can_be_chained() {
    impl Command for Term { }
    let r = Term::new();
    let term = r.db("heroes").table("marvel").map(|row| row.get_field("first_appearance"));
    panic!(format!("{:?}\n\n{}", term, term.encode()));
}
<|endoftext|>


<commit_before>#![deny(missing_docs)]

//! A structure for storing and look up 3D geometry

extern crate range;

use range::{ Range, ParentRange };

/// A geometry range, pointing to triangle list index buffer.
pub struct GeometryRange<I>(Range);

impl<I> ParentRange for GeometryRange<I> {
    type Child = I;

    fn from_range(range: Range) -> Self { GeometryRange(range) }
    fn range(&self) -> &Range { &self.0 }
    fn range_mut(&mut self) -> &mut Range { &mut self.0 }
}

<commit_msg>Added `ObjectRange`, made geometry child `u32`<commit_after>#![deny(missing_docs)]

//! A structure for storing and look up 3D geometry

extern crate range;

use range::{ Range, ParentRange };

/// A geometry range, pointing to triangle list `u32` index buffer.
pub struct GeometryRange(Range);

impl ParentRange for GeometryRange {
    type Child = u32;

    fn from_range(range: Range) -> Self { GeometryRange(range) }
    fn range(&self) -> &Range { &self.0 }
    fn range_mut(&mut self) -> &mut Range { &mut self.0 }
}

/// An object range, pointing to a geometry range buffer,
/// which points to a triangle list index `I` buffer.
pub struct ObjectRange(Range);

impl ParentRange for ObjectRange {
    type Child = GeometryRange;

    fn from_range(range: Range) -> Self { ObjectRange(range) }
    fn range(&self) -> &Range { &self.0 }
    fn range_mut(&mut self) -> &mut Range { &mut self.0 }
}

<|endoftext|>


<commit_before>//! This crate allows one-liners to read from a terminal
//! A minimal example to get an i32 from the command line is
//!
//! ```rust,no_run
//! #[macro_use] extern crate text_io;
//! fn main() {
//!     let i: i32 = read!();
//! }
//! ```
//!
//! The `read!()` macro will always read until the next ascii whitespace character
//! (`\n`, `\r`, `\t` or space).
//!
//! Any type that implements the `FromStr` trait can be read with the `read!` macro.
//!
//! # Advanced
//! Text parsing can be done similar to `println!` by adding a format string
//! to the macro:
//!
//! ```rust,no_run
//! # #[macro_use]
//! # extern crate text_io;
//! # fn main() {
//! let i: i32 = read!("The answer: {}!");
//! # }
//! ```
//!
//! This will read `"The answer: "`, then an integer, then an exclamation mark. Any deviation from
//! the format string will result in a panic.
//!
//! Note: only a single value can be read per `read!` invocation.

use std::error;
use std::fmt;
use std::str::FromStr;

#[derive(Debug, PartialEq)]
pub enum Error {
    MissingMatch,
    MissingClosingBrace,
    UnexpectedValue(u8, Option<u8>),
    InvalidUtf8(Vec<u8>),
    PartialUtf8(usize, Vec<u8>),
    Parse(String, &'static str),
    #[doc(hidden)]
    __NonExhaustive__,
}

impl error::Error for Error {
    fn description(&self) -> &str {
        use Error::*;

        match *self {
            MissingMatch => "Bad read! format string: did not contain {{}}",
            MissingClosingBrace => "found single open curly brace at the end of the format string",
            UnexpectedValue(..) => "found value not matching the pattern",
            InvalidUtf8(..) => "input was not valid utf8",
            PartialUtf8(..) => "input was only partially valid utf8",
            Parse(..) => "could not parse input as target type",
            __NonExhaustive__ => unreachable!(),
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use Error::*;
        use std::str::from_utf8;

        match *self {
            InvalidUtf8(ref raw) => write!(f, "input was not valid utf8: {:?}", raw),
            Parse(ref s, arg) => write!(f, "could not parse {} as target type of {}", s, arg),
            UnexpectedValue(exp, act) => write!(
                f,
                "found value {:?} not matching the pattern value {}",
                act.map(|b| b as char),
                exp as char
            ),
            PartialUtf8(n, ref raw) => write!(
                f,
                "input was only partially valid utf8: \"{}\" followed by {:?}",
                from_utf8(&raw[..n]).unwrap(),
                &raw[n..]
            ),
            _ => write!(f, "{}", <Error as error::Error>::description(self)),
        }
    }
}

pub fn match_next(expected: u8, iter: &mut Iterator<Item = u8>) -> Result<(), Error> {
    let next = iter.next();
    if next != Some(expected) {
        return Err(Error::UnexpectedValue(expected, next))?
    }
    Ok(())
}

pub fn parse_capture<T>(name: &'static str, next: Option<u8>, iter: &mut Iterator<Item = u8>)
-> Result<T, Error>
where
    T: FromStr,
    <T as FromStr>::Err: ::std::fmt::Debug
{
    static WHITESPACES: &'static [u8] = b"\t\r\n ";
    let raw: Vec<u8> = match next {
        Some(c) => iter.take_while(|&ch| ch != c).collect(),
        None => iter
            .skip_while(|ch| WHITESPACES.contains(ch))
            .take_while(|ch| !WHITESPACES.contains(ch))
            .collect(),
    };
    match String::from_utf8(raw) {
        Ok(s) => FromStr::from_str(&s).map_err(|_| Error::Parse(s, name)),
        Err(e) => {
            let n = e.utf8_error().valid_up_to();
            let raw = e.into_bytes();
            if n == 0 {
                Err(Error::InvalidUtf8(raw))
            } else {
                Err(Error::PartialUtf8(n, raw))
            }
        }
    }
}

/// ```rust,no_run
/// # #[macro_use]
/// # extern crate text_io;
/// # fn main() {
/// let i: i32 = try_read!("The answer: {}!").unwrap();
/// let i: Result<i32, _> = try_read!("The {}{{}}!", "The answer is 42!".bytes());
/// assert!(i.is_err());
/// # }
/// ```
///
/// ```rust
/// # #[macro_use]
/// # extern crate text_io;
/// # fn main() {
/// let i: Result<i32, _> = try_read!("The answer is {}!", "The answer is 42!".bytes());
/// assert!(i.is_ok());
///
/// let i: Result<i32, _> = try_read!("The {}{{}}!", "The answer is 42!".bytes());
/// assert!(i.is_err());
/// # }
/// ```
#[macro_export]
macro_rules! try_read(
    () => { try_read!("{}") };
    ($text:expr) => {{
        (|| -> Result<_, $crate::Error> {
            let __try_read_var__;
            try_scan!($text, __try_read_var__);
            Ok(__try_read_var__)
        })()
    }};
    ($text:expr, $input:expr) => {{
        (|| -> Result<_, $crate::Error> {
            let __try_read_var__;
            try_scan!($input => $text, __try_read_var__);
            Ok(__try_read_var__)
        })()
    }};
);

/// ```rust,no_run
/// # #[macro_use]
/// # extern crate text_io;
/// # use std::error::Error;
/// # fn main() {}
/// fn parser() -> Result<i32, Box<Error>> {
///     let i: i32;
///     let text = "The answer is 42!";
///
///     try_scan!(text.bytes() => "The answer is {}!", i);
///
///     assert_eq!(i, 1);
///     Ok(i)
/// }
/// ```
#[macro_export]
macro_rules! try_scan(
    ($pattern:expr, $($arg:expr),*) => {
        use ::std::io::Read;
        try_scan!(::std::io::stdin().bytes().map(|c| c.unwrap()) => $pattern, $($arg),*) ;
        format_args!($pattern, $($arg),*);
    };
    ($input:expr => $pattern:expr, $($arg:expr),*) => {{
        try_scan!(@impl question_mark; $input => $pattern, $($arg),*)
    }};
    (@question_mark: $($e:tt)+) => {{
        ($($e)+)?
    }};
    (@unwrap: $($e:tt)+) => {{
        ($($e)+).unwrap()
    }};
    (@impl $action:tt; $input:expr => $pattern:expr, $($arg:expr),*) => {{
        use $crate::{Error, match_next, parse_capture};

        // typesafe macros :)
        let pattern: &'static str = $pattern;
        let stdin: &mut Iterator<Item = u8> = &mut ($input);

        let mut pattern = pattern.bytes();

        $(
            $arg = loop {
                match try_scan!(@$action: pattern.next().ok_or(Error::MissingMatch)) {
                    b'{' => match try_scan!(@$action: pattern.next().ok_or(Error::MissingClosingBrace)) {
                        b'{' => try_scan!(@$action: match_next(b'{', stdin)),
                        b'}' => break try_scan!(@$action: parse_capture(stringify!($arg), pattern.next(), stdin)),
                        _ => return try_scan!(@$action: Err(Error::MissingClosingBrace)),
                    },
                    c => try_scan!(@$action: match_next(c, stdin)),
                }
            };
        )*

        for c in pattern {
            try_scan!(@$action: match_next(c, stdin))
        }

        format_args!($pattern, $($arg),*);
    }};
);

/// All text input is handled through this macro
#[macro_export]
macro_rules! read(
    ($($arg:tt)*) => {
        try_read!($($arg)*).unwrap()
    };
);

/// This macro allows to pass several variables so multiple values can be read
#[macro_export]
macro_rules! scan(
    ($text:expr, $($arg:expr),*) => {
        use ::std::io::Read;
        scan!(::std::io::stdin().bytes().map(|c| c.unwrap()) => $text, $($arg),*) ;
        format_args!($text, $($arg),*);
    };
    ($input:expr => $pattern:expr, $($arg:expr),*) => {{
        try_scan!(@impl unwrap; $input => $pattern, $($arg),*)
    }};
);
<commit_msg>avoid redundant closure clippy lint<commit_after>//! This crate allows one-liners to read from a terminal
//! A minimal example to get an i32 from the command line is
//!
//! ```rust,no_run
//! #[macro_use] extern crate text_io;
//! fn main() {
//!     let i: i32 = read!();
//! }
//! ```
//!
//! The `read!()` macro will always read until the next ascii whitespace character
//! (`\n`, `\r`, `\t` or space).
//!
//! Any type that implements the `FromStr` trait can be read with the `read!` macro.
//!
//! # Advanced
//! Text parsing can be done similar to `println!` by adding a format string
//! to the macro:
//!
//! ```rust,no_run
//! # #[macro_use]
//! # extern crate text_io;
//! # fn main() {
//! let i: i32 = read!("The answer: {}!");
//! # }
//! ```
//!
//! This will read `"The answer: "`, then an integer, then an exclamation mark. Any deviation from
//! the format string will result in a panic.
//!
//! Note: only a single value can be read per `read!` invocation.

use std::error;
use std::fmt;
use std::str::FromStr;

#[derive(Debug, PartialEq)]
pub enum Error {
    MissingMatch,
    MissingClosingBrace,
    UnexpectedValue(u8, Option<u8>),
    InvalidUtf8(Vec<u8>),
    PartialUtf8(usize, Vec<u8>),
    Parse(String, &'static str),
    #[doc(hidden)]
    __NonExhaustive__,
}

impl error::Error for Error {
    fn description(&self) -> &str {
        use Error::*;

        match *self {
            MissingMatch => "Bad read! format string: did not contain {{}}",
            MissingClosingBrace => "found single open curly brace at the end of the format string",
            UnexpectedValue(..) => "found value not matching the pattern",
            InvalidUtf8(..) => "input was not valid utf8",
            PartialUtf8(..) => "input was only partially valid utf8",
            Parse(..) => "could not parse input as target type",
            __NonExhaustive__ => unreachable!(),
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use Error::*;
        use std::str::from_utf8;

        match *self {
            InvalidUtf8(ref raw) => write!(f, "input was not valid utf8: {:?}", raw),
            Parse(ref s, arg) => write!(f, "could not parse {} as target type of {}", s, arg),
            UnexpectedValue(exp, act) => write!(
                f,
                "found value {:?} not matching the pattern value {}",
                act.map(|b| b as char),
                exp as char
            ),
            PartialUtf8(n, ref raw) => write!(
                f,
                "input was only partially valid utf8: \"{}\" followed by {:?}",
                from_utf8(&raw[..n]).unwrap(),
                &raw[n..]
            ),
            _ => write!(f, "{}", <Error as error::Error>::description(self)),
        }
    }
}

pub fn match_next(expected: u8, iter: &mut Iterator<Item = u8>) -> Result<(), Error> {
    let next = iter.next();
    if next != Some(expected) {
        return Err(Error::UnexpectedValue(expected, next))?
    }
    Ok(())
}

pub fn parse_capture<T>(name: &'static str, next: Option<u8>, iter: &mut Iterator<Item = u8>)
-> Result<T, Error>
where
    T: FromStr,
    <T as FromStr>::Err: ::std::fmt::Debug
{
    static WHITESPACES: &'static [u8] = b"\t\r\n ";
    let raw: Vec<u8> = match next {
        Some(c) => iter.take_while(|&ch| ch != c).collect(),
        None => iter
            .skip_while(|ch| WHITESPACES.contains(ch))
            .take_while(|ch| !WHITESPACES.contains(ch))
            .collect(),
    };
    match String::from_utf8(raw) {
        Ok(s) => FromStr::from_str(&s).map_err(|_| Error::Parse(s, name)),
        Err(e) => {
            let n = e.utf8_error().valid_up_to();
            let raw = e.into_bytes();
            if n == 0 {
                Err(Error::InvalidUtf8(raw))
            } else {
                Err(Error::PartialUtf8(n, raw))
            }
        }
    }
}

/// ```rust,no_run
/// # #[macro_use]
/// # extern crate text_io;
/// # fn main() {
/// let i: i32 = try_read!("The answer: {}!").unwrap();
/// let i: Result<i32, _> = try_read!("The {}{{}}!", "The answer is 42!".bytes());
/// assert!(i.is_err());
/// # }
/// ```
///
/// ```rust
/// # #[macro_use]
/// # extern crate text_io;
/// # fn main() {
/// let i: Result<i32, _> = try_read!("The answer is {}!", "The answer is 42!".bytes());
/// assert!(i.is_ok());
///
/// let i: Result<i32, _> = try_read!("The {}{{}}!", "The answer is 42!".bytes());
/// assert!(i.is_err());
/// # }
/// ```
#[macro_export]
macro_rules! try_read(
    () => { try_read!("{}") };
    ($text:expr) => {{
        (|| -> Result<_, $crate::Error> {
            let __try_read_var__;
            try_scan!($text, __try_read_var__);
            Ok(__try_read_var__)
        })()
    }};
    ($text:expr, $input:expr) => {{
        (|| -> Result<_, $crate::Error> {
            let __try_read_var__;
            try_scan!($input => $text, __try_read_var__);
            Ok(__try_read_var__)
        })()
    }};
);

/// ```rust,no_run
/// # #[macro_use]
/// # extern crate text_io;
/// # use std::error::Error;
/// # fn main() {}
/// fn parser() -> Result<i32, Box<Error>> {
///     let i: i32;
///     let text = "The answer is 42!";
///
///     try_scan!(text.bytes() => "The answer is {}!", i);
///
///     assert_eq!(i, 1);
///     Ok(i)
/// }
/// ```
#[macro_export]
macro_rules! try_scan(
    ($pattern:expr, $($arg:expr),*) => {
        use ::std::io::Read;
        try_scan!(::std::io::stdin().bytes().map(std::result::Result::unwrap) => $pattern, $($arg),*);
        format_args!($pattern, $($arg),*);
    };
    ($input:expr => $pattern:expr, $($arg:expr),*) => {{
        try_scan!(@impl question_mark; $input => $pattern, $($arg),*)
    }};
    (@question_mark: $($e:tt)+) => {{
        ($($e)+)?
    }};
    (@unwrap: $($e:tt)+) => {{
        ($($e)+).unwrap()
    }};
    (@impl $action:tt; $input:expr => $pattern:expr, $($arg:expr),*) => {{
        use $crate::{Error, match_next, parse_capture};

        // typesafe macros :)
        let pattern: &'static str = $pattern;
        let stdin: &mut Iterator<Item = u8> = &mut ($input);

        let mut pattern = pattern.bytes();

        $(
            $arg = loop {
                match try_scan!(@$action: pattern.next().ok_or(Error::MissingMatch)) {
                    b'{' => match try_scan!(@$action: pattern.next().ok_or(Error::MissingClosingBrace)) {
                        b'{' => try_scan!(@$action: match_next(b'{', stdin)),
                        b'}' => break try_scan!(@$action: parse_capture(stringify!($arg), pattern.next(), stdin)),
                        _ => return try_scan!(@$action: Err(Error::MissingClosingBrace)),
                    },
                    c => try_scan!(@$action: match_next(c, stdin)),
                }
            };
        )*

        for c in pattern {
            try_scan!(@$action: match_next(c, stdin))
        }

        format_args!($pattern, $($arg),*);
    }};
);

/// All text input is handled through this macro
#[macro_export]
macro_rules! read(
    ($($arg:tt)*) => {
        try_read!($($arg)*).unwrap()
    };
);

/// This macro allows to pass several variables so multiple values can be read
#[macro_export]
macro_rules! scan(
    ($text:expr, $($arg:expr),*) => {
        use ::std::io::Read;
        scan!(::std::io::stdin().bytes().map(std::result::Result::unwrap) => $text, $($arg),*);
        format_args!($text, $($arg),*);
    };
    ($input:expr => $pattern:expr, $($arg:expr),*) => {{
        try_scan!(@impl unwrap; $input => $pattern, $($arg),*)
    }};
);
<|endoftext|>


<commit_before>//! # `object`
//!
//! The `object` crate provides a unified interface to working with object files
//! across platforms.
//!
//! See the [`File` struct](./struct.File.html) for details.

#![deny(missing_docs)]

extern crate goblin;

use goblin::{elf, mach};
use std::io::Cursor;

/// An object file.
pub struct File<'a> {
    kind: ObjectKind<'a>,
    data: &'a [u8],
}

enum ObjectKind<'a> {
    Elf(elf::Elf<'a>),
    MachO(mach::MachO<'a>),
}

impl<'a> File<'a> {
    /// Parse the raw object file data.
    pub fn parse(data: &'a [u8]) -> Result<Self, &'static str> {
        let mut cursor = Cursor::new(data);
        let kind = match goblin::peek(&mut cursor)
                  .map_err(|_| "Could not parse file magic")? {
            goblin::Hint::Elf(_) => {
                let elf = elf::Elf::parse(data)
                    .map_err(|_| "Could not parse ELF header")?;
                ObjectKind::Elf(elf)
            }
            goblin::Hint::Mach(_) => {
                let macho = mach::MachO::parse(data, 0)
                    .map_err(|_| "Could not parse Mach-O header")?;
                ObjectKind::MachO(macho)
            }
            _ => return Err("Unknown file magic"),
        };
        Ok(File { kind, data })
    }

    /// Get the contents of the section named `section_name`, if such
    /// a section exists.
    pub fn get_section(&self, section_name: &str) -> Option<&'a [u8]> {
        match self.kind {
            ObjectKind::Elf(ref elf) => elf_get_section(elf, section_name, self.data),
            ObjectKind::MachO(ref macho) => macho_get_section(macho, section_name),
        }
    }

    /// Return true if the file is little endian, false if it is big endian.
    pub fn is_little_endian(&self) -> bool {
        match self.kind {
            ObjectKind::Elf(ref elf) => elf.little_endian,
            ObjectKind::MachO(ref macho) => macho.header.is_little_endian(),
        }
    }
}

fn elf_get_section<'a>(elf: &elf::Elf<'a>, section_name: &str, data: &'a [u8]) -> Option<&'a [u8]> {
    for header in &elf.section_headers {
        if let Ok(name) = elf.shdr_strtab.get(header.sh_name) {
            if name == section_name {
                return Some(&data[header.sh_offset as usize..][..header.sh_size as usize]);
            }
        }
    }
    None
}

fn macho_get_section<'a>(macho: &mach::MachO<'a>, section_name: &str) -> Option<&'a [u8]> {
    let segment_name = "__DWARF";
    let section_name = macho_translate_section_name(section_name);

    for segment in &*macho.segments {
        if let Ok(name) = segment.name() {
            if name == segment_name {
                if let Ok(sections) = segment.sections() {
                    for section in sections {
                        if let Ok(name) = section.name() {
                            if name.as_bytes() == &*section_name {
                                return Some(section.data);
                            }
                        }
                    }
                }
            }
        }
    }
    None
}

// Translate the "." prefix to the "__" prefix used by OSX/Mach-O, eg
// ".debug_info" to "__debug_info".
fn macho_translate_section_name(section_name: &str) -> Vec<u8> {
    let mut name = Vec::with_capacity(section_name.len() + 1);
    name.push(b'_');
    name.push(b'_');
    for ch in &section_name.as_bytes()[1..] {
        name.push(*ch);
    }
    name
}

#[doc(hidden)]
#[deprecated]
pub trait Object {}
<commit_msg>Fix getting the `__eh_frame` section from Mach-O files<commit_after>//! # `object`
//!
//! The `object` crate provides a unified interface to working with object files
//! across platforms.
//!
//! See the [`File` struct](./struct.File.html) for details.

#![deny(missing_docs)]

extern crate goblin;

use goblin::{elf, mach};
use std::io::Cursor;

/// An object file.
pub struct File<'a> {
    kind: ObjectKind<'a>,
    data: &'a [u8],
}

enum ObjectKind<'a> {
    Elf(elf::Elf<'a>),
    MachO(mach::MachO<'a>),
}

impl<'a> File<'a> {
    /// Parse the raw object file data.
    pub fn parse(data: &'a [u8]) -> Result<Self, &'static str> {
        let mut cursor = Cursor::new(data);
        let kind = match goblin::peek(&mut cursor)
                  .map_err(|_| "Could not parse file magic")? {
            goblin::Hint::Elf(_) => {
                let elf = elf::Elf::parse(data)
                    .map_err(|_| "Could not parse ELF header")?;
                ObjectKind::Elf(elf)
            }
            goblin::Hint::Mach(_) => {
                let macho = mach::MachO::parse(data, 0)
                    .map_err(|_| "Could not parse Mach-O header")?;
                ObjectKind::MachO(macho)
            }
            _ => return Err("Unknown file magic"),
        };
        Ok(File { kind, data })
    }

    /// Get the contents of the section named `section_name`, if such
    /// a section exists.
    pub fn get_section(&self, section_name: &str) -> Option<&'a [u8]> {
        match self.kind {
            ObjectKind::Elf(ref elf) => elf_get_section(elf, section_name, self.data),
            ObjectKind::MachO(ref macho) => macho_get_section(macho, section_name),
        }
    }

    /// Return true if the file is little endian, false if it is big endian.
    pub fn is_little_endian(&self) -> bool {
        match self.kind {
            ObjectKind::Elf(ref elf) => elf.little_endian,
            ObjectKind::MachO(ref macho) => macho.header.is_little_endian(),
        }
    }
}

fn elf_get_section<'a>(elf: &elf::Elf<'a>, section_name: &str, data: &'a [u8]) -> Option<&'a [u8]> {
    for header in &elf.section_headers {
        if let Ok(name) = elf.shdr_strtab.get(header.sh_name) {
            if name == section_name {
                return Some(&data[header.sh_offset as usize..][..header.sh_size as usize]);
            }
        }
    }
    None
}

fn macho_get_section<'a>(macho: &mach::MachO<'a>, section_name: &str) -> Option<&'a [u8]> {
    let segment_name = if section_name == ".eh_frame" {
        "__TEXT"
    } else {
        "__DWARF"
    };
    let section_name = macho_translate_section_name(section_name);

    for segment in &*macho.segments {
        if let Ok(name) = segment.name() {
            if name == segment_name {
                if let Ok(sections) = segment.sections() {
                    for section in sections {
                        if let Ok(name) = section.name() {
                            if name.as_bytes() == &*section_name {
                                return Some(section.data);
                            }
                        }
                    }
                }
            }
        }
    }
    None
}

// Translate the "." prefix to the "__" prefix used by OSX/Mach-O, eg
// ".debug_info" to "__debug_info".
fn macho_translate_section_name(section_name: &str) -> Vec<u8> {
    let mut name = Vec::with_capacity(section_name.len() + 1);
    name.push(b'_');
    name.push(b'_');
    for ch in &section_name.as_bytes()[1..] {
        name.push(*ch);
    }
    name
}

#[doc(hidden)]
#[deprecated]
pub trait Object {}
<|endoftext|>


<commit_before>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
#![feature(tuple_indexing)]
#![feature(macro_rules)]

pub use vector::Vector;
pub use vector::VectorOperations;
pub use matrix::Matrix;

pub mod vector;
pub mod matrix_vector;
pub mod matrix;

pub mod attribute;
pub mod default;
pub mod pointer;
mod scalar;
<commit_msg>Unfeature-gate tuple indexing<commit_after>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
#![feature(macro_rules)]

pub use vector::Vector;
pub use vector::VectorOperations;
pub use matrix::Matrix;

pub mod vector;
pub mod matrix_vector;
pub mod matrix;

pub mod attribute;
pub mod default;
pub mod pointer;
mod scalar;
<|endoftext|>


<commit_before>#![crate_name = "coremidi"]
#![crate_type = "lib"]
#![doc(html_root_url = "https://chris-zen.github.io/coremidi/")]

/*!
This is a [CoreMIDI](https://developer.apple.com/reference/coremidi) library for Rust built on top of the low-level bindings [coremidi-sys](https://github.com/jonas-k/coremidi-sys).
CoreMIDI is a macOS framework that provides APIs for communicating with MIDI (Musical Instrument Digital Interface) devices, including hardware keyboards and synthesizers.

This library preserves the fundamental concepts behind the CoreMIDI framework, while being Rust idiomatic. This means that if you already know CoreMIDI, you will find very easy to start using it.

Please see the [examples](examples) for an idea on how it looks like, but if you are eager to see an example, this is how you would send some note:

```rust,no_run
extern crate coremidi;
use std::time::Duration;
use std::thread;
let client = coremidi::Client::new("example-client").unwrap();
let output_port = client.output_port("example-port").unwrap();
let destination = coremidi::Destination::from_index(0).unwrap();
let note_on = coremidi::PacketBuffer::new(0, &[0x90, 0x40, 0x7f]);
let note_off = coremidi::PacketBuffer::new(0, &[0x80, 0x40, 0x7f]);
output_port.send(&destination, &note_on).unwrap();
thread::sleep(Duration::from_millis(1000));
output_port.send(&destination, &note_off).unwrap();
```

If you are looking for a portable MIDI library then you can look into:

- [midir](https://github.com/Boddlnagg/midir) (which is using this lib)
- [portmidi-rs](https://github.com/musitdev/portmidi-rs)

For handling low level MIDI data you may look into:

- [midi-rs](https://github.com/samdoshi/midi-rs)
- [rimd](https://github.com/RustAudio/rimd)

*/

extern crate core_foundation_sys;
extern crate core_foundation;
extern crate coremidi_sys;

use core_foundation_sys::base::OSStatus;

use coremidi_sys::{
    MIDIObjectRef, MIDIFlushOutput, MIDIRestart, MIDIPacket, MIDIPacketList
};

/// A [MIDI Object](https://developer.apple.com/reference/coremidi/midiobjectref).
///
/// The base class of many CoreMIDI objects.
///
#[derive(PartialEq)]
pub struct Object(MIDIObjectRef);

/// A [MIDI client](https://developer.apple.com/reference/coremidi/midiclientref).
///
/// An object maintaining per-client state.
///
/// A simple example to create a Client:
///
/// ```rust,no_run
/// let client = coremidi::Client::new("example-client").unwrap();
/// ```
#[derive(Debug)]
pub struct Client {
    // Order is important, object needs to be dropped first
    object: Object,
    callback: BoxedCallback<Notification>,
}

// A lifetime-managed wrapper for callback functions
#[derive(Debug, PartialEq)]
struct BoxedCallback<T>(*mut Box<FnMut(&T)>);

impl<T> BoxedCallback<T> {
    fn new<F: FnMut(&T) + Send + 'static>(f: F) -> BoxedCallback<T> {
        BoxedCallback(Box::into_raw(Box::new(Box::new(f))))
    }

    fn null() -> BoxedCallback<T> {
        BoxedCallback(::std::ptr::null_mut())
    }

    fn raw_ptr(&mut self) -> *mut ::std::os::raw::c_void {
        self.0 as *mut ::std::os::raw::c_void
    }

    // must not be null
    unsafe fn call_from_raw_ptr(raw_ptr: *mut ::std::os::raw::c_void, arg: &T) {
        let callback = &mut *(raw_ptr as *mut Box<FnMut(&T)>);
        callback(arg);
    }
}

impl<T> Drop for BoxedCallback<T> {
    fn drop(&mut self) {
        unsafe {
            if !self.0.is_null() {
                let _ = Box::from_raw(self.0);
            }
        }
    }
}

/// A MIDI connection port owned by a client.
/// See [MIDIPortRef](https://developer.apple.com/reference/coremidi/midiportref).
///
/// Ports can't be instantiated directly, but through a client.
///
#[derive(Debug)]
pub struct Port { object: Object }

/// An output [MIDI port](https://developer.apple.com/reference/coremidi/midiportref) owned by a client.
///
/// A simple example to create an output port and send a MIDI event:
///
/// ```rust,no_run
/// let client = coremidi::Client::new("example-client").unwrap();
/// let output_port = client.output_port("example-port").unwrap();
/// let destination = coremidi::Destination::from_index(0).unwrap();
/// let packets = coremidi::PacketBuffer::new(0, &[0x90, 0x40, 0x7f]);
/// output_port.send(&destination, &packets).unwrap();
/// ```
#[derive(Debug)]
pub struct OutputPort { port: Port }

/// An input [MIDI port](https://developer.apple.com/reference/coremidi/midiportref) owned by a client.
///
/// A simple example to create an input port:
///
/// ```rust,no_run
/// let client = coremidi::Client::new("example-client").unwrap();
/// let input_port = client.input_port("example-port", |packet_list| println!("{}", packet_list)).unwrap();
/// let source = coremidi::Source::from_index(0).unwrap();
/// input_port.connect_source(&source);
/// ```
#[derive(Debug)]
pub struct InputPort {
    // Note: the order is important here, port needs to be dropped first
    port: Port,
    callback: BoxedCallback<PacketList>,
}

/// A MIDI source or source, owned by an entity.
/// See [MIDIEndpointRef](https://developer.apple.com/reference/coremidi/midiendpointref).
///
/// You don't need to create an endpoint directly, instead you can create system sources and sources or virtual ones from a client.
///
#[derive(Debug)]
pub struct Endpoint { object: Object }

/// A [MIDI source](https://developer.apple.com/reference/coremidi/midiendpointref) owned by an entity.
///
/// A source can be created from an index like this:
///
/// ```rust,no_run
/// let source = coremidi::Destination::from_index(0).unwrap();
/// println!("The source at index 0 has display name '{}'", source.display_name().unwrap());
/// ```
///
#[derive(Debug)]
pub struct Destination { endpoint: Endpoint }

/// A [MIDI source](https://developer.apple.com/reference/coremidi/midiendpointref) owned by an entity.
///
/// A source can be created from an index like this:
///
/// ```rust,no_run
/// let source = coremidi::Source::from_index(0).unwrap();
/// println!("The source at index 0 has display name '{}'", source.display_name().unwrap());
/// ```
///
#[derive(Debug)]
pub struct Source { endpoint: Endpoint }

/// A [MIDI virtual source](https://developer.apple.com/reference/coremidi/1495212-midisourcecreate) owned by a client.
///
/// A virtual source can be created like:
///
/// ```rust,no_run
/// let client = coremidi::Client::new("example-client").unwrap();
/// let source = client.virtual_source("example-source").unwrap();
/// ```
///
#[derive(Debug)]
pub struct VirtualSource { endpoint: Endpoint }

/// A [MIDI virtual destination](https://developer.apple.com/reference/coremidi/1495347-mididestinationcreate) owned by a client.
///
/// A virtual destination can be created like:
///
/// ```rust,no_run
/// let client = coremidi::Client::new("example-client").unwrap();
/// client.virtual_destination("example-destination", |packet_list| println!("{}", packet_list)).unwrap();
/// ```
///
#[derive(Debug)]
pub struct VirtualDestination {
    // Note: the order is important here, endpoint needs to be dropped first
    endpoint: Endpoint,
    callback: BoxedCallback<PacketList>,
}

/// A [MIDI object](https://developer.apple.com/reference/coremidi/midideviceref).
///
/// A MIDI device or external device, containing entities.
///
#[derive(Debug)]
#[derive(PartialEq)]
pub struct Device { object: Object }

/// A [list of MIDI events](https://developer.apple.com/reference/coremidi/midipacketlist) being received from, or being sent to, one endpoint.
///
#[repr(C)]
pub struct PacketList {
    // NOTE: This type must only exist in the form of immutable references
    //       pointing to valid instances of MIDIPacketList.
    //       This type must NOT implement `Copy`!
    inner: PacketListInner,
    _do_not_construct: packets::alignment::Marker
}

#[repr(packed)]
struct PacketListInner {
    num_packets: u32,
    data: [MIDIPacket; 0]
}

impl PacketList {
    /// For internal usage only.
    /// Requires this instance to actually point to a valid MIDIPacketList
    unsafe fn as_ptr(&self) -> *mut MIDIPacketList {
        self as *const PacketList as *mut PacketList as *mut MIDIPacketList
    }
}

mod object;
mod devices;
mod client;
mod ports;
mod packets;
mod properties;
mod endpoints;
mod notifications;
pub use endpoints::destinations::Destinations;
pub use endpoints::sources::Sources;
pub use packets::{PacketListIterator, Packet, PacketBuffer};
pub use properties::{Properties, PropertyGetter, PropertySetter};
pub use notifications::Notification;

/// Unschedules previously-sent packets for all the endpoints.
/// See [MIDIFlushOutput](https://developer.apple.com/reference/coremidi/1495312-midiflushoutput).
///
pub fn flush() -> Result<(), OSStatus> {
    let status = unsafe { MIDIFlushOutput(0) };
    if status == 0 { Ok(()) } else { Err(status) }
}

/// Stops and restarts MIDI I/O.
/// See [MIDIRestart](https://developer.apple.com/reference/coremidi/1495146-midirestart).
///
pub fn restart() -> Result<(), OSStatus> {
    let status = unsafe { MIDIRestart() };
    if status == 0 { Ok(()) } else { Err(status) }
}
<commit_msg>implement Send for BoxedCallback (#15)<commit_after>#![crate_name = "coremidi"]
#![crate_type = "lib"]
#![doc(html_root_url = "https://chris-zen.github.io/coremidi/")]

/*!
This is a [CoreMIDI](https://developer.apple.com/reference/coremidi) library for Rust built on top of the low-level bindings [coremidi-sys](https://github.com/jonas-k/coremidi-sys).
CoreMIDI is a macOS framework that provides APIs for communicating with MIDI (Musical Instrument Digital Interface) devices, including hardware keyboards and synthesizers.

This library preserves the fundamental concepts behind the CoreMIDI framework, while being Rust idiomatic. This means that if you already know CoreMIDI, you will find very easy to start using it.

Please see the [examples](examples) for an idea on how it looks like, but if you are eager to see an example, this is how you would send some note:

```rust,no_run
extern crate coremidi;
use std::time::Duration;
use std::thread;
let client = coremidi::Client::new("example-client").unwrap();
let output_port = client.output_port("example-port").unwrap();
let destination = coremidi::Destination::from_index(0).unwrap();
let note_on = coremidi::PacketBuffer::new(0, &[0x90, 0x40, 0x7f]);
let note_off = coremidi::PacketBuffer::new(0, &[0x80, 0x40, 0x7f]);
output_port.send(&destination, &note_on).unwrap();
thread::sleep(Duration::from_millis(1000));
output_port.send(&destination, &note_off).unwrap();
```

If you are looking for a portable MIDI library then you can look into:

- [midir](https://github.com/Boddlnagg/midir) (which is using this lib)
- [portmidi-rs](https://github.com/musitdev/portmidi-rs)

For handling low level MIDI data you may look into:

- [midi-rs](https://github.com/samdoshi/midi-rs)
- [rimd](https://github.com/RustAudio/rimd)

*/

extern crate core_foundation_sys;
extern crate core_foundation;
extern crate coremidi_sys;

use core_foundation_sys::base::OSStatus;

use coremidi_sys::{
    MIDIObjectRef, MIDIFlushOutput, MIDIRestart, MIDIPacket, MIDIPacketList
};

/// A [MIDI Object](https://developer.apple.com/reference/coremidi/midiobjectref).
///
/// The base class of many CoreMIDI objects.
///
#[derive(PartialEq)]
pub struct Object(MIDIObjectRef);

/// A [MIDI client](https://developer.apple.com/reference/coremidi/midiclientref).
///
/// An object maintaining per-client state.
///
/// A simple example to create a Client:
///
/// ```rust,no_run
/// let client = coremidi::Client::new("example-client").unwrap();
/// ```
#[derive(Debug)]
pub struct Client {
    // Order is important, object needs to be dropped first
    object: Object,
    callback: BoxedCallback<Notification>,
}

// A lifetime-managed wrapper for callback functions
#[derive(Debug, PartialEq)]
struct BoxedCallback<T>(*mut Box<FnMut(&T)>);

impl<T> BoxedCallback<T> {
    fn new<F: FnMut(&T) + Send + 'static>(f: F) -> BoxedCallback<T> {
        BoxedCallback(Box::into_raw(Box::new(Box::new(f))))
    }

    fn null() -> BoxedCallback<T> {
        BoxedCallback(::std::ptr::null_mut())
    }

    fn raw_ptr(&mut self) -> *mut ::std::os::raw::c_void {
        self.0 as *mut ::std::os::raw::c_void
    }

    // must not be null
    unsafe fn call_from_raw_ptr(raw_ptr: *mut ::std::os::raw::c_void, arg: &T) {
        let callback = &mut *(raw_ptr as *mut Box<FnMut(&T)>);
        callback(arg);
    }
}

unsafe impl<T> Send for BoxedCallback<T> {}

impl<T> Drop for BoxedCallback<T> {
    fn drop(&mut self) {
        unsafe {
            if !self.0.is_null() {
                let _ = Box::from_raw(self.0);
            }
        }
    }
}

/// A MIDI connection port owned by a client.
/// See [MIDIPortRef](https://developer.apple.com/reference/coremidi/midiportref).
///
/// Ports can't be instantiated directly, but through a client.
///
#[derive(Debug)]
pub struct Port { object: Object }

/// An output [MIDI port](https://developer.apple.com/reference/coremidi/midiportref) owned by a client.
///
/// A simple example to create an output port and send a MIDI event:
///
/// ```rust,no_run
/// let client = coremidi::Client::new("example-client").unwrap();
/// let output_port = client.output_port("example-port").unwrap();
/// let destination = coremidi::Destination::from_index(0).unwrap();
/// let packets = coremidi::PacketBuffer::new(0, &[0x90, 0x40, 0x7f]);
/// output_port.send(&destination, &packets).unwrap();
/// ```
#[derive(Debug)]
pub struct OutputPort { port: Port }

/// An input [MIDI port](https://developer.apple.com/reference/coremidi/midiportref) owned by a client.
///
/// A simple example to create an input port:
///
/// ```rust,no_run
/// let client = coremidi::Client::new("example-client").unwrap();
/// let input_port = client.input_port("example-port", |packet_list| println!("{}", packet_list)).unwrap();
/// let source = coremidi::Source::from_index(0).unwrap();
/// input_port.connect_source(&source);
/// ```
#[derive(Debug)]
pub struct InputPort {
    // Note: the order is important here, port needs to be dropped first
    port: Port,
    callback: BoxedCallback<PacketList>,
}

/// A MIDI source or source, owned by an entity.
/// See [MIDIEndpointRef](https://developer.apple.com/reference/coremidi/midiendpointref).
///
/// You don't need to create an endpoint directly, instead you can create system sources and sources or virtual ones from a client.
///
#[derive(Debug)]
pub struct Endpoint { object: Object }

/// A [MIDI source](https://developer.apple.com/reference/coremidi/midiendpointref) owned by an entity.
///
/// A source can be created from an index like this:
///
/// ```rust,no_run
/// let source = coremidi::Destination::from_index(0).unwrap();
/// println!("The source at index 0 has display name '{}'", source.display_name().unwrap());
/// ```
///
#[derive(Debug)]
pub struct Destination { endpoint: Endpoint }

/// A [MIDI source](https://developer.apple.com/reference/coremidi/midiendpointref) owned by an entity.
///
/// A source can be created from an index like this:
///
/// ```rust,no_run
/// let source = coremidi::Source::from_index(0).unwrap();
/// println!("The source at index 0 has display name '{}'", source.display_name().unwrap());
/// ```
///
#[derive(Debug)]
pub struct Source { endpoint: Endpoint }

/// A [MIDI virtual source](https://developer.apple.com/reference/coremidi/1495212-midisourcecreate) owned by a client.
///
/// A virtual source can be created like:
///
/// ```rust,no_run
/// let client = coremidi::Client::new("example-client").unwrap();
/// let source = client.virtual_source("example-source").unwrap();
/// ```
///
#[derive(Debug)]
pub struct VirtualSource { endpoint: Endpoint }

/// A [MIDI virtual destination](https://developer.apple.com/reference/coremidi/1495347-mididestinationcreate) owned by a client.
///
/// A virtual destination can be created like:
///
/// ```rust,no_run
/// let client = coremidi::Client::new("example-client").unwrap();
/// client.virtual_destination("example-destination", |packet_list| println!("{}", packet_list)).unwrap();
/// ```
///
#[derive(Debug)]
pub struct VirtualDestination {
    // Note: the order is important here, endpoint needs to be dropped first
    endpoint: Endpoint,
    callback: BoxedCallback<PacketList>,
}

/// A [MIDI object](https://developer.apple.com/reference/coremidi/midideviceref).
///
/// A MIDI device or external device, containing entities.
///
#[derive(Debug)]
#[derive(PartialEq)]
pub struct Device { object: Object }

/// A [list of MIDI events](https://developer.apple.com/reference/coremidi/midipacketlist) being received from, or being sent to, one endpoint.
///
#[repr(C)]
pub struct PacketList {
    // NOTE: This type must only exist in the form of immutable references
    //       pointing to valid instances of MIDIPacketList.
    //       This type must NOT implement `Copy`!
    inner: PacketListInner,
    _do_not_construct: packets::alignment::Marker
}

#[repr(packed)]
struct PacketListInner {
    num_packets: u32,
    data: [MIDIPacket; 0]
}

impl PacketList {
    /// For internal usage only.
    /// Requires this instance to actually point to a valid MIDIPacketList
    unsafe fn as_ptr(&self) -> *mut MIDIPacketList {
        self as *const PacketList as *mut PacketList as *mut MIDIPacketList
    }
}

mod object;
mod devices;
mod client;
mod ports;
mod packets;
mod properties;
mod endpoints;
mod notifications;
pub use endpoints::destinations::Destinations;
pub use endpoints::sources::Sources;
pub use packets::{PacketListIterator, Packet, PacketBuffer};
pub use properties::{Properties, PropertyGetter, PropertySetter};
pub use notifications::Notification;

/// Unschedules previously-sent packets for all the endpoints.
/// See [MIDIFlushOutput](https://developer.apple.com/reference/coremidi/1495312-midiflushoutput).
///
pub fn flush() -> Result<(), OSStatus> {
    let status = unsafe { MIDIFlushOutput(0) };
    if status == 0 { Ok(()) } else { Err(status) }
}

/// Stops and restarts MIDI I/O.
/// See [MIDIRestart](https://developer.apple.com/reference/coremidi/1495146-midirestart).
///
pub fn restart() -> Result<(), OSStatus> {
    let status = unsafe { MIDIRestart() };
    if status == 0 { Ok(()) } else { Err(status) }
}
<|endoftext|>


<commit_before>
mod abort_on_panic;

use abort_on_panic::abort_on_panic;

/// Allows use of a value inside a `&mut T` as though it was owned by the closure
///
/// The closure must return a valid T
/// # Aborts
/// Will abort the program (exiting with status code -1) if the closure panics.
pub fn take<T, F>(mut_ref: &mut T, closure: F)
  where F: FnOnce(T) -> T {
    use std::ptr;
    abort_on_panic(|| {
        unsafe {
            let old_t = ptr::read(mut_ref);
            let new_t = closure(old_t);
            ptr::write(mut_ref, new_t);
        }
    });
}

#[test]
fn it_works() {
    #[derive(PartialEq, Eq, Debug)]
    enum Foo {A, B};
    impl Drop for Foo {
        fn drop(&mut self) {
            match *self {
                Foo::A => println!("Foo::A dropped"),
                Foo::B => println!("Foo::B dropped")
            }
        }
    }
    let mut foo = Foo::A;
    take(&mut foo, |mut f| {
       drop(f);
       Foo::B
    });
    assert_eq!(&foo, &Foo::B);
}<commit_msg>Add example for take_mut::take()<commit_after>
mod abort_on_panic;

use abort_on_panic::abort_on_panic;

/// Allows use of a value inside a `&mut T` as though it was owned by the closure
///
/// The closure must return a valid T
/// # Aborts
/// Will abort the program (exiting with status code -1) if the closure panics.
///
/// # Example
/// ```
/// struct Foo;
/// let mut foo = Foo;
/// take_mut::take(&mut foo, |foo| {
///     // Can now consume from the reference, and provide a new value later
///     drop(foo);
///     // Do more stuff
///     Foo // Return new Foo from closure
/// });
pub fn take<T, F>(mut_ref: &mut T, closure: F)
  where F: FnOnce(T) -> T {
    use std::ptr;
    abort_on_panic(|| {
        unsafe {
            let old_t = ptr::read(mut_ref);
            let new_t = closure(old_t);
            ptr::write(mut_ref, new_t);
        }
    });
}

#[test]
fn it_works() {
    #[derive(PartialEq, Eq, Debug)]
    enum Foo {A, B};
    impl Drop for Foo {
        fn drop(&mut self) {
            match *self {
                Foo::A => println!("Foo::A dropped"),
                Foo::B => println!("Foo::B dropped")
            }
        }
    }
    let mut foo = Foo::A;
    take(&mut foo, |mut f| {
       drop(f);
       Foo::B
    });
    assert_eq!(&foo, &Foo::B);
}<|endoftext|>


<commit_before>#![feature(globs)]
#![feature(phase)]

#[phase(plugin, link)] extern crate log;

extern crate time;
extern crate conduit;
extern crate "conduit-middleware" as middleware;

use std::fmt::Show;

use conduit::{Request, Response};
use middleware::Middleware;

pub struct LogRequests(pub u32);

struct LogStart(u64);

impl Middleware for LogRequests {
    fn before(&self, req: &mut Request) -> Result<(), Box<Show + 'static>> {
        req.mut_extensions().insert(LogStart(time::precise_time_ns()));
        Ok(())
    }

    fn after(&self, req: &mut Request, resp: Result<Response, Box<Show + 'static>>)
             -> Result<Response, Box<Show + 'static>> {
        let LogStart(start) = *req.mut_extensions().find::<LogStart>().unwrap();

        match resp {
            Ok(ref resp) => self.log_message(req, start, resp.status.val0(),
                                             None),
            Err(ref e) => {
                let msg: &Show = &**e;
                self.log_message(req, start, 500, Some(msg))
            }
        }
        resp
    }

}

impl LogRequests {
    fn log_message(&self, req: &mut Request, start: u64, status: uint,
                   msg: Option<&Show>) {
        let LogRequests(level) = *self;
        log!(level, "{} [{}] {} {} - {}ms {}{}",
             req.remote_ip(),
             time::now().rfc3339(),
             req.method(),
             req.path(),
             (time::precise_time_ns() - start) / 1000000,
             status,
             match msg {
                 None => String::new(),
                 Some(s) => format!(": {}", s),
             })
    }
}

#[cfg(test)]
mod tests {
    extern crate "conduit-test" as test;

    use {LogRequests};

    use std;
    use log;
    use conduit;
    use middleware;

    use std::io::{ChanWriter, ChanReader};
    use log::{Logger, LogRecord};
    use conduit::{Request, Response, Handler};

    struct MyWriter(ChanWriter);

    impl Logger for MyWriter {
        fn log(&mut self, record: &LogRecord) {
            let MyWriter(ref mut inner) = *self;
            (write!(inner, "{}", record.args)).unwrap();
        }
    }

    #[test]
    fn test_log() {
        let (sender, receiver) = channel();
        let mut reader = ChanReader::new(receiver);

        let mut builder = middleware::MiddlewareBuilder::new(handler);
        builder.add(LogRequests(log::ERROR));

        task(builder, sender);

        let result = reader.read_to_string().ok().expect("No response");
        let parts = result.as_slice().split(' ').map(|s| s.to_string()).collect::<Vec<String>>();

        assert_eq!(parts[0].as_slice(), "127.0.0.1");
        // Failing on travis?! bug in libtime?!
        // assert!(parts.get(1).as_slice().len() == "[2014-07-01T22:34:06-07:00]".len(),
        //         "bad length for {}", parts.get(1));
        assert_eq!(parts[2].as_slice(), "Get");
        assert_eq!(parts[3].as_slice(), "/foo");
    }

    fn task<H: Handler + 'static + Send>(handler: H, sender: Sender<Vec<u8>>) {
        spawn(proc() {
            log::set_logger(box MyWriter(ChanWriter::new(sender)));
            let mut request = test::MockRequest::new(conduit::Get, "/foo");
            let _ = handler.call(&mut request);
        });
    }

    fn handler(_: &mut Request) -> Result<Response, ()> {
        Ok(Response {
            status: (200, "OK"),
            headers: std::collections::HashMap::new(),
            body: box std::io::util::NullReader
        })
    }
}
<commit_msg>Update to conduit master<commit_after>#![feature(globs)]
#![feature(phase)]

#[phase(plugin, link)] extern crate log;

extern crate time;
extern crate conduit;
extern crate "conduit-middleware" as middleware;

use std::fmt::Show;

use conduit::{Request, Response};
use middleware::Middleware;

pub struct LogRequests(pub u32);

struct LogStart(u64);

impl Middleware for LogRequests {
    fn before(&self, req: &mut Request) -> Result<(), Box<Show + 'static>> {
        req.mut_extensions().insert(LogStart(time::precise_time_ns()));
        Ok(())
    }

    fn after(&self, req: &mut Request, resp: Result<Response, Box<Show + 'static>>)
             -> Result<Response, Box<Show + 'static>> {
        let LogStart(start) = *req.mut_extensions().find::<LogStart>().unwrap();

        match resp {
            Ok(ref resp) => self.log_message(req, start, resp.status.val0(),
                                             None),
            Err(ref e) => {
                let msg: &Show = &**e;
                self.log_message(req, start, 500, Some(msg))
            }
        }
        resp
    }

}

impl LogRequests {
    fn log_message(&self, req: &mut Request, start: u64, status: uint,
                   msg: Option<&Show>) {
        let LogRequests(level) = *self;
        log!(level, "{} [{}] {} {} - {}ms {}{}",
             req.remote_ip(),
             time::now().rfc3339(),
             req.method(),
             req.path(),
             (time::precise_time_ns() - start) / 1000000,
             status,
             match msg {
                 None => String::new(),
                 Some(s) => format!(": {}", s),
             })
    }
}

#[cfg(test)]
mod tests {
    extern crate "conduit-test" as test;

    use {LogRequests};

    use std;
    use log;
    use middleware;

    use std::io::{ChanWriter, ChanReader};
    use log::{Logger, LogRecord};
    use conduit::{Request, Response, Handler, Method};

    struct MyWriter(ChanWriter);

    impl Logger for MyWriter {
        fn log(&mut self, record: &LogRecord) {
            let MyWriter(ref mut inner) = *self;
            (write!(inner, "{}", record.args)).unwrap();
        }
    }

    #[test]
    fn test_log() {
        let (sender, receiver) = channel();
        let mut reader = ChanReader::new(receiver);

        let mut builder = middleware::MiddlewareBuilder::new(handler);
        builder.add(LogRequests(log::ERROR));

        task(builder, sender);

        let result = reader.read_to_string().ok().expect("No response");
        let parts = result.as_slice().split(' ').map(|s| s.to_string()).collect::<Vec<String>>();

        assert_eq!(parts[0].as_slice(), "127.0.0.1");
        // Failing on travis?! bug in libtime?!
        // assert!(parts.get(1).as_slice().len() == "[2014-07-01T22:34:06-07:00]".len(),
        //         "bad length for {}", parts.get(1));
        assert_eq!(parts[2].as_slice(), "Get");
        assert_eq!(parts[3].as_slice(), "/foo");
    }

    fn task<H: Handler + 'static + Send>(handler: H, sender: Sender<Vec<u8>>) {
        spawn(proc() {
            log::set_logger(box MyWriter(ChanWriter::new(sender)));
            let mut request = test::MockRequest::new(Method::Get, "/foo");
            let _ = handler.call(&mut request);
        });
    }

    fn handler(_: &mut Request) -> Result<Response, ()> {
        Ok(Response {
            status: (200, "OK"),
            headers: std::collections::HashMap::new(),
            body: box std::io::util::NullReader
        })
    }
}
<|endoftext|>


<commit_before>#[macro_use] extern crate bitflags;
extern crate byteorder;

use std::io;

use byteorder::{ReadBytesExt, LittleEndian};

use std::io::Read;
use std::io::Seek;

mod block_groups;
mod extents;
mod parse;

pub mod mbr;

use extents::TreeReader;

bitflags! {
    struct InodeFlags: u32 {
        const INODE_SECRM        = 0x00000001; /* Secure deletion */
        const INODE_UNRM         = 0x00000002; /* Undelete */
        const INODE_COMPR        = 0x00000004; /* Compress file */
        const INODE_SYNC         = 0x00000008; /* Synchronous updates */
        const INODE_IMMUTABLE    = 0x00000010; /* Immutable file */
        const INODE_APPEND       = 0x00000020; /* writes to file may only append */
        const INODE_NODUMP       = 0x00000040; /* do not dump file */
        const INODE_NOATIME      = 0x00000080; /* do not update atime */
        const INODE_DIRTY        = 0x00000100; /* reserved for compression */
        const INODE_COMPRBLK     = 0x00000200; /* One or more compressed clusters */
        const INODE_NOCOMPR      = 0x00000400; /* Don't compress */
        const INODE_ENCRYPT      = 0x00000800; /* encrypted file */
        const INODE_INDEX        = 0x00001000; /* hash-indexed directory */
        const INODE_IMAGIC       = 0x00002000; /* AFS directory */
        const INODE_JOURNAL_DATA = 0x00004000; /* file data should be journaled */
        const INODE_NOTAIL       = 0x00008000; /* file tail should not be merged */
        const INODE_DIRSYNC      = 0x00010000; /* dirsync behaviour (directories only) */
        const INODE_TOPDIR       = 0x00020000; /* Top of directory hierarchies*/
        const INODE_HUGE_FILE    = 0x00040000; /* Set to each huge file */
        const INODE_EXTENTS      = 0x00080000; /* Inode uses extents */
        const INODE_EA_INODE     = 0x00200000; /* Inode used for large EA */
        const INODE_EOFBLOCKS    = 0x00400000; /* Blocks allocated beyond EOF */
        const INODE_INLINE_DATA  = 0x10000000; /* Inode has inline data. */
        const INODE_PROJINHERIT  = 0x20000000; /* Create with parents projid */
        const INODE_RESERVED     = 0x80000000; /* reserved for ext4 lib */
    }
}

#[derive(Debug, PartialEq)]
pub enum FileType {
    RegularFile,     // S_IFREG (Regular file)
    SymbolicLink,    // S_IFLNK (Symbolic link)
    CharacterDevice, // S_IFCHR (Character device)
    BlockDevice,     // S_IFBLK (Block device)
    Directory,       // S_IFDIR (Directory)
    Fifo,            // S_IFIFO (FIFO)
    Socket,          // S_IFSOCK (Socket)
}

#[derive(Debug)]
pub enum Enhanced {
    RegularFile,
    SymbolicLink(String),
    CharacterDevice(u16, u32),
    BlockDevice(u16, u32),
    Directory(Vec<DirEntry>),
    Fifo,
    Socket,
}

impl FileType {
    fn from_mode(mode: u16) -> Option<FileType> {
        match mode >> 12 {
            0x1 => Some(FileType::Fifo),
            0x2 => Some(FileType::CharacterDevice),
            0x4 => Some(FileType::Directory),
            0x6 => Some(FileType::BlockDevice),
            0x8 => Some(FileType::RegularFile),
            0xA => Some(FileType::SymbolicLink),
            0xC => Some(FileType::Socket),
            _ => None,
        }
    }

    fn from_dir_hint(hint: u8) -> Option<FileType> {
        match hint {
            1 => Some(FileType::RegularFile),
            2 => Some(FileType::Directory),
            3 => Some(FileType::CharacterDevice),
            4 => Some(FileType::BlockDevice),
            5 => Some(FileType::Fifo),
            6 => Some(FileType::Socket),
            7 => Some(FileType::SymbolicLink),
            _ => None,
        }
    }
}

#[derive(Debug)]
pub struct DirEntry {
    pub inode: u32,
    pub file_type: FileType,
    pub name: String,
}

#[derive(Debug)]
pub struct Stat {
    pub extracted_type: FileType,
    pub file_mode: u16,
    pub uid: u32,
    pub gid: u32,
    pub size: u64,
    pub atime: Time,
    pub ctime: Time,
    pub mtime: Time,
    pub btime: Option<Time>,
    pub link_count: u16,
}

pub struct Inode {
    pub stat: Stat,
    pub number: u32,
    flags: InodeFlags,
    block: [u8; 4 * 15],
    block_size: u32,
}

#[derive(Debug)]
pub struct SuperBlock<R> {
    inner: R,
    groups: block_groups::BlockGroups,
}

#[derive(Debug)]
pub struct Time {
    pub epoch_secs: u32,
    pub nanos: Option<u32>,
}

impl<R> SuperBlock<R>
where R: io::Read + io::Seek {

    pub fn load(mut inner: R) -> io::Result<SuperBlock<R>> {
        inner.seek(io::SeekFrom::Start(1024))?;
        parse::superblock(inner)
    }

    pub fn load_inode(&mut self, inode: u32) -> io::Result<Inode> {
        self.inner.seek(io::SeekFrom::Start(self.groups.index_of(inode)))?;
        parse::inode(&mut self.inner, inode, self.groups.block_size)
    }

    pub fn root(&mut self) -> io::Result<Inode> {
        self.load_inode(2)
    }

    pub fn walk<F>(&mut self, inode: &Inode, path: String, visit: &F) -> io::Result<bool>
    where F: Fn(&str, u32, &Stat, &Enhanced) -> io::Result<bool> {
        let enhanced = inode.enhance(&mut self.inner)?;

        if !visit(path.as_str(), inode.number, &inode.stat, &enhanced)? {
            return Ok(false);
        }

        if let Enhanced::Directory(entries) = enhanced {
            for entry in entries {
                if "." == entry.name || ".." == entry.name {
                    continue;
                }

                let child_node = self.load_inode(entry.inode)?;
                if !self.walk(&child_node, format!("{}/{}", path, entry.name), visit)? {
                    return Ok(false)
                }
            }
        }

//    self.walk(inner, &i, format!("{}/{}", path, entry.name)).map_err(|e|
//    parse_error(format!("while processing {}: {}", path, e)))?;

        Ok(true)
    }
}

impl Inode {

    pub fn reader<R>(&self, inner: R) -> io::Result<TreeReader<R>>
    where R: io::Read + io::Seek {
        TreeReader::new(inner, self.block_size, self.block)
    }

    pub fn enhance<R>(&self, inner: R) -> io::Result<Enhanced>
    where R: io::Read + io::Seek {
        Ok(match self.stat.extracted_type {
            FileType::RegularFile => Enhanced::RegularFile,
            FileType::Socket => Enhanced::Socket,
            FileType::Fifo => Enhanced::Fifo,

            FileType::Directory => Enhanced::Directory(self.read_directory(inner)?),
            FileType::SymbolicLink =>
                Enhanced::SymbolicLink(if self.stat.size < 60 {
                    assert!(self.flags.is_empty());
                    std::str::from_utf8(&self.block[0..self.stat.size as usize]).expect("utf-8").to_string()
                } else {
                    assert!(self.only_relevant_flag_is_extents());
                    std::str::from_utf8(&self.load_all(inner)?).expect("utf-8").to_string()
                }),
            FileType::CharacterDevice => {
                let (maj, min) = load_maj_min(self.block);
                Enhanced::CharacterDevice(maj, min)
            }
            FileType::BlockDevice => {
                let (maj, min) = load_maj_min(self.block);
                Enhanced::BlockDevice(maj, min)
            }
        })
    }

    fn load_all<R>(&self, inner: R) -> io::Result<Vec<u8>>
    where R: io::Read + io::Seek {
        let size = usize_check(self.stat.size)?;
        let mut ret = Vec::with_capacity(size);

        assert_eq!(size, self.reader(inner)?.read_to_end(&mut ret)?);

        Ok(ret)
    }

    fn read_directory<R>(&self, inner: R) -> io::Result<Vec<DirEntry>>
    where R: io::Read + io::Seek {

        let mut dirs = Vec::with_capacity(40);

        let data = {
            // if the flags, minus irrelevant flags, isn't just EXTENTS...
            if !self.only_relevant_flag_is_extents() {
                return Err(parse_error(format!("inode without unsupported flags: {0:x} {0:b}", self.flags)));
            }

            self.load_all(inner)?
        };

        let total_len = data.len();

        let mut cursor = io::Cursor::new(data);
        let mut read = 0usize;
        loop {
            let child_inode = cursor.read_u32::<LittleEndian>()?;
            let rec_len = cursor.read_u16::<LittleEndian>()?;
            let name_len = cursor.read_u8()?;
            let file_type = cursor.read_u8()?;
            let mut name = vec![0u8; name_len as usize];
            cursor.read_exact(&mut name)?;
            cursor.seek(io::SeekFrom::Current(rec_len as i64 - name_len as i64 - 4 - 2 - 2))?;
            if 0 != child_inode {
                let name = std::str::from_utf8(&name).map_err(|e|
                    parse_error(format!("invalid utf-8 in file name: {}", e)))?;

                dirs.push(DirEntry {
                    inode: child_inode,
                    name: name.to_string(),
                    file_type: FileType::from_dir_hint(file_type)
                        .expect("valid file type"),
                });
            }

            read += rec_len as usize;
            if read >= total_len {
                assert_eq!(read, total_len);
                break;
            }
        }

        Ok(dirs)
    }

    fn only_relevant_flag_is_extents(&self) -> bool {
        self.flags & (
            INODE_COMPR
            | INODE_DIRTY
            | INODE_COMPRBLK
            | INODE_ENCRYPT
            | INODE_IMAGIC
            | INODE_NOTAIL
            | INODE_TOPDIR
            | INODE_HUGE_FILE
            | INODE_EXTENTS
            | INODE_EA_INODE
            | INODE_EOFBLOCKS
            | INODE_INLINE_DATA
        ) == INODE_EXTENTS
    }
}

fn load_maj_min(block: [u8; 4 * 15]) -> (u16, u32) {
    if 0 != block[0] || 0 != block[1] {
        (block[1] as u16, block[0] as u32)
    } else {
        // if you think reading this is bad, I had to write it
        (block[5] as u16
             | (((block[6] & 0b0000_1111) as u16) << 8),
         block[4] as u32
             | ((block[7] as u32) << 12)
             | (((block[6] & 0b1111_0000) as u32) >> 4) << 8)
    }
}

fn as_u16(buf: &[u8]) -> u16 {
    buf[0] as u16 + buf[1] as u16 * 0x100
}

fn as_u32(buf: &[u8]) -> u32 {
    as_u16(buf) as u32 + as_u16(&buf[2..]) as u32 * 0x10000
}

fn parse_error(msg: String) -> io::Error {
    io::Error::new(io::ErrorKind::InvalidInput, msg)
}

#[allow(unknown_lints, absurd_extreme_comparisons)]
fn usize_check(val: u64) -> io::Result<usize> {
    // this check only makes sense on non-64-bit platforms; on 64-bit usize == u64.
    if val > std::usize::MAX as u64 {
        Err(io::Error::new(io::ErrorKind::InvalidData,
                                  format!("value is too big for memory on this platform: {}",
                                          val)))
    } else {
        Ok(val as usize)
    }
}
<commit_msg>helpers?<commit_after>#[macro_use] extern crate bitflags;
extern crate byteorder;

use std::io;

use byteorder::{ReadBytesExt, LittleEndian};

use std::io::Read;
use std::io::Seek;

mod block_groups;
mod extents;
mod parse;

pub mod mbr;

use extents::TreeReader;

bitflags! {
    struct InodeFlags: u32 {
        const INODE_SECRM        = 0x00000001; /* Secure deletion */
        const INODE_UNRM         = 0x00000002; /* Undelete */
        const INODE_COMPR        = 0x00000004; /* Compress file */
        const INODE_SYNC         = 0x00000008; /* Synchronous updates */
        const INODE_IMMUTABLE    = 0x00000010; /* Immutable file */
        const INODE_APPEND       = 0x00000020; /* writes to file may only append */
        const INODE_NODUMP       = 0x00000040; /* do not dump file */
        const INODE_NOATIME      = 0x00000080; /* do not update atime */
        const INODE_DIRTY        = 0x00000100; /* reserved for compression */
        const INODE_COMPRBLK     = 0x00000200; /* One or more compressed clusters */
        const INODE_NOCOMPR      = 0x00000400; /* Don't compress */
        const INODE_ENCRYPT      = 0x00000800; /* encrypted file */
        const INODE_INDEX        = 0x00001000; /* hash-indexed directory */
        const INODE_IMAGIC       = 0x00002000; /* AFS directory */
        const INODE_JOURNAL_DATA = 0x00004000; /* file data should be journaled */
        const INODE_NOTAIL       = 0x00008000; /* file tail should not be merged */
        const INODE_DIRSYNC      = 0x00010000; /* dirsync behaviour (directories only) */
        const INODE_TOPDIR       = 0x00020000; /* Top of directory hierarchies*/
        const INODE_HUGE_FILE    = 0x00040000; /* Set to each huge file */
        const INODE_EXTENTS      = 0x00080000; /* Inode uses extents */
        const INODE_EA_INODE     = 0x00200000; /* Inode used for large EA */
        const INODE_EOFBLOCKS    = 0x00400000; /* Blocks allocated beyond EOF */
        const INODE_INLINE_DATA  = 0x10000000; /* Inode has inline data. */
        const INODE_PROJINHERIT  = 0x20000000; /* Create with parents projid */
        const INODE_RESERVED     = 0x80000000; /* reserved for ext4 lib */
    }
}

#[derive(Debug, PartialEq)]
pub enum FileType {
    RegularFile,     // S_IFREG (Regular file)
    SymbolicLink,    // S_IFLNK (Symbolic link)
    CharacterDevice, // S_IFCHR (Character device)
    BlockDevice,     // S_IFBLK (Block device)
    Directory,       // S_IFDIR (Directory)
    Fifo,            // S_IFIFO (FIFO)
    Socket,          // S_IFSOCK (Socket)
}

#[derive(Debug)]
pub enum Enhanced {
    RegularFile,
    SymbolicLink(String),
    CharacterDevice(u16, u32),
    BlockDevice(u16, u32),
    Directory(Vec<DirEntry>),
    Fifo,
    Socket,
}

impl FileType {
    fn from_mode(mode: u16) -> Option<FileType> {
        match mode >> 12 {
            0x1 => Some(FileType::Fifo),
            0x2 => Some(FileType::CharacterDevice),
            0x4 => Some(FileType::Directory),
            0x6 => Some(FileType::BlockDevice),
            0x8 => Some(FileType::RegularFile),
            0xA => Some(FileType::SymbolicLink),
            0xC => Some(FileType::Socket),
            _ => None,
        }
    }

    fn from_dir_hint(hint: u8) -> Option<FileType> {
        match hint {
            1 => Some(FileType::RegularFile),
            2 => Some(FileType::Directory),
            3 => Some(FileType::CharacterDevice),
            4 => Some(FileType::BlockDevice),
            5 => Some(FileType::Fifo),
            6 => Some(FileType::Socket),
            7 => Some(FileType::SymbolicLink),
            _ => None,
        }
    }
}

#[derive(Debug)]
pub struct DirEntry {
    pub inode: u32,
    pub file_type: FileType,
    pub name: String,
}

#[derive(Debug)]
pub struct Stat {
    pub extracted_type: FileType,
    pub file_mode: u16,
    pub uid: u32,
    pub gid: u32,
    pub size: u64,
    pub atime: Time,
    pub ctime: Time,
    pub mtime: Time,
    pub btime: Option<Time>,
    pub link_count: u16,
}

pub struct Inode {
    pub stat: Stat,
    pub number: u32,
    flags: InodeFlags,
    block: [u8; 4 * 15],
    block_size: u32,
}

#[derive(Debug)]
pub struct SuperBlock<R> {
    inner: R,
    groups: block_groups::BlockGroups,
}

#[derive(Debug)]
pub struct Time {
    pub epoch_secs: u32,
    pub nanos: Option<u32>,
}

impl<R> SuperBlock<R>
where R: io::Read + io::Seek {

    pub fn load(mut inner: R) -> io::Result<SuperBlock<R>> {
        inner.seek(io::SeekFrom::Start(1024))?;
        parse::superblock(inner)
    }

    pub fn load_inode(&mut self, inode: u32) -> io::Result<Inode> {
        self.inner.seek(io::SeekFrom::Start(self.groups.index_of(inode)))?;
        parse::inode(&mut self.inner, inode, self.groups.block_size)
    }

    pub fn root(&mut self) -> io::Result<Inode> {
        self.load_inode(2)
    }

    pub fn walk<F>(&mut self, inode: &Inode, path: String, visit: &F) -> io::Result<bool>
    where F: Fn(&str, u32, &Stat, &Enhanced) -> io::Result<bool> {
        let enhanced = inode.enhance(&mut self.inner)?;

        if !visit(path.as_str(), inode.number, &inode.stat, &enhanced)? {
            return Ok(false);
        }

        if let Enhanced::Directory(entries) = enhanced {
            for entry in entries {
                if "." == entry.name || ".." == entry.name {
                    continue;
                }

                let child_node = self.load_inode(entry.inode)?;
                if !self.walk(&child_node, format!("{}/{}", path, entry.name), visit)? {
                    return Ok(false)
                }
            }
        }

//    self.walk(inner, &i, format!("{}/{}", path, entry.name)).map_err(|e|
//    parse_error(format!("while processing {}: {}", path, e)))?;

        Ok(true)
    }

    pub fn open(&mut self, inode: &Inode) -> io::Result<TreeReader<&mut R>> {
        inode.reader(&mut self.inner)
    }

    pub fn enhance(&mut self, inode: &Inode) -> io::Result<Enhanced> {
        inode.enhance(&mut self.inner)
    }
}

impl Inode {

    fn reader<R>(&self, inner: R) -> io::Result<TreeReader<R>>
    where R: io::Read + io::Seek {
        TreeReader::new(inner, self.block_size, self.block)
    }

    fn enhance<R>(&self, inner: R) -> io::Result<Enhanced>
    where R: io::Read + io::Seek {
        Ok(match self.stat.extracted_type {
            FileType::RegularFile => Enhanced::RegularFile,
            FileType::Socket => Enhanced::Socket,
            FileType::Fifo => Enhanced::Fifo,

            FileType::Directory => Enhanced::Directory(self.read_directory(inner)?),
            FileType::SymbolicLink =>
                Enhanced::SymbolicLink(if self.stat.size < 60 {
                    assert!(self.flags.is_empty());
                    std::str::from_utf8(&self.block[0..self.stat.size as usize]).expect("utf-8").to_string()
                } else {
                    assert!(self.only_relevant_flag_is_extents());
                    std::str::from_utf8(&self.load_all(inner)?).expect("utf-8").to_string()
                }),
            FileType::CharacterDevice => {
                let (maj, min) = load_maj_min(self.block);
                Enhanced::CharacterDevice(maj, min)
            }
            FileType::BlockDevice => {
                let (maj, min) = load_maj_min(self.block);
                Enhanced::BlockDevice(maj, min)
            }
        })
    }

    fn load_all<R>(&self, inner: R) -> io::Result<Vec<u8>>
    where R: io::Read + io::Seek {
        let size = usize_check(self.stat.size)?;
        let mut ret = Vec::with_capacity(size);

        assert_eq!(size, self.reader(inner)?.read_to_end(&mut ret)?);

        Ok(ret)
    }

    fn read_directory<R>(&self, inner: R) -> io::Result<Vec<DirEntry>>
    where R: io::Read + io::Seek {

        let mut dirs = Vec::with_capacity(40);

        let data = {
            // if the flags, minus irrelevant flags, isn't just EXTENTS...
            if !self.only_relevant_flag_is_extents() {
                return Err(parse_error(format!("inode without unsupported flags: {0:x} {0:b}", self.flags)));
            }

            self.load_all(inner)?
        };

        let total_len = data.len();

        let mut cursor = io::Cursor::new(data);
        let mut read = 0usize;
        loop {
            let child_inode = cursor.read_u32::<LittleEndian>()?;
            let rec_len = cursor.read_u16::<LittleEndian>()?;
            let name_len = cursor.read_u8()?;
            let file_type = cursor.read_u8()?;
            let mut name = vec![0u8; name_len as usize];
            cursor.read_exact(&mut name)?;
            cursor.seek(io::SeekFrom::Current(rec_len as i64 - name_len as i64 - 4 - 2 - 2))?;
            if 0 != child_inode {
                let name = std::str::from_utf8(&name).map_err(|e|
                    parse_error(format!("invalid utf-8 in file name: {}", e)))?;

                dirs.push(DirEntry {
                    inode: child_inode,
                    name: name.to_string(),
                    file_type: FileType::from_dir_hint(file_type)
                        .expect("valid file type"),
                });
            }

            read += rec_len as usize;
            if read >= total_len {
                assert_eq!(read, total_len);
                break;
            }
        }

        Ok(dirs)
    }

    fn only_relevant_flag_is_extents(&self) -> bool {
        self.flags & (
            INODE_COMPR
            | INODE_DIRTY
            | INODE_COMPRBLK
            | INODE_ENCRYPT
            | INODE_IMAGIC
            | INODE_NOTAIL
            | INODE_TOPDIR
            | INODE_HUGE_FILE
            | INODE_EXTENTS
            | INODE_EA_INODE
            | INODE_EOFBLOCKS
            | INODE_INLINE_DATA
        ) == INODE_EXTENTS
    }
}

fn load_maj_min(block: [u8; 4 * 15]) -> (u16, u32) {
    if 0 != block[0] || 0 != block[1] {
        (block[1] as u16, block[0] as u32)
    } else {
        // if you think reading this is bad, I had to write it
        (block[5] as u16
             | (((block[6] & 0b0000_1111) as u16) << 8),
         block[4] as u32
             | ((block[7] as u32) << 12)
             | (((block[6] & 0b1111_0000) as u32) >> 4) << 8)
    }
}

fn as_u16(buf: &[u8]) -> u16 {
    buf[0] as u16 + buf[1] as u16 * 0x100
}

fn as_u32(buf: &[u8]) -> u32 {
    as_u16(buf) as u32 + as_u16(&buf[2..]) as u32 * 0x10000
}

fn parse_error(msg: String) -> io::Error {
    io::Error::new(io::ErrorKind::InvalidInput, msg)
}

#[allow(unknown_lints, absurd_extreme_comparisons)]
fn usize_check(val: u64) -> io::Result<usize> {
    // this check only makes sense on non-64-bit platforms; on 64-bit usize == u64.
    if val > std::usize::MAX as u64 {
        Err(io::Error::new(io::ErrorKind::InvalidData,
                                  format!("value is too big for memory on this platform: {}",
                                          val)))
    } else {
        Ok(val as usize)
    }
}
<|endoftext|>