<commit_before>// External modules:
use walkdir::{DirEntry, WalkDir, WalkDirIterator};
use error::{Result, ResultExt};
use image;
use image::imageops::resize;
use image::{GenericImage, FilterType};

// Internal modules:
use config::PanolutionConfig;
use optimizer::{Solution, ImageArrangement};

// Std modules:
use std::path::PathBuf;

fn is_supported_format(entry: &DirEntry) -> bool {
    if entry.file_type().is_file() {
        if let Some(file_name) = entry.file_name().to_str() {
            let extension = file_name.split(".").last().unwrap_or("").to_lowercase();

            let supported: Vec<String> = vec!["jpg", "jpeg", "gif", "png", "tif", "tiff"].iter().map(|s| s.to_string()).collect();

            supported.contains(&extension)
        } else {
            false
        }
    } else {
        false
    }
}

fn create_image_arrangement(path: &PathBuf) -> Result<ImageArrangement> {
    info!("Loading image file: '{:?}'", path);
    let img = image::open(&path).chain_err(|| format!("can't open image: '{:?}", path))?;
    let width = img.width();
    let height = img.height();

    Ok(ImageArrangement{
        file_name: path.to_str().unwrap().to_string(),
        w: width,
        h: height,
        x: 0.5,
        y: 0.5,
        angle: 0.0
    })
}

pub fn create_thumbnails(config: &PanolutionConfig) -> Result<Vec<Solution>> {
    let mut all_image_paths: Vec<PathBuf> = Vec::new();
    let mut result = Vec::new();
    let walker = WalkDir::new(&config.input_path).into_iter();

    for entry in walker.filter_entry(|e| is_supported_format(e)) {
        let entry = entry.chain_err(|| "error in WalkDir")?;
        let path = entry.path();

        if let Some(file_name) = path.file_name() {
            if let Some(file_name) = file_name.to_str() {
                if file_name.starts_with("thumb_") {
                    info!("Ignore thumbnail file: {:?}", path);
                } else {
                    all_image_paths.push(path.to_path_buf());
                }
            } else {
                info!("Could not converto to str: {:?}", file_name);
            }
        } else {
            info!("Could not get file_name: {:?}", path)
        }
    }

    for scale_factor in &config.scale_factors {
        let mut arrangement = Vec::new();

        for path in &all_image_paths {
            if *scale_factor >= 1.0 {
                info!("Add original image");

                arrangement.push(create_image_arrangement(&path)?);
            } else {
                let base_path = path.parent().unwrap();
                let file_name = path.file_name().unwrap(); // Save to unwrap since we checked above
                let thumb_path = base_path.join(format!("thumb_{}_{}", scale_factor, file_name.to_str().unwrap()));

                if thumb_path.exists() {
                    info!("Thumbnail was already generated, using old one: '{:?}'", &thumb_path);
                    arrangement.push(create_image_arrangement(&thumb_path)?);
                } else {
                    info!("Loading image file: '{:?}'", path);
                    let orig_img = image::open(&path).chain_err(|| format!("can't open image: '{:?}", path))?;
                    let width = orig_img.width();
                    let height = orig_img.height();
                    info!("No thumbnail found for scale factor '{}', generating new one", scale_factor);
                    let (orig_w, orig_h) = orig_img.dimensions();
                    let (thumb_w, thumb_h) = (((orig_w as f64) * scale_factor) as u32, ((orig_h as f64) * scale_factor) as u32);
                    info!("image sizes: ({}, {}) -> ({}, {})", orig_w, orig_h, thumb_w, thumb_h);
                    let thumb_img = resize(&orig_img, thumb_w, thumb_h, FilterType::Nearest);
                    let _ = thumb_img.save(&thumb_path).chain_err(|| "can't save thumbnail image")?;

                    arrangement.push(
                        ImageArrangement{
                            file_name: thumb_path.to_str().unwrap().to_string(),
                            w: thumb_w,
                            h: thumb_h,
                            x: 0.5,
                            y: 0.5,
                            angle: 0.0
                        }
                    );
                }
            }
        }

        result.push(
            Solution {
                arrangement: arrangement
            }
        );
    }

    Ok(result)
}
<commit_msg>code clean up<commit_after>// External modules:
use walkdir::{DirEntry, WalkDir, WalkDirIterator};
use error::{Result, ResultExt};
use image;
use image::imageops::resize;
use image::{GenericImage, FilterType};

// Internal modules:
use config::PanolutionConfig;
use optimizer::{Solution, ImageArrangement};

// Std modules:
use std::path::PathBuf;

fn is_supported_format(entry: &DirEntry) -> bool {
    if entry.file_type().is_file() {
        if let Some(file_name) = entry.file_name().to_str() {
            let extension = file_name.split(".").last().unwrap_or("").to_lowercase();

            let supported: Vec<String> = vec!["jpg", "jpeg", "gif", "png", "tif", "tiff"].iter().map(|s| s.to_string()).collect();

            supported.contains(&extension)
        } else {
            false
        }
    } else {
        false
    }
}

fn create_image_arrangement(path: &PathBuf) -> Result<ImageArrangement> {
    info!("Loading image file: '{:?}'", path);
    let img = image::open(&path).chain_err(|| format!("can't open image: '{:?}", path))?;
    let width = img.width();
    let height = img.height();

    Ok(ImageArrangement{
        file_name: path.to_str().unwrap().to_string(),
        w: width,
        h: height,
        x: 0.5,
        y: 0.5,
        angle: 0.0
    })
}

pub fn create_thumbnails(config: &PanolutionConfig) -> Result<Vec<Solution>> {
    let mut all_image_paths: Vec<PathBuf> = Vec::new();
    let mut result = Vec::new();
    let walker = WalkDir::new(&config.input_path).into_iter();

    for entry in walker.filter_entry(|e| is_supported_format(e)) {
        let entry = entry.chain_err(|| "error in WalkDir")?;
        let path = entry.path();

        if let Some(file_name) = path.file_name() {
            if let Some(file_name) = file_name.to_str() {
                if file_name.starts_with("thumb_") {
                    info!("Ignore thumbnail file: {:?}", path);
                } else {
                    all_image_paths.push(path.to_path_buf());
                }
            } else {
                info!("Could not converto to str: {:?}", file_name);
            }
        } else {
            info!("Could not get file_name: {:?}", path)
        }
    }

    for scale_factor in &config.scale_factors {
        let mut arrangement = Vec::new();

        for path in &all_image_paths {
            if *scale_factor >= 1.0 {
                info!("Add original image");

                arrangement.push(create_image_arrangement(&path)?);
            } else {
                let base_path = path.parent().unwrap();
                let file_name = path.file_name().unwrap(); // Save to unwrap since we checked above
                let thumb_path = base_path.join(format!("thumb_{}_{}", scale_factor, file_name.to_str().unwrap()));

                if thumb_path.exists() {
                    info!("Thumbnail was already generated, using old one: '{:?}'", &thumb_path);
                    arrangement.push(create_image_arrangement(&thumb_path)?);
                } else {
                    info!("Loading image file: '{:?}'", path);
                    let orig_img = image::open(&path).chain_err(|| format!("can't open image: '{:?}", path))?;
                    let width = orig_img.width();
                    let height = orig_img.height();
                    info!("No thumbnail found for scale factor '{}', generating new one", scale_factor);
                    let (orig_w, orig_h) = orig_img.dimensions();
                    let (thumb_w, thumb_h) = (((orig_w as f64) * scale_factor) as u32, ((orig_h as f64) * scale_factor) as u32);
                    info!("image sizes: ({}, {}) -> ({}, {})", orig_w, orig_h, thumb_w, thumb_h);
                    let thumb_img = resize(&orig_img, thumb_w, thumb_h, FilterType::Nearest);
                    let _ = thumb_img.save(&thumb_path).chain_err(|| "can't save thumbnail image")?;

                    arrangement.push(
                        ImageArrangement{
                            file_name: thumb_path.to_str().unwrap().to_string(),
                            w: thumb_w,
                            h: thumb_h,
                            x: 0.5,
                            y: 0.5,
                            angle: 0.0
                        }
                    );
                }
            }
        }

        result.push(Solution{arrangement: arrangement});
    }

    Ok(result)
}
<|endoftext|>


<commit_before>// Dependency Graph Library in Rust

//! dglr is a Dependency Graph Library in Rust.
//! In short, you register elements and their dependencies, and then
//! ask for the dependencies of any element in an order that satisfies.
//!
//! Elements are simply &str strings.  You register them with
//! register_dependency() or register_dependencies().
//!
//! Dependenies are (currently) just a list of other elements that
//! the element in question depends on.  [In the future, we may add
//! boolean logic, but currently they are all AND-ed together].
//!
//! Then call get_ordered_dependencies_of() and the library does the
//! magic and returns an order which will work.  It is possible that
//! other orders also work, but the library's algorithm is
//! deterministic, so you'll always get the same particular one.

#![crate_id = "dglr#0.1"]
#![crate_type = "lib"]

// Required for log and rustdoc:
#![feature(phase)]
#[phase(plugin, link)]

extern crate log;

use std::collections::hashmap::{HashMap,HashSet};

/// This is the dependency graph.  You can create it yourself, or
/// use the convenience methods of new(), register_dependency() and
/// register_dependencies() to build one up (that must be mutable).
pub struct DepGraph {
    /// List of dependencies.  Key is the element, values are the
    /// other elements that the key element depends upon.
    pub dependencies: HashMap<String,Vec<String>>,
}

// Internal structure keeping state between recursive functions
struct WalkState {
    // The path we have currently walked
    curpath: HashSet<String>,
    // The output so far
    output: Vec<String>,
}

impl DepGraph {

    /// Create an empty DepGraph.
    pub fn new() -> DepGraph
    {
        DepGraph {
            dependencies: HashMap::new(),
        }
    }

    /// Add a dependency to a DepGraph.  The thing does not need
    /// to pre-exist, nor do the dependency elements.  But if the
    /// thing does pre-exist, the dependsOn will be added to its
    /// existing dependency list.
    pub fn register_dependency<'a>( &mut self,
                                thing: &'a str,
                                dependsOn: &'a str )
    {
        self.dependencies.insert_or_update_with(
            String::from_str(thing),
            vec![String::from_str(dependsOn)],
            |_,v| { v.push(String::from_str(dependsOn)); }
            );
    }

