<commit_before>pub static RUSTUP_HELP: &'static str =
r"DISCUSSION:
    rustup installs The Rust Programming Language from the official
    release channels, enabling you to easily switch between stable,
    beta, and nightly compilers and keep them updated. It makes
    cross-compiling simpler with binary builds of the standard library
    for common platforms.

    If you are new to Rust consider running `rustup doc --book` to
    learn Rust.";

pub static SHOW_HELP: &'static str =
r"DISCUSSION:
    Shows the name of the active toolchain and the version of `rustc`.

    If the active toolchain has installed support for additional
    compilation targets, then they are listed as well.

    If there are multiple toolchains installed then all installed
    toolchains are listed as well.";

pub static UPDATE_HELP: &'static str =
r"DISCUSSION:
    With no toolchain specified, the `update` command updates each of
    the installed toolchains from the official release channels, then
    updates rustup itself.

    If given a toolchain argument then `update` updates that
    toolchain, the same as `rustup toolchain install`.

    'toolchain' specifies a toolchain name, such as 'stable',
    'nightly', or '1.8.0'. For more information see `rustup help
    toolchain`.";

pub static INSTALL_HELP: &'static str =
r"DISCUSSION:
    Installs a specific rust toolchain.

    The 'install' command is an alias for 'rustup update <toolchain>'.

    'toolchain' specifies a toolchain name, such as 'stable',
    'nightly', or '1.8.0'. For more information see `rustup help
    toolchain`.";

pub static DEFAULT_HELP: &'static str =
r"DISCUSSION:
    Sets the default toolchain to the one specified. If the toolchain
    is not already installed then it is installed first.";

pub static TOOLCHAIN_HELP: &'static str =
r"DISCUSSION:
    Many `rustup` commands deal with *toolchains*, a single
    installation of the Rust compiler. `rustup` supports multiple
    types of toolchains. The most basic track the official release
    channels: 'stable', 'beta' and 'nightly'; but `rustup` can also
    install toolchains from the official archives, for alternate host
    platforms, and from local builds.

    Standard release channel toolchain names have the following form:

        <channel>[-<date>][-<host>]

        <channel>       = stable|beta|nightly|<version>
        <date>          = YYYY-MM-DD
        <host>          = <target-triple>

    'channel' is either a named release channel or an explicit version
    number, such as '1.8.0'. Channel names can be optionally appended
    with an archive date, as in 'nightly-2014-12-18', in which case
    the toolchain is downloaded from the archive for that date.

    Finally, the host may be specified as a target triple. This is
    most useful for installing a 32-bit compiler on a 64-bit platform,
    or for installing the [MSVC-based toolchain] on Windows. For
    example:

        rustup toolchain install stable-x86_64-pc-windows-msvc

    For convenience, elements of the target triple that are omitted
    will be inferred, so the above could be written:

        $ rustup default stable-msvc

    rustup can also manage symlinked local toolchain builds, which are
    often used to for developing Rust itself. For more information see
    `rustup toolchain help link`.";

pub static TOOLCHAIN_LINK_HELP: &'static str =
r"DISCUSSION:
    'toolchain' is the custom name to be assigned to the new toolchain.
    Any name is permitted as long as it does not fully match an initial
    substring of a standard release channel. For example, you can use
    the names 'latest' or '2017-04-01' but you cannot use 'stable' or
    'beta-i686' or 'nightly-x86_64-unknown-linux-gnu'.

    'path' specifies the directory where the binaries and libraries for
    the custom toolchain can be found. For example, when used for
    development of Rust itself, toolchains can be linked directly out of
    the build directory. After building, you can test out different
    compiler versions as follows:

        $ rustup toolchain link latest-stage1 build/x86_64-unknown-linux-gnu/stage1
        $ rustup override set latest-stage1

    If you now compile a crate in the current directory, the custom
    toolchain 'latest-stage1' will be used.";

pub static OVERRIDE_HELP: &'static str =
r"DISCUSSION:
    Overrides configure rustup to use a specific toolchain when
    running in a specific directory.

    Directories can be assigned their own Rust toolchain with `rustup
    override`. When a directory has an override then any time `rustc`
    or `cargo` is run inside that directory, or one of its child
    directories, the override toolchain will be invoked.

    To pin to a specific nightly:

        rustup override set nightly-2014-12-18

    Or a specific stable release:

        rustup override set 1.0.0

    To see the active toolchain use `rustup show`. To remove the
    override and use the default toolchain again, `rustup override
    unset`.";

pub static OVERRIDE_UNSET_HELP: &'static str =
r"DISCUSSION:
    If `--path` argument is present, removes the override toolchain
    for the specified directory. If `--nonexistent` argument is
    present, removes the override toolchain for all nonexistent
    directories. Otherwise, removes the override toolchain for the
    current directory.";

pub static RUN_HELP: &'static str =
r"DISCUSSION:
    Configures an environment to use the given toolchain and then runs
    the specified program. The command may be any program, not just
    rustc or cargo. This can be used for testing arbitrary toolchains
    without setting an override.

    Commands explicitly proxied by `rustup` (such as `rustc` and
    `cargo`) also have a shorthand for this available. The toolchain
    can be set by using `+toolchain` as the first argument. These are
    equivalent:

        cargo +nightly build

        rustup run nightly cargo build";

pub static DOC_HELP: &'static str =
r"DISCUSSION:
    Opens the documentation for the currently active toolchain with
    the default browser.

    By default, it opens the documentation index. Use the various
    flags to open specific pieces of documentation.";

