<commit_before>
// Copyright 2017 The gltf Library Developers
//
// 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 v2::json::{camera, mesh, scene, skin, Extras, Index};

/// A node in the node hierarchy.  When the node contains `skin`, all `mesh.primitives` must contain `JOINTS_0` and `WEIGHTS_0` attributes.  A node can have either a `matrix` or any combination of `translation`/`rotation`/`scale` (TRS) properties. TRS properties are converted to matrices and postmultiplied in the `T * R * S` order to compose the transformation matrix; first the scale is applied to the vertices, then the rotation, and then the translation. If none are provided, the transform is the identity. When a node is targeted for animation (referenced by an animation.channel.target), only TRS properties may be present; `matrix` will not be present..
#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
#[serde(deny_unknown_fields)]
pub struct Node {
    /// The index of the camera referenced by this node.
    pub camera: Option<Index<camera::Camera>>,

    /// The indices of this node's children.
    pub children: Option<Vec<Index<scene::Node>>>,

    /// Extension specific data.
    #[serde(default)]
    pub extensions: NodeExtensions,

    /// Optional application specific data.
    #[serde(default)]
    pub extras: Extras,

    /// 4x4 column-major transformation matrix.
    #[serde(default = "node_matrix_default")]
    pub matrix: [f32; 16],

    /// The index of the mesh in this node.
    pub mesh: Option<Index<mesh::Mesh>>,

    /// Optional user-defined name for this object.
    pub name: Option<String>,

    /// The node's unit quaternion rotation in the order (x, y, z, w), where w is the scalar.
    #[serde(default = "node_rotation_default")]
    pub rotation: [f32; 4],

    /// The node's non-uniform scale.
    #[serde(default = "node_scale_default")]
    pub scale: [f32; 3],

    /// The node's translation.
    #[serde(default)]
    pub translation: [f32; 3],

    /// The index of the skin referenced by this node.
    pub skin: Option<Index<skin::Skin>>,

    /// The weights of the instantiated Morph Target. Number of elements must match number of Morph Targets of used mesh.
    pub weights: Option<Vec<f32>>,
}

/// Extension specific data for `Node`.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct NodeExtensions {
    #[serde(default)]
    _allow_unknown_fields: (),
}

fn node_matrix_default() -> [f32; 16] {
    [1.0, 0.0, 0.0, 0.0,
     0.0, 1.0, 0.0, 0.0,
     0.0, 0.0, 1.0, 0.0,
     0.0, 0.0, 0.0, 1.0]
}

fn node_rotation_default() -> [f32; 4] {
    [0.0, 0.0, 0.0, 1.0]
}

fn node_scale_default() -> [f32; 3] {
    [1.0, 1.0, 1.0]
}

/// The root `Node`s of a scene.
#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
#[serde(deny_unknown_fields)]
pub struct Scene {
    /// Extension specific data.
    #[serde(default)]
    pub extensions: SceneExtensions,

    /// Optional application specific data.
    #[serde(default)]
    pub extras: Extras,

    /// Optional user-defined name for this object.
    pub name: Option<String>,

    /// The indices of each root node.
    pub nodes: Vec<Index<Node>>,
}

/// Extension specific data for `Scene`.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct SceneExtensions {
    #[serde(default)]
    _allow_unknown_fields: (),
}
<commit_msg>Added validation for Node<commit_after>
// Copyright 2017 The gltf Library Developers
//
// 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 v2::json::{camera, mesh, scene, skin, Extras, Index, Root};
use v2::validation::{Error, JsonPath, Validate};

/// A node in the node hierarchy.  When the node contains `skin`, all `mesh.primitives` must contain `JOINTS_0` and `WEIGHTS_0` attributes.  A node can have either a `matrix` or any combination of `translation`/`rotation`/`scale` (TRS) properties. TRS properties are converted to matrices and postmultiplied in the `T * R * S` order to compose the transformation matrix; first the scale is applied to the vertices, then the rotation, and then the translation. If none are provided, the transform is the identity. When a node is targeted for animation (referenced by an animation.channel.target), only TRS properties may be present; `matrix` will not be present..
#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
#[serde(deny_unknown_fields)]
pub struct Node {
    /// The index of the camera referenced by this node.
    pub camera: Option<Index<camera::Camera>>,

    /// The indices of this node's children.
    pub children: Option<Vec<Index<scene::Node>>>,

    /// Extension specific data.
    #[serde(default)]
    pub extensions: NodeExtensions,

    /// Optional application specific data.
    #[serde(default)]
    pub extras: Extras,

    /// 4x4 column-major transformation matrix.
    #[serde(default = "node_matrix_default")]
    pub matrix: [f32; 16],

    /// The index of the mesh in this node.
    pub mesh: Option<Index<mesh::Mesh>>,

    /// Optional user-defined name for this object.
    pub name: Option<String>,

    /// The node's unit quaternion rotation in the order (x, y, z, w), where w is the scalar.
    #[serde(default)]
    pub rotation: UnitQuaternion,

    /// The node's non-uniform scale.
    #[serde(default = "node_scale_default")]
    pub scale: [f32; 3],

    /// The node's translation.
    #[serde(default)]
    pub translation: [f32; 3],

    /// The index of the skin referenced by this node.
    pub skin: Option<Index<skin::Skin>>,

    /// The weights of the instantiated Morph Target. Number of elements must match number of Morph Targets of used mesh.
    pub weights: Option<Vec<f32>>,
}

/// Extension specific data for `Node`.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct NodeExtensions {
    #[serde(default)]
    _allow_unknown_fields: (),
}

fn node_matrix_default() -> [f32; 16] {
    [1.0, 0.0, 0.0, 0.0,
     0.0, 1.0, 0.0, 0.0,
     0.0, 0.0, 1.0, 0.0,
     0.0, 0.0, 0.0, 1.0]
}

fn node_scale_default() -> [f32; 3] {
    [1.0, 1.0, 1.0]
}

/// The root `Node`s of a scene.
#[derive(Clone, Debug, Deserialize, Serialize, Validate)]
#[serde(deny_unknown_fields)]
pub struct Scene {
    /// Extension specific data.
    #[serde(default)]
    pub extensions: SceneExtensions,

    /// Optional application specific data.
    #[serde(default)]
    pub extras: Extras,

    /// Optional user-defined name for this object.
    pub name: Option<String>,

    /// The indices of each root node.
    pub nodes: Vec<Index<Node>>,
}

/// Extension specific data for `Scene`.
#[derive(Clone, Debug, Default, Deserialize, Serialize, Validate)]
pub struct SceneExtensions {
    #[serde(default)]
    _allow_unknown_fields: (),
}

/// Unit quaternion rotation in the order (x, y, z, w), where w is the scalar.
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
pub struct UnitQuaternion(pub [f32; 4]);

impl Default for UnitQuaternion {
    fn default() -> Self {
        UnitQuaternion([0.0, 0.0, 0.0, 1.0])
    }
}

impl Validate for UnitQuaternion {
    fn validate<F>(&self, _: &Root, path: JsonPath, report: &mut F)
        where F: FnMut(Error)
    {
        for x in &self.0 {
            if *x < -1.0 || *x > 1.0 {
                report(Error::invalid_value(path, self.0.to_vec()));
                // Only report once
                break;
            }
        }
    }
}
<|endoftext|>


<commit_before>//! Implementation of compiling the compiler and standard library, in "check"-based modes.

use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
use crate::cache::Interned;
use crate::compile::{add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo};
use crate::config::TargetSelection;
use crate::tool::{prepare_tool_cargo, SourceType};
use crate::INTERNER;
use crate::{Compiler, Mode, Subcommand};
use std::path::PathBuf;

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Std {
    pub target: TargetSelection,
}

/// Returns args for the subcommand itself (not for cargo)
fn args(builder: &Builder<'_>) -> Vec<String> {
    fn strings<'a>(arr: &'a [&str]) -> impl Iterator<Item = String> + 'a {
        arr.iter().copied().map(String::from)
    }

    if let Subcommand::Clippy { fix, .. } = builder.config.cmd {
        let mut args = vec![];
        if fix {
            #[rustfmt::skip]
            args.extend(strings(&[
                "--fix", "-Zunstable-options",
                // FIXME: currently, `--fix` gives an error while checking tests for libtest,
                // possibly because libtest is not yet built in the sysroot.
                // As a workaround, avoid checking tests and benches when passed --fix.
                "--lib", "--bins", "--examples",
            ]));
        }
        args.extend(strings(&["--", "--cap-lints", "warn"]));
        args
    } else {
        vec![]
    }
}

fn cargo_subcommand(kind: Kind) -> &'static str {
    match kind {
        Kind::Check => "check",
        Kind::Clippy => "clippy",
        Kind::Fix => "fix",
        _ => unreachable!(),
    }
}

impl Step for Std {
    type Output = ();
    const DEFAULT: bool = true;

    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
        run.all_krates("test")
    }

    fn make_run(run: RunConfig<'_>) {
        run.builder.ensure(Std { target: run.target });
    }

    fn run(self, builder: &Builder<'_>) {
        let target = self.target;
        let compiler = builder.compiler(0, builder.config.build);

        let mut cargo = builder.cargo(
            compiler,
            Mode::Std,
            SourceType::InTree,
            target,
            cargo_subcommand(builder.kind),
        );
        std_cargo(builder, target, compiler.stage, &mut cargo);

        builder.info(&format!("Checking std artifacts ({} -> {})", &compiler.host, target));
        run_cargo(
            builder,
            cargo,
            args(builder),
            &libstd_stamp(builder, compiler, target),
            vec![],
            true,
        );

        let libdir = builder.sysroot_libdir(compiler, target);
        let hostdir = builder.sysroot_libdir(compiler, compiler.host);
        add_to_sysroot(&builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target));

        // Then run cargo again, once we've put the rmeta files for the library
        // crates into the sysroot. This is needed because e.g., core's tests
        // depend on `libtest` -- Cargo presumes it will exist, but it doesn't
        // since we initialize with an empty sysroot.
        //
        // Currently only the "libtest" tree of crates does this.

        if let Subcommand::Check { all_targets: true, .. } = builder.config.cmd {
            let mut cargo = builder.cargo(
                compiler,
                Mode::Std,
                SourceType::InTree,
                target,
                cargo_subcommand(builder.kind),
            );
            std_cargo(builder, target, compiler.stage, &mut cargo);
            cargo.arg("--all-targets");

            // Explicitly pass -p for all dependencies krates -- this will force cargo
            // to also check the tests/benches/examples for these crates, rather
            // than just the leaf crate.
            for krate in builder.in_tree_crates("test", Some(target)) {
                cargo.arg("-p").arg(krate.name);
            }

            builder.info(&format!(
                "Checking std test/bench/example targets ({} -> {})",
                &compiler.host, target
            ));
            run_cargo(
                builder,
                cargo,
                args(builder),
                &libstd_test_stamp(builder, compiler, target),
                vec![],
                true,
            );
        }
    }
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Rustc {
    pub target: TargetSelection,
}

