<commit_before>use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::{def, BindingAnnotation, Block, Expr, ExprKind, MatchSource, PatKind, StmtKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};

use crate::utils::paths::{OPTION, OPTION_NONE};
use crate::utils::sugg::Sugg;
use crate::utils::{
    higher, match_def_path, match_qpath, match_type, snippet_with_applicability, span_lint_and_then, SpanlessEq,
};

declare_clippy_lint! {
    /// **What it does:** Checks for expressions that could be replaced by the question mark operator.
    ///
    /// **Why is this bad?** Question mark usage is more idiomatic.
    ///
    /// **Known problems:** None
    ///
    /// **Example:**
    /// ```ignore
    /// if option.is_none() {
    ///     return None;
    /// }
    /// ```
    ///
    /// Could be written:
    ///
    /// ```ignore
    /// option?;
    /// ```
    pub QUESTION_MARK,
    style,
    "checks for expressions that could be replaced by the question mark operator"
}

declare_lint_pass!(QuestionMark => [QUESTION_MARK]);

impl QuestionMark {
    /// Checks if the given expression on the given context matches the following structure:
    ///
    /// ```ignore
    /// if option.is_none() {
    ///    return None;
    /// }
    /// ```
    ///
    /// If it matches, it will suggest to use the question mark operator instead
    fn check_is_none_and_early_return_none(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
        if_chain! {
            if let Some((if_expr, body, else_)) = higher::if_block(&expr);
            if let ExprKind::MethodCall(segment, _, args) = &if_expr.kind;
            if segment.ident.name == sym!(is_none);
            if Self::expression_returns_none(cx, body);
            if let Some(subject) = args.get(0);
            if Self::is_option(cx, subject);

            then {
                let mut applicability = Applicability::MachineApplicable;
                let receiver_str = snippet_with_applicability(cx, subject.span, "..", &mut applicability);
                let mut replacement: Option<String> = None;
                if let Some(else_) = else_ {
                    if_chain! {
                        if let ExprKind::Block(block, None) = &else_.kind;
                        if block.stmts.is_empty();
                        if let Some(block_expr) = &block.expr;
                        if SpanlessEq::new(cx).ignore_fn().eq_expr(subject, block_expr);
                        then {
                            replacement = Some(format!("Some({}?)", receiver_str));
                        }
                    }
                } else if Self::moves_by_default(cx, subject) {
                        replacement = Some(format!("{}.as_ref()?;", receiver_str));
                } else {
                        replacement = Some(format!("{}?;", receiver_str));
                }

                if let Some(replacement_str) = replacement {
                    span_lint_and_then(
                        cx,
                        QUESTION_MARK,
                        expr.span,
                        "this block may be rewritten with the `?` operator",
                        |db| {
                            db.span_suggestion(
                                expr.span,
                                "replace it with",
                                replacement_str,
                                applicability,
                            );
                        }
                    )
               }
            }
        }
    }

    fn check_if_let_some_and_early_return_none(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
        if_chain! {
            if let ExprKind::Match(subject, arms, source) = &expr.kind;
            if *source == MatchSource::IfLetDesugar { contains_else_clause: true };
            if Self::is_option(cx, subject);

            if let PatKind::TupleStruct(path1, fields, None) = &arms[0].pat.kind;
            if match_qpath(path1, &["Some"]);
            if let PatKind::Binding(annot, _, bind, _) = &fields[0].kind;
            let by_ref = matches!(annot, BindingAnnotation::Ref | BindingAnnotation::RefMut);

            if let ExprKind::Block(block, None) = &arms[0].body.kind;
            if block.stmts.is_empty();
            if let Some(trailing_expr) = &block.expr;
            if let ExprKind::Path(path) = &trailing_expr.kind;
            if match_qpath(path, &[&bind.as_str()]);

            if let PatKind::Wild = arms[1].pat.kind;
            if Self::expression_returns_none(cx, arms[1].body);
            then {
                let mut applicability = Applicability::MachineApplicable;
                let receiver_str = snippet_with_applicability(cx, subject.span, "..", &mut applicability);
                let replacement = format!(
                    "{}{}?",
                    receiver_str,
                    if by_ref { ".as_ref()" } else { "" },
                );

                span_lint_and_then(
                    cx,
                    QUESTION_MARK,
                    expr.span,
                    "this if-let-else may be rewritten with the `?` operator",
                    |db| {
                        db.span_suggestion(
                            expr.span,
                            "replace it with",
                            replacement,
                            applicability,
                        );
                    }
                )
            }
        }
    }

    fn moves_by_default(cx: &LateContext<'_, '_>, expression: &Expr<'_>) -> bool {
        let expr_ty = cx.tables.expr_ty(expression);

        !expr_ty.is_copy_modulo_regions(cx.tcx, cx.param_env, expression.span)
    }

    fn is_option(cx: &LateContext<'_, '_>, expression: &Expr<'_>) -> bool {
        let expr_ty = cx.tables.expr_ty(expression);

        match_type(cx, expr_ty, &OPTION)
    }

    fn expression_returns_none(cx: &LateContext<'_, '_>, expression: &Expr<'_>) -> bool {
        match expression.kind {
            ExprKind::Block(ref block, _) => {
                if let Some(return_expression) = Self::return_expression(block) {
                    return Self::expression_returns_none(cx, &return_expression);
                }

                false
            },
            ExprKind::Ret(Some(ref expr)) => Self::expression_returns_none(cx, expr),
            ExprKind::Path(ref qp) => {
                if let Res::Def(DefKind::Ctor(def::CtorOf::Variant, def::CtorKind::Const), def_id) =
                    cx.tables.qpath_res(qp, expression.hir_id)
                {
                    return match_def_path(cx, def_id, &OPTION_NONE);
                }

                false
            },
            _ => false,
        }
    }

    fn return_expression<'tcx>(block: &Block<'tcx>) -> Option<&'tcx Expr<'tcx>> {
        // Check if last expression is a return statement. Then, return the expression
        if_chain! {
            if block.stmts.len() == 1;
            if let Some(expr) = block.stmts.iter().last();
            if let StmtKind::Semi(ref expr) = expr.kind;
            if let ExprKind::Ret(ret_expr) = expr.kind;
            if let Some(ret_expr) = ret_expr;

            then {
                return Some(ret_expr);
            }
        }

        // Check for `return` without a semicolon.
        if_chain! {
            if block.stmts.is_empty();
            if let Some(ExprKind::Ret(Some(ret_expr))) = block.expr.as_ref().map(|e| &e.kind);
            then {
                return Some(ret_expr);
            }
        }

        None
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for QuestionMark {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
        Self::check_is_none_and_early_return_none(cx, expr);
        Self::check_if_let_some_and_early_return_none(cx, expr);
    }
}
<commit_msg>Apply suggestions from code review<commit_after>use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::{def, BindingAnnotation, Block, Expr, ExprKind, MatchSource, PatKind, StmtKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};

use crate::utils::paths::{OPTION, OPTION_NONE};
use crate::utils::sugg::Sugg;
use crate::utils::{
    higher, match_def_path, match_qpath, match_type, snippet_with_applicability, span_lint_and_sugg, SpanlessEq,
};

declare_clippy_lint! {
    /// **What it does:** Checks for expressions that could be replaced by the question mark operator.
    ///
    /// **Why is this bad?** Question mark usage is more idiomatic.
    ///
    /// **Known problems:** None
    ///
    /// **Example:**
    /// ```ignore
    /// if option.is_none() {
    ///     return None;
    /// }
    /// ```
    ///
    /// Could be written:
    ///
    /// ```ignore
    /// option?;
    /// ```
    pub QUESTION_MARK,
    style,
    "checks for expressions that could be replaced by the question mark operator"
}

declare_lint_pass!(QuestionMark => [QUESTION_MARK]);

impl QuestionMark {
    /// Checks if the given expression on the given context matches the following structure:
    ///
    /// ```ignore
    /// if option.is_none() {
    ///    return None;
    /// }
    /// ```
    ///
    /// If it matches, it will suggest to use the question mark operator instead
    fn check_is_none_and_early_return_none(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
        if_chain! {
            if let Some((if_expr, body, else_)) = higher::if_block(&expr);
            if let ExprKind::MethodCall(segment, _, args) = &if_expr.kind;
            if segment.ident.name == sym!(is_none);
            if Self::expression_returns_none(cx, body);
            if let Some(subject) = args.get(0);
            if Self::is_option(cx, subject);

            then {
                let mut applicability = Applicability::MachineApplicable;
                let receiver_str = &Sugg::hir_with_applicability(cx, subject, "..", &mut applicability);
                let mut replacement: Option<String> = None;
                if let Some(else_) = else_ {
                    if_chain! {
                        if let ExprKind::Block(block, None) = &else_.kind;
                        if block.stmts.is_empty();
                        if let Some(block_expr) = &block.expr;
                        if SpanlessEq::new(cx).ignore_fn().eq_expr(subject, block_expr);
                        then {
                            replacement = Some(format!("Some({}?)", receiver_str));
                        }
                    }
                } else if Self::moves_by_default(cx, subject) {
                        replacement = Some(format!("{}.as_ref()?;", receiver_str));
                } else {
                        replacement = Some(format!("{}?;", receiver_str));
                }

                if let Some(replacement_str) = replacement {
                    span_lint_and_sugg(
                        cx,
                        QUESTION_MARK,
                        expr.span,
                        "this block may be rewritten with the `?` operator",
                        "replace it with",
                        replacement_str,
                        applicability,
                    )
               }
            }
        }
    }

