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

use std::fs;
use std::env;
use std::path::PathBuf;
use std::process::Command;

use Mode;
use Compiler;
use builder::{Step, RunConfig, ShouldRun, Builder};
use util::{copy, exe, add_lib_path};
use compile::{self, libtest_stamp, libstd_stamp, librustc_stamp};
use native;
use channel::GitInfo;
use cache::Interned;

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
struct CleanTools {
    compiler: Compiler,
    target: Interned<String>,
    mode: Mode,
}

impl Step for CleanTools {
    type Output = ();

    fn should_run(run: ShouldRun) -> ShouldRun {
        run.never()
    }

    /// Build a tool in `src/tools`
    ///
    /// This will build the specified tool with the specified `host` compiler in
    /// `stage` into the normal cargo output directory.
    fn run(self, builder: &Builder) {
        let build = builder.build;
        let compiler = self.compiler;
        let target = self.target;
        let mode = self.mode;

        let stamp = match mode {
            Mode::Libstd => libstd_stamp(build, compiler, target),
            Mode::Libtest => libtest_stamp(build, compiler, target),
            Mode::Librustc => librustc_stamp(build, compiler, target),
            _ => panic!(),
        };
        let out_dir = build.cargo_out(compiler, Mode::Tool, target);
        build.clear_if_dirty(&out_dir, &stamp);
    }
}

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
struct ToolBuild {
    compiler: Compiler,
    target: Interned<String>,
    tool: &'static str,
    mode: Mode,
}

impl Step for ToolBuild {
    type Output = PathBuf;

    fn should_run(run: ShouldRun) -> ShouldRun {
        run.never()
    }

    /// Build a tool in `src/tools`
    ///
    /// This will build the specified tool with the specified `host` compiler in
    /// `stage` into the normal cargo output directory.
    fn run(self, builder: &Builder) -> PathBuf {
        let build = builder.build;
        let compiler = self.compiler;
        let target = self.target;
        let tool = self.tool;

        builder.ensure(CleanTools { compiler, target, mode: self.mode });
        match self.mode {
            Mode::Libstd => builder.ensure(compile::Std { compiler, target }),
            Mode::Libtest => builder.ensure(compile::Test { compiler, target }),
            Mode::Librustc => builder.ensure(compile::Rustc { compiler, target }),
            Mode::Tool => panic!("unexpected Mode::Tool for tool build")
        }

        let _folder = build.fold_output(|| format!("stage{}-{}", compiler.stage, tool));
        println!("Building stage{} tool {} ({})", compiler.stage, tool, target);

        let mut cargo = prepare_tool_cargo(builder, compiler, target, tool);
        build.run(&mut cargo);
        build.cargo_out(compiler, Mode::Tool, target).join(exe(tool, &compiler.host))
    }
}

fn prepare_tool_cargo(
    builder: &Builder,
    compiler: Compiler,
    target: Interned<String>,
    tool: &'static str,
) -> Command {
    let build = builder.build;
    let mut cargo = builder.cargo(compiler, Mode::Tool, target, "build");
    let dir = build.src.join("src/tools").join(tool);
    cargo.arg("--manifest-path").arg(dir.join("Cargo.toml"));

    // We don't want to build tools dynamically as they'll be running across
    // stages and such and it's just easier if they're not dynamically linked.
    cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");

    if let Some(dir) = build.openssl_install_dir(target) {
        cargo.env("OPENSSL_STATIC", "1");
        cargo.env("OPENSSL_DIR", dir);
        cargo.env("LIBZ_SYS_STATIC", "1");
    }

    cargo.env("CFG_RELEASE_CHANNEL", &build.config.channel);

    let info = GitInfo::new(&build.config, &dir);
    if let Some(sha) = info.sha() {
        cargo.env("CFG_COMMIT_HASH", sha);
    }
    if let Some(sha_short) = info.sha_short() {
        cargo.env("CFG_SHORT_COMMIT_HASH", sha_short);
    }
    if let Some(date) = info.commit_date() {
        cargo.env("CFG_COMMIT_DATE", date);
    }
    cargo
}

macro_rules! tool {
    ($($name:ident, $path:expr, $tool_name:expr, $mode:expr;)+) => {
        #[derive(Copy, Clone)]
        pub enum Tool {
            $(
                $name,
            )+
        }

        impl<'a> Builder<'a> {
            pub fn tool_exe(&self, tool: Tool) -> PathBuf {
                match tool {
                    $(Tool::$name =>
                        self.ensure($name {
                            compiler: self.compiler(0, self.build.build),
                            target: self.build.build,
                        }),
                    )+
                }
            }
        }

        $(
            #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
        pub struct $name {
            pub compiler: Compiler,
            pub target: Interned<String>,
        }

        impl Step for $name {
            type Output = PathBuf;

            fn should_run(run: ShouldRun) -> ShouldRun {
                run.path($path)
            }

            fn make_run(run: RunConfig) {
                run.builder.ensure($name {
                    compiler: run.builder.compiler(run.builder.top_stage, run.builder.build.build),
                    target: run.target,
                });
            }

            fn run(self, builder: &Builder) -> PathBuf {
                builder.ensure(ToolBuild {
                    compiler: self.compiler,
                    target: self.target,
                    tool: $tool_name,
                    mode: $mode,
                })
            }
        }
        )+
    }
}

tool!(
    Rustbook, "src/tools/rustbook", "rustbook", Mode::Librustc;
    ErrorIndex, "src/tools/error_index_generator", "error_index_generator", Mode::Librustc;
    UnstableBookGen, "src/tools/unstable-book-gen", "unstable-book-gen", Mode::Libstd;
    Tidy, "src/tools/tidy", "tidy", Mode::Libstd;
    Linkchecker, "src/tools/linkchecker", "linkchecker", Mode::Libstd;
    CargoTest, "src/tools/cargotest", "cargotest", Mode::Libstd;
    Compiletest, "src/tools/compiletest", "compiletest", Mode::Libtest;
    BuildManifest, "src/tools/build-manifest", "build-manifest", Mode::Librustc;
    RemoteTestClient, "src/tools/remote-test-client", "remote-test-client", Mode::Libstd;
    RustInstaller, "src/tools/rust-installer", "rust-installer", Mode::Libstd;
);

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct RemoteTestServer {
    pub compiler: Compiler,
    pub target: Interned<String>,
}

impl Step for RemoteTestServer {
    type Output = PathBuf;

    fn should_run(run: ShouldRun) -> ShouldRun {
        run.path("src/tools/remote-test-server")
    }

    fn make_run(run: RunConfig) {
        run.builder.ensure(RemoteTestServer {
            compiler: run.builder.compiler(run.builder.top_stage, run.builder.build.build),
            target: run.target,
        });
    }

    fn run(self, builder: &Builder) -> PathBuf {
        builder.ensure(ToolBuild {
            compiler: self.compiler,
            target: self.target,
            tool: "remote-test-server",
            mode: Mode::Libstd,
        })
    }
}

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Rustdoc {
    pub target_compiler: Compiler,
}

impl Step for Rustdoc {
    type Output = PathBuf;
    const DEFAULT: bool = true;
    const ONLY_HOSTS: bool = true;

    fn should_run(run: ShouldRun) -> ShouldRun {
        run.path("src/tools/rustdoc")
    }

    fn make_run(run: RunConfig) {
        run.builder.ensure(Rustdoc {
            target_compiler: run.builder.compiler(run.builder.top_stage, run.host),
        });
    }

    fn run(self, builder: &Builder) -> PathBuf {
        let build = builder.build;
        let target_compiler = self.target_compiler;
        let target = target_compiler.host;
        let build_compiler = if target_compiler.stage == 0 {
            builder.compiler(0, builder.build.build)
        } else {
            // Similar to `compile::Assemble`, build with the previous stage's compiler. Otherwise
            // we'd have stageN/bin/rustc and stageN/bin/rustdoc be effectively different stage
            // compilers, which isn't what we want.
            builder.compiler(target_compiler.stage - 1, builder.build.build)
        };

        builder.ensure(CleanTools { compiler: build_compiler, target, mode: Mode::Librustc });
        builder.ensure(compile::Rustc { compiler: build_compiler, target });

        let _folder = build.fold_output(|| format!("stage{}-rustdoc", target_compiler.stage));
        println!("Building rustdoc for stage{} ({})", target_compiler.stage, target_compiler.host);

        let mut cargo = prepare_tool_cargo(builder, build_compiler, target, "rustdoc");
        build.run(&mut cargo);
        let tool_rustdoc = build.cargo_out(build_compiler, Mode::Tool, target)
            .join(exe("rustdoc", &target_compiler.host));

        // don't create a stage0-sysroot/bin directory.
        if target_compiler.stage > 0 {
            let sysroot = builder.sysroot(target_compiler);
            let bindir = sysroot.join("bin");
            t!(fs::create_dir_all(&bindir));
            let bin_rustdoc = bindir.join(exe("rustdoc", &*target_compiler.host));
            let _ = fs::remove_file(&bin_rustdoc);
            copy(&tool_rustdoc, &bin_rustdoc);
            bin_rustdoc
        } else {
            tool_rustdoc
        }
    }
}

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Cargo {
    pub compiler: Compiler,
    pub target: Interned<String>,
}

impl Step for Cargo {
    type Output = PathBuf;
    const DEFAULT: bool = true;
    const ONLY_HOSTS: bool = true;

    fn should_run(run: ShouldRun) -> ShouldRun {
        let builder = run.builder;
        run.path("src/tools/cargo").default_condition(builder.build.config.extended)
    }

    fn make_run(run: RunConfig) {
        run.builder.ensure(Cargo {
            compiler: run.builder.compiler(run.builder.top_stage, run.builder.build.build),
            target: run.target,
        });
    }

    fn run(self, builder: &Builder) -> PathBuf {
        builder.ensure(native::Openssl {
            target: self.target,
        });
        // Cargo depends on procedural macros, which requires a full host
        // compiler to be available, so we need to depend on that.
        builder.ensure(compile::Rustc {
            compiler: self.compiler,
            target: builder.build.build,
        });
        builder.ensure(ToolBuild {
            compiler: self.compiler,
            target: self.target,
            tool: "cargo",
            mode: Mode::Librustc,
        })
    }
}

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Rls {
    pub compiler: Compiler,
    pub target: Interned<String>,
}

impl Step for Rls {
    type Output = PathBuf;
    const DEFAULT: bool = true;
    const ONLY_HOSTS: bool = true;

    fn should_run(run: ShouldRun) -> ShouldRun {
        let builder = run.builder;
        run.path("src/tools/rls").default_condition(builder.build.config.extended)
    }

    fn make_run(run: RunConfig) {
        run.builder.ensure(Rls {
            compiler: run.builder.compiler(run.builder.top_stage, run.builder.build.build),
            target: run.target,
        });
    }

    fn run(self, builder: &Builder) -> PathBuf {
        builder.ensure(native::Openssl {
            target: self.target,
        });
        // RLS depends on procedural macros, which requires a full host
        // compiler to be available, so we need to depend on that.
        builder.ensure(compile::Rustc {
            compiler: self.compiler,
            target: builder.build.build,
        });
        builder.ensure(ToolBuild {
            compiler: self.compiler,
            target: self.target,
            tool: "rls",
            mode: Mode::Librustc,
        })
    }
}

impl<'a> Builder<'a> {
    /// Get a `Command` which is ready to run `tool` in `stage` built for
    /// `host`.
    pub fn tool_cmd(&self, tool: Tool) -> Command {
        let mut cmd = Command::new(self.tool_exe(tool));
        let compiler = self.compiler(0, self.build.build);
        self.prepare_tool_cmd(compiler, &mut cmd);
        cmd
    }