impl Step for Rustc {
    type Output = ();
    const ONLY_HOSTS: bool = true;
    const DEFAULT: bool = true;

    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
        run.all_krates("rustc-main")
    }

    fn make_run(run: RunConfig<'_>) {
        run.builder.ensure(Rustc { target: run.target });
    }

    /// Builds the compiler.
    ///
    /// This will build the compiler for a particular stage of the build using
    /// the `compiler` targeting the `target` architecture. The artifacts
    /// created will also be linked into the sysroot directory.
    fn run(self, builder: &Builder<'_>) {
        let compiler = builder.compiler(0, builder.config.build);
        let target = self.target;

        builder.ensure(Std { target });

        let mut cargo = builder.cargo(
            compiler,
            Mode::Rustc,
            SourceType::InTree,
            target,
            cargo_subcommand(builder.kind),
        );
        rustc_cargo(builder, &mut cargo, target);
        if let Subcommand::Check { all_targets: true, .. } = builder.config.cmd {
            cargo.arg("--all-targets");
        }

        // Explicitly pass -p for all compiler krates -- this will force cargo
        // to also check the tests/benches/examples for these crates, rather
        // than just the leaf crate.
        for krate in builder.in_tree_crates("rustc-main", Some(target)) {
            cargo.arg("-p").arg(krate.name);
        }

        builder.info(&format!("Checking compiler artifacts ({} -> {})", &compiler.host, target));
        run_cargo(
            builder,
            cargo,
            args(builder),
            &librustc_stamp(builder, compiler, target),
            vec![],
            true,
        );

        let libdir = builder.sysroot_libdir(compiler, target);
        let hostdir = builder.sysroot_libdir(compiler, compiler.host);
        add_to_sysroot(&builder, &libdir, &hostdir, &librustc_stamp(builder, compiler, target));
    }
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct CodegenBackend {
    pub target: TargetSelection,
    pub backend: Interned<String>,
}

impl Step for CodegenBackend {
    type Output = ();
    const ONLY_HOSTS: bool = true;
    const DEFAULT: bool = true;

    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
        run.paths(&["compiler/rustc_codegen_cranelift", "rustc_codegen_cranelift"])
    }

    fn make_run(run: RunConfig<'_>) {
        for &backend in &[INTERNER.intern_str("cranelift")] {
            run.builder.ensure(CodegenBackend { target: run.target, backend });
        }
    }

    fn run(self, builder: &Builder<'_>) {
        let compiler = builder.compiler(0, builder.config.build);
        let target = self.target;
        let backend = self.backend;

        builder.ensure(Rustc { target });

        let mut cargo = builder.cargo(
            compiler,
            Mode::Codegen,
            SourceType::Submodule,
            target,
            cargo_subcommand(builder.kind),
        );
        cargo
            .arg("--manifest-path")
            .arg(builder.src.join(format!("compiler/rustc_codegen_{}/Cargo.toml", backend)));
        rustc_cargo_env(builder, &mut cargo, target);

        builder.info(&format!(
            "Checking {} artifacts ({} -> {})",
            backend, &compiler.host.triple, target.triple
        ));

        run_cargo(
            builder,
            cargo,
            args(builder),
            &codegen_backend_stamp(builder, compiler, target, backend),
            vec![],
            true,
        );
    }
}

macro_rules! tool_check_step {
    ($name:ident, $path:expr, $source_type:expr) => {
        #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
        pub struct $name {
            pub target: TargetSelection,
        }

        impl Step for $name {
            type Output = ();
            const ONLY_HOSTS: bool = true;
            const DEFAULT: bool = true;

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

            fn make_run(run: RunConfig<'_>) {
                run.builder.ensure($name { target: run.target });
            }

            fn run(self, builder: &Builder<'_>) {
                let compiler = builder.compiler(0, builder.config.build);
                let target = self.target;

                builder.ensure(Rustc { target });

                let mut cargo = prepare_tool_cargo(
                    builder,
                    compiler,
                    Mode::ToolRustc,
                    target,
                    cargo_subcommand(builder.kind),
                    $path,
                    $source_type,
                    &[],
                );

                if let Subcommand::Check { all_targets: true, .. } = builder.config.cmd {
                    cargo.arg("--all-targets");
                }

                builder.info(&format!(
                    "Checking {} artifacts ({} -> {})",
                    stringify!($name).to_lowercase(),
                    &compiler.host.triple,
                    target.triple
                ));
                run_cargo(
                    builder,
                    cargo,
                    args(builder),
                    &stamp(builder, compiler, target),
                    vec![],
                    true,
                );

                let libdir = builder.sysroot_libdir(compiler, target);
                let hostdir = builder.sysroot_libdir(compiler, compiler.host);
                add_to_sysroot(&builder, &libdir, &hostdir, &stamp(builder, compiler, target));

                /// Cargo's output path in a given stage, compiled by a particular
                /// compiler for the specified target.
                fn stamp(
                    builder: &Builder<'_>,
                    compiler: Compiler,
                    target: TargetSelection,
                ) -> PathBuf {
                    builder
                        .cargo_out(compiler, Mode::ToolRustc, target)
                        .join(format!(".{}-check.stamp", stringify!($name).to_lowercase()))
                }
            }
        }
    };
}

tool_check_step!(Rustdoc, "src/tools/rustdoc", SourceType::InTree);
// Clippy is a hybrid. It is an external tool, but uses a git subtree instead
// of a submodule. Since the SourceType only drives the deny-warnings
// behavior, treat it as in-tree so that any new warnings in clippy will be
// rejected.
tool_check_step!(Clippy, "src/tools/clippy", SourceType::InTree);

tool_check_step!(Bootstrap, "src/bootstrap", SourceType::InTree);

/// Cargo's output path for the standard library in a given stage, compiled
/// by a particular compiler for the specified target.
fn libstd_stamp(builder: &Builder<'_>, compiler: Compiler, target: TargetSelection) -> PathBuf {
    builder.cargo_out(compiler, Mode::Std, target).join(".libstd-check.stamp")
}

/// Cargo's output path for the standard library in a given stage, compiled
/// by a particular compiler for the specified target.
fn libstd_test_stamp(
    builder: &Builder<'_>,
    compiler: Compiler,
    target: TargetSelection,
) -> PathBuf {
    builder.cargo_out(compiler, Mode::Std, target).join(".libstd-check-test.stamp")
}

/// Cargo's output path for librustc in a given stage, compiled by a particular
/// compiler for the specified target.
fn librustc_stamp(builder: &Builder<'_>, compiler: Compiler, target: TargetSelection) -> PathBuf {
    builder.cargo_out(compiler, Mode::Rustc, target).join(".librustc-check.stamp")
}

/// Cargo's output path for librustc_codegen_llvm in a given stage, compiled by a particular
/// compiler for the specified target and backend.
fn codegen_backend_stamp(
    builder: &Builder<'_>,
    compiler: Compiler,
    target: TargetSelection,
    backend: Interned<String>,
) -> PathBuf {
    builder
        .cargo_out(compiler, Mode::Codegen, target)
        .join(format!(".librustc_codegen_{}-check.stamp", backend))
}
<commit_msg>./x.py clippy: allow the most noisy lints<commit_after>//! Implementation of compiling the compiler and standard library, in "check"-based modes.

use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step};
use crate::cache::Interned;
use crate::compile::{add_to_sysroot, run_cargo, rustc_cargo, rustc_cargo_env, std_cargo};
use crate::config::TargetSelection;
use crate::tool::{prepare_tool_cargo, SourceType};
use crate::INTERNER;
use crate::{Compiler, Mode, Subcommand};
use std::path::PathBuf;

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Std {
    pub target: TargetSelection,
}

/// Returns args for the subcommand itself (not for cargo)
fn args(builder: &Builder<'_>) -> Vec<String> {
    fn strings<'a>(arr: &'a [&str]) -> impl Iterator<Item = String> + 'a {
        arr.iter().copied().map(String::from)
    }

    if let Subcommand::Clippy { fix, .. } = builder.config.cmd {
        // disable the most spammy clippy lints
        let ignored_lints = vec![
            "many_single_char_names", // there are a lot in stdarch
            "collapsible_if",
            "type_complexity",
            "missing_safety_doc", // almost 3K warnings
            "too_many_arguments",
            "needless_lifetimes", // people want to keep the lifetimes
            "wrong_self_convention",
        ];
        let mut args = vec![];
        if fix {
            #[rustfmt::skip]
            args.extend(strings(&[
                "--fix", "-Zunstable-options",
                // FIXME: currently, `--fix` gives an error while checking tests for libtest,
                // possibly because libtest is not yet built in the sysroot.
                // As a workaround, avoid checking tests and benches when passed --fix.
                "--lib", "--bins", "--examples",
            ]));
        }
        args.extend(strings(&["--", "--cap-lints", "warn"]));
        args.extend(ignored_lints.iter().map(|lint| format!("-Aclippy::{}", lint)));
        args
    } else {
        vec![]
    }
}

fn cargo_subcommand(kind: Kind) -> &'static str {
    match kind {
        Kind::Check => "check",
        Kind::Clippy => "clippy",
        Kind::Fix => "fix",
        _ => unreachable!(),
    }
}

impl Step for Std {
    type Output = ();
    const DEFAULT: bool = true;

    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
        run.all_krates("test")
    }

    fn make_run(run: RunConfig<'_>) {
        run.builder.ensure(Std { target: run.target });
    }

    fn run(self, builder: &Builder<'_>) {
        let target = self.target;
        let compiler = builder.compiler(0, builder.config.build);

        let mut cargo = builder.cargo(
            compiler,
            Mode::Std,
            SourceType::InTree,
            target,
            cargo_subcommand(builder.kind),
        );
        std_cargo(builder, target, compiler.stage, &mut cargo);

        builder.info(&format!("Checking std artifacts ({} -> {})", &compiler.host, target));
        run_cargo(
            builder,
            cargo,
            args(builder),
            &libstd_stamp(builder, compiler, target),
            vec![],
            true,
        );

        let libdir = builder.sysroot_libdir(compiler, target);
        let hostdir = builder.sysroot_libdir(compiler, compiler.host);
        add_to_sysroot(&builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target));

        // Then run cargo again, once we've put the rmeta files for the library
        // crates into the sysroot. This is needed because e.g., core's tests
        // depend on `libtest` -- Cargo presumes it will exist, but it doesn't
        // since we initialize with an empty sysroot.
        //
        // Currently only the "libtest" tree of crates does this.

        if let Subcommand::Check { all_targets: true, .. } = builder.config.cmd {
            let mut cargo = builder.cargo(
                compiler,
                Mode::Std,
                SourceType::InTree,
                target,
                cargo_subcommand(builder.kind),
            );
            std_cargo(builder, target, compiler.stage, &mut cargo);
            cargo.arg("--all-targets");

            // Explicitly pass -p for all dependencies krates -- this will force cargo
            // to also check the tests/benches/examples for these crates, rather
            // than just the leaf crate.
            for krate in builder.in_tree_crates("test", Some(target)) {
                cargo.arg("-p").arg(krate.name);
            }

            builder.info(&format!(
                "Checking std test/bench/example targets ({} -> {})",
                &compiler.host, target
            ));
            run_cargo(
                builder,
                cargo,
                args(builder),
                &libstd_test_stamp(builder, compiler, target),
                vec![],
                true,
            );
        }
    }
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct Rustc {
    pub target: TargetSelection,
}

