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

// Handles invoking external binaries.
// This module assumes that, for a given machine, there is only one place
// where the desired executable might be installed. It expects the engine
// to identify that place at its initialization by invoking verify_binaries(),
// and to exit immediately if verify_binaries() return an error. If this
// protocol is followed then when any command is executed the unique absolute
// path of the binary for this machine will already have been identified.
// However stratisd may run for a while and it is possible for the binary
// to be caused to be uninstalled while stratisd is being run. Therefore,
// the existence of the file is checked before the command is invoked, and
// an explicit error is returned if the executable can not be found.

use std::{
    collections::HashMap,
    path::{Path, PathBuf},
    process::Command,
};

use uuid::Uuid;

use crate::stratis::{StratisError, StratisResult};

/// Find the binary with the given name by looking in likely locations.
/// Return None if no binary was found.
/// Search an explicit list of directories rather than the user's PATH
/// environment variable. stratisd may be running when there is no PATH
/// variable set.
fn find_binary(name: &str) -> Option<PathBuf> {
    ["/usr/sbin", "/sbin", "/usr/bin", "/bin"]
        .iter()
        .map(|pre| [pre, name].iter().collect::<PathBuf>())
        .find(|path| path.exists())
}

// These are the external binaries that stratisd relies on.
// Any change in this list requires a corresponding change to BINARIES,
// and vice-versa.
const MKFS_XFS: &str = "mkfs.xfs";
const THIN_CHECK: &str = "thin_check";
const THIN_REPAIR: &str = "thin_repair";
const UDEVADM: &str = "udevadm";
const XFS_DB: &str = "xfs_db";
const XFS_GROWFS: &str = "xfs_growfs";

lazy_static! {
    static ref BINARIES: HashMap<String, Option<PathBuf>> = [
        (MKFS_XFS.to_string(), find_binary(MKFS_XFS)),
        (THIN_CHECK.to_string(), find_binary(THIN_CHECK)),
        (THIN_REPAIR.to_string(), find_binary(THIN_REPAIR)),
        (UDEVADM.to_string(), find_binary(UDEVADM)),
        (XFS_DB.to_string(), find_binary(XFS_DB)),
        (XFS_GROWFS.to_string(), find_binary(XFS_GROWFS)),
    ]
    .iter()
    .cloned()
    .collect();
}

/// Verify that all binaries that the engine might invoke are available at some
/// path. Return an error if any are missing. Required to be called on engine
/// initialization.
pub fn verify_binaries() -> StratisResult<()> {
    match BINARIES.iter().find(|&(_, ref path)| path.is_none()) {
        None => Ok(()),
        Some((ref name, _)) => Err(StratisError::Error(format!(
            "Unable to find absolute path for \"{}\"",
            name
        ))),
    }
}

/// Invoke the specified command. Return an error if invoking the command
/// fails or if the command itself fails.
fn execute_cmd(cmd: &mut Command) -> StratisResult<()> {
    match cmd.output() {
        Err(err) => Err(StratisError::Error(format!(
            "Failed to execute command {:?}, err: {:?}",
            cmd, err
        ))),
        Ok(result) => {
            if result.status.success() {
                Ok(())
            } else {
                let exit_reason = result
                    .status
                    .code()
                    .map_or(String::from("process terminated by signal"), |ec| {
                        ec.to_string()
                    });
                let std_out_txt = String::from_utf8_lossy(&result.stdout);
                let std_err_txt = String::from_utf8_lossy(&result.stderr);
                let err_msg = format!(
                    "Command failed: cmd: {:?}, exit reason: {} stdout: {} stderr: {}",
                    cmd, exit_reason, std_out_txt, std_err_txt
                );
                Err(StratisError::Error(err_msg))
            }
        }
    }
}

/// Get an absolute path for the executable with the given name.
/// Precondition: verify_binaries() has already been invoked.
fn get_executable(name: &str) -> &Path {
    BINARIES
        .get(name)
        .expect("name arguments are all constants defined with BINARIES, lookup can not fail")
        .as_ref()
        .expect("verify_binaries() was previously called and returned no error")
}

/// Create a filesystem on devnode.
pub fn create_fs(devnode: &Path, uuid: Uuid) -> StratisResult<()> {
    execute_cmd(
        Command::new(get_executable(MKFS_XFS).as_os_str())
            .arg("-f")
            .arg("-q")
            .arg(&devnode)
            .arg("-m")
            .arg(format!("uuid={}", uuid)),
    )
}

/// Use the xfs_growfs command to expand a filesystem mounted at the given
/// mount point.
pub fn xfs_growfs(mount_point: &Path) -> StratisResult<()> {
    execute_cmd(
        Command::new(get_executable(XFS_GROWFS).as_os_str())
            .arg(mount_point)
            .arg("-d"),
    )
}

/// Set a new UUID for filesystem on the devnode.
pub fn set_uuid(devnode: &Path, uuid: Uuid) -> StratisResult<()> {
    execute_cmd(
        Command::new(get_executable(XFS_DB).as_os_str())
            .arg("-x")
            .arg(format!("-c uuid {}", uuid))
            .arg(&devnode),
    )
}

/// Call thin_check on a thinpool
pub fn thin_check(devnode: &Path) -> StratisResult<()> {
    execute_cmd(
        Command::new(get_executable(THIN_CHECK).as_os_str())
            .arg("-q")
            .arg(devnode),
    )
}

/// Call thin_repair on a thinpool
pub fn thin_repair(meta_dev: &Path, new_meta_dev: &Path) -> StratisResult<()> {
    execute_cmd(
        Command::new(get_executable(THIN_REPAIR).as_os_str())
            .arg("-i")
            .arg(meta_dev)
            .arg("-o")
            .arg(new_meta_dev),
    )
}

/// Call udevadm settle
pub fn udev_settle() -> StratisResult<()> {
    execute_cmd(Command::new(get_executable(UDEVADM).as_os_str()).arg("settle"))
}

#[cfg(test)]
pub fn create_ext3_fs(devnode: &Path) -> StratisResult<()> {
    execute_cmd(Command::new("wipefs").arg("-a").arg(&devnode))?;
    execute_cmd(Command::new("mkfs.ext3").arg(&devnode))
}

#[cfg(test)]
#[allow(dead_code)]
pub fn xfs_repair(devnode: &Path) -> StratisResult<()> {
    execute_cmd(Command::new("xfs_repair").arg("-n").arg(&devnode))
}
<commit_msg>Make more understandable error message<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

// Handles invoking external binaries.
// This module assumes that, for a given machine, there is only one place
// where the desired executable might be installed. It expects the engine
// to identify that place at its initialization by invoking verify_binaries(),
// and to exit immediately if verify_binaries() return an error. If this
// protocol is followed then when any command is executed the unique absolute
// path of the binary for this machine will already have been identified.
// However stratisd may run for a while and it is possible for the binary
// to be caused to be uninstalled while stratisd is being run. Therefore,
// the existence of the file is checked before the command is invoked, and
// an explicit error is returned if the executable can not be found.

use std::{
    collections::HashMap,
    path::{Path, PathBuf},
    process::Command,
};

use uuid::Uuid;

use crate::stratis::{StratisError, StratisResult};

const BINARIES_PATHS: [&str; 4] = ["/usr/sbin", "/sbin", "/usr/bin", "/bin"];

/// Find the binary with the given name by looking in likely locations.
/// Return None if no binary was found.
/// Search an explicit list of directories rather than the user's PATH
/// environment variable. stratisd may be running when there is no PATH
/// variable set.
fn find_binary(name: &str) -> Option<PathBuf> {
    BINARIES_PATHS
        .iter()
        .map(|pre| [pre, name].iter().collect::<PathBuf>())
        .find(|path| path.exists())
}

// These are the external binaries that stratisd relies on.
// Any change in this list requires a corresponding change to BINARIES,
// and vice-versa.
const MKFS_XFS: &str = "mkfs.xfs";
const THIN_CHECK: &str = "thin_check";
const THIN_REPAIR: &str = "thin_repair";
const UDEVADM: &str = "udevadm";
const XFS_DB: &str = "xfs_db";
const XFS_GROWFS: &str = "xfs_growfs";

lazy_static! {
    static ref BINARIES: HashMap<String, Option<PathBuf>> = [
        (MKFS_XFS.to_string(), find_binary(MKFS_XFS)),
        (THIN_CHECK.to_string(), find_binary(THIN_CHECK)),
        (THIN_REPAIR.to_string(), find_binary(THIN_REPAIR)),
        (UDEVADM.to_string(), find_binary(UDEVADM)),
        (XFS_DB.to_string(), find_binary(XFS_DB)),
        (XFS_GROWFS.to_string(), find_binary(XFS_GROWFS)),
    ]
    .iter()
    .cloned()
    .collect();
}

/// Verify that all binaries that the engine might invoke are available at some
/// path. Return an error if any are missing. Required to be called on engine
/// initialization.
pub fn verify_binaries() -> StratisResult<()> {
    match BINARIES.iter().find(|&(_, ref path)| path.is_none()) {
        None => Ok(()),
        Some((ref name, _)) => Err(StratisError::Error(format!(
            "Unable to find executable \"{}\" in any of {}",
            name,
            BINARIES_PATHS
                .iter()
                .map(|p| format!("\"{}\"", p))
                .collect::<Vec<_>>()
                .join(", "),
        ))),
    }
}

/// Invoke the specified command. Return an error if invoking the command
/// fails or if the command itself fails.
fn execute_cmd(cmd: &mut Command) -> StratisResult<()> {
    match cmd.output() {
        Err(err) => Err(StratisError::Error(format!(
            "Failed to execute command {:?}, err: {:?}",
            cmd, err
        ))),
        Ok(result) => {
            if result.status.success() {
                Ok(())
            } else {
                let exit_reason = result
                    .status
                    .code()
                    .map_or(String::from("process terminated by signal"), |ec| {
                        ec.to_string()
                    });
                let std_out_txt = String::from_utf8_lossy(&result.stdout);
                let std_err_txt = String::from_utf8_lossy(&result.stderr);
                let err_msg = format!(
                    "Command failed: cmd: {:?}, exit reason: {} stdout: {} stderr: {}",
                    cmd, exit_reason, std_out_txt, std_err_txt
                );
                Err(StratisError::Error(err_msg))
            }
        }
    }
}

/// Get an absolute path for the executable with the given name.
/// Precondition: verify_binaries() has already been invoked.
fn get_executable(name: &str) -> &Path {
    BINARIES
        .get(name)
        .expect("name arguments are all constants defined with BINARIES, lookup can not fail")
        .as_ref()
        .expect("verify_binaries() was previously called and returned no error")
}