    fn check_if_let_some_and_early_return_none(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
        if_chain! {
            if let ExprKind::Match(subject, arms, source) = &expr.kind;
            if *source == MatchSource::IfLetDesugar { contains_else_clause: true };
            if Self::is_option(cx, subject);

            if let PatKind::TupleStruct(path1, fields, None) = &arms[0].pat.kind;
            if match_qpath(path1, &["Some"]);
            if let PatKind::Binding(annot, _, bind, _) = &fields[0].kind;
            let by_ref = matches!(annot, BindingAnnotation::Ref | BindingAnnotation::RefMut);

            if let ExprKind::Block(block, None) = &arms[0].body.kind;
            if block.stmts.is_empty();
            if let Some(trailing_expr) = &block.expr;
            if let ExprKind::Path(path) = &trailing_expr.kind;
            if match_qpath(path, &[&bind.as_str()]);

            if let PatKind::Wild = arms[1].pat.kind;
            if Self::expression_returns_none(cx, arms[1].body);
            then {
                let mut applicability = Applicability::MachineApplicable;
                let receiver_str = snippet_with_applicability(cx, subject.span, "..", &mut applicability);
                let replacement = format!(
                    "{}{}?",
                    receiver_str,
                    if by_ref { ".as_ref()" } else { "" },
                );

                span_lint_and_sugg(
                    cx,
                    QUESTION_MARK,
                    expr.span,
                    "this if-let-else may be rewritten with the `?` operator",
                    "replace it with",
                    replacement,
                    applicability,
                )
            }
        }
    }

    fn moves_by_default(cx: &LateContext<'_, '_>, expression: &Expr<'_>) -> bool {
        let expr_ty = cx.tables.expr_ty(expression);

        !expr_ty.is_copy_modulo_regions(cx.tcx, cx.param_env, expression.span)
    }

    fn is_option(cx: &LateContext<'_, '_>, expression: &Expr<'_>) -> bool {
        let expr_ty = cx.tables.expr_ty(expression);

        match_type(cx, expr_ty, &OPTION)
    }

    fn expression_returns_none(cx: &LateContext<'_, '_>, expression: &Expr<'_>) -> bool {
        match expression.kind {
            ExprKind::Block(ref block, _) => {
                if let Some(return_expression) = Self::return_expression(block) {
                    return Self::expression_returns_none(cx, &return_expression);
                }

                false
            },
            ExprKind::Ret(Some(ref expr)) => Self::expression_returns_none(cx, expr),
            ExprKind::Path(ref qp) => {
                if let Res::Def(DefKind::Ctor(def::CtorOf::Variant, def::CtorKind::Const), def_id) =
                    cx.tables.qpath_res(qp, expression.hir_id)
                {
                    return match_def_path(cx, def_id, &OPTION_NONE);
                }

                false
            },
            _ => false,
        }
    }

    fn return_expression<'tcx>(block: &Block<'tcx>) -> Option<&'tcx Expr<'tcx>> {
        // Check if last expression is a return statement. Then, return the expression
        if_chain! {
            if block.stmts.len() == 1;
            if let Some(expr) = block.stmts.iter().last();
            if let StmtKind::Semi(ref expr) = expr.kind;
            if let ExprKind::Ret(ret_expr) = expr.kind;
            if let Some(ret_expr) = ret_expr;

            then {
                return Some(ret_expr);
            }
        }

        // Check for `return` without a semicolon.
        if_chain! {
            if block.stmts.is_empty();
            if let Some(ExprKind::Ret(Some(ret_expr))) = block.expr.as_ref().map(|e| &e.kind);
            then {
                return Some(ret_expr);
            }
        }

        None
    }
}

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for QuestionMark {
    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
        Self::check_is_none_and_early_return_none(cx, expr);
        Self::check_if_let_some_and_early_return_none(cx, expr);
    }
}
<|endoftext|>


<commit_before>use {types as ot, errors as oe, utils};

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

use byteorder::{BigEndian, ReadBytesExt};

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

pub fn decode(msg: &[u8]) -> ot::OscResult<ot::OscPacket> {
    match msg[0] as char {
        '/' => {
            decode_message(msg)
        }
        '#' => {
            decode_bundle(msg)
        }
        _ => Err(oe::OscError::BadPacket("Unknown message format.".to_string())),
    }
}

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

    match read_osc_string(&mut cursor) {
        Ok(s) => {
            let addr: String = s;
            match read_osc_string(&mut cursor) {
                Ok(type_tags) => {
                    if type_tags.len() > 1 {
                        match read_osc_args(&mut cursor, type_tags) {
                            Ok(args) => {
                                Ok(ot::OscPacket::Message(ot::OscMessage {
                                    addr: addr,
                                    args: Some(args),
                                }))
                            }
                            Err(e) => Err(e),
                        }
                    } else {
                        Ok(ot::OscPacket::Message(ot::OscMessage {
                            addr: addr,
                            args: None,
                        }))
                    }
                }
                Err(e) => Err(e),
            }
        }
        Err(e) => Err(e),
    }
}

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

    match read_osc_string(&mut cursor).map(|s| s == "bundle") {
        Ok(b) => {
            if b {
                match read_time_tag(&mut cursor) {
                    Ok(tt) => {
                        let mut bundle: Vec<ot::OscPacket> = Vec::new();
                        match cursor.read_u32::<BigEndian>()
                                    .map_err(|e| oe::OscError::ByteOrderError(e)) {
                            Ok(size) => {
                                let mut buf: Vec<u8> = Vec::new();
                                match cursor.take(size as u64).read_to_end(&mut buf) {
                                    Ok(cnt) => {
                                        if cnt == (size as usize) {
                                            match decode(&mut buf) {
                                                Ok(p) => bundle.push(p),
                                                Err(e) => return Err(e),
                                            }
                                        } else {
                                            return Err(oe::OscError::BadBundle);
                                        }
                                    }
                                    Err(e) => return Err(oe::OscError::ReadError(e)),
                                }
                            }
                            Err(e) => return Err(e),
                        }
                        Ok(ot::OscPacket::Bundle(ot::OscBundle {
                            timetag: tt,
                            content: bundle,
                        }))
                    }
                    Err(e) => Err(e),
                }
            } else {
                Err(oe::OscError::BadBundle)
            }
        }
        Err(e) => Err(e),
    }
}

fn read_osc_string(cursor: &mut io::Cursor<&[u8]>) -> ot::OscResult<String> {
    let mut str_buf: Vec<u8> = Vec::new();
    match cursor.read_until(0, &mut str_buf) {
        Ok(_) => {
            pad_cursor(cursor);
            String::from_utf8(str_buf)
                .map_err(|e| oe::OscError::StringError(e))
                .map(|s| s.trim_matches(0u8 as char).to_string())
        }
        Err(e) => Err(oe::OscError::ReadError(e)),
    }
}

fn read_osc_args(cursor: &mut io::Cursor<&[u8]>,
                 raw_type_tags: String)
                 -> ot::OscResult<Vec<ot::OscType>> {
    let type_tags: Vec<char> = raw_type_tags.chars()
                                            .skip(1)
                                            .map(|c| c as char)
                                            .collect();
    let mut args: Vec<ot::OscType> = Vec::with_capacity(type_tags.len());
    for tag in type_tags {
        match read_osc_arg(cursor, tag) {
            Ok(arg) => {
                args.push(arg);
            }
            Err(e) => return Err(e),
        }
    }
    Ok(args)
}

fn read_osc_arg(cursor: &mut io::Cursor<&[u8]>, tag: char) -> ot::OscResult<ot::OscType> {
    match tag {
        'f' => {
            cursor.read_f32::<BigEndian>()
                  .map(|f| ot::OscType::Float(f))
                  .map_err(|e| oe::OscError::ByteOrderError(e))
        }
        'd' => {
            cursor.read_f64::<BigEndian>()
                  .map(|d| ot::OscType::Double(d))
                  .map_err(|e| oe::OscError::ByteOrderError(e))
        }
        'i' => {
            cursor.read_i32::<BigEndian>()
                  .map(|i| ot::OscType::Int(i))
                  .map_err(|e| oe::OscError::ByteOrderError(e))
        }
        'h' => {
            cursor.read_i64::<BigEndian>()
                  .map(|l| ot::OscType::Long(l))
                  .map_err(|e| oe::OscError::ByteOrderError(e))
        }
        's' => {
            read_osc_string(cursor).map(|s| ot::OscType::String(s))
        }
        't' => {
            // http://opensoundcontrol.org/node/3/#timetags
            read_time_tag(cursor)
        }
        'b' => {
            match cursor.read_u32::<BigEndian>() {
                Ok(size) => {
                    let mut buf: Vec<u8> = Vec::with_capacity(size as usize);
                    match cursor.take(size as u64).read(&mut buf) {
                        Ok(blob_size) => Ok(ot::OscType::Blob(buf)),
                        Err(e) => Err(oe::OscError::ReadError(e)),
                    }
                }
                // TODO: use correct error type
                Err(e) => return Err(oe::OscError::BadBundle),
            }
        }
        _ => Err(oe::OscError::BadArg(format!("Type tag \"{}\" is not implemented!", tag))),
    }
}

fn read_time_tag(cursor: &mut io::Cursor<&[u8]>) -> ot::OscResult<ot::OscType> {
    match cursor.read_u32::<BigEndian>() {
        Ok(date) => {
            match cursor.read_u32::<BigEndian>() {
                Ok(frac) => Ok(ot::OscType::Time(date, frac)),
                Err(e) => Err(oe::OscError::ByteOrderError(e)),
            }
        }
        Err(e) => Err(oe::OscError::ByteOrderError(e)),
    }
}

fn pad_cursor(cursor: &mut io::Cursor<&[u8]>) {
    let pos = cursor.position();
    cursor.set_position(utils::pad(pos));
}
<commit_msg>Refactor Osc bundle decoding<commit_after>use {types as ot, errors as oe, utils};

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

use byteorder::{BigEndian, ReadBytesExt};

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

