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

use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc_errors::Applicability;
use crate::syntax::ast::*;
use crate::syntax::parse::{parser, token};
use crate::syntax::tokenstream::{ThinTokenStream, TokenStream};
use crate::utils::{snippet_with_applicability, span_lint, span_lint_and_sugg};
use std::borrow::Cow;

/// **What it does:** This lint warns when you use `println!("")` to
/// print a newline.
///
/// **Why is this bad?** You should use `println!()`, which is simpler.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// println!("");
/// ```
declare_clippy_lint! {
    pub PRINTLN_EMPTY_STRING,
    style,
    "using `println!(\"\")` with an empty string"
}

/// **What it does:** This lint warns when you use `print!()` with a format
/// string that
/// ends in a newline.
///
/// **Why is this bad?** You should use `println!()` instead, which appends the
/// newline.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// print!("Hello {}!\n", name);
/// ```
/// use println!() instead
/// ```rust
/// println!("Hello {}!", name);
/// ```
declare_clippy_lint! {
    pub PRINT_WITH_NEWLINE,
    style,
    "using `print!()` with a format string that ends in a single newline"
}

/// **What it does:** Checks for printing on *stdout*. The purpose of this lint
/// is to catch debugging remnants.
///
/// **Why is this bad?** People often print on *stdout* while debugging an
/// application and might forget to remove those prints afterward.
///
/// **Known problems:** Only catches `print!` and `println!` calls.
///
/// **Example:**
/// ```rust
/// println!("Hello world!");
/// ```
declare_clippy_lint! {
    pub PRINT_STDOUT,
    restriction,
    "printing on stdout"
}

/// **What it does:** Checks for use of `Debug` formatting. The purpose of this
/// lint is to catch debugging remnants.
///
/// **Why is this bad?** The purpose of the `Debug` trait is to facilitate
/// debugging Rust code. It should not be used in in user-facing output.
///
/// **Example:**
/// ```rust
/// println!("{:?}", foo);
/// ```
declare_clippy_lint! {
    pub USE_DEBUG,
    restriction,
    "use of `Debug`-based formatting"
}

/// **What it does:** This lint warns about the use of literals as `print!`/`println!` args.
///
/// **Why is this bad?** Using literals as `println!` args is inefficient
/// (c.f., https://github.com/matthiaskrgr/rust-str-bench) and unnecessary
/// (i.e., just put the literal in the format string)
///
/// **Known problems:** Will also warn with macro calls as arguments that expand to literals
/// -- e.g., `println!("{}", env!("FOO"))`.
///
/// **Example:**
/// ```rust
/// println!("{}", "foo");
/// ```
/// use the literal without formatting:
/// ```rust
/// println!("foo");
/// ```
declare_clippy_lint! {
    pub PRINT_LITERAL,
    style,
    "printing a literal with a format string"
}

/// **What it does:** This lint warns when you use `writeln!(buf, "")` to
/// print a newline.
///
/// **Why is this bad?** You should use `writeln!(buf)`, which is simpler.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// writeln!("");
/// ```
declare_clippy_lint! {
    pub WRITELN_EMPTY_STRING,
    style,
    "using `writeln!(\"\")` with an empty string"
}

/// **What it does:** This lint warns when you use `write!()` with a format
/// string that
/// ends in a newline.
///
/// **Why is this bad?** You should use `writeln!()` instead, which appends the
/// newline.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// write!(buf, "Hello {}!\n", name);
/// ```
declare_clippy_lint! {
    pub WRITE_WITH_NEWLINE,
    style,
    "using `write!()` with a format string that ends in a single newline"
}

/// **What it does:** This lint warns about the use of literals as `write!`/`writeln!` args.
///
/// **Why is this bad?** Using literals as `writeln!` args is inefficient
/// (c.f., https://github.com/matthiaskrgr/rust-str-bench) and unnecessary
/// (i.e., just put the literal in the format string)
///
/// **Known problems:** Will also warn with macro calls as arguments that expand to literals
/// -- e.g., `writeln!(buf, "{}", env!("FOO"))`.
///
/// **Example:**
/// ```rust
/// writeln!(buf, "{}", "foo");
/// ```
declare_clippy_lint! {
    pub WRITE_LITERAL,
    style,
    "writing a literal with a format string"
}

#[derive(Copy, Clone, Debug)]
pub struct Pass;

impl LintPass for Pass {
    fn get_lints(&self) -> LintArray {
        lint_array!(
            PRINT_WITH_NEWLINE,
            PRINTLN_EMPTY_STRING,
            PRINT_STDOUT,
            USE_DEBUG,
            PRINT_LITERAL,
            WRITE_WITH_NEWLINE,
            WRITELN_EMPTY_STRING,
            WRITE_LITERAL
        )
    }
}

impl EarlyLintPass for Pass {
    fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &Mac) {
        if mac.node.path == "println" {
            span_lint(cx, PRINT_STDOUT, mac.span, "use of `println!`");
            if let Some(fmtstr) = check_tts(cx, &mac.node.tts, false).0 {
                if fmtstr == "" {
                    span_lint_and_sugg(
                        cx,
                        PRINTLN_EMPTY_STRING,
                        mac.span,
                        "using `println!(\"\")`",
                        "replace it with",
                        "println!()".to_string(),
                        Applicability::MachineApplicable,
                    );
                }
            }
        } else if mac.node.path == "print" {
            span_lint(cx, PRINT_STDOUT, mac.span, "use of `print!`");
            if let Some(fmtstr) = check_tts(cx, &mac.node.tts, false).0 {
                if fmtstr.ends_with("\\n") &&
                   // don't warn about strings with several `\n`s (#3126)
                   fmtstr.matches("\\n").count() == 1
                {
                    span_lint(
                        cx,
                        PRINT_WITH_NEWLINE,
                        mac.span,
                        "using `print!()` with a format string that ends in a \
                         single newline, consider using `println!()` instead",
                    );
                }
            }
        } else if mac.node.path == "write" {
            if let Some(fmtstr) = check_tts(cx, &mac.node.tts, true).0 {
                if fmtstr.ends_with("\\n") &&
                   // don't warn about strings with several `\n`s (#3126)
                   fmtstr.matches("\\n").count() == 1
                {
                    span_lint(
                        cx,
                        WRITE_WITH_NEWLINE,
                        mac.span,
                        "using `write!()` with a format string that ends in a \
                         single newline, consider using `writeln!()` instead",
                    );
                }
            }
        } else if mac.node.path == "writeln" {
            let check_tts = check_tts(cx, &mac.node.tts, true);
            if let Some(fmtstr) = check_tts.0 {
                if fmtstr == "" {
                    let mut applicability = Applicability::MachineApplicable;
                    let suggestion = check_tts.1.map_or_else(
                        move || {
                            applicability = Applicability::HasPlaceholders;
                            Cow::Borrowed("v")
                        },
                        move |expr| snippet_with_applicability(cx, expr.span, "v", &mut applicability),
                    );

                    span_lint_and_sugg(
                        cx,
                        WRITELN_EMPTY_STRING,
                        mac.span,
                        format!("using `writeln!({}, \"\")`", suggestion).as_str(),
                        "replace it with",
                        format!("writeln!({})", suggestion),
                        applicability,
                    );
                }
            }
        }
    }
}

/// Checks the arguments of `print[ln]!` and `write[ln]!` calls. It will return a tuple of two
/// options. The first part of the tuple is format_str of the macros. The secund part of the tuple
/// is in the `write[ln]!` case the expression the format_str should be written to.
///
/// Example:
///
/// Calling this function on
/// ```rust,ignore
/// writeln!(buf, "string to write: {}", something)
/// ```
/// will return
/// ```rust,ignore
/// (Some("string to write: {}"), Some(buf))
/// ```
fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) -> (Option<String>, Option<Expr>) {
    use crate::fmt_macros::*;
    let tts = TokenStream::from(tts.clone());
    let mut parser = parser::Parser::new(&cx.sess.parse_sess, tts, None, false, false);
    let mut expr: Option<Expr> = None;
    if is_write {
        expr = match parser.parse_expr().map_err(|mut err| err.cancel()) {
            Ok(p) => Some(p.into_inner()),
            Err(_) => return (None, None),
        };
        // might be `writeln!(foo)`
        if parser.expect(&token::Comma).map_err(|mut err| err.cancel()).is_err() {
            return (None, expr);
        }
    }

    let fmtstr = match parser.parse_str().map_err(|mut err| err.cancel()) {
        Ok(token) => token.0.to_string(),
        Err(_) => return (None, expr),
    };
    let tmp = fmtstr.clone();
    let mut args = vec![];
    let mut fmt_parser = Parser::new(&tmp, None);
    while let Some(piece) = fmt_parser.next() {
        if !fmt_parser.errors.is_empty() {
            return (None, expr);
        }
        if let Piece::NextArgument(arg) = piece {
            if arg.format.ty == "?" {
                // FIXME: modify rustc's fmt string parser to give us the current span
                span_lint(cx, USE_DEBUG, parser.prev_span, "use of `Debug`-based formatting");
            }
            args.push(arg);
        }
    }
    let lint = if is_write { WRITE_LITERAL } else { PRINT_LITERAL };
    let mut idx = 0;
    loop {
        const SIMPLE: FormatSpec<'_> = FormatSpec {
            fill: None,
            align: AlignUnknown,
            flags: 0,
            precision: CountImplied,
            width: CountImplied,
            ty: "",
        };
        if !parser.eat(&token::Comma) {
            return (Some(fmtstr), expr);
        }
        let token_expr = match parser.parse_expr().map_err(|mut err| err.cancel()) {
            Ok(expr) => expr,
            Err(_) => return (Some(fmtstr), None),
        };
        match &token_expr.node {
            ExprKind::Lit(_) => {
                let mut all_simple = true;
                let mut seen = false;
                for arg in &args {
                    match arg.position {
                        ArgumentImplicitlyIs(n) | ArgumentIs(n) => if n == idx {
                            all_simple &= arg.format == SIMPLE;
                            seen = true;
                        },
                        ArgumentNamed(_) => {},
                    }
                }
                if all_simple && seen {
                    span_lint(cx, lint, token_expr.span, "literal with an empty format string");
                }
                idx += 1;
            },
            ExprKind::Assign(lhs, rhs) => {
                if let ExprKind::Lit(_) = rhs.node {
                    if let ExprKind::Path(_, p) = &lhs.node {
                        let mut all_simple = true;
                        let mut seen = false;
                        for arg in &args {
                            match arg.position {
                                ArgumentImplicitlyIs(_) | ArgumentIs(_) => {},
                                ArgumentNamed(name) => if *p == name {
                                    seen = true;
                                    all_simple &= arg.format == SIMPLE;
                                },
                            }
                        }
                        if all_simple && seen {
                            span_lint(cx, lint, rhs.span, "literal with an empty format string");
                        }
                    }
                }
            },
            _ => idx += 1,
        }
    }
}
<commit_msg>Fix dogfood error<commit_after>// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use crate::rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass};
use crate::rustc::{declare_tool_lint, lint_array};
use crate::rustc_errors::Applicability;
use crate::syntax::ast::*;
use crate::syntax::parse::{parser, token};
use crate::syntax::tokenstream::{ThinTokenStream, TokenStream};
use crate::utils::{snippet_with_applicability, span_lint, span_lint_and_sugg};
use std::borrow::Cow;

