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

use syntax::codemap::FileName;

use config::config_type::ConfigType;
use config::file_lines::FileLines;
use config::lists::*;
use config::Config;
use {FmtResult, WRITE_MODE_LIST};

use failure::err_msg;

use getopts::Matches;
use std::collections::HashSet;
use std::path::{Path, PathBuf};
use std::str::FromStr;

/// Macro for deriving implementations of Serialize/Deserialize for enums
#[macro_export]
macro_rules! impl_enum_serialize_and_deserialize {
    ( $e:ident, $( $x:ident ),* ) => {
        impl ::serde::ser::Serialize for $e {
            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
                where S: ::serde::ser::Serializer
            {
                use serde::ser::Error;

                // We don't know whether the user of the macro has given us all options.
                #[allow(unreachable_patterns)]
                match *self {
                    $(
                        $e::$x => serializer.serialize_str(stringify!($x)),
                    )*
                    _ => {
                        Err(S::Error::custom(format!("Cannot serialize {:?}", self)))
                    }
                }
            }
        }

        impl<'de> ::serde::de::Deserialize<'de> for $e {
            fn deserialize<D>(d: D) -> Result<Self, D::Error>
                    where D: ::serde::Deserializer<'de> {
                use serde::de::{Error, Visitor};
                use std::marker::PhantomData;
                use std::fmt;
                struct StringOnly<T>(PhantomData<T>);
                impl<'de, T> Visitor<'de> for StringOnly<T>
                        where T: ::serde::Deserializer<'de> {
                    type Value = String;
                    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                        formatter.write_str("string")
                    }
                    fn visit_str<E>(self, value: &str) -> Result<String, E> {
                        Ok(String::from(value))
                    }
                }
                let s = d.deserialize_string(StringOnly::<D>(PhantomData))?;
                $(
                    if stringify!($x).eq_ignore_ascii_case(&s) {
                      return Ok($e::$x);
                    }
                )*
                static ALLOWED: &'static[&str] = &[$(stringify!($x),)*];
                Err(D::Error::unknown_variant(&s, ALLOWED))
            }
        }

        impl ::std::str::FromStr for $e {
            type Err = &'static str;

            fn from_str(s: &str) -> Result<Self, Self::Err> {
                $(
                    if stringify!($x).eq_ignore_ascii_case(s) {
                        return Ok($e::$x);
                    }
                )*
                Err("Bad variant")
            }
        }

        impl ConfigType for $e {
            fn doc_hint() -> String {
                let mut variants = Vec::new();
                $(
                    variants.push(stringify!($x));
                )*
                format!("[{}]", variants.join("|"))
            }
        }
    };
}

macro_rules! configuration_option_enum{
    ($e:ident: $( $x:ident ),+ $(,)*) => {
        #[derive(Copy, Clone, Eq, PartialEq, Debug)]
        pub enum $e {
            $( $x ),+
        }

        impl_enum_serialize_and_deserialize!($e, $( $x ),+);
    }
}

configuration_option_enum! { NewlineStyle:
    Windows, // \r\n
    Unix, // \n
    Native, // \r\n in Windows, \n on other platforms
}

configuration_option_enum! { BraceStyle:
    AlwaysNextLine,
    PreferSameLine,
    // Prefer same line except where there is a where clause, in which case force
    // the brace to the next line.
    SameLineWhere,
}

configuration_option_enum! { ControlBraceStyle:
    // K&R style, Rust community default
    AlwaysSameLine,
    // Stroustrup style
    ClosingNextLine,
    // Allman style
    AlwaysNextLine,
}

configuration_option_enum! { IndentStyle:
    // First line on the same line as the opening brace, all lines aligned with
    // the first line.
    Visual,
    // First line is on a new line and all lines align with block indent.
    Block,
}

configuration_option_enum! { Density:
    // Fit as much on one line as possible.
    Compressed,
    // Use more lines.
    Tall,
    // Place every item on a separate line.
    Vertical,
}

configuration_option_enum! { TypeDensity:
    // No spaces around "=" and "+"
    Compressed,
    // Spaces around " = " and " + "
    Wide,
}

impl Density {
    pub fn to_list_tactic(self) -> ListTactic {
        match self {
            Density::Compressed => ListTactic::Mixed,
            Density::Tall => ListTactic::HorizontalVertical,
            Density::Vertical => ListTactic::Vertical,
        }
    }
}

configuration_option_enum! { ReportTactic:
    Always,
    Unnumbered,
    Never,
}

configuration_option_enum! { WriteMode:
    // Backs the original file up and overwrites the original.
    Replace,
    // Overwrites original file without backup.
    Overwrite,
    // Writes the output to stdout.
    Display,
    // Writes the diff to stdout.
    Diff,
    // Displays how much of the input file was processed
    Coverage,
    // Unfancy stdout
    Plain,
    // Outputs a checkstyle XML file.
    Checkstyle,
    // Output the changed lines (for internal value only)
    Modified,
    // Checks if a diff can be generated. If so, rustfmt outputs a diff and quits with exit code 1.
    // This option is designed to be run in CI where a non-zero exit signifies non-standard code formatting.
    Check,
    // Rustfmt shouldn't output anything formatting-like (e.g., emit a help message).
    None,
}

configuration_option_enum! { Color:
    // Always use color, whether it is a piped or terminal output
    Always,
    // Never use color
    Never,
    // Automatically use color, if supported by terminal
    Auto,
}

#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct WidthHeuristics {
    // Maximum width of the args of a function call before falling back
    // to vertical formatting.
    pub fn_call_width: usize,
    // Maximum width in the body of a struct lit before falling back to
    // vertical formatting.
    pub struct_lit_width: usize,
    // Maximum width in the body of a struct variant before falling back
    // to vertical formatting.
    pub struct_variant_width: usize,
    // Maximum width of an array literal before falling back to vertical
    // formatting.
    pub array_width: usize,
    // Maximum length of a chain to fit on a single line.
    pub chain_width: usize,
    // Maximum line length for single line if-else expressions. A value
    // of zero means always break if-else expressions.
    pub single_line_if_else_max_width: usize,
}

impl WidthHeuristics {
    // Using this WidthHeuristics means we ignore heuristics.
    pub fn null() -> WidthHeuristics {
        WidthHeuristics {
            fn_call_width: usize::max_value(),
            struct_lit_width: 0,
            struct_variant_width: 0,
            array_width: usize::max_value(),
            chain_width: usize::max_value(),
            single_line_if_else_max_width: 0,
        }
    }

    // scale the default WidthHeuristics according to max_width
    pub fn scaled(max_width: usize) -> WidthHeuristics {
        let mut max_width_ratio: f32 = max_width as f32 / 100.0; // 100 is the default width -> default ratio is 1
        max_width_ratio = (max_width_ratio * 10.0).round() / 10.0; // round to the closest 0.1
        WidthHeuristics {
            fn_call_width: (60.0 * max_width_ratio).round() as usize,
            struct_lit_width: (18.0 * max_width_ratio).round() as usize,
            struct_variant_width: (35.0 * max_width_ratio).round() as usize,
            array_width: (60.0 * max_width_ratio).round() as usize,
            chain_width: (60.0 * max_width_ratio).round() as usize,
            single_line_if_else_max_width: (50.0 * max_width_ratio).round() as usize,
        }
    }
}

impl ::std::str::FromStr for WidthHeuristics {
    type Err = &'static str;

    fn from_str(_: &str) -> Result<Self, Self::Err> {
        Err("WidthHeuristics is not parsable")
    }
}

impl Default for WriteMode {
    fn default() -> WriteMode {
        WriteMode::Overwrite
    }
}

/// A set of directories, files and modules that rustfmt should ignore.
#[derive(Default, Deserialize, Serialize, Clone, Debug)]
pub struct IgnoreList(HashSet<PathBuf>);

impl IgnoreList {
    pub fn add_prefix(&mut self, dir: &Path) {
        self.0 = self.0
            .iter()
            .map(|s| {
                if s.has_root() {
                    s.clone()
                } else {
                    let mut path = PathBuf::from(dir);
                    path.push(s);
                    path
                }
            })
            .collect();
    }

    fn skip_file_inner(&self, file: &Path) -> bool {
        self.0.iter().any(|path| file.starts_with(path))
    }

    pub fn skip_file(&self, file: &FileName) -> bool {
        if let FileName::Real(ref path) = file {
            self.skip_file_inner(path)
        } else {
            false
        }
    }
}

impl ::std::str::FromStr for IgnoreList {
    type Err = &'static str;

    fn from_str(_: &str) -> Result<Self, Self::Err> {
        Err("IgnoreList is not parsable")
    }
}

/// Parsed command line options.
#[derive(Clone, Debug, Default)]
pub struct CliOptions {
    skip_children: Option<bool>,
    verbose: bool,
    verbose_diff: bool,
    pub(super) config_path: Option<PathBuf>,
    write_mode: Option<WriteMode>,
    color: Option<Color>,
    file_lines: FileLines, // Default is all lines in all files.
    unstable_features: bool,
    error_on_unformatted: Option<bool>,
}

impl CliOptions {
    pub fn from_matches(matches: &Matches) -> FmtResult<CliOptions> {
        let mut options = CliOptions::default();
        options.verbose = matches.opt_present("verbose");
        options.verbose_diff = matches.opt_present("verbose-diff");

        let unstable_features = matches.opt_present("unstable-features");
        let rust_nightly = option_env!("CFG_RELEASE_CHANNEL")
            .map(|c| c == "nightly")
            .unwrap_or(false);
        if unstable_features && !rust_nightly {
            return Err(format_err!(
                "Unstable features are only available on Nightly channel"
            ));
        } else {
            options.unstable_features = unstable_features;
        }

        options.config_path = matches.opt_str("config-path").map(PathBuf::from);

        if let Some(ref write_mode) = matches.opt_str("write-mode") {
            if let Ok(write_mode) = WriteMode::from_str(write_mode) {
                options.write_mode = Some(write_mode);
            } else {
                return Err(format_err!(
                    "Invalid write-mode: {}, expected one of {}",
                    write_mode,
                    WRITE_MODE_LIST
                ));
            }
        }

        if let Some(ref color) = matches.opt_str("color") {
            match Color::from_str(color) {
                Ok(color) => options.color = Some(color),
                _ => return Err(format_err!("Invalid color: {}", color)),
            }
        }

        if let Some(ref file_lines) = matches.opt_str("file-lines") {
            options.file_lines = file_lines.parse().map_err(err_msg)?;
        }

        if matches.opt_present("skip-children") {
            options.skip_children = Some(true);
        }
        if matches.opt_present("error-on-unformatted") {
            options.error_on_unformatted = Some(true);
        }

        Ok(options)
    }