/// Create a filesystem on devnode.
pub fn create_fs(devnode: &Path, uuid: Uuid) -> StratisResult<()> {
    execute_cmd(
        Command::new(get_executable(MKFS_XFS).as_os_str())
            .arg("-f")
            .arg("-q")
            .arg(&devnode)
            .arg("-m")
            .arg(format!("uuid={}", uuid)),
    )
}

/// Use the xfs_growfs command to expand a filesystem mounted at the given
/// mount point.
pub fn xfs_growfs(mount_point: &Path) -> StratisResult<()> {
    execute_cmd(
        Command::new(get_executable(XFS_GROWFS).as_os_str())
            .arg(mount_point)
            .arg("-d"),
    )
}

/// Set a new UUID for filesystem on the devnode.
pub fn set_uuid(devnode: &Path, uuid: Uuid) -> StratisResult<()> {
    execute_cmd(
        Command::new(get_executable(XFS_DB).as_os_str())
            .arg("-x")
            .arg(format!("-c uuid {}", uuid))
            .arg(&devnode),
    )
}

/// Call thin_check on a thinpool
pub fn thin_check(devnode: &Path) -> StratisResult<()> {
    execute_cmd(
        Command::new(get_executable(THIN_CHECK).as_os_str())
            .arg("-q")
            .arg(devnode),
    )
}

/// Call thin_repair on a thinpool
pub fn thin_repair(meta_dev: &Path, new_meta_dev: &Path) -> StratisResult<()> {
    execute_cmd(
        Command::new(get_executable(THIN_REPAIR).as_os_str())
            .arg("-i")
            .arg(meta_dev)
            .arg("-o")
            .arg(new_meta_dev),
    )
}

/// Call udevadm settle
pub fn udev_settle() -> StratisResult<()> {
    execute_cmd(Command::new(get_executable(UDEVADM).as_os_str()).arg("settle"))
}

#[cfg(test)]
pub fn create_ext3_fs(devnode: &Path) -> StratisResult<()> {
    execute_cmd(Command::new("wipefs").arg("-a").arg(&devnode))?;
    execute_cmd(Command::new("mkfs.ext3").arg(&devnode))
}

#[cfg(test)]
#[allow(dead_code)]
pub fn xfs_repair(devnode: &Path) -> StratisResult<()> {
    execute_cmd(Command::new("xfs_repair").arg("-n").arg(&devnode))
}
<|endoftext|>


<commit_before>// error-pattern:&& cannot be applied to type `int`

fn main() { let x = 1 && 2; }
<commit_msg>Adding `i` suffixes so cfail tests keep failing after suffix inference<commit_after>// error-pattern:&& cannot be applied to type `int`

fn main() { let x = 1i && 2i; }
<|endoftext|>


<commit_before>// Copyright 2017 The xi-editor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Very basic syntax detection.

use std::borrow::Borrow;
use std::collections::{BTreeMap, HashMap};
use std::path::Path;
use std::sync::Arc;

use crate::config::Table;

/// The canonical identifier for a particular `LanguageDefinition`.
#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct LanguageId(Arc<String>);

/// Describes a `LanguageDefinition`. Although these are provided by plugins,
/// they are a fundamental concept in core, used to determine things like
/// plugin activations and active user config tables.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LanguageDefinition {
    pub name: LanguageId,
    pub extensions: Vec<String>,
    pub first_line_match: Option<String>,
    pub scope: String,
    #[serde(skip)]
    pub default_config: Option<Table>,
}

/// A repository of all loaded `LanguageDefinition`s.
#[derive(Debug, Default)]
pub struct Languages {
    // NOTE: BTreeMap is used for sorting the languages by name alphabetically
    named: BTreeMap<LanguageId, Arc<LanguageDefinition>>,
    extensions: HashMap<String, Arc<LanguageDefinition>>,
}

impl Languages {
    pub fn new(language_defs: &[LanguageDefinition]) -> Self {
        let mut named = BTreeMap::new();
        let mut extensions = HashMap::new();
        for lang in language_defs.iter() {
            let lang_arc = Arc::new(lang.clone());
            named.insert(lang.name.clone(), lang_arc.clone());
            for ext in &lang.extensions {
                extensions.insert(ext.clone(), lang_arc.clone());
            }
        }
        Languages { named, extensions }
    }

    pub fn language_for_path(&self, path: &Path) -> Option<Arc<LanguageDefinition>> {
        match path.extension() {
            Some(_) => path
                .extension()
                .and_then(|ext| self.extensions.get(ext.to_str().unwrap_or_default()))
                .map(Arc::clone),
            None => path
                .file_name()
                .and_then(|name| self.extensions.get(name.to_str().unwrap_or_default()))
                .map(Arc::clone),
        }
    }

    pub fn language_for_name<S>(&self, name: S) -> Option<Arc<LanguageDefinition>>
    where
        S: AsRef<str>,
    {
        self.named.get(name.as_ref()).map(Arc::clone)
    }

    /// Returns a Vec of any `LanguageDefinition`s which exist
    /// in `self` but not `other`.
    pub fn difference(&self, other: &Languages) -> Vec<Arc<LanguageDefinition>> {
        self.named
            .iter()
            .filter(|(k, _)| !other.named.contains_key(*k))
            .map(|(_, v)| v.clone())
            .collect()
    }

    pub fn iter(&self) -> impl Iterator<Item = &Arc<LanguageDefinition>> {
        self.named.values()
    }
}

impl AsRef<str> for LanguageId {
    fn as_ref(&self) -> &str {
        self.0.as_ref()
    }
}

// let's us use &str to query a HashMap with `LanguageId` keys
impl Borrow<str> for LanguageId {
    fn borrow(&self) -> &str {
        &self.0.as_ref()
    }
}

impl<'a> From<&'a str> for LanguageId {
    fn from(src: &'a str) -> LanguageId {
        LanguageId(Arc::new(src.into()))
    }
}

// for testing
#[cfg(test)]
impl LanguageDefinition {
    pub(crate) fn simple(name: &str, exts: &[&str], scope: &str, config: Option<Table>) -> Self {
        LanguageDefinition {
            name: name.into(),
            extensions: exts.iter().map(|s| (*s).into()).collect(),
            first_line_match: None,
            scope: scope.into(),
            default_config: config,
        }
    }
}

// for testing
#[cfg(test)]
pub fn language_for_name() {}
<commit_msg>Write tests for : Syntax detection fails for git commit messages<commit_after>// Copyright 2017 The xi-editor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Very basic syntax detection.

use std::borrow::Borrow;
use std::collections::{BTreeMap, HashMap};
use std::path::Path;
use std::sync::Arc;

use crate::config::Table;

/// The canonical identifier for a particular `LanguageDefinition`.
#[derive(Debug, Default, Clone, Serialize, Deserialize, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct LanguageId(Arc<String>);

/// Describes a `LanguageDefinition`. Although these are provided by plugins,
/// they are a fundamental concept in core, used to determine things like
/// plugin activations and active user config tables.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LanguageDefinition {
    pub name: LanguageId,
    pub extensions: Vec<String>,
    pub first_line_match: Option<String>,
    pub scope: String,
    #[serde(skip)]
    pub default_config: Option<Table>,
}

/// A repository of all loaded `LanguageDefinition`s.
#[derive(Debug, Default)]
pub struct Languages {
    // NOTE: BTreeMap is used for sorting the languages by name alphabetically
    named: BTreeMap<LanguageId, Arc<LanguageDefinition>>,
    extensions: HashMap<String, Arc<LanguageDefinition>>,
}

impl Languages {
    pub fn new(language_defs: &[LanguageDefinition]) -> Self {
        let mut named = BTreeMap::new();
        let mut extensions = HashMap::new();
        for lang in language_defs.iter() {
            let lang_arc = Arc::new(lang.clone());
            named.insert(lang.name.clone(), lang_arc.clone());
            for ext in &lang.extensions {
                extensions.insert(ext.clone(), lang_arc.clone());
            }
        }
        Languages { named, extensions }
    }

    pub fn language_for_path(&self, path: &Path) -> Option<Arc<LanguageDefinition>> {
        path.extension()
            .or_else(|| path.file_name())
            .and_then(|ext| self.extensions.get(ext.to_str().unwrap_or_default()))
            .map(Arc::clone)
    }

    pub fn language_for_name<S>(&self, name: S) -> Option<Arc<LanguageDefinition>>
    where
        S: AsRef<str>,
    {
        self.named.get(name.as_ref()).map(Arc::clone)
    }

    /// Returns a Vec of any `LanguageDefinition`s which exist
    /// in `self` but not `other`.
    pub fn difference(&self, other: &Languages) -> Vec<Arc<LanguageDefinition>> {
        self.named
            .iter()
            .filter(|(k, _)| !other.named.contains_key(*k))
            .map(|(_, v)| v.clone())
            .collect()
    }

    pub fn iter(&self) -> impl Iterator<Item = &Arc<LanguageDefinition>> {
        self.named.values()
    }
}

impl AsRef<str> for LanguageId {
    fn as_ref(&self) -> &str {
        self.0.as_ref()
    }
}

// let's us use &str to query a HashMap with `LanguageId` keys
impl Borrow<str> for LanguageId {
    fn borrow(&self) -> &str {
        &self.0.as_ref()
    }
}

impl<'a> From<&'a str> for LanguageId {
    fn from(src: &'a str) -> LanguageId {
        LanguageId(Arc::new(src.into()))
    }
}

// for testing
#[cfg(test)]
impl LanguageDefinition {
    pub(crate) fn simple(name: &str, exts: &[&str], scope: &str, config: Option<Table>) -> Self {
        LanguageDefinition {
            name: name.into(),
            extensions: exts.iter().map(|s| (*s).into()).collect(),
            first_line_match: None,
            scope: scope.into(),
            default_config: config,
        }
    }
}

// for testing
#[cfg(test)]
pub fn language_for_name() {}

#[cfg(test)]
pub fn language_for_path() {
    let ld_rust = LanguageDefinition {
        name: LanguageId::from("Rust"),
        extensions: vec![String::from("rs")],
        scope: String::from("source.rust"),
        first_line_match: None,
        default_config: None,
    };
    let ld_commit_msg = LanguageDefinition {
        name: LanguageId::from("Git Commit"),
        extensions: vec![
            String::from("COMMIT_EDITMSG"),
            String::from("MERGE_MSG"),
            String::from("TAG_EDITMSG"),
        ],
        scope: String::from("text.git.commit"),
        first_line_match: None,
        default_config: None,
    };
    let languages = Languages::new(&[ld_rust.clone(), ld_commit_msg.clone()]);

    assert_eq!(ld_rust.name, languages.language_for_path(Path::new("/path/test.rs")).unwrap().name);
    assert_eq!(
        ld_commit_msg.name,
        languages.language_for_path(Path::new("/path/COMMIT_EDITMSG")).unwrap().name
    );
    assert_eq!(
        ld_commit_msg.name,
        languages.language_for_path(Path::new("/path/MERGE_MSG")).unwrap().name
    );
    assert_eq!(
        ld_commit_msg.name,
        languages.language_for_path(Path::new("/path/TAG_EDITMSG")).unwrap().name
    );
}
<|endoftext|>