impl Step for Rustc {
    type Output = ();
    const ONLY_HOSTS: bool = true;
    const DEFAULT: bool = true;

    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
        run.all_krates("rustc-main")
    }

    fn make_run(run: RunConfig<'_>) {
        run.builder.ensure(Rustc { target: run.target });
    }

    /// Builds the compiler.
    ///
    /// This will build the compiler for a particular stage of the build using
    /// the `compiler` targeting the `target` architecture. The artifacts
    /// created will also be linked into the sysroot directory.
    fn run(self, builder: &Builder<'_>) {
        let compiler = builder.compiler(0, builder.config.build);
        let target = self.target;

        builder.ensure(Std { target });

        let mut cargo = builder.cargo(
            compiler,
            Mode::Rustc,
            SourceType::InTree,
            target,
            cargo_subcommand(builder.kind),
        );
        rustc_cargo(builder, &mut cargo, target);
        if let Subcommand::Check { all_targets: true, .. } = builder.config.cmd {
            cargo.arg("--all-targets");
        }

        // Explicitly pass -p for all compiler krates -- this will force cargo
        // to also check the tests/benches/examples for these crates, rather
        // than just the leaf crate.
        for krate in builder.in_tree_crates("rustc-main", Some(target)) {
            cargo.arg("-p").arg(krate.name);
        }

        builder.info(&format!("Checking compiler artifacts ({} -> {})", &compiler.host, target));
        run_cargo(
            builder,
            cargo,
            args(builder),
            &librustc_stamp(builder, compiler, target),
            vec![],
            true,
        );

        let libdir = builder.sysroot_libdir(compiler, target);
        let hostdir = builder.sysroot_libdir(compiler, compiler.host);
        add_to_sysroot(&builder, &libdir, &hostdir, &librustc_stamp(builder, compiler, target));
    }
}

#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct CodegenBackend {
    pub target: TargetSelection,
    pub backend: Interned<String>,
}

impl Step for CodegenBackend {
    type Output = ();
    const ONLY_HOSTS: bool = true;
    const DEFAULT: bool = true;

    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
        run.paths(&["compiler/rustc_codegen_cranelift", "rustc_codegen_cranelift"])
    }

    fn make_run(run: RunConfig<'_>) {
        for &backend in &[INTERNER.intern_str("cranelift")] {
            run.builder.ensure(CodegenBackend { target: run.target, backend });
        }
    }

    fn run(self, builder: &Builder<'_>) {
        let compiler = builder.compiler(0, builder.config.build);
        let target = self.target;
        let backend = self.backend;

        builder.ensure(Rustc { target });

        let mut cargo = builder.cargo(
            compiler,
            Mode::Codegen,
            SourceType::Submodule,
            target,
            cargo_subcommand(builder.kind),
        );
        cargo
            .arg("--manifest-path")
            .arg(builder.src.join(format!("compiler/rustc_codegen_{}/Cargo.toml", backend)));
        rustc_cargo_env(builder, &mut cargo, target);

        builder.info(&format!(
            "Checking {} artifacts ({} -> {})",
            backend, &compiler.host.triple, target.triple
        ));

        run_cargo(
            builder,
            cargo,
            args(builder),
            &codegen_backend_stamp(builder, compiler, target, backend),
            vec![],
            true,
        );
    }
}

macro_rules! tool_check_step {
    ($name:ident, $path:expr, $source_type:expr) => {
        #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
        pub struct $name {
            pub target: TargetSelection,
        }

        impl Step for $name {
            type Output = ();
            const ONLY_HOSTS: bool = true;
            const DEFAULT: bool = true;

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

            fn make_run(run: RunConfig<'_>) {
                run.builder.ensure($name { target: run.target });
            }

            fn run(self, builder: &Builder<'_>) {
                let compiler = builder.compiler(0, builder.config.build);
                let target = self.target;

                builder.ensure(Rustc { target });

                let mut cargo = prepare_tool_cargo(
                    builder,
                    compiler,
                    Mode::ToolRustc,
                    target,
                    cargo_subcommand(builder.kind),
                    $path,
                    $source_type,
                    &[],
                );

                if let Subcommand::Check { all_targets: true, .. } = builder.config.cmd {
                    cargo.arg("--all-targets");
                }

                builder.info(&format!(
                    "Checking {} artifacts ({} -> {})",
                    stringify!($name).to_lowercase(),
                    &compiler.host.triple,
                    target.triple
                ));
                run_cargo(
                    builder,
                    cargo,
                    args(builder),
                    &stamp(builder, compiler, target),
                    vec![],
                    true,
                );

                let libdir = builder.sysroot_libdir(compiler, target);
                let hostdir = builder.sysroot_libdir(compiler, compiler.host);
                add_to_sysroot(&builder, &libdir, &hostdir, &stamp(builder, compiler, target));

                /// Cargo's output path in a given stage, compiled by a particular
                /// compiler for the specified target.
                fn stamp(
                    builder: &Builder<'_>,
                    compiler: Compiler,
                    target: TargetSelection,
                ) -> PathBuf {
                    builder
                        .cargo_out(compiler, Mode::ToolRustc, target)
                        .join(format!(".{}-check.stamp", stringify!($name).to_lowercase()))
                }
            }
        }
    };
}

tool_check_step!(Rustdoc, "src/tools/rustdoc", SourceType::InTree);
// Clippy is a hybrid. It is an external tool, but uses a git subtree instead
// of a submodule. Since the SourceType only drives the deny-warnings
// behavior, treat it as in-tree so that any new warnings in clippy will be
// rejected.
tool_check_step!(Clippy, "src/tools/clippy", SourceType::InTree);

tool_check_step!(Bootstrap, "src/bootstrap", SourceType::InTree);

/// Cargo's output path for the standard library in a given stage, compiled
/// by a particular compiler for the specified target.
fn libstd_stamp(builder: &Builder<'_>, compiler: Compiler, target: TargetSelection) -> PathBuf {
    builder.cargo_out(compiler, Mode::Std, target).join(".libstd-check.stamp")
}

/// Cargo's output path for the standard library in a given stage, compiled
/// by a particular compiler for the specified target.
fn libstd_test_stamp(
    builder: &Builder<'_>,
    compiler: Compiler,
    target: TargetSelection,
) -> PathBuf {
    builder.cargo_out(compiler, Mode::Std, target).join(".libstd-check-test.stamp")
}

/// Cargo's output path for librustc in a given stage, compiled by a particular
/// compiler for the specified target.
fn librustc_stamp(builder: &Builder<'_>, compiler: Compiler, target: TargetSelection) -> PathBuf {
    builder.cargo_out(compiler, Mode::Rustc, target).join(".librustc-check.stamp")
}

/// Cargo's output path for librustc_codegen_llvm in a given stage, compiled by a particular
/// compiler for the specified target and backend.
fn codegen_backend_stamp(
    builder: &Builder<'_>,
    compiler: Compiler,
    target: TargetSelection,
    backend: Interned<String>,
) -> PathBuf {
    builder
        .cargo_out(compiler, Mode::Codegen, target)
        .join(format!(".librustc_codegen_{}-check.stamp", backend))
}
<|endoftext|>


<commit_before>use std::marker::PhantomData;
use context::Context;
use framebuffer::FramebufferBinding;
use vertex_data::{VertexData, VertexBytes, VertexAttribBinder};
use index_data::{IndexData, IndexDatum};
use buffer::{Buffer, BufferBinding,
             ArrayBufferBinding, ElementArrayBufferBinding};
use types::DrawingMode;

pub struct VertexBuffer<T: VertexData> {
    pub attrib_binder: Option<T::Binder>,
    buffer: Buffer,
    count: usize,
    phantom: PhantomData<*const T>
}

impl<T: VertexData> VertexBuffer<T> {
    pub fn build_attrib_binder(&self)
        -> <T::Binder as VertexAttribBinder>::Builder
    {
        T::build_attrib_binder()
    }

    pub fn bind_attrib_pointers(&mut self, binder: T::Binder) {
        self.attrib_binder = Some(binder);
    }

    pub fn bind(&self, gl_buffer: &ArrayBufferBinding) -> Result<(), ()> {
        match self.attrib_binder {
            Some(ref binder) => {
                binder.bind(gl_buffer);
                Ok(())
            },
            None => { Err(()) }
        }
    }

    pub fn buffer(&self) -> &Buffer {
        &self.buffer
    }

    pub fn buffer_mut(&mut self) -> &mut Buffer {
        &mut self.buffer
    }
}

pub struct VertexBufferBinding<'a, T: VertexData>
    where T: 'a, T::Binder: 'a
{
    gl_buffer: ArrayBufferBinding<'a>,
    vbo: &'a mut VertexBuffer<T>
}

impl<'a, T: VertexData> VertexBufferBinding<'a, T>
    where T: 'a, T::Binder: 'a
{
    pub fn new(gl_buffer: ArrayBufferBinding<'a>, vbo: &'a mut VertexBuffer<T>)
        -> Self
    {
        VertexBufferBinding {
            gl_buffer: gl_buffer,
            vbo: vbo
        }
    }

    pub fn buffer_data(&mut self, data: &[T], usage: super::BufferDataUsage)
        where [T]: VertexBytes
    {
        self.vbo.count = data.len();
        self.gl_buffer.buffer_bytes(data.vertex_bytes(), usage);
    }
}

impl<'a> FramebufferBinding<'a> {
    pub fn draw_arrays_range_vbo<T>(&mut self,
                                    gl_vbo: &VertexBufferBinding<T>,
                                    mode: DrawingMode,
                                    start: u32,
                                    length: usize)
        where T: VertexData
    {
        debug_assert!((start as usize) + length <= gl_vbo.vbo.count);

        unsafe {
            self.draw_arrays_range(&gl_vbo.gl_buffer, mode, start, length);
        }
    }

    pub fn draw_arrays_vbo<T>(&mut self,
                              gl_vbo: &VertexBufferBinding<T>,
                              mode: DrawingMode)
        where T: VertexData
    {
        unsafe {
            self.draw_arrays_range(&gl_vbo.gl_buffer,
                                   mode,
                                   0,
                                   gl_vbo.vbo.count);
        }
    }

    pub fn draw_n_elements_buffered_vbo<T, I>(&mut self,
                                              gl_vbo: &VertexBufferBinding<T>,
                                              gl_ibo: &IndexBufferBinding<I>,
                                              mode: DrawingMode,
                                              length: usize)
        where T: VertexData, I: IndexDatum
    {
        debug_assert!(length <= gl_ibo.ibo.count);

        unsafe {
            self.draw_n_elements_buffered(&gl_vbo.gl_buffer,
                                          &gl_ibo.gl_buffer,
                                          mode,
                                          length,
                                          I::index_datum_type());
        }
    }

    pub fn draw_elements_buffered_vbo<T, I>(&mut self,
                                            gl_vbo: &VertexBufferBinding<T>,
                                            gl_ibo: &IndexBufferBinding<I>,
                                            mode: DrawingMode)
        where T: VertexData, I: IndexDatum
    {
        unsafe {
            self.draw_n_elements_buffered(&gl_vbo.gl_buffer,
                                          &gl_ibo.gl_buffer,
                                          mode,
                                          gl_ibo.ibo.count,
                                          I::index_datum_type());
        }
    }

    pub fn draw_n_elements_vbo<T, I>(&mut self,
                                     gl_vbo: &VertexBufferBinding<'a, T>,
                                     mode: DrawingMode,
                                     count: usize,
                                     indicies: &[I])
        where T: VertexData, I: IndexDatum, [I]: IndexData
    {
        unsafe {
            self.draw_n_elements(&gl_vbo.gl_buffer, mode, count, indicies);
        }
    }