    pub fn apply_to(self, config: &mut Config) {
        config.set().verbose(self.verbose);
        config.set().verbose_diff(self.verbose_diff);
        config.set().file_lines(self.file_lines);
        config.set().unstable_features(self.unstable_features);
        if let Some(skip_children) = self.skip_children {
            config.set().skip_children(skip_children);
        }
        if let Some(error_on_unformatted) = self.error_on_unformatted {
            config.set().error_on_unformatted(error_on_unformatted);
        }
        if let Some(write_mode) = self.write_mode {
            config.set().write_mode(write_mode);
        }
        if let Some(color) = self.color {
            config.set().color(color);
        }
    }

    pub fn verify_file_lines(&self, files: &[PathBuf]) {
        for f in self.file_lines.files() {
            match *f {
                FileName::Real(ref f) if files.contains(f) => {}
                FileName::Real(_) => {
                    eprintln!("Warning: Extra file listed in file_lines option '{}'", f)
                }
                _ => eprintln!("Warning: Not a file '{}'", f),
            }
        }
    }
}
<commit_msg>Do not scale WidthHeuristics when max_width less than 100<commit_after>// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use syntax::codemap::FileName;

use config::config_type::ConfigType;
use config::file_lines::FileLines;
use config::lists::*;
use config::Config;
use {FmtResult, WRITE_MODE_LIST};

use failure::err_msg;

use getopts::Matches;
use std::collections::HashSet;
use std::path::{Path, PathBuf};
use std::str::FromStr;

/// Macro for deriving implementations of Serialize/Deserialize for enums
#[macro_export]
macro_rules! impl_enum_serialize_and_deserialize {
    ( $e:ident, $( $x:ident ),* ) => {
        impl ::serde::ser::Serialize for $e {
            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
                where S: ::serde::ser::Serializer
            {
                use serde::ser::Error;

                // We don't know whether the user of the macro has given us all options.
                #[allow(unreachable_patterns)]
                match *self {
                    $(
                        $e::$x => serializer.serialize_str(stringify!($x)),
                    )*
                    _ => {
                        Err(S::Error::custom(format!("Cannot serialize {:?}", self)))
                    }
                }
            }
        }

        impl<'de> ::serde::de::Deserialize<'de> for $e {
            fn deserialize<D>(d: D) -> Result<Self, D::Error>
                    where D: ::serde::Deserializer<'de> {
                use serde::de::{Error, Visitor};
                use std::marker::PhantomData;
                use std::fmt;
                struct StringOnly<T>(PhantomData<T>);
                impl<'de, T> Visitor<'de> for StringOnly<T>
                        where T: ::serde::Deserializer<'de> {
                    type Value = String;
                    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                        formatter.write_str("string")
                    }
                    fn visit_str<E>(self, value: &str) -> Result<String, E> {
                        Ok(String::from(value))
                    }
                }
                let s = d.deserialize_string(StringOnly::<D>(PhantomData))?;
                $(
                    if stringify!($x).eq_ignore_ascii_case(&s) {
                      return Ok($e::$x);
                    }
                )*
                static ALLOWED: &'static[&str] = &[$(stringify!($x),)*];
                Err(D::Error::unknown_variant(&s, ALLOWED))
            }
        }

        impl ::std::str::FromStr for $e {
            type Err = &'static str;

            fn from_str(s: &str) -> Result<Self, Self::Err> {
                $(
                    if stringify!($x).eq_ignore_ascii_case(s) {
                        return Ok($e::$x);
                    }
                )*
                Err("Bad variant")
            }
        }

        impl ConfigType for $e {
            fn doc_hint() -> String {
                let mut variants = Vec::new();
                $(
                    variants.push(stringify!($x));
                )*
                format!("[{}]", variants.join("|"))
            }
        }
    };
}

macro_rules! configuration_option_enum{
    ($e:ident: $( $x:ident ),+ $(,)*) => {
        #[derive(Copy, Clone, Eq, PartialEq, Debug)]
        pub enum $e {
            $( $x ),+
        }

        impl_enum_serialize_and_deserialize!($e, $( $x ),+);
    }
}

configuration_option_enum! { NewlineStyle:
    Windows, // \r\n
    Unix, // \n
    Native, // \r\n in Windows, \n on other platforms
}

configuration_option_enum! { BraceStyle:
    AlwaysNextLine,
    PreferSameLine,
    // Prefer same line except where there is a where clause, in which case force
    // the brace to the next line.
    SameLineWhere,
}

configuration_option_enum! { ControlBraceStyle:
    // K&R style, Rust community default
    AlwaysSameLine,
    // Stroustrup style
    ClosingNextLine,
    // Allman style
    AlwaysNextLine,
}

configuration_option_enum! { IndentStyle:
    // First line on the same line as the opening brace, all lines aligned with
    // the first line.
    Visual,
    // First line is on a new line and all lines align with block indent.
    Block,
}

configuration_option_enum! { Density:
    // Fit as much on one line as possible.
    Compressed,
    // Use more lines.
    Tall,
    // Place every item on a separate line.
    Vertical,
}

configuration_option_enum! { TypeDensity:
    // No spaces around "=" and "+"
    Compressed,
    // Spaces around " = " and " + "
    Wide,
}

impl Density {
    pub fn to_list_tactic(self) -> ListTactic {
        match self {
            Density::Compressed => ListTactic::Mixed,
            Density::Tall => ListTactic::HorizontalVertical,
            Density::Vertical => ListTactic::Vertical,
        }
    }
}

configuration_option_enum! { ReportTactic:
    Always,
    Unnumbered,
    Never,
}

configuration_option_enum! { WriteMode:
    // Backs the original file up and overwrites the original.
    Replace,
    // Overwrites original file without backup.
    Overwrite,
    // Writes the output to stdout.
    Display,
    // Writes the diff to stdout.
    Diff,
    // Displays how much of the input file was processed
    Coverage,
    // Unfancy stdout
    Plain,
    // Outputs a checkstyle XML file.
    Checkstyle,
    // Output the changed lines (for internal value only)
    Modified,
    // Checks if a diff can be generated. If so, rustfmt outputs a diff and quits with exit code 1.
    // This option is designed to be run in CI where a non-zero exit signifies non-standard code formatting.
    Check,
    // Rustfmt shouldn't output anything formatting-like (e.g., emit a help message).
    None,
}

configuration_option_enum! { Color:
    // Always use color, whether it is a piped or terminal output
    Always,
    // Never use color
    Never,
    // Automatically use color, if supported by terminal
    Auto,
}

#[derive(Deserialize, Serialize, Clone, Debug)]
pub struct WidthHeuristics {
    // Maximum width of the args of a function call before falling back
    // to vertical formatting.
    pub fn_call_width: usize,
    // Maximum width in the body of a struct lit before falling back to
    // vertical formatting.
    pub struct_lit_width: usize,
    // Maximum width in the body of a struct variant before falling back
    // to vertical formatting.
    pub struct_variant_width: usize,
    // Maximum width of an array literal before falling back to vertical
    // formatting.
    pub array_width: usize,
    // Maximum length of a chain to fit on a single line.
    pub chain_width: usize,
    // Maximum line length for single line if-else expressions. A value
    // of zero means always break if-else expressions.
    pub single_line_if_else_max_width: usize,
}

impl WidthHeuristics {
    // Using this WidthHeuristics means we ignore heuristics.
    pub fn null() -> WidthHeuristics {
        WidthHeuristics {
            fn_call_width: usize::max_value(),
            struct_lit_width: 0,
            struct_variant_width: 0,
            array_width: usize::max_value(),
            chain_width: usize::max_value(),
            single_line_if_else_max_width: 0,
        }
    }

    // scale the default WidthHeuristics according to max_width
    pub fn scaled(max_width: usize) -> WidthHeuristics {
        const DEFAULT_MAX_WIDTH: usize = 100;
        let max_width_ratio = if max_width > DEFAULT_MAX_WIDTH {
            let ratio = max_width as f32 / DEFAULT_MAX_WIDTH as f32;
            // round to the closest 0.1
            (ratio * 10.0).round() / 10.0
        } else {
            1.0
        };
        WidthHeuristics {
            fn_call_width: (60.0 * max_width_ratio).round() as usize,
            struct_lit_width: (18.0 * max_width_ratio).round() as usize,
            struct_variant_width: (35.0 * max_width_ratio).round() as usize,
            array_width: (60.0 * max_width_ratio).round() as usize,
            chain_width: (60.0 * max_width_ratio).round() as usize,
            single_line_if_else_max_width: (50.0 * max_width_ratio).round() as usize,
        }
    }
}

impl ::std::str::FromStr for WidthHeuristics {
    type Err = &'static str;

    fn from_str(_: &str) -> Result<Self, Self::Err> {
        Err("WidthHeuristics is not parsable")
    }
}

impl Default for WriteMode {
    fn default() -> WriteMode {
        WriteMode::Overwrite
    }
}

/// A set of directories, files and modules that rustfmt should ignore.
#[derive(Default, Deserialize, Serialize, Clone, Debug)]
pub struct IgnoreList(HashSet<PathBuf>);

impl IgnoreList {
    pub fn add_prefix(&mut self, dir: &Path) {
        self.0 = self.0
            .iter()
            .map(|s| {
                if s.has_root() {
                    s.clone()
                } else {
                    let mut path = PathBuf::from(dir);
                    path.push(s);
                    path
                }
            })
            .collect();
    }

    fn skip_file_inner(&self, file: &Path) -> bool {
        self.0.iter().any(|path| file.starts_with(path))
    }

    pub fn skip_file(&self, file: &FileName) -> bool {
        if let FileName::Real(ref path) = file {
            self.skip_file_inner(path)
        } else {
            false
        }
    }
}

impl ::std::str::FromStr for IgnoreList {
    type Err = &'static str;

    fn from_str(_: &str) -> Result<Self, Self::Err> {
        Err("IgnoreList is not parsable")
    }
}

/// Parsed command line options.
#[derive(Clone, Debug, Default)]
pub struct CliOptions {
    skip_children: Option<bool>,
    verbose: bool,
    verbose_diff: bool,
    pub(super) config_path: Option<PathBuf>,
    write_mode: Option<WriteMode>,
    color: Option<Color>,
    file_lines: FileLines, // Default is all lines in all files.
    unstable_features: bool,
    error_on_unformatted: Option<bool>,
}