/// **What it does:** This lint warns when you use `println!("")` to
/// print a newline.
///
/// **Why is this bad?** You should use `println!()`, which is simpler.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// println!("");
/// ```
declare_clippy_lint! {
    pub PRINTLN_EMPTY_STRING,
    style,
    "using `println!(\"\")` with an empty string"
}

/// **What it does:** This lint warns when you use `print!()` with a format
/// string that
/// ends in a newline.
///
/// **Why is this bad?** You should use `println!()` instead, which appends the
/// newline.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// print!("Hello {}!\n", name);
/// ```
/// use println!() instead
/// ```rust
/// println!("Hello {}!", name);
/// ```
declare_clippy_lint! {
    pub PRINT_WITH_NEWLINE,
    style,
    "using `print!()` with a format string that ends in a single newline"
}

/// **What it does:** Checks for printing on *stdout*. The purpose of this lint
/// is to catch debugging remnants.
///
/// **Why is this bad?** People often print on *stdout* while debugging an
/// application and might forget to remove those prints afterward.
///
/// **Known problems:** Only catches `print!` and `println!` calls.
///
/// **Example:**
/// ```rust
/// println!("Hello world!");
/// ```
declare_clippy_lint! {
    pub PRINT_STDOUT,
    restriction,
    "printing on stdout"
}

/// **What it does:** Checks for use of `Debug` formatting. The purpose of this
/// lint is to catch debugging remnants.
///
/// **Why is this bad?** The purpose of the `Debug` trait is to facilitate
/// debugging Rust code. It should not be used in in user-facing output.
///
/// **Example:**
/// ```rust
/// println!("{:?}", foo);
/// ```
declare_clippy_lint! {
    pub USE_DEBUG,
    restriction,
    "use of `Debug`-based formatting"
}

/// **What it does:** This lint warns about the use of literals as `print!`/`println!` args.
///
/// **Why is this bad?** Using literals as `println!` args is inefficient
/// (c.f., https://github.com/matthiaskrgr/rust-str-bench) and unnecessary
/// (i.e., just put the literal in the format string)
///
/// **Known problems:** Will also warn with macro calls as arguments that expand to literals
/// -- e.g., `println!("{}", env!("FOO"))`.
///
/// **Example:**
/// ```rust
/// println!("{}", "foo");
/// ```
/// use the literal without formatting:
/// ```rust
/// println!("foo");
/// ```
declare_clippy_lint! {
    pub PRINT_LITERAL,
    style,
    "printing a literal with a format string"
}

/// **What it does:** This lint warns when you use `writeln!(buf, "")` to
/// print a newline.
///
/// **Why is this bad?** You should use `writeln!(buf)`, which is simpler.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// writeln!("");
/// ```
declare_clippy_lint! {
    pub WRITELN_EMPTY_STRING,
    style,
    "using `writeln!(\"\")` with an empty string"
}

/// **What it does:** This lint warns when you use `write!()` with a format
/// string that
/// ends in a newline.
///
/// **Why is this bad?** You should use `writeln!()` instead, which appends the
/// newline.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// write!(buf, "Hello {}!\n", name);
/// ```
declare_clippy_lint! {
    pub WRITE_WITH_NEWLINE,
    style,
    "using `write!()` with a format string that ends in a single newline"
}

/// **What it does:** This lint warns about the use of literals as `write!`/`writeln!` args.
///
/// **Why is this bad?** Using literals as `writeln!` args is inefficient
/// (c.f., https://github.com/matthiaskrgr/rust-str-bench) and unnecessary
/// (i.e., just put the literal in the format string)
///
/// **Known problems:** Will also warn with macro calls as arguments that expand to literals
/// -- e.g., `writeln!(buf, "{}", env!("FOO"))`.
///
/// **Example:**
/// ```rust
/// writeln!(buf, "{}", "foo");
/// ```
declare_clippy_lint! {
    pub WRITE_LITERAL,
    style,
    "writing a literal with a format string"
}

#[derive(Copy, Clone, Debug)]
pub struct Pass;

impl LintPass for Pass {
    fn get_lints(&self) -> LintArray {
        lint_array!(
            PRINT_WITH_NEWLINE,
            PRINTLN_EMPTY_STRING,
            PRINT_STDOUT,
            USE_DEBUG,
            PRINT_LITERAL,
            WRITE_WITH_NEWLINE,
            WRITELN_EMPTY_STRING,
            WRITE_LITERAL
        )
    }
}

impl EarlyLintPass for Pass {
    fn check_mac(&mut self, cx: &EarlyContext<'_>, mac: &Mac) {
        if mac.node.path == "println" {
            span_lint(cx, PRINT_STDOUT, mac.span, "use of `println!`");
            if let Some(fmtstr) = check_tts(cx, &mac.node.tts, false).0 {
                if fmtstr == "" {
                    span_lint_and_sugg(
                        cx,
                        PRINTLN_EMPTY_STRING,
                        mac.span,
                        "using `println!(\"\")`",
                        "replace it with",
                        "println!()".to_string(),
                        Applicability::MachineApplicable,
                    );
                }
            }
        } else if mac.node.path == "print" {
            span_lint(cx, PRINT_STDOUT, mac.span, "use of `print!`");
            if let Some(fmtstr) = check_tts(cx, &mac.node.tts, false).0 {
                if fmtstr.ends_with("\\n") &&
                   // don't warn about strings with several `\n`s (#3126)
                   fmtstr.matches("\\n").count() == 1
                {
                    span_lint(
                        cx,
                        PRINT_WITH_NEWLINE,
                        mac.span,
                        "using `print!()` with a format string that ends in a \
                         single newline, consider using `println!()` instead",
                    );
                }
            }
        } else if mac.node.path == "write" {
            if let Some(fmtstr) = check_tts(cx, &mac.node.tts, true).0 {
                if fmtstr.ends_with("\\n") &&
                   // don't warn about strings with several `\n`s (#3126)
                   fmtstr.matches("\\n").count() == 1
                {
                    span_lint(
                        cx,
                        WRITE_WITH_NEWLINE,
                        mac.span,
                        "using `write!()` with a format string that ends in a \
                         single newline, consider using `writeln!()` instead",
                    );
                }
            }
        } else if mac.node.path == "writeln" {
            let check_tts = check_tts(cx, &mac.node.tts, true);
            if let Some(fmtstr) = check_tts.0 {
                if fmtstr == "" {
                    let mut applicability = Applicability::MachineApplicable;
                    let suggestion = check_tts.1.map_or_else(
                        move || {
                            applicability = Applicability::HasPlaceholders;
                            Cow::Borrowed("v")
                        },
                        move |expr| snippet_with_applicability(cx, expr.span, "v", &mut applicability),
                    );

                    span_lint_and_sugg(
                        cx,
                        WRITELN_EMPTY_STRING,
                        mac.span,
                        format!("using `writeln!({}, \"\")`", suggestion).as_str(),
                        "replace it with",
                        format!("writeln!({})", suggestion),
                        applicability,
                    );
                }
            }
        }
    }
}