pub fn decode(msg: &[u8]) -> ot::OscResult<ot::OscPacket> {
    match msg[0] as char {
        '/' => {
            decode_message(msg)
        }
        '#' => {
            decode_bundle(msg)
        }
        _ => Err(oe::OscError::BadPacket("Unknown message format.".to_string())),
    }
}

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

    match read_osc_string(&mut cursor) {
        Ok(s) => {
            let addr: String = s;
            match read_osc_string(&mut cursor) {
                Ok(type_tags) => {
                    if type_tags.len() > 1 {
                        match read_osc_args(&mut cursor, type_tags) {
                            Ok(args) => {
                                Ok(ot::OscPacket::Message(ot::OscMessage {
                                    addr: addr,
                                    args: Some(args),
                                }))
                            }
                            Err(e) => Err(e),
                        }
                    } else {
                        Ok(ot::OscPacket::Message(ot::OscMessage {
                            addr: addr,
                            args: None,
                        }))
                    }
                }
                Err(e) => Err(e),
            }
        }
        Err(e) => Err(e),
    }
}

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

    let b = try!(read_osc_string(&mut cursor));
    if b != "bundle" {
        return Err(oe::OscError::BadBundle);
    }

    let time_tag = try!(read_time_tag(&mut cursor));
    let mut bundle: Vec<ot::OscPacket> = Vec::new();
    let size: usize = try!(cursor.read_u32::<BigEndian>()
                   .map_err(oe::OscError::ByteOrderError)) as usize;
    let mut buf: Vec<u8> = Vec::new();
    let cnt: usize = try!(cursor.take(size as u64)
                                .read_to_end(&mut buf)
                                .map_err(oe::OscError::ReadError));
    if cnt == size {
        try!(decode(&mut buf).map(|p| bundle.push(p)));
    } else {
        return Err(oe::OscError::BadBundle);
    }

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

fn read_osc_string(cursor: &mut io::Cursor<&[u8]>) -> ot::OscResult<String> {
    let mut str_buf: Vec<u8> = Vec::new();
    match cursor.read_until(0, &mut str_buf) {
        Ok(_) => {
            pad_cursor(cursor);
            String::from_utf8(str_buf)
                .map_err(|e| oe::OscError::StringError(e))
                .map(|s| s.trim_matches(0u8 as char).to_string())
        }
        Err(e) => Err(oe::OscError::ReadError(e)),
    }
}

fn read_osc_args(cursor: &mut io::Cursor<&[u8]>,
                 raw_type_tags: String)
                 -> ot::OscResult<Vec<ot::OscType>> {
    let type_tags: Vec<char> = raw_type_tags.chars()
                                            .skip(1)
                                            .map(|c| c as char)
                                            .collect();
    let mut args: Vec<ot::OscType> = Vec::with_capacity(type_tags.len());
    for tag in type_tags {
        match read_osc_arg(cursor, tag) {
            Ok(arg) => {
                args.push(arg);
            }
            Err(e) => return Err(e),
        }
    }
    Ok(args)
}

fn read_osc_arg(cursor: &mut io::Cursor<&[u8]>, tag: char) -> ot::OscResult<ot::OscType> {
    match tag {
        'f' => {
            cursor.read_f32::<BigEndian>()
                  .map(|f| ot::OscType::Float(f))
                  .map_err(|e| oe::OscError::ByteOrderError(e))
        }
        'd' => {
            cursor.read_f64::<BigEndian>()
                  .map(|d| ot::OscType::Double(d))
                  .map_err(|e| oe::OscError::ByteOrderError(e))
        }
        'i' => {
            cursor.read_i32::<BigEndian>()
                  .map(|i| ot::OscType::Int(i))
                  .map_err(|e| oe::OscError::ByteOrderError(e))
        }
        'h' => {
            cursor.read_i64::<BigEndian>()
                  .map(|l| ot::OscType::Long(l))
                  .map_err(|e| oe::OscError::ByteOrderError(e))
        }
        's' => {
            read_osc_string(cursor).map(|s| ot::OscType::String(s))
        }
        't' => {
            // http://opensoundcontrol.org/node/3/#timetags
            read_time_tag(cursor)
        }
        'b' => {
            match cursor.read_u32::<BigEndian>() {
                Ok(size) => {
                    let mut buf: Vec<u8> = Vec::with_capacity(size as usize);
                    match cursor.take(size as u64).read(&mut buf) {
                        Ok(blob_size) => Ok(ot::OscType::Blob(buf)),
                        Err(e) => Err(oe::OscError::ReadError(e)),
                    }
                }
                // TODO: use correct error type
                Err(e) => return Err(oe::OscError::BadBundle),
            }
        }
        _ => Err(oe::OscError::BadArg(format!("Type tag \"{}\" is not implemented!", tag))),
    }
}

fn read_time_tag(cursor: &mut io::Cursor<&[u8]>) -> ot::OscResult<ot::OscType> {
    match cursor.read_u32::<BigEndian>() {
        Ok(date) => {
            match cursor.read_u32::<BigEndian>() {
                Ok(frac) => Ok(ot::OscType::Time(date, frac)),
                Err(e) => Err(oe::OscError::ByteOrderError(e)),
            }
        }
        Err(e) => Err(oe::OscError::ByteOrderError(e)),
    }
}

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


<commit_before>use std::borrow::IntoCow;
use std::collections::hash_map::HashMap;
use std::old_io::{IoResult, MemReader};
use std::old_io::Reader as IoReader;
use std::mem::transmute;

use byteorder::{ReaderBytesExt, BigEndian};
use rustc_serialize::Decodable;

use rustc_decoder::CborDecoder;
use {
    Cbor, CborUnsigned, CborSigned, CborFloat, CborBytes, CborTag, Type,
    CborResult, CborError, ReadError,
};

/// Read CBOR data items into Rust values from the underlying reader `R`.
pub struct Decoder<R> {
    rdr: CborReader<R>,
}

impl<R: IoReader> Decoder<R> {
    /// Create a new CBOR decoder from the underlying reader.
    pub fn from_reader(rdr: R) -> Decoder<R> {
        Decoder { rdr: CborReader::new(rdr) }
    }

    /// Decode a sequence of top-level CBOR data items into Rust values.
    ///
    /// # Example
    ///
    /// This shows how to encode and decode a sequence of data items:
    ///
    /// ```rust
    /// use cbor::{Decoder, Encoder};
    ///
    /// let data = vec![("a".to_string(), 1), ("b".to_string(), 2),
    ///                 ("c".to_string(), 3)];
    ///
    /// let mut enc = Encoder::from_memory();
    /// enc.encode(&data).unwrap();
    ///
    /// let mut dec = Decoder::from_bytes(enc.as_bytes());
    /// let items: Vec<(String, i32)> = dec.decode()
    ///                                    .collect::<Result<_, _>>()
    ///                                    .unwrap();
    ///
    /// assert_eq!(items, data);
    /// ```
    pub fn decode<D: Decodable>(&mut self) -> DecodedItems<R, D> {
        DecodedItems {
            it: self.items(),
            _phantom: ::std::marker::PhantomData,
        }
    }

    /// Read a sequence of top-level CBOR data items.
    ///
    /// This yields data items represented by the `Cbor` type, which is its
    /// abstract syntax. (Using the `decode` iterator is probably much more
    /// convenient, but this is useful when you need to do more sophisticated
    /// analysis on the CBOR data.)
    ///
    /// # Example
    ///
    /// This shows how to encode and decode a sequence of data items:
    ///
    /// ```rust
    /// use cbor::{Cbor, CborUnsigned, Decoder, Encoder};
    ///
    /// let mut enc = Encoder::from_memory();
    /// enc.encode(vec![("a", 1), ("b", 2), ("c", 3)]).unwrap();
    ///
    /// let mut dec = Decoder::from_bytes(enc.as_bytes());
    /// let items = dec.items().collect::<Result<Vec<_>, _>>().unwrap();
    ///
    /// assert_eq!(items, vec![
    ///     Cbor::Array(vec![
    ///         Cbor::Unicode("a".to_string()),
    ///         Cbor::Unsigned(CborUnsigned::UInt8(1)),
    ///     ]),
    ///     Cbor::Array(vec![
    ///         Cbor::Unicode("b".to_string()),
    ///         Cbor::Unsigned(CborUnsigned::UInt8(2)),
    ///     ]),
    ///     Cbor::Array(vec![
    ///         Cbor::Unicode("c".to_string()),
    ///         Cbor::Unsigned(CborUnsigned::UInt8(3)),
    ///     ]),
    /// ]);
    /// ```
    pub fn items(&mut self) -> Items<R> {
        Items { dec: self }
    }

    fn read_data_item(&mut self, first: Option<u8>) -> CborResult<Cbor> {
        let first = match first {
            Some(first) => first,
            None => try!(self.rdr.read_byte()),
        };
        match (first & 0b111_00000) >> 5 {
            0 => self.read_uint(first).map(Cbor::Unsigned),
            1 => self.read_int(first).map(Cbor::Signed),
            2 => self.read_bytes(first),
            3 => self.read_string(first),
            4 => self.read_array(first),
            5 => self.read_map(first),
            6 => self.read_tag(first),
            7 => match first & 0b000_11111 {
                v @ 0...23 => self.read_simple_value(v),
                24 => {
                    let b = try!(self.rdr.read_byte());
                    self.read_simple_value(b)
                }
                25...27 => self.read_float(first).map(Cbor::Float),
                v @ 28...30 =>
                    Err(self.errat(
                        ReadError::Unassigned { major: 7, add: v })),
                31 => Ok(Cbor::Break),
                // Because max(byte & 0b000_11111) == 2^5 - 1 == 31
                _ => unreachable!(),
            },
            // This is truly unreachable because `byte & 0b111_00000 >> 5`
            // can only produce 8 distinct values---each of which are handled
            // above. ---AG
            _ => unreachable!(),
        }
    }

    fn read_simple_value(&mut self, val: u8) -> CborResult<Cbor> {
        Ok(match val {
            v @ 0...19 =>
                return Err(self.errat(
                    ReadError::Unassigned { major: 7, add: v })),
            20 => Cbor::Bool(false),
            21 => Cbor::Bool(true),
            22 => Cbor::Null,
            23 => Cbor::Undefined,
            v @ 24...31 =>
                return Err(self.errat(
                    ReadError::Reserved { major: 7, add: v })),
            v /* 32...255 */ =>
                return Err(self.errat(
                    ReadError::Unassigned { major: 7, add: v })),
        })
    }

    fn read_float(&mut self, first: u8) -> CborResult<CborFloat> {
        Ok(match first & 0b000_11111 {
            25 => {
                // Rust doesn't have a `f16` type, so just read a u16 and
                // cast it to a u32 and then a f32.
                // I think this is wrong. ---AG
                let n = try!(self.rdr.read_u16::<BigEndian>());
                CborFloat::Float16(unsafe { transmute(n as u32) })
            }
            26 => CborFloat::Float32(try!(self.rdr.read_f32::<BigEndian>())),
            27 => CborFloat::Float64(try!(self.rdr.read_f64::<BigEndian>())),
            // Reaching this case is probably a bug. ---AG
            v => return Err(self.errat(
                ReadError::InvalidAddValue { ty: Type::Float, val: v })),
        })
    }