impl CliOptions {
    pub fn from_matches(matches: &Matches) -> FmtResult<CliOptions> {
        let mut options = CliOptions::default();
        options.verbose = matches.opt_present("verbose");
        options.verbose_diff = matches.opt_present("verbose-diff");

        let unstable_features = matches.opt_present("unstable-features");
        let rust_nightly = option_env!("CFG_RELEASE_CHANNEL")
            .map(|c| c == "nightly")
            .unwrap_or(false);
        if unstable_features && !rust_nightly {
            return Err(format_err!(
                "Unstable features are only available on Nightly channel"
            ));
        } else {
            options.unstable_features = unstable_features;
        }

        options.config_path = matches.opt_str("config-path").map(PathBuf::from);

        if let Some(ref write_mode) = matches.opt_str("write-mode") {
            if let Ok(write_mode) = WriteMode::from_str(write_mode) {
                options.write_mode = Some(write_mode);
            } else {
                return Err(format_err!(
                    "Invalid write-mode: {}, expected one of {}",
                    write_mode,
                    WRITE_MODE_LIST
                ));
            }
        }

        if let Some(ref color) = matches.opt_str("color") {
            match Color::from_str(color) {
                Ok(color) => options.color = Some(color),
                _ => return Err(format_err!("Invalid color: {}", color)),
            }
        }

        if let Some(ref file_lines) = matches.opt_str("file-lines") {
            options.file_lines = file_lines.parse().map_err(err_msg)?;
        }

        if matches.opt_present("skip-children") {
            options.skip_children = Some(true);
        }
        if matches.opt_present("error-on-unformatted") {
            options.error_on_unformatted = Some(true);
        }

        Ok(options)
    }

    pub fn apply_to(self, config: &mut Config) {
        config.set().verbose(self.verbose);
        config.set().verbose_diff(self.verbose_diff);
        config.set().file_lines(self.file_lines);
        config.set().unstable_features(self.unstable_features);
        if let Some(skip_children) = self.skip_children {
            config.set().skip_children(skip_children);
        }
        if let Some(error_on_unformatted) = self.error_on_unformatted {
            config.set().error_on_unformatted(error_on_unformatted);
        }
        if let Some(write_mode) = self.write_mode {
            config.set().write_mode(write_mode);
        }
        if let Some(color) = self.color {
            config.set().color(color);
        }
    }