/// Checks the arguments of `print[ln]!` and `write[ln]!` calls. It will return a tuple of two
/// options. The first part of the tuple is `format_str` of the macros. The secund part of the tuple
/// is in the `write[ln]!` case the expression the `format_str` should be written to.
///
/// Example:
///
/// Calling this function on
/// ```rust,ignore
/// writeln!(buf, "string to write: {}", something)
/// ```
/// will return
/// ```rust,ignore
/// (Some("string to write: {}"), Some(buf))
/// ```
fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &ThinTokenStream, is_write: bool) -> (Option<String>, Option<Expr>) {
    use crate::fmt_macros::*;
    let tts = TokenStream::from(tts.clone());
    let mut parser = parser::Parser::new(&cx.sess.parse_sess, tts, None, false, false);
    let mut expr: Option<Expr> = None;
    if is_write {
        expr = match parser.parse_expr().map_err(|mut err| err.cancel()) {
            Ok(p) => Some(p.into_inner()),
            Err(_) => return (None, None),
        };
        // might be `writeln!(foo)`
        if parser.expect(&token::Comma).map_err(|mut err| err.cancel()).is_err() {
            return (None, expr);
        }
    }

    let fmtstr = match parser.parse_str().map_err(|mut err| err.cancel()) {
        Ok(token) => token.0.to_string(),
        Err(_) => return (None, expr),
    };
    let tmp = fmtstr.clone();
    let mut args = vec![];
    let mut fmt_parser = Parser::new(&tmp, None);
    while let Some(piece) = fmt_parser.next() {
        if !fmt_parser.errors.is_empty() {
            return (None, expr);
        }
        if let Piece::NextArgument(arg) = piece {
            if arg.format.ty == "?" {
                // FIXME: modify rustc's fmt string parser to give us the current span
                span_lint(cx, USE_DEBUG, parser.prev_span, "use of `Debug`-based formatting");
            }
            args.push(arg);
        }
    }
    let lint = if is_write { WRITE_LITERAL } else { PRINT_LITERAL };
    let mut idx = 0;
    loop {
        const SIMPLE: FormatSpec<'_> = FormatSpec {
            fill: None,
            align: AlignUnknown,
            flags: 0,
            precision: CountImplied,
            width: CountImplied,
            ty: "",
        };
        if !parser.eat(&token::Comma) {
            return (Some(fmtstr), expr);
        }
        let token_expr = match parser.parse_expr().map_err(|mut err| err.cancel()) {
            Ok(expr) => expr,
            Err(_) => return (Some(fmtstr), None),
        };
        match &token_expr.node {
            ExprKind::Lit(_) => {
                let mut all_simple = true;
                let mut seen = false;
                for arg in &args {
                    match arg.position {
                        ArgumentImplicitlyIs(n) | ArgumentIs(n) => if n == idx {
                            all_simple &= arg.format == SIMPLE;
                            seen = true;
                        },
                        ArgumentNamed(_) => {},
                    }
                }
                if all_simple && seen {
                    span_lint(cx, lint, token_expr.span, "literal with an empty format string");
                }
                idx += 1;
            },
            ExprKind::Assign(lhs, rhs) => {
                if let ExprKind::Lit(_) = rhs.node {
                    if let ExprKind::Path(_, p) = &lhs.node {
                        let mut all_simple = true;
                        let mut seen = false;
                        for arg in &args {
                            match arg.position {
                                ArgumentImplicitlyIs(_) | ArgumentIs(_) => {},
                                ArgumentNamed(name) => if *p == name {
                                    seen = true;
                                    all_simple &= arg.format == SIMPLE;
                                },
                            }
                        }
                        if all_simple && seen {
                            span_lint(cx, lint, rhs.span, "literal with an empty format string");
                        }
                    }
                }
            },
            _ => idx += 1,
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 Ilkka Rauta
//
// 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.

#[allow(dead_code,non_camel_case_types,non_snake_case)]
mod ffi;

use libc::{c_ulong};

pub struct Demux {
    device: DeviceFileDescriptor
}

use super::device::{DeviceFileDescriptor,BlockMode,ReadWriteMode,DeviceResult,DeviceError};

impl Demux {
    pub fn open(file: &Path, rw_mode: ReadWriteMode, block_mode: BlockMode) -> DeviceResult<Frontend> {
        let device = try!(DeviceFileDescriptor::open(file, rw_mode, block_mode));
        Ok(Demux { device: device })
    }

    pub fn read(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    // Should this even exist here?
    pub fn write(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    pub fn start(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    pub fn stop(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    pub fn set_filter(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    pub fn set_pes_filter(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    pub fn set_buffer_size(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    pub fn get_system_time_counter(&self) -> DeviceResult<SystemTimeCounter> {
        unimplemented!();
    }

    pub fn get_pes_pids(&self) -> DeviceResult<[u16; 5]> {
        unimplemented!();
    }

    pub fn get_caps(&self) -> DeviceResult<DemuxCaps> {
        unimplemented!();
    }

    pub fn set_source(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    pub fn add_pid(&self, pid: u16) -> DeviceResult<()> {
        unimplemented!();
    }

    pub fn remove_pid(&selfm, pid: u16) -> DeviceResult<()> {
        unimplemented!();
    }
}<commit_msg>Implement demux start() and stop().<commit_after>// Copyright 2015 Ilkka Rauta
//
// 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.

#[allow(dead_code,non_camel_case_types,non_snake_case)]
mod ffi;

use libc::{c_ulong};

pub struct Demux {
    device: DeviceFileDescriptor
}

use super::device::{DeviceFileDescriptor,BlockMode,ReadWriteMode,DeviceResult,DeviceError};

impl Demux {
    pub fn open(file: &Path, rw_mode: ReadWriteMode, block_mode: BlockMode) -> DeviceResult<Frontend> {
        let device = try!(DeviceFileDescriptor::open(file, rw_mode, block_mode));
        Ok(Demux { device: device })
    }

    pub fn read(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    // Should this even exist here?
    pub fn write(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    pub fn start(&self) -> DeviceResult<()> {
        self.device.ioctl_argumentless(ffi::DMX_START as c_ulong)
    }

    pub fn stop(&self) -> DeviceResult<()> {
        self.device.ioctl_argumentless(ffi::DMX_STOP as c_ulong)
    }

    pub fn set_filter(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    pub fn set_pes_filter(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    pub fn set_buffer_size(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    pub fn get_system_time_counter(&self) -> DeviceResult<SystemTimeCounter> {
        unimplemented!();
    }

    pub fn get_pes_pids(&self) -> DeviceResult<[u16; 5]> {
        unimplemented!();
    }

    pub fn get_caps(&self) -> DeviceResult<DemuxCaps> {
        unimplemented!();
    }

    pub fn set_source(&self) -> DeviceResult<()> {
        unimplemented!();
    }

    pub fn add_pid(&self, pid: u16) -> DeviceResult<()> {
        unimplemented!();
    }

    pub fn remove_pid(&selfm, pid: u16) -> DeviceResult<()> {
        unimplemented!();
    }
}<|endoftext|>


<commit_before>use std::collections::hashmap::HashMap;
use std::char::is_digit;

#[deriving(PartialEq,Show,Clone)]
enum XPathToken {
    And,
    AtSign,
    CurrentNode,
    Divide,
    DollarSign,
    DoubleColon,
    DoubleSlash,
    Equal,
    GreaterThan,
    GreaterThanOrEqual,
    LeftBracket,
    LeftParen,
    LessThan,
    LessThanOrEqual,
    Literal(String),
    MinusSign,
    Multiply,
    NotEqual,
    Number(f64),
    Or,
    ParentNode,
    Pipe,
    PlusSign,
    PrefixedName(String, String),
    Remainder,
    RightBracket,
    RightParen,
    Slash,
    String(String),
}

impl XPathToken {
    fn precedes_node_test(& self) -> bool {
        match *self {
            AtSign |
            DoubleColon => true,
            _ => false,
        }
    }

    fn precedes_expression(& self) -> bool {
        match *self {
            LeftParen |
            LeftBracket => true,
            _ => false,
        }
    }

    fn is_operator(& self) -> bool {
        match *self {
            Slash |
            DoubleSlash |
            PlusSign |
            MinusSign |
            Pipe |
            Equal |
            NotEqual |
            LessThan |
            LessThanOrEqual |
            GreaterThan |
            GreaterThanOrEqual |
            And |
            Or |
            Remainder |
            Divide |
            Multiply => true,
            _ => false,
        }
    }
}

struct XPathTokenizer {
    xpath: Vec<char>,
    start: uint,
    prefer_recognition_of_operator_names: bool,
}

impl XPathTokenizer {
    fn new(xpath: & str) -> XPathTokenizer {
        XPathTokenizer {
            xpath: xpath.chars().collect(),
            start: 0,
            prefer_recognition_of_operator_names: false,
        }
    }

    fn has_more_tokens(& self) -> bool {
        self.xpath.len() > self.start
    }

    fn valid_ncname_start_char(& self, offset: uint) -> bool {
        let c = self.xpath[offset];
        if (c >= 'A' && c <= 'Z') { return true }
        if (c == '_') { return true }
        if (c >= 'a' && c <= 'z') { return true }
        // TODO: All non-ASCII codepoints
        return false;
    }

    fn valid_ncname_follow_char(& self, offset: uint) -> bool {
        let c = self.xpath[offset];
        if (self.valid_ncname_start_char(offset)) { return true }
        if (c == '-') { return true }
        if (c == '.') { return true }
        if (c >= '0' && c <= '9') { return true }
        // TODO: All non-ASCII codepoints
        return false;
    }

    fn while_valid_string(& self, offset: uint) -> uint {
        let mut offset = offset;

        if (self.valid_ncname_start_char(offset)) {
            offset += 1;

            while (offset < self.xpath.len() && self.valid_ncname_follow_char(offset)) {
                offset += 1;
            }
        }

        return offset;
    }

    fn while_valid_number(& self, offset: uint) -> uint {
        let mut offset = offset;

        while offset < self.xpath.len() && is_number_char(self.xpath[offset]) {
            offset += 1;
        }

        return offset;
    }

    fn while_not_character(& self, offset: uint, end_char: char) -> uint {
        let mut offset = offset;

        while offset < self.xpath.len() && self.xpath[offset] != end_char {
            offset += 1;
        }

        return offset;
    }

    fn two_char_tokens(& self) -> HashMap<String, XPathToken> {
        let mut m = HashMap::new();
        m.insert("<=".to_string(), LessThanOrEqual);
        m.insert(">=".to_string(), GreaterThanOrEqual);
        m.insert("!=".to_string(), NotEqual);
        m.insert("::".to_string(), DoubleColon);
        m.insert("//".to_string(), DoubleSlash);
        m.insert("..".to_string(), ParentNode);
        m
    }

    fn single_char_tokens(&self) -> HashMap<char, XPathToken> {
        let mut m = HashMap::new();
        m.insert('/', Slash);
        m.insert('(', LeftParen);
        m.insert(')', RightParen);
        m.insert('[', LeftBracket);
        m.insert(']', RightBracket);
        m.insert('@', AtSign);
        m.insert('$', DollarSign);
        m.insert('+', PlusSign);
        m.insert('-', MinusSign);
        m.insert('|', Pipe);
        m.insert('=', Equal);
        m.insert('<', LessThan);
        m.insert('>', GreaterThan);
        m
    }

    fn named_operators(& self) -> Vec<(& 'static str, XPathToken)> {
        vec!(("and", And),
             ("or",  Or),
             ("mod", Remainder),
             ("div", Divide),
             ("*",   Multiply))
    }

    fn tokenize_literal(& mut self, quote_char: char) -> XPathToken {
        let mut offset = self.start;

        offset += 1; // Skip over the starting quote
        let start_of_string = offset;

        offset = self.while_not_character(offset, quote_char);
        let end_of_string = offset;

        if (self.xpath[offset] != quote_char) {
            fail!("throw MismatchedQuoteCharacterException(quote_char)");
        }
        offset += 1; // Skip over ending quote

        self.start = offset;
        let value = self.xpath.slice(start_of_string, end_of_string);
        return Literal(String::from_chars(value));
    }

    fn substr(& self, start: uint, end: uint) -> String {
        String::from_chars(self.xpath.slice(start, end))
    }

    fn raw_next_token(& mut self) -> XPathToken {
        let first_two = self.substr(self.start, self.start + 2);
        let c = self.xpath[self.start];

        match self.two_char_tokens().find(&first_two) {
            Some(token) => {
                self.start += 2;
                return token.clone();
            }
            _ => {}
        }

        match self.single_char_tokens().find(&c) {
            Some(token) => {
                self.start += 1;
                return token.clone();
            }
            _ => {}
        }

        for quote_char in QUOTE_CHARS.iter() {
            if *quote_char == c {
                return self.tokenize_literal(*quote_char);
            }
        }

        if ('.' == c && ! is_digit(self.xpath[self.start + 1])) {
            // Ugly. Should we use START / FOLLOW constructs?
            self.start += 1;
            return CurrentNode;
        }

        if (is_number_char(c)) {
            let mut offset = self.start;
            let current_start = self.start;

            offset = self.while_valid_number(offset);

            self.start = offset;
            let substr = self.substr(current_start, offset);
            match from_str(substr.as_slice()) {
                Some(value) => Number(value),
                None => fail!("Not really a number!")
            }
        } else {
            let mut offset = self.start;
            let current_start = self.start;

            if (self.prefer_recognition_of_operator_names) {
                for &(ref name, ref token) in self.named_operators().iter() {

                    let name_chars: Vec<char> = name.chars().collect();
                    let name_chars_slice = name_chars.as_slice();
                    let xpath_chars = self.xpath.slice(offset, offset + name_chars.len());

                    if (name_chars_slice == xpath_chars) {
                        self.start += name_chars.len();
                        return token.clone();
                    }
                }
            }

            if (self.xpath[offset] == '*') {
                self.start = offset + 1;
                return String("*".to_string());
            }

            offset = self.while_valid_string(offset);
            if (self.xpath[offset] == ':' && self.xpath[offset + 1] != ':') {
                let prefix = self.substr(current_start, offset);

                offset += 1;

                let current_start = offset;
                offset = self.while_valid_string(offset);

                if (current_start == offset) {
                    fail!("throw MissingLocalNameException()");
                }

                let name = self.substr(current_start, offset);

                self.start = offset;
                return PrefixedName(prefix, name);
            } else {
                self.start = offset;
                return String(String::from_chars(self.xpath.slice(current_start, offset)));
            }
        }
    }

    fn consume_whitespace(& mut self) {
        while self.start < self.xpath.len() {
            let c = self.xpath[self.start];

            if (! is_xml_space(c)) {
                break;
            }

            self.start += 1;
        }
    }

    pub fn next_token(& mut self) -> XPathToken {
        self.consume_whitespace();

        if (! self.has_more_tokens()) {
            fail!("throw NoMoreTokensAvailableException()");
        }

        let old_start = self.start;
        let token = self.raw_next_token();

        if (old_start == self.start) {
            fail!("throw UnableToCreateTokenException()");
        }

        self.consume_whitespace();

        if (! (token.precedes_node_test() ||
               token.precedes_expression() ||
               token.is_operator())) {
            // See http://www.w3.org/TR/xpath/#exprlex
            self.prefer_recognition_of_operator_names = true;
        } else {
            self.prefer_recognition_of_operator_names = false;
        }
        return token;
    }
}

fn is_xml_space(c: char) -> bool {
    return
        c == ' '  ||
        c == '\t' ||
        c == '\n' ||
        c == '\r';
}

fn is_number_char(c: char) -> bool {
    return is_digit(c) || '.' == c;
}

// broken nesting double in single
// open paren / suqre brace causes indent
static QUOTE_CHARS: [char, .. 2] =  ['\'', '"'];

fn main() {
    }
<commit_msg>Remove warnings<commit_after>use std::collections::hashmap::HashMap;
use std::char::is_digit;

#[deriving(PartialEq,Show,Clone)]
enum XPathToken {
    And,
    AtSign,
    CurrentNode,
    Divide,
    DollarSign,
    DoubleColon,
    DoubleSlash,
    Equal,
    GreaterThan,
    GreaterThanOrEqual,
    LeftBracket,
    LeftParen,
    LessThan,
    LessThanOrEqual,
    Literal(String),
    MinusSign,
    Multiply,
    NotEqual,
    Number(f64),
    Or,
    ParentNode,
    Pipe,
    PlusSign,
    PrefixedName(String, String),
    Remainder,
    RightBracket,
    RightParen,
    Slash,
    String(String),
}

impl XPathToken {
    fn precedes_node_test(& self) -> bool {
        match *self {
            AtSign |
            DoubleColon => true,
            _ => false,
        }
    }

    fn precedes_expression(& self) -> bool {
        match *self {
            LeftParen |
            LeftBracket => true,
            _ => false,
        }
    }

    fn is_operator(& self) -> bool {
        match *self {
            Slash |
            DoubleSlash |
            PlusSign |
            MinusSign |
            Pipe |
            Equal |
            NotEqual |
            LessThan |
            LessThanOrEqual |
            GreaterThan |
            GreaterThanOrEqual |
            And |
            Or |
            Remainder |
            Divide |
            Multiply => true,
            _ => false,
        }
    }
}

struct XPathTokenizer {
    xpath: Vec<char>,
    start: uint,
    prefer_recognition_of_operator_names: bool,
}

impl XPathTokenizer {
    fn new(xpath: & str) -> XPathTokenizer {
        XPathTokenizer {
            xpath: xpath.chars().collect(),
            start: 0,
            prefer_recognition_of_operator_names: false,
        }
    }

    fn has_more_tokens(& self) -> bool {
        self.xpath.len() > self.start
    }

    fn valid_ncname_start_char(& self, offset: uint) -> bool {
        let c = self.xpath[offset];
        if c >= 'A' && c <= 'Z' { return true }
        if c == '_' { return true }
        if c >= 'a' && c <= 'z' { return true }
        // TODO: All non-ASCII codepoints
        return false;
    }

    fn valid_ncname_follow_char(& self, offset: uint) -> bool {
        let c = self.xpath[offset];
        if self.valid_ncname_start_char(offset) { return true }
        if c == '-' { return true }
        if c == '.' { return true }
        if c >= '0' && c <= '9' { return true }
        // TODO: All non-ASCII codepoints
        return false;
    }

    fn while_valid_string(& self, offset: uint) -> uint {
        let mut offset = offset;

        if self.valid_ncname_start_char(offset) {
            offset += 1;

            while offset < self.xpath.len() && self.valid_ncname_follow_char(offset) {
                offset += 1;
            }
        }

        return offset;
    }

    fn while_valid_number(& self, offset: uint) -> uint {
        let mut offset = offset;

        while offset < self.xpath.len() && is_number_char(self.xpath[offset]) {
            offset += 1;
        }

        return offset;
    }

    fn while_not_character(& self, offset: uint, end_char: char) -> uint {
        let mut offset = offset;

        while offset < self.xpath.len() && self.xpath[offset] != end_char {
            offset += 1;
        }

        return offset;
    }

    fn two_char_tokens(& self) -> HashMap<String, XPathToken> {
        let mut m = HashMap::new();
        m.insert("<=".to_string(), LessThanOrEqual);
        m.insert(">=".to_string(), GreaterThanOrEqual);
        m.insert("!=".to_string(), NotEqual);
        m.insert("::".to_string(), DoubleColon);
        m.insert("//".to_string(), DoubleSlash);
        m.insert("..".to_string(), ParentNode);
        m
    }

    fn single_char_tokens(&self) -> HashMap<char, XPathToken> {
        let mut m = HashMap::new();
        m.insert('/', Slash);
        m.insert('(', LeftParen);
        m.insert(')', RightParen);
        m.insert('[', LeftBracket);
        m.insert(']', RightBracket);
        m.insert('@', AtSign);
        m.insert('$', DollarSign);
        m.insert('+', PlusSign);
        m.insert('-', MinusSign);
        m.insert('|', Pipe);
        m.insert('=', Equal);
        m.insert('<', LessThan);
        m.insert('>', GreaterThan);
        m
    }

    fn named_operators(& self) -> Vec<(& 'static str, XPathToken)> {
        vec!(("and", And),
             ("or",  Or),
             ("mod", Remainder),
             ("div", Divide),
             ("*",   Multiply))
    }

    fn tokenize_literal(& mut self, quote_char: char) -> XPathToken {
        let mut offset = self.start;

        offset += 1; // Skip over the starting quote
        let start_of_string = offset;

        offset = self.while_not_character(offset, quote_char);
        let end_of_string = offset;

        if self.xpath[offset] != quote_char {
            fail!("throw MismatchedQuoteCharacterException(quote_char)");
        }
        offset += 1; // Skip over ending quote

        self.start = offset;
        let value = self.xpath.slice(start_of_string, end_of_string);
        return Literal(String::from_chars(value));
    }

    fn substr(& self, start: uint, end: uint) -> String {
        String::from_chars(self.xpath.slice(start, end))
    }

    fn raw_next_token(& mut self) -> XPathToken {
        let first_two = self.substr(self.start, self.start + 2);
        let c = self.xpath[self.start];

        match self.two_char_tokens().find(&first_two) {
            Some(token) => {
                self.start += 2;
                return token.clone();
            }
            _ => {}
        }

        match self.single_char_tokens().find(&c) {
            Some(token) => {
                self.start += 1;
                return token.clone();
            }
            _ => {}
        }

        for quote_char in QUOTE_CHARS.iter() {
            if *quote_char == c {
                return self.tokenize_literal(*quote_char);
            }
        }

        if '.' == c && ! is_digit(self.xpath[self.start + 1]) {
            // Ugly. Should we use START / FOLLOW constructs?
            self.start += 1;
            return CurrentNode;
        }

        if is_number_char(c) {
            let mut offset = self.start;
            let current_start = self.start;

            offset = self.while_valid_number(offset);

            self.start = offset;
            let substr = self.substr(current_start, offset);
            match from_str(substr.as_slice()) {
                Some(value) => Number(value),
                None => fail!("Not really a number!")
            }
        } else {
            let mut offset = self.start;
            let current_start = self.start;

            if self.prefer_recognition_of_operator_names {
                for &(ref name, ref token) in self.named_operators().iter() {
                    let name_chars: Vec<char> = name.chars().collect();
                    let name_chars_slice = name_chars.as_slice();
                    let xpath_chars = self.xpath.slice(offset, offset + name_chars.len());

                    if name_chars_slice == xpath_chars {
                        self.start += name_chars.len();
                        return token.clone();
                    }
                }
            }

            if self.xpath[offset] == '*' {
                self.start = offset + 1;
                return String("*".to_string());
            }

            offset = self.while_valid_string(offset);
            if self.xpath[offset] == ':' && self.xpath[offset + 1] != ':' {
                let prefix = self.substr(current_start, offset);

                offset += 1;

                let current_start = offset;
                offset = self.while_valid_string(offset);

                if current_start == offset {
                    fail!("throw MissingLocalNameException()");
                }

                let name = self.substr(current_start, offset);

                self.start = offset;
                return PrefixedName(prefix, name);
            } else {
                self.start = offset;
                return String(String::from_chars(self.xpath.slice(current_start, offset)));
            }
        }
    }

    fn consume_whitespace(& mut self) {
        while self.start < self.xpath.len() {
            let c = self.xpath[self.start];

            if ! is_xml_space(c) {
                break;
            }

            self.start += 1;
        }
    }

    pub fn next_token(& mut self) -> XPathToken {
        self.consume_whitespace();

        if ! self.has_more_tokens() {
            fail!("throw NoMoreTokensAvailableException()");
        }

        let old_start = self.start;
        let token = self.raw_next_token();

        if old_start == self.start {
            fail!("throw UnableToCreateTokenException()");
        }

        self.consume_whitespace();

        if ! (token.precedes_node_test() ||
              token.precedes_expression() ||
              token.is_operator()) {
            // See http://www.w3.org/TR/xpath/#exprlex
            self.prefer_recognition_of_operator_names = true;
        } else {
            self.prefer_recognition_of_operator_names = false;
        }
        return token;
    }
}

fn is_xml_space(c: char) -> bool {
    return
        c == ' '  ||
        c == '\t' ||
        c == '\n' ||
        c == '\r';
}

fn is_number_char(c: char) -> bool {
    return is_digit(c) || '.' == c;
}

fn main() {
    let mut tzer = XPathTokenizer::new("//foo");
    println!("Hi! {}", tzer.next_token());
}

// broken nesting double in single
// open paren / suqre brace causes indent
static QUOTE_CHARS: [char, .. 2] =  ['\'', '"'];
<|endoftext|>


<commit_before>#![no_main]
use libfuzzer_sys::fuzz_target;

struct StaticSymbolSupplier {
    file: Vec<u8>,
}

#[async_trait::async_trait]
impl minidump_processor::SymbolSupplier for StaticSymbolSupplier {
    async fn locate_symbols(
        &self,
        _module: &(dyn minidump_common::traits::Module + Sync),
    ) -> Result<minidump_processor::SymbolFile, minidump_processor::SymbolError> {
        minidump_processor::SymbolFile::from_bytes(&self.file)
    }
}

fuzz_target!(|data: (&[u8], &[u8])| {
    if let Ok(dump) = minidump::Minidump::read(data.0) {
        let supplier = StaticSymbolSupplier {
            file: data.1.to_vec(),
        };

        let provider = minidump_processor::Symbolizer::new(supplier);

        let val: Result<_, _> = minidump_processor_fuzz::fuzzing_block_on(
            minidump_processor::process_minidump(&dump, &provider),
        );

        if let Ok(v) = val {
            let _: Result<(), _> = v.print_json(&mut std::io::sink(), true);
        }
    }
});
<commit_msg>Make the fuzzer test all features of minidump-processor<commit_after>#![no_main]
use libfuzzer_sys::fuzz_target;

struct StaticSymbolSupplier {
    file: Vec<u8>,
}

#[async_trait::async_trait]
impl minidump_processor::SymbolSupplier for StaticSymbolSupplier {
    async fn locate_symbols(
        &self,
        _module: &(dyn minidump_common::traits::Module + Sync),
    ) -> Result<minidump_processor::SymbolFile, minidump_processor::SymbolError> {
        minidump_processor::SymbolFile::from_bytes(&self.file)
    }
}

fuzz_target!(|data: (&[u8], &[u8])| {
    if let Ok(dump) = minidump::Minidump::read(data.0) {
        let supplier = StaticSymbolSupplier {
            file: data.1.to_vec(),
        };

        let provider = minidump_processor::Symbolizer::new(supplier);
        // Fuzz every possible feature
        let options = minidump_processor::ProcessorOptions::unstable_all();

        let val: Result<_, _> = minidump_processor_fuzz::fuzzing_block_on(
            minidump_processor::process_minidump_with_options(&dump, &provider, options),
        );

        if let Ok(v) = val {
            let _: Result<(), _> = v.print_json(&mut std::io::sink(), true);
        }
    }
});
<|endoftext|>


<commit_before>// spell-checker:ignore (words) araba newroot userspec chdir

use crate::common::util::*;

#[test]
fn test_invalid_arg() {
    new_ucmd!().arg("--definitely-invalid").fails().code_is(125);
}

#[test]
fn test_missing_operand() {
    let result = new_ucmd!().fails();

    result.code_is(125);

    assert!(result
        .stderr_str()
        .starts_with("error: The following required arguments were not provided"));

    assert!(result.stderr_str().contains("<newroot>"));
}

#[test]
#[cfg(not(target_os = "android"))]
fn test_enter_chroot_fails() {
    // NOTE: since #2689 this test also ensures that we don't regress #2687
    let (at, mut ucmd) = at_and_ucmd!();

    at.mkdir("jail");

    let result = ucmd.arg("jail").fails();
    result.code_is(125);
    assert!(result
        .stderr_str()
        .starts_with("chroot: cannot chroot to 'jail': Operation not permitted (os error 1)"));
}

#[test]
fn test_no_such_directory() {
    let (at, mut ucmd) = at_and_ucmd!();

    at.touch(&at.plus_as_string("a"));

    ucmd.arg("a")
        .fails()
        .stderr_is("chroot: cannot change root directory to 'a': no such directory")
        .code_is(125);
}

#[test]
fn test_invalid_user_spec() {
    let (at, mut ucmd) = at_and_ucmd!();

    at.mkdir("a");

    let result = ucmd.arg("a").arg("--userspec=ARABA:").fails();
    result.code_is(125);
    assert!(result.stderr_str().starts_with("chroot: invalid userspec"));
}

#[test]
fn test_preference_of_userspec() {
    let scene = TestScenario::new(util_name!());
    let result = scene.cmd("whoami").run();
    if is_ci() && result.stderr_str().contains("No such user/group") {
        // In the CI, some server are failing to return whoami.
        // As seems to be a configuration issue, ignoring it
        return;
    }
    println!("result.stdout = {}", result.stdout_str());
    println!("result.stderr = {}", result.stderr_str());
    let username = result.stdout_str().trim_end();

    let ts = TestScenario::new("id");
    let result = ts.cmd("id").arg("-g").arg("-n").run();
    println!("result.stdout = {}", result.stdout_str());
    println!("result.stderr = {}", result.stderr_str());

    if is_ci() && result.stderr_str().contains("cannot find name for user ID") {
        // In the CI, some server are failing to return id.
        // As seems to be a configuration issue, ignoring it
        return;
    }

    let group_name = result.stdout_str().trim_end();
    let (at, mut ucmd) = at_and_ucmd!();

    at.mkdir("a");

    let result = ucmd
        .arg("a")
        .arg("--user")
        .arg("fake")
        .arg("-G")
        .arg("ABC,DEF")
        .arg(format!("--userspec={}:{}", username, group_name))
        .fails();

    result.code_is(125);

    println!("result.stdout = {}", result.stdout_str());
    println!("result.stderr = {}", result.stderr_str());
}

#[test]
fn test_default_shell() {
    // NOTE: This test intends to trigger code which can only be reached with root permissions.
    let ts = TestScenario::new(util_name!());
    let at = &ts.fixtures;

    let dir = "CHROOT_DIR";
    at.mkdir(dir);

    let shell = std::env::var("SHELL").unwrap_or_else(|_| "/bin/sh".to_string());
    let expected = format!(
        "chroot: failed to run command '{}': No such file or directory",
        shell
    );

    if let Ok(result) = run_ucmd_as_root(&ts, &[dir]) {
        result.stderr_contains(expected);
    } else {
        print!("TEST SKIPPED");
    }
}

#[test]
fn test_chroot() {
    let ts = TestScenario::new(util_name!());
    let at = &ts.fixtures;

    let dir = "CHROOT_DIR";
    at.mkdir(dir);
    if let Ok(result) = run_ucmd_as_root(&ts, &[dir, "whoami"]) {
        result.success().no_stderr().stdout_is("root");
    } else {
        print!("Test skipped; requires root user");
    }

    if let Ok(result) = run_ucmd_as_root(&ts, &[dir, "pwd"]) {
        result.success().no_stderr().stdout_is("/");
    } else {
        print!("Test skipped; requires root user");
    }
}

#[test]
fn test_chroot_skip_chdir() {
    let ts = TestScenario::new(util_name!());
    let at = &ts.fixtures;

    let dir = "CHROOT_DIR";
    at.mkdir(dir);
    let env_cd = std::env::current_dir().unwrap();
    if let Ok(result) = run_ucmd_as_root(&ts, &[dir, "--skip-chdir", "pwd"]) {
        // Should return the same path
        assert_eq!(
            result.success().no_stderr().stdout_str(),
            env_cd.to_str().unwrap()
        );
    } else {
        print!("Test skipped; requires root user");
    }
}
<commit_msg>chroot: add a new test to verify that 'chroot / ls -al' works<commit_after>// spell-checker:ignore (words) araba newroot userspec chdir pwd's

use crate::common::util::*;

#[test]
fn test_invalid_arg() {
    new_ucmd!().arg("--definitely-invalid").fails().code_is(125);
}

#[test]
fn test_missing_operand() {
    let result = new_ucmd!().fails();

    result.code_is(125);

    assert!(result
        .stderr_str()
        .starts_with("error: The following required arguments were not provided"));

    assert!(result.stderr_str().contains("<newroot>"));
}

#[test]
#[cfg(not(target_os = "android"))]
fn test_enter_chroot_fails() {
    // NOTE: since #2689 this test also ensures that we don't regress #2687
    let (at, mut ucmd) = at_and_ucmd!();

    at.mkdir("jail");

    let result = ucmd.arg("jail").fails();
    result.code_is(125);
    assert!(result
        .stderr_str()
        .starts_with("chroot: cannot chroot to 'jail': Operation not permitted (os error 1)"));
}

#[test]
fn test_no_such_directory() {
    let (at, mut ucmd) = at_and_ucmd!();

    at.touch(&at.plus_as_string("a"));

    ucmd.arg("a")
        .fails()
        .stderr_is("chroot: cannot change root directory to 'a': no such directory")
        .code_is(125);
}

#[test]
fn test_invalid_user_spec() {
    let (at, mut ucmd) = at_and_ucmd!();

    at.mkdir("a");

    let result = ucmd.arg("a").arg("--userspec=ARABA:").fails();
    result.code_is(125);
    assert!(result.stderr_str().starts_with("chroot: invalid userspec"));
}

#[test]
fn test_preference_of_userspec() {
    let scene = TestScenario::new(util_name!());
    let result = scene.cmd("whoami").run();
    if is_ci() && result.stderr_str().contains("No such user/group") {
        // In the CI, some server are failing to return whoami.
        // As seems to be a configuration issue, ignoring it
        return;
    }
    println!("result.stdout = {}", result.stdout_str());
    println!("result.stderr = {}", result.stderr_str());
    let username = result.stdout_str().trim_end();

    let ts = TestScenario::new("id");
    let result = ts.cmd("id").arg("-g").arg("-n").run();
    println!("result.stdout = {}", result.stdout_str());
    println!("result.stderr = {}", result.stderr_str());

    if is_ci() && result.stderr_str().contains("cannot find name for user ID") {
        // In the CI, some server are failing to return id.
        // As seems to be a configuration issue, ignoring it
        return;
    }

    let group_name = result.stdout_str().trim_end();
    let (at, mut ucmd) = at_and_ucmd!();

    at.mkdir("a");

    let result = ucmd
        .arg("a")
        .arg("--user")
        .arg("fake")
        .arg("-G")
        .arg("ABC,DEF")
        .arg(format!("--userspec={}:{}", username, group_name))
        .fails();

    result.code_is(125);

    println!("result.stdout = {}", result.stdout_str());
    println!("result.stderr = {}", result.stderr_str());
}

#[test]
fn test_default_shell() {
    // NOTE: This test intends to trigger code which can only be reached with root permissions.
    let ts = TestScenario::new(util_name!());
    let at = &ts.fixtures;

    let dir = "CHROOT_DIR";
    at.mkdir(dir);

    let shell = std::env::var("SHELL").unwrap_or_else(|_| "/bin/sh".to_string());
    let expected = format!(
        "chroot: failed to run command '{}': No such file or directory",
        shell
    );

    if let Ok(result) = run_ucmd_as_root(&ts, &[dir]) {
        result.stderr_contains(expected);
    } else {
        print!("TEST SKIPPED");
    }
}

#[test]
fn test_chroot() {
    let ts = TestScenario::new(util_name!());
    let at = &ts.fixtures;

    let dir = "CHROOT_DIR";
    at.mkdir(dir);
    if let Ok(result) = run_ucmd_as_root(&ts, &[dir, "whoami"]) {
        result.success().no_stderr().stdout_is("root");
    } else {
        print!("Test skipped; requires root user");
    }

    if let Ok(result) = run_ucmd_as_root(&ts, &[dir, "pwd"]) {
        result.success().no_stderr().stdout_is("/");
    } else {
        print!("Test skipped; requires root user");
    }
}

#[test]
fn test_chroot_skip_chdir() {
    let ts = TestScenario::new(util_name!());
    let at = &ts.fixtures;

    let dir = "CHROOT_DIR";
    at.mkdir(dir);
    let env_cd = std::env::current_dir().unwrap();
    if let Ok(result) = run_ucmd_as_root(&ts, &[dir, "--skip-chdir", "pwd"]) {
        // Should return the same path
        assert_eq!(
            result.success().no_stderr().stdout_str(),
            env_cd.to_str().unwrap()
        );
    } else {
        print!("Test skipped; requires root user");
    }
}

#[test]
fn test_chroot_extra_arg() {
    let ts = TestScenario::new(util_name!());
    let at = &ts.fixtures;

    let dir = "CHROOT_DIR";
    at.mkdir(dir);
    let env_cd = std::env::current_dir().unwrap();
    // Verify that -P is pwd's and not chroot
    if let Ok(result) = run_ucmd_as_root(&ts, &[dir, "pwd", "-P"]) {
        assert_eq!(
            result.success().no_stderr().stdout_str(),
            env_cd.to_str().unwrap()
        );
    } else {
        print!("Test skipped; requires root user");
    }
}
<|endoftext|>


<commit_before>use crate::common::util::*;

#[test]
#[cfg(any(target_vendor = "apple", target_os = "linux"))]
fn test_groups() {
    if !is_ci() {
        new_ucmd!().succeeds().stdout_is(expected_result(&[]));
    } else {
        // TODO: investigate how this could be tested in CI
        // stderr = groups: cannot find name for group ID 116
        println!("test skipped:");
    }
}

#[test]
#[cfg(any(target_os = "linux"))]
#[ignore = "fixme: 'groups USERNAME' needs more debugging"]
fn test_groups_username() {
    let scene = TestScenario::new(util_name!());
    let whoami_result = scene.cmd("whoami").run();

    let username = if whoami_result.succeeded() {
        whoami_result.stdout_move_str()
    } else if is_ci() {
        String::from("docker")
    } else {
        println!("test skipped:");
        return;
    };

    // TODO: stdout should be in the form: "username : group1 group2 group3"

    scene
        .ucmd()
        .arg(&username)
        .succeeds()
        .stdout_is(expected_result(&[&username]));
}

#[cfg(any(target_vendor = "apple", target_os = "linux"))]
fn expected_result(args: &[&str]) -> String {
    #[cfg(target_os = "linux")]
    let util_name = util_name!();
    #[cfg(target_vendor = "apple")]
    let util_name = format!("g{}", util_name!());

    TestScenario::new(&util_name)
        .cmd_keepenv(util_name)
        .env("LANGUAGE", "C")
        .args(args)
        .succeeds()
        .stdout_move_str()
}
<commit_msg>groups: fix test for arch<commit_after>use crate::common::util::*;

#[test]
#[cfg(any(target_vendor = "apple", target_os = "linux"))]
fn test_groups() {
    if !is_ci() {
        new_ucmd!().succeeds().stdout_is(expected_result(&[]));
    } else {
        // TODO: investigate how this could be tested in CI
        // stderr = groups: cannot find name for group ID 116
        println!("test skipped:");
    }
}

#[test]
#[cfg(any(target_vendor = "apple", target_os = "linux"))]
#[ignore = "fixme: 'groups USERNAME' needs more debugging"]
fn test_groups_username() {
    let scene = TestScenario::new(util_name!());
    let whoami_result = scene.cmd("whoami").run();

    let username = if whoami_result.succeeded() {
        whoami_result.stdout_move_str()
    } else if is_ci() {
        String::from("docker")
    } else {
        println!("test skipped:");
        return;
    };

    // TODO: stdout should be in the form: "username : group1 group2 group3"

    scene
        .ucmd()
        .arg(&username)
        .succeeds()
        .stdout_is(expected_result(&[&username]));
}

#[cfg(any(target_vendor = "apple", target_os = "linux"))]
fn expected_result(args: &[&str]) -> String {
    let util_name = "id";

    TestScenario::new(&util_name)
        .cmd_keepenv(util_name)
        .env("LANGUAGE", "C")
        .args(args)
        .args(&["-Gn"])
        .succeeds()
        .stdout_move_str()
}
<|endoftext|>


<commit_before>use super::dsp::Dsp;
use super::super::apu::Apu;
use super::envelope::Envelope;
use super::brr_block_decoder::BrrBlockDecoder;
use super::dsp_helpers;

#[derive(Clone, Copy)]
pub struct VoiceOutput {
    pub left_out: i32,
    pub right_out: i32,
    pub last_voice_out: i32
}

impl VoiceOutput {
    pub fn default() -> VoiceOutput {
        VoiceOutput {
            left_out: 0,
            right_out: 0,
            last_voice_out: 0
        }
    }
}

pub const VOICE_BUFFER_LEN: usize = 128;

// TODO: If Rust had facilities for specifying arrray sizes with generic parameters,
// this could be removed in favor of a more generalized RingBuffer.
pub struct VoiceBuffer {
    pub buffer: Box<[VoiceOutput; VOICE_BUFFER_LEN]>,
    pub pos: i32
}

impl VoiceBuffer {
    pub fn new() -> VoiceBuffer {
        VoiceBuffer {
            buffer: Box::new([VoiceOutput::default(); VOICE_BUFFER_LEN]),
            pos: 0
        }
    }

    pub fn reset(&mut self) {
        for i in 0..VOICE_BUFFER_LEN {
            self.buffer[i] = VoiceOutput::default();
        }
        self.pos = 0;
    }

    pub fn write(&mut self, value: VoiceOutput) {
        self.buffer[self.pos as usize] = value;
        self.pos = (self.pos + 1) % (VOICE_BUFFER_LEN as i32);
    }
}

pub struct Voice {
    dsp: *mut Dsp,
    emulator: *mut Apu,

    pub envelope: Box<Envelope>,

    pub vol_left: u8,
    pub vol_right: u8,
    pub pitch_low: u8,
    pitch_high: u8,
    pub source: u8,
    pub pitch_mod: bool,
    pub noise_on: bool,
    pub echo_on: bool,

    sample_start_address: u32,
    loop_start_address: u32,
    brr_block_decoder: Box<BrrBlockDecoder>,
    sample_address: u32,
    sample_pos: i32,
    current_sample: i32,
    next_sample: i32,

    pub output_buffer: Box<VoiceBuffer>,
    pub is_muted: bool
}

impl Voice {
    pub fn new(dsp: *mut Dsp, emulator: *mut Apu) -> Voice {
        let mut ret = Voice {
            dsp: dsp,
            emulator: emulator,

            envelope: Box::new(Envelope::new(dsp)),

            vol_left: 0,
            vol_right: 0,
            pitch_low: 0,
            pitch_high: 0,
            source: 0,
            pitch_mod: false,
            noise_on: false,
            echo_on: false,

            sample_start_address: 0,
            loop_start_address: 0,
            brr_block_decoder: Box::new(BrrBlockDecoder::new()),
            sample_address: 0,
            sample_pos: 0,
            current_sample: 0,
            next_sample: 0,

            output_buffer: Box::new(VoiceBuffer::new()),
            is_muted: false,
        };
        ret.reset();
        ret
    }

    #[inline]
    fn dsp(&self) -> &mut Dsp {
        unsafe {
            &mut (*self.dsp)
        }
    }

    #[inline]
    fn emulator(&self) -> &mut Apu {
        unsafe {
            &mut (*self.emulator)
        }
    }

    pub fn reset(&mut self) {
        self.envelope.reset();

        self.vol_left = 0;
        self.vol_right = 0;
        self.pitch_low = 0;
        self.pitch_high = 0x10;
        self.source = 0;
        self.pitch_mod = false;
        self.noise_on = false;

        self.sample_start_address = 0;
        self.loop_start_address = 0;
        self.brr_block_decoder.reset(0, 0);
        self.sample_address = 0;
        self.sample_pos = 0;
        self.current_sample = 0;
        self.next_sample = 0;

        self.output_buffer.reset();
        self.is_muted = false;
    }

    pub fn render_sample(&mut self, last_voice_out: i32, noise: i32) -> VoiceOutput {
        let mut pitch = ((self.pitch_high as i32) << 8) | (self.pitch_low as i32);
        if self.pitch_mod {
            pitch += ((last_voice_out >> 5) * pitch) >> 10;
        }
        if pitch < 0 {
            pitch = 0;
        }
        if pitch > 0x3fff {
            pitch = 0x3fff;
        }

        let mut sample = if !self.noise_on {
            let p1 = self.sample_pos;
            let p2 = 0x1000 - p1;
            dsp_helpers::clamp((self.current_sample * p2 + self.next_sample * p1) >> 12) & !1
        } else {
            ((noise * 2) as i16) as i32
        };

        self.envelope.tick();
        let env_level = self.envelope.level;

        sample = ((sample * env_level) >> 11) & !1;

        if self.brr_block_decoder.is_end && !self.brr_block_decoder.is_looping {
            self.envelope.key_off();
            self.envelope.level = 0;
        }

        self.sample_pos += pitch;
        while self.sample_pos >= 0x1000 {
            self.sample_pos -= 0x1000;
            self.read_next_sample();

            if self.brr_block_decoder.is_finished() {
                if self.brr_block_decoder.is_end && self.brr_block_decoder.is_looping {
                    self.read_entry();
                    self.sample_address = self.loop_start_address;
                }
                self.read_next_block();
            }
        }

        let ret =
            if !self.is_muted {
                VoiceOutput {
                    left_out: dsp_helpers::multiply_volume(sample, self.vol_left),
                    right_out: dsp_helpers::multiply_volume(sample, self.vol_right),
                    last_voice_out: sample
                }
            } else {
                VoiceOutput {
                    left_out: 0,
                    right_out: 0,
                    last_voice_out: 0
                }
            };
        self.output_buffer.write(ret);
        ret
    }

    pub fn set_pitch_high(&mut self, value: u8) {
        self.pitch_high = value & 0x3f;
    }

    pub fn key_on(&mut self) {
        self.read_entry();
        self.sample_address = self.sample_start_address;
        self.brr_block_decoder.reset(0, 0);
        self.read_next_block();
        self.sample_pos = 0;
        self.next_sample = 0;
        self.read_next_sample();
        self.envelope.key_on();
    }

    pub fn key_off(&mut self) {
        self.envelope.key_off();
    }

    fn read_entry(&mut self) {
        self.sample_start_address = self.dsp().read_source_dir_start_address(self.source as i32);
        self.loop_start_address = self.dsp().read_source_dir_loop_address(self.source as i32);
    }

    fn read_next_block(&mut self) {
        let mut buf = [0; 9];
        for i in 0..9 {
            buf[i] = self.emulator().read_u8(self.sample_address + (i as u32));
        }
        self.brr_block_decoder.read(&buf);
        self.sample_address += 9;
    }

    fn read_next_sample(&mut self) {
        self.current_sample = self.next_sample;
        self.next_sample = self.brr_block_decoder.read_next_sample() as i32;
    }
}
<commit_msg>current/next_sample -> last/current_sample<commit_after>use super::dsp::Dsp;
use super::super::apu::Apu;
use super::envelope::Envelope;
use super::brr_block_decoder::BrrBlockDecoder;
use super::dsp_helpers;

#[derive(Clone, Copy)]
pub struct VoiceOutput {
    pub left_out: i32,
    pub right_out: i32,
    pub last_voice_out: i32
}

impl VoiceOutput {
    pub fn default() -> VoiceOutput {
        VoiceOutput {
            left_out: 0,
            right_out: 0,
            last_voice_out: 0
        }
    }
}

pub const VOICE_BUFFER_LEN: usize = 128;

// TODO: If Rust had facilities for specifying arrray sizes with generic parameters,
// this could be removed in favor of a more generalized RingBuffer.
pub struct VoiceBuffer {
    pub buffer: Box<[VoiceOutput; VOICE_BUFFER_LEN]>,
    pub pos: i32
}

impl VoiceBuffer {
    pub fn new() -> VoiceBuffer {
        VoiceBuffer {
            buffer: Box::new([VoiceOutput::default(); VOICE_BUFFER_LEN]),
            pos: 0
        }
    }

    pub fn reset(&mut self) {
        for i in 0..VOICE_BUFFER_LEN {
            self.buffer[i] = VoiceOutput::default();
        }
        self.pos = 0;
    }

    pub fn write(&mut self, value: VoiceOutput) {
        self.buffer[self.pos as usize] = value;
        self.pos = (self.pos + 1) % (VOICE_BUFFER_LEN as i32);
    }
}

pub struct Voice {
    dsp: *mut Dsp,
    emulator: *mut Apu,

    pub envelope: Box<Envelope>,

    pub vol_left: u8,
    pub vol_right: u8,
    pub pitch_low: u8,
    pitch_high: u8,
    pub source: u8,
    pub pitch_mod: bool,
    pub noise_on: bool,
    pub echo_on: bool,

    sample_start_address: u32,
    loop_start_address: u32,
    brr_block_decoder: Box<BrrBlockDecoder>,
    sample_address: u32,
    sample_pos: i32,
    current_sample: i32,
    last_sample: i32,

    pub output_buffer: Box<VoiceBuffer>,
    pub is_muted: bool
}

impl Voice {
    pub fn new(dsp: *mut Dsp, emulator: *mut Apu) -> Voice {
        let mut ret = Voice {
            dsp: dsp,
            emulator: emulator,

            envelope: Box::new(Envelope::new(dsp)),

            vol_left: 0,
            vol_right: 0,
            pitch_low: 0,
            pitch_high: 0,
            source: 0,
            pitch_mod: false,
            noise_on: false,
            echo_on: false,

            sample_start_address: 0,
            loop_start_address: 0,
            brr_block_decoder: Box::new(BrrBlockDecoder::new()),
            sample_address: 0,
            sample_pos: 0,
            current_sample: 0,
            next_sample: 0,
            last_sample: 0,

            output_buffer: Box::new(VoiceBuffer::new()),
            is_muted: false,
        };
        ret.reset();
        ret
    }

    #[inline]
    fn dsp(&self) -> &mut Dsp {
        unsafe {
            &mut (*self.dsp)
        }
    }

    #[inline]
    fn emulator(&self) -> &mut Apu {
        unsafe {
            &mut (*self.emulator)
        }
    }

    pub fn reset(&mut self) {
        self.envelope.reset();

        self.vol_left = 0;
        self.vol_right = 0;
        self.pitch_low = 0;
        self.pitch_high = 0x10;
        self.source = 0;
        self.pitch_mod = false;
        self.noise_on = false;

        self.sample_start_address = 0;
        self.loop_start_address = 0;
        self.brr_block_decoder.reset(0, 0);
        self.sample_address = 0;
        self.sample_pos = 0;
        self.current_sample = 0;
        self.last_sample = 0;

        self.output_buffer.reset();
        self.is_muted = false;
    }

    pub fn render_sample(&mut self, last_voice_out: i32, noise: i32) -> VoiceOutput {
        let mut pitch = ((self.pitch_high as i32) << 8) | (self.pitch_low as i32);
        if self.pitch_mod {
            pitch += ((last_voice_out >> 5) * pitch) >> 10;
        }
        if pitch < 0 {
            pitch = 0;
        }
        if pitch > 0x3fff {
            pitch = 0x3fff;
        }

        let mut sample = if !self.noise_on {
            let p1 = self.sample_pos;
            let p2 = 0x1000 - p1;
            dsp_helpers::clamp((self.current_sample * p1 + self.last_sample * p2) >> 12) & !1
        } else {
            ((noise * 2) as i16) as i32
        };

        self.envelope.tick();
        let env_level = self.envelope.level;

        sample = ((sample * env_level) >> 11) & !1;

        if self.brr_block_decoder.is_end && !self.brr_block_decoder.is_looping {
            self.envelope.key_off();
            self.envelope.level = 0;
        }

        self.sample_pos += pitch;
        while self.sample_pos >= 0x1000 {
            self.sample_pos -= 0x1000;
            self.read_next_sample();

            if self.brr_block_decoder.is_finished() {
                if self.brr_block_decoder.is_end && self.brr_block_decoder.is_looping {
                    self.read_entry();
                    self.sample_address = self.loop_start_address;
                }
                self.read_next_block();
            }
        }

        let ret =
            if !self.is_muted {
                VoiceOutput {
                    left_out: dsp_helpers::multiply_volume(sample, self.vol_left),
                    right_out: dsp_helpers::multiply_volume(sample, self.vol_right),
                    last_voice_out: sample
                }
            } else {
                VoiceOutput {
                    left_out: 0,
                    right_out: 0,
                    last_voice_out: 0
                }
            };
        self.output_buffer.write(ret);
        ret
    }

    pub fn set_pitch_high(&mut self, value: u8) {
        self.pitch_high = value & 0x3f;
    }

    pub fn key_on(&mut self) {
        self.read_entry();
        self.sample_address = self.sample_start_address;
        self.brr_block_decoder.reset(0, 0);
        self.read_next_block();
        self.sample_pos = 0;
        self.current_sample = 0;
        self.read_next_sample();
        self.envelope.key_on();
    }

    pub fn key_off(&mut self) {
        self.envelope.key_off();
    }

    fn read_entry(&mut self) {
        self.sample_start_address = self.dsp().read_source_dir_start_address(self.source as i32);
        self.loop_start_address = self.dsp().read_source_dir_loop_address(self.source as i32);
    }

    fn read_next_block(&mut self) {
        let mut buf = [0; 9];
        for i in 0..9 {
            buf[i] = self.emulator().read_u8(self.sample_address + (i as u32));
        }
        self.brr_block_decoder.read(&buf);
        self.sample_address += 9;
    }

    fn read_next_sample(&mut self) {
        self.last_sample = self.current_sample;
        self.current_sample = self.brr_block_decoder.read_next_sample() as i32;
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate enum_map;

use enum_map::{EnumMap, IntoIter};

use std::cell::RefCell;

#[derive(Copy, Clone, Debug, EnumMap, PartialEq)]
enum Example {
    A,
    B,
    C,
}

#[test]
fn test_bool() {
    let mut map = enum_map! { false => 24, true => 42 };
    assert_eq!(map[false], 24);
    assert_eq!(map[true], 42);
    map[false] += 1;
    assert_eq!(map[false], 25);
    for (key, item) in &mut map {
        if !key {
            *item += 1;
        }
    }
    assert_eq!(map[false], 26);
    assert_eq!(map[true], 42);
}

#[test]
fn test_option_bool() {
    let mut map = enum_map! { None => 1, Some(false) => 2, Some(true) => 3};
    assert_eq!(map[None], 1);
    assert_eq!(map[Some(false)], 2);
    assert_eq!(map[Some(true)], 3);
    map[None] = 4;
    map[Some(false)] = 5;
    map[Some(true)] = 6;
    assert_eq!(map[None], 4);
    assert_eq!(map[Some(false)], 5);
    assert_eq!(map[Some(true)], 6);
    assert_eq!(map.as_slice(), [4, 5, 6]);
    assert_eq!(
        map.into_iter().collect::<Vec<_>>(),
        [(None, 4), (Some(false), 5), (Some(true), 6)]
    );
}

#[test]
fn test_clone() {
    let map = enum_map! { false => 3, true => 5 };
    assert_eq!(map.clone(), map);
}

#[test]
fn test_debug() {
    let map = enum_map! { false => 3, true => 5 };
    assert_eq!(format!("{:?}", map), "{false: 3, true: 5}");
}

#[test]
fn discriminants() {
    #[derive(Debug, EnumMap, PartialEq)]
    enum Discriminants {
        A = 2000,
        B = 3000,
        C = 1000,
    }
    let mut map = EnumMap::new();
    map[Discriminants::A] = 3;
    map[Discriminants::B] = 2;
    map[Discriminants::C] = 1;
    let mut pairs = map.iter();
    assert_eq!(pairs.next(), Some((Discriminants::A, &3)));
    assert_eq!(pairs.next(), Some((Discriminants::B, &2)));
    assert_eq!(pairs.next(), Some((Discriminants::C, &1)));
    assert_eq!(pairs.next(), None);
}

#[test]
fn extend() {
    let mut map = enum_map! { _ => 0 };
    map.extend(vec![(Example::A, 3)]);
    map.extend(vec![(&Example::B, &4)]);
    assert_eq!(
        map,
        enum_map! { Example:: A => 3, Example:: B => 4, Example::C => 0 }
    );
}

#[test]
fn huge_enum() {
    #[derive(EnumMap)]
    enum Example {
        A,
        B,
        C,
        D,
        E,
        F,
        G,
        H,
        I,
        J,
        K,
        L,
        M,
        N,
        O,
        P,
        Q,
        R,
        S,
        T,
        U,
        V,
        W,
        X,
        Y,
        Z,
        Aa,
        Bb,
        Cc,
        Dd,
        Ee,
        Ff,
        Gg,
        Hh,
        Ii,
        Jj,
        Kk,
        Ll,
        Mm,
        Nn,
        Oo,
        Pp,
        Qq,
        Rr,
        Ss,
        Tt,
        Uu,
        Vv,
        Ww,
        Xx,
        Yy,
        Zz,
    }

    let map = enum_map! { _ => 2 };
    assert_eq!(map[Example::Xx], 2);
}

#[test]
fn iterator_len() {
    assert_eq!(
        enum_map! { Example::A | Example::B | Example::C => 0 }
            .iter()
            .len(),
        3
    );
}

#[test]
fn iterator_next_back() {
    assert_eq!(
        enum_map! { Example::A => 1, Example::B => 2, Example::C => 3 }
            .iter()
            .next_back(),
        Some((Example::C, &3))
    );
}

struct DropReporter<'a> {
    into: &'a RefCell<Vec<usize>>,
    value: usize,
}

impl<'a> Drop for DropReporter<'a> {
    fn drop(&mut self) {
        self.into.borrow_mut().push(self.value);
    }
}

#[test]
fn into_iter_drop() {
    let dropped = RefCell::new(Vec::new());
    let mut a: IntoIter<Example, _> = enum_map! {
        k => DropReporter {
            into: &dropped,
            value: k as usize,
        },
    }.into_iter();
    assert_eq!(a.next().unwrap().0, Example::A);
    assert_eq!(*dropped.borrow(), &[0]);
    drop(a);
    assert_eq!(*dropped.borrow(), &[0, 1, 2]);
}

#[test]
fn test_u8() {
    let map = enum_map! { b'a' => 4, _ => 0 };
    assert_eq!(map[b'a'], 4);
    assert_eq!(map[b'b'], 0);
}

#[derive(EnumMap)]
enum Void {}

#[test]
fn empty_map() {
    let void: EnumMap<Void, Void> = enum_map!{};
    assert!(void.is_empty());
}

#[test]
#[should_panic]
fn empty_value() {
    let _void: EnumMap<bool, Void> = enum_map! { _ => unreachable!() };
}
<commit_msg>Test whether Hash implementation works<commit_after>#[macro_use]
extern crate enum_map;

use enum_map::{EnumMap, IntoIter};

use std::cell::RefCell;
use std::collections::HashSet;

#[derive(Copy, Clone, Debug, EnumMap, PartialEq)]
enum Example {
    A,
    B,
    C,
}

#[test]
fn test_bool() {
    let mut map = enum_map! { false => 24, true => 42 };
    assert_eq!(map[false], 24);
    assert_eq!(map[true], 42);
    map[false] += 1;
    assert_eq!(map[false], 25);
    for (key, item) in &mut map {
        if !key {
            *item += 1;
        }
    }
    assert_eq!(map[false], 26);
    assert_eq!(map[true], 42);
}

#[test]
fn test_option_bool() {
    let mut map = enum_map! { None => 1, Some(false) => 2, Some(true) => 3};
    assert_eq!(map[None], 1);
    assert_eq!(map[Some(false)], 2);
    assert_eq!(map[Some(true)], 3);
    map[None] = 4;
    map[Some(false)] = 5;
    map[Some(true)] = 6;
    assert_eq!(map[None], 4);
    assert_eq!(map[Some(false)], 5);
    assert_eq!(map[Some(true)], 6);
    assert_eq!(map.as_slice(), [4, 5, 6]);
    assert_eq!(
        map.into_iter().collect::<Vec<_>>(),
        [(None, 4), (Some(false), 5), (Some(true), 6)]
    );
}

#[test]
fn test_clone() {
    let map = enum_map! { false => 3, true => 5 };
    assert_eq!(map.clone(), map);
}

#[test]
fn test_debug() {
    let map = enum_map! { false => 3, true => 5 };
    assert_eq!(format!("{:?}", map), "{false: 3, true: 5}");
}

#[test]
fn test_hash() {
    let map = enum_map! { false => 3, true => 5 };
    let mut set = HashSet::new();
    set.insert(map);
    assert!(set.contains(&map));
}

#[test]
fn discriminants() {
    #[derive(Debug, EnumMap, PartialEq)]
    enum Discriminants {
        A = 2000,
        B = 3000,
        C = 1000,
    }
    let mut map = EnumMap::new();
    map[Discriminants::A] = 3;
    map[Discriminants::B] = 2;
    map[Discriminants::C] = 1;
    let mut pairs = map.iter();
    assert_eq!(pairs.next(), Some((Discriminants::A, &3)));
    assert_eq!(pairs.next(), Some((Discriminants::B, &2)));
    assert_eq!(pairs.next(), Some((Discriminants::C, &1)));
    assert_eq!(pairs.next(), None);
}

#[test]
fn extend() {
    let mut map = enum_map! { _ => 0 };
    map.extend(vec![(Example::A, 3)]);
    map.extend(vec![(&Example::B, &4)]);
    assert_eq!(
        map,
        enum_map! { Example:: A => 3, Example:: B => 4, Example::C => 0 }
    );
}

#[test]
fn huge_enum() {
    #[derive(EnumMap)]
    enum Example {
        A,
        B,
        C,
        D,
        E,
        F,
        G,
        H,
        I,
        J,
        K,
        L,
        M,
        N,
        O,
        P,
        Q,
        R,
        S,
        T,
        U,
        V,
        W,
        X,
        Y,
        Z,
        Aa,
        Bb,
        Cc,
        Dd,
        Ee,
        Ff,
        Gg,
        Hh,
        Ii,
        Jj,
        Kk,
        Ll,
        Mm,
        Nn,
        Oo,
        Pp,
        Qq,
        Rr,
        Ss,
        Tt,
        Uu,
        Vv,
        Ww,
        Xx,
        Yy,
        Zz,
    }

    let map = enum_map! { _ => 2 };
    assert_eq!(map[Example::Xx], 2);
}

#[test]
fn iterator_len() {
    assert_eq!(
        enum_map! { Example::A | Example::B | Example::C => 0 }
            .iter()
            .len(),
        3
    );
}

#[test]
fn iterator_next_back() {
    assert_eq!(
        enum_map! { Example::A => 1, Example::B => 2, Example::C => 3 }
            .iter()
            .next_back(),
        Some((Example::C, &3))
    );
}

struct DropReporter<'a> {
    into: &'a RefCell<Vec<usize>>,
    value: usize,
}

impl<'a> Drop for DropReporter<'a> {
    fn drop(&mut self) {
        self.into.borrow_mut().push(self.value);
    }
}

#[test]
fn into_iter_drop() {
    let dropped = RefCell::new(Vec::new());
    let mut a: IntoIter<Example, _> = enum_map! {
        k => DropReporter {
            into: &dropped,
            value: k as usize,
        },
    }.into_iter();
    assert_eq!(a.next().unwrap().0, Example::A);
    assert_eq!(*dropped.borrow(), &[0]);
    drop(a);
    assert_eq!(*dropped.borrow(), &[0, 1, 2]);
}

#[test]
fn test_u8() {
    let map = enum_map! { b'a' => 4, _ => 0 };
    assert_eq!(map[b'a'], 4);
    assert_eq!(map[b'b'], 0);
}

#[derive(EnumMap)]
enum Void {}

#[test]
fn empty_map() {
    let void: EnumMap<Void, Void> = enum_map!{};
    assert!(void.is_empty());
}

#[test]
#[should_panic]
fn empty_value() {
    let _void: EnumMap<bool, Void> = enum_map! { _ => unreachable!() };
}
<|endoftext|>