    pub fn draw_elements_vbo<T, I>(&mut self,
                                   gl_vbo: &VertexBufferBinding<'a, T>,
                                   mode: DrawingMode,
                                   indicies: &[I])
        where T: VertexData, I: IndexDatum, [I]: IndexData
    {
        unsafe {
            self.draw_elements(&gl_vbo.gl_buffer, mode, indicies);
        }
    }
}

impl Context {
    pub fn new_vertex_buffer<T: VertexData>(&self) -> VertexBuffer<T> {
        VertexBuffer {
            attrib_binder: None,
            buffer: self.gen_buffer(),
            count: 0,
            phantom: PhantomData
        }
    }
}

pub struct IndexBuffer<T: IndexDatum> {
    buffer: Buffer,
    count: usize,
    phantom: PhantomData<*const T>
}

impl<T: IndexDatum> IndexBuffer<T> {
    pub fn buffer(&self) -> &Buffer {
        &self.buffer
    }

    pub fn buffer_mut(&mut self) -> &mut Buffer {
        &mut self.buffer
    }
}

pub struct IndexBufferBinding<'a, T: IndexDatum + 'a> {
    gl_buffer: ElementArrayBufferBinding<'a>,
    ibo: &'a mut IndexBuffer<T>
}

impl<'a, T: IndexDatum + 'a> IndexBufferBinding<'a, T> {
    pub fn new(gl_buffer: ElementArrayBufferBinding<'a>,
               ibo: &'a mut IndexBuffer<T>)
        -> Self
    {
        IndexBufferBinding {
            gl_buffer: gl_buffer,
            ibo: ibo
        }
    }

    pub fn buffer_data(&mut self, data: &[T], usage: super::BufferDataUsage)
        where [T]: IndexData
    {
        self.ibo.count = data.len();
        self.gl_buffer.buffer_bytes(data.index_bytes(), usage);
    }
}

impl Context {
    pub fn new_index_buffer<T: IndexDatum>(&self) -> IndexBuffer<T> {
        IndexBuffer {
            buffer: self.gen_buffer(),
            count: 0,
            phantom: PhantomData
        }
    }
}

#[macro_export]
macro_rules! attrib_pointers {
    ($gl:expr, $vbo:expr, {
        $($field_name:ident => $field_attrib:expr),*
    }) => {
        $vbo.build_attrib_binder()
            $(.$field_name($field_attrib))*
            .unwrap($gl);
    }
}

#[macro_export]
macro_rules! bind_attrib_pointers {
    ($gl:expr, $vbo:expr, {
        $($field_name:ident => $field_attrib:expr),*
    }) => {
        {
            let vbo = $vbo;
            let binder = vbo.build_attrib_binder()
                            $(.$field_name($field_attrib))*
                            .unwrap($gl);
            vbo.attrib_binder = Some(binder)
        }
    }
}

#[macro_export]
macro_rules! bind_vertex_buffer {
    ($gl:expr, $vbo:expr) => {
        {
            let vbo = $vbo;

            let gl_buffer = bind_array_buffer!($gl, vbo.buffer_mut());
            vbo.bind(&gl_buffer).unwrap();
            $crate::VertexBufferBinding::new(gl_buffer, vbo)
        }
    }
}

#[macro_export]
macro_rules! bind_index_buffer {
    ($gl:expr, $ibo:expr) => {
        {
            let ibo = $ibo;

            let gl_buffer = bind_element_array_buffer!($gl, ibo.buffer_mut());
            $crate::IndexBufferBinding::new(gl_buffer, ibo)
        }
    }
}
<commit_msg>Refactor `bind_attrib_pointers!`<commit_after>use std::marker::PhantomData;
use context::Context;
use framebuffer::FramebufferBinding;
use vertex_data::{VertexData, VertexBytes, VertexAttribBinder};
use index_data::{IndexData, IndexDatum};
use buffer::{Buffer, BufferBinding,
             ArrayBufferBinding, ElementArrayBufferBinding};
use types::DrawingMode;

pub struct VertexBuffer<T: VertexData> {
    pub attrib_binder: Option<T::Binder>,
    buffer: Buffer,
    count: usize,
    phantom: PhantomData<*const T>
}

impl<T: VertexData> VertexBuffer<T> {
    pub fn build_attrib_binder(&self)
        -> <T::Binder as VertexAttribBinder>::Builder
    {
        T::build_attrib_binder()
    }

    pub fn bind_attrib_pointers(&mut self, binder: T::Binder) {
        self.attrib_binder = Some(binder);
    }

    pub fn bind(&self, gl_buffer: &ArrayBufferBinding) -> Result<(), ()> {
        match self.attrib_binder {
            Some(ref binder) => {
                binder.bind(gl_buffer);
                Ok(())
            },
            None => { Err(()) }
        }
    }

    pub fn buffer(&self) -> &Buffer {
        &self.buffer
    }

    pub fn buffer_mut(&mut self) -> &mut Buffer {
        &mut self.buffer
    }
}

pub struct VertexBufferBinding<'a, T: VertexData>
    where T: 'a, T::Binder: 'a
{
    gl_buffer: ArrayBufferBinding<'a>,
    vbo: &'a mut VertexBuffer<T>
}

impl<'a, T: VertexData> VertexBufferBinding<'a, T>
    where T: 'a, T::Binder: 'a
{
    pub fn new(gl_buffer: ArrayBufferBinding<'a>, vbo: &'a mut VertexBuffer<T>)
        -> Self
    {
        VertexBufferBinding {
            gl_buffer: gl_buffer,
            vbo: vbo
        }
    }

    pub fn buffer_data(&mut self, data: &[T], usage: super::BufferDataUsage)
        where [T]: VertexBytes
    {
        self.vbo.count = data.len();
        self.gl_buffer.buffer_bytes(data.vertex_bytes(), usage);
    }
}

impl<'a> FramebufferBinding<'a> {
    pub fn draw_arrays_range_vbo<T>(&mut self,
                                    gl_vbo: &VertexBufferBinding<T>,
                                    mode: DrawingMode,
                                    start: u32,
                                    length: usize)
        where T: VertexData
    {
        debug_assert!((start as usize) + length <= gl_vbo.vbo.count);

        unsafe {
            self.draw_arrays_range(&gl_vbo.gl_buffer, mode, start, length);
        }
    }

    pub fn draw_arrays_vbo<T>(&mut self,
                              gl_vbo: &VertexBufferBinding<T>,
                              mode: DrawingMode)
        where T: VertexData
    {
        unsafe {
            self.draw_arrays_range(&gl_vbo.gl_buffer,
                                   mode,
                                   0,
                                   gl_vbo.vbo.count);
        }
    }

    pub fn draw_n_elements_buffered_vbo<T, I>(&mut self,
                                              gl_vbo: &VertexBufferBinding<T>,
                                              gl_ibo: &IndexBufferBinding<I>,
                                              mode: DrawingMode,
                                              length: usize)
        where T: VertexData, I: IndexDatum
    {
        debug_assert!(length <= gl_ibo.ibo.count);

        unsafe {
            self.draw_n_elements_buffered(&gl_vbo.gl_buffer,
                                          &gl_ibo.gl_buffer,
                                          mode,
                                          length,
                                          I::index_datum_type());
        }
    }

    pub fn draw_elements_buffered_vbo<T, I>(&mut self,
                                            gl_vbo: &VertexBufferBinding<T>,
                                            gl_ibo: &IndexBufferBinding<I>,
                                            mode: DrawingMode)
        where T: VertexData, I: IndexDatum
    {
        unsafe {
            self.draw_n_elements_buffered(&gl_vbo.gl_buffer,
                                          &gl_ibo.gl_buffer,
                                          mode,
                                          gl_ibo.ibo.count,
                                          I::index_datum_type());
        }
    }

    pub fn draw_n_elements_vbo<T, I>(&mut self,
                                     gl_vbo: &VertexBufferBinding<'a, T>,
                                     mode: DrawingMode,
                                     count: usize,
                                     indicies: &[I])
        where T: VertexData, I: IndexDatum, [I]: IndexData
    {
        unsafe {
            self.draw_n_elements(&gl_vbo.gl_buffer, mode, count, indicies);
        }
    }

    pub fn draw_elements_vbo<T, I>(&mut self,
                                   gl_vbo: &VertexBufferBinding<'a, T>,
                                   mode: DrawingMode,
                                   indicies: &[I])
        where T: VertexData, I: IndexDatum, [I]: IndexData
    {
        unsafe {
            self.draw_elements(&gl_vbo.gl_buffer, mode, indicies);
        }
    }
}

impl Context {
    pub fn new_vertex_buffer<T: VertexData>(&self) -> VertexBuffer<T> {
        VertexBuffer {
            attrib_binder: None,
            buffer: self.gen_buffer(),
            count: 0,
            phantom: PhantomData
        }
    }
}

pub struct IndexBuffer<T: IndexDatum> {
    buffer: Buffer,
    count: usize,
    phantom: PhantomData<*const T>
}

impl<T: IndexDatum> IndexBuffer<T> {
    pub fn buffer(&self) -> &Buffer {
        &self.buffer
    }

    pub fn buffer_mut(&mut self) -> &mut Buffer {
        &mut self.buffer
    }
}

pub struct IndexBufferBinding<'a, T: IndexDatum + 'a> {
    gl_buffer: ElementArrayBufferBinding<'a>,
    ibo: &'a mut IndexBuffer<T>
}

impl<'a, T: IndexDatum + 'a> IndexBufferBinding<'a, T> {
    pub fn new(gl_buffer: ElementArrayBufferBinding<'a>,
               ibo: &'a mut IndexBuffer<T>)
        -> Self
    {
        IndexBufferBinding {
            gl_buffer: gl_buffer,
            ibo: ibo
        }
    }

    pub fn buffer_data(&mut self, data: &[T], usage: super::BufferDataUsage)
        where [T]: IndexData
    {
        self.ibo.count = data.len();
        self.gl_buffer.buffer_bytes(data.index_bytes(), usage);
    }
}

impl Context {
    pub fn new_index_buffer<T: IndexDatum>(&self) -> IndexBuffer<T> {
        IndexBuffer {
            buffer: self.gen_buffer(),
            count: 0,
            phantom: PhantomData
        }
    }
}

#[macro_export]
macro_rules! attrib_pointers {
    ($gl:expr, $vbo:expr, {
        $($field_name:ident => $field_attrib:expr),*
    }) => {
        $vbo.build_attrib_binder()
            $(.$field_name($field_attrib))*
            .unwrap($gl);
    }
}

#[macro_export]
macro_rules! bind_attrib_pointers {
    ($gl:expr, $vbo:expr, {
        $($field_name:ident => $field_attrib:expr),*
    }) => {
        {
            let vbo = $vbo;
            let binder = {
                attrib_pointers!($gl, vbo, {
                    $($field_name => $field_attrib),*
                })
            };
            vbo.bind_attrib_pointers(binder);
        }
    }
}

#[macro_export]
macro_rules! bind_vertex_buffer {
    ($gl:expr, $vbo:expr) => {
        {
            let vbo = $vbo;

            let gl_buffer = bind_array_buffer!($gl, vbo.buffer_mut());
            vbo.bind(&gl_buffer).unwrap();
            $crate::VertexBufferBinding::new(gl_buffer, vbo)
        }
    }
}