<commit_before>#[derive(Clone, Copy, PartialEq)]
#[repr(u8)]
enum Token {
    Mine = b'*',
    Empty = b' ',
}

impl Into<char> for Token {
    fn into(self) -> char {
        self as u8 as char
    }
}

impl Token {
    fn from(c: char) -> Result<Token, ()> {
        match c {
            '*' => Ok(Token::Mine),
            ' ' => Ok(Token::Empty),
            _ => Err(()),
        }
    }
}

struct Board {
    field: Vec<Vec<Token>>,
}

impl Board {
    fn new(minefield: &[&str]) -> Self {
        let field = minefield
            .iter()
            .map(|row| row.chars().map(|char| Token::from(char).unwrap()).collect())
            .collect();
        Board { field }
    }

    fn annotate(&self) -> Vec<String> {
        let annotated: Vec<String> = self
            .field
            .iter()
            .enumerate()
            .map(|(row, _)| self.annotate_row(row))
            .collect();
        annotated
    }

    fn annotate_row(&self, y: usize) -> String {
        let row = &self.field[y];
        let annotated_row = row
            .iter()
            .enumerate()
            .map(|(x, token)| match token {
                Token::Mine => Token::Mine.into(),
                Token::Empty => {
                    let neighbor_mines = self.num_neighbor_mines(y as u32, x as u32);
                    if neighbor_mines == 0 {
                        return ' ';
                    } else {
                        return (b'0' + neighbor_mines as u8) as char;
                    };
                }
            })
            .collect();

        annotated_row
    }

    fn num_neighbor_mines(&self, y: u32, x: u32) -> usize {
        return self
            .get_neighbors(y, x)
            .iter()
            .filter(|neighbor| neighbor == &&&Token::Mine)
            .count();
    }

    fn get_neighbors(&self, y: u32, x: u32) -> Vec<&Token> {
        let mut neighbors = Vec::new();
        let y = y as i32;
        let x = x as i32;

        let delta_ys: Vec<i32> = (-1..=1).collect();
        for delta_y in delta_ys {
            let delta_xs: Vec<i32> = (-1..=1).collect();
            for delta_x in delta_xs {
                if delta_y == 0 && delta_x == 0 {
                    continue;
                }
                if y + delta_y < 0 || y + delta_y >= self.num_rows() as i32 {
                    continue;
                }
                if x + delta_x < 0 || x + delta_x >= self.num_cols() as i32 {
                    continue;
                }
                let neighbor = &self.field[(y + delta_y) as usize][(x + delta_x) as usize];
                neighbors.push(neighbor)
            }
        }

        neighbors
    }

    fn num_rows(&self) -> usize {
        return self.field.len();
    }

    fn num_cols(&self) -> usize {
        return self.field[0].len();
    }
}

pub fn annotate(minefield: &[&str]) -> Vec<String> {
    let board = Board::new(minefield);
    return board.annotate();
}
<commit_msg>Extract annotate_token<commit_after>#[derive(Clone, Copy, PartialEq)]
#[repr(u8)]
enum Token {
    Mine = b'*',
    Empty = b' ',
}

impl Into<char> for Token {
    fn into(self) -> char {
        self as u8 as char
    }
}

impl Token {
    fn from(c: char) -> Result<Token, ()> {
        match c {
            '*' => Ok(Token::Mine),
            ' ' => Ok(Token::Empty),
            _ => Err(()),
        }
    }
}

struct Board {
    field: Vec<Vec<Token>>,
}

impl Board {
    fn new(minefield: &[&str]) -> Self {
        let field = minefield
            .iter()
            .map(|row| row.chars().map(|char| Token::from(char).unwrap()).collect())
            .collect();
        Board { field }
    }

    fn annotate(&self) -> Vec<String> {
        return self
            .field
            .iter()
            .enumerate()
            .map(|(row, _)| self.annotate_row(row))
            .collect();
    }

    fn annotate_row(&self, y: usize) -> String {
        let row = &self.field[y];
        return row
            .iter()
            .enumerate()
            .map(|(x, _)| self.annotate_token(y, x))
            .collect();
    }

    fn annotate_token(&self, y: usize, x: usize) -> char {
        let token = self.field[y][x];
        match token {
            Token::Mine => Token::Mine.into(),
            Token::Empty => {
                let neighbor_mines = self.num_neighbor_mines(y as u32, x as u32);
                if neighbor_mines == 0 {
                    return ' ';
                } else {
                    return (b'0' + neighbor_mines as u8) as char;
                };
            }
        }
    }

    fn num_neighbor_mines(&self, y: u32, x: u32) -> usize {
        return self
            .get_neighbors(y, x)
            .iter()
            .filter(|neighbor| neighbor == &&&Token::Mine)
            .count();
    }

    fn get_neighbors(&self, y: u32, x: u32) -> Vec<&Token> {
        let mut neighbors = Vec::new();
        let y = y as i32;
        let x = x as i32;

        let delta_ys: Vec<i32> = (-1..=1).collect();
        for delta_y in delta_ys {
            let delta_xs: Vec<i32> = (-1..=1).collect();
            for delta_x in delta_xs {
                if delta_y == 0 && delta_x == 0 {
                    continue;
                }
                if y + delta_y < 0 || y + delta_y >= self.num_rows() as i32 {
                    continue;
                }
                if x + delta_x < 0 || x + delta_x >= self.num_cols() as i32 {
                    continue;
                }
                let neighbor = &self.field[(y + delta_y) as usize][(x + delta_x) as usize];
                neighbors.push(neighbor)
            }
        }

        neighbors
    }

    fn num_rows(&self) -> usize {
        return self.field.len();
    }

    fn num_cols(&self) -> usize {
        return self.field[0].len();
    }
}

pub fn annotate(minefield: &[&str]) -> Vec<String> {
    let board = Board::new(minefield);
    return board.annotate();
}
<|endoftext|>


<commit_before>use walkdir::WalkDir;
use std::path::PathBuf;
use std::{env, fs};