    /// Prepares the `cmd` provided to be able to run the `compiler` provided.
    ///
    /// Notably this munges the dynamic library lookup path to point to the
    /// right location to run `compiler`.
    fn prepare_tool_cmd(&self, compiler: Compiler, cmd: &mut Command) {
        let host = &compiler.host;
        let mut paths: Vec<PathBuf> = vec![
            PathBuf::from(&self.sysroot_libdir(compiler, compiler.host)),
            self.cargo_out(compiler, Mode::Tool, *host).join("deps"),
        ];

        // On MSVC a tool may invoke a C compiler (e.g. compiletest in run-make
        // mode) and that C compiler may need some extra PATH modification. Do
        // so here.
        if compiler.host.contains("msvc") {
            let curpaths = env::var_os("PATH").unwrap_or_default();
            let curpaths = env::split_paths(&curpaths).collect::<Vec<_>>();
            for &(ref k, ref v) in self.cc[&compiler.host].0.env() {
                if k != "PATH" {
                    continue
                }
                for path in env::split_paths(v) {
                    if !curpaths.contains(&path) {
                        paths.push(path);
                    }
                }
            }
        }
        add_lib_path(paths, cmd);
    }
}
<commit_msg>Build rustdoc with the stageN compiler in N >= 2.<commit_after>// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::fs;
use std::env;
use std::path::PathBuf;
use std::process::Command;

use Mode;
use Compiler;
use builder::{Step, RunConfig, ShouldRun, Builder};
use util::{copy, exe, add_lib_path};
use compile::{self, libtest_stamp, libstd_stamp, librustc_stamp};
use native;
use channel::GitInfo;
use cache::Interned;

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
struct CleanTools {
    compiler: Compiler,
    target: Interned<String>,
    mode: Mode,
}

impl Step for CleanTools {
    type Output = ();

    fn should_run(run: ShouldRun) -> ShouldRun {
        run.never()
    }

    /// Build a tool in `src/tools`
    ///
    /// This will build the specified tool with the specified `host` compiler in
    /// `stage` into the normal cargo output directory.
    fn run(self, builder: &Builder) {
        let build = builder.build;
        let compiler = self.compiler;
        let target = self.target;
        let mode = self.mode;

        let stamp = match mode {
            Mode::Libstd => libstd_stamp(build, compiler, target),
            Mode::Libtest => libtest_stamp(build, compiler, target),
            Mode::Librustc => librustc_stamp(build, compiler, target),
            _ => panic!(),
        };
        let out_dir = build.cargo_out(compiler, Mode::Tool, target);
        build.clear_if_dirty(&out_dir, &stamp);
    }
}

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
struct ToolBuild {
    compiler: Compiler,
    target: Interned<String>,
    tool: &'static str,
    mode: Mode,
}

impl Step for ToolBuild {
    type Output = PathBuf;

    fn should_run(run: ShouldRun) -> ShouldRun {
        run.never()
    }

    /// Build a tool in `src/tools`
    ///
    /// This will build the specified tool with the specified `host` compiler in
    /// `stage` into the normal cargo output directory.
    fn run(self, builder: &Builder) -> PathBuf {
        let build = builder.build;
        let compiler = self.compiler;
        let target = self.target;
        let tool = self.tool;

        builder.ensure(CleanTools { compiler, target, mode: self.mode });
        match self.mode {
            Mode::Libstd => builder.ensure(compile::Std { compiler, target }),
            Mode::Libtest => builder.ensure(compile::Test { compiler, target }),
            Mode::Librustc => builder.ensure(compile::Rustc { compiler, target }),
            Mode::Tool => panic!("unexpected Mode::Tool for tool build")
        }

        let _folder = build.fold_output(|| format!("stage{}-{}", compiler.stage, tool));
        println!("Building stage{} tool {} ({})", compiler.stage, tool, target);

        let mut cargo = prepare_tool_cargo(builder, compiler, target, tool);
        build.run(&mut cargo);
        build.cargo_out(compiler, Mode::Tool, target).join(exe(tool, &compiler.host))
    }
}

fn prepare_tool_cargo(
    builder: &Builder,
    compiler: Compiler,
    target: Interned<String>,
    tool: &'static str,
) -> Command {
    let build = builder.build;
    let mut cargo = builder.cargo(compiler, Mode::Tool, target, "build");
    let dir = build.src.join("src/tools").join(tool);
    cargo.arg("--manifest-path").arg(dir.join("Cargo.toml"));

    // We don't want to build tools dynamically as they'll be running across
    // stages and such and it's just easier if they're not dynamically linked.
    cargo.env("RUSTC_NO_PREFER_DYNAMIC", "1");

    if let Some(dir) = build.openssl_install_dir(target) {
        cargo.env("OPENSSL_STATIC", "1");
        cargo.env("OPENSSL_DIR", dir);
        cargo.env("LIBZ_SYS_STATIC", "1");
    }

    cargo.env("CFG_RELEASE_CHANNEL", &build.config.channel);

    let info = GitInfo::new(&build.config, &dir);
    if let Some(sha) = info.sha() {
        cargo.env("CFG_COMMIT_HASH", sha);
    }
    if let Some(sha_short) = info.sha_short() {
        cargo.env("CFG_SHORT_COMMIT_HASH", sha_short);
    }
    if let Some(date) = info.commit_date() {
        cargo.env("CFG_COMMIT_DATE", date);
    }
    cargo
}

macro_rules! tool {
    ($($name:ident, $path:expr, $tool_name:expr, $mode:expr;)+) => {
        #[derive(Copy, Clone)]
        pub enum Tool {
            $(
                $name,
            )+
        }

        impl<'a> Builder<'a> {
            pub fn tool_exe(&self, tool: Tool) -> PathBuf {
                match tool {
                    $(Tool::$name =>
                        self.ensure($name {
                            compiler: self.compiler(0, self.build.build),
                            target: self.build.build,
                        }),
                    )+
                }
            }
        }

        $(
            #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
        pub struct $name {
            pub compiler: Compiler,
            pub target: Interned<String>,
        }

        impl Step for $name {
            type Output = PathBuf;

            fn should_run(run: ShouldRun) -> ShouldRun {
                run.path($path)
            }

            fn make_run(run: RunConfig) {
                run.builder.ensure($name {
                    compiler: run.builder.compiler(run.builder.top_stage, run.builder.build.build),
                    target: run.target,
                });
            }

            fn run(self, builder: &Builder) -> PathBuf {
                builder.ensure(ToolBuild {
                    compiler: self.compiler,
                    target: self.target,
                    tool: $tool_name,
                    mode: $mode,
                })
            }
        }
        )+
    }
}

tool!(
    Rustbook, "src/tools/rustbook", "rustbook", Mode::Librustc;
    ErrorIndex, "src/tools/error_index_generator", "error_index_generator", Mode::Librustc;
    UnstableBookGen, "src/tools/unstable-book-gen", "unstable-book-gen", Mode::Libstd;
    Tidy, "src/tools/tidy", "tidy", Mode::Libstd;
    Linkchecker, "src/tools/linkchecker", "linkchecker", Mode::Libstd;
    CargoTest, "src/tools/cargotest", "cargotest", Mode::Libstd;
    Compiletest, "src/tools/compiletest", "compiletest", Mode::Libtest;
    BuildManifest, "src/tools/build-manifest", "build-manifest", Mode::Librustc;
    RemoteTestClient, "src/tools/remote-test-client", "remote-test-client", Mode::Libstd;
    RustInstaller, "src/tools/rust-installer", "rust-installer", Mode::Libstd;
);

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct RemoteTestServer {
    pub compiler: Compiler,
    pub target: Interned<String>,
}

impl Step for RemoteTestServer {
    type Output = PathBuf;

    fn should_run(run: ShouldRun) -> ShouldRun {
        run.path("src/tools/remote-test-server")
    }

    fn make_run(run: RunConfig) {
        run.builder.ensure(RemoteTestServer {
            compiler: run.builder.compiler(run.builder.top_stage, run.builder.build.build),
            target: run.target,
        });
    }

    fn run(self, builder: &Builder) -> PathBuf {
        builder.ensure(ToolBuild {
            compiler: self.compiler,
            target: self.target,
            tool: "remote-test-server",
            mode: Mode::Libstd,
        })
    }
}

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Rustdoc {
    pub target_compiler: Compiler,
}

impl Step for Rustdoc {
    type Output = PathBuf;
    const DEFAULT: bool = true;
    const ONLY_HOSTS: bool = true;

    fn should_run(run: ShouldRun) -> ShouldRun {
        run.path("src/tools/rustdoc")
    }

    fn make_run(run: RunConfig) {
        run.builder.ensure(Rustdoc {
            target_compiler: run.builder.compiler(run.builder.top_stage, run.host),
        });
    }

    fn run(self, builder: &Builder) -> PathBuf {
        let build = builder.build;
        let target_compiler = self.target_compiler;
        let target = target_compiler.host;
        let build_compiler = if target_compiler.stage == 0 {
            builder.compiler(0, builder.build.build)
        } else if target_compiler.stage >= 2 {
            // Past stage 2, we consider the compiler to be ABI-compatible and hence capable of
            // building rustdoc itself.
            target_compiler
        } else {
            // Similar to `compile::Assemble`, build with the previous stage's compiler. Otherwise
            // we'd have stageN/bin/rustc and stageN/bin/rustdoc be effectively different stage
            // compilers, which isn't what we want.
            builder.compiler(target_compiler.stage - 1, builder.build.build)
        };

        builder.ensure(CleanTools { compiler: build_compiler, target, mode: Mode::Librustc });
        builder.ensure(compile::Rustc { compiler: build_compiler, target });

        let _folder = build.fold_output(|| format!("stage{}-rustdoc", target_compiler.stage));
        println!("Building rustdoc for stage{} ({})", target_compiler.stage, target_compiler.host);

        let mut cargo = prepare_tool_cargo(builder, build_compiler, target, "rustdoc");
        build.run(&mut cargo);
        let tool_rustdoc = build.cargo_out(build_compiler, Mode::Tool, target)
            .join(exe("rustdoc", &target_compiler.host));

        // don't create a stage0-sysroot/bin directory.
        if target_compiler.stage > 0 {
            let sysroot = builder.sysroot(target_compiler);
            let bindir = sysroot.join("bin");
            t!(fs::create_dir_all(&bindir));
            let bin_rustdoc = bindir.join(exe("rustdoc", &*target_compiler.host));
            let _ = fs::remove_file(&bin_rustdoc);
            copy(&tool_rustdoc, &bin_rustdoc);
            bin_rustdoc
        } else {
            tool_rustdoc
        }
    }
}

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Cargo {
    pub compiler: Compiler,
    pub target: Interned<String>,
}

impl Step for Cargo {
    type Output = PathBuf;
    const DEFAULT: bool = true;
    const ONLY_HOSTS: bool = true;

    fn should_run(run: ShouldRun) -> ShouldRun {
        let builder = run.builder;
        run.path("src/tools/cargo").default_condition(builder.build.config.extended)
    }

    fn make_run(run: RunConfig) {
        run.builder.ensure(Cargo {
            compiler: run.builder.compiler(run.builder.top_stage, run.builder.build.build),
            target: run.target,
        });
    }

    fn run(self, builder: &Builder) -> PathBuf {
        builder.ensure(native::Openssl {
            target: self.target,
        });
        // Cargo depends on procedural macros, which requires a full host
        // compiler to be available, so we need to depend on that.
        builder.ensure(compile::Rustc {
            compiler: self.compiler,
            target: builder.build.build,
        });
        builder.ensure(ToolBuild {
            compiler: self.compiler,
            target: self.target,
            tool: "cargo",
            mode: Mode::Librustc,
        })
    }
}

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub struct Rls {
    pub compiler: Compiler,
    pub target: Interned<String>,
}

impl Step for Rls {
    type Output = PathBuf;
    const DEFAULT: bool = true;
    const ONLY_HOSTS: bool = true;

    fn should_run(run: ShouldRun) -> ShouldRun {
        let builder = run.builder;
        run.path("src/tools/rls").default_condition(builder.build.config.extended)
    }