#[macro_export]
macro_rules! bind_index_buffer {
    ($gl:expr, $ibo:expr) => {
        {
            let ibo = $ibo;

            let gl_buffer = bind_element_array_buffer!($gl, ibo.buffer_mut());
            $crate::IndexBufferBinding::new(gl_buffer, ibo)
        }
    }
}
<|endoftext|>


<commit_before>
use types::{Int, ForthCell};
use error::{ForthResult, ForthError};
use dictionary::{Dictionary, DictionaryExt, Entry};
use statement::{Statement, StatementExt};
use word::ForthWord;

pub type Stack = Vec<Int>;

pub struct Interpreter {
    pub dictionary: Dictionary,
    last_result: Option<Stack>,
}

macro_rules! try_stack {
	($x:expr) => {
		match $x {
			Some(i) => i,
			None => return Err(ForthError::EmptyStack),
		}
	}
}

macro_rules! binary_entry {
	($dict:ident, $name:expr, $f:expr) => {
		$dict.insert_entry(Entry::new($name,
				ForthWord::Native(Box::new(|_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let b = try_stack!(stack.pop());
					let a = try_stack!(stack.pop());
					stack.push($f(a, b));
					Ok(())
				})),
			))
	}
}

macro_rules! unary_entry {
	($dict:ident, $name:expr, $f:expr) => {
		$dict.insert_entry(Entry::new($name,
				ForthWord::Native(Box::new(|_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let a = try_stack!(stack.pop());
					stack.push($f(a));
					Ok(())
				})),
			))
	}
}

macro_rules! nonary_entry {
	($dict:ident, $name:expr, $f:expr) => {
		$dict.insert_entry(Entry::new($name,
				ForthWord::Native(Box::new(|_: &mut Interpreter, _: &mut Stack| -> ForthResult<()> {
					ForthCell::Number($f);
					Ok(())
				})),
			))
	}
}

macro_rules! entry {
	($dict:ident, $name:expr, $f:expr) => {
		$dict.insert_entry(Entry::new($name, ForthWord::Native(Box::new($f))))
	}
}

impl Interpreter {
	pub fn new() -> Interpreter {
		let mut dict = Dictionary::new();

		binary_entry!(dict, "/", ::std::ops::Div::div);
		binary_entry!(dict, "*", ::std::ops::Mul::mul);
		binary_entry!(dict, "+", ::std::ops::Add::add);
		binary_entry!(dict, "-", ::std::ops::Sub::sub);
		binary_entry!(dict, "mod", ::std::ops::Rem::rem);
		binary_entry!(dict, "and", ::std::ops::BitAnd::bitand);
		binary_entry!(dict, "or", ::std::ops::BitOr::bitor);
		binary_entry!(dict, "xor", ::std::ops::BitXor::bitxor);
		binary_entry!(dict, "rshift", ::std::ops::Shr::shr);
		binary_entry!(dict, "lshift", ::std::ops::Shl::shl);

		unary_entry!(dict, "negate", ::std::ops::Neg::neg);
		unary_entry!(dict, "not", ::std::ops::Not::not);

		nonary_entry!(dict, "bye", ::std::process::exit(0));

		entry!(dict, "$", |interp: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(interp.last_result.clone());
					for v in x {
						stack.push(v);
					}
					Ok(())
				});

		entry!(dict, "<", | _: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let y = try_stack!(stack.pop());
					let x = try_stack!(stack.pop());
					stack.push(if x < y { 1 } else { 0 });
					Ok(())
				});

		entry!(dict, ">", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let y = try_stack!(stack.pop());
					let x = try_stack!(stack.pop());
					stack.push(if x > y { 1 } else { 0 });
					Ok(())
				});

		entry!(dict, "=", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let y = try_stack!(stack.pop());
					let x = try_stack!(stack.pop());
					stack.push(if x == y { 1 } else { 0 });
					Ok(())
				});

		entry!(dict, "0<", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					stack.push(if x < 0 { 1 } else { 0 });
					Ok(())
				});

		entry!(dict, "0=", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					stack.push(if x == 0 { 1 } else { 0 });
					Ok(())
				});

		entry!(dict, "0>", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					stack.push(if x > 0 { 1 } else { 0 });
					Ok(())
				});

		entry!(dict, "1+", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					stack.push(x + 1);
					Ok(())
				});

		entry!(dict, "1-", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					stack.push(x - 1);
					Ok(())
				});

		entry!(dict, "2+", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					stack.push(x + 2);
					Ok(())
				});

		entry!(dict, "2-", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					stack.push(x - 2);
					Ok(())
				});

		entry!(dict, "2/", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					stack.push(x >> 1); // Per fst83 standard
					Ok(())
				});

		entry!(dict, "dup", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					stack.push(x.clone());
					stack.push(x);
					Ok(())
				});

		entry!(dict, "?dup", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					if x != 0 {
						stack.push(x.clone());
						stack.push(x);
					} else {
						stack.push(x);
					}
					Ok(())
				});

		entry!(dict, "over", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					let y = try_stack!(stack.pop());
					stack.push(x.clone());
					stack.push(y);
					stack.push(x);
					Ok(())
				});

		entry!(dict, "swap", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					let y = try_stack!(stack.pop());
					stack.push(x);
					stack.push(y);
					Ok(())
				});

		entry!(dict, "rot", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					let y = try_stack!(stack.pop());
					let z = try_stack!(stack.pop());
					stack.push(y);
					stack.push(x);
					stack.push(z);
					Ok(())
				});

		entry!(dict, "dump", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					println!("ds =  {:?} ", stack);
					Ok(())
				});

		entry!(dict, "cr", |_: &mut Interpreter, _: &mut Stack| -> ForthResult<()> {
					println!("");
					Ok(())
				});

		entry!(dict, ".", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					println!("{}", try_stack!(stack.pop()));
					Ok(())
				});

		entry!(dict, "branch", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let y = try_stack!(stack.pop());
					let x = try_stack!(stack.pop());
					stack.push(if x == y { 1 } else { 0 });
					Ok(())
				});

		let square = {
			let mut s = Statement::new();
			s.push_back(ForthCell::Word(dict.get("dup").unwrap().clone()));
			s.push_back(ForthCell::Word(dict.get("*").unwrap().clone()));
			s
		};
		dict.insert_entry(Entry::from_statement("square", square));

		Interpreter {
			dictionary: dict,
			last_result: None,
		}
	}

	pub fn exec(&mut self, statement: &str) -> ForthResult<()> {
		let mut words = statement.split(|c: char| c.is_whitespace());
		let mut stmt = Statement::new();
		while let Some(word) = words.next() { match word {
			"(" => while let Some(w) = words.next() { if w == ")" { break; } },
			"\\" => while let Some(w) = words.next() { if w == "\n" { break; } },
			":" => {
				let mut comp = Statement::new();
				let name = match words.next() {
					Some(w) => w,
					None => return Err(ForthError::WordNameNotFound),
				};
				while let Some(w) = words.next() {
					if w == ";" {
						self.dictionary.insert_entry(Entry::from_statement(name, comp));
						return Ok(());
					}
					match w.parse::<i32>() {
						Ok(n) => comp.push_back(ForthCell::Number(n)),
						Err(_) => comp.push_back(ForthCell::Word(self.dictionary.get(w).unwrap().clone())),
					}
				}
				return Err(ForthError::UnterminatedWordDefinition);
			},
			_ => match word.parse::<i32>() {
				Ok(n) => {
					stmt.push_back(ForthCell::Number(n));
				},
				Err(_) => {
					if let Some(elem) = self.dictionary.get(word) {
						stmt.push_back(ForthCell::Word(elem.clone()));
					} else {
						return Err(ForthError::WordNotFound)
					}
				},
			},

		}}

		match stmt.run(self) {
			Err(e) => {
				self.last_result = None;
				Err(e)
			},
			Ok(s) => {
				self.last_result = Some(s);
				Ok(())
			}
		}
	}
}<commit_msg>Add 'drop' word.<commit_after>
use types::{Int, ForthCell};
use error::{ForthResult, ForthError};
use dictionary::{Dictionary, DictionaryExt, Entry};
use statement::{Statement, StatementExt};
use word::ForthWord;

pub type Stack = Vec<Int>;

pub struct Interpreter {
    pub dictionary: Dictionary,
    last_result: Option<Stack>,
}

macro_rules! try_stack {
	($x:expr) => {
		match $x {
			Some(i) => i,
			None => return Err(ForthError::EmptyStack),
		}
	}
}

macro_rules! binary_entry {
	($dict:ident, $name:expr, $f:expr) => {
		$dict.insert_entry(Entry::new($name,
				ForthWord::Native(Box::new(|_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let b = try_stack!(stack.pop());
					let a = try_stack!(stack.pop());
					stack.push($f(a, b));
					Ok(())
				})),
			))
	}
}

macro_rules! unary_entry {
	($dict:ident, $name:expr, $f:expr) => {
		$dict.insert_entry(Entry::new($name,
				ForthWord::Native(Box::new(|_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let a = try_stack!(stack.pop());
					stack.push($f(a));
					Ok(())
				})),
			))
	}
}

macro_rules! nonary_entry {
	($dict:ident, $name:expr, $f:expr) => {
		$dict.insert_entry(Entry::new($name,
				ForthWord::Native(Box::new(|_: &mut Interpreter, _: &mut Stack| -> ForthResult<()> {
					ForthCell::Number($f);
					Ok(())
				})),
			))
	}
}

macro_rules! entry {
	($dict:ident, $name:expr, $f:expr) => {
		$dict.insert_entry(Entry::new($name, ForthWord::Native(Box::new($f))))
	}
}

impl Interpreter {
	pub fn new() -> Interpreter {
		let mut dict = Dictionary::new();

		binary_entry!(dict, "/", ::std::ops::Div::div);
		binary_entry!(dict, "*", ::std::ops::Mul::mul);
		binary_entry!(dict, "+", ::std::ops::Add::add);
		binary_entry!(dict, "-", ::std::ops::Sub::sub);
		binary_entry!(dict, "mod", ::std::ops::Rem::rem);
		binary_entry!(dict, "and", ::std::ops::BitAnd::bitand);
		binary_entry!(dict, "or", ::std::ops::BitOr::bitor);
		binary_entry!(dict, "xor", ::std::ops::BitXor::bitxor);
		binary_entry!(dict, "rshift", ::std::ops::Shr::shr);
		binary_entry!(dict, "lshift", ::std::ops::Shl::shl);

		unary_entry!(dict, "negate", ::std::ops::Neg::neg);
		unary_entry!(dict, "not", ::std::ops::Not::not);

		nonary_entry!(dict, "bye", ::std::process::exit(0));

		entry!(dict, "$", |interp: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(interp.last_result.clone());
					for v in x {
						stack.push(v);
					}
					Ok(())
				});