    fn read_tag(&mut self, first: u8) -> CborResult<Cbor> {
        let tag = try!(self.read_uint(first));
        let tag = try!(tag.to_u64().map_err(|err| self.errat(err)));
        let data = try!(self.read_data_item(None));
        Ok(Cbor::Tag(CborTag { tag: tag, data: Box::new(data) }))
    }

    fn read_map(&mut self, first: u8) -> CborResult<Cbor> {
        let len = try!(self.read_len(first));
        let mut map = HashMap::with_capacity(len);
        let at = self.rdr.bytes_read; // for coherent error reporting
        for _ in 0..len {
            let key = match try!(self.read_data_item(None)) {
                Cbor::Unicode(s) => s,
                v => return Err(CborError::AtOffset {
                    kind: ReadError::mismatch(Type::Unicode, &v),
                    offset: at,
                }),
            };
            let val = try!(self.read_data_item(None));
            map.insert(key, val);
        }
        Ok(Cbor::Map(map))
    }

    fn read_array(&mut self, first: u8) -> CborResult<Cbor> {
        let len = try!(self.read_len(first));
        let mut array = Vec::with_capacity(len);
        for _ in 0..len {
            let v = try!(self.read_data_item(None));
            array.push(v);
        }
        Ok(Cbor::Array(array))
    }

    fn read_string(&mut self, first: u8) -> CborResult<Cbor> {
        let len = try!(self.read_len(first));
        let mut buf = vec_from_elem(len, 0u8);
        try!(self.rdr.read_full(&mut buf));
        String::from_utf8(buf)
               .map(Cbor::Unicode)
               .map_err(|err| self.errstr(err.utf8_error().to_string()))
    }

    fn read_bytes(&mut self, first: u8) -> CborResult<Cbor> {
        let len = try!(self.read_len(first));
        let mut buf = vec_from_elem(len, 0u8);
        try!(self.rdr.read_full(&mut buf));
        Ok(Cbor::Bytes(CborBytes(buf)))
    }

    fn read_len(&mut self, first: u8) -> CborResult<usize> {
        self.read_uint(first)
            .and_then(|v| v.to_usize().map_err(|err| self.errat(err)))
    }

    fn read_uint(&mut self, first: u8) -> CborResult<CborUnsigned> {
        Ok(match first & 0b000_11111 {
            n @ 0...23 => CborUnsigned::UInt8(n),
            24 => CborUnsigned::UInt8(try!(self.rdr.read_byte())),
            25 => CborUnsigned::UInt16(try!(self.rdr.read_u16::<BigEndian>())),
            26 => CborUnsigned::UInt32(try!(self.rdr.read_u32::<BigEndian>())),
            27 => CborUnsigned::UInt64(try!(self.rdr.read_u64::<BigEndian>())),
            v => return Err(self.errat(
                ReadError::InvalidAddValue { ty: Type::UInt, val: v })),
        })
    }

    fn read_int(&mut self, first: u8) -> CborResult<CborSigned> {
        Ok(match first & 0b000_11111 {
            n @ 0...23 => CborSigned::Int8(-1 - (n as i8)),
            24 => {
                let n = try!(self.rdr.read_byte());
                if n > ::std::i8::MAX as u8 {
                    CborSigned::Int16(-1 - (n as i16))
                } else {
                    CborSigned::Int8(-1 - (n as i8))
                }
            }
            25 => {
                let n = try!(self.rdr.read_u16::<BigEndian>());
                if n > ::std::i16::MAX as u16 {
                    CborSigned::Int32(-1 - (n as i32))
                } else {
                    CborSigned::Int16(-1 - (n as i16))
                }
            }
            26 => {
                let n = try!(self.rdr.read_u32::<BigEndian>());
                if n > ::std::i32::MAX as u32 {
                    CborSigned::Int64(-1 - (n as i64))
                } else {
                    CborSigned::Int32(-1 - (n as i32))
                }
            }
            27 => {
                let n = try!(self.rdr.read_u64::<BigEndian>());
                if n > ::std::i64::MAX as u64 {
                    return Err(self.errstr(format!(
                        "Negative integer out of range: {:?}", n)));
                }
                CborSigned::Int64(-1 - (n as i64))
            }
            v => return Err(self.errat(
                ReadError::InvalidAddValue { ty: Type::Int, val: v })),
        })
    }
}

impl Decoder<MemReader> {
    /// Create a new CBOR decoder that reads from the buffer given.
    ///
    /// The buffer is usually given as either a `Vec<u8>` or a `&[u8]`.
    pub fn from_bytes<'a, T>(bytes: T) -> Decoder<MemReader>
            where T: IntoCow<'a, [u8]> {
        Decoder::from_reader(MemReader::new(bytes.into_cow().into_owned()))
    }
}

impl<R: IoReader> Decoder<R> {
    fn errat(&self, err: ReadError) -> CborError {
        CborError::AtOffset { kind: err, offset: self.rdr.last_offset }
    }

    fn errstr(&self, s: String) -> CborError {
        self.errat(ReadError::Other(s))
    }
}

/// An iterator over items decoded from CBOR into Rust values.
///
/// `D` represents the type of the Rust value being decoded into, `R`
/// represents the underlying reader and `'a` is the lifetime of the decoder.
pub struct DecodedItems<'a, R: 'a, D> {
    it: Items<'a, R>,
    _phantom: ::std::marker::PhantomData<D>,
}

impl<'a, R: IoReader, D: Decodable> Iterator for DecodedItems<'a, R, D> {
    type Item = CborResult<D>;

    fn next(&mut self) -> Option<CborResult<D>> {
        self.it.next().map(|result| {
            result.and_then(|v| Decodable::decode(&mut CborDecoder::new(v)))
        })
    }
}

/// An iterator over CBOR items in terms of the abstract syntax.
///
/// `R` represents the underlying reader and `'a` is the lifetime of the
/// decoder.
pub struct Items<'a, R: 'a> {
    dec: &'a mut Decoder<R>,
}

impl<'a, R: IoReader> Iterator for Items<'a, R> {
    type Item = CborResult<Cbor>;

    fn next(&mut self) -> Option<CborResult<Cbor>> {
        match self.dec.read_data_item(None) {
            Err(ref err) if err.is_eof() => None,
            Err(err) => Some(Err(err)),
            Ok(v) => Some(Ok(v)),
        }
    }
}

/// A very light layer over a basic reader that keeps track of offset
/// information at the byte level.
struct CborReader<R> {
    rdr: R,
    // used for error reporting
    last_offset: usize,
    bytes_read: usize,
}

impl<R: IoReader> IoReader for CborReader<R> {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
        let n = try!(self.rdr.read(buf));
        self.last_offset = self.bytes_read;
        self.bytes_read += n;
        Ok(n)
    }
}

impl<R: IoReader> CborReader<R> {
    fn new(rdr: R) -> CborReader<R> {
        CborReader { rdr: rdr, last_offset: 0, bytes_read: 0 }
    }

    fn read_full(&mut self, buf: &mut [u8]) -> IoResult<()> {
        let mut n = 0usize;
        while n < buf.len() {
            n += try!(self.read(&mut buf[n..]));
        }
        Ok(())
    }
}

fn vec_from_elem<T: Copy>(len: usize, v: T) -> Vec<T> {
    let mut xs = Vec::with_capacity(len);
    unsafe { xs.set_len(len); }
    for x in &mut xs { *x = v; }
    xs
}
<commit_msg>Major lapse --- use a buffered reader in the decoder.<commit_after>use std::borrow::IntoCow;
use std::collections::hash_map::HashMap;
use std::old_io::{BufferedReader, IoResult, MemReader};
use std::old_io::Reader as IoReader;
use std::mem::transmute;

use byteorder::{ReaderBytesExt, BigEndian};
use rustc_serialize::Decodable;

use rustc_decoder::CborDecoder;
use {
    Cbor, CborUnsigned, CborSigned, CborFloat, CborBytes, CborTag, Type,
    CborResult, CborError, ReadError,
};

/// Read CBOR data items into Rust values from the underlying reader `R`.
pub struct Decoder<R> {
    rdr: CborReader<R>,
}

impl<R: IoReader> Decoder<BufferedReader<R>> {
    /// Create a new CBOR decoder from the underlying reader.
    pub fn from_reader(rdr: R) -> Decoder<BufferedReader<R>> {
        Decoder { rdr: CborReader::new(BufferedReader::new(rdr)) }
    }
}

impl<R: IoReader> Decoder<R> {
    /// Decode a sequence of top-level CBOR data items into Rust values.
    ///
    /// # Example
    ///
    /// This shows how to encode and decode a sequence of data items:
    ///
    /// ```rust
    /// use cbor::{Decoder, Encoder};
    ///
    /// let data = vec![("a".to_string(), 1), ("b".to_string(), 2),
    ///                 ("c".to_string(), 3)];
    ///
    /// let mut enc = Encoder::from_memory();
    /// enc.encode(&data).unwrap();
    ///
    /// let mut dec = Decoder::from_bytes(enc.as_bytes());
    /// let items: Vec<(String, i32)> = dec.decode()
    ///                                    .collect::<Result<_, _>>()
    ///                                    .unwrap();
    ///
    /// assert_eq!(items, data);
    /// ```
    pub fn decode<D: Decodable>(&mut self) -> DecodedItems<R, D> {
        DecodedItems {
            it: self.items(),
            _phantom: ::std::marker::PhantomData,
        }
    }