    pub fn verify_file_lines(&self, files: &[PathBuf]) {
        for f in self.file_lines.files() {
            match *f {
                FileName::Real(ref f) if files.contains(f) => {}
                FileName::Real(_) => {
                    eprintln!("Warning: Extra file listed in file_lines option '{}'", f)
                }
                _ => eprintln!("Warning: Not a file '{}'", f),
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::{
    fs::{copy, create_dir_all, remove_file},
    path::Path,
};

use binary_stencila::{BinaryTrait, StencilaBinary};
use buildpack::{
    eyre,
    fs_utils::symlink_file,
    libcnb::{
        self,
        build::{BuildContext, BuildResult, BuildResultBuilder},
        data::{
            build_plan::BuildPlan,
            launch::{Launch, ProcessBuilder},
            layer_content_metadata::LayerTypes,
            layer_name, process_type,
        },
        detect::{DetectContext, DetectResult, DetectResultBuilder},
        generic::{GenericMetadata, GenericPlatform},
        layer::{ExistingLayerStrategy, Layer, LayerResult, LayerResultBuilder},
        Buildpack,
    },
    maplit::hashmap,
    tracing, BuildpackContext, BuildpackTrait, LayerOptions, LayerVersionMetadata,
};

pub struct StencilaBuildpack;

impl BuildpackTrait for StencilaBuildpack {
    fn toml() -> &'static str {
        include_str!("../buildpack.toml")
    }
}

const TOOL_VERSIONS: &str = ".tool-versions";

impl Buildpack for StencilaBuildpack {
    type Platform = GenericPlatform;
    type Metadata = GenericMetadata;
    type Error = eyre::Report;

    fn detect(&self, _context: DetectContext<Self>) -> libcnb::Result<DetectResult, Self::Error> {
        // Read `.tool-versions` for Stencila version
        let tool_versions = Self::tool_versions();

        // Resolve Stencila version from `.tool-versions`
        let (version, source) = if let Some(version) = tool_versions.get("stencila") {
            (version.to_string(), TOOL_VERSIONS)
        } else {
            // Default to at least 1.1.0 which is the first version with a `musl` binary suitable for
            // use in a CNB container
            (">=1.1.0".to_string(), "")
        };

        // Require and provide Stencila
        let (require, provide) = Self::require_and_provide(
            "stencila",
            source,
            format!("Install Stencila {}", version).trim(),
            Some(hashmap! {
                "version" => version
            }),
        );

        let mut build_plan = BuildPlan::new();
        build_plan.requires = vec![require];
        build_plan.provides = vec![provide];
        DetectResultBuilder::pass().build_plan(build_plan).build()
    }

    fn build(&self, context: BuildContext<Self>) -> libcnb::Result<BuildResult, Self::Error> {
        let entries = self.buildpack_plan_entries(&context.buildpack_plan);

        if let Some(options) = entries.get("stencila") {
            context.handle_layer(layer_name!("stencila"), StencilaLayer::new(options))?;
        }

        let launch = Launch::new().process(
            ProcessBuilder::new(process_type!("server"), "stencila")
                .args(["server", "start", "--url=0.0.0.0:9000"])
                .direct(true)
                .default(true)
                .build(),
        );

        BuildResultBuilder::new().launch(launch).build()
    }
}

struct StencilaLayer {
    /// The semantic version requirement for the `stencila` binary
    requirement: String,
}

impl StencilaLayer {
    fn new(options: &LayerOptions) -> Self {
        let requirement = options
            .get("version")
            .cloned()
            .unwrap_or_else(|| "*".to_string());

        Self { requirement }
    }
}

impl Layer for StencilaLayer {
    type Buildpack = StencilaBuildpack;
    type Metadata = LayerVersionMetadata;

    fn types(&self) -> LayerTypes {
        LayerTypes {
            build: true,
            launch: true,
            cache: true,
        }
    }

    fn existing_layer_strategy(
        &self,
        _context: &BuildContext<Self::Buildpack>,
        layer_data: &libcnb::layer::LayerData<Self::Metadata>,
    ) -> Result<libcnb::layer::ExistingLayerStrategy, <Self::Buildpack as Buildpack>::Error> {
        let version = &layer_data.content_metadata.metadata.version;
        let installed = StencilaBinary {}.semver_version_matches(version, &self.requirement)?;
        let strategy = if installed {
            tracing::info!(
                "Existing `stencila` layer has `stencila {}` which matches semver requirement `{}`; will keep",
                version,
                self.requirement
            );
            ExistingLayerStrategy::Keep
        } else {
            tracing::info!(
                "Existing `stencila` layer has `stencila {}` which does not match semver requirement `{}`; will recreate",
                version,
                self.requirement
            );
            ExistingLayerStrategy::Recreate
        };
        Ok(strategy)
    }

    fn create(
        &self,
        context: &BuildContext<Self::Buildpack>,
        layer_path: &Path,
    ) -> Result<LayerResult<Self::Metadata>, eyre::Report> {
        tracing::info!(
            "Creating `stencila` layer with semver requirement `{}`",
            self.requirement
        );

        let stencila = StencilaBinary {}.ensure_version_sync(&self.requirement)?;
        let version = stencila.version()?.to_string();

        let bin_path = layer_path.join("bin");
        create_dir_all(&bin_path)?;

        if context.is_local() {
            tracing::info!("Linking to `stencila {}`", version);

            symlink_file(stencila.path, bin_path.join(stencila.name))?;
        } else {
            #[allow(clippy::collapsible_else_if)]
            if stencila.is_stencila_install() {
                tracing::info!("Moving `stencila {}`", version);

                copy(&stencila.path, bin_path.join(stencila.name))?;
                remove_file(stencila.path)?;
            } else {
                tracing::info!("Linking to `stencila {}` installed on stack image", version);

                symlink_file(stencila.path, bin_path.join(stencila.name))?;
            }
        }

        // Store version in metadata to detect if layer is stale in `existing_layer_strategy()`
        let metadata = LayerVersionMetadata { version };

        LayerResultBuilder::new(metadata).build()
    }
}
<commit_msg>fix(Stencila buildpack): For non-local builds install into the layer dir<commit_after>use std::{fs::create_dir_all, path::Path};

use binary_stencila::{BinaryTrait, StencilaBinary};
use buildpack::{
    eyre,
    fs_utils::symlink_file,
    libcnb::{
        self,
        build::{BuildContext, BuildResult, BuildResultBuilder},
        data::{
            build_plan::BuildPlan,
            launch::{Launch, ProcessBuilder},
            layer_content_metadata::LayerTypes,
            layer_name, process_type,
        },
        detect::{DetectContext, DetectResult, DetectResultBuilder},
        generic::{GenericMetadata, GenericPlatform},
        layer::{ExistingLayerStrategy, Layer, LayerResult, LayerResultBuilder},
        Buildpack,
    },
    maplit::hashmap,
    tracing, BuildpackContext, BuildpackTrait, LayerOptions, LayerVersionMetadata,
};

pub struct StencilaBuildpack;

impl BuildpackTrait for StencilaBuildpack {
    fn toml() -> &'static str {
        include_str!("../buildpack.toml")
    }
}

const TOOL_VERSIONS: &str = ".tool-versions";

impl Buildpack for StencilaBuildpack {
    type Platform = GenericPlatform;
    type Metadata = GenericMetadata;
    type Error = eyre::Report;

    fn detect(&self, _context: DetectContext<Self>) -> libcnb::Result<DetectResult, Self::Error> {
        // Read `.tool-versions` for Stencila version
        let tool_versions = Self::tool_versions();

        // Resolve Stencila version from `.tool-versions`
        let (version, source) = if let Some(version) = tool_versions.get("stencila") {
            (version.to_string(), TOOL_VERSIONS)
        } else {
            // Default to at least 1.1.0 which is the first version with a `musl` binary suitable for
            // use in a CNB container
            (">=1.1.0".to_string(), "")
        };

        // Require and provide Stencila
        let (require, provide) = Self::require_and_provide(
            "stencila",
            source,
            format!("Install Stencila {}", version).trim(),
            Some(hashmap! {
                "version" => version
            }),
        );

        let mut build_plan = BuildPlan::new();
        build_plan.requires = vec![require];
        build_plan.provides = vec![provide];
        DetectResultBuilder::pass().build_plan(build_plan).build()
    }

    fn build(&self, context: BuildContext<Self>) -> libcnb::Result<BuildResult, Self::Error> {
        let entries = self.buildpack_plan_entries(&context.buildpack_plan);

        if let Some(options) = entries.get("stencila") {
            context.handle_layer(layer_name!("stencila"), StencilaLayer::new(options))?;
        }

        let launch = Launch::new().process(
            ProcessBuilder::new(process_type!("server"), "stencila")
                .args(["server", "start", "--url=0.0.0.0:9000"])
                .direct(true)
                .default(true)
                .build(),
        );

        BuildResultBuilder::new().launch(launch).build()
    }
}

struct StencilaLayer {
    /// The semantic version requirement for the `stencila` binary
    requirement: String,
}

impl StencilaLayer {
    fn new(options: &LayerOptions) -> Self {
        let requirement = options
            .get("version")
            .cloned()
            .unwrap_or_else(|| "*".to_string());

        Self { requirement }
    }
}

impl Layer for StencilaLayer {
    type Buildpack = StencilaBuildpack;
    type Metadata = LayerVersionMetadata;

    fn types(&self) -> LayerTypes {
        LayerTypes {
            build: true,
            launch: true,
            cache: true,
        }
    }

    fn existing_layer_strategy(
        &self,
        _context: &BuildContext<Self::Buildpack>,
        layer_data: &libcnb::layer::LayerData<Self::Metadata>,
    ) -> Result<libcnb::layer::ExistingLayerStrategy, <Self::Buildpack as Buildpack>::Error> {
        let version = &layer_data.content_metadata.metadata.version;
        let installed = StencilaBinary {}.semver_version_matches(version, &self.requirement)?;
        let strategy = if installed {
            tracing::info!(
                "Existing `stencila` layer has `stencila {}` which matches semver requirement `{}`; will keep",
                version,
                self.requirement
            );
            ExistingLayerStrategy::Keep
        } else {
            tracing::info!(
                "Existing `stencila` layer has `stencila {}` which does not match semver requirement `{}`; will recreate",
                version,
                self.requirement
            );
            ExistingLayerStrategy::Recreate
        };
        Ok(strategy)
    }

    fn create(
        &self,
        context: &BuildContext<Self::Buildpack>,
        layer_path: &Path,
    ) -> Result<LayerResult<Self::Metadata>, eyre::Report> {
        tracing::info!(
            "Creating `stencila` layer with semver requirement `{}`",
            self.requirement
        );

        let bin_path = layer_path.join("bin");
        create_dir_all(&bin_path)?;

        let version = if context.is_local() {
            let stencila = StencilaBinary {}.ensure_version_sync(&self.requirement)?;
            let version = stencila.version()?.to_string();

            tracing::info!("Linking to `stencila {}`", version);

            symlink_file(stencila.path, bin_path.join(stencila.name))?;

            version
        } else {
            tracing::info!("Installing `stencila {}`", self.requirement);

            StencilaBinary {}.install_in_sync(Some(self.requirement.clone()), Some(bin_path))?
        };

        // Store version in metadata to detect if layer is stale in `existing_layer_strategy()`
        let metadata = LayerVersionMetadata { version };

        LayerResultBuilder::new(metadata).build()
    }
}
<|endoftext|>


<commit_before>//! Contains test for all types supporting `bind_parameter`
//!
//! These tests assume there is a Stage table with a Varchar in 'A', an Integer in 'B' and a Real
//! in 'C'
extern crate odbc;
use odbc::*;

#[test]
#[ignore]
/// tested in windows中文版 codepage 936
fn _exec_direct() {
    let env = create_environment_v3().unwrap();
    let conn = env.connect("TestDataSource", "", "").unwrap();
    let stmt = Statement::with_parent(&conn).unwrap();

    // select '你好' as hello
    if let Ok(Data(mut stmt)) = stmt.exec_direct_bytes(vec![115, 101, 108, 101, 99, 116, 32, 39, 196, 227, 186, 195, 39, 32, 97, 115, 32, 104, 101, 108, 108, 111, 32].as_slice()) {
        while let Some(mut cursor) = stmt.fetch().unwrap() {
            match cursor.get_data::<Vec<u8>>(1).unwrap() {
                Some(val) => assert_eq!(val, vec![196, 227, 186, 195]),  // when  你好 is encoded by gbk, it is [196, 227, 186, 195]
                None => panic!(" NULL"),
            }
        }
    } else {
        panic!("SELECT did not return result set");
    }
}

#[test]
#[ignore]
/// tested in windows中文版 codepage 936
fn _prepare_1() {
    let env = create_environment_v3().unwrap();
    let conn = env.connect("TestDataSource", "", "").unwrap();
    // select '你好' as hello where 1 = ?
    let stmt = Statement::with_parent(&conn).unwrap().prepare_bytes(vec![115, 101, 108, 101, 99, 116, 32, 39, 196, 227, 186, 195, 39, 32, 97, 115, 32, 104, 101, 108, 108, 111, 32, 119, 104, 101, 114, 101, 32, 32, 49, 32, 61, 32, 63, 32].as_slice()).unwrap();
    let stmt = stmt.bind_parameter(1, &1).unwrap();

    match stmt.execute().unwrap() {
        Data(mut stmt) => {
            while let Some(mut cursor) = stmt.fetch().unwrap() {
                match cursor.get_data::<Vec<u8>>(1).unwrap() {
                    Some(val) => assert_eq!(val, vec![196, 227, 186, 195]),
                    None => panic!(" NULL"),
                }
            }
        }
        NoData(_) => {
            panic!("SELECT did not return result set");
        }
    }

}

#[test]
//#[ignore]
/// tested in windows中文版 codepage 936
fn _prepare_2() {
    let env = create_environment_v3().unwrap();
    let conn = env.connect("TestDataSource", "sa", "123456").unwrap();
    // select '你好' as hello where '你好' = ?
    let stmt = Statement::with_parent(&conn).unwrap().prepare_bytes(vec![115, 101, 108, 101, 99, 116, 32, 39, 228, 189, 160, 229, 165, 189, 39, 32, 97, 115, 32, 104, 101, 108, 108, 111, 32, 119, 104, 101, 114, 101, 32, 39, 228, 189, 160, 229, 165, 189, 39, 32, 61, 32, 63].as_slice()).unwrap();
    // bind  gbk encoded byte
    let param = CustomOdbcType {
        data: &[228, 189, 160, 229, 165, 189]
    };
    let stmt = stmt.bind_parameter(1, &param).unwrap();

    if let Ok(Data(mut stmt)) = stmt.execute() {
        if let Some(mut cursor) = stmt.fetch().unwrap() {
            match cursor.get_data::<Vec<u8>>(1).unwrap() {
                Some(val) => assert_eq!(val, vec![196, 227, 186, 195]),
                None => panic!(" NULL"),
            }
        } else {
            panic!("No data")
        }
    } else {
        panic!("SELECT did not return result set");
    }
}

#[test]
fn exec_direct() {
    let env = create_environment_v3().unwrap();
    let conn = env.connect("TestDataSource", "", "").unwrap();
    let stmt = Statement::with_parent(&conn).unwrap();

    // select 'hello'
    if let Ok(Data(mut stmt)) = stmt.exec_direct_bytes(vec![115, 101, 108, 101, 99, 116, 32, 39, 104, 101, 108, 108, 111, 39, 32].as_slice()) {
        if let Some(mut cursor) = stmt.fetch().unwrap() {
            match cursor.get_data::<Vec<u8>>(1).unwrap() {
                Some(val) => assert_eq!(val, vec![104, 101, 108, 108, 111]),  // when  hello is encoded by utf8, it is [104, 101, 108, 108, 111]
                None => panic!(" NULL"),
            }
        } else {
            panic!("No Data");
        }
    } else {
        panic!("SELECT did not return result set");
    }
}

#[test]
fn prepare_1() {
    let env = create_environment_v3().unwrap();
    let conn = env.connect("TestDataSource", "", "").unwrap();
    // select 'hello' where 'hello' = ?
    let stmt = Statement::with_parent(&conn).unwrap().prepare_bytes(vec![115, 101, 108, 101, 99, 116, 32, 39, 104, 101, 108, 108, 111, 39, 32, 119, 104, 101, 114, 101, 32, 39, 104, 101, 108, 108, 111, 39, 32, 61, 32, 63, 32].as_slice()).unwrap();
    let stmt = stmt.bind_parameter(1, &"hello").unwrap();

    if let Ok(Data(mut stmt)) = stmt.execute() {
        if let Some(mut cursor) = stmt.fetch().unwrap() {
            match cursor.get_data::<Vec<u8>>(1).unwrap() {
                Some(val) => assert_eq!(val, vec![104, 101, 108, 108, 111]),
                None => panic!(" NULL"),
            }
        } else {
            panic!("No data");
        }
    } else {
        panic!("SELECT did not return result set");
    }

}

/// CustomOdbcType  for bindParameter
struct CustomOdbcType<'a> {
    data: &'a [u8],
}

unsafe impl<'a> OdbcType<'a> for CustomOdbcType<'a> {
    fn sql_data_type() -> ffi::SqlDataType {
        ffi::SQL_VARCHAR
    }
    fn c_data_type() -> ffi::SqlCDataType {
        ffi::SQL_C_CHAR
    }

    fn convert(buffer: &'a [u8]) -> Self {
        CustomOdbcType {
            data: buffer
        }
    }

    fn column_size(&self) -> ffi::SQLULEN {
        self.data.len() as ffi::SQLULEN
    }

    fn value_ptr(&self) -> ffi::SQLPOINTER {
        self.data.as_ptr() as *const Self as ffi::SQLPOINTER
    }
}