		entry!(dict, "<", | _: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let y = try_stack!(stack.pop());
					let x = try_stack!(stack.pop());
					stack.push(if x < y { 1 } else { 0 });
					Ok(())
				});

		entry!(dict, ">", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let y = try_stack!(stack.pop());
					let x = try_stack!(stack.pop());
					stack.push(if x > y { 1 } else { 0 });
					Ok(())
				});

		entry!(dict, "=", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let y = try_stack!(stack.pop());
					let x = try_stack!(stack.pop());
					stack.push(if x == y { 1 } else { 0 });
					Ok(())
				});

		entry!(dict, "0<", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					stack.push(if x < 0 { 1 } else { 0 });
					Ok(())
				});

		entry!(dict, "0=", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					stack.push(if x == 0 { 1 } else { 0 });
					Ok(())
				});

		entry!(dict, "0>", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					stack.push(if x > 0 { 1 } else { 0 });
					Ok(())
				});

		entry!(dict, "1+", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					stack.push(x + 1);
					Ok(())
				});

		entry!(dict, "1-", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					stack.push(x - 1);
					Ok(())
				});

		entry!(dict, "2+", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					stack.push(x + 2);
					Ok(())
				});

		entry!(dict, "2-", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					stack.push(x - 2);
					Ok(())
				});

		entry!(dict, "2/", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					stack.push(x >> 1); // Per fst83 standard
					Ok(())
				});

		entry!(dict, "dup", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					stack.push(x.clone());
					stack.push(x);
					Ok(())
				});

		entry!(dict, "?dup", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					if x != 0 {
						stack.push(x.clone());
						stack.push(x);
					} else {
						stack.push(x);
					}
					Ok(())
				});

		entry!(dict, "drop", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let _ = try_stack!(stack.pop());
					Ok(())
				});

		entry!(dict, "over", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					let y = try_stack!(stack.pop());
					stack.push(x.clone());
					stack.push(y);
					stack.push(x);
					Ok(())
				});

		entry!(dict, "swap", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					let y = try_stack!(stack.pop());
					stack.push(x);
					stack.push(y);
					Ok(())
				});

		entry!(dict, "rot", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let x = try_stack!(stack.pop());
					let y = try_stack!(stack.pop());
					let z = try_stack!(stack.pop());
					stack.push(y);
					stack.push(x);
					stack.push(z);
					Ok(())
				});

		entry!(dict, "dump", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					println!("ds =  {:?} ", stack);
					Ok(())
				});

		entry!(dict, "cr", |_: &mut Interpreter, _: &mut Stack| -> ForthResult<()> {
					println!("");
					Ok(())
				});

		entry!(dict, ".", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					println!("{}", try_stack!(stack.pop()));
					Ok(())
				});

		entry!(dict, "branch", |_: &mut Interpreter, stack: &mut Stack| -> ForthResult<()> {
					let y = try_stack!(stack.pop());
					let x = try_stack!(stack.pop());
					stack.push(if x == y { 1 } else { 0 });
					Ok(())
				});

		let square = {
			let mut s = Statement::new();
			s.push_back(ForthCell::Word(dict.get("dup").unwrap().clone()));
			s.push_back(ForthCell::Word(dict.get("*").unwrap().clone()));
			s
		};
		dict.insert_entry(Entry::from_statement("square", square));

		Interpreter {
			dictionary: dict,
			last_result: None,
		}
	}

	pub fn exec(&mut self, statement: &str) -> ForthResult<()> {
		let mut words = statement.split(|c: char| c.is_whitespace());
		let mut stmt = Statement::new();
		while let Some(word) = words.next() { match word {
			"(" => while let Some(w) = words.next() { if w == ")" { break; } },
			"\\" => while let Some(w) = words.next() { if w == "\n" { break; } },
			":" => {
				let mut comp = Statement::new();
				let name = match words.next() {
					Some(w) => w,
					None => return Err(ForthError::WordNameNotFound),
				};
				while let Some(w) = words.next() {
					if w == ";" {
						self.dictionary.insert_entry(Entry::from_statement(name, comp));
						return Ok(());
					}
					match w.parse::<i32>() {
						Ok(n) => comp.push_back(ForthCell::Number(n)),
						Err(_) => comp.push_back(ForthCell::Word(self.dictionary.get(w).unwrap().clone())),
					}
				}
				return Err(ForthError::UnterminatedWordDefinition);
			},
			_ => match word.parse::<i32>() {
				Ok(n) => {
					stmt.push_back(ForthCell::Number(n));
				},
				Err(_) => {
					if let Some(elem) = self.dictionary.get(word) {
						stmt.push_back(ForthCell::Word(elem.clone()));
					} else {
						return Err(ForthError::WordNotFound)
					}
				},
			},

		}}

		match stmt.run(self) {
			Err(e) => {
				self.last_result = None;
				Err(e)
			},
			Ok(s) => {
				self.last_result = Some(s);
				Ok(())
			}
		}
	}
}<|endoftext|>


<commit_before>//! Contains code to handle an IPC channel which is issuing commands.

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

use rustc_serialize::Decodable;
use rustc_serialize::json::{Json, ToJson, Decoder, EncoderError};

use unix_socket::UnixStream;

/// Reasons a client message might be erroneous
#[derive(Debug, Clone)]
enum ResponseError {
    /// Connection was closed
    ConnectionClosed,
    /// Json was invalid
    InvalidJson(EncoderError)
}

/// Receives a packet from the given stream.
fn receive_packet(stream: &mut UnixStream) -> Result<Json, ResponseError> {
    Err(ResponseError::ConnectionClosed)
}

pub fn handle_client(mut stream: UnixStream) {
    println!("Starting connection.");

    // Listen for starting connection
}

fn command(mut stream: UnixStream) {

}

fn event(mut stream: UnixStream) {

}
<commit_msg>Add basic packet read, including unsafe conversion<commit_after>//! Contains code to handle an IPC channel which is issuing commands.

use std::io::Error as IOError;
use std::io::prelude::*;

use rustc_serialize::Decodable;
use rustc_serialize::json::{Json, ToJson, Decoder, ParserError, EncoderError};

use unix_socket::UnixStream;

/// Reasons a client message might be erroneous
#[derive(Debug)]
enum ResponseError {
    /// Connection was closed
    ConnectionClosed,
    /// Some bytes dun goofed
    InvalidString,
    /// There were IO issues
    IO(IOError),
    /// Json was invalid
    InvalidJson(ParserError)
}

/// Receives a packet from the given stream.
fn receive_packet(stream: &mut Read) -> Result<Json, ResponseError> {
    let mut buffer = [0u8; 4];
    try!(stream.read_exact(&mut buffer).map_err(ResponseError::IO));
    // This is what the byteorder crate does (needs testing)
    let len = u32::from_be(unsafe { buffer.as_ptr() as *const u32 } as u32);
    trace!("Listening for packet of length {}", len);
    return Json::from_reader(&mut stream.take(len as u64))
        .map_err(ResponseError::InvalidJson);
}

pub fn handle_client(mut stream: UnixStream) {
    println!("Starting connection.");

    // Listen for starting connection
}

fn command(mut stream: UnixStream) {

}

fn event(mut stream: UnixStream) {

}
<|endoftext|>


<commit_before>use std::collections::HashSet;
use std::fs::{read_dir, read_link, remove_file};
use std::io::{stdout, stderr};
use std::path::Path;
use std::str::FromStr;

use argparse::{ArgumentParser, PushConst, StoreTrue};

use super::setup;
use super::Wrapper;
use container::util::clean_dir;
use file_util::read_visible_entries;
use path_util::PathExt;

#[derive(Clone, Copy)]
enum Action {
    Temporary,
    Old,
    Everything,
    Orphans,
    Transient,
}