pub static COMPLETIONS_HELP: &'static str =
r"DISCUSSION:
    One can generate a completion script for `rustup` that is
    compatible with a given shell. The script is output on `stdout`
    allowing one to re-direct the output to the file of their
    choosing. Where you place the file will depend on which shell, and
    which operating system you are using. Your particular
    configuration may also determine where these scripts need to be
    placed.

    Here are some common set ups for the three supported shells under
    Unix and similar operating systems (such as GNU/Linux).

    BASH:

    Completion files are commonly stored in `/etc/bash_completion.d/`

    Run the command:

    `rustup completions bash > /etc/bash_completion.d/rustup.bash-completion`

    This installs the completion script. You may have to log out and
    log back in to your shell session for the changes to take affect.

    BASH (macOS/Homebrew):

    Homebrew stores bash completion files within the Homebrew directory.
    With the `bash-completion` brew formula installed, run the command:

    `rustup completions bash > $(brew --prefix)/etc/bash_completion.d/rustup.bash-completion`

    FISH:

    Fish completion files are commonly stored in
    `$HOME/.config/fish/completions`

    Run the command:
    `rustup completions fish > ~/.config/fish/completions/rustup.fish`

    This installs the completion script. You may have to log out and
    log back in to your shell session for the changes to take affect.

    ZSH:

    ZSH completions are commonly stored in any directory listed in
    your `$fpath` variable. To use these completions, you must either
    add the generated script to one of those directories, or add your
    own to this list.

    Adding a custom directory is often the safest bet if you are
    unsure of which directory to use. First create the directory; for
    this example we'll create a hidden directory inside our `$HOME`
    directory

    `mkdir ~/.zfunc`

    Then add the following lines to your `.zshrc` just before
    `compinit`

    `fpath+=~/.zfunc`

    Now you can install the completions script using the following
    command

    `rustup completions zsh > ~/.zfunc/_rustup`

    You must then either log out and log back in, or simply run

    `exec zsh`

    For the new completions to take affect.

    CUSTOM LOCATIONS:

    Alternatively, you could save these files to the place of your
    choosing, such as a custom directory inside your $HOME. Doing so
    will require you to add the proper directives, such as `source`ing
    inside your login script. Consult your shells documentation for
    how to add such directives.

    POWERSHELL:

    The powershell completion scripts require PowerShell v5.0+ (which
    comes Windows 10, but can be downloaded separately for windows 7
    or 8.1).

    First, check if a profile has already been set

    `PS C:\> Test-Path $profile`

    If the above command returns `False` run the following

    `PS C:\> New-Item -path $profile -type file -force`

    Now open the file provided by `$profile` (if you used the
    `New-Item` command it will be
    `%USERPROFILE%\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1`

    Next, we either save the completions file into our profile, or
    into a separate file and source it inside our profile. To save the
    completions into our profile simply use

    `PS C:\> rustup completions powershell >> %USERPROFILE%\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1`";
<commit_msg>Auto merge of #1107 - rap2hpoutre:patch-1, r=Diggsey<commit_after>pub static RUSTUP_HELP: &'static str =
r"DISCUSSION:
    rustup installs The Rust Programming Language from the official
    release channels, enabling you to easily switch between stable,
    beta, and nightly compilers and keep them updated. It makes
    cross-compiling simpler with binary builds of the standard library
    for common platforms.

    If you are new to Rust consider running `rustup doc --book` to
    learn Rust.";

pub static SHOW_HELP: &'static str =
r"DISCUSSION:
    Shows the name of the active toolchain and the version of `rustc`.

    If the active toolchain has installed support for additional
    compilation targets, then they are listed as well.

    If there are multiple toolchains installed then all installed
    toolchains are listed as well.";

pub static UPDATE_HELP: &'static str =
r"DISCUSSION:
    With no toolchain specified, the `update` command updates each of
    the installed toolchains from the official release channels, then
    updates rustup itself.

    If given a toolchain argument then `update` updates that
    toolchain, the same as `rustup toolchain install`.

    'toolchain' specifies a toolchain name, such as 'stable',
    'nightly', or '1.8.0'. For more information see `rustup help
    toolchain`.";

pub static INSTALL_HELP: &'static str =
r"DISCUSSION:
    Installs a specific rust toolchain.

    The 'install' command is an alias for 'rustup update <toolchain>'.

    'toolchain' specifies a toolchain name, such as 'stable',
    'nightly', or '1.8.0'. For more information see `rustup help
    toolchain`.";

pub static DEFAULT_HELP: &'static str =
r"DISCUSSION:
    Sets the default toolchain to the one specified. If the toolchain
    is not already installed then it is installed first.";

pub static TOOLCHAIN_HELP: &'static str =
r"DISCUSSION:
    Many `rustup` commands deal with *toolchains*, a single
    installation of the Rust compiler. `rustup` supports multiple
    types of toolchains. The most basic track the official release
    channels: 'stable', 'beta' and 'nightly'; but `rustup` can also
    install toolchains from the official archives, for alternate host
    platforms, and from local builds.

    Standard release channel toolchain names have the following form:

        <channel>[-<date>][-<host>]

        <channel>       = stable|beta|nightly|<version>
        <date>          = YYYY-MM-DD
        <host>          = <target-triple>

    'channel' is either a named release channel or an explicit version
    number, such as '1.8.0'. Channel names can be optionally appended
    with an archive date, as in 'nightly-2017-05-09', in which case
    the toolchain is downloaded from the archive for that date.

    Finally, the host may be specified as a target triple. This is
    most useful for installing a 32-bit compiler on a 64-bit platform,
    or for installing the [MSVC-based toolchain] on Windows. For
    example:

        rustup toolchain install stable-x86_64-pc-windows-msvc

    For convenience, elements of the target triple that are omitted
    will be inferred, so the above could be written:

        $ rustup default stable-msvc

    rustup can also manage symlinked local toolchain builds, which are
    often used to for developing Rust itself. For more information see
    `rustup toolchain help link`.";

pub static TOOLCHAIN_LINK_HELP: &'static str =
r"DISCUSSION:
    'toolchain' is the custom name to be assigned to the new toolchain.
    Any name is permitted as long as it does not fully match an initial
    substring of a standard release channel. For example, you can use
    the names 'latest' or '2017-04-01' but you cannot use 'stable' or
    'beta-i686' or 'nightly-x86_64-unknown-linux-gnu'.

    'path' specifies the directory where the binaries and libraries for
    the custom toolchain can be found. For example, when used for
    development of Rust itself, toolchains can be linked directly out of
    the build directory. After building, you can test out different
    compiler versions as follows:

        $ rustup toolchain link latest-stage1 build/x86_64-unknown-linux-gnu/stage1
        $ rustup override set latest-stage1

    If you now compile a crate in the current directory, the custom
    toolchain 'latest-stage1' will be used.";

pub static OVERRIDE_HELP: &'static str =
r"DISCUSSION:
    Overrides configure rustup to use a specific toolchain when
    running in a specific directory.

    Directories can be assigned their own Rust toolchain with `rustup
    override`. When a directory has an override then any time `rustc`
    or `cargo` is run inside that directory, or one of its child
    directories, the override toolchain will be invoked.

    To pin to a specific nightly:

        rustup override set nightly-2014-12-18

    Or a specific stable release:

        rustup override set 1.0.0

    To see the active toolchain use `rustup show`. To remove the
    override and use the default toolchain again, `rustup override
    unset`.";

pub static OVERRIDE_UNSET_HELP: &'static str =
r"DISCUSSION:
    If `--path` argument is present, removes the override toolchain
    for the specified directory. If `--nonexistent` argument is
    present, removes the override toolchain for all nonexistent
    directories. Otherwise, removes the override toolchain for the
    current directory.";

pub static RUN_HELP: &'static str =
r"DISCUSSION:
    Configures an environment to use the given toolchain and then runs
    the specified program. The command may be any program, not just
    rustc or cargo. This can be used for testing arbitrary toolchains
    without setting an override.

    Commands explicitly proxied by `rustup` (such as `rustc` and
    `cargo`) also have a shorthand for this available. The toolchain
    can be set by using `+toolchain` as the first argument. These are
    equivalent:

        cargo +nightly build

        rustup run nightly cargo build";

pub static DOC_HELP: &'static str =
r"DISCUSSION:
    Opens the documentation for the currently active toolchain with
    the default browser.

    By default, it opens the documentation index. Use the various
    flags to open specific pieces of documentation.";

pub static COMPLETIONS_HELP: &'static str =
r"DISCUSSION:
    One can generate a completion script for `rustup` that is
    compatible with a given shell. The script is output on `stdout`
    allowing one to re-direct the output to the file of their
    choosing. Where you place the file will depend on which shell, and
    which operating system you are using. Your particular
    configuration may also determine where these scripts need to be
    placed.

    Here are some common set ups for the three supported shells under
    Unix and similar operating systems (such as GNU/Linux).

    BASH:

    Completion files are commonly stored in `/etc/bash_completion.d/`

    Run the command:

    `rustup completions bash > /etc/bash_completion.d/rustup.bash-completion`

    This installs the completion script. You may have to log out and
    log back in to your shell session for the changes to take affect.

    BASH (macOS/Homebrew):

    Homebrew stores bash completion files within the Homebrew directory.
    With the `bash-completion` brew formula installed, run the command:

    `rustup completions bash > $(brew --prefix)/etc/bash_completion.d/rustup.bash-completion`

    FISH:

    Fish completion files are commonly stored in
    `$HOME/.config/fish/completions`

    Run the command:
    `rustup completions fish > ~/.config/fish/completions/rustup.fish`

    This installs the completion script. You may have to log out and
    log back in to your shell session for the changes to take affect.

    ZSH:

    ZSH completions are commonly stored in any directory listed in
    your `$fpath` variable. To use these completions, you must either
    add the generated script to one of those directories, or add your
    own to this list.

    Adding a custom directory is often the safest bet if you are
    unsure of which directory to use. First create the directory; for
    this example we'll create a hidden directory inside our `$HOME`
    directory

    `mkdir ~/.zfunc`

    Then add the following lines to your `.zshrc` just before
    `compinit`

    `fpath+=~/.zfunc`

    Now you can install the completions script using the following
    command

    `rustup completions zsh > ~/.zfunc/_rustup`

    You must then either log out and log back in, or simply run

    `exec zsh`

    For the new completions to take affect.

    CUSTOM LOCATIONS:

    Alternatively, you could save these files to the place of your
    choosing, such as a custom directory inside your $HOME. Doing so
    will require you to add the proper directives, such as `source`ing
    inside your login script. Consult your shells documentation for
    how to add such directives.

    POWERSHELL:

    The powershell completion scripts require PowerShell v5.0+ (which
    comes Windows 10, but can be downloaded separately for windows 7
    or 8.1).

    First, check if a profile has already been set

    `PS C:\> Test-Path $profile`

    If the above command returns `False` run the following

    `PS C:\> New-Item -path $profile -type file -force`

    Now open the file provided by `$profile` (if you used the
    `New-Item` command it will be
    `%USERPROFILE%\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1`

    Next, we either save the completions file into our profile, or
    into a separate file and source it inside our profile. To save the
    completions into our profile simply use

    `PS C:\> rustup completions powershell >> %USERPROFILE%\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1`";
<|endoftext|>


<commit_before>// Copyright 2016 `multipart` Crate Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://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.

//! Boundary parsing for `multipart` requests.

use super::buf_redux::BufReader;
use super::{safemem, twoway};

use log::LogLevel;

use std::cmp;
use std::borrow::Borrow;

use std::io;
use std::io::prelude::*;

/// A struct implementing `Read` and `BufRead` that will yield bytes until it sees a given sequence.
#[derive(Debug)]
pub struct BoundaryReader<R> {
    source: BufReader<R>,
    boundary: Vec<u8>,
    search_idx: usize,
    boundary_read: bool,
    at_end: bool,
}

impl<R> BoundaryReader<R> where R: Read {
    #[doc(hidden)]
    pub fn from_reader<B: Into<Vec<u8>>>(reader: R, boundary: B) -> BoundaryReader<R> {
        let mut boundary = boundary.into();
        safemem::prepend(b"--", &mut boundary);

        BoundaryReader {
            source: BufReader::new(reader),
            boundary: boundary,
            search_idx: 0,
            boundary_read: false,
            at_end: false,
        }
    }

    fn read_to_boundary(&mut self) -> io::Result<&[u8]> {
        // Make sure there's enough bytes in the buffer to positively identify the boundary.
        let min_len = self.search_idx + (self.boundary.len() * 2);

        let buf = fill_buf_min(&mut self.source, min_len)?;

        if buf.is_empty() {
            debug!("fill_buf_min returned zero-sized buf");
            self.at_end = true;
            return Ok(buf);
        }

        trace!("Buf: {:?}", String::from_utf8_lossy(buf));

        debug!("Before-loop Buf len: {} Search idx: {} Boundary read: {:?}",
               buf.len(), self.search_idx, self.boundary_read);

        if !self.boundary_read && self.search_idx < buf.len() {
            let lookahead = &buf[self.search_idx..];

            debug!("Find boundary loop! Lookahead len: {}", lookahead.len());

            // Look for the boundary, or if it isn't found, stop near the end.
            match twoway::find_bytes(lookahead, &self.boundary) {
                Some(found_idx) => {
                    self.search_idx += found_idx;
                    self.boundary_read = true;
                },
                None => {
                    self.search_idx += lookahead.len().saturating_sub(self.boundary.len() + 2);
                }
            }
        }

        debug!("After-loop Buf len: {} Search idx: {} Boundary read: {:?}",
               buf.len(), self.search_idx, self.boundary_read);

        // If the two bytes before the boundary are a CR-LF, we need to back up
        // the cursor so we don't yield bytes that client code isn't expecting.
        if self.boundary_read && self.search_idx >= 2 {
            let two_bytes_before = &buf[self.search_idx - 2 .. self.search_idx];

            trace!("Two bytes before: {:?} ({:?}) (\"\\r\\n\": {:?})",
                   String::from_utf8_lossy(two_bytes_before), two_bytes_before, b"\r\n");

            if two_bytes_before == &*b"\r\n" {
                debug!("Subtract two!");
                self.search_idx -= 2;
            }
        }

        let ret_buf = &buf[..self.search_idx];

        trace!("Returning buf: {:?}", String::from_utf8_lossy(ret_buf));

        Ok(ret_buf)
    }

    #[doc(hidden)]
    pub fn consume_boundary(&mut self) -> io::Result<bool> {
        if self.at_end {
            return Ok(true);
        }

        while !(self.boundary_read || self.at_end){
            debug!("Boundary not found yet");

            let buf_len = self.read_to_boundary()?.len();

            debug!("Discarding {} bytes", buf_len);

            if buf_len == 0 {
                break;
            }

            self.consume(buf_len);
        }

        self.source.consume(self.search_idx);
        self.search_idx = 0;

        trace!("Consumed up to self.search_idx, remaining buf: {:?}",
               String::from_utf8_lossy(self.source.get_buf()));

        let consume_amt = {
            let buf = self.source.get_buf();
            self.boundary.len() + if buf.len() >=2 && buf[..2] == *b"\r\n" { 2 } else { 0 }
        };

        self.source.consume(consume_amt);
        self.boundary_read = false;

        let mut bytes_after = [0, 0];

        let read = self.source.read(&mut bytes_after)?;

        if read == 1 {
            let _ = self.source.read(&mut bytes_after[1..])?;
        }

        if bytes_after == *b"--" {
            self.at_end = true;
        } else if bytes_after != *b"\r\n" {
            debug!("Unexpected bytes following boundary: {:?}", String::from_utf8_lossy(&bytes_after));
        }

        trace!("Consumed boundary (at_end: {:?}), remaining buf: {:?}", self.at_end,
               String::from_utf8_lossy(self.source.get_buf()));

        Ok(self.at_end)
    }
}

impl<R> Borrow<R> for BoundaryReader<R> {
    fn borrow(&self) -> &R {
        self.source.get_ref()
    }
}

impl<R> Read for BoundaryReader<R> where R: Read {
    fn read(&mut self, out: &mut [u8]) -> io::Result<usize> {
        let read = {
            let mut buf = self.read_to_boundary()?;
            // This shouldn't ever be an error so unwrapping is fine.
            buf.read(out).unwrap()
        };

        self.consume(read);
        Ok(read)
    }
}

impl<R> BufRead for BoundaryReader<R> where R: Read {
    fn fill_buf(&mut self) -> io::Result<&[u8]> {
        self.read_to_boundary()
    }

    fn consume(&mut self, amt: usize) {
        let true_amt = cmp::min(amt, self.search_idx);

        debug!("Consume! amt: {} true amt: {}", amt, true_amt);

        self.source.consume(true_amt);
        self.search_idx -= true_amt;
    }
}

fn fill_buf_min<R: Read>(buf: &mut BufReader<R>, min: usize) -> io::Result<&[u8]> {
    const MAX_ATTEMPTS: usize = 3;

    let mut attempts = 0;

    while buf.available() < min && attempts < MAX_ATTEMPTS {
        if buf.read_into_buf()? == 0 { break; };
        attempts += 1;
    }

    Ok(buf.get_buf())
}

#[cfg(test)]
mod test {
    use super::BoundaryReader;

    use std::io;
    use std::io::prelude::*;

    const BOUNDARY: &'static str = "boundary";
    const TEST_VAL: &'static str = "--boundary\r
dashed-value-1\r
--boundary\r
dashed-value-2\r
--boundary--";

    #[test]
    fn test_boundary() {
        let _ = ::env_logger::init();
        debug!("Testing boundary (no split)");

        let src = &mut TEST_VAL.as_bytes();
        let reader = BoundaryReader::from_reader(src, BOUNDARY);

        test_boundary_reader(reader);
    }

    struct SplitReader<'a> {
        left: &'a [u8],
        right: &'a [u8],
    }

    impl<'a> SplitReader<'a> {
        fn split(data: &'a [u8], at: usize) -> SplitReader<'a> {
            let (left, right) = data.split_at(at);

            SplitReader {
                left: left,
                right: right,
            }
        }
    }

    impl<'a> Read for SplitReader<'a> {
        fn read(&mut self, dst: &mut [u8]) -> io::Result<usize> {
            fn copy_bytes_partial(src: &mut &[u8], dst: &mut [u8]) -> usize {
                src.read(dst).unwrap()
            }

            let mut copy_amt = copy_bytes_partial(&mut self.left, dst);

            if copy_amt == 0 {
                copy_amt = copy_bytes_partial(&mut self.right, dst)
            };

            Ok(copy_amt)
        }
    }

    #[test]
    fn test_split_boundary() {
        let _ = ::env_logger::init();
        debug!("Testing boundary (split)");

        // Substitute for `.step_by()` being unstable.
        for split_at in 0 .. TEST_VAL.len(){
            debug!("Testing split at: {}", split_at);

            let src = SplitReader::split(TEST_VAL.as_bytes(), split_at);
            let reader = BoundaryReader::from_reader(src, BOUNDARY);
            test_boundary_reader(reader);
        }

    }

    fn test_boundary_reader<R: Read>(mut reader: BoundaryReader<R>) {
        let ref mut buf = String::new();

        debug!("Read 1");
        let _ = reader.read_to_string(buf).unwrap();
        assert!(buf.is_empty(), "Buffer not empty: {:?}", buf);
        buf.clear();

        debug!("Consume 1");
        reader.consume_boundary().unwrap();

        debug!("Read 2");
        let _ = reader.read_to_string(buf).unwrap();
        assert_eq!(buf, "dashed-value-1");
        buf.clear();

        debug!("Consume 2");
        reader.consume_boundary().unwrap();

        debug!("Read 3");
        let _ = reader.read_to_string(buf).unwrap();
        assert_eq!(buf, "dashed-value-2");
        buf.clear();

        debug!("Consume 3");
        reader.consume_boundary().unwrap();

        debug!("Read 4");
        let _ = reader.read_to_string(buf).unwrap();
        assert_eq!(buf, "");
    }
}
<commit_msg>Cleanup formatting<commit_after>// Copyright 2016 `multipart` Crate Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://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.

//! Boundary parsing for `multipart` requests.

use super::buf_redux::BufReader;
use super::{safemem, twoway};

use log::LogLevel;

use std::cmp;
use std::borrow::Borrow;

use std::io;
use std::io::prelude::*;

/// A struct implementing `Read` and `BufRead` that will yield bytes until it sees a given sequence.
#[derive(Debug)]
pub struct BoundaryReader<R> {
    source: BufReader<R>,
    boundary: Vec<u8>,
    search_idx: usize,
    boundary_read: bool,
    at_end: bool,
}

impl<R> BoundaryReader<R> where R: Read {
    #[doc(hidden)]
    pub fn from_reader<B: Into<Vec<u8>>>(reader: R, boundary: B) -> BoundaryReader<R> {
        let mut boundary = boundary.into();
        safemem::prepend(b"--", &mut boundary);

        BoundaryReader {
            source: BufReader::new(reader),
            boundary: boundary,
            search_idx: 0,
            boundary_read: false,
            at_end: false,
        }
    }

    fn read_to_boundary(&mut self) -> io::Result<&[u8]> {
        // Make sure there's enough bytes in the buffer to positively identify the boundary.
        let min_len = self.search_idx + (self.boundary.len() * 2);

        let buf = fill_buf_min(&mut self.source, min_len)?;

        if buf.is_empty() {
            debug!("fill_buf_min returned zero-sized buf");
            self.at_end = true;
            return Ok(buf);
        }

        trace!("Buf: {:?}", String::from_utf8_lossy(buf));

        debug!("Before-loop Buf len: {} Search idx: {} Boundary read: {:?}",
               buf.len(), self.search_idx, self.boundary_read);

        if !self.boundary_read && self.search_idx < buf.len() {
            let lookahead = &buf[self.search_idx..];

            debug!("Find boundary loop! Lookahead len: {}", lookahead.len());

            // Look for the boundary, or if it isn't found, stop near the end.
            match twoway::find_bytes(lookahead, &self.boundary) {
                Some(found_idx) => {
                    self.search_idx += found_idx;
                    self.boundary_read = true;
                },
                None => {
                    self.search_idx += lookahead.len().saturating_sub(self.boundary.len() + 2);
                }
            }
        }

        debug!("After-loop Buf len: {} Search idx: {} Boundary read: {:?}",
               buf.len(), self.search_idx, self.boundary_read);

        // If the two bytes before the boundary are a CR-LF, we need to back up
        // the cursor so we don't yield bytes that client code isn't expecting.
        if self.boundary_read && self.search_idx >= 2 {
            let two_bytes_before = &buf[self.search_idx - 2 .. self.search_idx];

            trace!("Two bytes before: {:?} ({:?}) (\"\\r\\n\": {:?})",
                   String::from_utf8_lossy(two_bytes_before), two_bytes_before, b"\r\n");

            if two_bytes_before == &*b"\r\n" {
                debug!("Subtract two!");
                self.search_idx -= 2;
            }
        }

        let ret_buf = &buf[..self.search_idx];

        trace!("Returning buf: {:?}", String::from_utf8_lossy(ret_buf));

        Ok(ret_buf)
    }

    #[doc(hidden)]
    pub fn consume_boundary(&mut self) -> io::Result<bool> {
        if self.at_end {
            return Ok(true);
        }

        while !(self.boundary_read || self.at_end){
            debug!("Boundary not found yet");

            let buf_len = self.read_to_boundary()?.len();

            debug!("Discarding {} bytes", buf_len);

            if buf_len == 0 {
                break;
            }

            self.consume(buf_len);
        }

        self.source.consume(self.search_idx);
        self.search_idx = 0;

        trace!("Consumed up to self.search_idx, remaining buf: {:?}",
               String::from_utf8_lossy(self.source.get_buf()));

        let consume_amt = {
            let buf = self.source.get_buf();
            self.boundary.len() + if buf.len() >=2 && buf[..2] == *b"\r\n" { 2 } else { 0 }
        };

        self.source.consume(consume_amt);
        self.boundary_read = false;

        let mut bytes_after = [0, 0];

        let read = self.source.read(&mut bytes_after)?;

        if read == 1 {
            let _ = self.source.read(&mut bytes_after[1..])?;
        }

        if bytes_after == *b"--" {
            self.at_end = true;
        } else if bytes_after != *b"\r\n" {
            debug!("Unexpected bytes following boundary: {:?}", String::from_utf8_lossy(&bytes_after));
        }

        trace!("Consumed boundary (at_end: {:?}), remaining buf: {:?}", self.at_end,
               String::from_utf8_lossy(self.source.get_buf()));

        Ok(self.at_end)
    }
}

impl<R> Borrow<R> for BoundaryReader<R> {
    fn borrow(&self) -> &R {
        self.source.get_ref()
    }
}

impl<R> Read for BoundaryReader<R> where R: Read {
    fn read(&mut self, out: &mut [u8]) -> io::Result<usize> {
        let read = {
            let mut buf = self.read_to_boundary()?;
            // This shouldn't ever be an error so unwrapping is fine.
            buf.read(out).unwrap()
        };

        self.consume(read);
        Ok(read)
    }
}

impl<R> BufRead for BoundaryReader<R> where R: Read {
    fn fill_buf(&mut self) -> io::Result<&[u8]> {
        self.read_to_boundary()
    }

    fn consume(&mut self, amt: usize) {
        let true_amt = cmp::min(amt, self.search_idx);

        debug!("Consume! amt: {} true amt: {}", amt, true_amt);

        self.source.consume(true_amt);
        self.search_idx -= true_amt;
    }
}

fn fill_buf_min<R: Read>(buf: &mut BufReader<R>, min: usize) -> io::Result<&[u8]> {
    const MAX_ATTEMPTS: usize = 3;

    let mut attempts = 0;

    while buf.available() < min && attempts < MAX_ATTEMPTS {
        if buf.read_into_buf()? == 0 { break; };
        attempts += 1;
    }

    Ok(buf.get_buf())
}

#[cfg(test)]
mod test {
    use super::BoundaryReader;

    use std::io;
    use std::io::prelude::*;

    const BOUNDARY: &'static str = "boundary";
    const TEST_VAL: &'static str = "--boundary\r\n\
                                    dashed-value-1\r\n\
                                    --boundary\r\n\
                                    dashed-value-2\r\n\
                                    --boundary--";

    #[test]
    fn test_boundary() {
        let _ = ::env_logger::init();
        debug!("Testing boundary (no split)");

        let src = &mut TEST_VAL.as_bytes();
        let reader = BoundaryReader::from_reader(src, BOUNDARY);

        test_boundary_reader(reader);
    }

    struct SplitReader<'a> {
        left: &'a [u8],
        right: &'a [u8],
    }

    impl<'a> SplitReader<'a> {
        fn split(data: &'a [u8], at: usize) -> SplitReader<'a> {
            let (left, right) = data.split_at(at);

            SplitReader {
                left: left,
                right: right,
            }
        }
    }

    impl<'a> Read for SplitReader<'a> {
        fn read(&mut self, dst: &mut [u8]) -> io::Result<usize> {
            fn copy_bytes_partial(src: &mut &[u8], dst: &mut [u8]) -> usize {
                src.read(dst).unwrap()
            }

            let mut copy_amt = copy_bytes_partial(&mut self.left, dst);

            if copy_amt == 0 {
                copy_amt = copy_bytes_partial(&mut self.right, dst)
            };

            Ok(copy_amt)
        }
    }

    #[test]
    fn test_split_boundary() {
        let _ = ::env_logger::init();
        debug!("Testing boundary (split)");

        // Substitute for `.step_by()` being unstable.
        for split_at in 0 .. TEST_VAL.len(){
            debug!("Testing split at: {}", split_at);

            let src = SplitReader::split(TEST_VAL.as_bytes(), split_at);
            let reader = BoundaryReader::from_reader(src, BOUNDARY);
            test_boundary_reader(reader);
        }

    }

    fn test_boundary_reader<R: Read>(mut reader: BoundaryReader<R>) {
        let ref mut buf = String::new();

        debug!("Read 1");
        let _ = reader.read_to_string(buf).unwrap();
        assert!(buf.is_empty(), "Buffer not empty: {:?}", buf);
        buf.clear();

        debug!("Consume 1");
        reader.consume_boundary().unwrap();

        debug!("Read 2");
        let _ = reader.read_to_string(buf).unwrap();
        assert_eq!(buf, "dashed-value-1");
        buf.clear();

        debug!("Consume 2");
        reader.consume_boundary().unwrap();

        debug!("Read 3");
        let _ = reader.read_to_string(buf).unwrap();
        assert_eq!(buf, "dashed-value-2");
        buf.clear();

        debug!("Consume 3");
        reader.consume_boundary().unwrap();

        debug!("Read 4");
        let _ = reader.read_to_string(buf).unwrap();
        assert_eq!(buf, "");
    }
}
<|endoftext|>


<commit_before>use std::marker::PhantomData;
use super::Act;
use super::internal_iface::ProcessPacketBatch;
use super::packet_batch::cast_from_u8;
use super::TransformBatch;
use super::ApplyBatch;
use super::super::interface::EndOffset;

pub struct ParsedBatch<'a, T:'a + EndOffset, V> where
    V:'a + ProcessPacketBatch + Act {
    parent: &'a mut V,
    applied: bool,
    phantom: PhantomData<&'a T>,
}

impl<'a, T, V> Act for ParsedBatch<'a, T, V>
    where T:'a + EndOffset,
    V: 'a +  ProcessPacketBatch + Act {
    fn act(&mut self) -> &mut Self {
        self.parent.act();
        self
    }
}