    fn make_run(run: RunConfig) {
        run.builder.ensure(Rls {
            compiler: run.builder.compiler(run.builder.top_stage, run.builder.build.build),
            target: run.target,
        });
    }

    fn run(self, builder: &Builder) -> PathBuf {
        builder.ensure(native::Openssl {
            target: self.target,
        });
        // RLS depends on procedural macros, which requires a full host
        // compiler to be available, so we need to depend on that.
        builder.ensure(compile::Rustc {
            compiler: self.compiler,
            target: builder.build.build,
        });
        builder.ensure(ToolBuild {
            compiler: self.compiler,
            target: self.target,
            tool: "rls",
            mode: Mode::Librustc,
        })
    }
}

impl<'a> Builder<'a> {
    /// Get a `Command` which is ready to run `tool` in `stage` built for
    /// `host`.
    pub fn tool_cmd(&self, tool: Tool) -> Command {
        let mut cmd = Command::new(self.tool_exe(tool));
        let compiler = self.compiler(0, self.build.build);
        self.prepare_tool_cmd(compiler, &mut cmd);
        cmd
    }

    /// Prepares the `cmd` provided to be able to run the `compiler` provided.
    ///
    /// Notably this munges the dynamic library lookup path to point to the
    /// right location to run `compiler`.
    fn prepare_tool_cmd(&self, compiler: Compiler, cmd: &mut Command) {
        let host = &compiler.host;
        let mut paths: Vec<PathBuf> = vec![
            PathBuf::from(&self.sysroot_libdir(compiler, compiler.host)),
            self.cargo_out(compiler, Mode::Tool, *host).join("deps"),
        ];

        // On MSVC a tool may invoke a C compiler (e.g. compiletest in run-make
        // mode) and that C compiler may need some extra PATH modification. Do
        // so here.
        if compiler.host.contains("msvc") {
            let curpaths = env::var_os("PATH").unwrap_or_default();
            let curpaths = env::split_paths(&curpaths).collect::<Vec<_>>();
            for &(ref k, ref v) in self.cc[&compiler.host].0.env() {
                if k != "PATH" {
                    continue
                }
                for path in env::split_paths(v) {
                    if !curpaths.contains(&path) {
                        paths.push(path);
                    }
                }
            }
        }
        add_lib_path(paths, cmd);
    }
}
<|endoftext|>


<commit_before>use nalgebra::na::{Vec3};
use ncollide3df32::bounding_volume::aabb::AABB;
use std::collections::HashSet;
use std::hash::Hash;
use std::mem;
use std::ptr::RawPtr;

type F = f32;

fn less(p1: &Vec3<F>, p2: &Vec3<F>) -> bool {
  p1.x < p2.x &&
  p1.y < p2.y &&
  p1.z < p2.z
}

fn lequal(p1: &Vec3<F>, p2: &Vec3<F>) -> bool {
  p1.x <= p2.x &&
  p1.y <= p2.y &&
  p1.z <= p2.z
}

fn intersect(b1: &AABB, b2: &AABB) -> bool {
  let r = less(b1.mins(), b2.maxs()) && less(b2.mins(), b1.maxs());
  r
}

fn contains(b1: &AABB, b2: &AABB) -> bool {
  lequal(b1.mins(), b2.mins()) && lequal(b2.mins(), b2.maxs())
}

fn length(bounds: &AABB, d: Dimension) -> F {
  get(d, bounds.maxs()) - get(d, bounds.mins())
}

fn middle(bounds: &AABB, d: Dimension) -> F {
  (get(d, bounds.maxs()) + get(d, bounds.mins())) / 2.0
}

fn get(d: Dimension, p: &Vec3<F>) -> F {
  match d {
    X => p.x.clone(),
    Y => p.y.clone(),
    Z => p.z.clone(),
  }
}

fn set<F>(d: Dimension, p: &mut Vec3<F>, v: F) {
  match d {
    X => p.x = v,
    Y => p.y = v,
    Z => p.z = v,
  }
}

fn split(mid: F, d: Dimension, bounds: AABB) -> (Option<AABB>, Option<AABB>) {
  if get(d, bounds.maxs()) <= mid {
    (Some(bounds), None)
  } else if get(d, bounds.mins()) >= mid {
    (None, Some(bounds))
  } else {
    let (new_min, new_max) = {
      let (mut new_min, mut new_max) = (bounds.mins().clone(), bounds.maxs().clone());
      set(d, &mut new_min, mid.clone());
      set(d, &mut new_max, mid);
      (new_min, new_max)
    };
    (Some(AABB::new(*bounds.mins(), new_max)),
      Some(AABB::new(new_min, *bounds.maxs())))
  }
}

pub enum Dimension { X, Y, Z }

struct Branches<V> {
  low_tree: Box<Octree<V>>,
  high_tree: Box<Octree<V>>,
}

type LeafContents<V> = Vec<(AABB, V)>;

enum OctreeContents<V> {
  Empty,
  Leaf(LeafContents<V>),
  Branch(Branches<V>),
}

pub struct Octree<V> {
  parent: *mut Octree<V>,
  dimension: Dimension,
  bounds: AABB,
  contents: OctreeContents<V>,
}

impl<V: Clone + Eq + Hash> Octree<V> {
  pub fn new(bounds: &AABB) -> Octree<V> {
    Octree {
      parent: RawPtr::null(),
      dimension: X,
      bounds: bounds.clone(),
      contents: Empty,
    }
  }

  pub fn insert(&mut self, bounds: AABB, v: V) -> *mut Octree<V> {
    assert!(contains(&self.bounds, &bounds));
    let t: Option<*mut Octree<V>> =
      match self.contents {
        Empty => {
          let vs = Vec::from_elem(1, (bounds.clone(), v.clone()));
          // if the object mostly fills the leaf, don't bother subsecting space more.
          if length(&bounds, self.dimension) * (2.0 as f32) < length(&self.bounds, self.dimension) {
            let mid = middle(&self.bounds, self.dimension);

            let d = self.dimension;
            let (low, high) = self.bisect(mid);
            let (mut low, mut high) = (box low, box high);
            unsafe {
              let (low_bounds, high_bounds) = split(mid.clone(), d, bounds);
              let mut spans_multiple = false;
              let mut parent = None;
              low_bounds.map(
                |bs| {
                  low.insert(bs, v.clone());
                  spans_multiple = true;
                  parent = Some(mem::transmute(&mut *low));
                }
              );
              high_bounds.map(
                |bs| {
                  high.insert(bs, v.clone());
                  spans_multiple = true;
                  parent = Some(mem::transmute(&mut *high));
                }
              );

              self.contents = Branch(Branches { low_tree: low, high_tree: high });

              if spans_multiple {
                None
              } else {
                parent
              }
            }
          } else {
            self.contents = Leaf(vs);
            None
          }
        },
        Leaf(ref mut vs) => {
          vs.push((bounds, v));
          // TODO: bisect this leaf if the median length is less than half the
          // current length.
          None
        },
        Branch(ref mut b) => {
          // copied in remove()
          let (l, h) = split(middle(&self.bounds, self.dimension), self.dimension, bounds);
          l.map(|low_half| { b.low_tree.insert(low_half, v.clone()); });
          h.map(|high_half| { b.high_tree.insert(high_half, v.clone()); });
          None
        },
      };
    unsafe {
      t.map_or(mem::transmute(self), |x| { mem::transmute(x) })
    }
  }

  // Split this tree into two sub-trees around a given point,
  fn bisect(&mut self, mid: F) -> (Octree<V>, Octree<V>) {
    let (low_bounds, high_bounds) = split(mid.clone(), self.dimension, self.bounds.clone());
    let low_bounds = low_bounds.expect("world bounds couldn't split on middle");
    let high_bounds = high_bounds.expect("world bounds couldn't split on middle");
    let new_d = match self.dimension {
        X => Y,
        Y => Z,
        Z => X,
      };

    (
      Octree {
        parent: self,
        dimension: new_d,
        bounds: low_bounds.clone(),
        contents: Empty,
      },
      Octree {
        parent: self,
        dimension: new_d,
        bounds: high_bounds.clone(),
        contents: Empty
      }
    )
  }

  fn on_ancestor<T>(&self, bounds: &AABB, f: |&Octree<V>| -> T) -> T {
    if contains(&self.bounds, bounds) {
      f(self)
    } else {
      unsafe {
        assert!(self.parent.is_not_null());
        (*self.parent).on_ancestor(bounds, f)
      }
    }
  }

  fn on_mut_ancestor<T>(&mut self, bounds: &AABB, f: |&mut Octree<V>| -> T) -> T {
    if contains(&self.bounds, bounds) {
      f(self)
    } else {
      unsafe {
        assert!(self.parent.is_not_null());
        (*self.parent).on_mut_ancestor(bounds, f)
      }
    }
  }

  // Find whether there are objects overlapping the object & bounds provided in
  // this/child trees. Uses equality comparison on V to ignore "same" objects.
  pub fn intersect(&self, bounds: &AABB, self_v: V) -> bool {
    match self.contents {
      Empty => false,
      Leaf(ref vs) => vs.iter().any(|&(bs, ref v)| { *v != self_v && intersect(bounds, &bs) }),
      Branch(ref b) => {
        let mid = middle(&self.bounds, self.dimension);
        let (low_bounds, high_bounds) = split(mid, self.dimension, *bounds);
        low_bounds.map_or(false, |bs| { b.low_tree.intersect(&bs, self_v.clone()) }) ||
        high_bounds.map_or(false, |bs| { b.high_tree.intersect(&bs, self_v.clone()) })
      }
    }
  }

  // Find details of objects overlapping the object & bounds provided in this
  // and child trees. Uses equality comparison on V to ignore "same" objects.
  // Only finds intersects in this and child trees.
  pub fn intersect_details(&self, bounds: &AABB, self_v: V) -> HashSet<V> {
    match self.contents {
      Empty => HashSet::new(),
      Leaf(ref vs) => {
        let mut r = HashSet::new();
        for &(bs, ref v) in vs.iter() {
          if *v != self_v {
            if intersect(bounds, &bs) {
              r.insert(v.clone());
            }
          }
        }
        r
      },
      Branch(ref b) => {
        let mut r = HashSet::new();
        let mid = middle(&self.bounds, self.dimension);
        let (low_bounds, high_bounds) = split(mid, self.dimension, *bounds);
        low_bounds.map(|bs| {
          for ref v in b.low_tree.intersect_details(&bs, self_v.clone()).iter() {
            r.insert((*v).clone());
          }
        });
        high_bounds.map(|bs| {
          for ref v in b.high_tree.intersect_details(&bs, self_v.clone()).iter() {
            r.insert((*v).clone());
          }
        });
        r
      }
    }
  }

  #[allow(dead_code)]
  // Find the details of objects overlapping the object & bounds provided in
  // this tree, any children, or any relatives, starting the search from the
  // current tree. Uses equality comparison on V to ignore "same" objects.
  pub fn intersect_details_from(&self, bounds: &AABB, self_v: V) -> HashSet<V> {
    self.on_ancestor(bounds, |t| { t.intersect_details(bounds, self_v.clone()) })
  }

  // like insert, but before recursing downward, we recurse up the parents
  // until the bounds provided are inside the tree.
  fn insert_from(&mut self, bounds: AABB, v: V) -> *mut Octree<V> {
    self.on_mut_ancestor(&bounds, |t| { t.insert(bounds.clone(), v.clone()) })
  }

  // TODO: consider collapsing space
  pub fn remove(&mut self, v: V, bounds: &AABB) {
    assert!(contains(&self.bounds, bounds));
    // copied largely from insert()
    match self.contents {
      Empty => {
        fail!("Could not Octree::remove(&Empty)");
      },
      Leaf(ref mut vs) => {
        let i = vs.iter().position(|&(_, ref x)| { *x == v }).expect("could not Octree::remove()");
        vs.swap_remove(i);
      },
      Branch(ref mut bs) => {
        let (l, h) = split(middle(&self.bounds, self.dimension), self.dimension, *bounds);
        l.map(|low_half| { bs.low_tree.remove(v.clone(), &low_half); });
        h.map(|high_half| { bs.high_tree.remove(v.clone(), &high_half); });
      }
    }
  }