    /// Read a sequence of top-level CBOR data items.
    ///
    /// This yields data items represented by the `Cbor` type, which is its
    /// abstract syntax. (Using the `decode` iterator is probably much more
    /// convenient, but this is useful when you need to do more sophisticated
    /// analysis on the CBOR data.)
    ///
    /// # Example
    ///
    /// This shows how to encode and decode a sequence of data items:
    ///
    /// ```rust
    /// use cbor::{Cbor, CborUnsigned, Decoder, Encoder};
    ///
    /// let mut enc = Encoder::from_memory();
    /// enc.encode(vec![("a", 1), ("b", 2), ("c", 3)]).unwrap();
    ///
    /// let mut dec = Decoder::from_bytes(enc.as_bytes());
    /// let items = dec.items().collect::<Result<Vec<_>, _>>().unwrap();
    ///
    /// assert_eq!(items, vec![
    ///     Cbor::Array(vec![
    ///         Cbor::Unicode("a".to_string()),
    ///         Cbor::Unsigned(CborUnsigned::UInt8(1)),
    ///     ]),
    ///     Cbor::Array(vec![
    ///         Cbor::Unicode("b".to_string()),
    ///         Cbor::Unsigned(CborUnsigned::UInt8(2)),
    ///     ]),
    ///     Cbor::Array(vec![
    ///         Cbor::Unicode("c".to_string()),
    ///         Cbor::Unsigned(CborUnsigned::UInt8(3)),
    ///     ]),
    /// ]);
    /// ```
    pub fn items(&mut self) -> Items<R> {
        Items { dec: self }
    }

    fn read_data_item(&mut self, first: Option<u8>) -> CborResult<Cbor> {
        let first = match first {
            Some(first) => first,
            None => try!(self.rdr.read_byte()),
        };
        match (first & 0b111_00000) >> 5 {
            0 => self.read_uint(first).map(Cbor::Unsigned),
            1 => self.read_int(first).map(Cbor::Signed),
            2 => self.read_bytes(first),
            3 => self.read_string(first),
            4 => self.read_array(first),
            5 => self.read_map(first),
            6 => self.read_tag(first),
            7 => match first & 0b000_11111 {
                v @ 0...23 => self.read_simple_value(v),
                24 => {
                    let b = try!(self.rdr.read_byte());
                    self.read_simple_value(b)
                }
                25...27 => self.read_float(first).map(Cbor::Float),
                v @ 28...30 =>
                    Err(self.errat(
                        ReadError::Unassigned { major: 7, add: v })),
                31 => Ok(Cbor::Break),
                // Because max(byte & 0b000_11111) == 2^5 - 1 == 31
                _ => unreachable!(),
            },
            // This is truly unreachable because `byte & 0b111_00000 >> 5`
            // can only produce 8 distinct values---each of which are handled
            // above. ---AG
            _ => unreachable!(),
        }
    }

    fn read_simple_value(&mut self, val: u8) -> CborResult<Cbor> {
        Ok(match val {
            v @ 0...19 =>
                return Err(self.errat(
                    ReadError::Unassigned { major: 7, add: v })),
            20 => Cbor::Bool(false),
            21 => Cbor::Bool(true),
            22 => Cbor::Null,
            23 => Cbor::Undefined,
            v @ 24...31 =>
                return Err(self.errat(
                    ReadError::Reserved { major: 7, add: v })),
            v /* 32...255 */ =>
                return Err(self.errat(
                    ReadError::Unassigned { major: 7, add: v })),
        })
    }

    fn read_float(&mut self, first: u8) -> CborResult<CborFloat> {
        Ok(match first & 0b000_11111 {
            25 => {
                // Rust doesn't have a `f16` type, so just read a u16 and
                // cast it to a u32 and then a f32.
                // I think this is wrong. ---AG
                let n = try!(self.rdr.read_u16::<BigEndian>());
                CborFloat::Float16(unsafe { transmute(n as u32) })
            }
            26 => CborFloat::Float32(try!(self.rdr.read_f32::<BigEndian>())),
            27 => CborFloat::Float64(try!(self.rdr.read_f64::<BigEndian>())),
            // Reaching this case is probably a bug. ---AG
            v => return Err(self.errat(
                ReadError::InvalidAddValue { ty: Type::Float, val: v })),
        })
    }

    fn read_tag(&mut self, first: u8) -> CborResult<Cbor> {
        let tag = try!(self.read_uint(first));
        let tag = try!(tag.to_u64().map_err(|err| self.errat(err)));
        let data = try!(self.read_data_item(None));
        Ok(Cbor::Tag(CborTag { tag: tag, data: Box::new(data) }))
    }

    fn read_map(&mut self, first: u8) -> CborResult<Cbor> {
        let len = try!(self.read_len(first));
        let mut map = HashMap::with_capacity(len);
        let at = self.rdr.bytes_read; // for coherent error reporting
        for _ in 0..len {
            let key = match try!(self.read_data_item(None)) {
                Cbor::Unicode(s) => s,
                v => return Err(CborError::AtOffset {
                    kind: ReadError::mismatch(Type::Unicode, &v),
                    offset: at,
                }),
            };
            let val = try!(self.read_data_item(None));
            map.insert(key, val);
        }
        Ok(Cbor::Map(map))
    }

    fn read_array(&mut self, first: u8) -> CborResult<Cbor> {
        let len = try!(self.read_len(first));
        let mut array = Vec::with_capacity(len);
        for _ in 0..len {
            let v = try!(self.read_data_item(None));
            array.push(v);
        }
        Ok(Cbor::Array(array))
    }

    fn read_string(&mut self, first: u8) -> CborResult<Cbor> {
        let len = try!(self.read_len(first));
        let mut buf = vec_from_elem(len, 0u8);
        try!(self.rdr.read_full(&mut buf));
        String::from_utf8(buf)
               .map(Cbor::Unicode)
               .map_err(|err| self.errstr(err.utf8_error().to_string()))
    }

    fn read_bytes(&mut self, first: u8) -> CborResult<Cbor> {
        let len = try!(self.read_len(first));
        let mut buf = vec_from_elem(len, 0u8);
        try!(self.rdr.read_full(&mut buf));
        Ok(Cbor::Bytes(CborBytes(buf)))
    }

    fn read_len(&mut self, first: u8) -> CborResult<usize> {
        self.read_uint(first)
            .and_then(|v| v.to_usize().map_err(|err| self.errat(err)))
    }

    fn read_uint(&mut self, first: u8) -> CborResult<CborUnsigned> {
        Ok(match first & 0b000_11111 {
            n @ 0...23 => CborUnsigned::UInt8(n),
            24 => CborUnsigned::UInt8(try!(self.rdr.read_byte())),
            25 => CborUnsigned::UInt16(try!(self.rdr.read_u16::<BigEndian>())),
            26 => CborUnsigned::UInt32(try!(self.rdr.read_u32::<BigEndian>())),
            27 => CborUnsigned::UInt64(try!(self.rdr.read_u64::<BigEndian>())),
            v => return Err(self.errat(
                ReadError::InvalidAddValue { ty: Type::UInt, val: v })),
        })
    }

    fn read_int(&mut self, first: u8) -> CborResult<CborSigned> {
        Ok(match first & 0b000_11111 {
            n @ 0...23 => CborSigned::Int8(-1 - (n as i8)),
            24 => {
                let n = try!(self.rdr.read_byte());
                if n > ::std::i8::MAX as u8 {
                    CborSigned::Int16(-1 - (n as i16))
                } else {
                    CborSigned::Int8(-1 - (n as i8))
                }
            }
            25 => {
                let n = try!(self.rdr.read_u16::<BigEndian>());
                if n > ::std::i16::MAX as u16 {
                    CborSigned::Int32(-1 - (n as i32))
                } else {
                    CborSigned::Int16(-1 - (n as i16))
                }
            }
            26 => {
                let n = try!(self.rdr.read_u32::<BigEndian>());
                if n > ::std::i32::MAX as u32 {
                    CborSigned::Int64(-1 - (n as i64))
                } else {
                    CborSigned::Int32(-1 - (n as i32))
                }
            }
            27 => {
                let n = try!(self.rdr.read_u64::<BigEndian>());
                if n > ::std::i64::MAX as u64 {
                    return Err(self.errstr(format!(
                        "Negative integer out of range: {:?}", n)));
                }
                CborSigned::Int64(-1 - (n as i64))
            }
            v => return Err(self.errat(
                ReadError::InvalidAddValue { ty: Type::Int, val: v })),
        })
    }
}

impl Decoder<MemReader> {
    /// Create a new CBOR decoder that reads from the buffer given.
    ///
    /// The buffer is usually given as either a `Vec<u8>` or a `&[u8]`.
    pub fn from_bytes<'a, T>(bytes: T) -> Decoder<MemReader>
            where T: IntoCow<'a, [u8]> {
        let rdr = MemReader::new(bytes.into_cow().into_owned());
        Decoder { rdr: CborReader::new(rdr) }
    }
}

impl<R: IoReader> Decoder<R> {
    fn errat(&self, err: ReadError) -> CborError {
        CborError::AtOffset { kind: err, offset: self.rdr.last_offset }
    }

    fn errstr(&self, s: String) -> CborError {
        self.errat(ReadError::Other(s))
    }
}

/// An iterator over items decoded from CBOR into Rust values.
///
/// `D` represents the type of the Rust value being decoded into, `R`
/// represents the underlying reader and `'a` is the lifetime of the decoder.
pub struct DecodedItems<'a, R: 'a, D> {
    it: Items<'a, R>,
    _phantom: ::std::marker::PhantomData<D>,
}

impl<'a, R: IoReader, D: Decodable> Iterator for DecodedItems<'a, R, D> {
    type Item = CborResult<D>;

    fn next(&mut self) -> Option<CborResult<D>> {
        self.it.next().map(|result| {
            result.and_then(|v| Decodable::decode(&mut CborDecoder::new(v)))
        })
    }
}

/// An iterator over CBOR items in terms of the abstract syntax.
///
/// `R` represents the underlying reader and `'a` is the lifetime of the
/// decoder.
pub struct Items<'a, R: 'a> {
    dec: &'a mut Decoder<R>,
}

impl<'a, R: IoReader> Iterator for Items<'a, R> {
    type Item = CborResult<Cbor>;

    fn next(&mut self) -> Option<CborResult<Cbor>> {
        match self.dec.read_data_item(None) {
            Err(ref err) if err.is_eof() => None,
            Err(err) => Some(Err(err)),
            Ok(v) => Some(Ok(v)),
        }
    }
}

