<commit_before>use crate::utils::paths;
use crate::utils::{
    is_expn_of, is_type_diagnostic_item, last_path_segment, match_def_path, match_function_call, snippet, snippet_opt,
    span_lint_and_then,
};
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::{Arm, BorrowKind, Expr, ExprKind, MatchSource, PatKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span;
use rustc_span::sym;

declare_clippy_lint! {
    /// **What it does:** Checks for the use of `format!("string literal with no
    /// argument")` and `format!("{}", foo)` where `foo` is a string.
    ///
    /// **Why is this bad?** There is no point of doing that. `format!("foo")` can
    /// be replaced by `"foo".to_owned()` if you really need a `String`. The even
    /// worse `&format!("foo")` is often encountered in the wild. `format!("{}",
    /// foo)` can be replaced by `foo.clone()` if `foo: String` or `foo.to_owned()`
    /// if `foo: &str`.
    ///
    /// **Known problems:** None.
    ///
    /// **Examples:**
    /// ```rust
    ///
    /// // Bad
    /// # let foo = "foo";
    /// format!("{}", foo);
    ///
    /// // Good
    /// format!("foo");
    /// ```
    pub USELESS_FORMAT,
    complexity,
    "useless use of `format!`"
}

declare_lint_pass!(UselessFormat => [USELESS_FORMAT]);

impl<'tcx> LateLintPass<'tcx> for UselessFormat {
    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
        let span = match is_expn_of(expr.span, "format") {
            Some(s) if !s.from_expansion() => s,
            _ => return,
        };

        // Operate on the only argument of `alloc::fmt::format`.
        if let Some(sugg) = on_new_v1(cx, expr) {
            span_useless_format(cx, span, "consider using `.to_string()`", sugg);
        } else if let Some(sugg) = on_new_v1_fmt(cx, expr) {
            span_useless_format(cx, span, "consider using `.to_string()`", sugg);
        }
    }
}

fn span_useless_format<T: LintContext>(cx: &T, span: Span, help: &str, mut sugg: String) {
    let to_replace = span.source_callsite();

    // The callsite span contains the statement semicolon for some reason.
    let snippet = snippet(cx, to_replace, "..");
    if snippet.ends_with(';') {
        sugg.push(';');
    }

    span_lint_and_then(cx, USELESS_FORMAT, span, "useless use of `format!`", |diag| {
        diag.span_suggestion(
            to_replace,
            help,
            sugg,
            Applicability::MachineApplicable, // snippet
        );
    });
}

fn on_argumentv1_new<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arms: &'tcx [Arm<'_>]) -> Option<String> {
    if_chain! {
        if let ExprKind::AddrOf(BorrowKind::Ref, _, ref format_args) = expr.kind;
        if let ExprKind::Array(ref elems) = arms[0].body.kind;
        if elems.len() == 1;
        if let Some(args) = match_function_call(cx, &elems[0], &paths::FMT_ARGUMENTV1_NEW);
        // matches `core::fmt::Display::fmt`
        if args.len() == 2;
        if let ExprKind::Path(ref qpath) = args[1].kind;
        if let Some(did) = cx.qpath_res(qpath, args[1].hir_id).opt_def_id();
        if match_def_path(cx, did, &paths::DISPLAY_FMT_METHOD);
        // check `(arg0,)` in match block
        if let PatKind::Tuple(ref pats, None) = arms[0].pat.kind;
        if pats.len() == 1;
        then {
            let ty = cx.typeck_results().pat_ty(&pats[0]).peel_refs();
            if *ty.kind() != rustc_middle::ty::Str && !is_type_diagnostic_item(cx, ty, sym::string_type) {
                return None;
            }
            if let ExprKind::Lit(ref lit) = format_args.kind {
                if let LitKind::Str(ref s, _) = lit.node {
                    return Some(format!("{:?}.to_string()", s.as_str()));
                }
            } else {
                let snip = snippet(cx, format_args.span, "<arg>");
                if let ExprKind::MethodCall(ref path, _, _, _) = format_args.kind {
                    if path.ident.name == sym!(to_string) {
                        return Some(format!("{}", snip));
                    }
                } else if let ExprKind::Binary(..) = format_args.kind {
                    return Some(format!("{}", snip));
                }
                return Some(format!("{}.to_string()", snip));
            }
        }
    }
    None
}

fn on_new_v1<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<String> {
    if_chain! {
        if let Some(args) = match_function_call(cx, expr, &paths::FMT_ARGUMENTS_NEW_V1);
        if args.len() == 2;
        // Argument 1 in `new_v1()`
        if let ExprKind::AddrOf(BorrowKind::Ref, _, ref arr) = args[0].kind;
        if let ExprKind::Array(ref pieces) = arr.kind;
        if pieces.len() == 1;
        if let ExprKind::Lit(ref lit) = pieces[0].kind;
        if let LitKind::Str(ref s, _) = lit.node;
        // Argument 2 in `new_v1()`
        if let ExprKind::AddrOf(BorrowKind::Ref, _, ref arg1) = args[1].kind;
        if let ExprKind::Match(ref matchee, ref arms, MatchSource::Normal) = arg1.kind;
        if arms.len() == 1;
        if let ExprKind::Tup(ref tup) = matchee.kind;
        then {
            // `format!("foo")` expansion contains `match () { () => [], }`
            if tup.is_empty() {
                if let Some(s_src) = snippet_opt(cx, lit.span) {
                    // Simulate macro expansion, converting {{ and }} to { and }.
                    let s_expand = s_src.replace("{{", "{").replace("}}", "}");
                    return Some(format!("{}.to_string()", s_expand))
                }
            } else if s.as_str().is_empty() {
                return on_argumentv1_new(cx, &tup[0], arms);
            }
        }
    }
    None
}

fn on_new_v1_fmt<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<String> {
    if_chain! {
        if let Some(args) = match_function_call(cx, expr, &paths::FMT_ARGUMENTS_NEW_V1_FORMATTED);
        if args.len() == 3;
        if check_unformatted(&args[2]);
        // Argument 1 in `new_v1_formatted()`
        if let ExprKind::AddrOf(BorrowKind::Ref, _, ref arr) = args[0].kind;
        if let ExprKind::Array(ref pieces) = arr.kind;
        if pieces.len() == 1;
        if let ExprKind::Lit(ref lit) = pieces[0].kind;
        if let LitKind::Str(..) = lit.node;
        // Argument 2 in `new_v1_formatted()`
        if let ExprKind::AddrOf(BorrowKind::Ref, _, ref arg1) = args[1].kind;
        if let ExprKind::Match(ref matchee, ref arms, MatchSource::Normal) = arg1.kind;
        if arms.len() == 1;
        if let ExprKind::Tup(ref tup) = matchee.kind;
        then {
            return on_argumentv1_new(cx, &tup[0], arms);
        }
    }
    None
}

/// Checks if the expression matches
/// ```rust,ignore
/// &[_ {
///    format: _ {
///         width: _::Implied,
///         precision: _::Implied,
///         ...
///    },
///    ...,
/// }]
/// ```
fn check_unformatted(expr: &Expr<'_>) -> bool {
    if_chain! {
        if let ExprKind::AddrOf(BorrowKind::Ref, _, ref expr) = expr.kind;
        if let ExprKind::Array(ref exprs) = expr.kind;
        if exprs.len() == 1;
        // struct `core::fmt::rt::v1::Argument`
        if let ExprKind::Struct(_, ref fields, _) = exprs[0].kind;
        if let Some(format_field) = fields.iter().find(|f| f.ident.name == sym::format);
        // struct `core::fmt::rt::v1::FormatSpec`
        if let ExprKind::Struct(_, ref fields, _) = format_field.expr.kind;
        if let Some(precision_field) = fields.iter().find(|f| f.ident.name == sym::precision);
        if let ExprKind::Path(ref precision_path) = precision_field.expr.kind;
        if last_path_segment(precision_path).ident.name == sym::Implied;
        if let Some(width_field) = fields.iter().find(|f| f.ident.name == sym::width);
        if let ExprKind::Path(ref width_qpath) = width_field.expr.kind;
        if last_path_segment(width_qpath).ident.name == sym::Implied;
        then {
            return true;
        }
    }

    false
}
<commit_msg>useless_format: fix examples in the description<commit_after>use crate::utils::paths;
use crate::utils::{
    is_expn_of, is_type_diagnostic_item, last_path_segment, match_def_path, match_function_call, snippet, snippet_opt,
    span_lint_and_then,
};
use if_chain::if_chain;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::{Arm, BorrowKind, Expr, ExprKind, MatchSource, PatKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::Span;
use rustc_span::sym;

declare_clippy_lint! {
    /// **What it does:** Checks for the use of `format!("string literal with no
    /// argument")` and `format!("{}", foo)` where `foo` is a string.
    ///
    /// **Why is this bad?** There is no point of doing that. `format!("foo")` can
    /// be replaced by `"foo".to_owned()` if you really need a `String`. The even
    /// worse `&format!("foo")` is often encountered in the wild. `format!("{}",
    /// foo)` can be replaced by `foo.clone()` if `foo: String` or `foo.to_owned()`
    /// if `foo: &str`.
    ///
    /// **Known problems:** None.
    ///
    /// **Examples:**
    /// ```rust
    ///
    /// // Bad
    /// let foo = "foo";
    /// format!("{}", foo);
    ///
    /// // Good
    /// foo.to_owned();
    /// ```
    pub USELESS_FORMAT,
    complexity,
    "useless use of `format!`"
}

declare_lint_pass!(UselessFormat => [USELESS_FORMAT]);

impl<'tcx> LateLintPass<'tcx> for UselessFormat {
    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
        let span = match is_expn_of(expr.span, "format") {
            Some(s) if !s.from_expansion() => s,
            _ => return,
        };

        // Operate on the only argument of `alloc::fmt::format`.
        if let Some(sugg) = on_new_v1(cx, expr) {
            span_useless_format(cx, span, "consider using `.to_string()`", sugg);
        } else if let Some(sugg) = on_new_v1_fmt(cx, expr) {
            span_useless_format(cx, span, "consider using `.to_string()`", sugg);
        }
    }
}