    /// Add multiple dependencies of one thing to a DepGraph.  The
    /// thing does not need to pre-exist, nor do the dependency elements.
    /// But if the thing does pre-exist, the dependsOn will be added
    /// to its existing dependency list.
    pub fn register_dependencies<'a>( &mut self,
                                  thing: &'a str,
                                  dependsOn: &'a[&'a str] )
    {
        let newvec: Vec<String> = dependsOn.iter().map(
            |s| String::from_str(*s)).collect();

        self.dependencies.insert_or_update_with(
            String::from_str(thing),
            newvec.clone(),
            |_,v| { v.push_all(newvec.as_slice()); }
            );
    }

    /// This returns either a vector of elements (Strings) in the
    /// order which they must be resolved as dependencies of thing,
    /// or in the case where there is a dependency cycle, None is
    /// returned.
    pub fn get_ordered_dependencies_of(&self, thing: &str)
        -> Option<Vec<String>>
    {
        let mut state = WalkState {
            curpath: HashSet::new(),
            output: Vec::new(),
        };

        debug!("Recursing for the first time, with {}",thing);
        if ! self.get_deps_of_recurse(&String::from_str(thing), &mut state)
        {
            return None;
        }

        debug!("output is {}",state.output);
        Some(state.output)
    }

    // Internal function, recursion for get_ordered_dependencies_of
    fn get_deps_of_recurse(&self, thing: &String, state: &mut WalkState)
        -> bool
    {
        // If we find thing, we have a circular dependency:
        if state.curpath.contains(thing) {
            error!("Circular dependency detected at {}", thing);
            return false;
        }

        state.curpath.insert(thing.clone());

        match self.dependencies.find(thing) {
            None => {
                debug!("{} has no dependencies",thing);
            },

            Some(deplist) => {
                debug!("Handling the dependencies of {}",thing);
                for n in deplist.iter() {
                    // If thing was not yet visited, recurse into it
                    if !state.output.contains(n) {

                        debug!("Recursing for {}",n);
                        if ! self.get_deps_of_recurse(n, state) {
                            return false;
                        }

                        debug!("Appending {} to output",n);
                        state.output.push(n.clone());
                    }
                }
            },
        }

        state.curpath.remove(thing);

        return true;
    }
}

#[test]
fn dglr_test() {
    let mut depgraph: DepGraph = DepGraph::new();

    depgraph.register_dependencies("a",&["b","c","d"]);
    depgraph.register_dependency("b","d");
    depgraph.register_dependencies("c",&["e","m","g"]);
    depgraph.register_dependency("e","f");
    depgraph.register_dependency("g","h");
    depgraph.register_dependency("h","i");
    depgraph.register_dependencies("i",&["j","k"]);
    depgraph.register_dependencies("k",&["l","m"]);
    depgraph.register_dependency("m","n");

    let deps = depgraph.get_ordered_dependencies_of("a").unwrap();
    debug!("Deps of a = {}",deps);
    assert!( deps == vec![String::from_str("d"),
                          String::from_str("b"),
                          String::from_str("f"),
                          String::from_str("e"),
                          String::from_str("n"),
                          String::from_str("m"),
                          String::from_str("j"),
                          String::from_str("l"),
                          String::from_str("k"),
                          String::from_str("i"),
                          String::from_str("h"),
                          String::from_str("g"),
                          String::from_str("c")] );

    let deps2 = depgraph.get_ordered_dependencies_of("i").unwrap();
    debug!("Deps of i = {}",deps2);
    assert!( deps2 == vec![String::from_str("j"),
                           String::from_str("l"),
                           String::from_str("n"),
                           String::from_str("m"),
                           String::from_str("k")] );

    depgraph.register_dependency("i","g");
    let deps3 = depgraph.get_ordered_dependencies_of("a");
    assert!(deps3 == None);
    debug!("Circular dependency was detected.");
}
<commit_msg>get_ordered_dependencies_of returns a Result now<commit_after>// Dependency Graph Library in Rust

//! dglr is a Dependency Graph Library in Rust.
//! In short, you register elements and their dependencies, and then
//! ask for the dependencies of any element in an order that satisfies.
//!
//! Elements are simply &str strings.  You register them with
//! register_dependency() or register_dependencies().
//!
//! Dependenies are (currently) just a list of other elements that
//! the element in question depends on.  [In the future, we may add
//! boolean logic, but currently they are all AND-ed together].
//!
//! Then call get_ordered_dependencies_of() and the library does the
//! magic and returns an order which will work.  It is possible that
//! other orders also work, but the library's algorithm is
//! deterministic, so you'll always get the same particular one.

#![crate_id = "dglr#0.1"]
#![crate_type = "lib"]

// Required for log and rustdoc:
#![feature(phase)]
#[phase(plugin, link)]

extern crate log;

use std::collections::hashmap::{HashMap,HashSet};

/// This is the dependency graph.  You can create it yourself, or
/// use the convenience methods of new(), register_dependency() and
/// register_dependencies() to build one up (that must be mutable).
pub struct DepGraph {
    /// List of dependencies.  Key is the element, values are the
    /// other elements that the key element depends upon.
    pub dependencies: HashMap<String,Vec<String>>,
}

// Internal structure keeping state between recursive functions
struct WalkState {
    // The path we have currently walked
    curpath: HashSet<String>,
    // The output so far
    output: Vec<String>,
}

impl DepGraph {

    /// Create an empty DepGraph.
    pub fn new() -> DepGraph
    {
        DepGraph {
            dependencies: HashMap::new(),
        }
    }

    /// Add a dependency to a DepGraph.  The thing does not need
    /// to pre-exist, nor do the dependency elements.  But if the
    /// thing does pre-exist, the dependsOn will be added to its
    /// existing dependency list.
    pub fn register_dependency<'a>( &mut self,
                                thing: &'a str,
                                dependsOn: &'a str )
    {
        self.dependencies.insert_or_update_with(
            String::from_str(thing),
            vec![String::from_str(dependsOn)],
            |_,v| { v.push(String::from_str(dependsOn)); }
            );
    }

    /// Add multiple dependencies of one thing to a DepGraph.  The
    /// thing does not need to pre-exist, nor do the dependency elements.
    /// But if the thing does pre-exist, the dependsOn will be added
    /// to its existing dependency list.
    pub fn register_dependencies<'a>( &mut self,
                                  thing: &'a str,
                                  dependsOn: &'a[&'a str] )
    {
        let newvec: Vec<String> = dependsOn.iter().map(
            |s| String::from_str(*s)).collect();

        self.dependencies.insert_or_update_with(
            String::from_str(thing),
            newvec.clone(),
            |_,v| { v.push_all(newvec.as_slice()); }
            );
    }

    /// This returns either a vector of elements (Strings) in the
    /// order which they must be resolved as dependencies of thing,
    /// or in the case where there is a dependency cycle, an error
    /// string returned.
    pub fn get_ordered_dependencies_of(&self, thing: &str)
        -> Result<Vec<String>,String>
    {
        let mut state = WalkState {
            curpath: HashSet::new(),
            output: Vec::new(),
        };

        debug!("Recursing for the first time, with {}",thing);
        if ! self.get_deps_of_recurse(&String::from_str(thing), &mut state)
        {
            return Err(format!("Circular dependency detected at {}",thing));
        }

        debug!("output is {}",state.output);
        Ok(state.output)
    }

    // Internal function, recursion for get_ordered_dependencies_of
    fn get_deps_of_recurse(&self, thing: &String, state: &mut WalkState)
        -> bool
    {
        // If we find thing, we have a circular dependency:
        if state.curpath.contains(thing) { return false; }

        state.curpath.insert(thing.clone());

        match self.dependencies.find(thing) {
            None => {
                debug!("{} has no dependencies",thing);
            },

            Some(deplist) => {
                debug!("Handling the dependencies of {}",thing);
                for n in deplist.iter() {
                    // If thing was not yet visited, recurse into it
                    if !state.output.contains(n) {

                        debug!("Recursing for {}",n);
                        if ! self.get_deps_of_recurse(n, state) {
                            return false;
                        }

                        debug!("Appending {} to output",n);
                        state.output.push(n.clone());
                    }
                }
            },
        }

        state.curpath.remove(thing);

        return true;
    }
}

#[test]
fn dglr_test() {
    let mut depgraph: DepGraph = DepGraph::new();

    depgraph.register_dependencies("a",&["b","c","d"]);
    depgraph.register_dependency("b","d");
    depgraph.register_dependencies("c",&["e","m","g"]);
    depgraph.register_dependency("e","f");
    depgraph.register_dependency("g","h");
    depgraph.register_dependency("h","i");
    depgraph.register_dependencies("i",&["j","k"]);
    depgraph.register_dependencies("k",&["l","m"]);
    depgraph.register_dependency("m","n");

    let deps = depgraph.get_ordered_dependencies_of("a").unwrap();
    debug!("Deps of a = {}",deps);
    assert!( deps == vec![String::from_str("d"),
                          String::from_str("b"),
                          String::from_str("f"),
                          String::from_str("e"),
                          String::from_str("n"),
                          String::from_str("m"),
                          String::from_str("j"),
                          String::from_str("l"),
                          String::from_str("k"),
                          String::from_str("i"),
                          String::from_str("h"),
                          String::from_str("g"),
                          String::from_str("c")] );

    let deps2 = depgraph.get_ordered_dependencies_of("i").unwrap();
    debug!("Deps of i = {}",deps2);
    assert!( deps2 == vec![String::from_str("j"),
                           String::from_str("l"),
                           String::from_str("n"),
                           String::from_str("m"),
                           String::from_str("k")] );

    depgraph.register_dependency("i","g");
    let deps3 = depgraph.get_ordered_dependencies_of("a");
    match deps3 {
        Ok(_) => fail!("Unexpected result!"),
        Err(e) => {
            debug!("Circular dependency was detected {}",e);
        }
    }
}
<|endoftext|>


<commit_before>//! Handling of `xlink:href` and `href` attributes
//!
//! In SVG1.1, links to elements are done with the `xlink:href` attribute.  However, SVG2
//! reduced this to just plain `href` with no namespace:
//! https://svgwg.org/svg2-draft/linking.html#XLinkRefAttrs
//!
//! If an element has both `xlink:href` and `href` attributes, the `href` overrides the
//! other.  We implement that logic in this module.

use markup5ever::{expanded_name, local_name, namespace_url, ns, ExpandedName};