/// A very light layer over a basic reader that keeps track of offset
/// information at the byte level.
struct CborReader<R> {
    rdr: R,
    // used for error reporting
    last_offset: usize,
    bytes_read: usize,
}

impl<R: IoReader> IoReader for CborReader<R> {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
        let n = try!(self.rdr.read(buf));
        self.last_offset = self.bytes_read;
        self.bytes_read += n;
        Ok(n)
    }
}

impl<R: IoReader> CborReader<R> {
    fn new(rdr: R) -> CborReader<R> {
        CborReader {
            rdr: rdr,
            last_offset: 0,
            bytes_read: 0,
        }
    }

    fn read_full(&mut self, buf: &mut [u8]) -> IoResult<()> {
        let mut n = 0usize;
        while n < buf.len() {
            n += try!(self.read(&mut buf[n..]));
        }
        Ok(())
    }
}

fn vec_from_elem<T: Copy>(len: usize, v: T) -> Vec<T> {
    let mut xs = Vec::with_capacity(len);
    unsafe { xs.set_len(len); }
    for x in &mut xs { *x = v; }
    xs
}
<|endoftext|>


<commit_before>// Copyright 2014 Jonathan Eyolfson

use std::ptr;

use raw;

pub struct Display {
    ptr: *mut raw::wl_display
}

impl Display {
    pub fn connect_to_env_or_default() -> Display {
        unsafe {
            let ptr = raw::wl_display_connect(ptr::null());
            assert!(!ptr.is_null(), "wl_display_connect failed");
            Display { ptr: ptr }
        }
    }
    pub fn connect(name: &str) -> Display {
        unsafe {
            let ptr = raw::wl_display_connect(name.as_ptr() as *const i8);
            assert!(!ptr.is_null(), "wl_display_connect failed");
            Display { ptr: ptr }
        }
    }
    pub fn roundtrip(&mut self) -> i32 {
        unsafe {
            let r = raw::wl_display_roundtrip(self.ptr);
            assert!(r != -1, "wl_display_roundtrip failed");
            r
        }
    }
    pub fn read_events(&mut self) {
        unsafe {
            let r = raw::wl_display_read_events(self.ptr);
            assert!(r != -1, "wl_display_read_events failed");
        }
    }
    pub fn prepare_read(&mut self) {
        unsafe {
            let r = raw::wl_display_prepare_read(self.ptr);
            assert!(r != -1, "wl_display_prepare_read failed");
        }
    }
    pub fn cancel_read(&mut self) {
        unsafe {
            raw::wl_display_cancel_read(self.ptr);
        }
    }
    pub fn dispatch(&mut self) -> i32 {
        unsafe {
            let r = raw::wl_display_dispatch(self.ptr);
            assert!(r != -1);
            r
        }
    }
    pub fn flush(&mut self) -> i32 {
        unsafe {
            let r = raw::wl_display_flush(self.ptr);
            assert!(r != -1);
            r
        }
    }
    pub unsafe fn to_ptr(&mut self) -> *mut raw::wl_display { self.ptr }
}

impl Drop for Display {
    fn drop(&mut self) {
        unsafe {
            raw::wl_display_disconnect(self.ptr);
        }
    }
}
<commit_msg>Display remaining assert messages added<commit_after>// Copyright 2014 Jonathan Eyolfson

use std::ptr;

use raw;

pub struct Display {
    ptr: *mut raw::wl_display
}

impl Display {
    pub fn connect_to_env_or_default() -> Display {
        unsafe {
            let ptr = raw::wl_display_connect(ptr::null());
            assert!(!ptr.is_null(), "wl_display_connect failed");
            Display { ptr: ptr }
        }
    }
    pub fn connect(name: &str) -> Display {
        unsafe {
            let ptr = raw::wl_display_connect(name.as_ptr() as *const i8);
            assert!(!ptr.is_null(), "wl_display_connect failed");
            Display { ptr: ptr }
        }
    }
    pub fn roundtrip(&mut self) -> i32 {
        unsafe {
            let r = raw::wl_display_roundtrip(self.ptr);
            assert!(r != -1, "wl_display_roundtrip failed");
            r
        }
    }
    pub fn read_events(&mut self) {
        unsafe {
            let r = raw::wl_display_read_events(self.ptr);
            assert!(r != -1, "wl_display_read_events failed");
        }
    }
    pub fn prepare_read(&mut self) {
        unsafe {
            let r = raw::wl_display_prepare_read(self.ptr);
            assert!(r != -1, "wl_display_prepare_read failed");
        }
    }
    pub fn cancel_read(&mut self) {
        unsafe {
            raw::wl_display_cancel_read(self.ptr);
        }
    }
    pub fn dispatch(&mut self) -> i32 {
        unsafe {
            let r = raw::wl_display_dispatch(self.ptr);
            assert!(r != -1, "wl_display_dispatch failed");
            r
        }
    }
    pub fn flush(&mut self) -> i32 {
        unsafe {
            let r = raw::wl_display_flush(self.ptr);
            assert!(r != -1, "wl_display_flush failed");
            r
        }
    }
    pub unsafe fn to_ptr(&mut self) -> *mut raw::wl_display { self.ptr }
}

impl Drop for Display {
    fn drop(&mut self) {
        unsafe {
            raw::wl_display_disconnect(self.ptr);
        }
    }
}
<|endoftext|>


<commit_before>use std::char;
use num::Complex;
use rustty::{Terminal, Cell};

// indexing is from the top of the cell
fn pixel_nums_to_braille(p1: Option<u8>, p2: Option<u8>) -> char {
    let pixel_map = [[0x01, 0x08],
                     [0x02, 0x10],
                     [0x04, 0x20],
                     [0x40, 0x80]];

    let mut c = 0;
    if let Some(p) = p1 {
        c |= pixel_map[p as usize][0];
    }

    if let Some(p) = p2 {
        c |= pixel_map[p as usize][1];
    }

    char::from_u32((0x2800 + c) as u32).unwrap()
}

fn fft_shift<T: Clone>(spec: &mut [T]) {
    let spec_copy = spec.to_owned();

    let (first_half, last_half) = spec_copy.split_at((spec_copy.len() + 1) / 2);
    let shifted_spec = last_half.iter().chain(first_half.iter());
    for (x, y) in spec.iter_mut().zip(shifted_spec) {
        *x = y.clone();
    }
}

fn spectrum_to_bin_heights(spec: &[Complex<f32>], dest: &mut [f32]) {
    // subsample
    let mut last_idx = -1isize;
    for (i, x) in spec.iter().map(|x| x.norm()).enumerate() {
        if (i * dest.len() / spec.len()) as isize > last_idx {
            last_idx += 1;
            dest[last_idx as usize] = x;
        }
    }

    fft_shift(dest);
}

pub fn draw_spectrum(term: &mut Terminal, spec: Vec<Complex<f32>>) {
    term.clear().unwrap();
    let (num_cols, num_rows) = term.size();
    let pixel_height = num_rows * 4;
    let pixel_width = num_cols * 2;
    // TODO what should this value be?
    let max_height = 500.0;

    let mut bins = vec![0.0; pixel_width];
    spectrum_to_bin_heights(&spec[..], &mut bins[..]);

    for col_idx in 0..num_cols {
        // height in float between 0 and 1.
        let h1 = bins[col_idx * 2] / max_height;
        let h2 = bins[col_idx * 2 + 1] / max_height;

        // The "pixel" height of each point.
        let p1 = (h1 * pixel_height as f32).floor() as usize;
        let p2 = (h2 * pixel_height as f32).floor() as usize;
        let p1 = if p1 >= pixel_height { pixel_height - 1} else { p1 };
        let p2 = if p2 >= pixel_height { pixel_height - 1} else { p2 };

        // Reverse it, since the terminal indexing is from the top
        let p1 = pixel_height - p1 - 1;
        let p2 = pixel_height - p2 - 1;

        let c1 = p1 / 4;
        let c2 = p2 / 4;

        if c1 == c2 {
            term[(col_idx, c1)] = Cell::with_char(
                pixel_nums_to_braille(Some((p1 % 4) as u8), Some((p2 % 4) as u8)));
        } else {
            term[(col_idx, c1)] = Cell::with_char(
                pixel_nums_to_braille(Some((p1 % 4) as u8), None));
            term[(col_idx, c2)] = Cell::with_char(
                pixel_nums_to_braille(None, Some((p2 % 4) as u8)));
        }
    }
}

#[cfg(test)]
mod tests {
    use super::{pixel_nums_to_braille, fft_shift};

    #[test]
    fn test_fft_shift_dc() {
        let len = 9;
        let mut spec = vec![0; len];
        spec[0] = 1;
        fft_shift(&mut spec[..]);
        assert_eq!(spec[len / 2], 1);
    }

    #[test]
    fn test_fft_shift_even() {
        let mut before: Vec<usize> = (0..10).collect();
        let after = vec![5, 6, 7, 8, 9, 0, 1, 2, 3, 4];
        fft_shift(&mut before[..]);
        assert_eq!(before, after);
    }

    #[test]
    fn test_pixel_nums() {
        assert_eq!(pixel_nums_to_braille(Some(0), Some(0)), '⠉');
        assert_eq!(pixel_nums_to_braille(Some(1), Some(2)), '⠢');
        assert_eq!(pixel_nums_to_braille(None, Some(3)), '⢀');
        assert_eq!(pixel_nums_to_braille(Some(2), None), '⠄');
    }
}
<commit_msg>Filled in spectrum.<commit_after>use std::char;
use std::cmp::max;
use num::Complex;
use rustty::{Terminal, Cell, Style, Attr};

// indexing is from the top of the cell
fn pixel_nums_to_braille(p1: Option<u8>, p2: Option<u8>) -> char {
    let pixel_map = [[0x01, 0x08],
                     [0x02, 0x10],
                     [0x04, 0x20],
                     [0x40, 0x80]];

    let mut c = 0;
    if let Some(p) = p1 {
        for i in p..4 {
            c |= pixel_map[i as usize][0];
        }
    }

    if let Some(p) = p2 {
        for i in p..4 {
            c |= pixel_map[i as usize][1];
        }
    }

    char::from_u32((0x2800 + c) as u32).unwrap()
}