fn span_useless_format<T: LintContext>(cx: &T, span: Span, help: &str, mut sugg: String) {
    let to_replace = span.source_callsite();

    // The callsite span contains the statement semicolon for some reason.
    let snippet = snippet(cx, to_replace, "..");
    if snippet.ends_with(';') {
        sugg.push(';');
    }

    span_lint_and_then(cx, USELESS_FORMAT, span, "useless use of `format!`", |diag| {
        diag.span_suggestion(
            to_replace,
            help,
            sugg,
            Applicability::MachineApplicable, // snippet
        );
    });
}

fn on_argumentv1_new<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, arms: &'tcx [Arm<'_>]) -> Option<String> {
    if_chain! {
        if let ExprKind::AddrOf(BorrowKind::Ref, _, ref format_args) = expr.kind;
        if let ExprKind::Array(ref elems) = arms[0].body.kind;
        if elems.len() == 1;
        if let Some(args) = match_function_call(cx, &elems[0], &paths::FMT_ARGUMENTV1_NEW);
        // matches `core::fmt::Display::fmt`
        if args.len() == 2;
        if let ExprKind::Path(ref qpath) = args[1].kind;
        if let Some(did) = cx.qpath_res(qpath, args[1].hir_id).opt_def_id();
        if match_def_path(cx, did, &paths::DISPLAY_FMT_METHOD);
        // check `(arg0,)` in match block
        if let PatKind::Tuple(ref pats, None) = arms[0].pat.kind;
        if pats.len() == 1;
        then {
            let ty = cx.typeck_results().pat_ty(&pats[0]).peel_refs();
            if *ty.kind() != rustc_middle::ty::Str && !is_type_diagnostic_item(cx, ty, sym::string_type) {
                return None;
            }
            if let ExprKind::Lit(ref lit) = format_args.kind {
                if let LitKind::Str(ref s, _) = lit.node {
                    return Some(format!("{:?}.to_string()", s.as_str()));
                }
            } else {
                let snip = snippet(cx, format_args.span, "<arg>");
                if let ExprKind::MethodCall(ref path, _, _, _) = format_args.kind {
                    if path.ident.name == sym!(to_string) {
                        return Some(format!("{}", snip));
                    }
                } else if let ExprKind::Binary(..) = format_args.kind {
                    return Some(format!("{}", snip));
                }
                return Some(format!("{}.to_string()", snip));
            }
        }
    }
    None
}

fn on_new_v1<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<String> {
    if_chain! {
        if let Some(args) = match_function_call(cx, expr, &paths::FMT_ARGUMENTS_NEW_V1);
        if args.len() == 2;
        // Argument 1 in `new_v1()`
        if let ExprKind::AddrOf(BorrowKind::Ref, _, ref arr) = args[0].kind;
        if let ExprKind::Array(ref pieces) = arr.kind;
        if pieces.len() == 1;
        if let ExprKind::Lit(ref lit) = pieces[0].kind;
        if let LitKind::Str(ref s, _) = lit.node;
        // Argument 2 in `new_v1()`
        if let ExprKind::AddrOf(BorrowKind::Ref, _, ref arg1) = args[1].kind;
        if let ExprKind::Match(ref matchee, ref arms, MatchSource::Normal) = arg1.kind;
        if arms.len() == 1;
        if let ExprKind::Tup(ref tup) = matchee.kind;
        then {
            // `format!("foo")` expansion contains `match () { () => [], }`
            if tup.is_empty() {
                if let Some(s_src) = snippet_opt(cx, lit.span) {
                    // Simulate macro expansion, converting {{ and }} to { and }.
                    let s_expand = s_src.replace("{{", "{").replace("}}", "}");
                    return Some(format!("{}.to_string()", s_expand))
                }
            } else if s.as_str().is_empty() {
                return on_argumentv1_new(cx, &tup[0], arms);
            }
        }
    }
    None
}

fn on_new_v1_fmt<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<String> {
    if_chain! {
        if let Some(args) = match_function_call(cx, expr, &paths::FMT_ARGUMENTS_NEW_V1_FORMATTED);
        if args.len() == 3;
        if check_unformatted(&args[2]);
        // Argument 1 in `new_v1_formatted()`
        if let ExprKind::AddrOf(BorrowKind::Ref, _, ref arr) = args[0].kind;
        if let ExprKind::Array(ref pieces) = arr.kind;
        if pieces.len() == 1;
        if let ExprKind::Lit(ref lit) = pieces[0].kind;
        if let LitKind::Str(..) = lit.node;
        // Argument 2 in `new_v1_formatted()`
        if let ExprKind::AddrOf(BorrowKind::Ref, _, ref arg1) = args[1].kind;
        if let ExprKind::Match(ref matchee, ref arms, MatchSource::Normal) = arg1.kind;
        if arms.len() == 1;
        if let ExprKind::Tup(ref tup) = matchee.kind;
        then {
            return on_argumentv1_new(cx, &tup[0], arms);
        }
    }
    None
}

/// Checks if the expression matches
/// ```rust,ignore
/// &[_ {
///    format: _ {
///         width: _::Implied,
///         precision: _::Implied,
///         ...
///    },
///    ...,
/// }]
/// ```
fn check_unformatted(expr: &Expr<'_>) -> bool {
    if_chain! {
        if let ExprKind::AddrOf(BorrowKind::Ref, _, ref expr) = expr.kind;
        if let ExprKind::Array(ref exprs) = expr.kind;
        if exprs.len() == 1;
        // struct `core::fmt::rt::v1::Argument`
        if let ExprKind::Struct(_, ref fields, _) = exprs[0].kind;
        if let Some(format_field) = fields.iter().find(|f| f.ident.name == sym::format);
        // struct `core::fmt::rt::v1::FormatSpec`
        if let ExprKind::Struct(_, ref fields, _) = format_field.expr.kind;
        if let Some(precision_field) = fields.iter().find(|f| f.ident.name == sym::precision);
        if let ExprKind::Path(ref precision_path) = precision_field.expr.kind;
        if last_path_segment(precision_path).ident.name == sym::Implied;
        if let Some(width_field) = fields.iter().find(|f| f.ident.name == sym::width);
        if let ExprKind::Path(ref width_qpath) = width_field.expr.kind;
        if last_path_segment(width_qpath).ident.name == sym::Implied;
        then {
            return true;
        }
    }

    false
}
<|endoftext|>


<commit_before>// Claxon -- A FLAC decoding library in Rust
// Copyright (C) 2014-2015 Ruud van Asseldonk
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License, version 3,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

//! The `error` module defines the error and result types.

use std::error;
use std::fmt;
use std::io;
use std::result;

/// An error that prevents succesful decoding of the FLAC stream.
#[derive(Debug)]
pub enum Error {
    /// Not a decoding error, but a problem with the underlying IO.
    IoError(io::Error),