/// Returns whether the attribute is either of `xlink:href` or `href`.
///
/// # Example
///
/// Use with an `if` pattern inside a `match`:
///
/// ```
/// # #[macro_use] extern crate markup5ever;
/// # use markup5ever::{QualName, Prefix, Namespace, LocalName, ExpandedName};
/// # use librsvg::doctest_only::{is_href,set_href};
///
/// let qual_name = QualName::new(
///     Some(Prefix::from("xlink")),
///     Namespace::from("http://www.w3.org/1999/xlink"),
///     LocalName::from("href"),
/// );
///
/// let value = expanded_name!("", "path");
/// let mut foo = Some(value);
///
/// match qual_name.expanded() {
///     ref name if is_href(name) => set_href(name, &mut foo, value),
///     _ => unreachable!(),
/// }
/// ```
pub fn is_href(name: &ExpandedName<'_>) -> bool {
    matches!(
        *name,
        expanded_name!(xlink "href") | expanded_name!("", "href")
    )
}

/// Sets an `href` attribute in preference over an `xlink:href` one.
///
/// See [`is_href`](#fn.is_href.html) for example usage.
pub fn set_href<T>(name: &ExpandedName<'_>, dest: &mut Option<T>, href: T) {
    if dest.is_none() || *name != expanded_name!(xlink "href") {
        *dest = Some(href);
    }
}
<commit_msg>href.rs: links to doc items by name<commit_after>//! Handling of `xlink:href` and `href` attributes
//!
//! In SVG1.1, links to elements are done with the `xlink:href` attribute.  However, SVG2
//! reduced this to just plain `href` with no namespace:
//! https://svgwg.org/svg2-draft/linking.html#XLinkRefAttrs
//!
//! If an element has both `xlink:href` and `href` attributes, the `href` overrides the
//! other.  We implement that logic in this module.

use markup5ever::{expanded_name, local_name, namespace_url, ns, ExpandedName};

/// Returns whether the attribute is either of `xlink:href` or `href`.
///
/// # Example
///
/// Use with an `if` pattern inside a `match`:
///
/// ```
/// # #[macro_use] extern crate markup5ever;
/// # use markup5ever::{QualName, Prefix, Namespace, LocalName, ExpandedName};
/// # use librsvg::doctest_only::{is_href,set_href};
///
/// let qual_name = QualName::new(
///     Some(Prefix::from("xlink")),
///     Namespace::from("http://www.w3.org/1999/xlink"),
///     LocalName::from("href"),
/// );
///
/// let value = expanded_name!("", "path");
/// let mut foo = Some(value);
///
/// match qual_name.expanded() {
///     ref name if is_href(name) => set_href(name, &mut foo, value),
///     _ => unreachable!(),
/// }
/// ```
pub fn is_href(name: &ExpandedName<'_>) -> bool {
    matches!(
        *name,
        expanded_name!(xlink "href") | expanded_name!("", "href")
    )
}

/// Sets an `href` attribute in preference over an `xlink:href` one.
///
/// See [`is_href`] for example usage.
pub fn set_href<T>(name: &ExpandedName<'_>, dest: &mut Option<T>, href: T) {
    if dest.is_none() || *name != expanded_name!(xlink "href") {
        *dest = Some(href);
    }
}
<|endoftext|>


<commit_before>use std::fmt; // Import `fmt`

// A structure holding two numbers. `Debug` will be derived so the results can
// be contrasted with `Display`.
#[derive(Debug)]
struct MinMax(i64, i64);

// Implement `Display` for `MinMax`.
impl fmt::Display for MinMax {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // Use `self.number` to refer to each positional data point.
        write!(f, "({}, {})", self.0, self.1)
    }
}

// Define a structure where the fields are nameable for comparison.
#[derive(Debug)]
struct Point2 {
    x: f64,
    y: f64,
}

// Similarly, implement for Point2
impl fmt::Display for Point2 {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // Customize so only `x` and `y` are denoted.
        write!(f, "x: {}, y: {}", self.x, self.y)
    }
}

fn main() {
    let minmax = MinMax(0, 14);

    println!("Compare structures:");
    println!("Display: {}", minmax);
    println!("Debug: {:?}", minmax);

    let big_range =   MinMax(-300, 300);
    let small_range = MinMax(-3, 3);

    println!("The big range is {big} and the small is {small}",
             small = small_range,
             big = big_range);

    let point = Point2 { x: 3.3, y: 7.2 };

    println!("Compare points:");
    println!("Display: {}", point);
    println!("Debug: {:?}", point);

    // Error. Both `Debug` and `Display` were implemented but `{:b}`
    // requires `fmt::Binary` to be implemented. This will not work.
    // println!("What does Point2D look like in binary: {:b}?", point);
}
<commit_msg>examples/hello/print/print_display/display.rs: translated<commit_after>use std::fmt; // 导入 `fmt`

// 带有两个数字的结构体。`Debug` 将被派生，可以看到输出结果和 `Display` 的差异。
#[derive(Debug)]
struct MinMax(i64, i64);

// 实现 `MinMax` 的 `Display`。
impl fmt::Display for MinMax {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // 使用 `self.number` 方式来表示各个数据。
        write!(f, "({}, {})", self.0, self.1)
    }
}

// 为了比较，定义一个含有字段的结构体。
#[derive(Debug)]
struct Point2 {
    x: f64,
    y: f64,
}

// 类似地对 Point2 进行实现
impl fmt::Display for Point2 {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        // 自定义方式实现，仅让 `x` 和 `y` 标识出来。
        write!(f, "x: {}, y: {}", self.x, self.y)
    }
}

fn main() {
    let minmax = MinMax(0, 14);

    println!("Compare structures:");
    println!("Display: {}", minmax);
    println!("Debug: {:?}", minmax);

    let big_range =   MinMax(-300, 300);
    let small_range = MinMax(-3, 3);

    println!("The big range is {big} and the small is {small}",
             small = small_range,
             big = big_range);

    let point = Point2 { x: 3.3, y: 7.2 };

    println!("Compare points:");
    println!("Display: {}", point);
    println!("Debug: {:?}", point);

    // 有错误。`Debug` 和 `Display` 都被实现了，但 `{:b}` 需要 `fmt::Binary`
    // 得到实现。这语句不能运行。
    // println!("What does Point2D look like in binary: {:b}?", point);
}
<|endoftext|>


<commit_before>// Implements http://rosettacode.org/wiki/IBAN

extern crate num;

use num::bigint::{BigInt, ToBigInt};

#[cfg(not(test))]
fn main() {
    if is_valid("GB82 WEST 1234 5698 7654 32") {
        println!("IBAN correctly validated!");
    } else {
        println!("Invalid IBAN!");
    }
}

// Returns true if the IBAN is valid
// See http://en.wikipedia.org/wiki/International_Bank_Account_Number#Validating_the_IBAN
fn is_valid(iban: &str) -> bool {
    // Discard whitespace
    let mut iban_chars: Vec<char> = iban.chars().filter(|c| !c.is_whitespace()).collect();

    if iban_chars.len() < 2 {
        return false;
    }

    // Check length of the IBAN
    match country_length(iban.slice_to(2)) {
        Some(l) if l == iban_chars.len() => { }
        _                                => return false
    };

    // Rearrange (first four characters go to the back)
    for _ in range(0u, 4) {
        let front = iban_chars.shift().unwrap();
        iban_chars.push(front);
    }

    // Expand letters to digits
    let iban_int = parse_digits(iban_chars);

    // Check if the remainder is one
    match iban_int {
        Some(x) => x % 97u.to_bigint().unwrap() == 1u.to_bigint().unwrap(),
        None    => false
    }
}

// Returns a BigInt made from the digits and letters of the IBAN
fn parse_digits(chars: Vec<char>) -> Option<BigInt> {
    let mut vec = Vec::with_capacity(chars.len() + 10);

    // Copy the digits to the vector and expand the letters to digits
    // We convert the characters to Ascii to be able to transform the vector in a String directly
    for &c in chars.iter() {
        match c.to_digit(36) {
            Some(d) => vec.extend(d.to_string().as_slice().chars().map(|c| c.to_ascii())),
            None    => return None
        };
    }

    from_str(vec.into_string().as_slice())
}

fn country_length(country_code: &str) -> Option<uint> {
    let countries = [
        ("AL", 28),
        ("AD", 24),
        ("AT", 20),
        ("AZ", 28),
        ("BE", 16),
        ("BH", 22),
        ("BA", 20),
        ("BR", 29),
        ("BG", 22),
        ("CR", 21),
        ("HR", 21),
        ("CY", 28),
        ("CZ", 24),
        ("DK", 18),
        ("DO", 28),
        ("EE", 20),
        ("FO", 18),
        ("FI", 18),
        ("FR", 27),
        ("GE", 22),
        ("DE", 22),
        ("GI", 23),
        ("GR", 27),
        ("GL", 18),
        ("GT", 28),
        ("HU", 28),
        ("IS", 26),
        ("IE", 22),
        ("IL", 23),
        ("IT", 27),
        ("KZ", 20),
        ("KW", 30),
        ("LV", 21),
        ("LB", 28),
        ("LI", 21),
        ("LT", 20),
        ("LU", 20),
        ("MK", 19),
        ("MT", 31),
        ("MR", 27),
        ("MU", 30),
        ("MC", 27),
        ("MD", 24),
        ("ME", 22),
        ("NL", 18),
        ("NO", 15),
        ("PK", 24),
        ("PS", 29),
        ("PL", 28),
        ("PT", 25),
        ("RO", 24),
        ("SM", 27),
        ("SA", 24),
        ("RS", 22),
        ("SK", 24),
        ("SI", 19),
        ("ES", 24),
        ("SE", 24),
        ("CH", 21),
        ("TN", 24),
        ("TR", 26),
        ("AE", 23),
        ("GB", 22),
        ("VG", 24)];

    countries.iter()
             .find(|&&(country, _)| country == country_code)
             .map(|&(_, length)| length)
}

#[test]
fn test_valid() {
    assert!(is_valid("GB82 WEST 1234 5698 7654 32"));
    assert!(is_valid("BE18 0016 5492 3565"));
}

#[test]
fn test_wrong() {
    assert!(!is_valid("ASDA FJAS DMAF BKDB AKGS DH"));
    assert!(!is_valid("XX82 WEST 1234 5698 7654 32"));
    assert!(!is_valid("BE18 0016 5492 3566"));
    assert!(!is_valid("BE18 0016 5492 3565 6"));
    assert!(!is_valid("BE18 0016 5492 356"));
    assert!(!is_valid(""));
}
<commit_msg>iban deprecated shift<commit_after>// Implements http://rosettacode.org/wiki/IBAN