#[test]
fn prepare_2() {
    let env = create_environment_v3().unwrap();
    let conn = env.connect("TestDataSource", "", "").unwrap();
    // select 'hello' where 'hello' = ?
    let stmt = Statement::with_parent(&conn).unwrap().prepare_bytes(vec![115, 101, 108, 101, 99, 116, 32, 39, 104, 101, 108, 108, 111, 39, 32, 119, 104, 101, 114, 101, 32, 39, 104, 101, 108, 108, 111, 39, 32, 61, 32, 63, 32].as_slice()).unwrap();
    // bind  utf encoded byte
//    let param: Vec<u8> = vec![104, 101, 108, 108, 111];
    let param = CustomOdbcType {
        data: &[104, 101, 108, 108, 111]
    };
    let stmt = stmt.bind_parameter(1, &param).unwrap();

    if let Ok(Data(mut stmt)) = stmt.execute() {
        if let Some(mut cursor) = stmt.fetch().unwrap() {
            match cursor.get_data::<Vec<u8>>(1).unwrap() {
                Some(val) => assert_eq!(val, vec![104, 101, 108, 108, 111]),
                None => panic!(" NULL"),
            }
        } else {
            panic!("No data");
        }
    } else {
        panic!("SELECT did not return result set");
    }
}
<commit_msg>add customOdbcType for bindParameter with none utf8 bytes<commit_after>//! Contains test for all types supporting `bind_parameter`
//!
//! These tests assume there is a Stage table with a Varchar in 'A', an Integer in 'B' and a Real
//! in 'C'
extern crate odbc;
use odbc::*;

#[test]
#[ignore]
/// tested in windows中文版 codepage 936
fn _exec_direct() {
    let env = create_environment_v3().unwrap();
    let conn = env.connect("TestDataSource", "", "").unwrap();
    let stmt = Statement::with_parent(&conn).unwrap();

    // select '你好' as hello
    if let Ok(Data(mut stmt)) = stmt.exec_direct_bytes(vec![115, 101, 108, 101, 99, 116, 32, 39, 196, 227, 186, 195, 39, 32, 97, 115, 32, 104, 101, 108, 108, 111, 32].as_slice()) {
        while let Some(mut cursor) = stmt.fetch().unwrap() {
            match cursor.get_data::<Vec<u8>>(1).unwrap() {
                Some(val) => assert_eq!(val, vec![196, 227, 186, 195]),  // when  你好 is encoded by gbk, it is [196, 227, 186, 195]
                None => panic!(" NULL"),
            }
        }
    } else {
        panic!("SELECT did not return result set");
    }
}

#[test]
#[ignore]
/// tested in windows中文版 codepage 936
fn _prepare_1() {
    let env = create_environment_v3().unwrap();
    let conn = env.connect("TestDataSource", "", "").unwrap();
    // select '你好' as hello where 1 = ?
    let stmt = Statement::with_parent(&conn).unwrap().prepare_bytes(vec![115, 101, 108, 101, 99, 116, 32, 39, 196, 227, 186, 195, 39, 32, 97, 115, 32, 104, 101, 108, 108, 111, 32, 119, 104, 101, 114, 101, 32, 32, 49, 32, 61, 32, 63, 32].as_slice()).unwrap();
    let stmt = stmt.bind_parameter(1, &1).unwrap();

    match stmt.execute().unwrap() {
        Data(mut stmt) => {
            while let Some(mut cursor) = stmt.fetch().unwrap() {
                match cursor.get_data::<Vec<u8>>(1).unwrap() {
                    Some(val) => assert_eq!(val, vec![196, 227, 186, 195]),
                    None => panic!(" NULL"),
                }
            }
        }
        NoData(_) => {
            panic!("SELECT did not return result set");
        }
    }

}

#[test]
#[ignore]
/// tested in windows中文版 codepage 936
fn _prepare_2() {
    let env = create_environment_v3().unwrap();
    let conn = env.connect("TestDataSource", "sa", "123456").unwrap();
    // select '你好' as hello where '你好' = ?
    let stmt = Statement::with_parent(&conn).unwrap().prepare_bytes(vec![115, 101, 108, 101, 99, 116, 32, 39, 228, 189, 160, 229, 165, 189, 39, 32, 97, 115, 32, 104, 101, 108, 108, 111, 32, 119, 104, 101, 114, 101, 32, 39, 228, 189, 160, 229, 165, 189, 39, 32, 61, 32, 63].as_slice()).unwrap();
    // bind  gbk encoded byte
    let param = CustomOdbcType {
        data: &[228, 189, 160, 229, 165, 189]
    };
    let stmt = stmt.bind_parameter(1, &param).unwrap();

    if let Ok(Data(mut stmt)) = stmt.execute() {
        if let Some(mut cursor) = stmt.fetch().unwrap() {
            match cursor.get_data::<Vec<u8>>(1).unwrap() {
                Some(val) => assert_eq!(val, vec![196, 227, 186, 195]),
                None => panic!(" NULL"),
            }
        } else {
            panic!("No data")
        }
    } else {
        panic!("SELECT did not return result set");
    }
}

#[test]
fn exec_direct() {
    let env = create_environment_v3().unwrap();
    let conn = env.connect("TestDataSource", "", "").unwrap();
    let stmt = Statement::with_parent(&conn).unwrap();

    // select 'hello'
    if let Ok(Data(mut stmt)) = stmt.exec_direct_bytes(vec![115, 101, 108, 101, 99, 116, 32, 39, 104, 101, 108, 108, 111, 39, 32].as_slice()) {
        if let Some(mut cursor) = stmt.fetch().unwrap() {
            match cursor.get_data::<Vec<u8>>(1).unwrap() {
                Some(val) => assert_eq!(val, vec![104, 101, 108, 108, 111]),  // when  hello is encoded by utf8, it is [104, 101, 108, 108, 111]
                None => panic!(" NULL"),
            }
        } else {
            panic!("No Data");
        }
    } else {
        panic!("SELECT did not return result set");
    }
}

#[test]
fn prepare_1() {
    let env = create_environment_v3().unwrap();
    let conn = env.connect("TestDataSource", "", "").unwrap();
    // select 'hello' where 'hello' = ?
    let stmt = Statement::with_parent(&conn).unwrap().prepare_bytes(vec![115, 101, 108, 101, 99, 116, 32, 39, 104, 101, 108, 108, 111, 39, 32, 119, 104, 101, 114, 101, 32, 39, 104, 101, 108, 108, 111, 39, 32, 61, 32, 63, 32].as_slice()).unwrap();
    let stmt = stmt.bind_parameter(1, &"hello").unwrap();

    if let Ok(Data(mut stmt)) = stmt.execute() {
        if let Some(mut cursor) = stmt.fetch().unwrap() {
            match cursor.get_data::<Vec<u8>>(1).unwrap() {
                Some(val) => assert_eq!(val, vec![104, 101, 108, 108, 111]),
                None => panic!(" NULL"),
            }
        } else {
            panic!("No data");
        }
    } else {
        panic!("SELECT did not return result set");
    }

}

/// CustomOdbcType  for bindParameter
struct CustomOdbcType<'a> {
    data: &'a [u8],
}

unsafe impl<'a> OdbcType<'a> for CustomOdbcType<'a> {
    fn sql_data_type() -> ffi::SqlDataType {
        ffi::SQL_VARCHAR
    }
    fn c_data_type() -> ffi::SqlCDataType {
        ffi::SQL_C_CHAR
    }

    fn convert(buffer: &'a [u8]) -> Self {
        CustomOdbcType {
            data: buffer
        }
    }

    fn column_size(&self) -> ffi::SQLULEN {
        self.data.len() as ffi::SQLULEN
    }

    fn value_ptr(&self) -> ffi::SQLPOINTER {
        self.data.as_ptr() as *const Self as ffi::SQLPOINTER
    }
}

#[test]
fn prepare_2() {
    let env = create_environment_v3().unwrap();
    let conn = env.connect("TestDataSource", "", "").unwrap();
    // select 'hello' where 'hello' = ?
    let stmt = Statement::with_parent(&conn).unwrap().prepare_bytes(vec![115, 101, 108, 101, 99, 116, 32, 39, 104, 101, 108, 108, 111, 39, 32, 119, 104, 101, 114, 101, 32, 39, 104, 101, 108, 108, 111, 39, 32, 61, 32, 63, 32].as_slice()).unwrap();
    // bind  utf encoded byte
//    let param: Vec<u8> = vec![104, 101, 108, 108, 111];
    let param = CustomOdbcType {
        data: &[104, 101, 108, 108, 111]
    };
    let stmt = stmt.bind_parameter(1, &param).unwrap();

    if let Ok(Data(mut stmt)) = stmt.execute() {
        if let Some(mut cursor) = stmt.fetch().unwrap() {
            match cursor.get_data::<Vec<u8>>(1).unwrap() {
                Some(val) => assert_eq!(val, vec![104, 101, 108, 108, 111]),
                None => panic!(" NULL"),
            }
        } else {
            panic!("No data");
        }
    } else {
        panic!("SELECT did not return result set");
    }
}
<|endoftext|>


<commit_before>extern crate vobject;
use vobject::parse_component;
use std::borrow::ToOwned;

macro_rules! s(
    ($i:expr) => ($i.to_owned());
);

#[test]
fn test_vcard_basic() {
    let item = parse_component(
        "BEGIN:VCARD\n\
        VERSION:2.1\n\
        N:Mustermann;Erika\n\
        FN:Erika Mustermann\n\
        ORG:Wikipedia\n\
        TITLE:Oberleutnant\n\
        PHOTO;JPEG:http://commons.wikimedia.org/wiki/File:Erika_Mustermann_2010.jpg\n\
        TEL;WORK;VOICE:(0221) 9999123\n\n\n\
        TEL;HOME;VOICE:(0221) 1234567\n\
        ADR;HOME:;;Heidestrasse 17;Koeln;;51147;Deutschland\n\
        EMAIL;PREF;INTERNET:erika@mustermann.de\n\
        REV:20140301T221110Z\n\
        END:VCARD\n\r\n\n").unwrap();

    assert_eq!(item.single_prop("FN").unwrap().raw_value, s!("Erika Mustermann"));
    assert_eq!(item.single_prop("N").unwrap().raw_value,  s!("Mustermann;Erika"));

    let mut tel_values = item.all_props("TEL").iter().map(|x| &x.raw_value[..]);
    assert_eq!(tel_values.next().unwrap(), s!("(0221) 9999123"));
    assert_eq!(tel_values.next().unwrap(), s!("(0221) 1234567"));
    assert!(tel_values.next().is_none());
}