    /// An ill-formed FLAC stream was encountered.
    FormatError(&'static str),

    /// The audio stream has more bits per sample than the provided sample
    /// buffer to decode into.
    TooWide,

    /// A currently unsupported feature of the FLAC format was encountered.
    ///
    /// Claxon reads the FLAC format as it was with FLAC 1.3.1. Values in the
    /// specification that are marked as reserved will cause a `FormatError`;
    /// `Unsupported` is used for features that are in the specification, but
    /// which are not implemented by Claxon.
    Unsupported(&'static str),

    /// An overflow occurred when decoding the side channel.
    InvalidSideSample,
    /// An overflow occurred when doing fixed prediction.
    InvalidFixedSample,
    /// An overflow occurred when doing LPC prediction.
    InvalidLpcSample,

    /// The audio stream has more bits per sample than the provided sample
    /// buffer to decode into.
    SampleTooWide
}

impl PartialEq for Error {
    fn eq(&self, other: &Error) -> bool {
        use error::Error::{FormatError, TooWide, Unsupported};
        match (self, other) {
            (&FormatError(r1), &FormatError(r2)) => r1 == r2,
            (&TooWide, &TooWide) => true,
            (&Unsupported(f1), &Unsupported(f2)) => f1 == f2,
            // TODO: this is error-prone. The _ case is required for all
            // non-equal combinations, but it will prevent the compiler from
            // emitting a warning once a new enum variant is added. There must
            // be a better way, right?
            _ => false
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter)
           -> result::Result<(), fmt::Error> {
        match *self {
            Error::IoError(ref err) => err.fmt(formatter),
            Error::FormatError(reason) => {
                try!(formatter.write_str("Ill-formed FLAC stream: "));
                formatter.write_str(reason)
            },
            Error::TooWide => {
                formatter.write_str("The audio stream has more bits per sample than the provided sample buffer to decode into.")
            },
            Error::Unsupported(feature) => {
                try!(formatter.write_str("A currently unsupported feature of the FLAC format was encountered: "));
                formatter.write_str(feature)
            },
            // TODO: Remove this when possible.
            _ => formatter.write_str("deprecated error variant")
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::IoError(ref err) => err.description(),
            Error::FormatError(reason) => reason,
            Error::TooWide => "the sample has more bits than the destination type",
            Error::Unsupported(_) => "unsupported feature",
            // TODO: Remove this when possible.
            _ => "deprecated error variant"
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::IoError(ref err) => Some(err),
            Error::FormatError(_) => None,
            Error::TooWide => None,
            Error::Unsupported(_) => None,
            // TODO: Remove this when possible.
            _ => None
        }
    }
}

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

// TODO: Remove the `Flac` prefix.
/// Either `T` on success, or an `Error` on failure.
pub type FlacResult<T> = Result<T, Error>;
<commit_msg>remove unused Error variants<commit_after>// Claxon -- A FLAC decoding library in Rust
// Copyright (C) 2014-2015 Ruud van Asseldonk
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License, version 3,
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

//! The `error` module defines the error and result types.

use std::error;
use std::fmt;
use std::io;
use std::result;

/// An error that prevents succesful decoding of the FLAC stream.
#[derive(Debug)]
pub enum Error {
    /// Not a decoding error, but a problem with the underlying IO.
    IoError(io::Error),

    /// An ill-formed FLAC stream was encountered.
    FormatError(&'static str),

    /// The audio stream has more bits per sample than the provided sample
    /// buffer to decode into.
    TooWide,

    /// A currently unsupported feature of the FLAC format was encountered.
    ///
    /// Claxon reads the FLAC format as it was with FLAC 1.3.1. Values in the
    /// specification that are marked as reserved will cause a `FormatError`;
    /// `Unsupported` is used for features that are in the specification, but
    /// which are not implemented by Claxon.
    Unsupported(&'static str),

    /// An overflow occurred when doing LPC prediction.
    InvalidLpcSample,

    /// The audio stream has more bits per sample than the provided sample
    /// buffer to decode into.
    SampleTooWide
}

impl PartialEq for Error {
    fn eq(&self, other: &Error) -> bool {
        use error::Error::{FormatError, TooWide, Unsupported};
        match (self, other) {
            (&FormatError(r1), &FormatError(r2)) => r1 == r2,
            (&TooWide, &TooWide) => true,
            (&Unsupported(f1), &Unsupported(f2)) => f1 == f2,
            // TODO: this is error-prone. The _ case is required for all
            // non-equal combinations, but it will prevent the compiler from
            // emitting a warning once a new enum variant is added. There must
            // be a better way, right?
            _ => false
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, formatter: &mut fmt::Formatter)
           -> result::Result<(), fmt::Error> {
        match *self {
            Error::IoError(ref err) => err.fmt(formatter),
            Error::FormatError(reason) => {
                try!(formatter.write_str("Ill-formed FLAC stream: "));
                formatter.write_str(reason)
            },
            Error::TooWide => {
                formatter.write_str("The audio stream has more bits per sample than the provided sample buffer to decode into.")
            },
            Error::Unsupported(feature) => {
                try!(formatter.write_str("A currently unsupported feature of the FLAC format was encountered: "));
                formatter.write_str(feature)
            },
            // TODO: Remove this when possible.
            _ => formatter.write_str("deprecated error variant")
        }
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match *self {
            Error::IoError(ref err) => err.description(),
            Error::FormatError(reason) => reason,
            Error::TooWide => "the sample has more bits than the destination type",
            Error::Unsupported(_) => "unsupported feature",
            // TODO: Remove this when possible.
            _ => "deprecated error variant"
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match *self {
            Error::IoError(ref err) => Some(err),
            Error::FormatError(_) => None,
            Error::TooWide => None,
            Error::Unsupported(_) => None,
            // TODO: Remove this when possible.
            _ => None
        }
    }
}

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

// TODO: Remove the `Flac` prefix.
/// Either `T` on success, or an `Error` on failure.
pub type FlacResult<T> = Result<T, Error>;
<|endoftext|>


<commit_before>//! Error types and conversions.

use std::error::Error;
use std::fmt::{Display, Formatter};
use std::fmt::Error as FmtError;
use std::io::Error as IoError;
use std::string::FromUtf8Error;

use base64::Base64Error;
use diesel::result::{TransactionError, Error as DieselError};
use iron::{IronError, Response};
use iron::modifier::Modifier;
use iron::status::Status;
use persistent::PersistentError;
use r2d2::GetTimeout;
use serde_json;

/// A client-facing error.
#[derive(Clone, Debug, Serialize)]
pub struct APIError {
    #[serde(skip_serializing)]
    debug_message: Option<String>,
    errcode: APIErrorCode,
    error: String,
}

impl APIError {
    /// Create an error for invalid or incomplete JSON in request bodies.
    pub fn bad_json() -> APIError {
        APIError {
            debug_message: None,
            errcode: APIErrorCode::BadJson,
            error: "Invalid or missing key-value pairs in JSON.".to_owned(),
        }
    }

    /// Create an error for requests without JSON bodies.
    pub fn not_json() -> APIError {
        APIError {
            debug_message: None,
            errcode: APIErrorCode::NotJson,
            error: "No JSON found in request body.".to_owned(),
        }
    }

    /// Create an error for requests that are not marked as containing JSON.
    pub fn wrong_content_type() -> APIError {
        APIError {
            debug_message: None,
            errcode: APIErrorCode::NotJson,
            error: "Request's Content-Type header must be application/json.".to_owned(),
        }
    }

    /// Create a generic error for anything not specifically covered by the Matrix spec.
    pub fn unknown<E>(error: &E) -> APIError where E: Error {
        APIError {
            debug_message: Some(error.description().to_owned()),
            errcode: APIErrorCode::Unknown,
            error: "An unknown server-side error occurred.".to_owned(),
        }
    }

    /// Create a generic error for anything not specifically covered by the Matrix spec.
    ///
    /// Like `unknown`, but uses a `String` instead of an `Error` to create the value.
    pub fn unknown_from_string(message: String) -> APIError {
        APIError {
            debug_message: Some(message),
            errcode: APIErrorCode::Unknown,
            error: "An unknown server-side error occurred.".to_owned(),
        }
    }
}

impl Display for APIError {
    fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
        write!(f, "{}", self.error)
    }
}

impl Error for APIError {
    fn description(&self) -> &str {
        &self.error
    }
}

impl From<IoError> for APIError {
    fn from(error: IoError) -> APIError {
        APIError::unknown(&error)
    }
}

impl From<Base64Error> for APIError {
    fn from(error: Base64Error) -> APIError {
        APIError::unknown(&error)
    }
}

impl From<DieselError> for APIError {
    fn from(error: DieselError) -> APIError {
        APIError::unknown(&error)
    }
}

impl<T> From<TransactionError<T>> for APIError where T: Error {
    fn from(error: TransactionError<T>) -> APIError {
        APIError::unknown(&error)
    }
}

impl From<PersistentError> for APIError {
    fn from(error: PersistentError) -> APIError {
        APIError::unknown(&error)
    }
}

impl From<GetTimeout> for APIError {
    fn from(error: GetTimeout) -> APIError {
        APIError::unknown(&error)
    }
}

impl From<FromUtf8Error> for APIError {
    fn from(error: FromUtf8Error) -> APIError {
        APIError::unknown(&error)
    }
}

impl From<APIError> for IronError {
    fn from(error: APIError) -> IronError {
        IronError::new(error.clone(), error)
    }
}

impl Modifier<Response> for APIError {
    fn modify(self, response: &mut Response) {
        response.status = Some(self.errcode.status_code());
        response.body = Some(Box::new(serde_json::to_string(&self).expect("APIError should always serialize")));
    }
}

/// The error code for a client-facing error.
#[derive(Clone, Debug, Serialize)]
pub enum APIErrorCode {
    BadJson,
    Forbidden,
    LimitExceeded,
    NotFound,
    NotJson,
    Unknown,
    UnknownToken,
}

impl APIErrorCode {
    pub fn status_code(&self) -> Status {
        match *self {
            APIErrorCode::BadJson => Status::UnprocessableEntity,
            APIErrorCode::Forbidden => Status::Forbidden,
            APIErrorCode::LimitExceeded => Status::TooManyRequests,
            APIErrorCode::NotFound => Status::NotFound,
            APIErrorCode::NotJson => Status::BadRequest,
            APIErrorCode::Unknown => Status::InternalServerError,
            APIErrorCode::UnknownToken => Status::Unauthorized,
        }
    }
}

/// An operator-facing error.
pub struct CLIError {
    error: String,
}

impl CLIError {
    /// Create a new `CLIError` from any `Error` type.
    pub fn new<E>(error: E) -> CLIError where E: Into<String> {
        CLIError {
            error: error.into(),
        }
    }
}

impl<E> From<E> for CLIError where E: Error {
    fn from(error: E) -> CLIError {
        CLIError::new(error.description())
    }
}

impl Display for CLIError {
    fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
        write!(f, "{}", self.error)
    }
}
<commit_msg>Use logging for debug messages on error types.<commit_after>//! Error types and conversions.

use std::error::Error;
use std::fmt::{Display, Formatter};
use std::fmt::Error as FmtError;
use std::io::Error as IoError;
use std::string::FromUtf8Error;

use base64::Base64Error;
use diesel::result::{TransactionError, Error as DieselError};
use iron::{IronError, Response};
use iron::modifier::Modifier;
use iron::status::Status;
use persistent::PersistentError;
use r2d2::GetTimeout;
use serde_json;

/// A client-facing error.
#[derive(Clone, Debug, Serialize)]
pub struct APIError {
    errcode: APIErrorCode,
    error: String,
}

impl APIError {
    /// Create an error for invalid or incomplete JSON in request bodies.
    pub fn bad_json() -> APIError {
        APIError {
            errcode: APIErrorCode::BadJson,
            error: "Invalid or missing key-value pairs in JSON.".to_owned(),
        }
    }

    /// Create an error for requests without JSON bodies.
    pub fn not_json() -> APIError {
        APIError {
            errcode: APIErrorCode::NotJson,
            error: "No JSON found in request body.".to_owned(),
        }
    }

    /// Create an error for requests that are not marked as containing JSON.
    pub fn wrong_content_type() -> APIError {
        APIError {
            errcode: APIErrorCode::NotJson,
            error: "Request's Content-Type header must be application/json.".to_owned(),
        }
    }

    /// Create a generic error for anything not specifically covered by the Matrix spec.
    pub fn unknown<E>(error: &E) -> APIError where E: Error {
        debug!("APIError::unknown: {}", error);

        APIError {
            errcode: APIErrorCode::Unknown,
            error: "An unknown server-side error occurred.".to_owned(),
        }
    }

    /// Create a generic error for anything not specifically covered by the Matrix spec.
    ///
    /// Like `unknown`, but uses a `String` instead of an `Error` to create the value.
    pub fn unknown_from_string(message: String) -> APIError {
        debug!("APIError::unknown_from_string: {}", message);

        APIError {
            errcode: APIErrorCode::Unknown,
            error: "An unknown server-side error occurred.".to_owned(),
        }
    }
}

impl Display for APIError {
    fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
        write!(f, "{}", self.error)
    }
}

impl Error for APIError {
    fn description(&self) -> &str {
        &self.error
    }
}

impl From<IoError> for APIError {
    fn from(error: IoError) -> APIError {
        APIError::unknown(&error)
    }
}

impl From<Base64Error> for APIError {
    fn from(error: Base64Error) -> APIError {
        APIError::unknown(&error)
    }
}

impl From<DieselError> for APIError {
    fn from(error: DieselError) -> APIError {
        APIError::unknown(&error)
    }
}

impl<T> From<TransactionError<T>> for APIError where T: Error {
    fn from(error: TransactionError<T>) -> APIError {
        APIError::unknown(&error)
    }
}

impl From<PersistentError> for APIError {
    fn from(error: PersistentError) -> APIError {
        APIError::unknown(&error)
    }
}

impl From<GetTimeout> for APIError {
    fn from(error: GetTimeout) -> APIError {
        APIError::unknown(&error)
    }
}

impl From<FromUtf8Error> for APIError {
    fn from(error: FromUtf8Error) -> APIError {
        APIError::unknown(&error)
    }
}

impl From<APIError> for IronError {
    fn from(error: APIError) -> IronError {
        IronError::new(error.clone(), error)
    }
}

impl Modifier<Response> for APIError {
    fn modify(self, response: &mut Response) {
        response.status = Some(self.errcode.status_code());
        response.body = Some(Box::new(serde_json::to_string(&self).expect("APIError should always serialize")));
    }
}

/// The error code for a client-facing error.
#[derive(Clone, Debug, Serialize)]
pub enum APIErrorCode {
    BadJson,
    Forbidden,
    LimitExceeded,
    NotFound,
    NotJson,
    Unknown,
    UnknownToken,
}

impl APIErrorCode {
    pub fn status_code(&self) -> Status {
        match *self {
            APIErrorCode::BadJson => Status::UnprocessableEntity,
            APIErrorCode::Forbidden => Status::Forbidden,
            APIErrorCode::LimitExceeded => Status::TooManyRequests,
            APIErrorCode::NotFound => Status::NotFound,
            APIErrorCode::NotJson => Status::BadRequest,
            APIErrorCode::Unknown => Status::InternalServerError,
            APIErrorCode::UnknownToken => Status::Unauthorized,
        }
    }
}

/// An operator-facing error.
pub struct CLIError {
    error: String,
}

impl CLIError {
    /// Create a new `CLIError` from any `Error` type.
    pub fn new<E>(error: E) -> CLIError where E: Into<String> {
        CLIError {
            error: error.into(),
        }
    }
}

impl<E> From<E> for CLIError where E: Error {
    fn from(error: E) -> CLIError {
        CLIError::new(error.description())
    }
}

impl Display for CLIError {
    fn fmt(&self, f: &mut Formatter) -> Result<(), FmtError> {
        write!(f, "{}", self.error)
    }
}
<|endoftext|>


<commit_before>pub struct Gauge<T> {
    pub value: T
}

impl<T> Gauge<T> {
    pub fn update(&mut self, value: T) {
        self.value = value
    }

    pub fn snapshot(self) -> Gauge<T> {
        Gauge { value: self.value }
    }
}

#[cfg(test)]
mod test {
    use gauge::Gauge;

    #[test]
    fn create_and_snapshot() {
        let g: Gauge<f64> = Gauge {value: 0f64 };
        let mut g_snapshot = g.snapshot();

        g_snapshot.update(10f64);

        assert!(g.value == 0f64);
        assert!(g_snapshot.value == 10f64);
    }
}<commit_msg>Use traits and type specifiable<commit_after>pub struct StdGauge<T> {
    pub value: T
}

pub trait Gauge<T> {
    fn update(&mut self, value: T);
    fn snapshot(self) -> Self;
}

impl<T> Gauge<T> for StdGauge<T> {
    fn update(&mut self, value: T) {
        self.value = value
    }

    fn snapshot(self) -> StdGauge<T> {
        StdGauge { value: self.value }
    }
}

#[cfg(test)]
mod test {
    use gauge::{Gauge,StdGauge};

    #[test]
    fn create_and_snapshot() {
        let g: StdGauge<f64> = StdGauge {value: 0f64 };
        let mut g_snapshot = g.snapshot();

        g_snapshot.update(10f64);

        assert!(g.value == 0f64);
        assert!(g_snapshot.value == 10f64);
    }
}<|endoftext|>


<commit_before>#[cfg(feature = "cmake_build")]
extern crate cmake;
extern crate num_cpus;
extern crate pkg_config;

use std::env;
use std::path::{Path, PathBuf};
use std::process::{self, Command};

fn run_command_or_fail<P>(dir: &str, cmd: P, args: &[&str])
where
    P: AsRef<Path>,
{
    let cmd = cmd.as_ref();
    let cmd = if cmd.components().count() > 1 && cmd.is_relative() {
        // If `cmd` is a relative path (and not a bare command that should be
        // looked up in PATH), absolutize it relative to `dir`, as otherwise the
        // behavior of std::process::Command is undefined.
        // https://github.com/rust-lang/rust/issues/37868
        PathBuf::from(dir)
            .join(cmd)
            .canonicalize()
            .expect("canonicalization failed")
    } else {
        PathBuf::from(cmd)
    };
    eprintln!(
        "Running command: \"{} {}\" in dir: {}",
        cmd.display(),
        args.join(" "),
        dir
    );
    let ret = Command::new(cmd).current_dir(dir).args(args).status();
    match ret.map(|status| (status.success(), status.code())) {
        Ok((true, _)) => return,
        Ok((false, Some(c))) => panic!("Command failed with error code {}", c),
        Ok((false, None)) => panic!("Command got killed"),
        Err(e) => panic!("Command failed with error: {}", e),
    }
}

fn main() {
    let librdkafka_version = env!("CARGO_PKG_VERSION")
        .split('-')
        .next()
        .expect("Crate version is not valid");

    if env::var("CARGO_FEATURE_DYNAMIC_LINKING").is_ok() {
        eprintln!("librdkafka will be linked dynamically");
        let pkg_probe = pkg_config::Config::new()
            .cargo_metadata(true)
            .atleast_version(librdkafka_version)
            .probe("rdkafka");

        match pkg_probe {
            Ok(library) => {
                eprintln!("librdkafka found on the system:");
                eprintln!("  Name: {:?}", library.libs);
                eprintln!("  Path: {:?}", library.link_paths);
                eprintln!("  Version: {}", library.version);
            }
            Err(_) => {
                eprintln!(
                    "librdkafka {} cannot be found on the system",
                    librdkafka_version
                );
                eprintln!("Dynamic linking failed. Exiting.");
                process::exit(1);
            }
        }
    } else {
        if !Path::new("librdkafka/LICENSE").exists() {
            eprintln!("Setting up submodules");
            run_command_or_fail("../", "git", &["submodule", "update", "--init"]);
        }
        eprintln!("Building and linking librdkafka statically");
        build_librdkafka();
    }
}

#[cfg(not(feature = "cmake_build"))]
fn build_librdkafka() {
    let mut configure_flags = Vec::new();

    if env::var("CARGO_FEATURE_SASL").is_ok() {
        configure_flags.push("--enable-sasl");
        println!("cargo:rustc-link-lib=sasl2");
    } else {
        configure_flags.push("--disable-sasl");
    }

    if env::var("CARGO_FEATURE_SSL").is_ok() {
        configure_flags.push("--enable-ssl");
    } else {
        configure_flags.push("--disable-ssl");
    }

    if env::var("CARGO_FEATURE_ZSTD").is_ok() {
        configure_flags.push("--enable-zstd");
        println!("cargo:rustc-link-lib=static=zstd");
    } else {
        configure_flags.push("--disable-zstd");
    }

    if env::var("CARGO_FEATURE_EXTERNAL_LZ4").is_ok() {
        configure_flags.push("--enable-lz4");
        println!("cargo:rustc-link-lib=static=lz4");
    } else {
        configure_flags.push("--disable-lz4");
    }

    println!("Configuring librdkafka");
    run_command_or_fail("librdkafka", "./configure", configure_flags.as_slice());

    println!("Compiling librdkafka");
    make_librdkafka();

    println!(
        "cargo:rustc-link-search=native={}/librdkafka/src",
        env::current_dir()
            .expect("Can't find current dir")
            .display()
    );
    println!("cargo:rustc-link-lib=static=rdkafka");
}

#[cfg(not(feature = "cmake_build"))]
fn make_librdkafka() {
    run_command_or_fail(
        "librdkafka",
        if cfg!(target_os = "freebsd") { "gmake" } else { "make" },
        &["-j", &num_cpus::get().to_string(), "libs"],
    );
}

#[cfg(feature = "cmake_build")]
fn build_librdkafka() {
    env::set_var("NUM_JOBS", num_cpus::get().to_string());
    let mut config = cmake::Config::new("librdkafka");
    config
        .define("RDKAFKA_BUILD_STATIC", "1")
        .build_target("rdkafka");
    if env::var("CARGO_FEATURE_SSL").is_ok() {
        config.define("WITH_SSL", "1");
    } else {
        config.define("WITH_SSL", "0");
    }
    if env::var("CARGO_FEATURE_SASL").is_ok() {
        config.define("WITH_SASL", "1");
    } else {
        config.define("WITH_SASL", "0");
    }
    if env::var("CARGO_FEATURE_ZSTD").is_ok() {
        config.define("WITH_ZSTD", "1");
        config.register_dep("zstd");
        println!("cargo:rustc-link-lib=static=zstd");
    } else {
        config.define("WITH_ZSTD", "0");
    }
    if env::var("CARGO_FEATURE_EXTERNAL_LZ4").is_ok() {
        config.define("ENABLE_LZ4_EXT", "1");
        println!("cargo:rustc-link-lib=static=lz4");
    } else {
        config.define("ENABLE_LZ4_EXT", "0");
    }
    if let Ok(system_name) = env::var("CMAKE_SYSTEM_NAME") {
        config.define("CMAKE_SYSTEM_NAME", system_name);
    }
    let dst = config.build();
    println!("cargo:rustc-link-search=native={}/build/src", dst.display());
    println!("cargo:rustc-link-lib=static=rdkafka");
}
<commit_msg>Support CMake build on MSVC<commit_after>#[cfg(feature = "cmake_build")]
extern crate cmake;
extern crate num_cpus;
extern crate pkg_config;

use std::env;
use std::path::{Path, PathBuf};
use std::process::{self, Command};

fn run_command_or_fail<P>(dir: &str, cmd: P, args: &[&str])
where
    P: AsRef<Path>,
{
    let cmd = cmd.as_ref();
    let cmd = if cmd.components().count() > 1 && cmd.is_relative() {
        // If `cmd` is a relative path (and not a bare command that should be
        // looked up in PATH), absolutize it relative to `dir`, as otherwise the
        // behavior of std::process::Command is undefined.
        // https://github.com/rust-lang/rust/issues/37868
        PathBuf::from(dir)
            .join(cmd)
            .canonicalize()
            .expect("canonicalization failed")
    } else {
        PathBuf::from(cmd)
    };
    eprintln!(
        "Running command: \"{} {}\" in dir: {}",
        cmd.display(),
        args.join(" "),
        dir
    );
    let ret = Command::new(cmd).current_dir(dir).args(args).status();
    match ret.map(|status| (status.success(), status.code())) {
        Ok((true, _)) => return,
        Ok((false, Some(c))) => panic!("Command failed with error code {}", c),
        Ok((false, None)) => panic!("Command got killed"),
        Err(e) => panic!("Command failed with error: {}", e),
    }
}

fn main() {
    let librdkafka_version = env!("CARGO_PKG_VERSION")
        .split('-')
        .next()
        .expect("Crate version is not valid");

    if env::var("CARGO_FEATURE_DYNAMIC_LINKING").is_ok() {
        eprintln!("librdkafka will be linked dynamically");
        let pkg_probe = pkg_config::Config::new()
            .cargo_metadata(true)
            .atleast_version(librdkafka_version)
            .probe("rdkafka");

        match pkg_probe {
            Ok(library) => {
                eprintln!("librdkafka found on the system:");
                eprintln!("  Name: {:?}", library.libs);
                eprintln!("  Path: {:?}", library.link_paths);
                eprintln!("  Version: {}", library.version);
            }
            Err(_) => {
                eprintln!(
                    "librdkafka {} cannot be found on the system",
                    librdkafka_version
                );
                eprintln!("Dynamic linking failed. Exiting.");
                process::exit(1);
            }
        }
    } else {
        if !Path::new("librdkafka/LICENSE").exists() {
            eprintln!("Setting up submodules");
            run_command_or_fail("../", "git", &["submodule", "update", "--init"]);
        }
        eprintln!("Building and linking librdkafka statically");
        build_librdkafka();
    }
}

#[cfg(not(feature = "cmake_build"))]
fn build_librdkafka() {
    let mut configure_flags = Vec::new();

    if env::var("CARGO_FEATURE_SASL").is_ok() {
        configure_flags.push("--enable-sasl");
        println!("cargo:rustc-link-lib=sasl2");
    } else {
        configure_flags.push("--disable-sasl");
    }

    if env::var("CARGO_FEATURE_SSL").is_ok() {
        configure_flags.push("--enable-ssl");
    } else {
        configure_flags.push("--disable-ssl");
    }

    if env::var("CARGO_FEATURE_ZSTD").is_ok() {
        configure_flags.push("--enable-zstd");
        println!("cargo:rustc-link-lib=static=zstd");
    } else {
        configure_flags.push("--disable-zstd");
    }

    if env::var("CARGO_FEATURE_EXTERNAL_LZ4").is_ok() {
        configure_flags.push("--enable-lz4");
        println!("cargo:rustc-link-lib=static=lz4");
    } else {
        configure_flags.push("--disable-lz4");
    }

    println!("Configuring librdkafka");
    run_command_or_fail("librdkafka", "./configure", configure_flags.as_slice());

    println!("Compiling librdkafka");
    make_librdkafka();

    println!(
        "cargo:rustc-link-search=native={}/librdkafka/src",
        env::current_dir()
            .expect("Can't find current dir")
            .display()
    );
    println!("cargo:rustc-link-lib=static=rdkafka");
}

#[cfg(not(feature = "cmake_build"))]
fn make_librdkafka() {
    run_command_or_fail(
        "librdkafka",
        if cfg!(target_os = "freebsd") { "gmake" } else { "make" },
        &["-j", &num_cpus::get().to_string(), "libs"],
    );
}

#[cfg(feature = "cmake_build")]
fn build_librdkafka() {
    env::set_var("NUM_JOBS", num_cpus::get().to_string());
    let mut config = cmake::Config::new("librdkafka");
    config
        .define("RDKAFKA_BUILD_STATIC", "1")
        .build_target("rdkafka");
    if env::var("CARGO_FEATURE_SSL").is_ok() {
        config.define("WITH_SSL", "1");
    } else {
        config.define("WITH_SSL", "0");
    }
    if env::var("CARGO_FEATURE_SASL").is_ok() {
        config.define("WITH_SASL", "1");
    } else {
        config.define("WITH_SASL", "0");
    }
    if env::var("CARGO_FEATURE_ZSTD").is_ok() {
        config.define("WITH_ZSTD", "1");
        config.register_dep("zstd");
        println!("cargo:rustc-link-lib=static=zstd");
    } else {
        config.define("WITH_ZSTD", "0");
    }
    if env::var("CARGO_FEATURE_EXTERNAL_LZ4").is_ok() {
        config.define("ENABLE_LZ4_EXT", "1");
        println!("cargo:rustc-link-lib=static=lz4");
    } else {
        config.define("ENABLE_LZ4_EXT", "0");
    }
    if let Ok(system_name) = env::var("CMAKE_SYSTEM_NAME") {
        config.define("CMAKE_SYSTEM_NAME", system_name);
    }
    let dst = config.build();
    #[cfg(target_env = "msvc")]
    {
        let profile = match &env::var("PROFILE").expect("Cannot determine build profile")[..] {
            "release" | "bench" => "Release",
            _ => "Debug"
        };
        println!("cargo:rustc-link-search=native={}/build/src/{}", dst.display(), profile);
    }
    #[cfg(not(target_env = "msvc"))]
    println!("cargo:rustc-link-search=native={}/build/src", dst.display());
    println!("cargo:rustc-link-lib=static=rdkafka");
}
<|endoftext|>


<commit_before>use super::token::TokenType;
use super::token::Token;

struct Lexer {
    input: String,
    // Current position in input.
    position: usize,
    // Current reading position.
    read_position: usize,
    // Current char under examination.
    ch: char,
}

impl Lexer {
    fn new(input: String) -> Self {
        let mut l = Lexer {
            input: input,
            position: 0,
            read_position: 0,
            ch: '\0',
        };
        l.read_char();
        l
    }

    fn read_char(&mut self) {
        if self.read_position >= self.input.len() {
            self.ch = '\0';
        } else {
            self.ch = self.input.chars().nth(self.read_position).unwrap();
        }
        self.position = self.read_position;
        self.read_position += 1;
    }

    fn peek_char(&mut self) -> char {
        if self.read_position >= self.input.len() {
            return '\0';
        } else {
            return self.input.chars().nth(self.read_position).unwrap();
        }
    }

    fn is_letter(&self, ch: char) -> bool {
        ch.is_alphabetic() || ch == '_' || ch == '?'
    }

    fn read_ident(&mut self) -> String {
        let position = self.position;
        while self.is_letter(self.ch) {
            self.read_char();
        }

        self.input[position..self.position].to_string()
    }

    fn read_number(&mut self) -> String {
        let position = self.position;
        while self.ch.is_digit(10) {
            self.read_char();
        }

        self.input[position..self.position].to_string()
    }

    fn next_token(&mut self) -> Token {
        while self.ch.is_whitespace() {
            self.read_char();
        }

        let tok = match self.ch {
            '=' => {
                if self.peek_char() == '=' {
                    self.read_char();
                    Token::new(TokenType::Eq, "==".to_string())
                } else {
                    Token::new(TokenType::Assign, self.ch.to_string())
                }
            }
            ';' => Token::new(TokenType::Semicolon, self.ch.to_string()),
            '(' => Token::new(TokenType::LeftParen, self.ch.to_string()),
            ')' => Token::new(TokenType::RightParen, self.ch.to_string()),
            ',' => Token::new(TokenType::Comma, self.ch.to_string()),
            '+' => Token::new(TokenType::Plus, self.ch.to_string()),
            '{' => Token::new(TokenType::LeftBrace, self.ch.to_string()),
            '}' => Token::new(TokenType::RightBrace, self.ch.to_string()),
            '!' => {
                if self.peek_char() == '=' {
                    self.read_char();
                    Token::new(TokenType::NotEq, "!=".to_string())
                } else {
                    Token::new(TokenType::Bang, self.ch.to_string())
                }
            }
            '-' => Token::new(TokenType::Minus, self.ch.to_string()),
            '/' => Token::new(TokenType::Slash, self.ch.to_string()),
            '*' => Token::new(TokenType::Asterisk, self.ch.to_string()),
            '<' => Token::new(TokenType::LessThan, self.ch.to_string()),
            '>' => Token::new(TokenType::GreaterThan, self.ch.to_string()),
            '\0' => Token::new(TokenType::EOF, "".to_string()),
            ch @ _ if self.is_letter(ch) => {
                let ident = self.read_ident();
                let tt = TokenType::lookup_ident(&ident);
                return Token::new(tt, ident);
            }
            ch @ _ if ch.is_digit(10) => {
                let literal = self.read_number();
                return Token::new(TokenType::Int, literal);
            }
            _ => Token::new(TokenType::Illegal, self.ch.to_string()),
        };

        self.read_char();
        tok
    }
}

#[test]
fn test_next_token() {
    let input = String::from("let five = 5;
        let ten = 10;
        let add = fn(x, y) {
            x + y;
        };
        let result = add(five, ten);
        !-/*5;
        5 < 10 > 5;

        if (5 < 10) {
            return true;
        } else {
            return false;
        }

        10 == 10;
        10 != 9;
    ");
    let mut lexer = Lexer::new(input);

    let tests = vec![(TokenType::Let, "let"),
                     (TokenType::Ident, "five"),
                     (TokenType::Assign, "="),
                     (TokenType::Int, "5"),
                     (TokenType::Semicolon, ";"),
                     (TokenType::Let, "let"),
                     (TokenType::Ident, "ten"),
                     (TokenType::Assign, "="),
                     (TokenType::Int, "10"),
                     (TokenType::Semicolon, ";"),
                     (TokenType::Let, "let"),
                     (TokenType::Ident, "add"),
                     (TokenType::Assign, "="),
                     (TokenType::Function, "fn"),
                     (TokenType::LeftParen, "("),
                     (TokenType::Ident, "x"),
                     (TokenType::Comma, ","),
                     (TokenType::Ident, "y"),
                     (TokenType::RightParen, ")"),
                     (TokenType::LeftBrace, "{"),
                     (TokenType::Ident, "x"),
                     (TokenType::Plus, "+"),
                     (TokenType::Ident, "y"),
                     (TokenType::Semicolon, ";"),
                     (TokenType::RightBrace, "}"),
                     (TokenType::Semicolon, ";"),
                     (TokenType::Let, "let"),
                     (TokenType::Ident, "result"),
                     (TokenType::Assign, "="),
                     (TokenType::Ident, "add"),
                     (TokenType::LeftParen, "("),
                     (TokenType::Ident, "five"),
                     (TokenType::Comma, ","),
                     (TokenType::Ident, "ten"),
                     (TokenType::RightParen, ")"),
                     (TokenType::Semicolon, ";"),
                     (TokenType::Bang, "!"),
                     (TokenType::Minus, "-"),
                     (TokenType::Slash, "/"),
                     (TokenType::Asterisk, "*"),
                     (TokenType::Int, "5"),
                     (TokenType::Semicolon, ";"),
                     (TokenType::Int, "5"),
                     (TokenType::LessThan, "<"),
                     (TokenType::Int, "10"),
                     (TokenType::GreaterThan, ">"),
                     (TokenType::Int, "5"),
                     (TokenType::Semicolon, ";"),
                     (TokenType::If, "if"),
                     (TokenType::LeftParen, "("),
                     (TokenType::Int, "5"),
                     (TokenType::LessThan, "<"),
                     (TokenType::Int, "10"),
                     (TokenType::RightParen, ")"),
                     (TokenType::LeftBrace, "{"),
                     (TokenType::Return, "return"),
                     (TokenType::True, "true"),
                     (TokenType::Semicolon, ";"),
                     (TokenType::RightBrace, "}"),
                     (TokenType::Else, "else"),
                     (TokenType::LeftBrace, "{"),
                     (TokenType::Return, "return"),
                     (TokenType::False, "false"),
                     (TokenType::Semicolon, ";"),
                     (TokenType::RightBrace, "}"),
                     (TokenType::Int, "10"),
                     (TokenType::Eq, "=="),
                     (TokenType::Int, "10"),
                     (TokenType::Semicolon, ";"),
                     (TokenType::Int, "10"),
                     (TokenType::NotEq, "!="),
                     (TokenType::Int, "9"),
                     (TokenType::Semicolon, ";"),
                     (TokenType::EOF, "")];

    for (i, &(ref expected_type, ref expected_literal)) in tests.iter().enumerate() {
        let tok = lexer.next_token();

        assert!(tok.token_type == *expected_type,
                "Wrong TokenType [{}]. Expected - {:?}, got - {:?}.",
                i,
                expected_type,
                tok.token_type);

        assert!(tok.literal == *expected_literal,
                "Wrong literal [{}]. Expected - {:?}, got - {:?}.",
                i,
                expected_literal,
                tok.literal);
    }
}
<commit_msg>Small refactoring.<commit_after>use super::token::TokenType;
use super::token::Token;

pub struct Lexer {
    input: String,
    // Current position in input.
    position: usize,
    // Current reading position.
    read_position: usize,
    // Current char under examination.
    ch: char,
}

const EOF: char = '\0';

impl Lexer {
    pub fn new(input: String) -> Self {
        let mut l = Lexer {
            input: input,
            position: 0,
            read_position: 0,
            ch: EOF,
        };
        l.read_char();
        l
    }

    fn read_char(&mut self) {
        if self.read_position >= self.input.len() {
            self.ch = EOF;
        } else {
            self.ch = self.input.chars().nth(self.read_position).unwrap();
        }
        self.position = self.read_position;
        self.read_position += 1;
    }

    fn peek_char(&mut self) -> char {
        if self.read_position >= self.input.len() {
            return EOF;
        } else {
            return self.input.chars().nth(self.read_position).unwrap();
        }
    }

    fn is_letter(&self, ch: char) -> bool {
        ch.is_alphabetic() || ch == '_' || ch == '?'
    }

    fn read_ident(&mut self) -> String {
        let position = self.position;
        while self.is_letter(self.ch) {
            self.read_char();
        }

        self.input[position..self.position].to_string()
    }

    fn read_number(&mut self) -> String {
        let position = self.position;
        while self.ch.is_digit(10) {
            self.read_char();
        }

        self.input[position..self.position].to_string()
    }

    pub fn next_token(&mut self) -> Token {
        while self.ch.is_whitespace() {
            self.read_char();
        }

        let tok = match self.ch {
            '=' => {
                if self.peek_char() == '=' {
                    self.read_char();
                    Token::new(TokenType::Eq, "==".to_string())
                } else {
                    Token::new(TokenType::Assign, self.ch.to_string())
                }
            }
            ';' => Token::new(TokenType::Semicolon, self.ch.to_string()),
            '(' => Token::new(TokenType::LeftParen, self.ch.to_string()),
            ')' => Token::new(TokenType::RightParen, self.ch.to_string()),
            ',' => Token::new(TokenType::Comma, self.ch.to_string()),
            '+' => Token::new(TokenType::Plus, self.ch.to_string()),
            '{' => Token::new(TokenType::LeftBrace, self.ch.to_string()),
            '}' => Token::new(TokenType::RightBrace, self.ch.to_string()),
            '!' => {
                if self.peek_char() == '=' {
                    self.read_char();
                    Token::new(TokenType::NotEq, "!=".to_string())
                } else {
                    Token::new(TokenType::Bang, self.ch.to_string())
                }
            }
            '-' => Token::new(TokenType::Minus, self.ch.to_string()),
            '/' => Token::new(TokenType::Slash, self.ch.to_string()),
            '*' => Token::new(TokenType::Asterisk, self.ch.to_string()),
            '<' => Token::new(TokenType::LessThan, self.ch.to_string()),
            '>' => Token::new(TokenType::GreaterThan, self.ch.to_string()),
            EOF => Token::new(TokenType::EOF, "".to_string()),
            ch @ _ if self.is_letter(ch) => {
                let ident = self.read_ident();
                let tt = TokenType::lookup_ident(&ident);
                return Token::new(tt, ident);
            }
            ch @ _ if ch.is_digit(10) => {
                let literal = self.read_number();
                return Token::new(TokenType::Int, literal);
            }
            _ => Token::new(TokenType::Illegal, self.ch.to_string()),
        };

        self.read_char();
        tok
    }
}

#[test]
fn test_next_token() {
    let input = String::from("let five = 5;
        let ten = 10;
        let add = fn(x, y) {
            x + y;
        };
        let result = add(five, ten);
        !-/*5;
        5 < 10 > 5;

        if (5 < 10) {
            return true;
        } else {
            return false;
        }

        10 == 10;
        10 != 9;
    ");
    let mut lexer = Lexer::new(input);

    let tests = vec![(TokenType::Let, "let"),
                     (TokenType::Ident, "five"),
                     (TokenType::Assign, "="),
                     (TokenType::Int, "5"),
                     (TokenType::Semicolon, ";"),
                     (TokenType::Let, "let"),
                     (TokenType::Ident, "ten"),
                     (TokenType::Assign, "="),
                     (TokenType::Int, "10"),
                     (TokenType::Semicolon, ";"),
                     (TokenType::Let, "let"),
                     (TokenType::Ident, "add"),
                     (TokenType::Assign, "="),
                     (TokenType::Function, "fn"),
                     (TokenType::LeftParen, "("),
                     (TokenType::Ident, "x"),
                     (TokenType::Comma, ","),
                     (TokenType::Ident, "y"),
                     (TokenType::RightParen, ")"),
                     (TokenType::LeftBrace, "{"),
                     (TokenType::Ident, "x"),
                     (TokenType::Plus, "+"),
                     (TokenType::Ident, "y"),
                     (TokenType::Semicolon, ";"),
                     (TokenType::RightBrace, "}"),
                     (TokenType::Semicolon, ";"),
                     (TokenType::Let, "let"),
                     (TokenType::Ident, "result"),
                     (TokenType::Assign, "="),
                     (TokenType::Ident, "add"),
                     (TokenType::LeftParen, "("),
                     (TokenType::Ident, "five"),
                     (TokenType::Comma, ","),
                     (TokenType::Ident, "ten"),
                     (TokenType::RightParen, ")"),
                     (TokenType::Semicolon, ";"),
                     (TokenType::Bang, "!"),
                     (TokenType::Minus, "-"),
                     (TokenType::Slash, "/"),
                     (TokenType::Asterisk, "*"),
                     (TokenType::Int, "5"),
                     (TokenType::Semicolon, ";"),
                     (TokenType::Int, "5"),
                     (TokenType::LessThan, "<"),
                     (TokenType::Int, "10"),
                     (TokenType::GreaterThan, ">"),
                     (TokenType::Int, "5"),
                     (TokenType::Semicolon, ";"),
                     (TokenType::If, "if"),
                     (TokenType::LeftParen, "("),
                     (TokenType::Int, "5"),
                     (TokenType::LessThan, "<"),
                     (TokenType::Int, "10"),
                     (TokenType::RightParen, ")"),
                     (TokenType::LeftBrace, "{"),
                     (TokenType::Return, "return"),
                     (TokenType::True, "true"),
                     (TokenType::Semicolon, ";"),
                     (TokenType::RightBrace, "}"),
                     (TokenType::Else, "else"),
                     (TokenType::LeftBrace, "{"),
                     (TokenType::Return, "return"),
                     (TokenType::False, "false"),
                     (TokenType::Semicolon, ";"),
                     (TokenType::RightBrace, "}"),
                     (TokenType::Int, "10"),
                     (TokenType::Eq, "=="),
                     (TokenType::Int, "10"),
                     (TokenType::Semicolon, ";"),
                     (TokenType::Int, "10"),
                     (TokenType::NotEq, "!="),
                     (TokenType::Int, "9"),
                     (TokenType::Semicolon, ";"),
                     (TokenType::EOF, "")];

    for (i, &(ref expected_type, ref expected_literal)) in tests.iter().enumerate() {
        let tok = lexer.next_token();

        assert!(tok.token_type == *expected_type,
                "Wrong TokenType [{}]. Expected - {:?}, got - {:?}.",
                i,
                expected_type,
                tok.token_type);

        assert!(tok.literal == *expected_literal,
                "Wrong literal [{}]. Expected - {:?}, got - {:?}.",
                i,
                expected_literal,
                tok.literal);
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::HTMLCollectionBinding;
use dom::bindings::js::JS;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::element::Element;
use dom::window::Window;
use servo_util::str::DOMString;

#[deriving(Encodable)]
pub struct HTMLCollection {
    elements: ~[JS<Element>],
    reflector_: Reflector,
    window: JS<Window>,
}

impl HTMLCollection {
    pub fn new_inherited(window: JS<Window>, elements: ~[JS<Element>]) -> HTMLCollection {
        HTMLCollection {
            elements: elements,
            reflector_: Reflector::new(),
            window: window,
        }
    }

    pub fn new(window: &JS<Window>, elements: ~[JS<Element>]) -> JS<HTMLCollection> {
        reflect_dom_object(~HTMLCollection::new_inherited(window.clone(), elements),
                           window, HTMLCollectionBinding::Wrap)
    }
}

impl HTMLCollection {
    // http://dom.spec.whatwg.org/#dom-htmlcollection-length
    pub fn Length(&self) -> u32 {
        self.elements.len() as u32
    }

    // http://dom.spec.whatwg.org/#dom-htmlcollection-item
    pub fn Item(&self, index: u32) -> Option<JS<Element>> {
        if index < self.Length() {
            Some(self.elements[index].clone())
        } else {
            None
        }
    }

    // http://dom.spec.whatwg.org/#dom-htmlcollection-nameditem
    pub fn NamedItem(&self, key: DOMString) -> Option<JS<Element>> {
        // Step 1.
        if key.is_empty() {
            return None;
        }

        // Step 2.
        self.elements.iter().find(|elem| {
            let elem = elem.get();
            elem.get_string_attribute("name") == key || elem.get_string_attribute("id") == key
        }).map(|maybe_elem| maybe_elem.clone())
    }
}

impl HTMLCollection {
    pub fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<JS<Element>> {
        let maybe_elem = self.Item(index);
        *found = maybe_elem.is_some();
        maybe_elem
    }

    pub fn NamedGetter(&self, maybe_name: Option<DOMString>, found: &mut bool) -> Option<JS<Element>> {
        match maybe_name {
            Some(name) => {
                let maybe_elem = self.NamedItem(name);
                *found = maybe_elem.is_some();
                maybe_elem
            },
            None => {
                *found = false;
                None
            }
        }
    }
}

impl Reflectable for HTMLCollection {
    fn reflector<'a>(&'a self) -> &'a Reflector {
        &self.reflector_
    }

    fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector {
        &mut self.reflector_
    }
}
<commit_msg>Added HTMLCollection::create<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::InheritTypes::{ElementCast};
use dom::bindings::codegen::HTMLCollectionBinding;
use dom::bindings::js::JS;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::element::Element;
use dom::node::{Node, NodeHelpers};
use dom::window::Window;
use servo_util::str::DOMString;

#[deriving(Encodable)]
pub struct HTMLCollection {
    elements: ~[JS<Element>],
    reflector_: Reflector,
    window: JS<Window>,
}

impl HTMLCollection {
    pub fn new_inherited(window: JS<Window>, elements: ~[JS<Element>]) -> HTMLCollection {
        HTMLCollection {
            elements: elements,
            reflector_: Reflector::new(),
            window: window,
        }
    }

    pub fn new(window: &JS<Window>, elements: ~[JS<Element>]) -> JS<HTMLCollection> {
        reflect_dom_object(~HTMLCollection::new_inherited(window.clone(), elements),
                           window, HTMLCollectionBinding::Wrap)
    }
}

impl HTMLCollection {
    pub fn create(window: &JS<Window>, root: &JS<Node>, predicate: |elem: &JS<Element>| -> bool) -> JS<HTMLCollection> {
        let mut elements = ~[];
        for child in root.traverse_preorder() {
            if child.is_element() {
                let elem: JS<Element> = ElementCast::to(&child);
                if predicate(&elem) {
                    elements.push(elem);
                }
            }
        }
        HTMLCollection::new(window, elements)
    }
}

impl HTMLCollection {
    // http://dom.spec.whatwg.org/#dom-htmlcollection-length
    pub fn Length(&self) -> u32 {
        self.elements.len() as u32
    }

    // http://dom.spec.whatwg.org/#dom-htmlcollection-item
    pub fn Item(&self, index: u32) -> Option<JS<Element>> {
        if index < self.Length() {
            Some(self.elements[index].clone())
        } else {
            None
        }
    }

    // http://dom.spec.whatwg.org/#dom-htmlcollection-nameditem
    pub fn NamedItem(&self, key: DOMString) -> Option<JS<Element>> {
        // Step 1.
        if key.is_empty() {
            return None;
        }

        // Step 2.
        self.elements.iter().find(|elem| {
            let elem = elem.get();
            elem.get_string_attribute("name") == key || elem.get_string_attribute("id") == key
        }).map(|maybe_elem| maybe_elem.clone())
    }
}

impl HTMLCollection {
    pub fn IndexedGetter(&self, index: u32, found: &mut bool) -> Option<JS<Element>> {
        let maybe_elem = self.Item(index);
        *found = maybe_elem.is_some();
        maybe_elem
    }

    pub fn NamedGetter(&self, maybe_name: Option<DOMString>, found: &mut bool) -> Option<JS<Element>> {
        match maybe_name {
            Some(name) => {
                let maybe_elem = self.NamedItem(name);
                *found = maybe_elem.is_some();
                maybe_elem
            },
            None => {
                *found = false;
                None
            }
        }
    }
}

impl Reflectable for HTMLCollection {
    fn reflector<'a>(&'a self) -> &'a Reflector {
        &self.reflector_
    }

    fn mut_reflector<'a>(&'a mut self) -> &'a mut Reflector {
        &mut self.reflector_
    }
}
<|endoftext|>


<commit_before>// https://leetcode.com/problems/length-of-the-longest-alphabetical-continuous-substring/
pub fn longest_continuous_substring(s: String) -> i32 {
    todo!()
}

fn main() {
    println!("{}", longest_continuous_substring("abacaba".to_string())); // 2
    println!("{}", longest_continuous_substring("abcde".to_string())); // 5
    println!(
        "{}",
        longest_continuous_substring("xyziabcdefmnrvx".to_string())
    ); // 6
}
<commit_msg>Solve problem 2414<commit_after>// https://leetcode.com/problems/length-of-the-longest-alphabetical-continuous-substring/
pub fn longest_continuous_substring(s: String) -> i32 {
    let mut answer = 1;
    let bytes = s.as_bytes();
    let mut length = 1;
    for i in 0..bytes.len() - 1 {
        if bytes[i] + 1 == bytes[i + 1] {
            length += 1;
        } else {
            length = 1;
        }
        answer = answer.max(length);
    }
    answer
}

fn main() {
    println!("{}", longest_continuous_substring("abacaba".to_string())); // 2
    println!("{}", longest_continuous_substring("abcde".to_string())); // 5
    println!(
        "{}",
        longest_continuous_substring("xyziabcdefmnrvx".to_string())
    ); // 6
    println!(
        "{}",
        longest_continuous_substring("abcdefghijklmnopqrstuvwxyz".to_string())
    ); // 26
}
<|endoftext|>


<commit_before>use std::io::Read;
use std::cell::RefCell;

use hyper::Client;
use hyper::client::RequestBuilder;
use hyper::method::Method;
use hyper::header::{Headers, Authorization, Bearer};
use super::region::Region;
use super::auth::Token;

/// a commercetools client
pub struct CtpClient {
    api_url: String,
    auth_url: String,
    project_key: String,
    client_id: String,
    client_secret: String,
    client: Client,
    token: RefCell<Option<Token>>,
}

impl CtpClient {
    /// Returns a commercetools client for the given arguments
    ///
    /// # Arguments
    ///
    /// * `region` - the world region the client should use
    /// * `project_key` - project key
    /// * `client_id` - client id
    /// * `client_secret` - client secret
    ///
    /// # Examples
    ///
    /// ```
    /// use commercetools::region::Region;
    /// use commercetools::client::CtpClient;
    ///
    /// let client = CtpClient::new(&Region::Europe, "my project key", "my client id", "my client secret");
    /// ```
    pub fn new(region: &Region, project_key: &str, client_id: &str, client_secret: &str) -> CtpClient {
        CtpClient {
            api_url: region.api_url().to_string(),
            auth_url: region.auth_url().to_string(),
            project_key: project_key.to_string(),
            client_id: client_id.to_string(),
            client_secret: client_secret.to_string(),
            client: Client::new(),
            token: RefCell::new(None),
        }
    }

    // TODO (YaSi): avoid cloning the String on each call
    pub fn get_token(&self) -> String {
        let mut cache = self.token.borrow_mut();
        if cache.is_some() {
            let token = cache.as_ref().unwrap();
            if token.is_valid() {
                return token.access_token.clone();
            }
        }

        let new_token = super::auth::retrieve_token(&self.client,
                                                    &self.auth_url,
                                                    &self.project_key,
                                                    &self.client_id,
                                                    &self.client_secret)
            .unwrap();

        *cache = Some(new_token.clone());
        new_token.access_token
    }

    pub fn get(&self, uri: &str) -> String {
        send(self.request(Method::Get, uri))
    }

    pub fn post(&self, uri: &str, body: &str) -> String {
        send(self.request(Method::Post, uri).body(body))
    }

    // TODO: this method "leaks" hyper RequestBuilder
    pub fn request(&self, method: Method, uri: &str) -> RequestBuilder {
        let client = &self.client;

        let access_token = self.get_token();

        let mut headers = Headers::new();
        headers.set(Authorization(Bearer { token: access_token }));

        let uri = format!("{}/{}{}", self.api_url, self.project_key, uri);
        client.request(method, &uri)
            .headers(headers)
    }
}

fn send(r: RequestBuilder) -> String {
    let mut projets_res = r.send()
        .unwrap();

    let mut body = String::new();
    projets_res.read_to_string(&mut body).unwrap();
    body
}
<commit_msg>avoid String copy<commit_after>use std::io::Read;
use std::cell::RefCell;

use hyper::Client;
use hyper::client::RequestBuilder;
use hyper::method::Method;
use hyper::header::{Headers, Authorization, Bearer};
use super::region::Region;
use super::auth::Token;

/// a commercetools client
pub struct CtpClient<'a> {
    api_url: &'a str,
    auth_url: &'a str,
    project_key: &'a str,
    client_id: &'a str,
    client_secret: &'a str,
    client: Client,
    token: RefCell<Option<Token>>,
}

impl<'a> CtpClient<'a> {
    /// Returns a commercetools client for the given arguments
    ///
    /// # Arguments
    ///
    /// * `region` - the world region the client should use
    /// * `project_key` - project key
    /// * `client_id` - client id
    /// * `client_secret` - client secret
    ///
    /// # Examples
    ///
    /// ```
    /// use commercetools::region::Region;
    /// use commercetools::client::CtpClient;
    ///
    /// let region = Region::Europe;
    /// let client = CtpClient::new(&region, "my project key", "my client id", "my client secret");
    /// ```
    pub fn new(region: &'a Region, project_key: &'a str, client_id: &'a str, client_secret: &'a str) -> CtpClient<'a> {
        CtpClient {
            api_url: region.api_url(),
            auth_url: region.auth_url(),
            project_key: project_key,
            client_id: client_id,
            client_secret: client_secret,
            client: Client::new(),
            token: RefCell::new(None),
        }
    }

    // TODO (YaSi): avoid cloning the String on each call
    pub fn get_token(&self) -> String {
        let mut cache = self.token.borrow_mut();
        if cache.is_some() {
            let token = cache.as_ref().unwrap();
            if token.is_valid() {
                return token.access_token.clone();
            }
        }

        let new_token = super::auth::retrieve_token(&self.client,
                                                    self.auth_url,
                                                    self.project_key,
                                                    self.client_id,
                                                    self.client_secret)
            .unwrap();

        *cache = Some(new_token.clone());
        new_token.access_token
    }

    pub fn get(&self, uri: &str) -> String {
        send(self.request(Method::Get, uri))
    }

    pub fn post(&self, uri: &str, body: &str) -> String {
        send(self.request(Method::Post, uri).body(body))
    }

    // TODO: this method "leaks" hyper RequestBuilder
    pub fn request(&self, method: Method, uri: &str) -> RequestBuilder {
        let client = &self.client;

        let access_token = self.get_token();

        let mut headers = Headers::new();
        headers.set(Authorization(Bearer { token: access_token }));

        let uri = format!("{}/{}{}", self.api_url, self.project_key, uri);
        client.request(method, &uri)
            .headers(headers)
    }
}

fn send(r: RequestBuilder) -> String {
    let mut projets_res = r.send()
        .unwrap();

    let mut body = String::new();
    projets_res.read_to_string(&mut body).unwrap();
    body
}
<|endoftext|>


<commit_before>// Run with `rust run hello.rs`

fn greeter(greeting_text: &str) {
    println(fmt!("Hello %s!", greeting_text));
}

fn main() {
    greeter("World");
}
<commit_msg>Make Rust example work in post-rust-1.0 world<commit_after>// compile with `rustc hello.rs`
// run with `./hello`

fn greeter(greeting_text: &str) {
    println!("Hello {}!", greeting_text);
}

fn main() {
    greeter("World");
}
<|endoftext|>


<commit_before>#![allow(non_snake_case)]

use std::os::raw::c_void;
use std::path::Path;

use cgmath::{vec2, vec3};
use gl;
use image;
use image::DynamicImage::*;
use image::GenericImage;
use tobj;

use mesh::{ Mesh, Texture, Vertex };

#[derive(Default)]
pub struct Model {
    /*  Model Data */
    textures_loaded: Vec<Texture>,   // stores all the textures loaded so far, optimization to make sure textures aren't loaded more than once.
    pub meshes: Vec<Mesh>,
    directory: String,
}

impl Model {
    /// constructor, expects a filepath to a 3D model.
    pub fn new(path: &str, gamma: bool) -> Model {
        let mut model = Model::default();
        model.loadModel(path);
        model
    }

    // loads a model from file and stores the resulting meshes in the meshes vector.
    fn loadModel(&mut self, path: &str) {
        let path = Path::new(path);

        // retrieve the directory path of the filepath
        self.directory = path.parent().unwrap_or(Path::new("")).to_str().unwrap().into();

        let obj = tobj::load_obj(path);

        let (models, materials) = obj.unwrap(); // TODO: better error handling?
        for model in models {
            let mesh = &model.mesh;
            let num_vertices = mesh.positions.len() / 3;

            // data to fill
            let mut vertices: Vec<Vertex> = Vec::with_capacity(num_vertices);
            let indices: Vec<u32> = mesh.indices.clone();

            let (p, n, t) = (&mesh.positions, &mesh.normals, &mesh.texcoords);
            for i in 0..num_vertices {
                vertices.push(Vertex {
                    Position:  vec3(p[i*3], p[i*3+1], p[i*3+2]),
                    Normal:    vec3(n[i*3], n[i*3+1], n[i*3+2]),
                    TexCoords: vec2(t[i*2], t[i*2+1]),
                    ..Vertex::default()
                })
            }

            // process material
            let mut textures = Vec::new();
            if let Some(material_id) = mesh.material_id {
                let material = &materials[material_id];

                // 1. diffuse map
                if !material.diffuse_texture.is_empty() {
                    let texture = self.loadMaterialTexture(&material.diffuse_texture, "texture_diffuse");
                    textures.push(texture);
                }
                // 2. specular map
                if !material.specular_texture.is_empty() {
                    let texture = self.loadMaterialTexture(&material.specular_texture, "texture_specular");
                    textures.push(texture);
                }
                // 3. normal map
                if !material.normal_texture.is_empty() {
                    let texture = self.loadMaterialTexture(&material.normal_texture, "texture_normal");
                    textures.push(texture);
                }
                // NOTE: no height maps
            }

            self.meshes.push(Mesh::new(vertices, indices, textures));
        }

    }

    fn loadMaterialTexture(&self, path: &str, typeName: &str) -> Texture {
        // TODO: do skip check?
        Texture {
            id: unsafe { TextureFromFile(path, &self.directory) },
            type_: typeName.into(),
            path: path.into()
        }
    }
}

unsafe fn TextureFromFile(path: &str, directory: &str) -> u32 {
    let filename = format!("{}/{}", directory, path);

    let mut textureID = 0;
    gl::GenTextures(1, &mut textureID);

    let img = image::open(&Path::new(&filename)).expect("Texture failed to load");
    let format = match img {
        ImageLuma8(_) => gl::RED,
        ImageLumaA8(_) => gl::RG,
        ImageRgb8(_) => gl::RGB,
        ImageRgba8(_) => gl::RGBA,
    };

    let data = img.raw_pixels();

    gl::BindTexture(gl::TEXTURE_2D, textureID);
    gl::TexImage2D(gl::TEXTURE_2D, 0, format as i32, img.width() as i32, img.height() as i32,
        0, format, gl::UNSIGNED_BYTE, &data[0] as *const u8 as *const c_void);
    gl::GenerateMipmap(gl::TEXTURE_2D);

    gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::REPEAT as i32);
    gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::REPEAT as i32);
    gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR_MIPMAP_LINEAR as i32);
    gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as i32);

    textureID
}
<commit_msg>finish model (?)<commit_after>#![allow(non_snake_case)]

use std::os::raw::c_void;
use std::path::Path;

use cgmath::{vec2, vec3};
use gl;
use image;
use image::DynamicImage::*;
use image::GenericImage;
use tobj;

use mesh::{ Mesh, Texture, Vertex };
use shader::Shader;

#[derive(Default)]
pub struct Model {
    /*  Model Data */
    // TODO!: implement?
    // textures_loaded: Vec<Texture>,   // stores all the textures loaded so far, optimization to make sure textures aren't loaded more than once.
    pub meshes: Vec<Mesh>,
    directory: String,
}

impl Model {
    /// constructor, expects a filepath to a 3D model.
    pub fn new(path: &str) -> Model {
        let mut model = Model::default();
        model.loadModel(path);
        model
    }