extern crate num;

use num::bigint::{BigInt, ToBigInt};

#[cfg(not(test))]
fn main() {
    if is_valid("GB82 WEST 1234 5698 7654 32") {
        println!("IBAN correctly validated!");
    } else {
        println!("Invalid IBAN!");
    }
}

// Returns true if the IBAN is valid
// See http://en.wikipedia.org/wiki/International_Bank_Account_Number#Validating_the_IBAN
fn is_valid(iban: &str) -> bool {
    // Discard whitespace
    let mut iban_chars: Vec<char> = iban.chars().filter(|c| !c.is_whitespace()).collect();

    if iban_chars.len() < 2 {
        return false;
    }

    // Check length of the IBAN
    match country_length(iban.slice_to(2)) {
        Some(l) if l == iban_chars.len() => { }
        _                                => return false
    };

    // Rearrange (first four characters go to the back)
    for _ in range(0u, 4) {
        let front = iban_chars.remove(0).unwrap();
        iban_chars.push(front);
    }

    // Expand letters to digits
    let iban_int = parse_digits(iban_chars);

    // Check if the remainder is one
    match iban_int {
        Some(x) => x % 97u.to_bigint().unwrap() == 1u.to_bigint().unwrap(),
        None    => false
    }
}

// Returns a BigInt made from the digits and letters of the IBAN
fn parse_digits(chars: Vec<char>) -> Option<BigInt> {
    let mut vec = Vec::with_capacity(chars.len() + 10);

    // Copy the digits to the vector and expand the letters to digits
    // We convert the characters to Ascii to be able to transform the vector in a String directly
    for &c in chars.iter() {
        match c.to_digit(36) {
            Some(d) => vec.extend(d.to_string().as_slice().chars().map(|c| c.to_ascii())),
            None    => return None
        };
    }

    from_str(vec.into_string().as_slice())
}

fn country_length(country_code: &str) -> Option<uint> {
    let countries = [
        ("AL", 28),
        ("AD", 24),
        ("AT", 20),
        ("AZ", 28),
        ("BE", 16),
        ("BH", 22),
        ("BA", 20),
        ("BR", 29),
        ("BG", 22),
        ("CR", 21),
        ("HR", 21),
        ("CY", 28),
        ("CZ", 24),
        ("DK", 18),
        ("DO", 28),
        ("EE", 20),
        ("FO", 18),
        ("FI", 18),
        ("FR", 27),
        ("GE", 22),
        ("DE", 22),
        ("GI", 23),
        ("GR", 27),
        ("GL", 18),
        ("GT", 28),
        ("HU", 28),
        ("IS", 26),
        ("IE", 22),
        ("IL", 23),
        ("IT", 27),
        ("KZ", 20),
        ("KW", 30),
        ("LV", 21),
        ("LB", 28),
        ("LI", 21),
        ("LT", 20),
        ("LU", 20),
        ("MK", 19),
        ("MT", 31),
        ("MR", 27),
        ("MU", 30),
        ("MC", 27),
        ("MD", 24),
        ("ME", 22),
        ("NL", 18),
        ("NO", 15),
        ("PK", 24),
        ("PS", 29),
        ("PL", 28),
        ("PT", 25),
        ("RO", 24),
        ("SM", 27),
        ("SA", 24),
        ("RS", 22),
        ("SK", 24),
        ("SI", 19),
        ("ES", 24),
        ("SE", 24),
        ("CH", 21),
        ("TN", 24),
        ("TR", 26),
        ("AE", 23),
        ("GB", 22),
        ("VG", 24)];

    countries.iter()
             .find(|&&(country, _)| country == country_code)
             .map(|&(_, length)| length)
}

#[test]
fn test_valid() {
    assert!(is_valid("GB82 WEST 1234 5698 7654 32"));
    assert!(is_valid("BE18 0016 5492 3565"));
}

#[test]
fn test_wrong() {
    assert!(!is_valid("ASDA FJAS DMAF BKDB AKGS DH"));
    assert!(!is_valid("XX82 WEST 1234 5698 7654 32"));
    assert!(!is_valid("BE18 0016 5492 3566"));
    assert!(!is_valid("BE18 0016 5492 3565 6"));
    assert!(!is_valid("BE18 0016 5492 356"));
    assert!(!is_valid(""));
}
<|endoftext|>


<commit_before>// NO-RUSTC-WRAPPER
#![deny(warnings, rust_2018_idioms, unused_lifetimes)]

use std::fs::File;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
use std::time::{SystemTime, UNIX_EPOCH};
use std::{env, fs};
use std::thread;

/// A helper macro to `unwrap` a result except also print out details like:
///
/// * The file/line of the panic
/// * The expression that failed
/// * The error itself
///
/// This is currently used judiciously throughout the build system rather than
/// using a `Result` with `try!`, but this may change one day...
#[macro_export]
macro_rules! t {
    ($e:expr) => {
        match $e {
            Ok(e) => e,
            Err(e) => panic!("{} failed with {}", stringify!($e), e),
        }
    };
}

// Because Cargo adds the compiler's dylib path to our library search path, llvm-config may
// break: the dylib path for the compiler, as of this writing, contains a copy of the LLVM
// shared library, which means that when our freshly built llvm-config goes to load it's
// associated LLVM, it actually loads the compiler's LLVM. In particular when building the first
// compiler (i.e., in stage 0) that's a problem, as the compiler's LLVM is likely different from
// the one we want to use. As such, we restore the environment to what bootstrap saw. This isn't
// perfect -- we might actually want to see something from Cargo's added library paths -- but
// for now it works.
pub fn restore_library_path() {
    println!("cargo:rerun-if-env-changed=REAL_LIBRARY_PATH_VAR");
    println!("cargo:rerun-if-env-changed=REAL_LIBRARY_PATH");
    let key = env::var_os("REAL_LIBRARY_PATH_VAR").expect("REAL_LIBRARY_PATH_VAR");
    if let Some(env) = env::var_os("REAL_LIBRARY_PATH") {
        env::set_var(&key, &env);
    } else {
        env::remove_var(&key);
    }
}

pub fn run(cmd: &mut Command) {
    println!("running: {:?}", cmd);
    run_silent(cmd);
}

pub fn run_silent(cmd: &mut Command) {
    if !try_run_silent(cmd) {
        std::process::exit(1);
    }
}

pub fn try_run_silent(cmd: &mut Command) -> bool {
    let status = match cmd.status() {
        Ok(status) => status,
        Err(e) => fail(&format!(
            "failed to execute command: {:?}\nerror: {}",
            cmd, e
        )),
    };
    if !status.success() {
        println!(
            "\n\ncommand did not execute successfully: {:?}\n\
             expected success, got: {}\n\n",
            cmd, status
        );
    }
    status.success()
}

pub fn run_suppressed(cmd: &mut Command) {
    if !try_run_suppressed(cmd) {
        std::process::exit(1);
    }
}

pub fn try_run_suppressed(cmd: &mut Command) -> bool {
    let output = match cmd.output() {
        Ok(status) => status,
        Err(e) => fail(&format!(
            "failed to execute command: {:?}\nerror: {}",
            cmd, e
        )),
    };
    if !output.status.success() {
        println!(
            "\n\ncommand did not execute successfully: {:?}\n\
             expected success, got: {}\n\n\
             stdout ----\n{}\n\
             stderr ----\n{}\n\n",
            cmd,
            output.status,
            String::from_utf8_lossy(&output.stdout),
            String::from_utf8_lossy(&output.stderr)
        );
    }
    output.status.success()
}

pub fn gnu_target(target: &str) -> &str {
    match target {
        "i686-pc-windows-msvc" => "i686-pc-win32",
        "x86_64-pc-windows-msvc" => "x86_64-pc-win32",
        "i686-pc-windows-gnu" => "i686-w64-mingw32",
        "x86_64-pc-windows-gnu" => "x86_64-w64-mingw32",
        s => s,
    }
}

pub fn make(host: &str) -> PathBuf {
    if host.contains("dragonfly") || host.contains("freebsd")
        || host.contains("netbsd") || host.contains("openbsd")
    {
        PathBuf::from("gmake")
    } else {
        PathBuf::from("make")
    }
}

pub fn output(cmd: &mut Command) -> String {
    let output = match cmd.stderr(Stdio::inherit()).output() {
        Ok(status) => status,
        Err(e) => fail(&format!(
            "failed to execute command: {:?}\nerror: {}",
            cmd, e
        )),
    };
    if !output.status.success() {
        panic!(
            "command did not execute successfully: {:?}\n\
             expected success, got: {}",
            cmd, output.status
        );
    }
    String::from_utf8(output.stdout).unwrap()
}

pub fn rerun_if_changed_anything_in_dir(dir: &Path) {
    let mut stack = dir.read_dir()
        .unwrap()
        .map(|e| e.unwrap())
        .filter(|e| &*e.file_name() != ".git")
        .collect::<Vec<_>>();
    while let Some(entry) = stack.pop() {
        let path = entry.path();
        if entry.file_type().unwrap().is_dir() {
            stack.extend(path.read_dir().unwrap().map(|e| e.unwrap()));
        } else {
            println!("cargo:rerun-if-changed={}", path.display());
        }
    }
}

/// Returns the last-modified time for `path`, or zero if it doesn't exist.
pub fn mtime(path: &Path) -> SystemTime {
    fs::metadata(path)
        .and_then(|f| f.modified())
        .unwrap_or(UNIX_EPOCH)
}

/// Returns `true` if `dst` is up to date given that the file or files in `src`
/// are used to generate it.
///
/// Uses last-modified time checks to verify this.
pub fn up_to_date(src: &Path, dst: &Path) -> bool {
    if !dst.exists() {
        return false;
    }
    let threshold = mtime(dst);
    let meta = match fs::metadata(src) {
        Ok(meta) => meta,
        Err(e) => panic!("source {:?} failed to get metadata: {}", src, e),
    };
    if meta.is_dir() {
        dir_up_to_date(src, threshold)
    } else {
        meta.modified().unwrap_or(UNIX_EPOCH) <= threshold
    }
}

#[must_use]
pub struct NativeLibBoilerplate {
    pub src_dir: PathBuf,
    pub out_dir: PathBuf,
}