batch!{ParsedBatch, [parent: &'a mut V], [phantom: PhantomData]}

impl<'a, T, V> ProcessPacketBatch for ParsedBatch<'a, T, V>
    where T:'a + EndOffset,
    V: 'a +  ProcessPacketBatch + Act {
    #[inline]
    fn start(&self) -> usize {
        self.parent.start()
    }

    #[inline]
    fn end(&self) -> usize {
        self.parent.end()
    }

    #[inline]
    unsafe fn payload(&mut self, idx: usize) -> *mut u8 {
        let address = self.parent.payload(idx);
        let offset = T::offset(cast_from_u8::<T>(address));
        address.offset(offset as isize)
    }

    #[inline]
    unsafe fn address(&mut self, idx: usize) -> *mut u8 {
        self.parent.payload(idx)
    }
}
<commit_msg>Fix parsed batch<commit_after>use std::marker::PhantomData;
use super::Act;
use super::internal_iface::ProcessPacketBatch;
use super::packet_batch::cast_from_u8;
use super::TransformBatch;
use super::ApplyBatch;
use super::super::interface::EndOffset;

pub struct ParsedBatch<'a, T:'a + EndOffset, V> where
    V:'a + ProcessPacketBatch + Act {
    parent: &'a mut V,
    applied: bool,
    phantom: PhantomData<&'a T>,
}