    pub fn Draw(&self, shader: &Shader) {
        for mesh in &self.meshes {
            unsafe { mesh.Draw(shader); }
        }
    }

    // loads a model from file and stores the resulting meshes in the meshes vector.
    fn loadModel(&mut self, path: &str) {
        let path = Path::new(path);

        // retrieve the directory path of the filepath
        self.directory = path.parent().unwrap_or(Path::new("")).to_str().unwrap().into();

        let obj = tobj::load_obj(path);

        let (models, materials) = obj.unwrap(); // TODO: better error handling?
        for model in models {
            let mesh = &model.mesh;
            let num_vertices = mesh.positions.len() / 3;

            // data to fill
            let mut vertices: Vec<Vertex> = Vec::with_capacity(num_vertices);
            let indices: Vec<u32> = mesh.indices.clone();

            let (p, n, t) = (&mesh.positions, &mesh.normals, &mesh.texcoords);
            for i in 0..num_vertices {
                vertices.push(Vertex {
                    Position:  vec3(p[i*3], p[i*3+1], p[i*3+2]),
                    Normal:    vec3(n[i*3], n[i*3+1], n[i*3+2]),
                    TexCoords: vec2(t[i*2], t[i*2+1]),
                    ..Vertex::default()
                })
            }

            // process material
            let mut textures = Vec::new();
            if let Some(material_id) = mesh.material_id {
                let material = &materials[material_id];

                // 1. diffuse map
                if !material.diffuse_texture.is_empty() {
                    let texture = self.loadMaterialTexture(&material.diffuse_texture, "texture_diffuse");
                    textures.push(texture);
                }
                // 2. specular map
                if !material.specular_texture.is_empty() {
                    let texture = self.loadMaterialTexture(&material.specular_texture, "texture_specular");
                    textures.push(texture);
                }
                // 3. normal map
                if !material.normal_texture.is_empty() {
                    let texture = self.loadMaterialTexture(&material.normal_texture, "texture_normal");
                    textures.push(texture);
                }
                // NOTE: no height maps
            }

            self.meshes.push(Mesh::new(vertices, indices, textures));
        }

    }