#[test]
fn test_line_cont() {
    let item = parse_component(
        "BEGIN:VCARD\n\
        VERSION:2.1\n\
        N;ENCODING=QUOTED-PRINTABLE:Nikdo;Nikdo=\n\t\
        vic\n\
        FN;ENCODING=QUOTED-PRINT\n \
        ABLE:Alice;Alice=vic\n\
        NOTE:This ends with equal sign=\n\
        TEL;WORK:5555\n \
        4444\n\
        END:VCARD").unwrap();

    assert_eq!(item.name, s!("VCARD"));
    assert_eq!(item.single_prop("TEL").unwrap().raw_value, s!("55554444"));
    assert_eq!(item.single_prop("N").unwrap().raw_value, s!("Nikdo;Nikdo=vic"));
    assert_eq!(item.single_prop("FN").unwrap().raw_value, s!("Alice;Alice=vic"));
}

#[test]
fn test_icalendar_basic() {
    let item = parse_component(
            "BEGIN:VCALENDAR\n\
            VERSION:2.0\n\
            PRODID:http://www.example.com/calendarapplication/\n\
            METHOD:PUBLISH\n\
            BEGIN:VEVENT\n\
            UID:461092315540@example.com\n\
            ORGANIZER;CN=\"Alice Balder, Example Inc.\":MAILTO:alice@example.com\n\
            LOCATION:Somewhere\n\
            SUMMARY:Eine Kurzinfo\n\
            DESCRIPTION:Beschreibung des Termines\n\
            CLASS:PUBLIC\n\
            DTSTART:20060910T220000Z\n\
            DTEND:20060919T215900Z\n\
            DTSTAMP:20060812T125900Z\n\
            END:VEVENT\n\
            END:VCALENDAR\n").unwrap();

    assert_eq!(item.name, s!("VCALENDAR"));
    assert!(item.single_prop("LOCATION").is_none());
    assert!(item.single_prop("ORGANIZER").is_none());

    let event = &item.subcomponents[0];
    assert_eq!(event.name, s!("VEVENT"));
    assert!(event.single_prop("ORGANIZER").is_some());
    assert_eq!(event.single_prop("LOCATION").unwrap().raw_value, s!("Somewhere"));
}

#[test]
fn test_icalendar_multline() {
    // Adapted from a very popular provider's export
    // this used to give ParseError { desc: "Expected :, found \n" }
    let event = parse_component(
        "BEGIN:VEVENT\n\
        ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;CN=Jo\n \
        hn Doe;X-NUM-GUESTS=0:mailto:jd@cal.test\n\
        SUMMARY:Important meeting\n\
        END:VEVENT\n").unwrap();

    assert_eq!(event.name, s!("VEVENT"));
    assert_eq!(event.single_prop("SUMMARY").unwrap().raw_value,
               s!("Important meeting"));
}

#[test]
fn test_icalendar_multline2() {
    // Adapted from a very popular provider's export
    // this used to give ParseError { desc: "No property name found." }
    let event = parse_component(
        "BEGIN:VCALENDAR\n\
        BEGIN:VEVENT\n\
        ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;CN=Jo\n \
        hn Doe;X-NUM-GUESTS=0:mailto:jd@cal.test\n\
        SUMMARY:Important meeting\n\
        END:VEVENT\n\
        END:VCALENDAR\n").unwrap();

}

#[test]
fn test_escaping() {
    let item = parse_component(
            "BEGIN:VCALENDAR\n\
            ORGANIZER;CN=\"Cott:n Eye Joe\":mailto:joe@joe.com\n\
            END:VCALENDAR\n").unwrap();
    assert_eq!(item.name, s!("VCALENDAR"));
    assert_eq!(item.single_prop("ORGANIZER").unwrap().raw_value, s!("mailto:joe@joe.com"));
}

#[test]
fn test_property_groups() {
    let item = parse_component(
            "BEGIN:VCARD\n\
            foo.EMAIL;TYPE=INTERNET:foo@example.com\n\
            foo.X-ACTUAL-TYPE:CUSTOM\n\
            END:VCARD\n").unwrap();
    assert_eq!(item.single_prop("EMAIL").unwrap().prop_group, Some("foo".to_owned()));

}
<commit_msg>Got rid of 'unused' warning<commit_after>extern crate vobject;
use vobject::parse_component;
use std::borrow::ToOwned;

macro_rules! s(
    ($i:expr) => ($i.to_owned());
);

#[test]
fn test_vcard_basic() {
    let item = parse_component(
        "BEGIN:VCARD\n\
        VERSION:2.1\n\
        N:Mustermann;Erika\n\
        FN:Erika Mustermann\n\
        ORG:Wikipedia\n\
        TITLE:Oberleutnant\n\
        PHOTO;JPEG:http://commons.wikimedia.org/wiki/File:Erika_Mustermann_2010.jpg\n\
        TEL;WORK;VOICE:(0221) 9999123\n\n\n\
        TEL;HOME;VOICE:(0221) 1234567\n\
        ADR;HOME:;;Heidestrasse 17;Koeln;;51147;Deutschland\n\
        EMAIL;PREF;INTERNET:erika@mustermann.de\n\
        REV:20140301T221110Z\n\
        END:VCARD\n\r\n\n").unwrap();

    assert_eq!(item.single_prop("FN").unwrap().raw_value, s!("Erika Mustermann"));
    assert_eq!(item.single_prop("N").unwrap().raw_value,  s!("Mustermann;Erika"));

    let mut tel_values = item.all_props("TEL").iter().map(|x| &x.raw_value[..]);
    assert_eq!(tel_values.next().unwrap(), s!("(0221) 9999123"));
    assert_eq!(tel_values.next().unwrap(), s!("(0221) 1234567"));
    assert!(tel_values.next().is_none());
}

#[test]
fn test_line_cont() {
    let item = parse_component(
        "BEGIN:VCARD\n\
        VERSION:2.1\n\
        N;ENCODING=QUOTED-PRINTABLE:Nikdo;Nikdo=\n\t\
        vic\n\
        FN;ENCODING=QUOTED-PRINT\n \
        ABLE:Alice;Alice=vic\n\
        NOTE:This ends with equal sign=\n\
        TEL;WORK:5555\n \
        4444\n\
        END:VCARD").unwrap();

    assert_eq!(item.name, s!("VCARD"));
    assert_eq!(item.single_prop("TEL").unwrap().raw_value, s!("55554444"));
    assert_eq!(item.single_prop("N").unwrap().raw_value, s!("Nikdo;Nikdo=vic"));
    assert_eq!(item.single_prop("FN").unwrap().raw_value, s!("Alice;Alice=vic"));
}

#[test]
fn test_icalendar_basic() {
    let item = parse_component(
            "BEGIN:VCALENDAR\n\
            VERSION:2.0\n\
            PRODID:http://www.example.com/calendarapplication/\n\
            METHOD:PUBLISH\n\
            BEGIN:VEVENT\n\
            UID:461092315540@example.com\n\
            ORGANIZER;CN=\"Alice Balder, Example Inc.\":MAILTO:alice@example.com\n\
            LOCATION:Somewhere\n\
            SUMMARY:Eine Kurzinfo\n\
            DESCRIPTION:Beschreibung des Termines\n\
            CLASS:PUBLIC\n\
            DTSTART:20060910T220000Z\n\
            DTEND:20060919T215900Z\n\
            DTSTAMP:20060812T125900Z\n\
            END:VEVENT\n\
            END:VCALENDAR\n").unwrap();

    assert_eq!(item.name, s!("VCALENDAR"));
    assert!(item.single_prop("LOCATION").is_none());
    assert!(item.single_prop("ORGANIZER").is_none());

    let event = &item.subcomponents[0];
    assert_eq!(event.name, s!("VEVENT"));
    assert!(event.single_prop("ORGANIZER").is_some());
    assert_eq!(event.single_prop("LOCATION").unwrap().raw_value, s!("Somewhere"));
}

#[test]
fn test_icalendar_multline() {
    // Adapted from a very popular provider's export
    // this used to give ParseError { desc: "Expected :, found \n" }
    let event = parse_component(
        "BEGIN:VEVENT\n\
        ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;CN=Jo\n \
        hn Doe;X-NUM-GUESTS=0:mailto:jd@cal.test\n\
        SUMMARY:Important meeting\n\
        END:VEVENT\n").unwrap();

    assert_eq!(event.name, s!("VEVENT"));
    assert_eq!(event.single_prop("SUMMARY").unwrap().raw_value,
               s!("Important meeting"));
}

#[test]
fn test_icalendar_multline2() {
    // Adapted from a very popular provider's export
    // this used to give ParseError { desc: "No property name found." }
    let event = parse_component(
        "BEGIN:VCALENDAR\n\
        BEGIN:VEVENT\n\
        ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;CN=Jo\n \
        hn Doe;X-NUM-GUESTS=0:mailto:jd@cal.test\n\
        SUMMARY:Important meeting\n\
        END:VEVENT\n\
        END:VCALENDAR\n").unwrap();

    assert_eq!(event.name, s!("VCALENDAR"));
}

#[test]
fn test_escaping() {
    let item = parse_component(
            "BEGIN:VCALENDAR\n\
            ORGANIZER;CN=\"Cott:n Eye Joe\":mailto:joe@joe.com\n\
            END:VCALENDAR\n").unwrap();
    assert_eq!(item.name, s!("VCALENDAR"));
    assert_eq!(item.single_prop("ORGANIZER").unwrap().raw_value, s!("mailto:joe@joe.com"));
}

#[test]
fn test_property_groups() {
    let item = parse_component(
            "BEGIN:VCARD\n\
            foo.EMAIL;TYPE=INTERNET:foo@example.com\n\
            foo.X-ACTUAL-TYPE:CUSTOM\n\
            END:VCARD\n").unwrap();
    assert_eq!(item.single_prop("EMAIL").unwrap().prop_group, Some("foo".to_owned()));

}
<|endoftext|>


<commit_before>extern crate rust_guessing_game;
use rust_guessing_game::my_funcs;

#[test]
fn compare_greater_than() {
    assert!(my_funcs::compare(1,0) == Greater);
}

#[test]
fn compare_less_than() {
    assert!(my_funcs::compare(0,1) == Less);
}

#[test]
fn compare_equal_to() {
    assert!(my_funcs::compare(1,1) == Equal);
}
<commit_msg>Inlcude ordering<commit_after>extern crate rust_guessing_game;
use rust_guessing_game::my_funcs;
use std::cmp::Ordering;

#[test]
fn compare_greater_than() {
    assert!(my_funcs::compare(1,0) == Ordering::Greater);
}

#[test]
fn compare_less_than() {
    assert!(my_funcs::compare(0,1) == Ordering::Less);
}