pub fn clean_cmd(wrapper: &Wrapper, cmdline: Vec<String>)
    -> Result<i32, String>
{
    let mut global = false;
    let mut dry_run = false;
    let mut actions = vec!();
    {
        let mut ap = ArgumentParser::new();
        ap.set_description("
            Performs various cleanup tasks
            ");
        ap.refer(&mut actions)
          .add_option(&["--tmp", "--tmp-folders"],
                PushConst(Action::Temporary),
                "Clean temporary containers (failed builds)")
          .add_option(&["--old", "--old-containers"], PushConst(Action::Old),
                "Clean old versions of containers (configurable)")
          .add_option(&["--transient"], PushConst(Action::Transient),
                "Clean unneeded transient folders (left from containers with
                 `write-mode` set to transient-something). The pid of process
                 is checked for liveness first.")
          .add_option(&["--everything"], PushConst(Action::Everything),
                "Clean whole `.vagga` folder. Useful when deleting a project.
                 With ``--global`` cleans whole storage-dir and cache-dir")
          .add_option(&["--orphans"], PushConst(Action::Orphans),
                "Without `--global` removes containers which are not in
                 vagga.yaml any more. With `--global` removes all folders
                 which have `.lnk` pointing to nowhere (i.e. project dir
                 already deleted while vagga folder is not)")
          .required();
        ap.refer(&mut global)
          .add_option(&["--global"], StoreTrue,
                "Apply cleanup command to all containers. Works only \
                if `storage-dir` is configured in settings");
        ap.refer(&mut dry_run)
          .add_option(&["-n", "--dry-run"], StoreTrue,
                "Dry run. Don't delete everything, just print");
        match ap.parse(cmdline, &mut stdout(), &mut stderr()) {
            Ok(()) => {}
            Err(0) => return Ok(0),
            Err(_) => {
                return Ok(1);
            }
        }
    }
    if global && wrapper.ext_settings.storage_dir.is_none() {
        error!("The --global flag is only meaningful if you configure \
            storage-dir in settings");
        return Ok(2);
    }
    for action in actions.iter() {
        let res = match *action {
            Action::Temporary => clean_temporary(wrapper, global, dry_run),
            Action::Old => clean_old(wrapper, global, dry_run),
            Action::Transient => clean_transient(wrapper, global, dry_run),
            _ => unimplemented!(),
        };
        match res {
            Ok(()) => {}
            Err(err) => {
                error!("Error cleaning up: {}", err);
                return Ok(3);
            }
        }
    }
    return Ok(0);
}

fn clean_dir_wrapper(path: &Path, dry_run: bool) -> Result<(), String> {
    // TODO(tailhook) chroot to dir for removing
    if dry_run {
        println!("Would remove {:?}", path);
    } else {
        debug!("Removing {:?}", path);
        try!(clean_dir(path, true));
    }
    Ok(())
}

fn clean_temporary(wrapper: &Wrapper, global: bool, dry_run: bool)
    -> Result<(), String>
{
    if global {
        panic!("Global cleanup is not implemented yet");
    }
    let base = match try!(setup::get_vagga_base(
        wrapper.project_root, wrapper.ext_settings))
    {
        Some(base) => base,
        None => {
            warn!("No vagga directory exists");
            return Ok(());
        }
    };
    let roots = base.join(".roots");
    for entry in try_msg!(read_dir(&roots),
        "Can't read dir {r:?}: {err}", r=roots)
    {
        let entry = try_msg!(entry, "Can't read dir {r:?}: {err}", r=roots);
        let typ = try_msg!(entry.file_type(),
            "Can't stat {p:?}: {err}", p=entry.path());
        if typ.is_dir() &&
           entry.file_name()[..].to_str().map(|n| n.starts_with(".tmp"))
                                         .unwrap_or(false)
        {
            try!(clean_dir_wrapper(&entry.path(), dry_run));
        }
    }

    return Ok(());
}

fn clean_old(wrapper: &Wrapper, global: bool, dry_run: bool)
    -> Result<(), String>
{
    if global {
        panic!("Global cleanup is not implemented yet");
    }
    let base = match try!(setup::get_vagga_base(
        wrapper.project_root, wrapper.ext_settings))
    {
        Some(base) => base,
        None => {
            warn!("No vagga directory exists");
            return Ok(());
        }
    };
    let useful: HashSet<String> = try_msg!(
        read_visible_entries(&wrapper.project_root.join(".vagga")),
            "Can't read vagga directory: {err}")
        .into_iter()
        .filter_map(|path| read_link(&path)
             .map_err(|e| warn!("Can't readlink {:?}: {}", path, e))
             .ok()
             .and_then(|f| {
                 // The container name is next to the last component
                 f.iter().rev().nth(1)
                 .and_then(|x| x.to_str()).map(ToString::to_string)
             }))
        .collect();
    debug!("Useful images {:?}", useful);

    let roots = base.join(".roots");
    for entry in try_msg!(read_dir(&roots),
                         "Can't read dir {dir:?}: {err}", dir=roots)
    {
        let entry = try_msg!(entry,
                             "Can't read dir {dir:?}: {err}", dir=roots);
        let typ = try_msg!(entry.file_type(),
            "Can't stat {p:?}: {err}", p=entry.path());
        if !typ.is_dir() {
            try_msg!(remove_file(&entry.path()),
                "Can't remove file {p:?}: {err}", p=entry.path());
        } else if !typ.is_dir() || entry.file_name()[..].to_str()
            .map(|n| !useful.contains(&n.to_string()))
            .unwrap_or(false)
        {
            try!(clean_dir_wrapper(&entry.path(), dry_run));
        }
    }

    return Ok(());
}

fn clean_transient(wrapper: &Wrapper, global: bool, dry_run: bool)
    -> Result<(), String>
{
    if global {
        panic!("Global cleanup is not implemented yet");
    }
    let base = match try!(setup::get_vagga_base(
        wrapper.project_root, wrapper.ext_settings))
    {
        Some(base) => base,
        None => {
            warn!("No vagga directory exists");
            return Ok(());
        }
    };
    let procfs = Path::new("/proc");
    for entry in try_msg!(read_dir(&base.join(".transient")),
                        "Can't read .vagga/.transient dir: {err}")
    {
        let entry = try_msg!(entry, "Error reading .vagga/transient: {err}");
        if let Some(fname) = entry.file_name()[..].to_str() {
            if let Some(idx) = fname.find('.') {
                if u32::from_str(&fname[idx+1..]).is_ok() &&
                    procfs.join(&fname[idx+1..]).exists()
                {
                    continue;
                }
            }
        }
        try!(clean_dir_wrapper(&entry.path(), dry_run));
    }

    return Ok(());
}
<commit_msg>Remove `_clean --orphans` command which was never implemented<commit_after>use std::collections::HashSet;
use std::fs::{read_dir, read_link, remove_file};
use std::io::{stdout, stderr};
use std::path::Path;
use std::str::FromStr;

use argparse::{ArgumentParser, PushConst, StoreTrue};

use super::setup;
use super::Wrapper;
use container::util::clean_dir;
use file_util::read_visible_entries;
use path_util::PathExt;

#[derive(Clone, Copy)]
enum Action {
    Temporary,
    Old,
    Everything,
    Transient,
}

pub fn clean_cmd(wrapper: &Wrapper, cmdline: Vec<String>)
    -> Result<i32, String>
{
    let mut global = false;
    let mut dry_run = false;
    let mut actions = vec!();
    {
        let mut ap = ArgumentParser::new();
        ap.set_description("
            Performs various cleanup tasks
            ");
        ap.refer(&mut actions)
          .add_option(&["--tmp", "--tmp-folders"],
                PushConst(Action::Temporary),
                "Clean temporary containers (failed builds)")
          .add_option(&["--old", "--old-containers"], PushConst(Action::Old),
                "Clean old versions of containers (configurable)")
          .add_option(&["--transient"], PushConst(Action::Transient),
                "Clean unneeded transient folders (left from containers with
                 `write-mode` set to transient-something). The pid of process
                 is checked for liveness first.")
          .add_option(&["--everything"], PushConst(Action::Everything),
                "Clean whole `.vagga` folder. Useful when deleting a project.
                 With ``--global`` cleans whole storage-dir and cache-dir")
          .required();
        ap.refer(&mut global)
          .add_option(&["--global"], StoreTrue,
                "Apply cleanup command to all containers. Works only \
                if `storage-dir` is configured in settings");
        ap.refer(&mut dry_run)
          .add_option(&["-n", "--dry-run"], StoreTrue,
                "Dry run. Don't delete everything, just print");
        match ap.parse(cmdline, &mut stdout(), &mut stderr()) {
            Ok(()) => {}
            Err(0) => return Ok(0),
            Err(_) => {
                return Ok(1);
            }
        }
    }
    if global && wrapper.ext_settings.storage_dir.is_none() {
        error!("The --global flag is only meaningful if you configure \
            storage-dir in settings");
        return Ok(2);
    }
    for action in actions.iter() {
        let res = match *action {
            Action::Temporary => clean_temporary(wrapper, global, dry_run),
            Action::Old => clean_old(wrapper, global, dry_run),
            Action::Transient => clean_transient(wrapper, global, dry_run),
            _ => unimplemented!(),
        };
        match res {
            Ok(()) => {}
            Err(err) => {
                error!("Error cleaning up: {}", err);
                return Ok(3);
            }
        }
    }
    return Ok(0);
}

fn clean_dir_wrapper(path: &Path, dry_run: bool) -> Result<(), String> {
    // TODO(tailhook) chroot to dir for removing
    if dry_run {
        println!("Would remove {:?}", path);
    } else {
        debug!("Removing {:?}", path);
        try!(clean_dir(path, true));
    }
    Ok(())
}

fn clean_temporary(wrapper: &Wrapper, global: bool, dry_run: bool)
    -> Result<(), String>
{
    if global {
        panic!("Global cleanup is not implemented yet");
    }
    let base = match try!(setup::get_vagga_base(
        wrapper.project_root, wrapper.ext_settings))
    {
        Some(base) => base,
        None => {
            warn!("No vagga directory exists");
            return Ok(());
        }
    };
    let roots = base.join(".roots");
    for entry in try_msg!(read_dir(&roots),
        "Can't read dir {r:?}: {err}", r=roots)
    {
        let entry = try_msg!(entry, "Can't read dir {r:?}: {err}", r=roots);
        let typ = try_msg!(entry.file_type(),
            "Can't stat {p:?}: {err}", p=entry.path());
        if typ.is_dir() &&
           entry.file_name()[..].to_str().map(|n| n.starts_with(".tmp"))
                                         .unwrap_or(false)
        {
            try!(clean_dir_wrapper(&entry.path(), dry_run));
        }
    }

    return Ok(());
}

fn clean_old(wrapper: &Wrapper, global: bool, dry_run: bool)
    -> Result<(), String>
{
    if global {
        panic!("Global cleanup is not implemented yet");
    }
    let base = match try!(setup::get_vagga_base(
        wrapper.project_root, wrapper.ext_settings))
    {
        Some(base) => base,
        None => {
            warn!("No vagga directory exists");
            return Ok(());
        }
    };
    let useful: HashSet<String> = try_msg!(
        read_visible_entries(&wrapper.project_root.join(".vagga")),
            "Can't read vagga directory: {err}")
        .into_iter()
        .filter_map(|path| read_link(&path)
             .map_err(|e| warn!("Can't readlink {:?}: {}", path, e))
             .ok()
             .and_then(|f| {
                 // The container name is next to the last component
                 f.iter().rev().nth(1)
                 .and_then(|x| x.to_str()).map(ToString::to_string)
             }))
        .collect();
    debug!("Useful images {:?}", useful);

    let roots = base.join(".roots");
    for entry in try_msg!(read_dir(&roots),
                         "Can't read dir {dir:?}: {err}", dir=roots)
    {
        let entry = try_msg!(entry,
                             "Can't read dir {dir:?}: {err}", dir=roots);
        let typ = try_msg!(entry.file_type(),
            "Can't stat {p:?}: {err}", p=entry.path());
        if !typ.is_dir() {
            try_msg!(remove_file(&entry.path()),
                "Can't remove file {p:?}: {err}", p=entry.path());
        } else if !typ.is_dir() || entry.file_name()[..].to_str()
            .map(|n| !useful.contains(&n.to_string()))
            .unwrap_or(false)
        {
            try!(clean_dir_wrapper(&entry.path(), dry_run));
        }
    }

    return Ok(());
}

fn clean_transient(wrapper: &Wrapper, global: bool, dry_run: bool)
    -> Result<(), String>
{
    if global {
        panic!("Global cleanup is not implemented yet");
    }
    let base = match try!(setup::get_vagga_base(
        wrapper.project_root, wrapper.ext_settings))
    {
        Some(base) => base,
        None => {
            warn!("No vagga directory exists");
            return Ok(());
        }
    };
    let procfs = Path::new("/proc");
    for entry in try_msg!(read_dir(&base.join(".transient")),
                        "Can't read .vagga/.transient dir: {err}")
    {
        let entry = try_msg!(entry, "Error reading .vagga/transient: {err}");
        if let Some(fname) = entry.file_name()[..].to_str() {
            if let Some(idx) = fname.find('.') {
                if u32::from_str(&fname[idx+1..]).is_ok() &&
                    procfs.join(&fname[idx+1..]).exists()
                {
                    continue;
                }
            }
        }
        try!(clean_dir_wrapper(&entry.path(), dry_run));
    }

    return Ok(());
}
<|endoftext|>


<commit_before>/// Sends a message to an object. The first argument should implement the
/// `ToMessage` trait, and the syntax is similar to the message syntax in
/// Objective-C.
///
/// Variadic arguments are not currently supported. This macro should only be
/// used in cases where `objc_msgSend` would be used, as opposed to
/// `objc_msgSend_stret` or `objc_msgSend_fpret`.
/// For more information, see Apple's documenation:
/// https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ObjCRuntimeRef/index.html#//apple_ref/doc/uid/TP40001418-CH1g-88778
///
/// # Example
/// ```
/// let description = msg_send![obj, description];
/// msg_send![obj, setArg1:1u arg2:2u];
/// ```
#[macro_export]
macro_rules! msg_send {
    ($obj:expr, $name:ident) => ({
        let sel_name = stringify!($name);
        let sel = $crate::runtime::Sel::register(sel_name);
        let ptr = $crate::to_obj_ptr(&$obj);
        $crate::runtime::objc_msgSend(ptr, sel)
    });
    ($obj:expr, $($name:ident : $arg:expr)+) => ({
        let sel_name = concat!($(stringify!($name), ':'),+);
        let sel = $crate::runtime::Sel::register(sel_name);
        let ptr = $crate::to_obj_ptr(&$obj);
        $crate::runtime::objc_msgSend(ptr, sel $(,$arg)+)
    });
}

/// Implements the `Encode` trait for a `Message` type.
/// Specifically, this will implement `Encode` for reference, pointers, and
/// `Option` references of the given type.
///
/// The first argument should be a static string that is the type encoding
/// to use in the implementation. The second argument is the ident of the name
/// of the type to implement `Encode` for, and any further arguments are
/// used as type parameters for the type.
///
/// # Example
/// ```
/// impl Message for Object { }
/// encode_message_impl!("@", Object)
///
/// impl<T> Message for Array<T> { }
/// encode_message_impl!("@", Array, T)
/// ```
#[macro_export]
macro_rules! encode_message_impl {
    ($code:expr, $name:ident) => (
        encode_message_impl!($code, $name,);
    );
    ($code:expr, $name:ident, $($t:ident),*) => (
        impl<'a $(, $t)*> $crate::Encode for &'a $name<$($t),*> {
            fn code() -> $crate::Encoding<&'a $name<$($t),*>> {
                $crate::Encoding($code)
            }
        }

        impl<'a $(, $t)*> $crate::Encode for &'a mut $name<$($t),*> {
            fn code() -> $crate::Encoding<&'a mut $name<$($t),*>> {
                $crate::Encoding($code)
            }
        }

        impl<'a $(, $t)*> $crate::Encode for Option<&'a $name<$($t),*>> {
            fn code() -> $crate::Encoding<Option<&'a $name<$($t),*>>> {
                $crate::Encoding($code)
            }
        }

        impl<'a $(, $t)*> $crate::Encode for Option<&'a mut $name<$($t),*>> {
            fn code() -> $crate::Encoding<Option<&'a mut $name<$($t),*>>> {
                $crate::Encoding($code)
            }
        }

        impl<$($t),*> $crate::Encode for *const $name<$($t),*> {
            fn code() -> $crate::Encoding<*const $name<$($t),*>> {
                $crate::Encoding($code)
            }
        }

        impl<$($t),*> $crate::Encode for *mut $name<$($t),*> {
            fn code() -> $crate::Encoding<*mut $name<$($t),*>> {
                $crate::Encoding($code)
            }
        }
    );
}

/// Declares a method, returning a `MethodDecl`.
/// The syntax is a combination of Objective-C's syntax and Rust's:
///
/// * The first part is the type and name of the self variable for the method
/// followed by a comma, like: `(&MyObject)this,`.
/// * Then, the parts of the selector and arguments follow, separated by commas,
/// like `setArg1:(uint)arg1, arg2:(uint)arg2`.
/// * After this, if the method has a return type, it should be followed by an
/// arrow ("->"), otherwise it should be terminated by a semicolon.
/// * Then a block declares the implementation of the method using the provided
/// arguments.
///
/// # Example
/// ```
/// method!(
///     (&mut MYObject)this, setNumber:(uint)number; {
///         this.set_number(number);
///     }
/// )
///
/// method!(
///     (&MYObject)this, number -> uint, {
///         this.number()
///     }
/// )
/// ```
#[macro_export]
macro_rules! method {
    // Void no arguments
    (
        ($self_ty:ty)$self_name:ident,
        $name:ident
        ; $body:block
    ) => ({
        method!(-$name,; stringify!($name), $body, (), $self_name: $self_ty,)
    });
    // No arguments
    (
        ($self_ty:ty)$self_name:ident,
        $name:ident
        -> $ret_ty:ty, $body:block
    ) => ({
        method!(-$name,; stringify!($name), $body, $ret_ty, $self_name: $self_ty,)
    });
    // Void with arguments
    (
        ($self_ty:ty)$self_name:ident,
        $($name:ident : ($arg_ty:ty) $arg_name:ident),+
        ; $body:block
    ) => ({
        let sel_name = concat!($(stringify!($name), ':'),*);
        method!($(-$name,)+; sel_name, $body, (), $self_name: $self_ty, $($arg_name: $arg_ty),+)
    });
    // Arguments
    (
        ($self_ty:ty)$self_name:ident,
        $($name:ident : ($arg_ty:ty) $arg_name:ident),+
        -> $ret_ty:ty, $body:block
    ) => ({
        let sel_name = concat!($(stringify!($name), ':'),*);
        method!($(-$name,)+; sel_name, $body, $ret_ty, $self_name: $self_ty, $($arg_name: $arg_ty),+)
    });
    (
        // Preceding dash is necessary to disambiguate
        -$first_name:ident, $(-$next_name:ident,)*;
        $sel_name:expr, $body:block, $ret_ty:ty,
        $self_name:ident : $self_ty:ty, $($arg_name:ident : $arg_ty:ty),*
    ) => ({
        let sel = $crate::runtime::Sel::register($sel_name);

        #[allow(non_snake_case)]
        extern fn $first_name($self_name: $self_ty, _cmd: $crate::runtime::Sel $(, $arg_name: $arg_ty)*) -> $ret_ty $body
        let imp: $crate::runtime::Imp = unsafe { ::std::mem::transmute($first_name) };

        let mut types = $crate::encode::<$ret_ty>().to_string();
        types.push_str($crate::encode::<$self_ty>());
        types.push_str($crate::encode::<$crate::runtime::Sel>());
        $(types.push_str($crate::encode::<$arg_ty>());)*

        $crate::MethodDecl { sel: sel, imp: imp, types: types }
    });
}
<commit_msg>Added sel! macro.<commit_after>/// Registers a selector, returning an `Sel`.
///
/// # Example
/// ```
/// let sel = sel!(description);
/// let sel = sel!(setObject:forKey:);
/// ```
#[macro_export]
macro_rules! sel {
    ($name:ident) => ({
        let sel_name = concat!(stringify!($name), '\0');
        $crate::runtime::sel_registerName(sel_name.as_ptr() as *const i8)
    });
    ($($name:ident :)+) => ({
        let sel_name = concat!($(stringify!($name), ':'),+, '\0');
        $crate::runtime::sel_registerName(sel_name.as_ptr() as *const i8)
    });
}

/// Sends a message to an object. The first argument should implement the
/// `ToMessage` trait, and the syntax is similar to the message syntax in
/// Objective-C.
///
/// Variadic arguments are not currently supported. This macro should only be
/// used in cases where `objc_msgSend` would be used, as opposed to
/// `objc_msgSend_stret` or `objc_msgSend_fpret`.
/// For more information, see Apple's documenation:
/// https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ObjCRuntimeRef/index.html#//apple_ref/doc/uid/TP40001418-CH1g-88778
///
/// # Example
/// ```
/// let description = msg_send![obj, description];
/// msg_send![obj, setArg1:1u arg2:2u];
/// ```
#[macro_export]
macro_rules! msg_send {
    ($obj:expr, $name:ident) => ({
        let sel = sel!($name);
        let ptr = $crate::to_obj_ptr(&$obj);
        $crate::runtime::objc_msgSend(ptr, sel)
    });
    ($obj:expr, $($name:ident : $arg:expr)+) => ({
        let sel = sel!($($name:)+);
        let ptr = $crate::to_obj_ptr(&$obj);
        $crate::runtime::objc_msgSend(ptr, sel $(,$arg)+)
    });
}

/// Implements the `Encode` trait for a `Message` type.
/// Specifically, this will implement `Encode` for reference, pointers, and
/// `Option` references of the given type.
///
/// The first argument should be a static string that is the type encoding
/// to use in the implementation. The second argument is the ident of the name
/// of the type to implement `Encode` for, and any further arguments are
/// used as type parameters for the type.
///
/// # Example
/// ```
/// impl Message for Object { }
/// encode_message_impl!("@", Object)
///
/// impl<T> Message for Array<T> { }
/// encode_message_impl!("@", Array, T)
/// ```
#[macro_export]
macro_rules! encode_message_impl {
    ($code:expr, $name:ident) => (
        encode_message_impl!($code, $name,);
    );
    ($code:expr, $name:ident, $($t:ident),*) => (
        impl<'a $(, $t)*> $crate::Encode for &'a $name<$($t),*> {
            fn code() -> $crate::Encoding<&'a $name<$($t),*>> {
                $crate::Encoding($code)
            }
        }

        impl<'a $(, $t)*> $crate::Encode for &'a mut $name<$($t),*> {
            fn code() -> $crate::Encoding<&'a mut $name<$($t),*>> {
                $crate::Encoding($code)
            }
        }

        impl<'a $(, $t)*> $crate::Encode for Option<&'a $name<$($t),*>> {
            fn code() -> $crate::Encoding<Option<&'a $name<$($t),*>>> {
                $crate::Encoding($code)
            }
        }

        impl<'a $(, $t)*> $crate::Encode for Option<&'a mut $name<$($t),*>> {
            fn code() -> $crate::Encoding<Option<&'a mut $name<$($t),*>>> {
                $crate::Encoding($code)
            }
        }

        impl<$($t),*> $crate::Encode for *const $name<$($t),*> {
            fn code() -> $crate::Encoding<*const $name<$($t),*>> {
                $crate::Encoding($code)
            }
        }

        impl<$($t),*> $crate::Encode for *mut $name<$($t),*> {
            fn code() -> $crate::Encoding<*mut $name<$($t),*>> {
                $crate::Encoding($code)
            }
        }
    );
}