    fn loadMaterialTexture(&self, path: &str, typeName: &str) -> Texture {
        // TODO: do skip check?
        Texture {
            id: unsafe { TextureFromFile(path, &self.directory) },
            type_: typeName.into(),
            path: path.into()
        }
    }
}

unsafe fn TextureFromFile(path: &str, directory: &str) -> u32 {
    let filename = format!("{}/{}", directory, path);

    let mut textureID = 0;
    gl::GenTextures(1, &mut textureID);

    let img = image::open(&Path::new(&filename)).expect("Texture failed to load");
    let format = match img {
        ImageLuma8(_) => gl::RED,
        ImageLumaA8(_) => gl::RG,
        ImageRgb8(_) => gl::RGB,
        ImageRgba8(_) => gl::RGBA,
    };

    let data = img.raw_pixels();

    gl::BindTexture(gl::TEXTURE_2D, textureID);
    gl::TexImage2D(gl::TEXTURE_2D, 0, format as i32, img.width() as i32, img.height() as i32,
        0, format, gl::UNSIGNED_BYTE, &data[0] as *const u8 as *const c_void);
    gl::GenerateMipmap(gl::TEXTURE_2D);

    gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::REPEAT as i32);
    gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::REPEAT as i32);
    gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR_MIPMAP_LINEAR as i32);
    gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as i32);

    textureID
}
<|endoftext|>