#[test]
fn compare_equal_to() {
    assert!(my_funcs::compare(1,1) == Ordering::Equal);
}
<|endoftext|>


<commit_before>#![feature(collections)]

extern crate macaroons;
pub use macaroons::{Token, Tag};
pub use macaroons::caveat::{Caveat, Predicate};

fn example_key() -> Vec<u8> {
  String::from_str("this is our super secret key; only we should know it").into_bytes()
}

fn example_id() -> Vec<u8> {
  String::from_str("we used our secret key").into_bytes()
}

fn example_uri() -> Vec<u8> {
  String::from_str("http://mybank/").into_bytes()
}

fn example_predicate() -> Predicate {
  Predicate(String::from_str("test = caveat").into_bytes())
}

fn example_macaroon() -> Vec<u8> {
  String::from_str("MDAxY2xvY2F0aW9uIGh0dHA6Ly9teWJhbmsvCjAwMjZpZGVudGlmaWVyIHdlIHVzZWQgb3VyIHNlY3JldCBrZXkKMDAxNmNpZCB0ZXN0ID0gY2F2ZWF0CjAwMmZzaWduYXR1cmUgGXusegRK8zMyhluSZuJtSTvdZopmDkTYjOGpmMI9vWcK").into_bytes()
}

#[test]
fn empty_macaroon_signature() {
  let token = Token::new(example_key(), example_id(), example_uri());

  let expected_tag = [0xe3,0xd9,0xe0,0x29,0x08,0x52,0x6c,0x4c
                     ,0x00,0x39,0xae,0x15,0x11,0x41,0x15,0xd9
                     ,0x7f,0xdd,0x68,0xbf,0x2b,0xa3,0x79,0xb3
                     ,0x42,0xaa,0xf0,0xf6,0x17,0xd0,0x55,0x2f];

  let Tag(actual_tag) = token.tag;
  assert_eq!(expected_tag, actual_tag)
}

#[test]
fn signature_with_first_party_caveat() {
  let token = Token::new(example_key(), example_id(), example_uri());
  let new_token = token.add_caveat(Caveat::new(example_predicate()));

  let expected_tag = [0x19,0x7b,0xac,0x7a,0x04,0x4a,0xf3,0x33
                     ,0x32,0x86,0x5b,0x92,0x66,0xe2,0x6d,0x49
                     ,0x3b,0xdd,0x66,0x8a,0x66,0x0e,0x44,0xd8
                     ,0x8c,0xe1,0xa9,0x98,0xc2,0x3d,0xbd,0x67];

  let Tag(actual_tag) = new_token.tag;
  assert_eq!(expected_tag, actual_tag)
}

#[test]
fn binary_serialization() {
  let token = Token::new(example_key(), example_id(), example_uri());
  let new_token = token.add_caveat(Caveat::new(example_predicate()));

  assert_eq!(example_macaroon(), new_token.serialize());
}
<commit_msg>Extract EXPECTED_TAG<commit_after>#![feature(collections)]

extern crate macaroons;
pub use macaroons::{Token, Tag};
pub use macaroons::caveat::{Caveat, Predicate};

const EXPECTED_TAG: [u8; 32] = [0x19,0x7b,0xac,0x7a,0x04,0x4a,0xf3,0x33
                               ,0x32,0x86,0x5b,0x92,0x66,0xe2,0x6d,0x49
                               ,0x3b,0xdd,0x66,0x8a,0x66,0x0e,0x44,0xd8
                               ,0x8c,0xe1,0xa9,0x98,0xc2,0x3d,0xbd,0x67];

fn example_key() -> Vec<u8> {
  String::from_str("this is our super secret key; only we should know it").into_bytes()
}

fn example_id() -> Vec<u8> {
  String::from_str("we used our secret key").into_bytes()
}

fn example_uri() -> Vec<u8> {
  String::from_str("http://mybank/").into_bytes()
}

fn example_predicate() -> Predicate {
  Predicate(String::from_str("test = caveat").into_bytes())
}

fn example_macaroon() -> Vec<u8> {
  String::from_str("MDAxY2xvY2F0aW9uIGh0dHA6Ly9teWJhbmsvCjAwMjZpZGVudGlmaWVyIHdlIHVzZWQgb3VyIHNlY3JldCBrZXkKMDAxNmNpZCB0ZXN0ID0gY2F2ZWF0CjAwMmZzaWduYXR1cmUgGXusegRK8zMyhluSZuJtSTvdZopmDkTYjOGpmMI9vWcK").into_bytes()
}

#[test]
fn empty_macaroon_signature() {
  let token = Token::new(example_key(), example_id(), example_uri());

  let expected_tag = [0xe3,0xd9,0xe0,0x29,0x08,0x52,0x6c,0x4c
                     ,0x00,0x39,0xae,0x15,0x11,0x41,0x15,0xd9
                     ,0x7f,0xdd,0x68,0xbf,0x2b,0xa3,0x79,0xb3
                     ,0x42,0xaa,0xf0,0xf6,0x17,0xd0,0x55,0x2f];

  let Tag(actual_tag) = token.tag;
  assert_eq!(expected_tag, actual_tag)
}

#[test]
fn signature_with_first_party_caveat() {
  let token = Token::new(example_key(), example_id(), example_uri());
  let new_token = token.add_caveat(Caveat::new(example_predicate()));

  let Tag(actual_tag) = new_token.tag;
  assert_eq!(EXPECTED_TAG, actual_tag)
}

#[test]
fn binary_serialization() {
  let token = Token::new(example_key(), example_id(), example_uri());
  let new_token = token.add_caveat(Caveat::new(example_predicate()));

  assert_eq!(example_macaroon(), new_token.serialize());
}
<|endoftext|>


<commit_before>#![no_std]
#[macro_use]
extern crate generic_array;
use generic_array::typenum::{U1, U3, U97};
use generic_array::GenericArray;
use core::ops::Drop;
use core::cell::Cell;

#[test]
fn test() {
    let mut list97 = [0; 97];
    for i in 0..97 {
        list97[i] = i as i32;
    }
    let l: GenericArray<i32, U97> = GenericArray::clone_from_slice(&list97);
    assert_eq!(l[0], 0);
    assert_eq!(l[1], 1);
    assert_eq!(l[32], 32);
    assert_eq!(l[56], 56);
}

#[test]
fn test_drop() {
    #[derive(Clone)]
    struct TestDrop<'a>(&'a Cell<u32>);

    impl<'a> Drop for TestDrop<'a> {
        fn drop(&mut self) {
            self.0.set(self.0.get() + 1);
        }
    }

    let drop_counter = Cell::new(0);
    {
        let _: GenericArray<TestDrop, U3> = arr![TestDrop; TestDrop(&drop_counter), TestDrop(&drop_counter), TestDrop(&drop_counter)];
    }
    assert_eq!(drop_counter.get(), 3);
}

#[test]
fn test_arr() {
    let test: GenericArray<u32, U3> = arr![u32; 1, 2, 3];
    assert_eq!(test[1], 2);
}

#[test]
fn test_copy() {
    let test = arr![u32; 1, 2, 3];
    let test2 = test;
    // if GenericArray is not copy, this should fail as a use of a moved value
    assert_eq!(test[1], 2);
    assert_eq!(test2[0], 1);
}

#[test]
fn test_iter_flat_map() {
    assert!((0..5)
                .flat_map(|i| arr![i32; 2 * i, 2 * i + 1])
                .eq(0..10));
}

#[derive(Debug, PartialEq, Eq)]
struct NoClone<T>(T);

#[test]
fn test_from_slice() {
    let arr = [1, 2, 3, 4];
    let gen_arr = GenericArray::<_, U3>::from_slice(&arr[..3]);
    assert_eq!(&arr[..3], gen_arr.as_slice());
    let arr = [NoClone(1u32), NoClone(2), NoClone(3), NoClone(4)];
    let gen_arr = GenericArray::<_, U3>::from_slice(&arr[..3]);
    assert_eq!(&arr[..3], gen_arr.as_slice());
}

#[test]
fn test_from_mut_slice() {
    let mut arr = [1, 2, 3, 4];
    {
        let mut gen_arr = GenericArray::<_, U3>::from_mut_slice(&mut arr[..3]);
        gen_arr[2] = 10;
    }
    assert_eq!(arr, [1, 2, 10, 4]);
    let mut arr = [NoClone(1u32), NoClone(2), NoClone(3), NoClone(4)];
    {
        let mut gen_arr = GenericArray::<_, U3>::from_mut_slice(&mut arr[..3]);
        gen_arr[2] = NoClone(10);
    }
    assert_eq!(arr, [NoClone(1), NoClone(2), NoClone(10), NoClone(4)]);
}

#[test]
fn test_default() {
    let arr = GenericArray::<u8, U1>::default();
    assert_eq!(arr[0], 0);
}

#[test]
fn test_unit_macro() {
    let arr = arr![f32; 3.14];
    assert_eq!(arr[0], 3.14);
}

#[test]
fn test_empty_macro() {
    let arr = arr![f32;];
}

/// This test should cause a helpful compile error if uncommented.
// #[test]
// fn test_empty_macro2(){
//     let arr = arr![];
// }
#[cfg(feature="serde")]
mod impl_serde {
    extern crate serde_json;

    use generic_array::GenericArray;
    use generic_array::typenum::U6;

    #[test]
    fn test_serde_implementation() {
        let array: GenericArray<f64, U6> = arr![f64; 0.0, 5.0, 3.0, 7.07192, 76.0, -9.0];
        let string = serde_json::to_string(&array).unwrap();
        assert_eq!(string, "[0.0,5.0,3.0,7.07192,76.0,-9.0]");

        let test_array: GenericArray<f64, U6> = serde_json::from_str(&string).unwrap();
        assert_eq!(test_array, array);
    }
}
<commit_msg>Remove trailing whitespace<commit_after>#![no_std]
#[macro_use]
extern crate generic_array;
use generic_array::typenum::{U1, U3, U97};
use generic_array::GenericArray;
use core::ops::Drop;
use core::cell::Cell;

#[test]
fn test() {
    let mut list97 = [0; 97];
    for i in 0..97 {
        list97[i] = i as i32;
    }
    let l: GenericArray<i32, U97> = GenericArray::clone_from_slice(&list97);
    assert_eq!(l[0], 0);
    assert_eq!(l[1], 1);
    assert_eq!(l[32], 32);
    assert_eq!(l[56], 56);
}