/// Declares a method, returning a `MethodDecl`.
/// The syntax is a combination of Objective-C's syntax and Rust's:
///
/// * The first part is the type and name of the self variable for the method
/// followed by a comma, like: `(&MyObject)this,`.
/// * Then, the parts of the selector and arguments follow, separated by commas,
/// like `setArg1:(uint)arg1, arg2:(uint)arg2`.
/// * After this, if the method has a return type, it should be followed by an
/// arrow ("->"), otherwise it should be terminated by a semicolon.
/// * Then a block declares the implementation of the method using the provided
/// arguments.
///
/// # Example
/// ```
/// method!(
///     (&mut MYObject)this, setNumber:(uint)number; {
///         this.set_number(number);
///     }
/// )
///
/// method!(
///     (&MYObject)this, number -> uint, {
///         this.number()
///     }
/// )
/// ```
#[macro_export]
macro_rules! method {
    // Void no arguments
    (
        ($self_ty:ty)$self_name:ident,
        $name:ident
        ; $body:block
    ) => ({
        method!(-$name,; stringify!($name), $body, (), $self_name: $self_ty,)
    });
    // No arguments
    (
        ($self_ty:ty)$self_name:ident,
        $name:ident
        -> $ret_ty:ty, $body:block
    ) => ({
        method!(-$name,; stringify!($name), $body, $ret_ty, $self_name: $self_ty,)
    });
    // Void with arguments
    (
        ($self_ty:ty)$self_name:ident,
        $($name:ident : ($arg_ty:ty) $arg_name:ident),+
        ; $body:block
    ) => ({
        let sel_name = concat!($(stringify!($name), ':'),*);
        method!($(-$name,)+; sel_name, $body, (), $self_name: $self_ty, $($arg_name: $arg_ty),+)
    });
    // Arguments
    (
        ($self_ty:ty)$self_name:ident,
        $($name:ident : ($arg_ty:ty) $arg_name:ident),+
        -> $ret_ty:ty, $body:block
    ) => ({
        let sel_name = concat!($(stringify!($name), ':'),*);
        method!($(-$name,)+; sel_name, $body, $ret_ty, $self_name: $self_ty, $($arg_name: $arg_ty),+)
    });
    (
        // Preceding dash is necessary to disambiguate
        -$first_name:ident, $(-$next_name:ident,)*;
        $sel_name:expr, $body:block, $ret_ty:ty,
        $self_name:ident : $self_ty:ty, $($arg_name:ident : $arg_ty:ty),*
    ) => ({
        let sel = $crate::runtime::Sel::register($sel_name);

        #[allow(non_snake_case)]
        extern fn $first_name($self_name: $self_ty, _cmd: $crate::runtime::Sel $(, $arg_name: $arg_ty)*) -> $ret_ty $body
        let imp: $crate::runtime::Imp = unsafe { ::std::mem::transmute($first_name) };

        let mut types = $crate::encode::<$ret_ty>().to_string();
        types.push_str($crate::encode::<$self_ty>());
        types.push_str($crate::encode::<$crate::runtime::Sel>());
        $(types.push_str($crate::encode::<$arg_ty>());)*

        $crate::MethodDecl { sel: sel, imp: imp, types: types }
    });
}
<|endoftext|>