fn fft_shift<T: Clone>(spec: &mut [T]) {
    let spec_copy = spec.to_owned();

    let (first_half, last_half) = spec_copy.split_at((spec_copy.len() + 1) / 2);
    let shifted_spec = last_half.iter().chain(first_half.iter());
    for (x, y) in spec.iter_mut().zip(shifted_spec) {
        *x = y.clone();
    }
}

fn spectrum_to_bin_heights(spec: &[Complex<f32>], dest: &mut [f32]) {
    //TODO should be plotting in log scale

    // subsample
    let mut last_idx = -1isize;
    for (i, x) in spec.iter().map(|x| x.norm()).enumerate() {
        if (i * dest.len() / spec.len()) as isize > last_idx {
            last_idx += 1;
            dest[last_idx as usize] = x;
        }
    }

    //TODO unnecessary allocation
    fft_shift(dest);
}

fn char_to_cell(c: char) -> Cell {
    Cell::new(c, Style::with_attr(Attr::Bold), Style::with_attr(Attr::Default))
}

fn draw_pixel_pair(term: &mut Terminal, col_idx: usize, p1: usize, p2: usize) {
    let max_pixel_height = 4 * term.rows();

    // clamp heights
    let p1 = if p1 >= max_pixel_height { max_pixel_height - 1} else { p1 };
    let p2 = if p2 >= max_pixel_height { max_pixel_height - 1} else { p2 };

    // Reverse it, since the terminal indexing is from the top
    let p1 = max_pixel_height - p1 - 1;
    let p2 = max_pixel_height - p2 - 1;

    // cell indices
    let c1 = p1 / 4;
    let c2 = p2 / 4;

    let full_cell_char = pixel_nums_to_braille(Some(0), Some(0));
    for row_idx in max(c1, c2)..term.rows() {
        term[(col_idx, row_idx)] = char_to_cell(full_cell_char);
    }

    let left_fill_cell_char = pixel_nums_to_braille(Some(0), None);
    for row_idx in c1..max(c1, c2) {
        term[(col_idx, row_idx)] = char_to_cell(left_fill_cell_char);
    }

    let right_fill_cell_char = pixel_nums_to_braille(Some(0), None);
    for row_idx in c2..max(c1, c2) {
        term[(col_idx, row_idx)] = char_to_cell(right_fill_cell_char);
    }

    if c1 == c2 {
        term[(col_idx, c1)] = char_to_cell(
            pixel_nums_to_braille(Some((p1 % 4) as u8), Some((p2 % 4) as u8)));
    } else {
        term[(col_idx, c1)] = char_to_cell(
            pixel_nums_to_braille(Some((p1 % 4) as u8), None));
        term[(col_idx, c2)] = char_to_cell(
            pixel_nums_to_braille(None, Some((p2 % 4) as u8)));
    }
}

pub fn draw_spectrum(term: &mut Terminal, spec: Vec<Complex<f32>>) {
    term.clear().unwrap();
    let (num_cols, num_rows) = term.size();
    let pixel_height = num_rows * 4;
    let pixel_width = num_cols * 2;
    // TODO what should this value be?
    let max_height = 500.0;

    let mut bins = vec![0.0; pixel_width];
    spectrum_to_bin_heights(&spec[..], &mut bins[..]);

    for col_idx in 0..num_cols {
        // height in float between 0 and 1.
        let h1 = bins[col_idx * 2] / max_height;
        let h2 = bins[col_idx * 2 + 1] / max_height;

        // The "pixel" height of each point.
        let p1 = (h1 * pixel_height as f32).floor() as usize;
        let p2 = (h2 * pixel_height as f32).floor() as usize;

        draw_pixel_pair(term, col_idx, p1, p2);
    }
}

#[cfg(test)]
mod tests {
    use super::{pixel_nums_to_braille, fft_shift};

    #[test]
    fn test_fft_shift_dc() {
        let len = 9;
        let mut spec = vec![0; len];
        spec[0] = 1;
        fft_shift(&mut spec[..]);
        assert_eq!(spec[len / 2], 1);
    }

    #[test]
    fn test_fft_shift_even() {
        let mut before: Vec<usize> = (0..10).collect();
        let after = vec![5, 6, 7, 8, 9, 0, 1, 2, 3, 4];
        fft_shift(&mut before[..]);
        assert_eq!(before, after);
    }

    #[test]
    fn test_pixel_nums() {
        assert_eq!(pixel_nums_to_braille(Some(0), Some(0)), '⣿');
        assert_eq!(pixel_nums_to_braille(Some(1), Some(2)), '⣦');
        assert_eq!(pixel_nums_to_braille(None, Some(3)), '⢀');
        assert_eq!(pixel_nums_to_braille(Some(2), None), '⡄');
    }
}
<|endoftext|>


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

// TODO: add tests

use strings::string_buffer::StringBuffer;

use std::fs::{self, File};
use std::io::{self, Write, Read, stdout, BufWriter};

use config::{NewlineStyle, Config, WriteMode};
use rustfmt_diff::{make_diff, print_diff, Mismatch};
use checkstyle::{output_header, output_footer, output_checkstyle_file};

// A map of the files of a crate, with their new content
pub type FileMap = Vec<FileRecord>;

pub type FileRecord = (String, StringBuffer);

// Append a newline to the end of each file.
pub fn append_newline(s: &mut StringBuffer) {
    s.push_str("\n");
}

pub fn write_all_files<T>(file_map: &FileMap, out: &mut T, config: &Config) -> Result<(), io::Error>
    where T: Write
{
    output_header(out, config.write_mode).ok();
    for &(ref filename, ref text) in file_map {
        try!(write_file(text, filename, out, config));
    }
    output_footer(out, config.write_mode).ok();

    Ok(())
}

// Prints all newlines either as `\n` or as `\r\n`.
pub fn write_system_newlines<T>(writer: T,
                                text: &StringBuffer,
                                config: &Config)
                                -> Result<(), io::Error>
    where T: Write
{
    // Buffer output, since we're writing a since char at a time.
    let mut writer = BufWriter::new(writer);

    let style = if config.newline_style == NewlineStyle::Native {
        if cfg!(windows) {
            NewlineStyle::Windows
        } else {
            NewlineStyle::Unix
        }
    } else {
        config.newline_style
    };

    match style {
        NewlineStyle::Unix => write!(writer, "{}", text),
        NewlineStyle::Windows => {
            for (c, _) in text.chars() {
                match c {
                    '\n' => try!(write!(writer, "\r\n")),
                    '\r' => continue,
                    c => try!(write!(writer, "{}", c)),
                }
            }
            Ok(())
        }
        NewlineStyle::Native => unreachable!(),
    }
}

pub fn write_file<T>(text: &StringBuffer,
                     filename: &str,
                     out: &mut T,
                     config: &Config)
                     -> Result<bool, io::Error>
    where T: Write
{

    fn source_and_formatted_text(text: &StringBuffer,
                                 filename: &str,
                                 config: &Config)
                                 -> Result<(String, String), io::Error> {
        let mut f = try!(File::open(filename));
        let mut ori_text = String::new();
        try!(f.read_to_string(&mut ori_text));
        let mut v = Vec::new();
        try!(write_system_newlines(&mut v, text, config));
        let fmt_text = String::from_utf8(v).unwrap();
        Ok((ori_text, fmt_text))
    }

    fn create_diff(filename: &str,
                   text: &StringBuffer,
                   config: &Config)
                   -> Result<Vec<Mismatch>, io::Error> {
        let (ori, fmt) = try!(source_and_formatted_text(text, filename, config));
        Ok(make_diff(&ori, &fmt, 3))
    }

    match config.write_mode {
        WriteMode::Replace => {
            if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) {
                if fmt != ori {
                    // Do a little dance to make writing safer - write to a temp file
                    // rename the original to a .bk, then rename the temp file to the
                    // original.
                    let tmp_name = filename.to_owned() + ".tmp";
                    let bk_name = filename.to_owned() + ".bk";
                    {
                        // Write text to temp file
                        let tmp_file = try!(File::create(&tmp_name));
                        try!(write_system_newlines(tmp_file, text, config));
                    }

                    try!(fs::rename(filename, bk_name));
                    try!(fs::rename(tmp_name, filename));
                }
            }
        }
        WriteMode::Overwrite => {
            // Write text directly over original file.
            let file = try!(File::create(filename));
            try!(write_system_newlines(file, text, config));
        }
        WriteMode::Plain => {
            let stdout = stdout();
            let stdout = stdout.lock();
            try!(write_system_newlines(stdout, text, config));
        }
        WriteMode::Display | WriteMode::Coverage => {
            println!("{}:\n", filename);
            let stdout = stdout();
            let stdout = stdout.lock();
            try!(write_system_newlines(stdout, text, config));
        }
        WriteMode::Diff => {
            if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) {
                let mismatch = make_diff(&ori, &fmt, 3);
                let has_diff = !mismatch.is_empty();
                print_diff(mismatch,
                           |line_num| format!("Diff in {} at line {}:", filename, line_num));
                return Ok(has_diff);
            }
        }
        WriteMode::Checkstyle => {
            let diff = try!(create_diff(filename, text, config));
            try!(output_checkstyle_file(out, filename, diff));
        }
    }

    // when we are not in diff mode, don't indicate differing files
    Ok(false)
}
<commit_msg>Write to the supplied buffer if one is supplied to format_input<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// TODO: add tests

use strings::string_buffer::StringBuffer;

use std::fs::{self, File};
use std::io::{self, Write, Read, sBufWriter};

use config::{NewlineStyle, Config, WriteMode};
use rustfmt_diff::{make_diff, print_diff, Mismatch};
use checkstyle::{output_header, output_footer, output_checkstyle_file};

// A map of the files of a crate, with their new content
pub type FileMap = Vec<FileRecord>;

pub type FileRecord = (String, StringBuffer);

// Append a newline to the end of each file.
pub fn append_newline(s: &mut StringBuffer) {
    s.push_str("\n");
}