impl NativeLibBoilerplate {
    /// On macOS we don't want to ship the exact filename that compiler-rt builds.
    /// This conflicts with the system and ours is likely a wildly different
    /// version, so they can't be substituted.
    ///
    /// As a result, we rename it here but we need to also use
    /// `install_name_tool` on macOS to rename the commands listed inside of it to
    /// ensure it's linked against correctly.
    pub fn fixup_sanitizer_lib_name(&self, sanitizer_name: &str) {
        if env::var("TARGET").unwrap() != "x86_64-apple-darwin" {
            return
        }

        let dir = self.out_dir.join("build/lib/darwin");
        let name = format!("clang_rt.{}_osx_dynamic", sanitizer_name);
        let src = dir.join(&format!("lib{}.dylib", name));
        let new_name = format!("lib__rustc__{}.dylib", name);
        let dst = dir.join(&new_name);

        println!("{} => {}", src.display(), dst.display());
        fs::rename(&src, &dst).unwrap();
        let status = Command::new("install_name_tool")
            .arg("-id")
            .arg(format!("@rpath/{}", new_name))
            .arg(&dst)
            .status()
            .expect("failed to execute `install_name_tool`");
        assert!(status.success());
    }
}

impl Drop for NativeLibBoilerplate {
    fn drop(&mut self) {
        if !thread::panicking() {
            t!(File::create(self.out_dir.join("rustbuild.timestamp")));
        }
    }
}

// Perform standard preparations for native libraries that are build only once for all stages.
// Emit rerun-if-changed and linking attributes for Cargo, check if any source files are
// updated, calculate paths used later in actual build with CMake/make or C/C++ compiler.
// If Err is returned, then everything is up-to-date and further build actions can be skipped.
// Timestamps are created automatically when the result of `native_lib_boilerplate` goes out
// of scope, so all the build actions should be completed until then.
pub fn native_lib_boilerplate(
    src_dir: &Path,
    out_name: &str,
    link_name: &str,
    search_subdir: &str,
) -> Result<NativeLibBoilerplate, ()> {
    rerun_if_changed_anything_in_dir(src_dir);

    let out_dir = env::var_os("RUSTBUILD_NATIVE_DIR").unwrap_or_else(||
        env::var_os("OUT_DIR").unwrap());
    let out_dir = PathBuf::from(out_dir).join(out_name);
    t!(fs::create_dir_all(&out_dir));
    if link_name.contains('=') {
        println!("cargo:rustc-link-lib={}", link_name);
    } else {
        println!("cargo:rustc-link-lib=static={}", link_name);
    }
    println!(
        "cargo:rustc-link-search=native={}",
        out_dir.join(search_subdir).display()
    );

    let timestamp = out_dir.join("rustbuild.timestamp");
    if !up_to_date(Path::new("build.rs"), &timestamp) || !up_to_date(src_dir, &timestamp) {
        Ok(NativeLibBoilerplate {
            src_dir: src_dir.to_path_buf(),
            out_dir: out_dir,
        })
    } else {
        Err(())
    }
}

pub fn sanitizer_lib_boilerplate(sanitizer_name: &str)
    -> Result<(NativeLibBoilerplate, String), ()>
{
    let (link_name, search_path, apple) = match &*env::var("TARGET").unwrap() {
        "x86_64-unknown-linux-gnu" => (
            format!("clang_rt.{}-x86_64", sanitizer_name),
            "build/lib/linux",
            false,
        ),
        "x86_64-apple-darwin" => (
            format!("clang_rt.{}_osx_dynamic", sanitizer_name),
            "build/lib/darwin",
            true,
        ),
        _ => return Err(()),
    };
    let to_link = if apple {
        format!("dylib=__rustc__{}", link_name)
    } else {
        format!("static={}", link_name)
    };
    // This env var is provided by rustbuild to tell us where `compiler-rt`
    // lives.
    let dir = env::var_os("RUST_COMPILER_RT_ROOT").unwrap();
    let lib = native_lib_boilerplate(
        dir.as_ref(),
        sanitizer_name,
        &to_link,
        search_path,
    )?;
    Ok((lib, link_name))
}

fn dir_up_to_date(src: &Path, threshold: SystemTime) -> bool {
    t!(fs::read_dir(src)).map(|e| t!(e)).all(|e| {
        let meta = t!(e.metadata());
        if meta.is_dir() {
            dir_up_to_date(&e.path(), threshold)
        } else {
            meta.modified().unwrap_or(UNIX_EPOCH) < threshold
        }
    })
}

fn fail(s: &str) -> ! {
    println!("\n\n{}\n\n", s);
    std::process::exit(1);
}
<commit_msg>build_helper: rename run -> run_verbose (seems unused)<commit_after>// NO-RUSTC-WRAPPER
#![deny(warnings, rust_2018_idioms, unused_lifetimes)]

use std::fs::File;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};
use std::time::{SystemTime, UNIX_EPOCH};
use std::{env, fs};
use std::thread;

/// A helper macro to `unwrap` a result except also print out details like:
///
/// * The file/line of the panic
/// * The expression that failed
/// * The error itself
///
/// This is currently used judiciously throughout the build system rather than
/// using a `Result` with `try!`, but this may change one day...
#[macro_export]
macro_rules! t {
    ($e:expr) => {
        match $e {
            Ok(e) => e,
            Err(e) => panic!("{} failed with {}", stringify!($e), e),
        }
    };
}

// Because Cargo adds the compiler's dylib path to our library search path, llvm-config may
// break: the dylib path for the compiler, as of this writing, contains a copy of the LLVM
// shared library, which means that when our freshly built llvm-config goes to load it's
// associated LLVM, it actually loads the compiler's LLVM. In particular when building the first
// compiler (i.e., in stage 0) that's a problem, as the compiler's LLVM is likely different from
// the one we want to use. As such, we restore the environment to what bootstrap saw. This isn't
// perfect -- we might actually want to see something from Cargo's added library paths -- but
// for now it works.
pub fn restore_library_path() {
    println!("cargo:rerun-if-env-changed=REAL_LIBRARY_PATH_VAR");
    println!("cargo:rerun-if-env-changed=REAL_LIBRARY_PATH");
    let key = env::var_os("REAL_LIBRARY_PATH_VAR").expect("REAL_LIBRARY_PATH_VAR");
    if let Some(env) = env::var_os("REAL_LIBRARY_PATH") {
        env::set_var(&key, &env);
    } else {
        env::remove_var(&key);
    }
}

/// Run the command, printing what we are running.
pub fn run_verbose(cmd: &mut Command) {
    println!("running: {:?}", cmd);
    run_silent(cmd);
}

pub fn run_silent(cmd: &mut Command) {
    if !try_run_silent(cmd) {
        std::process::exit(1);
    }
}

pub fn try_run_silent(cmd: &mut Command) -> bool {
    let status = match cmd.status() {
        Ok(status) => status,
        Err(e) => fail(&format!(
            "failed to execute command: {:?}\nerror: {}",
            cmd, e
        )),
    };
    if !status.success() {
        println!(
            "\n\ncommand did not execute successfully: {:?}\n\
             expected success, got: {}\n\n",
            cmd, status
        );
    }
    status.success()
}

pub fn run_suppressed(cmd: &mut Command) {
    if !try_run_suppressed(cmd) {
        std::process::exit(1);
    }
}

pub fn try_run_suppressed(cmd: &mut Command) -> bool {
    let output = match cmd.output() {
        Ok(status) => status,
        Err(e) => fail(&format!(
            "failed to execute command: {:?}\nerror: {}",
            cmd, e
        )),
    };
    if !output.status.success() {
        println!(
            "\n\ncommand did not execute successfully: {:?}\n\
             expected success, got: {}\n\n\
             stdout ----\n{}\n\
             stderr ----\n{}\n\n",
            cmd,
            output.status,
            String::from_utf8_lossy(&output.stdout),
            String::from_utf8_lossy(&output.stderr)
        );
    }
    output.status.success()
}

pub fn gnu_target(target: &str) -> &str {
    match target {
        "i686-pc-windows-msvc" => "i686-pc-win32",
        "x86_64-pc-windows-msvc" => "x86_64-pc-win32",
        "i686-pc-windows-gnu" => "i686-w64-mingw32",
        "x86_64-pc-windows-gnu" => "x86_64-w64-mingw32",
        s => s,
    }
}

pub fn make(host: &str) -> PathBuf {
    if host.contains("dragonfly") || host.contains("freebsd")
        || host.contains("netbsd") || host.contains("openbsd")
    {
        PathBuf::from("gmake")
    } else {
        PathBuf::from("make")
    }
}

pub fn output(cmd: &mut Command) -> String {
    let output = match cmd.stderr(Stdio::inherit()).output() {
        Ok(status) => status,
        Err(e) => fail(&format!(
            "failed to execute command: {:?}\nerror: {}",
            cmd, e
        )),
    };
    if !output.status.success() {
        panic!(
            "command did not execute successfully: {:?}\n\
             expected success, got: {}",
            cmd, output.status
        );
    }
    String::from_utf8(output.stdout).unwrap()
}

pub fn rerun_if_changed_anything_in_dir(dir: &Path) {
    let mut stack = dir.read_dir()
        .unwrap()
        .map(|e| e.unwrap())
        .filter(|e| &*e.file_name() != ".git")
        .collect::<Vec<_>>();
    while let Some(entry) = stack.pop() {
        let path = entry.path();
        if entry.file_type().unwrap().is_dir() {
            stack.extend(path.read_dir().unwrap().map(|e| e.unwrap()));
        } else {
            println!("cargo:rerun-if-changed={}", path.display());
        }
    }
}

/// Returns the last-modified time for `path`, or zero if it doesn't exist.
pub fn mtime(path: &Path) -> SystemTime {
    fs::metadata(path)
        .and_then(|f| f.modified())
        .unwrap_or(UNIX_EPOCH)
}

/// Returns `true` if `dst` is up to date given that the file or files in `src`
/// are used to generate it.
///
/// Uses last-modified time checks to verify this.
pub fn up_to_date(src: &Path, dst: &Path) -> bool {
    if !dst.exists() {
        return false;
    }
    let threshold = mtime(dst);
    let meta = match fs::metadata(src) {
        Ok(meta) => meta,
        Err(e) => panic!("source {:?} failed to get metadata: {}", src, e),
    };
    if meta.is_dir() {
        dir_up_to_date(src, threshold)
    } else {
        meta.modified().unwrap_or(UNIX_EPOCH) <= threshold
    }
}

#[must_use]
pub struct NativeLibBoilerplate {
    pub src_dir: PathBuf,
    pub out_dir: PathBuf,
}