fn main() {
    // The src directory (we are in src/tools/error_index_generator)
    // Note that we could skip one of the .. but this ensures we at least loosely find the right
    // directory.
    let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
    let dest = out_dir.join("error_codes.rs");
    let mut idx = 0;
    for entry in WalkDir::new("../../../src") {
        let entry = entry.unwrap();
        if entry.file_name() == "error_codes.rs" {
            println!("cargo:rerun-if-changed={}", entry.path().to_str().unwrap());
            let file = fs::read_to_string(entry.path()).unwrap()
                .replace("syntax::register_diagnostics!", "register_diagnostics!");
            let contents = format!("(|| {{\n{}\n}})();", file);

            fs::write(&out_dir.join(&format!("error_{}.rs", idx)), &contents).unwrap();

            idx += 1;
        }
    }

    let mut all = String::new();
    all.push_str(r###"
fn register_all() -> Vec<(&'static str, Option<&'static str>)> {
    let mut long_codes: Vec<(&'static str, Option<&'static str>)> = Vec::new();
    macro_rules! register_diagnostics {
        ($($ecode:ident: $message:expr,)*) => (
            register_diagnostics!{$($ecode:$message,)* ;}
        );

        ($($ecode:ident: $message:expr,)* ; $($code:ident,)*) => (
            $(
                {long_codes.extend([
                    (stringify!($ecode), Some(stringify!($message))),
                ].iter());}
            )*
            $(
                {long_codes.extend([
                    stringify!($code),
                ].iter().cloned().map(|s| (s, None)).collect::<Vec<_>>());}
            )*
        )
    }
"###);
    for idx in 0..idx {
        all.push_str(&format!(r#"include!(concat!(env!("OUT_DIR"), "/error_{}.rs"));"#, idx));
        all.push_str("\n");
    }
    all.push_str("\nlong_codes\n");
    all.push_str("}\n");

    fs::write(&dest, all).unwrap();
}
<commit_msg>Remove raw string literal quotes from error index descriptions<commit_after>use walkdir::WalkDir;
use std::path::PathBuf;
use std::{env, fs};

fn main() {
    // The src directory (we are in src/tools/error_index_generator)
    // Note that we could skip one of the .. but this ensures we at least loosely find the right
    // directory.
    let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
    let dest = out_dir.join("error_codes.rs");
    let mut idx = 0;
    for entry in WalkDir::new("../../../src") {
        let entry = entry.unwrap();
        if entry.file_name() == "error_codes.rs" {
            println!("cargo:rerun-if-changed={}", entry.path().to_str().unwrap());
            let file = fs::read_to_string(entry.path()).unwrap()
                .replace("syntax::register_diagnostics!", "register_diagnostics!");
            let contents = format!("(|| {{\n{}\n}})();", file);

            fs::write(&out_dir.join(&format!("error_{}.rs", idx)), &contents).unwrap();

            idx += 1;
        }
    }

    let mut all = String::new();
    all.push_str(r###"
fn register_all() -> Vec<(&'static str, Option<&'static str>)> {
    let mut long_codes: Vec<(&'static str, Option<&'static str>)> = Vec::new();
    macro_rules! register_diagnostics {
        ($($ecode:ident: $message:expr,)*) => (
            register_diagnostics!{$($ecode:$message,)* ;}
        );

        ($($ecode:ident: $message:expr,)* ; $($code:ident,)*) => (
            $(
                {long_codes.extend([
                    (stringify!($ecode), Some($message)),
                ].iter());}
            )*
            $(
                {long_codes.extend([
                    stringify!($code),
                ].iter().cloned().map(|s| (s, None)).collect::<Vec<_>>());}
            )*
        )
    }
"###);
    for idx in 0..idx {
        all.push_str(&format!(r#"include!(concat!(env!("OUT_DIR"), "/error_{}.rs"));"#, idx));
        all.push_str("\n");
    }
    all.push_str("\nlong_codes\n");
    all.push_str("}\n");

    fs::write(&dest, all).unwrap();
}
<|endoftext|>


<commit_before>use arm::Cycles;

use crate::{
    memory::io::{FifoChannel, IoRegisters},
    Gba,
};

#[derive(Default)]
pub struct GbaAudio {
    commands: Vec<Command>,
    last_update_time: u64,
}

impl GbaAudio {
    pub fn clear(&mut self) {
        self.commands.clear();
    }

    pub fn commands(&self) -> &[Command] {
        &self.commands
    }

    fn fifo_play(&mut self, chan: FifoChannel, ioregs: &mut IoRegisters, late: Cycles) {
        self.wait(ioregs.time, late);
        let sample = if chan == FifoChannel::A {
            ioregs.fifo_a.pop_sample()
        } else {
            ioregs.fifo_b.pop_sample()
        };
        self.commands.push(Command::PlaySample(chan, sample as i8));
    }

    fn wait(&mut self, now: u64, late: arm::Cycles) {
        if now > self.last_update_time {
            let elapsed =
                (now - self.last_update_time).saturating_sub(u32::from(late) as u64) as u32;
            log::debug!("writing sample after {elapsed} cycles");
            if let Some(Command::Wait(ref mut cycles)) = self.commands.last_mut() {
                *cycles += elapsed;
            } else {
                self.commands.push(Command::Wait(elapsed));
            }
        }
        self.last_update_time = now;
    }
}

pub fn check_fifo_timer_overflow(timer: usize, gba: &mut Gba, late: Cycles) {
    if gba.mem.ioregs.soundcnt_h.dma_enable(FifoChannel::A)
        && gba.mem.ioregs.soundcnt_h.dma_timer_select(FifoChannel::A) == timer
    {
        gba.audio
            .fifo_play(FifoChannel::A, &mut gba.mem.ioregs, late)
    }

    if gba.mem.ioregs.soundcnt_h.dma_enable(FifoChannel::B)
        && gba.mem.ioregs.soundcnt_h.dma_timer_select(FifoChannel::B) == timer
    {
        gba.audio
            .fifo_play(FifoChannel::B, &mut gba.mem.ioregs, late)
    }
}

#[derive(Clone, Copy, Debug)]
pub enum Command {
    Wait(u32),
    PlaySample(FifoChannel, i8),
}
<commit_msg>Remove debug message in sound wait<commit_after>use arm::Cycles;

use crate::{
    memory::io::{FifoChannel, IoRegisters},
    Gba,
};

#[derive(Default)]
pub struct GbaAudio {
    commands: Vec<Command>,
    last_update_time: u64,
}

impl GbaAudio {
    pub fn clear(&mut self) {
        self.commands.clear();
    }

    pub fn commands(&self) -> &[Command] {
        &self.commands
    }

    fn fifo_play(&mut self, chan: FifoChannel, ioregs: &mut IoRegisters, late: Cycles) {
        self.wait(ioregs.time, late);
        let sample = if chan == FifoChannel::A {
            ioregs.fifo_a.pop_sample()
        } else {
            ioregs.fifo_b.pop_sample()
        };
        self.commands.push(Command::PlaySample(chan, sample as i8));
    }

    fn wait(&mut self, now: u64, late: arm::Cycles) {
        if now > self.last_update_time {
            let elapsed =
                (now - self.last_update_time).saturating_sub(u32::from(late) as u64) as u32;
            if let Some(Command::Wait(ref mut cycles)) = self.commands.last_mut() {
                *cycles += elapsed;
            } else {
                self.commands.push(Command::Wait(elapsed));
            }
        }
        self.last_update_time = now;
    }
}

pub fn check_fifo_timer_overflow(timer: usize, gba: &mut Gba, late: Cycles) {
    if gba.mem.ioregs.soundcnt_h.dma_enable(FifoChannel::A)
        && gba.mem.ioregs.soundcnt_h.dma_timer_select(FifoChannel::A) == timer
    {
        gba.audio
            .fifo_play(FifoChannel::A, &mut gba.mem.ioregs, late)
    }

    if gba.mem.ioregs.soundcnt_h.dma_enable(FifoChannel::B)
        && gba.mem.ioregs.soundcnt_h.dma_timer_select(FifoChannel::B) == timer
    {
        gba.audio
            .fifo_play(FifoChannel::B, &mut gba.mem.ioregs, late)
    }
}

#[derive(Clone, Copy, Debug)]
pub enum Command {
    Wait(u32),
    PlaySample(FifoChannel, i8),
}
<|endoftext|>


<commit_before>pub use self::DecodeError::*;
use std::fmt;

pub const ORDERED: Flavor = Flavor::Ordered(Ordered {});
pub const REVERSED: Flavor = Flavor::Reversed(Reversed {});

const BASE: u128 = 62;
const MAX_DECODED_LEN: usize = 111;

pub struct Ordered {}
pub struct Reversed {}
pub enum Flavor {
    Ordered(Ordered),
    Reversed(Reversed),
}

impl Flavor {
    fn alphabet(&self) -> [u8; BASE as usize] {
        match self {
            Flavor::Ordered(f) => f.alphabet(),
            Flavor::Reversed(f) => f.alphabet(),
        }
    }
}

trait Alphabet {
    fn alphabet(&self) -> [u8; BASE as usize];
}

impl Alphabet for Ordered {
    fn alphabet(&self) -> [u8; BASE as usize] {
        [
            b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b'A', b'B', b'C', b'D',
            b'E', b'F', b'G', b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O', b'P', b'Q', b'R',
            b'S', b'T', b'U', b'V', b'W', b'X', b'Y', b'Z', b'a', b'b', b'c', b'd', b'e', b'f',
            b'g', b'h', b'i', b'j', b'k', b'l', b'm', b'n', b'o', b'p', b'q', b'r', b's', b't',
            b'u', b'v', b'w', b'x', b'y', b'z',
        ]
    }
}

impl Alphabet for Reversed {
    fn alphabet(&self) -> [u8; BASE as usize] {
        [
            b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b'a', b'b', b'c', b'd',
            b'e', b'f', b'g', b'h', b'i', b'j', b'k', b'l', b'm', b'n', b'o', b'p', b'q', b'r',
            b's', b't', b'u', b'v', b'w', b'x', b'y', b'z', b'A', b'B', b'C', b'D', b'E', b'F',
            b'G', b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O', b'P', b'Q', b'R', b'S', b'T',
            b'U', b'V', b'W', b'X', b'Y', b'Z',
        ]
    }
}

#[derive(PartialEq)]
pub enum DecodeError {
    InvalidBase62Byte(char, usize),
    ArithmeticOverflow,
}

impl fmt::Debug for DecodeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            InvalidBase62Byte(ch, idx) => {
                write!(f, "Invalid character '{}' at position {}", ch, idx)
            }
            ArithmeticOverflow => write!(f, "Decode result is too large"),
        }
    }
}

impl fmt::Display for DecodeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self, f)
    }
}

/// Encode any uint as base64.
/// Returns a String.
///
/// # Example
///
/// ```rust
/// extern crate base62;
///
/// fn main() {
///     let b62 = base62::encode(1337u32);
///     println!("{}", b62);
/// }
/// ```
#[must_use]
pub fn encode<T: Into<u128>>(num: T) -> String {
    _encode(num.into(), Flavor::Ordered(Ordered {}))
}

#[must_use]
pub fn encode_config<T: Into<u128>>(num: T, flavor: Flavor) -> String {
    _encode(num.into(), flavor)
}

#[inline]
fn _encode(num: u128, flavor: Flavor) -> String {
    let mut buf = String::with_capacity(MAX_DECODED_LEN);
    encode_config_buf(num, flavor, &mut buf);
    buf
}

/// Encode any uint as base64.
/// Writes into the supplied output buffer, which will grow the buffer if needed.
///
/// # Example
///
/// ```rust
/// extern crate base62;
///
/// fn main() {
///     let mut buf = String::new();
///     base62::encode_buf(1337u32, &mut buf);
///     println!("{}", buf);
/// }
/// ```
pub fn encode_buf<T: Into<u128>>(num: T, buf: &mut String) {
    _encode_buf(num.into(), ORDERED, buf)
}

pub fn encode_config_buf<T: Into<u128>>(num: T, flavor: Flavor, buf: &mut String) {
    _encode_buf(num.into(), flavor, buf)
}

#[inline(always)]
fn _encode_buf(mut num: u128, flavor: Flavor, buf: &mut String) {
    if num == 0 {
        *buf = "0".to_owned();
        return;
    }
    let mut bytes: [u8; MAX_DECODED_LEN] = [0; MAX_DECODED_LEN];

    let mut i: usize = MAX_DECODED_LEN;
    loop {
        if num == 0 {
            break;
        }
        i -= 1;

        bytes[i] = flavor.alphabet()[(num % BASE) as usize];
        num /= BASE;
    }

    unsafe {
        *buf = std::str::from_utf8_unchecked(&bytes[i..MAX_DECODED_LEN]).to_owned();
    }
}

/// Decode from string reference as octets.
/// Returns a Result containing a u128 which can be downcasted to any other uint.
///
/// # Example
///
/// ```rust
/// extern crate base62;
///
/// fn main() {
///     let bytes = base62::decode("rustlang").unwrap();
///     println!("{:?}", bytes);
/// }
/// ```
pub fn decode<T: AsRef<[u8]>>(input: T) -> Result<u128, DecodeError> {
    _decode(input.as_ref(), ORDERED)
}

pub fn decode_config<T: AsRef<[u8]>>(input: T, flavor: Flavor) -> Result<u128, DecodeError> {
    _decode(input.as_ref(), flavor)
}

#[inline(always)]
fn _decode(input: &[u8], flavor: Flavor) -> Result<u128, DecodeError> {
    let mut result = 0u128;

    for (i, c) in input.iter().rev().enumerate() {
        let num = BASE.checked_pow(i as u32).ok_or(ArithmeticOverflow)?;
        match flavor.alphabet().iter().position(|x| x == c) {
            Some(v) => match (v as u128).checked_mul(num) {
                Some(z) => result = result.checked_add(z as u128).ok_or(ArithmeticOverflow)?,
                None => return Err(ArithmeticOverflow),
            },
            None => {
                return Err(InvalidBase62Byte(c.to_owned() as char, input.len() - i));
            }
        }
    }

    Ok(result)
}

#[cfg(test)]
mod tests {
    use crate::base62::*;
    use quickcheck::{quickcheck, TestResult};

    quickcheck! {
        fn encode_decode(xs: u128) -> bool {
            let encoded = encode(xs);
            xs == decode(&encoded).unwrap()
        }
    }

    quickcheck! {
        fn decode_good(xs: String) -> TestResult {
            if xs.chars().all(|c| c.is_ascii() && Flavor::alphabet(&ORDERED).iter().position(|x| *x == c as u8).is_some()) && !xs.is_empty() {
                return TestResult::from_bool(decode(&xs).is_ok());
            } else {
                TestResult::discard()
            }
        }
    }

    quickcheck! {
        fn decode_bad(xs: String) -> TestResult {
            if xs.chars().all(|c| c.is_ascii() && Flavor::alphabet(&ORDERED).iter().position(|x| *x == c as u8).is_some()) {
                TestResult::discard()
            } else {
                return TestResult::from_bool(decode(&xs).is_err());
            }
        }
    }

    #[test]
    fn test_encode() {
        assert_eq!(encode(u128::MAX), "7n42DGM5Tflk9n8mt7Fhc7");
        assert_eq!(encode(0u8), "0");
    }

    #[test]
    fn test_encode_config() {
        assert_eq!(encode_config(691337691337u128, REVERSED), "caCOuUN");
        assert_eq!(encode_config(0u8, REVERSED), "0");
    }

    #[test]
    fn test_encode_buf() {
        let mut buf = String::new();
        encode_buf(u128::MAX, &mut buf);
        assert_eq!(buf, "7n42DGM5Tflk9n8mt7Fhc7");
    }

    #[test]
    fn test_encode_config_buf() {
        let mut buf = String::new();
        encode_config_buf(691337691337u128, REVERSED, &mut buf);
        assert_eq!(buf, "caCOuUN");
    }

    #[test]
    fn test_decode() {
        assert_eq!(decode("7n42DGM5Tflk9n8mt7Fhc7").unwrap(), u128::MAX);
        assert_eq!(decode("").unwrap(), 0);
    }

    #[test]
    fn test_decode_config() {
        assert_eq!(
            decode_config("7N42dgm5tFLK9N8MT7fHC7", REVERSED).unwrap(),
            u128::MAX
        );
        assert_eq!(decode_config("", REVERSED).unwrap(), 0);
    }

    #[test]
    fn test_decode_invalid_char() {
        assert_eq!(
            decode("ds{Z455f"),
            Err(DecodeError::InvalidBase62Byte('{', 3))
        );
    }

    #[test]
    fn test_decode_long_string() {
        assert_eq!(
            decode("7n42DGM5Tflk9n8mt7Fhc7B"),
            Err(DecodeError::ArithmeticOverflow)
        );
    }
}
<commit_msg>Finish documentation<commit_after>pub use self::DecodeError::*;
use std::fmt;

pub const ORDERED: Flavor = Flavor::Ordered(Ordered {});
pub const REVERSED: Flavor = Flavor::Reversed(Reversed {});

const BASE: u128 = 62;
const MAX_DECODED_LEN: usize = 111;

pub struct Ordered {}
pub struct Reversed {}
pub enum Flavor {
    Ordered(Ordered),
    Reversed(Reversed),
}

impl Flavor {
    fn alphabet(&self) -> [u8; BASE as usize] {
        match self {
            Flavor::Ordered(f) => f.alphabet(),
            Flavor::Reversed(f) => f.alphabet(),
        }
    }
}

trait Alphabet {
    fn alphabet(&self) -> [u8; BASE as usize];
}

impl Alphabet for Ordered {
    fn alphabet(&self) -> [u8; BASE as usize] {
        [
            b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b'A', b'B', b'C', b'D',
            b'E', b'F', b'G', b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O', b'P', b'Q', b'R',
            b'S', b'T', b'U', b'V', b'W', b'X', b'Y', b'Z', b'a', b'b', b'c', b'd', b'e', b'f',
            b'g', b'h', b'i', b'j', b'k', b'l', b'm', b'n', b'o', b'p', b'q', b'r', b's', b't',
            b'u', b'v', b'w', b'x', b'y', b'z',
        ]
    }
}

impl Alphabet for Reversed {
    fn alphabet(&self) -> [u8; BASE as usize] {
        [
            b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b'a', b'b', b'c', b'd',
            b'e', b'f', b'g', b'h', b'i', b'j', b'k', b'l', b'm', b'n', b'o', b'p', b'q', b'r',
            b's', b't', b'u', b'v', b'w', b'x', b'y', b'z', b'A', b'B', b'C', b'D', b'E', b'F',
            b'G', b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O', b'P', b'Q', b'R', b'S', b'T',
            b'U', b'V', b'W', b'X', b'Y', b'Z',
        ]
    }
}

#[derive(PartialEq)]
pub enum DecodeError {
    InvalidBase62Byte(char, usize),
    ArithmeticOverflow,
}

impl fmt::Debug for DecodeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            InvalidBase62Byte(ch, idx) => {
                write!(f, "Invalid character '{}' at position {}", ch, idx)
            }
            ArithmeticOverflow => write!(f, "Decode result is too large"),
        }
    }
}