pub fn write_all_files<T>(file_map: &FileMap, out: &mut T, config: &Config) -> Result<(), io::Error>
    where T: Write
{
    output_header(out, config.write_mode).ok();
    for &(ref filename, ref text) in file_map {
        try!(write_file(text, filename, out, config));
    }
    output_footer(out, config.write_mode).ok();

    Ok(())
}

// Prints all newlines either as `\n` or as `\r\n`.
pub fn write_system_newlines<T>(writer: T,
                                text: &StringBuffer,
                                config: &Config)
                                -> Result<(), io::Error>
    where T: Write
{
    // Buffer output, since we're writing a since char at a time.
    let mut writer = BufWriter::new(writer);

    let style = if config.newline_style == NewlineStyle::Native {
        if cfg!(windows) {
            NewlineStyle::Windows
        } else {
            NewlineStyle::Unix
        }
    } else {
        config.newline_style
    };

    match style {
        NewlineStyle::Unix => write!(writer, "{}", text),
        NewlineStyle::Windows => {
            for (c, _) in text.chars() {
                match c {
                    '\n' => try!(write!(writer, "\r\n")),
                    '\r' => continue,
                    c => try!(write!(writer, "{}", c)),
                }
            }
            Ok(())
        }
        NewlineStyle::Native => unreachable!(),
    }
}

pub fn write_file<T>(text: &StringBuffer,
                     filename: &str,
                     out: &mut T,
                     config: &Config)
                     -> Result<bool, io::Error>
    where T: Write
{

    fn source_and_formatted_text(text: &StringBuffer,
                                 filename: &str,
                                 config: &Config)
                                 -> Result<(String, String), io::Error> {
        let mut f = try!(File::open(filename));
        let mut ori_text = String::new();
        try!(f.read_to_string(&mut ori_text));
        let mut v = Vec::new();
        try!(write_system_newlines(&mut v, text, config));
        let fmt_text = String::from_utf8(v).unwrap();
        Ok((ori_text, fmt_text))
    }

    fn create_diff(filename: &str,
                   text: &StringBuffer,
                   config: &Config)
                   -> Result<Vec<Mismatch>, io::Error> {
        let (ori, fmt) = try!(source_and_formatted_text(text, filename, config));
        Ok(make_diff(&ori, &fmt, 3))
    }

    match config.write_mode {
        WriteMode::Replace => {
            if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) {
                if fmt != ori {
                    // Do a little dance to make writing safer - write to a temp file
                    // rename the original to a .bk, then rename the temp file to the
                    // original.
                    let tmp_name = filename.to_owned() + ".tmp";
                    let bk_name = filename.to_owned() + ".bk";
                    {
                        // Write text to temp file
                        let tmp_file = try!(File::create(&tmp_name));
                        try!(write_system_newlines(tmp_file, text, config));
                    }

                    try!(fs::rename(filename, bk_name));
                    try!(fs::rename(tmp_name, filename));
                }
            }
        }
        WriteMode::Overwrite => {
            // Write text directly over original file.
            let file = try!(File::create(filename));
            try!(write_system_newlines(file, text, config));
        }
        WriteMode::Plain => {
            try!(write_system_newlines(out, text, config));
        }
        WriteMode::Display | WriteMode::Coverage => {
            println!("{}:\n", filename);
            try!(write_system_newlines(out, text, config));
        }
        WriteMode::Diff => {
            if let Ok((ori, fmt)) = source_and_formatted_text(text, filename, config) {
                let mismatch = make_diff(&ori, &fmt, 3);
                let has_diff = !mismatch.is_empty();
                print_diff(mismatch,
                           |line_num| format!("Diff in {} at line {}:", filename, line_num));
                return Ok(has_diff);
            }
        }
        WriteMode::Checkstyle => {
            let diff = try!(create_diff(filename, text, config));
            try!(output_checkstyle_file(out, filename, diff));
        }
    }

    // when we are not in diff mode, don't indicate differing files
    Ok(false)
}
<|endoftext|>


<commit_before>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/*!
HAL provides abstractions for specific MCU hardware.

Each peripheral in `hal` has a `xxxConf` struct that can be defined statically,
and each such struct has a `setup()` method that configures the hardware
(returning the object to interact with it where applicable).
*/

pub mod lpc11xx;
#[cfg(feature = "mcu_lpc17xx")]
pub mod lpc17xx;
#[cfg(feature = "mcu_stm32f4")]
pub mod stm32f4;
#[cfg(feature = "mcu_stm32l1")]
pub mod stm32l1;
#[cfg(feature = "mcu_k20")]
pub mod k20;
#[cfg(feature = "mcu_tiva_c")]
pub mod tiva_c;

#[cfg(any(feature = "cpu_cortex-m3",
          feature = "cpu_cortex-m4"))]
mod cortex_common;
#[cfg(feature = "cpu_cortex-m3")]
pub mod cortex_m3;
#[cfg(feature = "cpu_cortex-m4")]
pub mod cortex_m4;

pub mod mem_init;
pub mod pin;
pub mod spi;
pub mod stack;
pub mod timer;
pub mod uart;

#[cfg(target_os = "none")]
pub mod isr;
<commit_msg>Cleaned up layout of hal/mod.rs so feature guards are more obvious<commit_after>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/*!
HAL provides abstractions for specific MCU hardware.

Each peripheral in `hal` has a `xxxConf` struct that can be defined statically,
and each such struct has a `setup()` method that configures the hardware
(returning the object to interact with it where applicable).
*/

pub mod lpc11xx;
#[cfg(feature = "mcu_lpc17xx")] pub mod lpc17xx;
#[cfg(feature = "mcu_stm32f4")] pub mod stm32f4;
#[cfg(feature = "mcu_stm32l1")] pub mod stm32l1;
#[cfg(feature = "mcu_k20")] pub mod k20;
#[cfg(feature = "mcu_tiva_c")] pub mod tiva_c;

#[cfg(any(feature = "cpu_cortex-m0",
          feature = "cpu_cortex-m3",
          feature = "cpu_cortex-m4"))]
mod cortex_common;
#[cfg(feature = "cpu_cortex-m3")]
pub mod cortex_m3;
#[cfg(feature = "cpu_cortex-m4")]
pub mod cortex_m4;

pub mod mem_init;
pub mod pin;
pub mod spi;
pub mod stack;
pub mod timer;
pub mod uart;

#[cfg(target_os = "none")]
pub mod isr;
<|endoftext|>


<commit_before>//! Define trait for Hermite matrices

use ndarray::{Ix2, Array, RcArray};
use lapack::c::Layout;

use super::matrix::{Matrix, MFloat};
use super::square::SquareMatrix;
use super::error::LinalgError;
use super::impls::eigh::ImplEigh;
use super::impls::cholesky::ImplCholesky;

pub trait HMFloat: ImplEigh + ImplCholesky + MFloat {}
impl<A: ImplEigh + ImplCholesky + MFloat> HMFloat for A {}

/// Methods for Hermite matrix
pub trait HermiteMatrix: SquareMatrix + Matrix {
    /// eigenvalue decomposition
    fn eigh(self) -> Result<(Self::Vector, Self), LinalgError>;
    /// symmetric square root of Hermite matrix
    fn ssqrt(self) -> Result<Self, LinalgError>;
    /// Cholesky factorization
    fn cholesky(self) -> Result<Self, LinalgError>;
    /// calc determinant using Cholesky factorization
    fn deth(self) -> Result<Self::Scalar, LinalgError>;
}

impl<A: HMFloat> HermiteMatrix for Array<A, Ix2> {
    fn eigh(self) -> Result<(Self::Vector, Self), LinalgError> {
        self.check_square()?;
        let layout = self.layout()?;
        let (rows, cols) = self.size();
        let (w, a) = ImplEigh::eigh(layout, rows, self.into_raw_vec())?;
        let ea = Array::from_vec(w);
        let va = match layout {
            Layout::ColumnMajor => Array::from_vec(a).into_shape((rows, cols)).unwrap().reversed_axes(),
            Layout::RowMajor => Array::from_vec(a).into_shape((rows, cols)).unwrap(),
        };
        Ok((ea, va))
    }
    fn ssqrt(self) -> Result<Self, LinalgError> {
        let (n, _) = self.size();
        let (e, v) = self.eigh()?;
        let mut res = Array::zeros((n, n));
        for i in 0..n {
            for j in 0..n {
                res[(i, j)] = e[i].sqrt() * v[(j, i)];
            }
        }
        Ok(v.dot(&res))
    }
    fn cholesky(self) -> Result<Self, LinalgError> {
        self.check_square()?;
        let (n, _) = self.size();
        let layout = self.layout()?;
        let a = ImplCholesky::cholesky(layout, n, self.into_raw_vec())?;
        let mut c = match layout {
            Layout::RowMajor => Array::from_vec(a).into_shape((n, n)).unwrap(),
            Layout::ColumnMajor => Array::from_vec(a).into_shape((n, n)).unwrap().reversed_axes(),
        };
        for ((i, j), val) in c.indexed_iter_mut() {
            if i > j {
                *val = A::zero();
            }
        }
        Ok(c)
    }
    fn deth(self) -> Result<Self::Scalar, LinalgError> {
        let (n, _) = self.size();
        let c = self.cholesky()?;
        let rt = (0..n).map(|i| c[(i, i)]).fold(A::one(), |det, c| det * c);
        Ok(rt * rt)
    }
}

impl<A: HMFloat> HermiteMatrix for RcArray<A, Ix2> {
    fn eigh(self) -> Result<(Self::Vector, Self), LinalgError> {
        let (e, v) = self.into_owned().eigh()?;
        Ok((e.into_shared(), v.into_shared()))
    }
    fn ssqrt(self) -> Result<Self, LinalgError> {
        let s = self.into_owned().ssqrt()?;
        Ok(s.into_shared())
    }
    fn cholesky(self) -> Result<Self, LinalgError> {
        let s = self.into_owned().cholesky()?;
        Ok(s.into_shared())
    }
    fn deth(self) -> Result<Self::Scalar, LinalgError> {
        self.into_owned().deth()
    }
}
<commit_msg>Remove old hermite codes<commit_after><|endoftext|>