impl NativeLibBoilerplate {
    /// On macOS we don't want to ship the exact filename that compiler-rt builds.
    /// This conflicts with the system and ours is likely a wildly different
    /// version, so they can't be substituted.
    ///
    /// As a result, we rename it here but we need to also use
    /// `install_name_tool` on macOS to rename the commands listed inside of it to
    /// ensure it's linked against correctly.
    pub fn fixup_sanitizer_lib_name(&self, sanitizer_name: &str) {
        if env::var("TARGET").unwrap() != "x86_64-apple-darwin" {
            return
        }

        let dir = self.out_dir.join("build/lib/darwin");
        let name = format!("clang_rt.{}_osx_dynamic", sanitizer_name);
        let src = dir.join(&format!("lib{}.dylib", name));
        let new_name = format!("lib__rustc__{}.dylib", name);
        let dst = dir.join(&new_name);

        println!("{} => {}", src.display(), dst.display());
        fs::rename(&src, &dst).unwrap();
        let status = Command::new("install_name_tool")
            .arg("-id")
            .arg(format!("@rpath/{}", new_name))
            .arg(&dst)
            .status()
            .expect("failed to execute `install_name_tool`");
        assert!(status.success());
    }
}

impl Drop for NativeLibBoilerplate {
    fn drop(&mut self) {
        if !thread::panicking() {
            t!(File::create(self.out_dir.join("rustbuild.timestamp")));
        }
    }
}

// Perform standard preparations for native libraries that are build only once for all stages.
// Emit rerun-if-changed and linking attributes for Cargo, check if any source files are
// updated, calculate paths used later in actual build with CMake/make or C/C++ compiler.
// If Err is returned, then everything is up-to-date and further build actions can be skipped.
// Timestamps are created automatically when the result of `native_lib_boilerplate` goes out
// of scope, so all the build actions should be completed until then.
pub fn native_lib_boilerplate(
    src_dir: &Path,
    out_name: &str,
    link_name: &str,
    search_subdir: &str,
) -> Result<NativeLibBoilerplate, ()> {
    rerun_if_changed_anything_in_dir(src_dir);

    let out_dir = env::var_os("RUSTBUILD_NATIVE_DIR").unwrap_or_else(||
        env::var_os("OUT_DIR").unwrap());
    let out_dir = PathBuf::from(out_dir).join(out_name);
    t!(fs::create_dir_all(&out_dir));
    if link_name.contains('=') {
        println!("cargo:rustc-link-lib={}", link_name);
    } else {
        println!("cargo:rustc-link-lib=static={}", link_name);
    }
    println!(
        "cargo:rustc-link-search=native={}",
        out_dir.join(search_subdir).display()
    );

    let timestamp = out_dir.join("rustbuild.timestamp");
    if !up_to_date(Path::new("build.rs"), &timestamp) || !up_to_date(src_dir, &timestamp) {
        Ok(NativeLibBoilerplate {
            src_dir: src_dir.to_path_buf(),
            out_dir: out_dir,
        })
    } else {
        Err(())
    }
}

pub fn sanitizer_lib_boilerplate(sanitizer_name: &str)
    -> Result<(NativeLibBoilerplate, String), ()>
{
    let (link_name, search_path, apple) = match &*env::var("TARGET").unwrap() {
        "x86_64-unknown-linux-gnu" => (
            format!("clang_rt.{}-x86_64", sanitizer_name),
            "build/lib/linux",
            false,
        ),
        "x86_64-apple-darwin" => (
            format!("clang_rt.{}_osx_dynamic", sanitizer_name),
            "build/lib/darwin",
            true,
        ),
        _ => return Err(()),
    };
    let to_link = if apple {
        format!("dylib=__rustc__{}", link_name)
    } else {
        format!("static={}", link_name)
    };
    // This env var is provided by rustbuild to tell us where `compiler-rt`
    // lives.
    let dir = env::var_os("RUST_COMPILER_RT_ROOT").unwrap();
    let lib = native_lib_boilerplate(
        dir.as_ref(),
        sanitizer_name,
        &to_link,
        search_path,
    )?;
    Ok((lib, link_name))
}

fn dir_up_to_date(src: &Path, threshold: SystemTime) -> bool {
    t!(fs::read_dir(src)).map(|e| t!(e)).all(|e| {
        let meta = t!(e.metadata());
        if meta.is_dir() {
            dir_up_to_date(&e.path(), threshold)
        } else {
            meta.modified().unwrap_or(UNIX_EPOCH) < threshold
        }
    })
}

fn fail(s: &str) -> ! {
    println!("\n\n{}\n\n", s);
    std::process::exit(1);
}
<|endoftext|>


<commit_before>use std::fmt;
use std::io::prelude::*;

use atty;
use termcolor::Color::{Cyan, Green, Red, Yellow};
use termcolor::{self, Color, ColorSpec, StandardStream, WriteColor};

use util::errors::CargoResult;

/// The requested verbosity of output
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Verbosity {
    Verbose,
    Normal,
    Quiet,
}

/// An abstraction around a `Write`able object that remembers preferences for output verbosity and
/// color.
pub struct Shell {
    /// the `Write`able object, either with or without color support (represented by different enum
    /// variants)
    err: ShellOut,
    /// How verbose messages should be
    verbosity: Verbosity,
}

impl fmt::Debug for Shell {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.err {
            ShellOut::Write(_) => f.debug_struct("Shell")
                .field("verbosity", &self.verbosity)
                .finish(),
            ShellOut::Stream { color_choice, .. } => f.debug_struct("Shell")
                .field("verbosity", &self.verbosity)
                .field("color_choice", &color_choice)
                .finish(),
        }
    }
}

/// A `Write`able object, either with or without color support
enum ShellOut {
    /// A plain write object without color support
    Write(Box<Write>),
    /// Color-enabled stdio, with information on whether color should be used
    Stream {
        stream: StandardStream,
        tty: bool,
        color_choice: ColorChoice,
    },
}

/// Whether messages should use color output
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum ColorChoice {
    /// Force color output
    Always,
    /// Force disable color output
    Never,
    /// Intelligently guess whether to use color output
    CargoAuto,
}

impl Shell {
    /// Create a new shell (color choice and verbosity), defaulting to 'auto' color and verbose
    /// output.
    pub fn new() -> Shell {
        Shell {
            err: ShellOut::Stream {
                stream: StandardStream::stderr(ColorChoice::CargoAuto.to_termcolor_color_choice()),
                color_choice: ColorChoice::CargoAuto,
                tty: atty::is(atty::Stream::Stderr),
            },
            verbosity: Verbosity::Verbose,
        }
    }

    /// Create a shell from a plain writable object, with no color, and max verbosity.
    pub fn from_write(out: Box<Write>) -> Shell {
        Shell {
            err: ShellOut::Write(out),
            verbosity: Verbosity::Verbose,
        }
    }

    /// Print a message, where the status will have `color` color, and can be justified. The
    /// messages follows without color.
    fn print(
        &mut self,
        status: &fmt::Display,
        message: Option<&fmt::Display>,
        color: Color,
        justified: bool,
    ) -> CargoResult<()> {
        match self.verbosity {
            Verbosity::Quiet => Ok(()),
            _ => self.err.print(status, message, color, justified),
        }
    }

    /// Returns the width of the terminal in spaces, if any
    pub fn err_width(&self) -> Option<usize> {
        match self.err {
            ShellOut::Stream { tty: true, .. } => imp::stderr_width(),
            _ => None,
        }
    }

    /// Returns whether stderr is a tty
    pub fn is_err_tty(&self) -> bool {
        match self.err {
            ShellOut::Stream { tty, .. } => tty,
            _ => false,
        }
    }

    /// Get a reference to the underlying writer
    pub fn err(&mut self) -> &mut Write {
        self.err.as_write()
    }

    /// Shortcut to right-align and color green a status message.
    pub fn status<T, U>(&mut self, status: T, message: U) -> CargoResult<()>
    where
        T: fmt::Display,
        U: fmt::Display,
    {
        self.print(&status, Some(&message), Green, true)
    }

    pub fn status_header<T>(&mut self, status: T) -> CargoResult<()>
    where
        T: fmt::Display,
    {
        self.print(&status, None, Cyan, true)
    }

    /// Shortcut to right-align a status message.
    pub fn status_with_color<T, U>(
        &mut self,
        status: T,
        message: U,
        color: Color,
    ) -> CargoResult<()>
    where
        T: fmt::Display,
        U: fmt::Display,
    {
        self.print(&status, Some(&message), color, true)
    }

    /// Run the callback only if we are in verbose mode
    pub fn verbose<F>(&mut self, mut callback: F) -> CargoResult<()>
    where
        F: FnMut(&mut Shell) -> CargoResult<()>,
    {
        match self.verbosity {
            Verbosity::Verbose => callback(self),
            _ => Ok(()),
        }
    }

    /// Run the callback if we are not in verbose mode.
    pub fn concise<F>(&mut self, mut callback: F) -> CargoResult<()>
    where
        F: FnMut(&mut Shell) -> CargoResult<()>,
    {
        match self.verbosity {
            Verbosity::Verbose => Ok(()),
            _ => callback(self),
        }
    }

    /// Print a red 'error' message
    pub fn error<T: fmt::Display>(&mut self, message: T) -> CargoResult<()> {
        self.print(&"error:", Some(&message), Red, false)
    }

    /// Print an amber 'warning' message
    pub fn warn<T: fmt::Display>(&mut self, message: T) -> CargoResult<()> {
        match self.verbosity {
            Verbosity::Quiet => Ok(()),
            _ => self.print(&"warning:", Some(&message), Yellow, false),
        }
    }

    /// Update the verbosity of the shell
    pub fn set_verbosity(&mut self, verbosity: Verbosity) {
        self.verbosity = verbosity;
    }

    /// Get the verbosity of the shell
    pub fn verbosity(&self) -> Verbosity {
        self.verbosity
    }

    /// Update the color choice (always, never, or auto) from a string.
    pub fn set_color_choice(&mut self, color: Option<&str>) -> CargoResult<()> {
        if let ShellOut::Stream {
            ref mut stream,
            ref mut color_choice,
            ..
        } = self.err
        {
            let cfg = match color {
                Some("always") => ColorChoice::Always,
                Some("never") => ColorChoice::Never,

                Some("auto") | None => ColorChoice::CargoAuto,

                Some(arg) => bail!(
                    "argument for --color must be auto, always, or \
                     never, but found `{}`",
                    arg
                ),
            };
            *color_choice = cfg;
            *stream = StandardStream::stderr(cfg.to_termcolor_color_choice());
        }
        Ok(())
    }