impl fmt::Display for DecodeError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self, f)
    }
}

/// Encode any uint as base64.
/// Returns a String.
///
/// # Example
///
/// ```rust
/// extern crate base62;
///
/// fn main() {
///     let b62 = base62::encode(1337u32);
///     println!("{}", b62);
/// }
/// ```
#[must_use]
pub fn encode<T: Into<u128>>(num: T) -> String {
    _encode(num.into(), Flavor::Ordered(Ordered {}))
}

/// Encode any uint as base64 based on a specified alphabet.
/// Returns a String.
///
/// # Example
///
/// ```rust
/// extern crate base62;
/// use base62::ORDERED;
///
/// fn main() {
///     let b62 = base62::encode_config(1337u32, ORDERED);
///     println!("{}", b62);
/// }
/// ```
#[must_use]
pub fn encode_config<T: Into<u128>>(num: T, flavor: Flavor) -> String {
    _encode(num.into(), flavor)
}

#[inline]
fn _encode(num: u128, flavor: Flavor) -> String {
    let mut buf = String::with_capacity(MAX_DECODED_LEN);
    encode_config_buf(num, flavor, &mut buf);
    buf
}

/// Encode any uint as base64.
/// Writes into the supplied output buffer, which will grow the buffer if needed.
///
/// # Example
///
/// ```rust
/// extern crate base62;
///
/// fn main() {
///     let mut buf = String::new();
///     base62::encode_buf(1337u32, &mut buf);
///     println!("{}", buf);
/// }
/// ```
pub fn encode_buf<T: Into<u128>>(num: T, buf: &mut String) {
    _encode_buf(num.into(), ORDERED, buf)
}

/// Encode any uint as base64 based on a specified alphabet.
/// Writes into the supplied output buffer, which will grow the buffer if needed.
///
/// # Example
///
/// ```rust
/// extern crate base62;
/// use base62::ORDERED;
///
/// fn main() {
///     let mut buf = String::new();
///     base62::encode_config_buf(1337u32, ORDERED, &mut buf);
///     println!("{}", buf);
/// }
/// ```
pub fn encode_config_buf<T: Into<u128>>(num: T, flavor: Flavor, buf: &mut String) {
    _encode_buf(num.into(), flavor, buf)
}

#[inline(always)]
fn _encode_buf(mut num: u128, flavor: Flavor, buf: &mut String) {
    if num == 0 {
        *buf = "0".to_owned();
        return;
    }
    let mut bytes: [u8; MAX_DECODED_LEN] = [0; MAX_DECODED_LEN];

    let mut i: usize = MAX_DECODED_LEN;
    loop {
        if num == 0 {
            break;
        }
        i -= 1;

        bytes[i] = flavor.alphabet()[(num % BASE) as usize];
        num /= BASE;
    }

    unsafe {
        *buf = std::str::from_utf8_unchecked(&bytes[i..MAX_DECODED_LEN]).to_owned();
    }
}

/// Decode from string reference as octets.
/// Returns a Result containing a u128 which can be downcasted to any other uint.
///
/// # Example
///
/// ```rust
/// extern crate base62;
///
/// fn main() {
///     let bytes = base62::decode("rustlang").unwrap();
///     println!("{:?}", bytes);
/// }
/// ```
pub fn decode<T: AsRef<[u8]>>(input: T) -> Result<u128, DecodeError> {
    _decode(input.as_ref(), ORDERED)
}

/// Decode from string reference as octets based on a specified alphabet.
/// Returns a Result containing a u128 which can be downcasted to any other uint.
///
/// # Example
///
/// ```rust
/// extern crate base62;
/// use base62::ORDERED;
///
/// fn main() {
///     let bytes = base62::decode_config("rustlang", ORDERED).unwrap();
///     println!("{:?}", bytes);
/// }
/// ```
pub fn decode_config<T: AsRef<[u8]>>(input: T, flavor: Flavor) -> Result<u128, DecodeError> {
    _decode(input.as_ref(), flavor)
}

#[inline(always)]
fn _decode(input: &[u8], flavor: Flavor) -> Result<u128, DecodeError> {
    let mut result = 0u128;

    for (i, c) in input.iter().rev().enumerate() {
        let num = BASE.checked_pow(i as u32).ok_or(ArithmeticOverflow)?;
        match flavor.alphabet().iter().position(|x| x == c) {
            Some(v) => match (v as u128).checked_mul(num) {
                Some(z) => result = result.checked_add(z as u128).ok_or(ArithmeticOverflow)?,
                None => return Err(ArithmeticOverflow),
            },
            None => {
                return Err(InvalidBase62Byte(c.to_owned() as char, input.len() - i));
            }
        }
    }

    Ok(result)
}

#[cfg(test)]
mod tests {
    use crate::base62::*;
    use quickcheck::{quickcheck, TestResult};

    quickcheck! {
        fn encode_decode(xs: u128) -> bool {
            let encoded = encode(xs);
            xs == decode(&encoded).unwrap()
        }
    }

    quickcheck! {
        fn decode_good(xs: String) -> TestResult {
            if xs.chars().all(|c| c.is_ascii() && Flavor::alphabet(&ORDERED).iter().position(|x| *x == c as u8).is_some()) && !xs.is_empty() {
                return TestResult::from_bool(decode(&xs).is_ok());
            } else {
                TestResult::discard()
            }
        }
    }

    quickcheck! {
        fn decode_bad(xs: String) -> TestResult {
            if xs.chars().all(|c| c.is_ascii() && Flavor::alphabet(&ORDERED).iter().position(|x| *x == c as u8).is_some()) {
                TestResult::discard()
            } else {
                return TestResult::from_bool(decode(&xs).is_err());
            }
        }
    }

    #[test]
    fn test_encode() {
        assert_eq!(encode(u128::MAX), "7n42DGM5Tflk9n8mt7Fhc7");
        assert_eq!(encode(0u8), "0");
    }

    #[test]
    fn test_encode_config() {
        assert_eq!(encode_config(691337691337u128, REVERSED), "caCOuUN");
        assert_eq!(encode_config(0u8, REVERSED), "0");
    }

    #[test]
    fn test_encode_buf() {
        let mut buf = String::new();
        encode_buf(u128::MAX, &mut buf);
        assert_eq!(buf, "7n42DGM5Tflk9n8mt7Fhc7");
    }

    #[test]
    fn test_encode_config_buf() {
        let mut buf = String::new();
        encode_config_buf(691337691337u128, REVERSED, &mut buf);
        assert_eq!(buf, "caCOuUN");
    }