impl<'a, T, V> Act for ParsedBatch<'a, T, V>
    where T:'a + EndOffset,
    V: 'a +  ProcessPacketBatch + Act {
    fn act(&mut self) -> &mut Self {
        self.parent.act();
        self.applied = true;
        self
    }
}

batch!{ParsedBatch, [parent: &'a mut V], [phantom: PhantomData]}

impl<'a, T, V> ProcessPacketBatch for ParsedBatch<'a, T, V>
    where T:'a + EndOffset,
    V: 'a +  ProcessPacketBatch + Act {
    #[inline]
    fn start(&self) -> usize {
        self.parent.start()
    }

    #[inline]
    fn end(&self) -> usize {
        self.parent.end()
    }

    #[inline]
    unsafe fn payload(&mut self, idx: usize) -> *mut u8 {
        let address = self.parent.payload(idx);
        let offset = T::offset(cast_from_u8::<T>(address));
        address.offset(offset as isize)
    }

    #[inline]
    unsafe fn address(&mut self, idx: usize) -> *mut u8 {
        self.parent.payload(idx)
    }
}
<|endoftext|>


<commit_before>use std::convert;
use std::io;
use std::result;
use std::str::Utf8Error;

use byteorder;

const FIXSTR_SIZE   : u8 = 0x1f;
const FIXARRAY_SIZE : u8 = 0x0f;
const FIXMAP_SIZE   : u8 = 0x0f;

#[derive(Clone, Copy, PartialEq, Debug)]
pub enum Marker {
    PositiveFixnum(u8),
    NegativeFixnum(i8),
    Null,
    True,
    False,
    U8,
    U16,
    U32,
    U64,
    I8,
    I16,
    I32,
    I64,
    F32,
    F64,
    FixedString(u8),
    Str8,
    Str16,
    Str32,
    Bin8,
    Bin16,
    Bin32,
    FixedArray(u8),
    Array16,
    Array32,
    FixedMap(u8),
    Map16,
    Map32,
    FixExt1,
    FixExt2,
    FixExt4,
    FixExt8,
    FixExt16,
    Ext8,
    Ext16,
    Ext32,
    Reserved,
}

impl Marker {
    pub fn from_u8(n: u8) -> Marker {
        match n {
            val @ 0x00 ... 0x7f => Marker::PositiveFixnum(val as u8),
            val @ 0xe0 ... 0xff => Marker::NegativeFixnum(val as i8),
            val @ 0x80 ... 0x8f => Marker::FixedMap((val as u8) & FIXMAP_SIZE),
            val @ 0x90 ... 0x9f => Marker::FixedArray((val as u8) & FIXARRAY_SIZE),
            val @ 0xa0 ... 0xbf => Marker::FixedString((val as u8) & FIXSTR_SIZE),
            0xc0 => Marker::Null,
            /// Marked in MessagePack spec as never used.
            0xc1 => Marker::Reserved,
            0xc2 => Marker::False,
            0xc3 => Marker::True,
            0xc4 => Marker::Bin8,
            0xc5 => Marker::Bin16,
            0xc6 => Marker::Bin32,
            0xc7 => Marker::Ext8,
            0xc8 => Marker::Ext16,
            0xc9 => Marker::Ext32,
            0xca => Marker::F32,
            0xcb => Marker::F64,
            0xcc => Marker::U8,
            0xcd => Marker::U16,
            0xce => Marker::U32,
            0xcf => Marker::U64,
            0xd0 => Marker::I8,
            0xd1 => Marker::I16,
            0xd2 => Marker::I32,
            0xd3 => Marker::I64,
            0xd4 => Marker::FixExt1,
            0xd5 => Marker::FixExt2,
            0xd6 => Marker::FixExt4,
            0xd7 => Marker::FixExt8,
            0xd8 => Marker::FixExt16,
            0xd9 => Marker::Str8,
            0xda => Marker::Str16,
            0xdb => Marker::Str32,
            0xdc => Marker::Array16,
            0xdd => Marker::Array32,
            0xde => Marker::Map16,
            0xdf => Marker::Map32,
            _ => Marker::Reserved,
        }
    }

    pub fn to_u8(&self) -> u8 {
        match *self {
            Marker::PositiveFixnum(val) => val,
            Marker::NegativeFixnum(val) => val as u8,

            Marker::Null                => 0xc0,

            Marker::True                => 0xc3,
            Marker::False               => 0xc2,

            Marker::U8                  => 0xcc,
            Marker::U16                 => 0xcd,
            Marker::U32                 => 0xce,
            Marker::U64                 => 0xcf,

            Marker::I8                  => 0xd0,
            Marker::I16                 => 0xd1,
            Marker::I32                 => 0xd2,
            Marker::I64                 => 0xd3,

            Marker::F32                 => 0xca,
            Marker::F64                 => 0xcb,

            Marker::FixedString(len)    => 0xa0 | (len & FIXSTR_SIZE),
            Marker::Str8                => 0xd9,
            Marker::Str16               => 0xda,
            Marker::Str32               => 0xdb,

            Marker::Bin8                => 0xc4,
            Marker::Bin16               => 0xc5,
            Marker::Bin32               => 0xc6,

            Marker::FixedArray(len)     => 0x90 | (len & FIXARRAY_SIZE),
            Marker::Array16             => 0xdc,
            Marker::Array32             => 0xdd,

            Marker::FixedMap(len)       => 0x80 | (len & FIXMAP_SIZE),
            Marker::Map16               => 0xde,
            Marker::Map32               => 0xdf,

            Marker::FixExt1             => 0xd4,
            Marker::FixExt2             => 0xd5,
            Marker::FixExt4             => 0xd6,
            Marker::FixExt8             => 0xd7,
            Marker::FixExt16            => 0xd8,
            Marker::Ext8                => 0xc7,
            Marker::Ext16               => 0xc8,
            Marker::Ext32               => 0xc9,

            Marker::Reserved            => 0xc1,
        }
    }
}

/// An error type for reading bytes from the reader.
///
/// This is a thin wrapper over the standard `io::Error` type. Namely, it adds one additional error
/// case: an unexpected EOF.

/// Unstable: remove Debug trait; maybe rename IO variant to Io
#[derive(Debug)]
pub enum ReadError {
    UnexpectedEOF,
    IO(io::Error),
}

/// Unstable: this is a hack, because io::Error has PartialEq once; will be removed
impl PartialEq for ReadError {
    fn eq(&self, other: &ReadError) -> bool {
        match (self, other) {
            (&ReadError::UnexpectedEOF, &ReadError::UnexpectedEOF) => true,
            (&ReadError::IO(ref lhs),   &ReadError::IO(ref rhs)) => {
                lhs.kind() == rhs.kind()
            }
            _ => false
        }
    }

    fn ne(&self, other: &ReadError) -> bool {
        return !self.eq(other);
    }
}

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

impl convert::From<ReadError> for io::Error {
    fn from(err: ReadError) -> io::Error {
        match err {
            ReadError::IO(err) => err,
            ReadError::UnexpectedEOF => io::Error::new(io::ErrorKind::Other, "unexpected EOF")
        }
    }
}

impl convert::From<byteorder::Error> for ReadError {
    fn from(err: byteorder::Error) -> ReadError {
        match err {
            byteorder::Error::UnexpectedEOF => ReadError::UnexpectedEOF,
            byteorder::Error::Io(err) => ReadError::IO(err),
        }
    }
}

/// Unstable: remove Debug trait; incomplete
#[derive(Debug, PartialEq)]
pub enum Error {
    /// Marker type error.
    TypeMismatch(Marker),
    /// IO error while reading marker.
    InvalidMarkerRead(ReadError),
    /// IO error while reading data.
    InvalidDataRead(ReadError),
}

/// Unstable: Core? Shit name!
#[derive(Debug, PartialEq)]
pub enum DecodeStringError<'a> {
    Core(Error),
    /// The given buffer is too small to accumulate specified amount of bytes.
    BufferSizeTooSmall(u32),
    InvalidDataCopy(&'a [u8], ReadError),
    InvalidUtf8(&'a [u8], Utf8Error),
}

impl<'a> convert::From<Error> for DecodeStringError<'a> {
    fn from(err: Error) -> DecodeStringError<'a> {
        DecodeStringError::Core(err)
    }
}

pub type Result<T> = result::Result<T, Error>;

#[derive(Clone, Debug, PartialEq)]
pub enum Integer {
    /// Every non-negative integer is treated as u64, even if it fits in i64.
    U64(u64),
    /// Every negative integer is treated as i64.
    I64(i64),
}

#[derive(Clone, Debug, PartialEq)]
pub enum Value {
    Null,
    Integer(Integer),
    String(String),
    Array(Vec<Value>),
}

pub mod decode;
pub mod encode;
<commit_msg>[Misc] Code clean.<commit_after>use std::convert;
use std::io;
use std::result;
use std::str::Utf8Error;

use byteorder;

const FIXSTR_SIZE   : u8 = 0x1f;
const FIXARRAY_SIZE : u8 = 0x0f;
const FIXMAP_SIZE   : u8 = 0x0f;

#[derive(Clone, Copy, PartialEq, Debug)]
pub enum Marker {
    PositiveFixnum(u8),
    NegativeFixnum(i8),
    Null,
    True,
    False,
    U8,
    U16,
    U32,
    U64,
    I8,
    I16,
    I32,
    I64,
    F32,
    F64,
    FixedString(u8),
    Str8,
    Str16,
    Str32,
    Bin8,
    Bin16,
    Bin32,
    FixedArray(u8),
    Array16,
    Array32,
    FixedMap(u8),
    Map16,
    Map32,
    FixExt1,
    FixExt2,
    FixExt4,
    FixExt8,
    FixExt16,
    Ext8,
    Ext16,
    Ext32,
    Reserved,
}

impl Marker {
    pub fn from_u8(n: u8) -> Marker {
        match n {
            0x00 ... 0x7f => Marker::PositiveFixnum(n),
            0xe0 ... 0xff => Marker::NegativeFixnum(n as i8),
            0x80 ... 0x8f => Marker::FixedMap(n & FIXMAP_SIZE),
            0x90 ... 0x9f => Marker::FixedArray(n & FIXARRAY_SIZE),
            0xa0 ... 0xbf => Marker::FixedString(n & FIXSTR_SIZE),
            0xc0 => Marker::Null,
            /// Marked in MessagePack spec as never used.
            0xc1 => Marker::Reserved,
            0xc2 => Marker::False,
            0xc3 => Marker::True,
            0xc4 => Marker::Bin8,
            0xc5 => Marker::Bin16,
            0xc6 => Marker::Bin32,
            0xc7 => Marker::Ext8,
            0xc8 => Marker::Ext16,
            0xc9 => Marker::Ext32,
            0xca => Marker::F32,
            0xcb => Marker::F64,
            0xcc => Marker::U8,
            0xcd => Marker::U16,
            0xce => Marker::U32,
            0xcf => Marker::U64,
            0xd0 => Marker::I8,
            0xd1 => Marker::I16,
            0xd2 => Marker::I32,
            0xd3 => Marker::I64,
            0xd4 => Marker::FixExt1,
            0xd5 => Marker::FixExt2,
            0xd6 => Marker::FixExt4,
            0xd7 => Marker::FixExt8,
            0xd8 => Marker::FixExt16,
            0xd9 => Marker::Str8,
            0xda => Marker::Str16,
            0xdb => Marker::Str32,
            0xdc => Marker::Array16,
            0xdd => Marker::Array32,
            0xde => Marker::Map16,
            0xdf => Marker::Map32,
            _ => Marker::Reserved,
        }
    }

    pub fn to_u8(&self) -> u8 {
        match *self {
            Marker::PositiveFixnum(val) => val,
            Marker::NegativeFixnum(val) => val as u8,

            Marker::Null                => 0xc0,

            Marker::True                => 0xc3,
            Marker::False               => 0xc2,

            Marker::U8                  => 0xcc,
            Marker::U16                 => 0xcd,
            Marker::U32                 => 0xce,
            Marker::U64                 => 0xcf,

            Marker::I8                  => 0xd0,
            Marker::I16                 => 0xd1,
            Marker::I32                 => 0xd2,
            Marker::I64                 => 0xd3,

            Marker::F32                 => 0xca,
            Marker::F64                 => 0xcb,

            Marker::FixedString(len)    => 0xa0 | (len & FIXSTR_SIZE),
            Marker::Str8                => 0xd9,
            Marker::Str16               => 0xda,
            Marker::Str32               => 0xdb,

            Marker::Bin8                => 0xc4,
            Marker::Bin16               => 0xc5,
            Marker::Bin32               => 0xc6,

            Marker::FixedArray(len)     => 0x90 | (len & FIXARRAY_SIZE),
            Marker::Array16             => 0xdc,
            Marker::Array32             => 0xdd,

            Marker::FixedMap(len)       => 0x80 | (len & FIXMAP_SIZE),
            Marker::Map16               => 0xde,
            Marker::Map32               => 0xdf,

            Marker::FixExt1             => 0xd4,
            Marker::FixExt2             => 0xd5,
            Marker::FixExt4             => 0xd6,
            Marker::FixExt8             => 0xd7,
            Marker::FixExt16            => 0xd8,
            Marker::Ext8                => 0xc7,
            Marker::Ext16               => 0xc8,
            Marker::Ext32               => 0xc9,

            Marker::Reserved            => 0xc1,
        }
    }
}

/// An error type for reading bytes from the reader.
///
/// This is a thin wrapper over the standard `io::Error` type. Namely, it adds one additional error
/// case: an unexpected EOF.

/// Unstable: remove Debug trait; maybe rename IO variant to Io
#[derive(Debug)]
pub enum ReadError {
    UnexpectedEOF,
    IO(io::Error),
}

/// Unstable: this is a hack, because io::Error has PartialEq once; will be removed
impl PartialEq for ReadError {
    fn eq(&self, other: &ReadError) -> bool {
        match (self, other) {
            (&ReadError::UnexpectedEOF, &ReadError::UnexpectedEOF) => true,
            (&ReadError::IO(ref lhs),   &ReadError::IO(ref rhs)) => {
                lhs.kind() == rhs.kind()
            }
            _ => false
        }
    }

    fn ne(&self, other: &ReadError) -> bool {
        return !self.eq(other);
    }
}

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

impl convert::From<ReadError> for io::Error {
    fn from(err: ReadError) -> io::Error {
        match err {
            ReadError::IO(err) => err,
            ReadError::UnexpectedEOF => io::Error::new(io::ErrorKind::Other, "unexpected EOF")
        }
    }
}

impl convert::From<byteorder::Error> for ReadError {
    fn from(err: byteorder::Error) -> ReadError {
        match err {
            byteorder::Error::UnexpectedEOF => ReadError::UnexpectedEOF,
            byteorder::Error::Io(err) => ReadError::IO(err),
        }
    }
}

/// Unstable: remove Debug trait; incomplete
#[derive(Debug, PartialEq)]
pub enum Error {
    /// Marker type error.
    TypeMismatch(Marker),
    /// IO error while reading marker.
    InvalidMarkerRead(ReadError),
    /// IO error while reading data.
    InvalidDataRead(ReadError),
}

/// Unstable: Core? Shit name!
#[derive(Debug, PartialEq)]
pub enum DecodeStringError<'a> {
    Core(Error),
    /// The given buffer is too small to accumulate specified amount of bytes.
    BufferSizeTooSmall(u32),
    InvalidDataCopy(&'a [u8], ReadError),
    InvalidUtf8(&'a [u8], Utf8Error),
}

impl<'a> convert::From<Error> for DecodeStringError<'a> {
    fn from(err: Error) -> DecodeStringError<'a> {
        DecodeStringError::Core(err)
    }
}

pub type Result<T> = result::Result<T, Error>;

#[derive(Clone, Debug, PartialEq)]
pub enum Integer {
    /// Every non-negative integer is treated as u64, even if it fits in i64.
    U64(u64),
    /// Every negative integer is treated as i64.
    I64(i64),
}

#[derive(Clone, Debug, PartialEq)]
pub enum Value {
    Null,
    Integer(Integer),
    String(String),
    Array(Vec<Value>),
}

pub mod decode;
pub mod encode;
<|endoftext|>


<commit_before>//!
//! A game engine based around a state machine
//!

// tcod
//
// This library helps us create a window to render to, gives us functions for pathing, FOV, and
// generating dungeons (though we don't use their dungeon generators because I am much more interested in building my own.
// See the `Dungeon` module.)
extern crate tcod;
// We use tcod here to create the root console (to give it to the renderer) and to grab inputs from the player
use self::tcod::{console, Console};
use core::tcod::input;

// The game log
//
// Every roguelike needs a way of delivering messages to the player because - spoiler - ASCII isn't exactly expressive enough
// to alert the player as to their surroundings or the goings on of the game world they inhabit. The log system primarily is held
// together by equal parts eldritch rust knowledge and voodoo magic and each time I use it I am both simultaneously shocked at
// how hacky it is and how good rust is at handling it.
//
// Log is imported first so all other modules can get the macro
#[macro_use]
pub mod log;
use self::log::GlobalLog;

// The world handler
//
// The world is in charge of creating dungeons, populating them with creatures and items, and keeping track of the player.
// It basically ties together all game subsystems into a concrete package, hence, world.
//
// World is public so that docs are generated for it
pub mod world;
// Import world directly so we can make instances of it
use core::world::World;
use core::world::dungeon::map::Pos;

// Game objects
//
// Objects are essentially what most game-related non-map entities can be boiled down to. Objects encompass
// the very building blocks of the game such as `Pos`itions, `Creature`s which are combinations of `Actor`s, `Renderable`s,
// and `Action`s, and AI patterns that help drive monster descicion making.
//
// Object is public so that docs are generated for it
pub mod creature;
// While normally this module most likely should not have access to objects, we need to see `Action`s as the player's
// choices changes the state of the game
use core::creature::actions::Actions;

// Renderer
//
// The renderer is the interface by which game objects and constructs are made real through tcod interaction. The central
// idea is that if tcod is ever abandoned, minimal ammounts of code outside of the renderer should have to be changed.
// This hasn't *really* been the case as `World` depends on tcod lighting maps, the `Engine` holds a tcod root, and init creates
// said root.
//
// Renderer is public so that docs are generated for it
pub mod renderer;
// We import the renderer to create instances of it and RGB so we can color some log outputs
use self::renderer::Renderer;
use self::renderer::RGB;

// Initializer
//
// All things must be created, and all configurations must be loaded at some point. The initializer module prepares tcod consoles,
// and loads the configs with serde
//
// Pretty sure you understand why this is public by now
pub mod init;

///
/// Enum representing the state of the game
///
/// "All programs are just one big finite automata" - Nowak, probably
///
/// All games essentially boil down to a number of finite states and the transitions between them. To help decide what state
/// the game transitions to, or to make other choices regarding the game, some notion of a state has to be preserved to base
/// such a judgement off of. Most of the time however, the player is the main driving factor of the state changes.
///
pub enum State {
  // Game just created
  New,
  // All possible player actions are also valid states for the game to be in
  Act(Actions),
  // A key was pressed
  Keypress,
  // Debug command was triggered
  Debug
}

///
/// Engine struct to package the world with the renderer as well as any debug flags we may want to add
///
/// This engine isn't really a typical "game engine" in the way unreal or unity are but more or less what actually causes the game
/// to even be playable in the first place, as world elements are wrapped together with a renderer and input. It essentially bridges the gap
/// between physical user and the game world via the renderer, and in that sense it's more of a steering wheel than an engine, but
/// `SteeringWheel` makes pretty much no sense whatsoever and "engine" is already within the common vernacular of game developers
///
pub struct Engine {
  world: World,
  state: State,
  ren: Renderer,
  root: console::Root,

  // Debug options the engine tracks
  noclip: bool

}

impl Engine {

  ///
  /// Capture keyboard input from tcod and update player state
  ///
  fn process_keypress(&mut self, keypress: input::Key) {

    match keypress.code {

      // If the keycode isn't escape we continue checking for important keys
      input::KeyCode::Escape => panic!("Bye"),

      // This part of the code is for capturing the keypress not as an object, but as a character for easier parsing
      _ => {

        // We only care if the key is printable, aka, has some symbol attached to it
        if keypress.printable != ' ' {

          // First, make an assumption that the player is affecting their movement as 90% of the game
          // is walking around. We *could* add it to every single one of the vim keypresses to save a trivial ammount of
          // time assigning this variable, but I dislike that.
          let oldpos = self.world.player.actor.pos.clone();

          // In addition, update the game state
          // Important so that if the game state becomes debug we can leave that state instantly
          self.state = State::Keypress;

          // Begin to pattern match the char corresponding to the key pressed
          match keypress.printable {

            // Movement keys are bound to vim-like controls (hjklyubn)
            'h' => {
              self.world.player.actor.move_cart(-1, 0);
              self.world.player.state = Actions::Move;
            },
            'j' => {
              self.world.player.actor.move_cart(0, 1);
              self.world.player.state = Actions::Move;
            },
            'k' => {
              self.world.player.actor.move_cart(0, -1);
              self.world.player.state = Actions::Move;
            },
            'l' => {
              self.world.player.actor.move_cart(1, 0);
              self.world.player.state = Actions::Move;
            },
            'y' => {
              self.world.player.actor.move_cart(-1, -1);
              self.world.player.state = Actions::Move;
            },
            'u' => {
              self.world.player.actor.move_cart(1, -1);
              self.world.player.state = Actions::Move;
            },
            'b' => {
              self.world.player.actor.move_cart(-1, 1);
              self.world.player.state = Actions::Move;
            },
            'n' => {
              self.world.player.actor.move_cart(1, 1);
              self.world.player.state = Actions::Move;
            },

            // Force reload word
            'w' => {
              self.world = World::new(Pos::from_tup(init::map_dimensions()));
              self.state = State::Act(Actions::Unknown);
            },
            // Create an empty level for testing
            'q' => {
              self.world.test_empty();
              self.state = State::Act(Actions::Unknown);
            },
            // Wait
            '.' => {
              self.world.player.state = Actions::Wait;
            },

            // Go downstars (if possible)
            '>' => { self.world.player.state = Actions::DownStair },
            // Go upstairs (if possible)
            '<' => { self.world.player.state = Actions::UpStair },

            // Debug keypresses

            // Toggle scent
            'r' => {
              self.ren.show_scent = !self.ren.show_scent;
              self.ren.draw_all(&mut self.root, &mut self.world);
              self.state = State::Debug;
            },

            // Toggle sound
            't' => {
              self.ren.show_sound = !self.ren.show_sound;
              self.ren.draw_all(&mut self.root, &mut self.world);
              self.state = State::Debug;
            },

            // Toggle FoV
            'f' => {
              self.ren.fov = !self.ren.fov;
              self.ren.draw_all(&mut self.root, &mut self.world);
              self.state = State::Debug;
            },

            // Toggle noclip
            'z' => {
              self.noclip = !self.noclip;
              self.state = State::Debug;
            },

            // Tcod test
            'c' => {
              self.ren.tcod_test(&mut self.root);
              self.state = State::Debug;
            },

            // Unbound key, so we just say we don't know what the player did
            _ => { self.world.player.state = Actions::Unknown }

          }

          // Now the game state needs to be properly re-oriented based on the (potential) player action.
          // In addition, we should also process the action of the player while we're here
          match self.state {

            // If state is Debug, don't override
            State::Debug => (),

            _ => {

              // Set game state to player state
              self.state = State::Act(self.world.player.state.clone());

              // Now let's process the player's action
              match self.world.player.state {

                Actions::Move => {

                  // Make sure player doesn't do anything dumb
                  if !self.world.is_valid_pos(self.world.player.actor.pos.x, self.world.player.actor.pos.y) && !self.noclip {
                    self.world.player.actor.pos = oldpos;
                    self.world.player.state = Actions::Unknown;
                  // Otherwise if the position is valid check to see if there's stuff on the tile
                  } else {
                    self.world.check_trap();
                  }

                }

                _ => ()

              }

            }
          }

        }

        // Prints keycode to console in case if you're trying to find a key that isn't intutive, or you're debugging
        /*
        else {
          println!("{:?}", keypress.code);
        }
        */

      }

    }

  }

  ///
  /// Return a new `Engine`
  ///
  pub fn new() -> Self {

    // Get map height
    let map_dim = Pos::from_tup(init::map_dimensions());

    // Get root console
    let root = init::root();

    Engine {

      world: World::new(map_dim),

      state: State::New,

      ren: Renderer::new(
        map_dim,
        Pos::new(root.width() as isize, root.height() as isize),
        init::console_height(),
        init::panel_width()
      ),

      root: root,

      // Debug
      noclip: false

    }

  }

  ///
  /// Update the game state, then update the world depending on the new state
  ///
  fn update(&mut self) {

    match self.state {

      // Player moving or waiting prompts a world update
      State::Act(Actions::Move) | State::Act(Actions::Wait) => self.world.update(),

      // Trying to go up and downstairs prompts the respective response from world
      State::Act(Actions::DownStair) => {
        // No clip through floors
        if self.noclip {
          self.world.go_down();
        } else {
          self.world.player_go_down();
        }
      },

      State::Act(Actions::UpStair) => {
        // No clip through floors
        if self.noclip {
          self.world.go_up();
        } else {
          self.world.player_go_up();
        }
      }

      // All other variants are dropped
      _ => {}

    }

  }

  ///
  /// Title screen test
  ///
  fn title_screen(&mut self) {

    // First part of this pretty much just fills the screen with black

    let w = self.root.width().clone();
    let h = self.root.height().clone();

    for x in 0..w {
      for y in 0..h {
        self.root.put_char_ex(
          x as i32,
          y as i32,
          ' ',
          RGB(0, 0, 0).to_tcod(),
          RGB(0, 0, 0).to_tcod()
        );
      }
    }

    // Second part displays stuff

    let title = "Edgequest";
    let subtitle = "Press any key to start.";

    self.root.set_default_foreground(RGB(255, 255, 255).to_tcod());
    // i32 conversion is a pain since I'd rather store stuff as isize and the tcod lib wants i32 since it's
    // pretty much just a C++ interface which is annoying
    self.root.print((w / 2 - (title.len() / 2) as i32) as i32, (h / 2 - 1) as i32, title);
    self.root.print((w / 2 - (subtitle.len() / 2) as i32) as i32, (h / 2 + 1) as i32, subtitle);

    self.root.flush();

    // Wait for keypress
    let keypress = self.root.wait_for_keypress(true);

    // Escape on title should quit the game
    match keypress.code {

      // If the keycode isn't escape we continue checking for important keys
      input::KeyCode::Escape => panic!("Bye"),
      _ => {}

    }

  }

  ///
  /// Play the game.
  ///
  pub fn play(&mut self) {

    // Create the title screen
    self.title_screen();

    // Some starting messages, will be removed in later versions (hopefully)
    log!(("Welcome to Edgequest",                 RGB(255,   0, 255)));
    log!(("Move with vim keys",                   RGB(255, 255, 255)));
    log!(("esc to quit, w to regenerate the map", RGB(255, 255, 255)));
    log!(("r to toggle scent, t to toggle sound", RGB(255, 255, 255)));
    log!(("f to toggle FoV, z to toggle noclip",  RGB(255, 255, 255)));

    // Initial update
    self.update();

    // Draw all and capture keypresses
    while !self.root.window_closed() {

      // Draw what the camera sees
      self.ren.draw_all(&mut self.root, &mut self.world);

      // Capture game keys (Keys that change the state of the player)
      // This is what gives it the turn based nature, i.e. waits for player input before
      // doing anything. Process keypress also updates the engine state.
      //
      // We save input to keypress because directly sending the root back into the engine
      // causes it to be mutably borrowed more than once
      let keypress = self.root.wait_for_keypress(true);
      self.process_keypress(keypress);

      // Update engine based on state
      self.update();

    }

  }

}<commit_msg>Add new PR template<commit_after>//!
//! A game engine based around a state machine
//!

// tcod
//
// This library helps us create a window to render to, gives us functions for pathing, FOV, and
// generating dungeons (though we don't use their dungeon generators because I am much more interested in building my own.
// See the `Dungeon` module.)
extern crate tcod;
// We use tcod here to create the root console (to give it to the renderer) and to grab inputs from the player
use self::tcod::{console, Console};
use self::tcod::input;

// The game log
//
// Every roguelike needs a way of delivering messages to the player because - spoiler - ASCII isn't exactly expressive enough
// to alert the player as to their surroundings or the goings on of the game world they inhabit. The log system primarily is held
// together by equal parts eldritch rust knowledge and voodoo magic and each time I use it I am both simultaneously shocked at
// how hacky it is and how good rust is at handling it.
//
// Log is imported first so all other modules can get the macro
#[macro_use]
pub mod log;
use self::log::GlobalLog;

// The world handler
//
// The world is in charge of creating dungeons, populating them with creatures and items, and keeping track of the player.
// It basically ties together all game subsystems into a concrete package, hence, world.
//
// World is public so that docs are generated for it
pub mod world;
// Import world directly so we can make instances of it
use self::world::World;
use self::world::dungeon::map::Pos;

// Game objects
//
// Objects are essentially what most game-related non-map entities can be boiled down to. Objects encompass
// the very building blocks of the game such as `Pos`itions, `Creature`s which are combinations of `Actor`s, `Renderable`s,
// and `Action`s, and AI patterns that help drive monster descicion making.
//
// Object is public so that docs are generated for it
pub mod creature;
// While normally this module most likely should not have access to objects, we need to see `Action`s as the player's
// choices changes the state of the game
use self::creature::actions::Actions;

// Renderer
//
// The renderer is the interface by which game objects and constructs are made real through tcod interaction. The central
// idea is that if tcod is ever abandoned, minimal ammounts of code outside of the renderer should have to be changed.
// This hasn't *really* been the case as `World` depends on tcod lighting maps, the `Engine` holds a tcod root, and init creates
// said root.
//
// Renderer is public so that docs are generated for it
pub mod renderer;
// We import the renderer to create instances of it and RGB so we can color some log outputs
use self::renderer::Renderer;
use self::renderer::RGB;

// Initializer
//
// All things must be created, and all configurations must be loaded at some point. The initializer module prepares tcod consoles,
// and loads the configs with serde
//
// Pretty sure you understand why this is public by now
pub mod init;

///
/// Enum representing the state of the game
///
/// "All programs are just one big finite automata" - Nowak, probably
///
/// All games essentially boil down to a number of finite states and the transitions between them. To help decide what state
/// the game transitions to, or to make other choices regarding the game, some notion of a state has to be preserved to base
/// such a judgement off of. Most of the time however, the player is the main driving factor of the state changes.
///
pub enum State {
  // Game just created
  New,
  // All possible player actions are also valid states for the game to be in
  Act(Actions),
  // A key was pressed
  Keypress,
  // Debug command was triggered
  Debug
}

///
/// Engine struct to package the world with the renderer as well as any debug flags we may want to add
///
/// This engine isn't really a typical "game engine" in the way unreal or unity are but more or less what actually causes the game
/// to even be playable in the first place, as world elements are wrapped together with a renderer and input. It essentially bridges the gap
/// between physical user and the game world via the renderer, and in that sense it's more of a steering wheel than an engine, but
/// `SteeringWheel` makes pretty much no sense whatsoever and "engine" is already within the common vernacular of game developers
///
pub struct Engine {
  world: World,
  state: State,
  ren: Renderer,
  root: console::Root,

  // Debug options the engine tracks
  noclip: bool

}

impl Engine {

  ///
  /// Capture keyboard input from tcod and update player state
  ///
  fn process_keypress(&mut self, keypress: input::Key) {

    match keypress.code {

      // If the keycode isn't escape we continue checking for important keys
      input::KeyCode::Escape => panic!("Bye"),

      // This part of the code is for capturing the keypress not as an object, but as a character for easier parsing
      _ => {

        // We only care if the key is printable, aka, has some symbol attached to it
        if keypress.printable != ' ' {

          // First, make an assumption that the player is affecting their movement as 90% of the game
          // is walking around. We *could* add it to every single one of the vim keypresses to save a trivial ammount of
          // time assigning this variable, but I dislike that.
          let oldpos = self.world.player.actor.pos.clone();

          // In addition, update the game state
          // Important so that if the game state becomes debug we can leave that state instantly
          self.state = State::Keypress;

          // Begin to pattern match the char corresponding to the key pressed
          match keypress.printable {

            // Movement keys are bound to vim-like controls (hjklyubn)
            'h' => {
              self.world.player.actor.move_cart(-1, 0);
              self.world.player.state = Actions::Move;
            },
            'j' => {
              self.world.player.actor.move_cart(0, 1);
              self.world.player.state = Actions::Move;
            },
            'k' => {
              self.world.player.actor.move_cart(0, -1);
              self.world.player.state = Actions::Move;
            },
            'l' => {
              self.world.player.actor.move_cart(1, 0);
              self.world.player.state = Actions::Move;
            },
            'y' => {
              self.world.player.actor.move_cart(-1, -1);
              self.world.player.state = Actions::Move;
            },
            'u' => {
              self.world.player.actor.move_cart(1, -1);
              self.world.player.state = Actions::Move;
            },
            'b' => {
              self.world.player.actor.move_cart(-1, 1);
              self.world.player.state = Actions::Move;
            },
            'n' => {
              self.world.player.actor.move_cart(1, 1);
              self.world.player.state = Actions::Move;
            },

            // Force reload word
            'w' => {
              self.world = World::new(Pos::from_tup(init::map_dimensions()));
              self.state = State::Act(Actions::Unknown);
            },
            // Create an empty level for testing
            'q' => {
              self.world.test_empty();
              self.state = State::Act(Actions::Unknown);
            },
            // Wait
            '.' => {
              self.world.player.state = Actions::Wait;
            },

            // Go downstars (if possible)
            '>' => { self.world.player.state = Actions::DownStair },
            // Go upstairs (if possible)
            '<' => { self.world.player.state = Actions::UpStair },

            // Debug keypresses

            // Toggle scent
            'r' => {
              self.ren.show_scent = !self.ren.show_scent;
              self.ren.draw_all(&mut self.root, &mut self.world);
              self.state = State::Debug;
            },

            // Toggle sound
            't' => {
              self.ren.show_sound = !self.ren.show_sound;
              self.ren.draw_all(&mut self.root, &mut self.world);
              self.state = State::Debug;
            },

            // Toggle FoV
            'f' => {
              self.ren.fov = !self.ren.fov;
              self.ren.draw_all(&mut self.root, &mut self.world);
              self.state = State::Debug;
            },

            // Toggle noclip
            'z' => {
              self.noclip = !self.noclip;
              self.state = State::Debug;
            },

            // Tcod test
            'c' => {
              self.ren.tcod_test(&mut self.root);
              self.state = State::Debug;
            },

            // Unbound key, so we just say we don't know what the player did
            _ => { self.world.player.state = Actions::Unknown }

          }

          // Now the game state needs to be properly re-oriented based on the (potential) player action.
          // In addition, we should also process the action of the player while we're here
          match self.state {

            // If state is Debug, don't override
            State::Debug => (),

            _ => {

              // Set game state to player state
              self.state = State::Act(self.world.player.state.clone());

              // Now let's process the player's action
              match self.world.player.state {

                Actions::Move => {

                  // Make sure player doesn't do anything dumb
                  if !self.world.is_valid_pos(self.world.player.actor.pos.x, self.world.player.actor.pos.y) && !self.noclip {
                    self.world.player.actor.pos = oldpos;
                    self.world.player.state = Actions::Unknown;
                  // Otherwise if the position is valid check to see if there's stuff on the tile
                  } else {
                    self.world.check_trap();
                  }

                }

                _ => ()

              }

            }
          }

        }

        // Prints keycode to console in case if you're trying to find a key that isn't intutive, or you're debugging
        /*
        else {
          println!("{:?}", keypress.code);
        }
        */

      }

    }

  }

  ///
  /// Return a new `Engine`
  ///
  pub fn new() -> Self {

    // Get map height
    let map_dim = Pos::from_tup(init::map_dimensions());

    // Get root console
    let root = init::root();

    Engine {

      world: World::new(map_dim),

      state: State::New,

      ren: Renderer::new(
        map_dim,
        Pos::new(root.width() as isize, root.height() as isize),
        init::console_height(),
        init::panel_width()
      ),

      root: root,

      // Debug
      noclip: false

    }

  }

  ///
  /// Update the game state, then update the world depending on the new state
  ///
  fn update(&mut self) {

    match self.state {

      // Player moving or waiting prompts a world update
      State::Act(Actions::Move) | State::Act(Actions::Wait) => self.world.update(),

      // Trying to go up and downstairs prompts the respective response from world
      State::Act(Actions::DownStair) => {
        // No clip through floors
        if self.noclip {
          self.world.go_down();
        } else {
          self.world.player_go_down();
        }
      },

      State::Act(Actions::UpStair) => {
        // No clip through floors
        if self.noclip {
          self.world.go_up();
        } else {
          self.world.player_go_up();
        }
      }

      // All other variants are dropped
      _ => {}

    }

  }

  ///
  /// Title screen test
  ///
  fn title_screen(&mut self) {

    // First part of this pretty much just fills the screen with black

    let w = self.root.width().clone();
    let h = self.root.height().clone();

    for x in 0..w {
      for y in 0..h {
        self.root.put_char_ex(
          x as i32,
          y as i32,
          ' ',
          RGB(0, 0, 0).to_tcod(),
          RGB(0, 0, 0).to_tcod()
        );
      }
    }

    // Second part displays stuff

    let title = "Edgequest";
    let subtitle = "Press any key to start.";

    self.root.set_default_foreground(RGB(255, 255, 255).to_tcod());
    // i32 conversion is a pain since I'd rather store stuff as isize and the tcod lib wants i32 since it's
    // pretty much just a C++ interface which is annoying
    self.root.print((w / 2 - (title.len() / 2) as i32) as i32, (h / 2 - 1) as i32, title);
    self.root.print((w / 2 - (subtitle.len() / 2) as i32) as i32, (h / 2 + 1) as i32, subtitle);

    self.root.flush();

    // Wait for keypress
    let keypress = self.root.wait_for_keypress(true);

    // Escape on title should quit the game
    match keypress.code {

      // If the keycode isn't escape we continue checking for important keys
      input::KeyCode::Escape => panic!("Bye"),
      _ => {}

    }

  }

  ///
  /// Play the game.
  ///
  pub fn play(&mut self) {

    // Create the title screen
    self.title_screen();

    // Some starting messages, will be removed in later versions (hopefully)
    log!(("Welcome to Edgequest",                 RGB(255,   0, 255)));
    log!(("Move with vim keys",                   RGB(255, 255, 255)));
    log!(("esc to quit, w to regenerate the map", RGB(255, 255, 255)));
    log!(("r to toggle scent, t to toggle sound", RGB(255, 255, 255)));
    log!(("f to toggle FoV, z to toggle noclip",  RGB(255, 255, 255)));

    // Initial update
    self.update();

    // Draw all and capture keypresses
    while !self.root.window_closed() {

      // Draw what the camera sees
      self.ren.draw_all(&mut self.root, &mut self.world);

      // Capture game keys (Keys that change the state of the player)
      // This is what gives it the turn based nature, i.e. waits for player input before
      // doing anything. Process keypress also updates the engine state.
      //
      // We save input to keypress because directly sending the root back into the engine
      // causes it to be mutably borrowed more than once
      let keypress = self.root.wait_for_keypress(true);
      self.process_keypress(keypress);

      // Update engine based on state
      self.update();

    }

  }

}<|endoftext|>


<commit_before>use fixedbitset::FixedBitSet;

#[derive(Debug)]
pub struct Coverage {
    n: usize,
    rows: FixedBitSet,
    cols: FixedBitSet,
}

impl Coverage {
    pub fn n(&self) -> usize {
        self.n
    }

    pub fn new(n: usize) -> Coverage {
        Coverage {
            n: n,
            rows: FixedBitSet::with_capacity(n),
            cols: FixedBitSet::with_capacity(n),
        }
    }

    #[inline]
    /// find a single uncovered (row, col) pair. Iterates in col, row order.
    pub fn find_uncovered_col_row<F>(&self, mut f: F) -> Option<(usize, usize)>
        where F: FnMut((usize, usize)) -> bool
    {

        let n = self.n();

        for col in 0..n {
            if self.is_col_covered(col) {
                continue;
            }
            for row in 0..n {
                if self.is_row_covered(row) {
                    continue;
                }

                let pos = (row, col);
                if f(pos) {
                    return Some(pos);
                }
            }
        }

        return None;
    }

    #[inline]
    /// iterates over all uncovered (row, col) pairs in row, col order
    pub fn iter_uncovered_row_col<F>(&self, mut f: F)
        where F: FnMut((usize, usize))
    {
        let n = self.n();

        for row in 0..n {
            if self.is_row_covered(row) {
                continue;
            }

            for col in 0..n {
                if self.is_col_covered(col) {
                    continue;
                }

                f((row, col));
            }
        }
    }

    #[inline]
    /// iterates over all uncovered (row, col) pairs in row, col order, and set covered if f returns true.
    pub fn iter_uncovered_row_col_and_cover<F>(&mut self, mut f: F)
        where F: FnMut((usize, usize)) -> bool
    {
        let n = self.n();

        for row in 0..n {
            if self.is_row_covered(row) {
                continue;
            }

            for col in 0..n {
                if self.is_col_covered(col) {
                    continue;
                }

                let pos = (row, col);
                if f(pos) {
                    self.cover(pos);
                }
            }
        }
    }

    #[inline]
    pub fn is_row_covered(&self, row: usize) -> bool {
        self.rows.contains(row)
    }

    #[inline]
    pub fn is_col_covered(&self, col: usize) -> bool {
        self.cols.contains(col)
    }

    #[inline]
    pub fn cover(&mut self, pos: (usize, usize)) {
        match pos {
            (row, col) => {
                self.cover_row(row);
                self.cover_col(col);
            }
        }
    }

    #[inline]
    pub fn cover_col(&mut self, col: usize) {
        self.cols.set(col, true);
    }

    #[inline]
    pub fn uncover_col(&mut self, col: usize) {
        self.cols.set(col, false);
    }

    #[inline]
    pub fn cover_row(&mut self, row: usize) {
        self.rows.set(row, true);
    }

    pub fn clear(&mut self) {
        self.rows.clear();
        self.cols.clear();
    }
}
<commit_msg>BUG FIX! If we cover a row and column, we have to leave the column loop.<commit_after>use fixedbitset::FixedBitSet;

#[derive(Debug)]
pub struct Coverage {
    n: usize,
    rows: FixedBitSet,
    cols: FixedBitSet,
}

impl Coverage {
    pub fn n(&self) -> usize {
        self.n
    }

    pub fn new(n: usize) -> Coverage {
        Coverage {
            n: n,
            rows: FixedBitSet::with_capacity(n),
            cols: FixedBitSet::with_capacity(n),
        }
    }

    #[inline]
    /// find a single uncovered (row, col) pair. Iterates in col, row order.
    pub fn find_uncovered_col_row<F>(&self, mut f: F) -> Option<(usize, usize)>
        where F: FnMut((usize, usize)) -> bool
    {

        let n = self.n();

        for col in 0..n {
            if self.is_col_covered(col) {
                continue;
            }
            for row in 0..n {
                if self.is_row_covered(row) {
                    continue;
                }

                let pos = (row, col);
                if f(pos) {
                    return Some(pos);
                }
            }
        }

        return None;
    }

    #[inline]
    /// iterates over all uncovered (row, col) pairs in row, col order
    pub fn iter_uncovered_row_col<F>(&self, mut f: F)
        where F: FnMut((usize, usize))
    {
        let n = self.n();

        for row in 0..n {
            if self.is_row_covered(row) {
                continue;
            }

            for col in 0..n {
                if self.is_col_covered(col) {
                    continue;
                }

                f((row, col));
            }
        }
    }

    #[inline]
    /// iterates over all uncovered (row, col) pairs in row, col order, and set covered if f returns true.
    pub fn iter_uncovered_row_col_and_cover<F>(&mut self, mut f: F)
        where F: FnMut((usize, usize)) -> bool
    {
        let n = self.n();

        for row in 0..n {
            if self.is_row_covered(row) {
                continue;
            }

            'col: for col in 0..n {
                if self.is_col_covered(col) {
                    continue;
                }

                let pos = (row, col);
                if f(pos) {
                    self.cover(pos);
                    // the complete row is covered! break the loop!
                    break 'col;
                }
            }
        }
    }

    #[inline]
    pub fn is_row_covered(&self, row: usize) -> bool {
        self.rows.contains(row)
    }

    #[inline]
    pub fn is_col_covered(&self, col: usize) -> bool {
        self.cols.contains(col)
    }

    #[inline]
    pub fn cover(&mut self, pos: (usize, usize)) {
        match pos {
            (row, col) => {
                self.cover_row(row);
                self.cover_col(col);
            }
        }
    }

    #[inline]
    pub fn cover_col(&mut self, col: usize) {
        self.cols.set(col, true);
    }

    #[inline]
    pub fn uncover_col(&mut self, col: usize) {
        self.cols.set(col, false);
    }

    #[inline]
    pub fn cover_row(&mut self, row: usize) {
        self.rows.set(row, true);
    }

    pub fn clear(&mut self) {
        self.rows.clear();
        self.cols.clear();
    }
}
<|endoftext|>