    /// Get the current color choice
    ///
    /// If we are not using a color stream, this will always return Never, even if the color choice
    /// has been set to something else.
    pub fn color_choice(&self) -> ColorChoice {
        match self.err {
            ShellOut::Stream { color_choice, .. } => color_choice,
            ShellOut::Write(_) => ColorChoice::Never,
        }
    }

    /// Whether the shell supports color.
    pub fn supports_color(&self) -> bool {
        match &self.err {
            ShellOut::Write(_) => false,
            ShellOut::Stream { stream, .. } => stream.supports_color(),
        }
    }

    /// Prints a message and translates ANSI escape code into console colors.
    pub fn print_ansi(&mut self, message: &[u8]) -> CargoResult<()> {
        #[cfg(windows)]
        {
            if let ShellOut::Stream { stream, .. } = &mut self.err {
                ::fwdansi::write_ansi(stream, message)?;
                return Ok(());
            }
        }
        self.err().write_all(message)?;
        Ok(())
    }
}

impl Default for Shell {
    fn default() -> Self {
        Self::new()
    }
}

impl ShellOut {
    /// Print out a message with a status. The status comes first and is bold + the given color.
    /// The status can be justified, in which case the max width that will right align is 12 chars.
    fn print(
        &mut self,
        status: &fmt::Display,
        message: Option<&fmt::Display>,
        color: Color,
        justified: bool,
    ) -> CargoResult<()> {
        match *self {
            ShellOut::Stream { ref mut stream, .. } => {
                stream.reset()?;
                stream.set_color(ColorSpec::new().set_bold(true).set_fg(Some(color)))?;
                if justified {
                    write!(stream, "{:>12}", status)?;
                } else {
                    write!(stream, "{}", status)?;
                }
                stream.reset()?;
                match message {
                    Some(message) => writeln!(stream, " {}", message)?,
                    None => write!(stream, " ")?,
                }
            }
            ShellOut::Write(ref mut w) => {
                if justified {
                    write!(w, "{:>12}", status)?;
                } else {
                    write!(w, "{}", status)?;
                }
                match message {
                    Some(message) => writeln!(w, " {}", message)?,
                    None => write!(w, " ")?,
                }
            }
        }
        Ok(())
    }

    /// Get this object as a `io::Write`.
    fn as_write(&mut self) -> &mut Write {
        match *self {
            ShellOut::Stream { ref mut stream, .. } => stream,
            ShellOut::Write(ref mut w) => w,
        }
    }
}

impl ColorChoice {
    /// Convert our color choice to termcolor's version
    fn to_termcolor_color_choice(self) -> termcolor::ColorChoice {
        match self {
            ColorChoice::Always => termcolor::ColorChoice::Always,
            ColorChoice::Never => termcolor::ColorChoice::Never,
            ColorChoice::CargoAuto => {
                if atty::is(atty::Stream::Stderr) {
                    termcolor::ColorChoice::Auto
                } else {
                    termcolor::ColorChoice::Never
                }
            }
        }
    }
}

#[cfg(any(target_os = "linux", target_os = "macos"))]
mod imp {
    use std::mem;

    use libc;

    pub fn stderr_width() -> Option<usize> {
        unsafe {
            let mut winsize: libc::winsize = mem::zeroed();
            if libc::ioctl(libc::STDERR_FILENO, libc::TIOCGWINSZ, &mut winsize) < 0 {
                return None;
            }
            if winsize.ws_col > 0 {
                Some(winsize.ws_col as usize)
            } else {
                None
            }
        }
    }
}

#[cfg(all(unix, not(any(target_os = "linux", target_os = "macos"))))]
mod imp {
    pub fn stderr_width() -> Option<usize> {
        None
    }
}

#[cfg(windows)]
mod imp {
    extern crate winapi;

    use std::mem;
    use std::ptr;
    use self::winapi::um::fileapi::*;
    use self::winapi::um::handleapi::*;
    use self::winapi::um::processenv::*;
    use self::winapi::um::winbase::*;
    use self::winapi::um::wincon::*;
    use self::winapi::um::winnt::*;

    pub fn stderr_width() -> Option<usize> {
        unsafe {
            let stdout = GetStdHandle(STD_ERROR_HANDLE);
            let mut csbi: CONSOLE_SCREEN_BUFFER_INFO = mem::zeroed();
            if GetConsoleScreenBufferInfo(stdout, &mut csbi) != 0 {
                return Some((csbi.srWindow.Right - csbi.srWindow.Left) as usize)
            }

            // On mintty/msys/cygwin based terminals, the above fails with
            // INVALID_HANDLE_VALUE. Use an alternate method which works
            // in that case as well.
            let h = CreateFileA("CONOUT$\0".as_ptr() as *const CHAR,
                GENERIC_READ | GENERIC_WRITE,
                FILE_SHARE_READ | FILE_SHARE_WRITE,
                ptr::null_mut(),
                OPEN_EXISTING,
                0,
                ptr::null_mut()
            );
            if h == INVALID_HANDLE_VALUE {
                return None;
            }

            let mut csbi: CONSOLE_SCREEN_BUFFER_INFO = mem::zeroed();
            let rc = GetConsoleScreenBufferInfo(h, &mut csbi);
            CloseHandle(h);
            if rc != 0 {
                let width = (csbi.srWindow.Right - csbi.srWindow.Left) as usize;
                // Some terminals, such as mintty, always return 79 instead of
                // the actual width. In that case, use a conservative value.
                if width == 79 {
                    return Some(60);
                } else {
                    return Some(width);
                }
            }
            return None;
        }
    }
}
<commit_msg>Second attempt at fixing msys terminal width.<commit_after>use std::fmt;
use std::io::prelude::*;

use atty;
use termcolor::Color::{Cyan, Green, Red, Yellow};
use termcolor::{self, Color, ColorSpec, StandardStream, WriteColor};

use util::errors::CargoResult;

/// The requested verbosity of output
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Verbosity {
    Verbose,
    Normal,
    Quiet,
}

/// An abstraction around a `Write`able object that remembers preferences for output verbosity and
/// color.
pub struct Shell {
    /// the `Write`able object, either with or without color support (represented by different enum
    /// variants)
    err: ShellOut,
    /// How verbose messages should be
    verbosity: Verbosity,
}

impl fmt::Debug for Shell {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self.err {
            ShellOut::Write(_) => f.debug_struct("Shell")
                .field("verbosity", &self.verbosity)
                .finish(),
            ShellOut::Stream { color_choice, .. } => f.debug_struct("Shell")
                .field("verbosity", &self.verbosity)
                .field("color_choice", &color_choice)
                .finish(),
        }
    }
}

/// A `Write`able object, either with or without color support
enum ShellOut {
    /// A plain write object without color support
    Write(Box<Write>),
    /// Color-enabled stdio, with information on whether color should be used
    Stream {
        stream: StandardStream,
        tty: bool,
        color_choice: ColorChoice,
    },
}

/// Whether messages should use color output
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum ColorChoice {
    /// Force color output
    Always,
    /// Force disable color output
    Never,
    /// Intelligently guess whether to use color output
    CargoAuto,
}

impl Shell {
    /// Create a new shell (color choice and verbosity), defaulting to 'auto' color and verbose
    /// output.
    pub fn new() -> Shell {
        Shell {
            err: ShellOut::Stream {
                stream: StandardStream::stderr(ColorChoice::CargoAuto.to_termcolor_color_choice()),
                color_choice: ColorChoice::CargoAuto,
                tty: atty::is(atty::Stream::Stderr),
            },
            verbosity: Verbosity::Verbose,
        }
    }

    /// Create a shell from a plain writable object, with no color, and max verbosity.
    pub fn from_write(out: Box<Write>) -> Shell {
        Shell {
            err: ShellOut::Write(out),
            verbosity: Verbosity::Verbose,
        }
    }

    /// Print a message, where the status will have `color` color, and can be justified. The
    /// messages follows without color.
    fn print(
        &mut self,
        status: &fmt::Display,
        message: Option<&fmt::Display>,
        color: Color,
        justified: bool,
    ) -> CargoResult<()> {
        match self.verbosity {
            Verbosity::Quiet => Ok(()),
            _ => self.err.print(status, message, color, justified),
        }
    }

    /// Returns the width of the terminal in spaces, if any
    pub fn err_width(&self) -> Option<usize> {
        match self.err {
            ShellOut::Stream { tty: true, .. } => imp::stderr_width(),
            _ => None,
        }
    }

    /// Returns whether stderr is a tty
    pub fn is_err_tty(&self) -> bool {
        match self.err {
            ShellOut::Stream { tty, .. } => tty,
            _ => false,
        }
    }

    /// Get a reference to the underlying writer
    pub fn err(&mut self) -> &mut Write {
        self.err.as_write()
    }

    /// Shortcut to right-align and color green a status message.
    pub fn status<T, U>(&mut self, status: T, message: U) -> CargoResult<()>
    where
        T: fmt::Display,
        U: fmt::Display,
    {
        self.print(&status, Some(&message), Green, true)
    }

    pub fn status_header<T>(&mut self, status: T) -> CargoResult<()>
    where
        T: fmt::Display,
    {
        self.print(&status, None, Cyan, true)
    }

    /// Shortcut to right-align a status message.
    pub fn status_with_color<T, U>(
        &mut self,
        status: T,
        message: U,
        color: Color,
    ) -> CargoResult<()>
    where
        T: fmt::Display,
        U: fmt::Display,
    {
        self.print(&status, Some(&message), color, true)
    }

    /// Run the callback only if we are in verbose mode
    pub fn verbose<F>(&mut self, mut callback: F) -> CargoResult<()>
    where
        F: FnMut(&mut Shell) -> CargoResult<()>,
    {
        match self.verbosity {
            Verbosity::Verbose => callback(self),
            _ => Ok(()),
        }
    }

    /// Run the callback if we are not in verbose mode.
    pub fn concise<F>(&mut self, mut callback: F) -> CargoResult<()>
    where
        F: FnMut(&mut Shell) -> CargoResult<()>,
    {
        match self.verbosity {
            Verbosity::Verbose => Ok(()),
            _ => callback(self),
        }
    }

    /// Print a red 'error' message
    pub fn error<T: fmt::Display>(&mut self, message: T) -> CargoResult<()> {
        self.print(&"error:", Some(&message), Red, false)
    }