    #[test]
    fn test_decode() {
        assert_eq!(decode("7n42DGM5Tflk9n8mt7Fhc7").unwrap(), u128::MAX);
        assert_eq!(decode("").unwrap(), 0);
    }

    #[test]
    fn test_decode_config() {
        assert_eq!(
            decode_config("7N42dgm5tFLK9N8MT7fHC7", REVERSED).unwrap(),
            u128::MAX
        );
        assert_eq!(decode_config("", REVERSED).unwrap(), 0);
    }

    #[test]
    fn test_decode_invalid_char() {
        assert_eq!(
            decode("ds{Z455f"),
            Err(DecodeError::InvalidBase62Byte('{', 3))
        );
    }

    #[test]
    fn test_decode_long_string() {
        assert_eq!(
            decode("7n42DGM5Tflk9n8mt7Fhc7B"),
            Err(DecodeError::ArithmeticOverflow)
        );
    }
}
<|endoftext|>


<commit_before>use std::collections::HashSet;
use std::collections::hash_map::{HashMap, Occupied, Vacant};
use std::str;
use std::sync::Arc;

use core::{SourceMap, Package, PackageId, PackageSet, Resolve, Target};
use util::{mod, CargoResult, ChainError, internal, Config, profile};
use util::human;

use super::{Kind, KindHost, KindTarget, Compilation, BuildConfig};
use super::TargetConfig;
use super::layout::{Layout, LayoutProxy};
use super::custom_build::BuildState;

#[deriving(Show)]
pub enum PlatformRequirement {
    PlatformTarget,
    PlatformPlugin,
    PlatformPluginAndTarget,
}

pub struct Context<'a, 'b: 'a> {
    pub config: &'b Config<'b>,
    pub resolve: &'a Resolve,
    pub sources: &'a SourceMap<'b>,
    pub compilation: Compilation,
    pub build_state: Arc<BuildState>,

    env: &'a str,
    host: Layout,
    target: Option<Layout>,
    target_triple: String,
    host_dylib: Option<(String, String)>,
    package_set: &'a PackageSet,
    target_dylib: Option<(String, String)>,
    target_exe: String,
    requirements: HashMap<(&'a PackageId, &'a str), PlatformRequirement>,
    build_config: BuildConfig,
}

impl<'a, 'b: 'a> Context<'a, 'b> {
    pub fn new(env: &'a str, resolve: &'a Resolve, sources: &'a SourceMap<'b>,
               deps: &'a PackageSet, config: &'b Config<'b>,
               host: Layout, target: Option<Layout>,
               root_pkg: &Package,
               build_config: BuildConfig)
               -> CargoResult<Context<'a, 'b>> {
        let (target_dylib, target_exe) =
                try!(Context::filename_parts(config.target()));
        let host_dylib = if config.target().is_none() {
            target_dylib.clone()
        } else {
            let (dylib, _) = try!(Context::filename_parts(None));
            dylib
        };
        let target_triple = config.target().map(|s| s.to_string());
        let target_triple = target_triple.unwrap_or(config.rustc_host().to_string());
        Ok(Context {
            target_triple: target_triple,
            env: env,
            host: host,
            target: target,
            resolve: resolve,
            sources: sources,
            package_set: deps,
            config: config,
            target_dylib: target_dylib,
            target_exe: target_exe,
            host_dylib: host_dylib,
            requirements: HashMap::new(),
            compilation: Compilation::new(root_pkg),
            build_state: Arc::new(BuildState::new(build_config.clone(), deps)),
            build_config: build_config,
        })
    }

    /// Run `rustc` to discover the dylib prefix/suffix for the target
    /// specified as well as the exe suffix
    fn filename_parts(target: Option<&str>)
                      -> CargoResult<(Option<(String, String)>, String)> {
        let process = util::process("rustc")
                           .arg("-")
                           .arg("--crate-name").arg("-")
                           .arg("--crate-type").arg("dylib")
                           .arg("--crate-type").arg("bin")
                           .arg("--print-file-name");
        let process = match target {
            Some(s) => process.arg("--target").arg(s),
            None => process,
        };
        let output = try!(process.exec_with_output());

        let error = str::from_utf8(output.error.as_slice()).unwrap();
        let output = str::from_utf8(output.output.as_slice()).unwrap();
        let mut lines = output.lines();
        let dylib = if error.contains("dropping unsupported crate type `dylib`") {
            None
        } else {
            let dylib_parts: Vec<&str> = lines.next().unwrap().trim()
                                              .split('-').collect();
            assert!(dylib_parts.len() == 2,
                    "rustc --print-file-name output has changed");
            Some((dylib_parts[0].to_string(), dylib_parts[1].to_string()))
        };

        let exe_suffix = if error.contains("dropping unsupported crate type `bin`") {
            String::new()
        } else {
            lines.next().unwrap().trim()
                 .split('-').skip(1).next().unwrap().to_string()
        };
        Ok((dylib, exe_suffix.to_string()))
    }

    /// Prepare this context, ensuring that all filesystem directories are in
    /// place.
    pub fn prepare(&mut self, pkg: &'a Package) -> CargoResult<()> {
        let _p = profile::start("preparing layout");

        try!(self.host.prepare().chain_error(|| {
            internal(format!("couldn't prepare build directories for `{}`",
                             pkg.get_name()))
        }));
        match self.target {
            Some(ref mut target) => {
                try!(target.prepare().chain_error(|| {
                    internal(format!("couldn't prepare build directories \
                                      for `{}`", pkg.get_name()))
                }));
            }
            None => {}
        }

        let targets = pkg.get_targets().iter();
        for target in targets.filter(|t| t.get_profile().is_compile()) {
            self.build_requirements(pkg, target, PlatformTarget,
                                    &mut HashSet::new());
        }

        self.compilation.extra_env.insert("NUM_JOBS".to_string(),
                                          Some(self.config.jobs().to_string()));
        self.compilation.root_output =
                self.layout(pkg, KindTarget).proxy().dest().clone();
        self.compilation.deps_output =
                self.layout(pkg, KindTarget).proxy().deps().clone();

        return Ok(());
    }

    fn build_requirements(&mut self, pkg: &'a Package, target: &'a Target,
                          req: PlatformRequirement,
                          visiting: &mut HashSet<(&'a PackageId, &'a str)>) {

        let key = (pkg.get_package_id(), target.get_name());
        if !visiting.insert(key) { return }
        let req = if target.get_profile().is_for_host() {PlatformPlugin} else {req};
        match self.requirements.entry(key) {
            Occupied(mut entry) => { *entry.get_mut() = entry.get().combine(req); }
            Vacant(entry) => { entry.set(req); }
        };

        for &(pkg, dep) in self.dep_targets(pkg, target).iter() {
            self.build_requirements(pkg, dep, req, visiting);
        }

        match pkg.get_targets().iter().find(|t| t.get_profile().is_custom_build()) {
            Some(custom_build) => {
                self.build_requirements(pkg, custom_build, PlatformPlugin,
                                        visiting);
            }
            None => {}
        }

        visiting.remove(&key);
    }

    pub fn get_requirement(&self, pkg: &'a Package,
                           target: &'a Target) -> PlatformRequirement {
        let default = if target.get_profile().is_for_host() {
            PlatformPlugin
        } else {
            PlatformTarget
        };
        self.requirements.get(&(pkg.get_package_id(), target.get_name()))
            .map(|a| *a).unwrap_or(default)
    }

    /// Returns the appropriate directory layout for either a plugin or not.
    pub fn layout(&self, pkg: &Package, kind: Kind) -> LayoutProxy {
        let primary = pkg.get_package_id() == self.resolve.root();
        match kind {
            KindHost => LayoutProxy::new(&self.host, primary),
            KindTarget =>  LayoutProxy::new(self.target.as_ref()
                                                .unwrap_or(&self.host),
                                            primary),
        }
    }

    /// Return the (prefix, suffix) pair for dynamic libraries.
    ///
    /// If `plugin` is true, the pair corresponds to the host platform,
    /// otherwise it corresponds to the target platform.
    fn dylib(&self, kind: Kind) -> CargoResult<(&str, &str)> {
        let (triple, pair) = if kind == KindHost {
            (self.config.rustc_host(), &self.host_dylib)
        } else {
            (self.target_triple.as_slice(), &self.target_dylib)
        };
        match *pair {
            None => return Err(human(format!("dylib outputs are not supported \
                                              for {}", triple))),
            Some((ref s1, ref s2)) => Ok((s1.as_slice(), s2.as_slice())),
        }
    }

    /// Return the target triple which this context is targeting.
    pub fn target_triple(&self) -> &str {
        self.target_triple.as_slice()
    }

    /// Return the exact filename of the target.
    pub fn target_filenames(&self, target: &Target) -> CargoResult<Vec<String>> {
        let stem = target.file_stem();

        let mut ret = Vec::new();
        if target.is_example() || target.is_bin() ||
           target.get_profile().is_test() {
            ret.push(format!("{}{}", stem, self.target_exe));
        } else {
            if target.is_dylib() {
                let plugin = target.get_profile().is_for_host();
                let kind = if plugin {KindHost} else {KindTarget};
                let (prefix, suffix) = try!(self.dylib(kind));
                ret.push(format!("{}{}{}", prefix, stem, suffix));
            }
            if target.is_rlib() {
                ret.push(format!("lib{}.rlib", stem));
            }
            if target.is_staticlib() {
                ret.push(format!("lib{}.a", stem));
            }
        }
        assert!(ret.len() > 0);
        return Ok(ret);
    }

    /// For a package, return all targets which are registered as dependencies
    /// for that package.
    pub fn dep_targets(&self, pkg: &Package, target: &Target)
                       -> Vec<(&'a Package, &'a Target)> {
        let deps = match self.resolve.deps(pkg.get_package_id()) {
            None => return vec!(),
            Some(deps) => deps,
        };
        deps.map(|id| self.get_package(id)).filter(|dep| {
            // If this target is a build command, then we only want build
            // dependencies, otherwise we want everything *other than* build
            // dependencies.
            let pkg_dep = pkg.get_dependencies().iter().find(|d| {
                d.get_name() == dep.get_name()
            }).unwrap();
            target.get_profile().is_custom_build() == pkg_dep.is_build()
        }).filter_map(|pkg| {
            pkg.get_targets().iter().find(|&t| self.is_relevant_target(t))
               .map(|t| (pkg, t))
        }).collect()
    }

    /// Gets a package for the given package id.
    pub fn get_package(&self, id: &PackageId) -> &'a Package {
        self.package_set.iter()
            .find(|pkg| id == pkg.get_package_id())
            .expect("Should have found package")
    }

    pub fn env(&self) -> &str {
        // The "doc-all" environment just means to document everything (see
        // below), but we want to canonicalize that the the "doc" profile
        // environment, so do that here.
        if self.env == "doc-all" {"doc"} else {self.env}
    }

    pub fn is_relevant_target(&self, target: &Target) -> bool {
        target.is_lib() && match self.env {
            "doc" | "test" => target.get_profile().is_compile(),
            // doc-all == document everything, so look for doc targets and
            //            compile targets in dependencies
            "doc-all" => target.get_profile().is_compile() ||
                         (target.get_profile().get_env() == "doc" &&
                          target.get_profile().is_doc()),
            _ => target.get_profile().get_env() == self.env &&
                 !target.get_profile().is_test(),
        }
    }

    /// Get the user-specified linker for a particular host or target
    pub fn linker(&self, kind: Kind) -> Option<&str> {
        self.target_config(kind).linker.as_ref().map(|s| s.as_slice())
    }

    /// Get the user-specified `ar` program for a particular host or target
    pub fn ar(&self, kind: Kind) -> Option<&str> {
        self.target_config(kind).ar.as_ref().map(|s| s.as_slice())
    }

    /// Get the target configuration for a particular host or target
    fn target_config(&self, kind: Kind) -> &TargetConfig {
        match kind {
            KindHost => &self.build_config.host,
            KindTarget => &self.build_config.target,
        }
    }
}