  pub fn move(&mut self, v: V, bounds: &AABB, new_bounds: AABB) -> *mut Octree<V> {
    self.remove(v.clone(), bounds);
    self.insert_from(new_bounds, v)
  }
}
<commit_msg>use more ncollide functions<commit_after>use nalgebra::na::{Vec3};
use ncollide3df32::bounding_volume::aabb::AABB;
use ncollide3df32::bounding_volume::BoundingVolume;
use std::collections::HashSet;
use std::hash::Hash;
use std::mem;
use std::ptr::RawPtr;

type F = f32;

fn length(bounds: &AABB, d: Dimension) -> F {
  get(d, bounds.maxs()) - get(d, bounds.mins())
}

fn middle(bounds: &AABB, d: Dimension) -> F {
  (get(d, bounds.maxs()) + get(d, bounds.mins())) / 2.0
}

fn get(d: Dimension, p: &Vec3<F>) -> F {
  match d {
    X => p.x.clone(),
    Y => p.y.clone(),
    Z => p.z.clone(),
  }
}

fn set<F>(d: Dimension, p: &mut Vec3<F>, v: F) {
  match d {
    X => p.x = v,
    Y => p.y = v,
    Z => p.z = v,
  }
}

fn split(mid: F, d: Dimension, bounds: AABB) -> (Option<AABB>, Option<AABB>) {
  if get(d, bounds.maxs()) <= mid {
    (Some(bounds), None)
  } else if get(d, bounds.mins()) >= mid {
    (None, Some(bounds))
  } else {
    let (new_min, new_max) = {
      let (mut new_min, mut new_max) = (bounds.mins().clone(), bounds.maxs().clone());
      set(d, &mut new_min, mid.clone());
      set(d, &mut new_max, mid);
      (new_min, new_max)
    };
    (Some(AABB::new(*bounds.mins(), new_max)),
      Some(AABB::new(new_min, *bounds.maxs())))
  }
}

pub enum Dimension { X, Y, Z }

struct Branches<V> {
  low_tree: Box<Octree<V>>,
  high_tree: Box<Octree<V>>,
}

type LeafContents<V> = Vec<(AABB, V)>;

enum OctreeContents<V> {
  Empty,
  Leaf(LeafContents<V>),
  Branch(Branches<V>),
}

pub struct Octree<V> {
  parent: *mut Octree<V>,
  dimension: Dimension,
  bounds: AABB,
  contents: OctreeContents<V>,
}

impl<V: Clone + Eq + Hash> Octree<V> {
  pub fn new(bounds: &AABB) -> Octree<V> {
    Octree {
      parent: RawPtr::null(),
      dimension: X,
      bounds: bounds.clone(),
      contents: Empty,
    }
  }

  pub fn insert(&mut self, bounds: AABB, v: V) -> *mut Octree<V> {
    assert!(self.bounds.contains(&bounds));
    let t: Option<*mut Octree<V>> =
      match self.contents {
        Empty => {
          let vs = Vec::from_elem(1, (bounds.clone(), v.clone()));
          // if the object mostly fills the leaf, don't bother subsecting space more.
          if length(&bounds, self.dimension) * (2.0 as f32) < length(&self.bounds, self.dimension) {
            let mid = middle(&self.bounds, self.dimension);

            let d = self.dimension;
            let (low, high) = self.bisect(mid);
            let (mut low, mut high) = (box low, box high);
            unsafe {
              let (low_bounds, high_bounds) = split(mid.clone(), d, bounds);
              let mut spans_multiple = false;
              let mut parent = None;
              low_bounds.map(
                |bs| {
                  low.insert(bs, v.clone());
                  spans_multiple = true;
                  parent = Some(mem::transmute(&mut *low));
                }
              );
              high_bounds.map(
                |bs| {
                  high.insert(bs, v.clone());
                  spans_multiple = true;
                  parent = Some(mem::transmute(&mut *high));
                }
              );

              self.contents = Branch(Branches { low_tree: low, high_tree: high });

              if spans_multiple {
                None
              } else {
                parent
              }
            }
          } else {
            self.contents = Leaf(vs);
            None
          }
        },
        Leaf(ref mut vs) => {
          vs.push((bounds, v));
          // TODO: bisect this leaf if the median length is less than half the
          // current length.
          None
        },
        Branch(ref mut b) => {
          // copied in remove()
          let (l, h) = split(middle(&self.bounds, self.dimension), self.dimension, bounds);
          l.map(|low_half| { b.low_tree.insert(low_half, v.clone()); });
          h.map(|high_half| { b.high_tree.insert(high_half, v.clone()); });
          None
        },
      };
    unsafe {
      t.map_or(mem::transmute(self), |x| { mem::transmute(x) })
    }
  }

  // Split this tree into two sub-trees around a given point,
  fn bisect(&mut self, mid: F) -> (Octree<V>, Octree<V>) {
    let (low_bounds, high_bounds) = split(mid.clone(), self.dimension, self.bounds.clone());
    let low_bounds = low_bounds.expect("world bounds couldn't split on middle");
    let high_bounds = high_bounds.expect("world bounds couldn't split on middle");
    let new_d = match self.dimension {
        X => Y,
        Y => Z,
        Z => X,
      };

    (
      Octree {
        parent: self,
        dimension: new_d,
        bounds: low_bounds.clone(),
        contents: Empty,
      },
      Octree {
        parent: self,
        dimension: new_d,
        bounds: high_bounds.clone(),
        contents: Empty
      }
    )
  }

  fn on_ancestor<T>(&self, bounds: &AABB, f: |&Octree<V>| -> T) -> T {
    if self.bounds.contains(bounds) {
      f(self)
    } else {
      unsafe {
        assert!(self.parent.is_not_null());
        (*self.parent).on_ancestor(bounds, f)
      }
    }
  }

  fn on_mut_ancestor<T>(&mut self, bounds: &AABB, f: |&mut Octree<V>| -> T) -> T {
    if self.bounds.contains(bounds) {
      f(self)
    } else {
      unsafe {
        assert!(self.parent.is_not_null());
        (*self.parent).on_mut_ancestor(bounds, f)
      }
    }
  }

  // Find whether there are objects overlapping the object & bounds provided in
  // this/child trees. Uses equality comparison on V to ignore "same" objects.
  pub fn intersect(&self, bounds: &AABB, self_v: V) -> bool {
    match self.contents {
      Empty => false,
      Leaf(ref vs) => vs.iter().any(|&(bs, ref v)| { *v != self_v && bounds.intersects(&bs) }),
      Branch(ref b) => {
        let mid = middle(&self.bounds, self.dimension);
        let (low_bounds, high_bounds) = split(mid, self.dimension, *bounds);
        low_bounds.map_or(false, |bs| { b.low_tree.intersect(&bs, self_v.clone()) }) ||
        high_bounds.map_or(false, |bs| { b.high_tree.intersect(&bs, self_v.clone()) })
      }
    }
  }

  // Find details of objects overlapping the object & bounds provided in this
  // and child trees. Uses equality comparison on V to ignore "same" objects.
  // Only finds intersects in this and child trees.
  pub fn intersect_details(&self, bounds: &AABB, self_v: V) -> HashSet<V> {
    match self.contents {
      Empty => HashSet::new(),
      Leaf(ref vs) => {
        let mut r = HashSet::new();
        for &(bs, ref v) in vs.iter() {
          if *v != self_v {
            if bounds.intersects(&bs) {
              r.insert(v.clone());
            }
          }
        }
        r
      },
      Branch(ref b) => {
        let mut r = HashSet::new();
        let mid = middle(&self.bounds, self.dimension);
        let (low_bounds, high_bounds) = split(mid, self.dimension, *bounds);
        low_bounds.map(|bs| {
          for ref v in b.low_tree.intersect_details(&bs, self_v.clone()).iter() {
            r.insert((*v).clone());
          }
        });
        high_bounds.map(|bs| {
          for ref v in b.high_tree.intersect_details(&bs, self_v.clone()).iter() {
            r.insert((*v).clone());
          }
        });
        r
      }
    }
  }

  #[allow(dead_code)]
  // Find the details of objects overlapping the object & bounds provided in
  // this tree, any children, or any relatives, starting the search from the
  // current tree. Uses equality comparison on V to ignore "same" objects.
  pub fn intersect_details_from(&self, bounds: &AABB, self_v: V) -> HashSet<V> {
    self.on_ancestor(bounds, |t| { t.intersect_details(bounds, self_v.clone()) })
  }

  // like insert, but before recursing downward, we recurse up the parents
  // until the bounds provided are inside the tree.
  fn insert_from(&mut self, bounds: AABB, v: V) -> *mut Octree<V> {
    self.on_mut_ancestor(&bounds, |t| { t.insert(bounds.clone(), v.clone()) })
  }

  // TODO: consider collapsing space
  pub fn remove(&mut self, v: V, bounds: &AABB) {
    assert!(self.bounds.contains(bounds));
    // copied largely from insert()
    match self.contents {
      Empty => {
        fail!("Could not Octree::remove(&Empty)");
      },
      Leaf(ref mut vs) => {
        let i = vs.iter().position(|&(_, ref x)| { *x == v }).expect("could not Octree::remove()");
        vs.swap_remove(i);
      },
      Branch(ref mut bs) => {
        let (l, h) = split(middle(&self.bounds, self.dimension), self.dimension, *bounds);
        l.map(|low_half| { bs.low_tree.remove(v.clone(), &low_half); });
        h.map(|high_half| { bs.high_tree.remove(v.clone(), &high_half); });
      }
    }
  }

  pub fn move(&mut self, v: V, bounds: &AABB, new_bounds: AABB) -> *mut Octree<V> {
    self.remove(v.clone(), bounds);
    self.insert_from(new_bounds, v)
  }
}
<|endoftext|>


<commit_before>use client::bridge::gateway::ShardMessenger;
use gateway::InterMessage;
use model::prelude::*;
use parking_lot::Mutex;
use std::sync::{
    mpsc::Sender,
    Arc
};
use typemap::ShareMap;

#[cfg(feature = "builder")]
use builder::EditProfile;
#[cfg(feature = "builder")]
use internal::prelude::*;
#[cfg(all(feature = "builder", feature = "cache"))]
use super::CACHE;
#[cfg(feature = "builder")]
use {Result, http};
#[cfg(feature = "builder")]
use utils::{self, VecMap};

/// The context is a general utility struct provided on event dispatches, which
/// helps with dealing with the current "context" of the event dispatch.
/// The context also acts as a general high-level interface over the associated
/// [`Shard`] which received the event, or the low-level [`http`] module.
///
/// The context contains "shortcuts", like for interacting with the shard.
/// Methods like [`set_game`] will unlock the shard and perform an update for
/// you to save a bit of work.
///
/// A context will only live for the event it was dispatched for. After the
/// event handler finished, it is destroyed and will not be re-used.
///
/// [`Shard`]: ../gateway/struct.Shard.html
/// [`http`]: ../http/index.html
/// [`set_game`]: #method.set_game
#[derive(Clone)]
pub struct Context {
    /// A clone of [`Client::data`]. Refer to its documentation for more
    /// information.
    ///
    /// [`Client::data`]: struct.Client.html#structfield.data
    pub data: Arc<Mutex<ShareMap>>,
    /// The messenger to communicate with the shard runner.
    pub shard: ShardMessenger,
    /// The ID of the shard this context is related to.
    pub shard_id: u64,
}

impl Context {
    /// Create a new Context to be passed to an event handler.
    pub(crate) fn new(
        data: Arc<Mutex<ShareMap>>,
        runner_tx: Sender<InterMessage>,
        shard_id: u64,
    ) -> Context {
        Context {
            shard: ShardMessenger::new(runner_tx),
            shard_id,
            data,
        }
    }