    /// Print an amber 'warning' message
    pub fn warn<T: fmt::Display>(&mut self, message: T) -> CargoResult<()> {
        match self.verbosity {
            Verbosity::Quiet => Ok(()),
            _ => self.print(&"warning:", Some(&message), Yellow, false),
        }
    }

    /// Update the verbosity of the shell
    pub fn set_verbosity(&mut self, verbosity: Verbosity) {
        self.verbosity = verbosity;
    }

    /// Get the verbosity of the shell
    pub fn verbosity(&self) -> Verbosity {
        self.verbosity
    }

    /// Update the color choice (always, never, or auto) from a string.
    pub fn set_color_choice(&mut self, color: Option<&str>) -> CargoResult<()> {
        if let ShellOut::Stream {
            ref mut stream,
            ref mut color_choice,
            ..
        } = self.err
        {
            let cfg = match color {
                Some("always") => ColorChoice::Always,
                Some("never") => ColorChoice::Never,

                Some("auto") | None => ColorChoice::CargoAuto,

                Some(arg) => bail!(
                    "argument for --color must be auto, always, or \
                     never, but found `{}`",
                    arg
                ),
            };
            *color_choice = cfg;
            *stream = StandardStream::stderr(cfg.to_termcolor_color_choice());
        }
        Ok(())
    }

    /// Get the current color choice
    ///
    /// If we are not using a color stream, this will always return Never, even if the color choice
    /// has been set to something else.
    pub fn color_choice(&self) -> ColorChoice {
        match self.err {
            ShellOut::Stream { color_choice, .. } => color_choice,
            ShellOut::Write(_) => ColorChoice::Never,
        }
    }

    /// Whether the shell supports color.
    pub fn supports_color(&self) -> bool {
        match &self.err {
            ShellOut::Write(_) => false,
            ShellOut::Stream { stream, .. } => stream.supports_color(),
        }
    }

    /// Prints a message and translates ANSI escape code into console colors.
    pub fn print_ansi(&mut self, message: &[u8]) -> CargoResult<()> {
        #[cfg(windows)]
        {
            if let ShellOut::Stream { stream, .. } = &mut self.err {
                ::fwdansi::write_ansi(stream, message)?;
                return Ok(());
            }
        }
        self.err().write_all(message)?;
        Ok(())
    }
}

impl Default for Shell {
    fn default() -> Self {
        Self::new()
    }
}

impl ShellOut {
    /// Print out a message with a status. The status comes first and is bold + the given color.
    /// The status can be justified, in which case the max width that will right align is 12 chars.
    fn print(
        &mut self,
        status: &fmt::Display,
        message: Option<&fmt::Display>,
        color: Color,
        justified: bool,
    ) -> CargoResult<()> {
        match *self {
            ShellOut::Stream { ref mut stream, .. } => {
                stream.reset()?;
                stream.set_color(ColorSpec::new().set_bold(true).set_fg(Some(color)))?;
                if justified {
                    write!(stream, "{:>12}", status)?;
                } else {
                    write!(stream, "{}", status)?;
                }
                stream.reset()?;
                match message {
                    Some(message) => writeln!(stream, " {}", message)?,
                    None => write!(stream, " ")?,
                }
            }
            ShellOut::Write(ref mut w) => {
                if justified {
                    write!(w, "{:>12}", status)?;
                } else {
                    write!(w, "{}", status)?;
                }
                match message {
                    Some(message) => writeln!(w, " {}", message)?,
                    None => write!(w, " ")?,
                }
            }
        }
        Ok(())
    }

    /// Get this object as a `io::Write`.
    fn as_write(&mut self) -> &mut Write {
        match *self {
            ShellOut::Stream { ref mut stream, .. } => stream,
            ShellOut::Write(ref mut w) => w,
        }
    }
}

impl ColorChoice {
    /// Convert our color choice to termcolor's version
    fn to_termcolor_color_choice(self) -> termcolor::ColorChoice {
        match self {
            ColorChoice::Always => termcolor::ColorChoice::Always,
            ColorChoice::Never => termcolor::ColorChoice::Never,
            ColorChoice::CargoAuto => {
                if atty::is(atty::Stream::Stderr) {
                    termcolor::ColorChoice::Auto
                } else {
                    termcolor::ColorChoice::Never
                }
            }
        }
    }
}

#[cfg(any(target_os = "linux", target_os = "macos"))]
mod imp {
    use std::mem;

    use libc;

    pub fn stderr_width() -> Option<usize> {
        unsafe {
            let mut winsize: libc::winsize = mem::zeroed();
            if libc::ioctl(libc::STDERR_FILENO, libc::TIOCGWINSZ, &mut winsize) < 0 {
                return None;
            }
            if winsize.ws_col > 0 {
                Some(winsize.ws_col as usize)
            } else {
                None
            }
        }
    }
}

#[cfg(all(unix, not(any(target_os = "linux", target_os = "macos"))))]
mod imp {
    pub fn stderr_width() -> Option<usize> {
        None
    }
}

#[cfg(windows)]
mod imp {
    extern crate winapi;

    use std::{cmp, mem, ptr};
    use self::winapi::um::fileapi::*;
    use self::winapi::um::handleapi::*;
    use self::winapi::um::processenv::*;
    use self::winapi::um::winbase::*;
    use self::winapi::um::wincon::*;
    use self::winapi::um::winnt::*;

    pub fn stderr_width() -> Option<usize> {
        unsafe {
            let stdout = GetStdHandle(STD_ERROR_HANDLE);
            let mut csbi: CONSOLE_SCREEN_BUFFER_INFO = mem::zeroed();
            if GetConsoleScreenBufferInfo(stdout, &mut csbi) != 0 {
                return Some((csbi.srWindow.Right - csbi.srWindow.Left) as usize)
            }

            // On mintty/msys/cygwin based terminals, the above fails with
            // INVALID_HANDLE_VALUE. Use an alternate method which works
            // in that case as well.
            let h = CreateFileA("CONOUT$\0".as_ptr() as *const CHAR,
                GENERIC_READ | GENERIC_WRITE,
                FILE_SHARE_READ | FILE_SHARE_WRITE,
                ptr::null_mut(),
                OPEN_EXISTING,
                0,
                ptr::null_mut()
            );
            if h == INVALID_HANDLE_VALUE {
                return None;
            }

            let mut csbi: CONSOLE_SCREEN_BUFFER_INFO = mem::zeroed();
            let rc = GetConsoleScreenBufferInfo(h, &mut csbi);
            CloseHandle(h);
            if rc != 0 {
                let width = (csbi.srWindow.Right - csbi.srWindow.Left) as usize;
                // Unfortunately cygwin/mintty does not set the size of the
                // backing console to match the actual window size. This
                // always reports a size of 80 or 120 (not sure what
                // determines that). Use a conservative max of 60 which should
                // work in most circumstances. ConEmu does some magic to
                // resize the console correctly, but there's no reasonable way
                // to detect which kind of terminal we are running in, or if
                // GetConsoleScreenBufferInfo returns accurate information.
                return Some(cmp::min(60, width));
            }
            return None;
        }
    }
}
<|endoftext|>


<commit_before>extern crate gcc;
extern crate pkg_config;

use std::env;

fn main() {
    match pkg_config::find_library("mad") {
        Ok(_) => return,
        Err(..) => {}
    };

    let target = env::var("TARGET").unwrap();
    let fpm = if target.contains("i686") {
        "FPM_INTEL"
    } else if target.contains("x86_64") {
        "FPM_64BIT"
    } else if target.contains("arm") {
        "FPM_ARM"
    } else if target.contains("mips") {
        "FPM_MIPS"
    } else if target.contains("sparc") {
        "FPM_SPARC"
    } else if target.contains("ppc") || target.contains("powerpc") {
        "FPM_PPC"
    } else {
        "FPM_DEFAULT"
    };

    gcc::Config::new()
                .include("libmad-src")
                .define(&fpm, None)
                .file("libmad-src/version.c")
                .file("libmad-src/fixed.c")
                .file("libmad-src/bit.c")
                .file("libmad-src/timer.c")
                .file("libmad-src/stream.c")
                .file("libmad-src/frame.c")
                .file("libmad-src/synth.c")
                .file("libmad-src/decoder.c")
                .file("libmad-src/layer12.c")
                .file("libmad-src/layer3.c")
                .file("libmad-src/huffman.c")
                .compile("libmad.a");  // the official name is `libmad.la` but gcc-rs forbids that
}
<commit_msg>Add architecture specific optimizations<commit_after>extern crate gcc;
extern crate pkg_config;

use std::env;

fn main() {
    match pkg_config::find_library("mad") {
        Ok(_) => return,
        Err(..) => {}
    };

    // attempt to compile libmad manually
    let mut gcc = gcc::Config::new();
    gcc.include("libmad-src");

    let target = env::var("TARGET").unwrap();

    if target.contains("i686") {
        gcc.define("FPM_INTEL", None);
        gcc.define("ASO_ZEROCHECK", None);

    } else if target.contains("x86_64") {
        gcc.define("FPM_64BIT", None);

    } else if target.contains("arm") {
        gcc.define("FPM_ARM", None);
        // TODO: I'm not sure if compiling assembly works
        //gcc.define("ASO_INTERLEAVE1", None);
        //gcc.define("ASO_IMDCT", None);
        //gcc.file("libmad-src/imdct_l_arm.S");

    } else if target.contains("mips") {
        gcc.define("FPM_MIPS", None);
        gcc.define("ASO_INTERLEAVE2", None);
        gcc.define("ASO_ZEROCHECK", None);

    } else if target.contains("sparc") {
        gcc.define("FPM_SPARC", None);

    } else if target.contains("ppc") || target.contains("powerpc") {
        gcc.define("FPM_PPC", None);

    } else {
        gcc.define("FPM_DEFAULT", None);
    };

    gcc.file("libmad-src/version.c")
       .file("libmad-src/fixed.c")
       .file("libmad-src/bit.c")
       .file("libmad-src/timer.c")
       .file("libmad-src/stream.c")
       .file("libmad-src/frame.c")
       .file("libmad-src/synth.c")
       .file("libmad-src/decoder.c")
       .file("libmad-src/layer12.c")
       .file("libmad-src/layer3.c")
       .file("libmad-src/huffman.c")
       .compile("libmad.a");  // the official name is `libmad.la` but gcc-rs forbids that
}
<|endoftext|>