impl PlatformRequirement {
    fn combine(self, other: PlatformRequirement) -> PlatformRequirement {
        match (self, other) {
            (PlatformTarget, PlatformTarget) => PlatformTarget,
            (PlatformPlugin, PlatformPlugin) => PlatformPlugin,
            _ => PlatformPluginAndTarget,
        }
    }
}
<commit_msg>Respect Target target vs host exe suffix distinction.<commit_after>use std::collections::HashSet;
use std::collections::hash_map::{HashMap, Occupied, Vacant};
use std::str;
use std::sync::Arc;

use core::{SourceMap, Package, PackageId, PackageSet, Resolve, Target};
use util::{mod, CargoResult, ChainError, internal, Config, profile};
use util::human;

use super::{Kind, KindHost, KindTarget, Compilation, BuildConfig};
use super::TargetConfig;
use super::layout::{Layout, LayoutProxy};
use super::custom_build::BuildState;

#[deriving(Show)]
pub enum PlatformRequirement {
    PlatformTarget,
    PlatformPlugin,
    PlatformPluginAndTarget,
}

pub struct Context<'a, 'b: 'a> {
    pub config: &'b Config<'b>,
    pub resolve: &'a Resolve,
    pub sources: &'a SourceMap<'b>,
    pub compilation: Compilation,
    pub build_state: Arc<BuildState>,

    env: &'a str,
    host: Layout,
    target: Option<Layout>,
    target_triple: String,
    host_dylib: Option<(String, String)>,
    host_exe: String,
    package_set: &'a PackageSet,
    target_dylib: Option<(String, String)>,
    target_exe: String,
    requirements: HashMap<(&'a PackageId, &'a str), PlatformRequirement>,
    build_config: BuildConfig,
}

impl<'a, 'b: 'a> Context<'a, 'b> {
    pub fn new(env: &'a str, resolve: &'a Resolve, sources: &'a SourceMap<'b>,
               deps: &'a PackageSet, config: &'b Config<'b>,
               host: Layout, target: Option<Layout>,
               root_pkg: &Package,
               build_config: BuildConfig)
               -> CargoResult<Context<'a, 'b>> {
        let (target_dylib, target_exe) =
                try!(Context::filename_parts(config.target()));
        let (host_dylib, host_exe) = if config.target().is_none() {
            (target_dylib.clone(),
             target_exe.clone())
        } else {
            try!(Context::filename_parts(None))
        };
        let target_triple = config.target().map(|s| s.to_string());
        let target_triple = target_triple.unwrap_or(config.rustc_host().to_string());
        Ok(Context {
            target_triple: target_triple,
            env: env,
            host: host,
            target: target,
            resolve: resolve,
            sources: sources,
            package_set: deps,
            config: config,
            target_dylib: target_dylib,
            target_exe: target_exe,
            host_dylib: host_dylib,
            host_exe: host_exe,
            requirements: HashMap::new(),
            compilation: Compilation::new(root_pkg),
            build_state: Arc::new(BuildState::new(build_config.clone(), deps)),
            build_config: build_config,
        })
    }

    /// Run `rustc` to discover the dylib prefix/suffix for the target
    /// specified as well as the exe suffix
    fn filename_parts(target: Option<&str>)
                      -> CargoResult<(Option<(String, String)>, String)> {
        let process = util::process("rustc")
                           .arg("-")
                           .arg("--crate-name").arg("-")
                           .arg("--crate-type").arg("dylib")
                           .arg("--crate-type").arg("bin")
                           .arg("--print-file-name");
        let process = match target {
            Some(s) => process.arg("--target").arg(s),
            None => process,
        };
        let output = try!(process.exec_with_output());

        let error = str::from_utf8(output.error.as_slice()).unwrap();
        let output = str::from_utf8(output.output.as_slice()).unwrap();
        let mut lines = output.lines();
        let dylib = if error.contains("dropping unsupported crate type `dylib`") {
            None
        } else {
            let dylib_parts: Vec<&str> = lines.next().unwrap().trim()
                                              .split('-').collect();
            assert!(dylib_parts.len() == 2,
                    "rustc --print-file-name output has changed");
            Some((dylib_parts[0].to_string(), dylib_parts[1].to_string()))
        };

        let exe_suffix = if error.contains("dropping unsupported crate type `bin`") {
            String::new()
        } else {
            lines.next().unwrap().trim()
                 .split('-').skip(1).next().unwrap().to_string()
        };
        Ok((dylib, exe_suffix.to_string()))
    }

    /// Prepare this context, ensuring that all filesystem directories are in
    /// place.
    pub fn prepare(&mut self, pkg: &'a Package) -> CargoResult<()> {
        let _p = profile::start("preparing layout");

        try!(self.host.prepare().chain_error(|| {
            internal(format!("couldn't prepare build directories for `{}`",
                             pkg.get_name()))
        }));
        match self.target {
            Some(ref mut target) => {
                try!(target.prepare().chain_error(|| {
                    internal(format!("couldn't prepare build directories \
                                      for `{}`", pkg.get_name()))
                }));
            }
            None => {}
        }

        let targets = pkg.get_targets().iter();
        for target in targets.filter(|t| t.get_profile().is_compile()) {
            self.build_requirements(pkg, target, PlatformTarget,
                                    &mut HashSet::new());
        }

        self.compilation.extra_env.insert("NUM_JOBS".to_string(),
                                          Some(self.config.jobs().to_string()));
        self.compilation.root_output =
                self.layout(pkg, KindTarget).proxy().dest().clone();
        self.compilation.deps_output =
                self.layout(pkg, KindTarget).proxy().deps().clone();

        return Ok(());
    }

    fn build_requirements(&mut self, pkg: &'a Package, target: &'a Target,
                          req: PlatformRequirement,
                          visiting: &mut HashSet<(&'a PackageId, &'a str)>) {

        let key = (pkg.get_package_id(), target.get_name());
        if !visiting.insert(key) { return }
        let req = if target.get_profile().is_for_host() {PlatformPlugin} else {req};
        match self.requirements.entry(key) {
            Occupied(mut entry) => { *entry.get_mut() = entry.get().combine(req); }
            Vacant(entry) => { entry.set(req); }
        };

        for &(pkg, dep) in self.dep_targets(pkg, target).iter() {
            self.build_requirements(pkg, dep, req, visiting);
        }

        match pkg.get_targets().iter().find(|t| t.get_profile().is_custom_build()) {
            Some(custom_build) => {
                self.build_requirements(pkg, custom_build, PlatformPlugin,
                                        visiting);
            }
            None => {}
        }

        visiting.remove(&key);
    }

    pub fn get_requirement(&self, pkg: &'a Package,
                           target: &'a Target) -> PlatformRequirement {
        let default = if target.get_profile().is_for_host() {
            PlatformPlugin
        } else {
            PlatformTarget
        };
        self.requirements.get(&(pkg.get_package_id(), target.get_name()))
            .map(|a| *a).unwrap_or(default)
    }

    /// Returns the appropriate directory layout for either a plugin or not.
    pub fn layout(&self, pkg: &Package, kind: Kind) -> LayoutProxy {
        let primary = pkg.get_package_id() == self.resolve.root();
        match kind {
            KindHost => LayoutProxy::new(&self.host, primary),
            KindTarget =>  LayoutProxy::new(self.target.as_ref()
                                                .unwrap_or(&self.host),
                                            primary),
        }
    }

    /// Return the (prefix, suffix) pair for dynamic libraries.
    ///
    /// If `plugin` is true, the pair corresponds to the host platform,
    /// otherwise it corresponds to the target platform.
    fn dylib(&self, kind: Kind) -> CargoResult<(&str, &str)> {
        let (triple, pair) = if kind == KindHost {
            (self.config.rustc_host(), &self.host_dylib)
        } else {
            (self.target_triple.as_slice(), &self.target_dylib)
        };
        match *pair {
            None => return Err(human(format!("dylib outputs are not supported \
                                              for {}", triple))),
            Some((ref s1, ref s2)) => Ok((s1.as_slice(), s2.as_slice())),
        }
    }

    /// Return the target triple which this context is targeting.
    pub fn target_triple(&self) -> &str {
        self.target_triple.as_slice()
    }

    /// Return the exact filename of the target.
    pub fn target_filenames(&self, target: &Target) -> CargoResult<Vec<String>> {
        let stem = target.file_stem();

        let mut ret = Vec::new();
        if target.is_example() || target.is_bin() ||
           target.get_profile().is_test() {
            ret.push(format!("{}{}", stem,
                             if target.get_profile().is_for_host() {
                                 self.host_exe.as_slice()
                             } else {
                                 self.target_exe.as_slice()
                             }));
        } else {
            if target.is_dylib() {
                let plugin = target.get_profile().is_for_host();
                let kind = if plugin {KindHost} else {KindTarget};
                let (prefix, suffix) = try!(self.dylib(kind));
                ret.push(format!("{}{}{}", prefix, stem, suffix));
            }
            if target.is_rlib() {
                ret.push(format!("lib{}.rlib", stem));
            }
            if target.is_staticlib() {
                ret.push(format!("lib{}.a", stem));
            }
        }
        assert!(ret.len() > 0);
        return Ok(ret);
    }

    /// For a package, return all targets which are registered as dependencies
    /// for that package.
    pub fn dep_targets(&self, pkg: &Package, target: &Target)
                       -> Vec<(&'a Package, &'a Target)> {
        let deps = match self.resolve.deps(pkg.get_package_id()) {
            None => return vec!(),
            Some(deps) => deps,
        };
        deps.map(|id| self.get_package(id)).filter(|dep| {
            // If this target is a build command, then we only want build
            // dependencies, otherwise we want everything *other than* build
            // dependencies.
            let pkg_dep = pkg.get_dependencies().iter().find(|d| {
                d.get_name() == dep.get_name()
            }).unwrap();
            target.get_profile().is_custom_build() == pkg_dep.is_build()
        }).filter_map(|pkg| {
            pkg.get_targets().iter().find(|&t| self.is_relevant_target(t))
               .map(|t| (pkg, t))
        }).collect()
    }

    /// Gets a package for the given package id.
    pub fn get_package(&self, id: &PackageId) -> &'a Package {
        self.package_set.iter()
            .find(|pkg| id == pkg.get_package_id())
            .expect("Should have found package")
    }

    pub fn env(&self) -> &str {
        // The "doc-all" environment just means to document everything (see
        // below), but we want to canonicalize that the the "doc" profile
        // environment, so do that here.
        if self.env == "doc-all" {"doc"} else {self.env}
    }

    pub fn is_relevant_target(&self, target: &Target) -> bool {
        target.is_lib() && match self.env {
            "doc" | "test" => target.get_profile().is_compile(),
            // doc-all == document everything, so look for doc targets and
            //            compile targets in dependencies
            "doc-all" => target.get_profile().is_compile() ||
                         (target.get_profile().get_env() == "doc" &&
                          target.get_profile().is_doc()),
            _ => target.get_profile().get_env() == self.env &&
                 !target.get_profile().is_test(),
        }
    }

    /// Get the user-specified linker for a particular host or target
    pub fn linker(&self, kind: Kind) -> Option<&str> {
        self.target_config(kind).linker.as_ref().map(|s| s.as_slice())
    }

    /// Get the user-specified `ar` program for a particular host or target
    pub fn ar(&self, kind: Kind) -> Option<&str> {
        self.target_config(kind).ar.as_ref().map(|s| s.as_slice())
    }

    /// Get the target configuration for a particular host or target
    fn target_config(&self, kind: Kind) -> &TargetConfig {
        match kind {
            KindHost => &self.build_config.host,
            KindTarget => &self.build_config.target,
        }
    }
}