    /// Edits the current user's profile settings.
    ///
    /// Refer to `EditProfile`'s documentation for its methods.
    ///
    /// # Examples
    ///
    /// Change the current user's username:
    ///
    /// ```rust,no_run
    /// # use serenity::prelude::*;
    /// # use serenity::model::channel::Message;
    /// #
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn message(&self, ctx: Context, msg: Message) {
    ///         if msg.content == "!changename" {
    ///             ctx.edit_profile(|e| e.username("Edward Elric"));
    ///         }
    ///     }
    /// }
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// ```
    #[cfg(feature = "builder")]
    pub fn edit_profile<F: FnOnce(EditProfile) -> EditProfile>(&self, f: F) -> Result<CurrentUser> {
        let mut map = VecMap::with_capacity(2);

        feature_cache! {
            {
                let cache = CACHE.read();

                map.insert("username", Value::String(cache.user.name.clone()));

                if let Some(email) = cache.user.email.as_ref() {
                    map.insert("email", Value::String(email.clone()));
                }
            } else {
                let user = http::get_current_user()?;

                map.insert("username", Value::String(user.name));

                if let Some(email) = user.email {
                    map.insert("email", Value::String(email));
                }
            }
        }

        let edited = utils::vecmap_to_json_map(f(EditProfile(map)).0);

        http::edit_profile(&edited)
    }

    /// Sets the current user as being [`Online`]. This maintains the current
    /// game.
    ///
    /// # Examples
    ///
    /// Set the current user to being online on the shard:
    ///
    /// ```rust,no_run
    /// # use serenity::prelude::*;
    /// # use serenity::model::channel::Message;
    /// #
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn message(&self, ctx: Context, msg: Message) {
    ///         if msg.content == "!online" {
    ///             ctx.online();
    ///         }
    ///     }
    /// }
    ///
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// ```
    ///
    /// [`Online`]: ../model/user/enum.OnlineStatus.html#variant.Online
    #[inline]
    pub fn online(&self) {
        self.shard.set_status(OnlineStatus::Online);
    }

    /// Sets the current user as being [`Idle`]. This maintains the current
    /// game.
    ///
    /// # Examples
    ///
    /// Set the current user to being idle on the shard:
    ///
    /// ```rust,no_run
    /// # use serenity::prelude::*;
    /// # use serenity::model::channel::Message;
    /// #
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn message(&self, ctx: Context, msg: Message) {
    ///         if msg.content == "!idle" {
    ///             ctx.idle();
    ///         }
    ///     }
    /// }
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// ```
    ///
    /// [`Idle`]: ../model/user/enum.OnlineStatus.html#variant.Idle
    #[inline]
    pub fn idle(&self) {
        self.shard.set_status(OnlineStatus::Idle);
    }

    /// Sets the current user as being [`DoNotDisturb`]. This maintains the
    /// current game.
    ///
    /// # Examples
    ///
    /// Set the current user to being Do Not Disturb on the shard:
    ///
    /// ```rust,no_run
    /// # use serenity::prelude::*;
    /// # use serenity::model::channel::Message;
    /// #
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn message(&self, ctx: Context, msg: Message) {
    ///         if msg.content == "!dnd" {
    ///             ctx.dnd();
    ///         }
    ///     }
    /// }
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// ```
    ///
    /// [`DoNotDisturb`]: ../model/user/enum.OnlineStatus.html#variant.DoNotDisturb
    #[inline]
    pub fn dnd(&self) {
        self.shard.set_status(OnlineStatus::DoNotDisturb);
    }

    /// Sets the current user as being [`Invisible`]. This maintains the current
    /// game.
    ///
    /// # Examples
    ///
    /// Set the current user to being invisible on the shard when an
    /// [`Event::Ready`] is received:
    ///
    /// ```rust,no_run
    /// # use serenity::prelude::*;
    /// # use serenity::model::gateway::Ready;
    /// #
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn ready(&self, ctx: Context, _: Ready) {
    ///         ctx.invisible();
    ///     }
    /// }
    ///
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// ```
    ///
    /// [`Event::Ready`]: ../model/event/enum.Event.html#variant.Ready
    /// [`Invisible`]: ../model/user/enum.OnlineStatus.html#variant.Invisible
    #[inline]
    pub fn invisible(&self) {
        self.shard.set_status(OnlineStatus::Invisible);
    }

    /// "Resets" the current user's presence, by setting the game to `None` and
    /// the online status to [`Online`].
    ///
    /// Use [`set_presence`] for fine-grained control over individual details.
    ///
    /// # Examples
    ///
    /// Reset the presence when an [`Event::Resumed`] is received:
    ///
    /// ```rust,no_run
    /// # use serenity::prelude::*;
    /// # use serenity::model::event::ResumedEvent;
    /// #
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn resume(&self, ctx: Context, _: ResumedEvent) {
    ///         ctx.reset_presence();
    ///     }
    /// }
    ///
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// ```
    ///
    /// [`Event::Resumed`]: ../model/event/enum.Event.html#variant.Resumed
    /// [`Online`]: ../model/user/enum.OnlineStatus.html#variant.Online
    /// [`set_presence`]: #method.set_presence
    #[inline]
    pub fn reset_presence(&self) {
        self.shard.set_presence(None, OnlineStatus::Online);
    }

    /// Sets the current game, defaulting to an online status of [`Online`].
    ///
    /// # Examples
    ///
    /// Create a command named `~setgame` that accepts a name of a game to be
    /// playing:
    ///
    /// ```rust,no_run
    /// # #[cfg(feature = "model")]
    /// # fn main() {
    /// # use serenity::prelude::*;
    /// # use serenity::model::channel::Message;
    /// #
    /// use serenity::model::gateway::Game;
    ///
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn message(&self, ctx: Context, msg: Message) {
    ///         let args = msg.content.splitn(2, ' ').collect::<Vec<&str>>();
    ///
    ///         if args.len() < 2 || *unsafe { args.get_unchecked(0) } != "~setgame" {
    ///             return;
    ///         }
    ///
    ///         ctx.set_game(Game::playing(*unsafe { args.get_unchecked(1) }));
    ///     }
    /// }
    ///
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// # }
    ///
    /// # #[cfg(not(feature = "model"))]
    /// # fn main() {}
    /// ```
    ///
    /// [`Online`]: ../model/user/enum.OnlineStatus.html#variant.Online
    #[inline]
    pub fn set_game(&self, game: Game) {
        self.shard.set_presence(Some(game), OnlineStatus::Online);
    }

    /// Sets the current game, passing in only its name. This will automatically
    /// set the current user's [`OnlineStatus`] to [`Online`], and its
    /// [`GameType`] as [`Playing`].
    ///
    /// Use [`reset_presence`] to clear the current game, or [`set_presence`]
    /// for more fine-grained control.
    ///
    /// **Note**: Maximum length is 128.
    ///
    /// # Examples
    ///
    /// When an [`Event::Ready`] is received, set the game name to `"test"`:
    ///
    /// ```rust,no_run
    /// # use serenity::prelude::*;
    /// # use serenity::model::gateway::Ready;
    /// #
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn ready(&self, ctx: Context, _: Ready) {
    ///         ctx.set_game_name("test");
    ///     }
    /// }
    ///
    /// let mut client = Client::new("token", Handler).unwrap();
    /// client.start().unwrap();
    /// ```
    ///
    /// [`Event::Ready`]: ../model/event/enum.Event.html#variant.Ready
    /// [`GameType`]: ../model/gateway/enum.GameType.html
    /// [`Online`]: ../model/user/enum.OnlineStatus.html#variant.Online
    /// [`OnlineStatus`]: ../model/user/enum.OnlineStatus.html
    /// [`Playing`]: ../model/gateway/enum.GameType.html#variant.Playing
    /// [`reset_presence`]: #method.reset_presence
    /// [`set_presence`]: #method.set_presence
    pub fn set_game_name(&self, game_name: &str) {
        let game = Game {
            kind: GameType::Playing,
            name: game_name.to_string(),
            url: None,
        };

        self.shard.set_presence(Some(game), OnlineStatus::Online);
    }

    /// Sets the current user's presence, providing all fields to be passed.
    ///
    /// # Examples
    ///
    /// Setting the current user as having no game and being [`Idle`]:
    ///
    /// ```rust,no_run
    /// # use serenity::prelude::*;
    /// # use serenity::model::gateway::Ready;
    /// #
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn ready(&self, ctx: Context, _: Ready) {
    ///         use serenity::model::user::OnlineStatus;
    ///
    ///         ctx.set_presence(None, OnlineStatus::Idle);
    ///     }
    /// }
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// ```
    ///
    /// Setting the current user as playing `"Heroes of the Storm"`, while being
    /// [`DoNotDisturb`]:
    ///
    /// ```rust,ignore
    /// # use serenity::prelude::*;
    /// # use serenity::model::gateway::Ready;
    /// #
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn ready(&self, context: Context, _: Ready) {
    ///         use serenity::model::gateway::Game;
    ///         use serenity::model::user::OnlineStatus;
    ///
    ///         let game = Game::playing("Heroes of the Storm");
    ///         let status = OnlineStatus::DoNotDisturb;
    ///
    ///         context.set_presence(Some(game), status);
    ///     }
    /// }
    ///
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// ```
    ///
    /// [`DoNotDisturb`]: ../model/user/enum.OnlineStatus.html#variant.DoNotDisturb
    /// [`Idle`]: ../model/user/enum.OnlineStatus.html#variant.Idle
    #[inline]
    pub fn set_presence(&self, game: Option<Game>, status: OnlineStatus) {
        self.shard.set_presence(game, status);
    }

    /// Disconnects the shard from the websocket, essentially "quiting" it.
    /// Note however that this will only exit the one which the `Context` was given.
    /// If it's just one shard that's on, then serenity will stop any further actions
    /// until [`Client::start`] and vice versa are called again.
    ///
    /// [`Client::start`]: ./struct.Client.html#method.start
    #[inline]
    pub fn quit(&self) {
        self.shard.shutdown_clean();
    }
}
<commit_msg>Remove a usage of Clone::clone<commit_after>use client::bridge::gateway::ShardMessenger;
use gateway::InterMessage;
use model::prelude::*;
use parking_lot::Mutex;
use std::sync::{
    mpsc::Sender,
    Arc
};
use typemap::ShareMap;

#[cfg(feature = "builder")]
use builder::EditProfile;
#[cfg(feature = "builder")]
use internal::prelude::*;
#[cfg(all(feature = "builder", feature = "cache"))]
use super::CACHE;
#[cfg(feature = "builder")]
use {Result, http};
#[cfg(feature = "builder")]
use utils::{self, VecMap};

/// The context is a general utility struct provided on event dispatches, which
/// helps with dealing with the current "context" of the event dispatch.
/// The context also acts as a general high-level interface over the associated
/// [`Shard`] which received the event, or the low-level [`http`] module.
///
/// The context contains "shortcuts", like for interacting with the shard.
/// Methods like [`set_game`] will unlock the shard and perform an update for
/// you to save a bit of work.
///
/// A context will only live for the event it was dispatched for. After the
/// event handler finished, it is destroyed and will not be re-used.
///
/// [`Shard`]: ../gateway/struct.Shard.html
/// [`http`]: ../http/index.html
/// [`set_game`]: #method.set_game
#[derive(Clone)]
pub struct Context {
    /// A clone of [`Client::data`]. Refer to its documentation for more
    /// information.
    ///
    /// [`Client::data`]: struct.Client.html#structfield.data
    pub data: Arc<Mutex<ShareMap>>,
    /// The messenger to communicate with the shard runner.
    pub shard: ShardMessenger,
    /// The ID of the shard this context is related to.
    pub shard_id: u64,
}

impl Context {
    /// Create a new Context to be passed to an event handler.
    pub(crate) fn new(
        data: Arc<Mutex<ShareMap>>,
        runner_tx: Sender<InterMessage>,
        shard_id: u64,
    ) -> Context {
        Context {
            shard: ShardMessenger::new(runner_tx),
            shard_id,
            data,
        }
    }

    /// Edits the current user's profile settings.
    ///
    /// Refer to `EditProfile`'s documentation for its methods.
    ///
    /// # Examples
    ///
    /// Change the current user's username:
    ///
    /// ```rust,no_run
    /// # use serenity::prelude::*;
    /// # use serenity::model::channel::Message;
    /// #
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn message(&self, ctx: Context, msg: Message) {
    ///         if msg.content == "!changename" {
    ///             ctx.edit_profile(|e| e.username("Edward Elric"));
    ///         }
    ///     }
    /// }
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// ```
    #[cfg(feature = "builder")]
    pub fn edit_profile<F: FnOnce(EditProfile) -> EditProfile>(&self, f: F) -> Result<CurrentUser> {
        let mut map = VecMap::with_capacity(2);

        feature_cache! {
            {
                let cache = CACHE.read();

                map.insert("username", Value::String(cache.user.name.clone()));

                if let Some(email) = cache.user.email.clone() {
                    map.insert("email", Value::String(email));
                }
            } else {
                let user = http::get_current_user()?;

                map.insert("username", Value::String(user.name));

                if let Some(email) = user.email {
                    map.insert("email", Value::String(email));
                }
            }
        }

        let edited = utils::vecmap_to_json_map(f(EditProfile(map)).0);

        http::edit_profile(&edited)
    }

    /// Sets the current user as being [`Online`]. This maintains the current
    /// game.
    ///
    /// # Examples
    ///
    /// Set the current user to being online on the shard:
    ///
    /// ```rust,no_run
    /// # use serenity::prelude::*;
    /// # use serenity::model::channel::Message;
    /// #
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn message(&self, ctx: Context, msg: Message) {
    ///         if msg.content == "!online" {
    ///             ctx.online();
    ///         }
    ///     }
    /// }
    ///
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// ```
    ///
    /// [`Online`]: ../model/user/enum.OnlineStatus.html#variant.Online
    #[inline]
    pub fn online(&self) {
        self.shard.set_status(OnlineStatus::Online);
    }

    /// Sets the current user as being [`Idle`]. This maintains the current
    /// game.
    ///
    /// # Examples
    ///
    /// Set the current user to being idle on the shard:
    ///
    /// ```rust,no_run
    /// # use serenity::prelude::*;
    /// # use serenity::model::channel::Message;
    /// #
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn message(&self, ctx: Context, msg: Message) {
    ///         if msg.content == "!idle" {
    ///             ctx.idle();
    ///         }
    ///     }
    /// }
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// ```
    ///
    /// [`Idle`]: ../model/user/enum.OnlineStatus.html#variant.Idle
    #[inline]
    pub fn idle(&self) {
        self.shard.set_status(OnlineStatus::Idle);
    }

    /// Sets the current user as being [`DoNotDisturb`]. This maintains the
    /// current game.
    ///
    /// # Examples
    ///
    /// Set the current user to being Do Not Disturb on the shard:
    ///
    /// ```rust,no_run
    /// # use serenity::prelude::*;
    /// # use serenity::model::channel::Message;
    /// #
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn message(&self, ctx: Context, msg: Message) {
    ///         if msg.content == "!dnd" {
    ///             ctx.dnd();
    ///         }
    ///     }
    /// }
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// ```
    ///
    /// [`DoNotDisturb`]: ../model/user/enum.OnlineStatus.html#variant.DoNotDisturb
    #[inline]
    pub fn dnd(&self) {
        self.shard.set_status(OnlineStatus::DoNotDisturb);
    }

    /// Sets the current user as being [`Invisible`]. This maintains the current
    /// game.
    ///
    /// # Examples
    ///
    /// Set the current user to being invisible on the shard when an
    /// [`Event::Ready`] is received:
    ///
    /// ```rust,no_run
    /// # use serenity::prelude::*;
    /// # use serenity::model::gateway::Ready;
    /// #
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn ready(&self, ctx: Context, _: Ready) {
    ///         ctx.invisible();
    ///     }
    /// }
    ///
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// ```
    ///
    /// [`Event::Ready`]: ../model/event/enum.Event.html#variant.Ready
    /// [`Invisible`]: ../model/user/enum.OnlineStatus.html#variant.Invisible
    #[inline]
    pub fn invisible(&self) {
        self.shard.set_status(OnlineStatus::Invisible);
    }

    /// "Resets" the current user's presence, by setting the game to `None` and
    /// the online status to [`Online`].
    ///
    /// Use [`set_presence`] for fine-grained control over individual details.
    ///
    /// # Examples
    ///
    /// Reset the presence when an [`Event::Resumed`] is received:
    ///
    /// ```rust,no_run
    /// # use serenity::prelude::*;
    /// # use serenity::model::event::ResumedEvent;
    /// #
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn resume(&self, ctx: Context, _: ResumedEvent) {
    ///         ctx.reset_presence();
    ///     }
    /// }
    ///
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// ```
    ///
    /// [`Event::Resumed`]: ../model/event/enum.Event.html#variant.Resumed
    /// [`Online`]: ../model/user/enum.OnlineStatus.html#variant.Online
    /// [`set_presence`]: #method.set_presence
    #[inline]
    pub fn reset_presence(&self) {
        self.shard.set_presence(None, OnlineStatus::Online);
    }

    /// Sets the current game, defaulting to an online status of [`Online`].
    ///
    /// # Examples
    ///
    /// Create a command named `~setgame` that accepts a name of a game to be
    /// playing:
    ///
    /// ```rust,no_run
    /// # #[cfg(feature = "model")]
    /// # fn main() {
    /// # use serenity::prelude::*;
    /// # use serenity::model::channel::Message;
    /// #
    /// use serenity::model::gateway::Game;
    ///
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn message(&self, ctx: Context, msg: Message) {
    ///         let args = msg.content.splitn(2, ' ').collect::<Vec<&str>>();
    ///
    ///         if args.len() < 2 || *unsafe { args.get_unchecked(0) } != "~setgame" {
    ///             return;
    ///         }
    ///
    ///         ctx.set_game(Game::playing(*unsafe { args.get_unchecked(1) }));
    ///     }
    /// }
    ///
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// # }
    ///
    /// # #[cfg(not(feature = "model"))]
    /// # fn main() {}
    /// ```
    ///
    /// [`Online`]: ../model/user/enum.OnlineStatus.html#variant.Online
    #[inline]
    pub fn set_game(&self, game: Game) {
        self.shard.set_presence(Some(game), OnlineStatus::Online);
    }

    /// Sets the current game, passing in only its name. This will automatically
    /// set the current user's [`OnlineStatus`] to [`Online`], and its
    /// [`GameType`] as [`Playing`].
    ///
    /// Use [`reset_presence`] to clear the current game, or [`set_presence`]
    /// for more fine-grained control.
    ///
    /// **Note**: Maximum length is 128.
    ///
    /// # Examples
    ///
    /// When an [`Event::Ready`] is received, set the game name to `"test"`:
    ///
    /// ```rust,no_run
    /// # use serenity::prelude::*;
    /// # use serenity::model::gateway::Ready;
    /// #
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn ready(&self, ctx: Context, _: Ready) {
    ///         ctx.set_game_name("test");
    ///     }
    /// }
    ///
    /// let mut client = Client::new("token", Handler).unwrap();
    /// client.start().unwrap();
    /// ```
    ///
    /// [`Event::Ready`]: ../model/event/enum.Event.html#variant.Ready
    /// [`GameType`]: ../model/gateway/enum.GameType.html
    /// [`Online`]: ../model/user/enum.OnlineStatus.html#variant.Online
    /// [`OnlineStatus`]: ../model/user/enum.OnlineStatus.html
    /// [`Playing`]: ../model/gateway/enum.GameType.html#variant.Playing
    /// [`reset_presence`]: #method.reset_presence
    /// [`set_presence`]: #method.set_presence
    pub fn set_game_name(&self, game_name: &str) {
        let game = Game {
            kind: GameType::Playing,
            name: game_name.to_string(),
            url: None,
        };

        self.shard.set_presence(Some(game), OnlineStatus::Online);
    }

    /// Sets the current user's presence, providing all fields to be passed.
    ///
    /// # Examples
    ///
    /// Setting the current user as having no game and being [`Idle`]:
    ///
    /// ```rust,no_run
    /// # use serenity::prelude::*;
    /// # use serenity::model::gateway::Ready;
    /// #
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn ready(&self, ctx: Context, _: Ready) {
    ///         use serenity::model::user::OnlineStatus;
    ///
    ///         ctx.set_presence(None, OnlineStatus::Idle);
    ///     }
    /// }
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// ```
    ///
    /// Setting the current user as playing `"Heroes of the Storm"`, while being
    /// [`DoNotDisturb`]:
    ///
    /// ```rust,ignore
    /// # use serenity::prelude::*;
    /// # use serenity::model::gateway::Ready;
    /// #
    /// struct Handler;
    ///
    /// impl EventHandler for Handler {
    ///     fn ready(&self, context: Context, _: Ready) {
    ///         use serenity::model::gateway::Game;
    ///         use serenity::model::user::OnlineStatus;
    ///
    ///         let game = Game::playing("Heroes of the Storm");
    ///         let status = OnlineStatus::DoNotDisturb;
    ///
    ///         context.set_presence(Some(game), status);
    ///     }
    /// }
    ///
    /// let mut client = Client::new("token", Handler).unwrap();
    ///
    /// client.start().unwrap();
    /// ```
    ///
    /// [`DoNotDisturb`]: ../model/user/enum.OnlineStatus.html#variant.DoNotDisturb
    /// [`Idle`]: ../model/user/enum.OnlineStatus.html#variant.Idle
    #[inline]
    pub fn set_presence(&self, game: Option<Game>, status: OnlineStatus) {
        self.shard.set_presence(game, status);
    }

    /// Disconnects the shard from the websocket, essentially "quiting" it.
    /// Note however that this will only exit the one which the `Context` was given.
    /// If it's just one shard that's on, then serenity will stop any further actions
    /// until [`Client::start`] and vice versa are called again.
    ///
    /// [`Client::start`]: ./struct.Client.html#method.start
    #[inline]
    pub fn quit(&self) {
        self.shard.shutdown_clean();
    }
}
<|endoftext|>


<commit_before>use chattium_oxide_lib::json::FromJsonnable;
use chattium_oxide_lib::ChatMessage;
use hyper::server::{Request, Response};
use hyper::header::ContentLength;
use hyper::status::StatusCode;
use hyper::method::Method;
use std::io::{Read, Write};

pub fn handle_client(req: Request, mut res: Response) {
	let mut req = req;
	let mut body = format!("{}, use https://github.com/nabijaczleweli/chattium-oxide-client to connect to chat", req.remote_addr);

	*res.status_mut() = match req.method {
		Method::Post => {
			let mut reqbody = String::new();
			match req.read_to_string(&mut reqbody) {
				Ok(_) =>
					match ChatMessage::from_json_string(&reqbody) {
						Ok(mut message) => {
							message.sender.fill_ip(req.remote_addr);
							println!("{:?}", message);
							StatusCode::Ok
						},
						Err(error) => {
							println!("Couldn't process POSTed message from {}: {}", req.remote_addr, error);
							StatusCode::UnprocessableEntity
						},
					},
				Err(error) => {
					println!("Failed reading request from {}: {}", req.remote_addr, error);
					StatusCode::UnsupportedMediaType  // non-UTF-8
				},
			}
		},
	  _ => StatusCode::ImATeapot,
	};

	res.headers_mut().set(ContentLength(body.len() as u64));
	res.start().unwrap().write_all(body.as_bytes()).unwrap();
}
<commit_msg>Write errors to stderr. Handle response writing errors<commit_after>use chattium_oxide_lib::json::FromJsonnable;
use chattium_oxide_lib::ChatMessage;
use hyper::server::{Request, Response};
use hyper::header::ContentLength;
use hyper::status::StatusCode;
use hyper::method::Method;
use std::io::{Read, Write, stderr};

pub fn handle_client(req: Request, mut res: Response) {
	let mut req = req;
	let mut body = format!("{}, use https://github.com/nabijaczleweli/chattium-oxide-client to connect to chat", req.remote_addr);

	*res.status_mut() = match req.method {
		Method::Post => {
			let mut reqbody = String::new();
			match req.read_to_string(&mut reqbody) {
				Ok(_) =>
					match ChatMessage::from_json_string(&reqbody) {
						Ok(mut message) => {
							message.sender.fill_ip(req.remote_addr);
							println!("{:?}", message);
							StatusCode::Ok
						},
						Err(error) => {
							let _ = stderr().write_fmt(format_args!("Couldn't process POSTed message from {}: {}", req.remote_addr, error));
							StatusCode::UnprocessableEntity
						},
					},
				Err(error) => {
					let _ = stderr().write_fmt(format_args!("Failed reading request from {}: {}", req.remote_addr, error));
					StatusCode::UnsupportedMediaType  // non-UTF-8
				},
			}
		},
	  _ => StatusCode::ImATeapot,
	};

	res.headers_mut().set(ContentLength(body.len() as u64));
	if let Err(error) = res.start().unwrap().write_all(body.as_bytes()) {
		let _ = stderr().write_fmt(format_args!("Failed to respond to {}: {}", req.remote_addr, error));
	}
}
<|endoftext|>


<commit_before>use ast::*;
use collections::treemap::TreeMap;
use std::fmt;
use std::vec::Vec;
#[deriving(Clone)]
#[deriving(Eq)]
/// An error encountered during parsing an expression
pub enum ParseError {
	/// When it expected a certain kind of token, but got another
	Expected(Vec<Token>, Token),
	/// When it expected a certain expression, but got another
	ExpectedExpr(~str, Expr)
}
impl fmt::Show for ParseError {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		return match *self {
			Expected(ref wanted, ref got) if wanted.len() == 0 => write!(f.buf, "Expected expression, got {}", got),
			Expected(ref wanted, ref got) => {
				try!(write!(f.buf, "Expected "));
				let last = wanted.last().unwrap();
				for wanted_token in wanted.iter() {
					match write!(f.buf, "{}{}", wanted_token, if wanted_token == last {""} else {", "}) {
						Err(err) => return Err(err),
						Ok(_) => ()
					}
				}
				write!(f.buf, ", got {}", got)
			},
			ExpectedExpr(ref wanted, ref got) => {
				write!(f.buf, "Expected {}, got {}", wanted, got)
			}
		}
	}
}
/// A result which gives a pretty-printed error if it fails
pub trait VerboseResult<T> {
	/// Unwrap the value if it's Ok and if not pretty-print the error
	fn v_unwrap(&self) -> T;
}
impl<T : Clone, E : fmt::Show> VerboseResult<T> for Result<T, E> {
	fn v_unwrap(&self) -> T {
		match *self {
			Ok(ref val) => val.clone(),
			Err(ref err) => fail!("{}", err)
		}
	}
}
pub type ParseResult = Result<~Expr, ParseError>;
pub type ParseStructResult = Result<Option<~Expr>, ParseError>;
/// A Javascript parser
pub struct Parser {
	/// The tokens being input
	tokens: Vec<Token>,
	/// The current position within the tokens
	pos: uint
}
impl Parser {
	/// Creates a new parser, using [tokens] as input
	pub fn new(tokens: Vec<Token>) -> ~Parser {
		return ~Parser {tokens: tokens, pos: 0};
	}
	/// Parse all expressions in the token array
	pub fn parse_all(&mut self) -> ParseResult {
		let mut exprs = Vec::new();
		while self.pos < self.tokens.len() {
			let result = try!(self.parse());
			exprs.push(result);
		}
		return Ok(~BlockExpr(exprs));
	}
	fn parse_struct(&mut self, name:&str) -> ParseStructResult {
		match name {
			"true" => Ok(Some(~ConstExpr(CBool(true)))),
			"false" => Ok(Some(~ConstExpr(CBool(false)))),
			"null" => Ok(Some(~ConstExpr(CNull))),
			"undefined" => Ok(Some(~ConstExpr(CUndefined))),
			"throw" => {
				let thrown = try!(self.parse());
				Ok(Some(~ThrowExpr(thrown)))
			},
			"return" => Ok(Some(~ReturnExpr(Some(try!(self.parse()))))),
			"new" => {
				let call = try!(self.parse());
				print!("new {}", call);
				match *call {
					CallExpr(ref func, ref args) => Ok(Some(~ConstructExpr(func.clone(), args.clone()))),
					_ => Err(ExpectedExpr(~"constructor", *call))
				}
			}
			"if" => {
				try!(self.expect(TOpenParen));
				let cond = try!(self.parse());
				try!(self.expect(TCloseParen));
				let expr = try!(self.parse());
				let next = self.tokens.get(self.pos + 1).clone();
				Ok(Some(~IfExpr(cond, expr, if next == TIdent(~"else") {
					self.pos += 2;
					Some(try!(self.parse()))
				} else {
					None
				})))
			},
			"while" => {
				try!(self.expect(TOpenParen));
				let cond = try!(self.parse());
				try!(self.expect(TCloseParen));
				let expr = try!(self.parse());
				Ok(Some(~WhileLoopExpr(cond, expr)))
			},
			"switch" => {
				try!(self.expect(TOpenParen));
				let value = self.parse();
				try!(self.expect(TCloseParen));
				try!(self.expect(TOpenBlock));
				let mut cases = Vec::new();
				let mut default = None;
				while self.pos + 1 < self.tokens.len() {
					let tok = self.tokens.get(self.pos).clone();
					self.pos += 1;
					match tok {
						TIdent(ref id) if *id == ~"case" => {
							let cond = self.parse();
							let mut block = Vec::new();
							try!(self.expect(TColon));
							loop {
								match self.tokens.get(self.pos).clone() {
									TIdent(ref id) if *id == ~"case" || *id == ~"default" => break,
									TCloseBlock => break,
									_ => block.push(try!(self.parse()))
								}
							}
							cases.push((cond.unwrap(), block));
						},
						TIdent(ref id) if *id == ~"default" => {
							let mut block = Vec::new();
							try!(self.expect(TColon));
							loop {
								match self.tokens.get(self.pos).clone() {
									TIdent(ref id) if *id == ~"case" || *id == ~"default" => break,
									TCloseBlock => break,
									_ => block.push(try!(self.parse()))
								}
							}
							default = Some(~BlockExpr(block));
						},
						TCloseBlock => break,
						_ => fail!("Expected 'case', 'default' or '{}', not '{}'", '}', tok)
					}
				}
				try!(self.expect(TCloseBlock));
				Ok(Some(~SwitchExpr(value.unwrap(), cases, default)))
			},
			"function" => {
				let tk = self.tokens.get(self.pos).clone();
				let name : Option<~str> = match tk {
					TIdent(ref name) => {
						self.pos += 1;
						Some(name.clone())
					},
					TOpenParen => None,
					_ => return Err(Expected(vec!(TIdent(~"identifier")), tk.clone()))
				};
				try!(self.expect(TOpenParen));
				let mut args:Vec<~str> = Vec::new();
				let mut tk = self.tokens.get(self.pos).clone();
				while tk != TCloseParen {
					match tk {
						TIdent(ref id) => args.push(id.to_owned()),
						_ => return Err(Expected(vec!(TIdent(~"identifier")), tk))
					}
					self.pos += 1;
					if *self.tokens.get(self.pos) == TComma {
						self.pos += 1;
					}
					tk = self.tokens.get(self.pos).clone();
				}
				self.pos += 1;
				let block = try!(self.parse());
				Ok(Some(~FunctionDeclExpr(name, args, block)))
			},
			_ => Ok(None)
		}
	}
	/// Parse a single expression
	pub fn parse(&mut self) -> ParseResult {
		let token = self.tokens.get(self.pos).clone();
		self.pos += 1;
		let expr : ~Expr = match token {
			TSemicolon => try!(self.parse()),
			TIdent(ref s) => {
				let structure = try!(self.parse_struct(s.clone()));
				match structure {
					Some(v) => v,
					None => ~LocalExpr(s.to_owned())
				}
			},
			TString(ref s) => ~ConstExpr(CString(s.to_owned())),
			TOpenParen => {
				let nexte = try!(self.parse());
				try!(self.expect(TCloseParen));
				nexte
			},
			TOpenArray => {
				self.pos += 1;
				let mut array = Vec::new();
				while self.tokens.get(self.pos) == &TComma || array.len() == 0 {
					array.push(match *self.tokens.get(self.pos) {
						TComma => ~ConstExpr(CNull),
						_ => try!(self.parse())
					});
					self.pos += 1;
				}
				self.pos -= 1;
				try!(self.expect(TCloseArray));
				~ArrayDeclExpr(array)
			},
			TOpenBlock if self.tokens.get(self.pos) == &TCloseBlock => {
				self.pos += 1;
				~ObjectDeclExpr(~TreeMap::new())
			},
			TOpenBlock if self.tokens.get(self.pos + 1) == &TColon => {
				let mut map = ~TreeMap::new();
				while self.tokens.get(self.pos - 1) == &TComma || map.len() == 0 {
					let tk = self.tokens.get(self.pos).clone();
					let name = match tk {
						TIdent(ref id) => id,
						TString(ref str) => str,
						_ => return Err(Expected(vec!(TIdent(~"identifier"), TString(~"string")), tk))
					};
					self.pos += 1;
					try!(self.expect(TColon));
					let value = try!(self.parse());
					map.insert(name.to_owned(), value);
					self.pos += 1;
				}
				~ObjectDeclExpr(map)
			},
			TOpenBlock => {
				let mut exprs = Vec::new();
				loop {
					if *self.tokens.get(self.pos) == TCloseBlock {
						break;
					} else {
						exprs.push(try!(self.parse()));
					}
				}
				self.pos += 1;
				~BlockExpr(exprs)
			},
			TNumber(num) => ~ConstExpr(CNum(num)),
			_ => return Err(Expected(Vec::new(), token.clone()))
		};
		return if self.pos >= self.tokens.len() { Ok(expr) } else {self.parse_next(expr)};
	}
	fn parse_next(&mut self, expr:~Expr) -> ParseResult {
		let next = self.tokens.get(self.pos).clone();
		let mut carry_on = true;
		let mut result = expr.clone();
		match next {
			TDot => {
				self.pos += 1;
				let tk = self.tokens.get(self.pos).clone();
				match tk {
					TIdent(ref s) => result = ~GetConstFieldExpr(expr, s.to_owned()),
					_ => return Err(Expected(vec!(TIdent(~"identifier")), next))
				}
				self.pos += 1;
			},
			TOpenParen => {
				let mut args = Vec::new();
				let mut expect_comma_or_end = false;
				loop {
					let token = self.tokens.get(self.pos).clone();
					self.pos += 1;
					match token {
						TCloseParen if expect_comma_or_end => break,
						TComma if expect_comma_or_end => expect_comma_or_end = false,
						_ if expect_comma_or_end =>
							return Err(Expected(vec!(TComma, TCloseParen), token)),
						_ if !expect_comma_or_end => {
							args.push(try!(self.parse()));
							expect_comma_or_end = true;
						},
						_ => ()
					}
				}
				result = ~CallExpr(expr, args);
			},
			TQuestion => {
				self.pos += 1;
				let if_e = try!(self.parse());
				try!(self.expect(TColon));
				let else_e = try!(self.parse());
				result = ~IfExpr(expr, if_e, Some(else_e));
			},
			TOpenArray => {
				self.pos += 1;
				let index = try!(self.parse());
				try!(self.expect(TCloseArray));
				result = ~GetFieldExpr(expr, index);
			},
			TSemicolon => {
				self.pos += 1;
			},
			TNumOp(op) => {
				self.pos += 1;
				let next = try!(self.parse());
				result = ~NumOpExpr(op, expr, next);
			},
			_ => carry_on = false
		};
		return if carry_on && self.pos < self.tokens.len() { self.parse_next(result) } else {Ok(result)};
	}
	/// Returns an error if the next symbol is not [tk]
	fn expect(&mut self, tk:Token) -> Result<(), ParseError> {
		self.pos += 1;
		let curr_tk = self.tokens.get(self.pos - 1).clone();
		return if curr_tk != tk {
			Err(Expected(vec!(tk), curr_tk))
		} else {
			Ok(())
		};
	}
}<commit_msg>Rewrite function call parser<commit_after>use ast::*;
use collections::treemap::TreeMap;
use std::fmt;
use std::vec::Vec;
#[deriving(Clone)]
#[deriving(Eq)]
/// An error encountered during parsing an expression
pub enum ParseError {
	/// When it expected a certain kind of token, but got another
	Expected(Vec<Token>, Token),
	/// When it expected a certain expression, but got another
	ExpectedExpr(~str, Expr)
}
impl fmt::Show for ParseError {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		return match *self {
			Expected(ref wanted, ref got) if wanted.len() == 0 => write!(f.buf, "Expected expression, got {}", got),
			Expected(ref wanted, ref got) => {
				try!(write!(f.buf, "Expected "));
				let last = wanted.last().unwrap();
				for wanted_token in wanted.iter() {
					match write!(f.buf, "'{}'{}", wanted_token, if wanted_token == last {""} else {", "}) {
						Err(err) => return Err(err),
						Ok(_) => ()
					}
				}
				write!(f.buf, ", got {}", got)
			},
			ExpectedExpr(ref wanted, ref got) => {
				write!(f.buf, "Expected {}, got {}", wanted, got)
			}
		}
	}
}
/// A result which gives a pretty-printed error if it fails
pub trait VerboseResult<T> {
	/// Unwrap the value if it's Ok and if not pretty-print the error
	fn v_unwrap(&self) -> T;
}
impl<T : Clone, E : fmt::Show> VerboseResult<T> for Result<T, E> {
	fn v_unwrap(&self) -> T {
		match *self {
			Ok(ref val) => val.clone(),
			Err(ref err) => fail!("{}", err)
		}
	}
}
pub type ParseResult = Result<~Expr, ParseError>;
pub type ParseStructResult = Result<Option<~Expr>, ParseError>;
/// A Javascript parser
pub struct Parser {
	/// The tokens being input
	tokens: Vec<Token>,
	/// The current position within the tokens
	pos: uint
}
impl Parser {
	/// Creates a new parser, using [tokens] as input
	pub fn new(tokens: Vec<Token>) -> ~Parser {
		return ~Parser {tokens: tokens, pos: 0};
	}
	/// Parse all expressions in the token array
	pub fn parse_all(&mut self) -> ParseResult {
		let mut exprs = Vec::new();
		while self.pos < self.tokens.len() {
			let result = try!(self.parse());
			exprs.push(result);
		}
		return Ok(~BlockExpr(exprs));
	}
	fn parse_struct(&mut self, name:&str) -> ParseStructResult {
		match name {
			"true" => Ok(Some(~ConstExpr(CBool(true)))),
			"false" => Ok(Some(~ConstExpr(CBool(false)))),
			"null" => Ok(Some(~ConstExpr(CNull))),
			"undefined" => Ok(Some(~ConstExpr(CUndefined))),
			"throw" => {
				let thrown = try!(self.parse());
				Ok(Some(~ThrowExpr(thrown)))
			},
			"return" => Ok(Some(~ReturnExpr(Some(try!(self.parse()))))),
			"new" => {
				let call = try!(self.parse());
				print!("new {}", call);
				match *call {
					CallExpr(ref func, ref args) => Ok(Some(~ConstructExpr(func.clone(), args.clone()))),
					_ => Err(ExpectedExpr(~"constructor", *call))
				}
			}
			"if" => {
				try!(self.expect(TOpenParen));
				let cond = try!(self.parse());
				try!(self.expect(TCloseParen));
				let expr = try!(self.parse());
				let next = self.tokens.get(self.pos + 1).clone();
				Ok(Some(~IfExpr(cond, expr, if next == TIdent(~"else") {
					self.pos += 2;
					Some(try!(self.parse()))
				} else {
					None
				})))
			},
			"while" => {
				try!(self.expect(TOpenParen));
				let cond = try!(self.parse());
				try!(self.expect(TCloseParen));
				let expr = try!(self.parse());
				Ok(Some(~WhileLoopExpr(cond, expr)))
			},
			"switch" => {
				try!(self.expect(TOpenParen));
				let value = self.parse();
				try!(self.expect(TCloseParen));
				try!(self.expect(TOpenBlock));
				let mut cases = Vec::new();
				let mut default = None;
				while self.pos + 1 < self.tokens.len() {
					let tok = self.tokens.get(self.pos).clone();
					self.pos += 1;
					match tok {
						TIdent(ref id) if *id == ~"case" => {
							let cond = self.parse();
							let mut block = Vec::new();
							try!(self.expect(TColon));
							loop {
								match self.tokens.get(self.pos).clone() {
									TIdent(ref id) if *id == ~"case" || *id == ~"default" => break,
									TCloseBlock => break,
									_ => block.push(try!(self.parse()))
								}
							}
							cases.push((cond.unwrap(), block));
						},
						TIdent(ref id) if *id == ~"default" => {
							let mut block = Vec::new();
							try!(self.expect(TColon));
							loop {
								match self.tokens.get(self.pos).clone() {
									TIdent(ref id) if *id == ~"case" || *id == ~"default" => break,
									TCloseBlock => break,
									_ => block.push(try!(self.parse()))
								}
							}
							default = Some(~BlockExpr(block));
						},
						TCloseBlock => break,
						_ => fail!("Expected 'case', 'default' or '{}', not '{}'", '}', tok)
					}
				}
				try!(self.expect(TCloseBlock));
				Ok(Some(~SwitchExpr(value.unwrap(), cases, default)))
			},
			"function" => {
				let tk = self.tokens.get(self.pos).clone();
				let name : Option<~str> = match tk {
					TIdent(ref name) => {
						self.pos += 1;
						Some(name.clone())
					},
					TOpenParen => None,
					_ => return Err(Expected(vec!(TIdent(~"identifier")), tk.clone()))
				};
				try!(self.expect(TOpenParen));
				let mut args:Vec<~str> = Vec::new();
				let mut tk = self.tokens.get(self.pos).clone();
				while tk != TCloseParen {
					match tk {
						TIdent(ref id) => args.push(id.to_owned()),
						_ => return Err(Expected(vec!(TIdent(~"identifier")), tk))
					}
					self.pos += 1;
					if *self.tokens.get(self.pos) == TComma {
						self.pos += 1;
					}
					tk = self.tokens.get(self.pos).clone();
				}
				self.pos += 1;
				let block = try!(self.parse());
				Ok(Some(~FunctionDeclExpr(name, args, block)))
			},
			_ => Ok(None)
		}
	}
	/// Parse a single expression
	pub fn parse(&mut self) -> ParseResult {
		let token = self.tokens.get(self.pos).clone();
		self.pos += 1;
		let expr : ~Expr = match token {
			TSemicolon => try!(self.parse()),
			TIdent(ref s) => {
				let structure = try!(self.parse_struct(s.clone()));
				match structure {
					Some(v) => v,
					None => ~LocalExpr(s.to_owned())
				}
			},
			TString(ref s) => ~ConstExpr(CString(s.to_owned())),
			TOpenParen => {
				let nexte = try!(self.parse());
				try!(self.expect(TCloseParen));
				nexte
			},
			TOpenArray => {
				self.pos += 1;
				let mut array = Vec::new();
				while self.tokens.get(self.pos) == &TComma || array.len() == 0 {
					array.push(match *self.tokens.get(self.pos) {
						TComma => ~ConstExpr(CNull),
						_ => try!(self.parse())
					});
					self.pos += 1;
				}
				self.pos -= 1;
				try!(self.expect(TCloseArray));
				~ArrayDeclExpr(array)
			},
			TOpenBlock if self.tokens.get(self.pos) == &TCloseBlock => {
				self.pos += 1;
				~ObjectDeclExpr(~TreeMap::new())
			},
			TOpenBlock if self.tokens.get(self.pos + 1) == &TColon => {
				let mut map = ~TreeMap::new();
				while self.tokens.get(self.pos - 1) == &TComma || map.len() == 0 {
					let tk = self.tokens.get(self.pos).clone();
					let name = match tk {
						TIdent(ref id) => id,
						TString(ref str) => str,
						_ => return Err(Expected(vec!(TIdent(~"identifier"), TString(~"string")), tk))
					};
					self.pos += 1;
					try!(self.expect(TColon));
					let value = try!(self.parse());
					map.insert(name.to_owned(), value);
					self.pos += 1;
				}
				~ObjectDeclExpr(map)
			},
			TOpenBlock => {
				let mut exprs = Vec::new();
				loop {
					if *self.tokens.get(self.pos) == TCloseBlock {
						break;
					} else {
						exprs.push(try!(self.parse()));
					}
				}
				self.pos += 1;
				~BlockExpr(exprs)
			},
			TNumber(num) => ~ConstExpr(CNum(num)),
			_ => return Err(Expected(Vec::new(), token.clone()))
		};
		return if self.pos >= self.tokens.len() { Ok(expr) } else {self.parse_next(expr)};
	}
	fn parse_next(&mut self, expr:~Expr) -> ParseResult {
		let next = self.tokens.get(self.pos).clone();
		let mut carry_on = true;
		let mut result = expr.clone();
		match next {
			TDot => {
				self.pos += 1;
				let tk = self.tokens.get(self.pos).clone();
				match tk {
					TIdent(ref s) => result = ~GetConstFieldExpr(expr, s.to_owned()),
					_ => return Err(Expected(vec!(TIdent(~"identifier")), next))
				}
				self.pos += 1;
			},
			TOpenParen => {
				let mut args = Vec::new();
				let mut expect_comma_or_end = false;
				loop {
					self.pos += 1;
					let token = self.tokens.get(self.pos).clone();
					if token == TCloseParen && expect_comma_or_end {
						self.pos += 1;
						break;
					} else if token == TComma && expect_comma_or_end {
						expect_comma_or_end = false;
					} else if expect_comma_or_end {
						return Err(Expected(vec!(TComma, TCloseParen), token));
					} else {
						let parsed = try!(self.parse());
						self.pos -= 1;
						args.push(parsed);
						expect_comma_or_end = true;
					}
				}
				result = ~CallExpr(expr, args);
			},
			TQuestion => {
				self.pos += 1;
				let if_e = try!(self.parse());
				try!(self.expect(TColon));
				let else_e = try!(self.parse());
				result = ~IfExpr(expr, if_e, Some(else_e));
			},
			TOpenArray => {
				self.pos += 1;
				let index = try!(self.parse());
				try!(self.expect(TCloseArray));
				result = ~GetFieldExpr(expr, index);
			},
			TSemicolon => {
				self.pos += 1;
			},
			TNumOp(op) => {
				self.pos += 1;
				let next = try!(self.parse());
				result = ~NumOpExpr(op, expr, next);
			},
			_ => carry_on = false
		};
		return if carry_on && self.pos < self.tokens.len() { self.parse_next(result) } else {Ok(result)};
	}
	/// Returns an error if the next symbol is not [tk]
	fn expect(&mut self, tk:Token) -> Result<(), ParseError> {
		self.pos += 1;
		let curr_tk = self.tokens.get(self.pos - 1).clone();
		return if curr_tk != tk {
			Err(Expected(vec!(tk), curr_tk))
		} else {
			Ok(())
		};
	}
}<|endoftext|>