#[test]
fn test_drop() {
    #[derive(Clone)]
    struct TestDrop<'a>(&'a Cell<u32>);

    impl<'a> Drop for TestDrop<'a> {
        fn drop(&mut self) {
            self.0.set(self.0.get() + 1);
        }
    }

    let drop_counter = Cell::new(0);
    {
        let _: GenericArray<TestDrop, U3> = arr![TestDrop; TestDrop(&drop_counter), TestDrop(&drop_counter), TestDrop(&drop_counter)];
    }
    assert_eq!(drop_counter.get(), 3);
}

#[test]
fn test_arr() {
    let test: GenericArray<u32, U3> = arr![u32; 1, 2, 3];
    assert_eq!(test[1], 2);
}

#[test]
fn test_copy() {
    let test = arr![u32; 1, 2, 3];
    let test2 = test;
    // if GenericArray is not copy, this should fail as a use of a moved value
    assert_eq!(test[1], 2);
    assert_eq!(test2[0], 1);
}

#[test]
fn test_iter_flat_map() {
    assert!((0..5)
                .flat_map(|i| arr![i32; 2 * i, 2 * i + 1])
                .eq(0..10));
}

#[derive(Debug, PartialEq, Eq)]
struct NoClone<T>(T);

#[test]
fn test_from_slice() {
    let arr = [1, 2, 3, 4];
    let gen_arr = GenericArray::<_, U3>::from_slice(&arr[..3]);
    assert_eq!(&arr[..3], gen_arr.as_slice());
    let arr = [NoClone(1u32), NoClone(2), NoClone(3), NoClone(4)];
    let gen_arr = GenericArray::<_, U3>::from_slice(&arr[..3]);
    assert_eq!(&arr[..3], gen_arr.as_slice());
}

#[test]
fn test_from_mut_slice() {
    let mut arr = [1, 2, 3, 4];
    {
        let mut gen_arr = GenericArray::<_, U3>::from_mut_slice(&mut arr[..3]);
        gen_arr[2] = 10;
    }
    assert_eq!(arr, [1, 2, 10, 4]);
    let mut arr = [NoClone(1u32), NoClone(2), NoClone(3), NoClone(4)];
    {
        let mut gen_arr = GenericArray::<_, U3>::from_mut_slice(&mut arr[..3]);
        gen_arr[2] = NoClone(10);
    }
    assert_eq!(arr, [NoClone(1), NoClone(2), NoClone(10), NoClone(4)]);
}

#[test]
fn test_default() {
    let arr = GenericArray::<u8, U1>::default();
    assert_eq!(arr[0], 0);
}

#[test]
fn test_unit_macro() {
    let arr = arr![f32; 3.14];
    assert_eq!(arr[0], 3.14);
}

#[test]
fn test_empty_macro() {
    let arr = arr![f32;];
}

/// This test should cause a helpful compile error if uncommented.
// #[test]
// fn test_empty_macro2(){
//     let arr = arr![];
// }
#[cfg(feature="serde")]
mod impl_serde {
    extern crate serde_json;

    use generic_array::GenericArray;
    use generic_array::typenum::U6;

    #[test]
    fn test_serde_implementation() {
        let array: GenericArray<f64, U6> = arr![f64; 0.0, 5.0, 3.0, 7.07192, 76.0, -9.0];
        let string = serde_json::to_string(&array).unwrap();
        assert_eq!(string, "[0.0,5.0,3.0,7.07192,76.0,-9.0]");

        let test_array: GenericArray<f64, U6> = serde_json::from_str(&string).unwrap();
        assert_eq!(test_array, array);
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2017 Jason White
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use std::fmt;
use std::fs;
use std::io;
use std::path::{Path, PathBuf};

use super::traits::Task;
use detect::Detected;
use error::Error;

use res;
use util::{progress_dummy, Retry};

/// A task to create a directory.
#[derive(
    Serialize, Deserialize, Ord, PartialOrd, Eq, PartialEq, Hash, Clone,
)]
pub struct MakeDir {
    /// Path to the directory to create.
    path: PathBuf,

    /// Retry settings.
    #[serde(default)]
    retry: Retry,
}

impl MakeDir {
    pub fn new(path: PathBuf) -> MakeDir {
        MakeDir {
            path,
            retry: Retry::default(),
        }
    }

    fn execute_impl(
        &self,
        root: &Path,
        _log: &mut io::Write,
    ) -> Result<Detected, Error> {
        // Only create the last directory, not the entire directory path. We
        // would not be able to properly clean up directories if we did the
        // equivalent of `mkdir -p`. Instead, the entire directory path chain
        // should be coded into the build graph. For example, to create the
        // directory path `obj/x64`, there should be two rules: one for creating
        // `obj` and one for creating `obj/x64`. We automatically add a
        // dependency on the parent path such that they get created in the
        // correct order.
        fs::create_dir(&root.join(&self.path))?;

        Ok(Detected::new())
    }
}

impl fmt::Display for MakeDir {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "mkdir {:?}", self.path)
    }
}

impl fmt::Debug for MakeDir {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self)
    }
}

impl Task for MakeDir {
    fn execute(
        &self,
        root: &Path,
        log: &mut io::Write,
    ) -> Result<Detected, Error> {
        self.retry
            .call(|| self.execute_impl(root, log), progress_dummy)
    }

    fn known_inputs(&self, set: &mut res::Set) {
        // Add parent directory as an input. Adding this dependency also ensures
        // that we delete directories in the correct order relative to one
        // another.
        if let Some(parent) = self.path.parent() {
            if parent != Path::new("") && parent != Path::new(".") {
                set.insert(res::Dir::new(parent.to_path_buf()).into());
            }
        }
    }

    fn known_outputs(&self, set: &mut res::Set) {
        set.insert(res::Dir::new(self.path.clone()).into());
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use res;

    #[test]
    fn known_inputs_parent() {
        let task = MakeDir::new(PathBuf::from("foo/bar"));
        let mut set = res::Set::new();
        task.known_inputs(&mut set);
        assert_eq!(set.len(), 1);
        assert!(set.contains(&res::Dir::new("foo".into()).into()));
    }

    #[test]
    fn known_inputs_no_parent() {
        let task = MakeDir::new(PathBuf::from("foo"));
        let mut set = res::Set::new();
        task.known_inputs(&mut set);
        assert_eq!(set.len(), 0);
    }

    #[test]
    fn known_inputs_dot_parent() {
        let task = MakeDir::new(PathBuf::from("./foo"));
        let mut set = res::Set::new();
        task.known_inputs(&mut set);
        assert_eq!(set.len(), 0);
    }

    #[test]
    fn known_outputs() {
        let task = MakeDir::new(PathBuf::from("foobar"));
        let mut set = res::Set::new();
        task.known_outputs(&mut set);
        assert_eq!(set.len(), 1);
        assert!(set.contains(&res::Dir::new("foobar".into()).into()));
    }
}
<commit_msg>Fix failure to create existing directory<commit_after>// Copyright (c) 2017 Jason White
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

use std::fmt;
use std::fs;
use std::io;
use std::path::{Path, PathBuf};

use super::traits::Task;
use detect::Detected;
use error::Error;

use res;
use util::{progress_dummy, Retry};

/// A task to create a directory.
#[derive(
    Serialize, Deserialize, Ord, PartialOrd, Eq, PartialEq, Hash, Clone,
)]
pub struct MakeDir {
    /// Path to the directory to create.
    path: PathBuf,

    /// Retry settings.
    #[serde(default)]
    retry: Retry,
}

impl MakeDir {
    pub fn new(path: PathBuf) -> MakeDir {
        MakeDir {
            path,
            retry: Retry::default(),
        }
    }

    fn execute_impl(
        &self,
        root: &Path,
        _log: &mut io::Write,
    ) -> Result<Detected, Error> {
        // Only create the last directory, not the entire directory path. We
        // would not be able to properly clean up directories if we did the
        // equivalent of `mkdir -p`. Instead, the entire directory path chain
        // should be coded into the build graph. For example, to create the
        // directory path `obj/x64`, there should be two rules: one for creating
        // `obj` and one for creating `obj/x64`. We automatically add a
        // dependency on the parent path such that they get created in the
        // correct order.
        match fs::create_dir(&root.join(&self.path)) {
            Ok(()) => Ok(()),
            Err(err) => match err.kind() {
                // Don't care if it already exists.
                io::ErrorKind::AlreadyExists => Ok(()),
                _ => Err(err),
            }
        }?;

        Ok(Detected::new())
    }
}

impl fmt::Display for MakeDir {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "mkdir {:?}", self.path)
    }
}

impl fmt::Debug for MakeDir {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self)
    }
}

impl Task for MakeDir {
    fn execute(
        &self,
        root: &Path,
        log: &mut io::Write,
    ) -> Result<Detected, Error> {
        self.retry
            .call(|| self.execute_impl(root, log), progress_dummy)
    }

    fn known_inputs(&self, set: &mut res::Set) {
        // Add parent directory as an input. Adding this dependency also ensures
        // that we delete directories in the correct order relative to one
        // another.
        if let Some(parent) = self.path.parent() {
            if parent != Path::new("") && parent != Path::new(".") {
                set.insert(res::Dir::new(parent.to_path_buf()).into());
            }
        }
    }

    fn known_outputs(&self, set: &mut res::Set) {
        set.insert(res::Dir::new(self.path.clone()).into());
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use res;

    #[test]
    fn known_inputs_parent() {
        let task = MakeDir::new(PathBuf::from("foo/bar"));
        let mut set = res::Set::new();
        task.known_inputs(&mut set);
        assert_eq!(set.len(), 1);
        assert!(set.contains(&res::Dir::new("foo".into()).into()));
    }

    #[test]
    fn known_inputs_no_parent() {
        let task = MakeDir::new(PathBuf::from("foo"));
        let mut set = res::Set::new();
        task.known_inputs(&mut set);
        assert_eq!(set.len(), 0);
    }

    #[test]
    fn known_inputs_dot_parent() {
        let task = MakeDir::new(PathBuf::from("./foo"));
        let mut set = res::Set::new();
        task.known_inputs(&mut set);
        assert_eq!(set.len(), 0);
    }

    #[test]
    fn known_outputs() {
        let task = MakeDir::new(PathBuf::from("foobar"));
        let mut set = res::Set::new();
        task.known_outputs(&mut set);
        assert_eq!(set.len(), 1);
        assert!(set.contains(&res::Dir::new("foobar".into()).into()));
    }
}
<|endoftext|>