impl PlatformRequirement {
    fn combine(self, other: PlatformRequirement) -> PlatformRequirement {
        match (self, other) {
            (PlatformTarget, PlatformTarget) => PlatformTarget,
            (PlatformPlugin, PlatformPlugin) => PlatformPlugin,
            _ => PlatformPluginAndTarget,
        }
    }
}
<|endoftext|>


<commit_before>#![deny(warnings)]

extern crate coreutils;
extern crate extra;

use std::env;
use std::fs;
use std::io::{stderr, stdout, Write};
use std::path;
use std::process::exit;
use coreutils::ArgParser;
use extra::io::fail;
use extra::option::OptionalExt;

const MAN_PAGE: &'static str = /* @MANSTART{mv} */ r#"
NAME
    mv - move files

SYNOPSIS
    mv [ -h | --help ] SOURCE_FILE(S) DESTINATION_FILE

DESCRIPTION
    The mv utility renames the file named by the SOURCE_FILE operand to the destination path
    named by the DESTINATION_FILE operand. Otherwise moves files to new destination.

OPTIONS
    --help, -h
        print this message
"#; /* @MANEND */

fn main() {
    let stdout = stdout();
    let mut stdout = stdout.lock();
    let mut stderr = stderr();
    let mut parser = ArgParser::new(1)
        .add_flag(&["h", "help"]);
    parser.parse(env::args());

    if parser.found("help") {
        stdout.write_all(MAN_PAGE.as_bytes()).try(&mut stderr);
        stdout.flush().try(&mut stderr);
        exit(0);
    }

    if parser.args.is_empty() {
        fail("No source argument. Use --help to see the usage.", &mut stderr);
    }
    else if parser.args.len() == 1 {
        fail("No destination argument. Use --help to see the usage.", &mut stderr);
    }
    else if parser.args.len() == 2 {
        let src = path::Path::new(&parser.args[0]);
        let mut dst = path::PathBuf::from(&parser.args[1]);
        if dst.is_dir() {
            dst.push(src.file_name().try(&mut stderr))
        }
        fs::rename(src, dst).try(&mut stderr);
    }
    else {
        // This unwrap won't panic since it's been verified not to be empty
        let dst = parser.args.pop().unwrap();
        let dst = path::PathBuf::from(dst);
        if dst.is_dir() {
            for ref arg in parser.args {
                let src = path::Path::new(arg);
                fs::rename(src, dst.join(src.file_name().try(&mut stderr))).try(&mut stderr);
            }
        }
        else if dst.is_file() {
            fail("Destination should be a path, not a file. Use --help to see the usage.", &mut stderr);
        }
        else {
            fail("No destination found. Use --help to see the usage.", &mut stderr);
        }
    }
}
<commit_msg>mv recursive<commit_after>#![deny(warnings)]

extern crate coreutils;
extern crate extra;

use std::env;
use std::fs;
use std::io::{stderr, stdout, Write};
use std::path;
use std::process::exit;
use coreutils::ArgParser;
use extra::io::fail;
use extra::option::OptionalExt;

const MAN_PAGE: &'static str = /* @MANSTART{mv} */ r#"
NAME
    mv - move files

SYNOPSIS
    mv [ -h | --help ] SOURCE_FILE(S) DESTINATION_FILE

DESCRIPTION
    The mv utility renames the file named by the SOURCE_FILE operand to the destination path
    named by the DESTINATION_FILE operand. Otherwise moves files to new destination.

OPTIONS
    --help, -h
        print this message
"#; /* @MANEND */

fn main() {
    let stdout = stdout();
    let mut stdout = stdout.lock();
    let mut stderr = stderr();
    let mut parser = ArgParser::new(1)
        .add_flag(&["r", "recursive"])
        .add_flag(&["n", "no-action"])
        .add_flag(&["v", "verbose"])
        .add_flag(&["h", "help"]);
    parser.parse(env::args());

    if parser.found("help") {
        stdout.write_all(MAN_PAGE.as_bytes()).try(&mut stderr);
        stdout.flush().try(&mut stderr);
        exit(0);
    }

    let recurse = parser.found("recursive");
    let verbose = parser.found("verbose");
    let execute = ! parser.found("no-action");

    if parser.args.is_empty() {
        fail("No source argument. Use --help to see the usage.", &mut stderr);
    }
    else if parser.args.len() == 1 {
        fail("No destination argument. Use --help to see the usage.", &mut stderr);
    }
    else if parser.args.len() == 2 && ! recurse {
        let src = path::Path::new(&parser.args[0]);
        let mut dst = path::PathBuf::from(&parser.args[1]);
        if dst.is_dir() {
            dst.push(src.file_name().try(&mut stderr))
        }
        if execute {
            fs::rename(src, dst).try(&mut stderr);
        }
        if verbose {
            println!("{}", src.display());
        }
    }
    else {
        // This unwrap won't panic since it's been verified not to be empty
        let dst = parser.args.pop().unwrap();
        let dst = path::PathBuf::from(dst);
        if dst.is_dir() {
            for ref arg in parser.args {
                let src = path::Path::new(arg);
                if src.is_dir() && ! recurse {
                    fail("Can not move directories non-recursive", &mut stderr);
                }
                if recurse {
                    for entry in WalkDir::new(arg) {
                        let entry = entry.unwrap();
                        let src = path::Path::new(entry.path());
                        if execute {
                            if src.is_dir() {
                                fs::create_dir(dst.join(src)).try(&mut stderr);
                            } else if src.is_file() {
                                fs::rename(src, dst.join(src)).try(&mut stderr);
                            } // here we might also want to check for symlink, hardlink, socket, block, char, ...?
                        }
                        if verbose {
                            println!("{}", src.display());
                        }
                    }
                } else {
                    if execute {
                        fs::rename(src, dst.join(src.file_name().try(&mut stderr))).try(&mut stderr);
                    }
                    if verbose {
                        println!("{}", src.display());
                    }
                }
            }
        }
        else if dst.is_file() {
            fail("Destination should be a path, not a file. Use --help to see the usage.", &mut stderr);
        }
        else {
            fail("No destination found. Use --help to see the usage.", &mut stderr);
        }
    }
}
<|endoftext|>


<commit_before>use std::rc::Rc;
use builtins::Builtin;
use state::InterpState;

/// Represents a branch in the syntax tree
#[derive(Debug, PartialEq)]
pub enum Branch {
    Custom(Rc<Vec<Branch>>),
    Builtin(Builtin),
    Int(i32),
    Float(f32),
    IfElse(Vec<Branch>, Vec<Branch>),
    Dotquote(String),
}

impl Branch {
    pub fn call(&self, state: &mut InterpState) {
        match self {
            &Branch::Custom(ref branches) => {
                for branch in branches.iter() {
                    branch.call(state);
                }
            }
            &Branch::Builtin(ref builtin) => builtin.call(state),
            &Branch::Int(int) => state.stack.push(int),
            &Branch::Float(float) => state.stack.push(float as i32), //XXX
            &Branch::IfElse(ref ifbranches, ref elsebranches) => {
                if state.stack.pop() {
                    for branch in ifbranches.iter() {
                        branch.call(state);
                    }
                } else {
                    for branch in elsebranches.iter() {
                        branch.call(state);
                    }
                }
            }
            &Branch::Dotquote(ref text) => print!("{}", text),
        }
    }
}
<commit_msg>Slight syntax simplification<commit_after>use std::rc::Rc;
use builtins::Builtin;
use state::InterpState;

/// Represents a branch in the syntax tree
#[derive(Debug, PartialEq)]
pub enum Branch {
    Custom(Rc<Vec<Branch>>),
    Builtin(Builtin),
    Int(i32),
    Float(f32),
    IfElse(Vec<Branch>, Vec<Branch>),
    Dotquote(String),
}

impl Branch {
    pub fn call(&self, state: &mut InterpState) {
        match *self {
            Branch::Custom(ref branches) => {
                for branch in branches.iter() {
                    branch.call(state);
                }
            }
            Branch::Builtin(ref builtin) => builtin.call(state),
            Branch::Int(int) => state.stack.push(int),
            Branch::Float(float) => state.stack.push(float as i32), //XXX
            Branch::IfElse(ref ifbranches, ref elsebranches) => {
                if state.stack.pop() {
                    for branch in ifbranches.iter() {
                        branch.call(state);
                    }
                } else {
                    for branch in elsebranches.iter() {
                        branch.call(state);
                    }
                }
            }
            Branch::Dotquote(ref text) => print!("{}", text),
        }
    }
}
<|endoftext|>