<commit_before>use std::cmp;
use std::io::Write;

use kudu;
use libc;
use term;

use parser::Hint;
use Color;

pub struct Terminal {
    out: Box<term::StdoutTerminal>,
    err: Box<term::StderrTerminal>,
    color: bool,
}

impl Terminal {

    /// Creates a new terminal.
    pub fn new(color: Color) -> Terminal {
        let color = match color {
            Color::Auto => unsafe { libc::isatty(libc::STDERR_FILENO) != 0 },
            Color::Always => true,
            Color::Never => false,
        };

        Terminal {
            out: term::stdout().expect("unable to open stdout"),
            err: term::stderr().expect("unable to open stderr"),
            color: color,
        }
    }

    /// Colors stderr red.
    fn red(&mut self) {
        if self.color {
            self.err.fg(term::color::BRIGHT_RED).unwrap();
        }
    }

    /// Style output to stderr as bold.
    fn bold(&mut self) {
        if self.color {
            self.err.attr(term::Attr::Bold).unwrap();
        }

    }

    /// Resets the style and color of stderr to the default.
    fn reset(&mut self) {
        if self.color {
            self.err.reset().unwrap();
        }
    }

    /// Prints a parse error to stderr.
    pub fn print_parse_error(&mut self, input: &str, remaining: &str, hints: &[Hint]) {
        let error_idx = input.len() - remaining.len();
        assert_eq!(&input[error_idx..], remaining);
        if !input.is_empty() {
            for line in input.lines() {

                if line.len() >= error_idx {
                    self.red();
                    write!(self.err, "error: ").unwrap();
                    self.reset();

                    let hints = hints.into_iter().map(|hint| {
                        match hint {
                            &Hint::Constant(ref expected) => format!("'{}'", *expected,),
                            &Hint::Table(_) => "a table name".to_string(),
                        }
                    }).collect::<Vec<_>>();

                    self.bold();
                    writeln!(self.err, "expected: {}", hints.join(" or ")).unwrap();
                    self.reset();

                    let word_len = input[error_idx..].split_whitespace().next().unwrap_or("").len();
                    writeln!(self.err, "{}", line).unwrap();
                    writeln!(self.err, "{:>2$}{:~<3$}", "", "^", error_idx, word_len).unwrap();
                    break;
                }
            }
        }
        writeln!(&mut self.out, "").unwrap();
    }

    /// Prints a kudu err to stderr.
    pub fn print_kudu_error(&mut self, error: &kudu::Error) {
        self.red();
        write!(self.err, "error: ").unwrap();
        self.reset();
        writeln!(self.err, "{}", error.message()).unwrap();
    }

    /// Prints a table list to stdout.
    pub fn print_table_list(&mut self, tables: &[&str]) {
        let width = cmp::max(5, tables.iter().map(|name| name.len()).max().unwrap_or(0));

        writeln!(&mut self.out, "{:<1$}", "Table", width).unwrap();
        writeln!(&mut self.out, "{:-^1$}", "", width).unwrap();
        for table in tables {
            writeln!(&mut self.out, "{:<1$}", table, width).unwrap();
        }
        writeln!(&mut self.out, "").unwrap();
    }

    /// Prints a table description to stdout.
    pub fn print_table_description(&mut self, schema: &kudu::Schema) {
        let columns = (0..schema.num_columns()).map(|idx| schema.column(idx)).collect::<Vec<_>>();

        let mut names = vec!["Column".to_owned()];
        names.extend(columns.iter().map(|col| col.name().to_owned()));

        let mut types = vec!["Type".to_owned()];
        types.extend(columns.iter().map(|col| format!("{:?}", col.data_type())));

        let mut nullables = vec!["Nullable".to_owned()];
        nullables.extend(columns.iter().map(|col| {
            if col.is_nullable() { "True".to_owned() } else { "False".to_owned() }
        }));

        self.print_table(&[&names, &types, &nullables]);
    }

    fn print_table(&mut self, columns: &[&[String]]) {
        let rows = columns.iter().fold(None, |prev, col| {
            let rows = col.len();
            if let Some(prev_rows) = prev {
                assert_eq!(prev_rows, rows);
            }
            Some(rows)
        }).expect("there must be at least a header");
        let widths = columns.iter()
                            .map(|col| col.iter().map(|cell| cell.len()).max().unwrap_or(0))
                            .collect::<Vec<_>>();

        for row in 0..rows {
            for col in 0..columns.len() {
                if col == 0 {
                    write!(&mut self.out, " {:<1$} ", columns[col][row], widths[col]).unwrap();
                } else {
                    write!(&mut self.out, "| {:<1$} ", columns[col][row], widths[col]).unwrap();
                }
            }
            writeln!(&mut self.out, "").unwrap();

            if row == 0 {
                for col in 0..columns.len() {
                    if col == 0 {
                        write!(&mut self.out, " {:-<1$}", "", widths[col]).unwrap();
                    } else {
                        write!(&mut self.out, "-+-{:-<1$}", "", widths[col]).unwrap();
                    }
                }
                writeln!(&mut self.out, "").unwrap();
            }
        }
    }
}

#[cfg(test)]
mod test {

    use parser::{
        Command,
        Hint,
        Parser,
        ParseResult,
    };

    use super::write_parse_error;

    /*
    #[test]
    fn test_write_parse_error() {
        fn test(input: &str, msg: &str) {
            if let ParseResult::Err(expected, remaining) = Command.parse(input) {
                let mut actual = Vec::new();
                write_parse_error(&mut actual, input, remaining, expected);
                assert_eq!(msg.as_bytes(), &actual[..]);
            } else {
                panic!("expected parse to fail")
            }
        }

        test("DESCRIBE foo;",
             "Error: expected TABLE\nDESCRIBE foo;\n         ^");
    }
    */
}
<commit_msg>Add encoding and compression to table description output<commit_after>use std::cmp;
use std::io::Write;

use kudu;
use libc;
use term;

use parser::Hint;
use Color;

pub struct Terminal {
    out: Box<term::StdoutTerminal>,
    err: Box<term::StderrTerminal>,
    color: bool,
}

impl Terminal {

    /// Creates a new terminal.
    pub fn new(color: Color) -> Terminal {
        let color = match color {
            Color::Auto => unsafe { libc::isatty(libc::STDERR_FILENO) != 0 },
            Color::Always => true,
            Color::Never => false,
        };

        Terminal {
            out: term::stdout().expect("unable to open stdout"),
            err: term::stderr().expect("unable to open stderr"),
            color: color,
        }
    }

    /// Colors stderr red.
    fn red(&mut self) {
        if self.color {
            self.err.fg(term::color::BRIGHT_RED).unwrap();
        }
    }

    /// Style output to stderr as bold.
    fn bold(&mut self) {
        if self.color {
            self.err.attr(term::Attr::Bold).unwrap();
        }

    }

    /// Resets the style and color of stderr to the default.
    fn reset(&mut self) {
        if self.color {
            self.err.reset().unwrap();
        }
    }

    /// Prints a parse error to stderr.
    pub fn print_parse_error(&mut self, input: &str, remaining: &str, hints: &[Hint]) {
        let error_idx = input.len() - remaining.len();
        assert_eq!(&input[error_idx..], remaining);
        if !input.is_empty() {
            for line in input.lines() {

                if line.len() >= error_idx {
                    self.red();
                    write!(self.err, "error: ").unwrap();
                    self.reset();

                    let hints = hints.into_iter().map(|hint| {
                        match hint {
                            &Hint::Constant(ref expected) => format!("'{}'", *expected,),
                            &Hint::Table(_) => "a table name".to_string(),
                        }
                    }).collect::<Vec<_>>();

                    self.bold();
                    writeln!(self.err, "expected: {}", hints.join(" or ")).unwrap();
                    self.reset();

                    let word_len = input[error_idx..].split_whitespace().next().unwrap_or("").len();
                    writeln!(self.err, "{}", line).unwrap();
                    writeln!(self.err, "{:>2$}{:~<3$}", "", "^", error_idx, word_len).unwrap();
                    break;
                }
            }
        }
        writeln!(&mut self.out, "").unwrap();
    }

    /// Prints a kudu err to stderr.
    pub fn print_kudu_error(&mut self, error: &kudu::Error) {
        self.red();
        write!(self.err, "error: ").unwrap();
        self.reset();
        writeln!(self.err, "{}", error.message()).unwrap();
    }

    /// Prints a table list to stdout.
    pub fn print_table_list(&mut self, tables: &[&str]) {
        let width = cmp::max(5, tables.iter().map(|name| name.len()).max().unwrap_or(0));

        writeln!(&mut self.out, "{:<1$}", "Table", width).unwrap();
        writeln!(&mut self.out, "{:-^1$}", "", width).unwrap();
        for table in tables {
            writeln!(&mut self.out, "{:<1$}", table, width).unwrap();
        }
        writeln!(&mut self.out, "").unwrap();
    }

    /// Prints a table description to stdout.
    pub fn print_table_description(&mut self, schema: &kudu::Schema) {
        let columns = (0..schema.num_columns()).map(|idx| schema.column(idx)).collect::<Vec<_>>();

        let mut names = vec!["Column".to_owned()];
        names.extend(columns.iter().map(|col| col.name().to_owned()));

        let mut types = vec!["Type".to_owned()];
        types.extend(columns.iter().map(|col| format!("{:?}", col.data_type())));

        let mut nullables = vec!["Nullable".to_owned()];
        nullables.extend(columns.iter().map(|col| {
            if col.is_nullable() { "True".to_owned() } else { "False".to_owned() }
        }));

        let mut encodings = vec!["Encoding".to_owned()];
        encodings.extend(columns.iter().map(|col| format!("{:?}", col.encoding_type())));

        let mut compressions = vec!["Compression".to_owned()];
        compressions.extend(columns.iter().map(|col| format!("{:?}", col.compression_type())));

        self.print_table(&[&names, &types, &nullables, &encodings, &compressions]);
    }

    fn print_table(&mut self, columns: &[&[String]]) {
        let rows = columns.iter().fold(None, |prev, col| {
            let rows = col.len();
            if let Some(prev_rows) = prev {
                assert_eq!(prev_rows, rows);
            }
            Some(rows)
        }).expect("there must be at least a header");
        let widths = columns.iter()
                            .map(|col| col.iter().map(|cell| cell.len()).max().unwrap_or(0))
                            .collect::<Vec<_>>();

        for row in 0..rows {
            for col in 0..columns.len() {
                if col == 0 {
                    write!(&mut self.out, " {:<1$} ", columns[col][row], widths[col]).unwrap();
                } else {
                    write!(&mut self.out, "| {:<1$} ", columns[col][row], widths[col]).unwrap();
                }
            }
            writeln!(&mut self.out, "").unwrap();

            if row == 0 {
                for col in 0..columns.len() {
                    if col == 0 {
                        write!(&mut self.out, " {:-<1$}", "", widths[col]).unwrap();
                    } else {
                        write!(&mut self.out, "-+-{:-<1$}", "", widths[col]).unwrap();
                    }
                }
                writeln!(&mut self.out, "").unwrap();
            }
        }
    }
}

#[cfg(test)]
mod test {

    use parser::{
        Command,
        Hint,
        Parser,
        ParseResult,
    };

    use super::write_parse_error;

    /*
    #[test]
    fn test_write_parse_error() {
        fn test(input: &str, msg: &str) {
            if let ParseResult::Err(expected, remaining) = Command.parse(input) {
                let mut actual = Vec::new();
                write_parse_error(&mut actual, input, remaining, expected);
                assert_eq!(msg.as_bytes(), &actual[..]);
            } else {
                panic!("expected parse to fail")
            }
        }

        test("DESCRIBE foo;",
             "Error: expected TABLE\nDESCRIBE foo;\n         ^");
    }
    */
}
<|endoftext|>


<commit_before>//! Module containing various utility functions.

mod content_encoding;

use base64;
use std::f64;
use std::cmp;
use iron::Url;
use std::fs::File;
use std::path::Path;
use std::borrow::Cow;
use url::percent_encoding;
use std::collections::HashMap;
use time::{self, Duration, Tm};
use std::io::{BufReader, BufRead};
use mime_guess::get_mime_type_str;

pub use self::content_encoding::*;

/// The generic HTML page to use as response to errors.
pub static ERROR_HTML: &'static str = include_str!("../../assets/error.html");

/// The HTML page to use as template for a requested directory's listing.
pub static DIRECTORY_LISTING_HTML: &'static str = include_str!("../../assets/directory_listing.html");

lazy_static! {
    /// Collection of data to be injected into generated responses.
    pub static ref ASSETS: HashMap<&'static str, Cow<'static, str>> = {
        let mut ass = HashMap::with_capacity(1);
        ass.insert("favicon",
            Cow::Owned(format!("data:{};base64,{}", get_mime_type_str("ico").unwrap(), base64::encode(include_bytes!("../../assets/favicon.ico")))));
        ass.insert("dir_icon",
            Cow::Owned(format!("data:{};base64,{}",
                               get_mime_type_str("gif").unwrap(),
                               base64::encode(include_bytes!("../../assets/icons/directory_icon.gif")))));
        ass.insert("file_icon",
            Cow::Owned(format!("data:{};base64,{}",
                               get_mime_type_str("gif").unwrap(),
                               base64::encode(include_bytes!("../../assets/icons/file_icon.gif")))));
        ass.insert("file_binary_icon",
            Cow::Owned(format!("data:{};base64,{}",
                               get_mime_type_str("gif").unwrap(),
                               base64::encode(include_bytes!("../../assets/icons/file_binary_icon.gif")))));
        ass.insert("file_image_icon",
            Cow::Owned(format!("data:{};base64,{}",
                               get_mime_type_str("gif").unwrap(),
                               base64::encode(include_bytes!("../../assets/icons/file_image_icon.gif")))));
        ass.insert("file_text_icon",
            Cow::Owned(format!("data:{};base64,{}",
                               get_mime_type_str("gif").unwrap(),
                               base64::encode(include_bytes!("../../assets/icons/file_text_icon.gif")))));
        ass.insert("back_arrow_icon",
            Cow::Owned(format!("data:{};base64,{}",
                               get_mime_type_str("gif").unwrap(),
                               base64::encode(include_bytes!("../../assets/icons/back_arrow_icon.gif")))));
        ass.insert("drag_drop", Cow::Borrowed(include_str!("../../assets/drag_drop.js")));
        ass
    };
}

/// The port to start scanning from if no ports were given.
pub static PORT_SCAN_LOWEST: u16 = 8000;

/// The port to end scanning at if no ports were given.
pub static PORT_SCAN_HIGHEST: u16 = 9999;

/// The app name and version to use with User-Agent or Server response header.
pub static USER_AGENT: &'static str = concat!("http/", env!("CARGO_PKG_VERSION"));

/// Index file extensions to look for if `-i` was not specified.
pub static INDEX_EXTENSIONS: &'static [&'static str] = &["html", "htm", "shtml"];

/// Uppercase the first character of the supplied string.
///
/// Based on http://stackoverflow.com/a/38406885/2851815
///
/// # Examples
///
/// ```
/// # use https::util::uppercase_first;
/// assert_eq!(uppercase_first("abolish"), "Abolish".to_string());
/// ```
pub fn uppercase_first(s: &str) -> String {
    let mut c = s.chars();
    match c.next() {
        None => String::new(),
        Some(f) => f.to_uppercase().collect::<String>() + c.as_str(),
    }
}

/// Check if the specified file is to be considered "binary".
///
/// Basically checks is a file is UTF-8.
///
/// # Examples
///
/// ```
/// # use https::util::file_binary;
/// # #[cfg(target_os = "windows")]
/// # assert!(file_binary("target/debug/http.exe"));
/// # #[cfg(not(target_os = "windows"))]
/// assert!(file_binary("target/debug/http"));
/// assert!(!file_binary("Cargo.toml"));
/// ```
pub fn file_binary<P: AsRef<Path>>(path: P) -> bool {
    File::open(path).and_then(|f| BufReader::new(f).read_line(&mut String::new())).is_err()
}

/// Fill out an HTML template.
///
/// All fields must be addressed even if formatted to be empty.
///
/// # Examples
///
/// ```
/// # use https::util::{html_response, NOT_IMPLEMENTED_HTML};
/// println!(html_response(NOT_IMPLEMENTED_HTML, &["<p>Abolish the burgeoisie!</p>"]));
/// ```
pub fn html_response<S: AsRef<str>>(data: &str, format_strings: &[S]) -> String {
    ASSETS.iter().fold(format_strings.iter().enumerate().fold(data.to_string(), |d, (i, s)| d.replace(&format!("{{{}}}", i), s.as_ref())),
                       |d, (k, v)| d.replace(&format!("{{{}}}", k), v))
}

/// Return the path part of the URL.
///
/// # Example
///
/// ```
/// # extern crate iron;
/// # extern crate https;
/// # use iron::Url;
/// # use https::util::url_path;
/// let url = Url::parse("127.0.0.1:8000/capitalism/русский/");
/// assert_eq!(url_path(&url), "capitalism/русский/");
/// ```
pub fn url_path(url: &Url) -> String {
    let path = url.path();
    if path == [""] {
        "/".to_string()
    } else {
        path.into_iter().fold("".to_string(),
                              |cur, pp| format!("{}/{}", cur, percent_decode(pp).unwrap_or(Cow::Borrowed("<incorrect UTF8>"))))[1..]
            .to_string()
    }
}

/// Decode a percent-encoded string (like a part of a URL).
///
/// # Example
///
/// ```
/// # use https::util::percent_decode;
/// # use std::borrow::Cow;
/// assert_eq!(percent_decode("%D0%B0%D1%81%D0%B4%D1%84%20fdsa"), Some(Cow::Owned("асдф fdsa".to_string())));
/// assert_eq!(percent_decode("%D0%D1%81%D0%B4%D1%84%20fdsa"), None);
/// ```
pub fn percent_decode(s: &str) -> Option<Cow<str>> {
    percent_encoding::percent_decode(s.as_bytes()).decode_utf8().ok()
}

/// Get the timestamp of the file's last modification as a `time::Tm`.
pub fn file_time_modified(f: &Path) -> Tm {
    match f.metadata().unwrap().modified().unwrap().elapsed() {
        Ok(dur) => time::now() - Duration::from_std(dur).unwrap(),
        Err(ste) => time::now() + Duration::from_std(ste.duration()).unwrap(),
    }
}

/// Check, whether, in any place of the path, a file is treated like a directory.
///
/// A file is treated like a directory when it is treated as if it had a subpath, e.g., given:
///
/// ```sh
/// tree .
/// | dir0
/// | dir1
///   | file01
/// ```
///
/// This function would return true for `./dir1/file01/file010`, `./dir1/file01/dir010/file0100`, etc., but not
/// for `./dir0/file00`, `./dir0/dir00/file000`, `./dir1/file02/`, `./dir1/dir010/file0100`.
pub fn detect_file_as_dir(mut p: &Path) -> bool {
    while let Some(pnt) = p.parent() {
        if pnt.is_file() {
            return true;
        }

        p = pnt;
    }

    false
}

/// Check if a path refers to a symlink in a way that also works on Windows.
pub fn is_symlink<P: AsRef<Path>>(p: P) -> bool {
    p.as_ref().read_link().is_ok()
}

/// Construct string representing a human-readable size.
///
/// Stolen, adapted and inlined from [fielsize.js](http://filesizejs.com).
pub fn human_readable_size(s: u64) -> String {
    if s == 0 {
        "0 B".to_string()
    } else {
        let num = s as f64;
        let exp = cmp::min(cmp::max((num.log(f64::consts::E) / 1024f64.log(f64::consts::E)) as i32, 0), 8);

        let val = num / 2f64.powi(exp * 10);

        if exp > 0 {
                (val * 10f64).round() / 10f64
            } else {
                val.round()
            }
            .to_string() + " " + ["B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"][cmp::max(exp, 0) as usize]
    }
}
<commit_msg>Update ASSETS map capacity<commit_after>//! Module containing various utility functions.

mod content_encoding;

use base64;
use std::f64;
use std::cmp;
use iron::Url;
use std::fs::File;
use std::path::Path;
use std::borrow::Cow;
use url::percent_encoding;
use std::collections::HashMap;
use time::{self, Duration, Tm};
use std::io::{BufReader, BufRead};
use mime_guess::get_mime_type_str;

pub use self::content_encoding::*;

/// The generic HTML page to use as response to errors.
pub static ERROR_HTML: &'static str = include_str!("../../assets/error.html");

/// The HTML page to use as template for a requested directory's listing.
pub static DIRECTORY_LISTING_HTML: &'static str = include_str!("../../assets/directory_listing.html");

lazy_static! {
    /// Collection of data to be injected into generated responses.
    pub static ref ASSETS: HashMap<&'static str, Cow<'static, str>> = {
        let mut ass = HashMap::with_capacity(8);
        ass.insert("favicon",
            Cow::Owned(format!("data:{};base64,{}", get_mime_type_str("ico").unwrap(), base64::encode(include_bytes!("../../assets/favicon.ico")))));
        ass.insert("dir_icon",
            Cow::Owned(format!("data:{};base64,{}",
                               get_mime_type_str("gif").unwrap(),
                               base64::encode(include_bytes!("../../assets/icons/directory_icon.gif")))));
        ass.insert("file_icon",
            Cow::Owned(format!("data:{};base64,{}",
                               get_mime_type_str("gif").unwrap(),
                               base64::encode(include_bytes!("../../assets/icons/file_icon.gif")))));
        ass.insert("file_binary_icon",
            Cow::Owned(format!("data:{};base64,{}",
                               get_mime_type_str("gif").unwrap(),
                               base64::encode(include_bytes!("../../assets/icons/file_binary_icon.gif")))));
        ass.insert("file_image_icon",
            Cow::Owned(format!("data:{};base64,{}",
                               get_mime_type_str("gif").unwrap(),
                               base64::encode(include_bytes!("../../assets/icons/file_image_icon.gif")))));
        ass.insert("file_text_icon",
            Cow::Owned(format!("data:{};base64,{}",
                               get_mime_type_str("gif").unwrap(),
                               base64::encode(include_bytes!("../../assets/icons/file_text_icon.gif")))));
        ass.insert("back_arrow_icon",
            Cow::Owned(format!("data:{};base64,{}",
                               get_mime_type_str("gif").unwrap(),
                               base64::encode(include_bytes!("../../assets/icons/back_arrow_icon.gif")))));
        ass.insert("drag_drop", Cow::Borrowed(include_str!("../../assets/drag_drop.js")));
        ass
    };
}

/// The port to start scanning from if no ports were given.
pub static PORT_SCAN_LOWEST: u16 = 8000;

/// The port to end scanning at if no ports were given.
pub static PORT_SCAN_HIGHEST: u16 = 9999;

/// The app name and version to use with User-Agent or Server response header.
pub static USER_AGENT: &'static str = concat!("http/", env!("CARGO_PKG_VERSION"));

/// Index file extensions to look for if `-i` was not specified.
pub static INDEX_EXTENSIONS: &'static [&'static str] = &["html", "htm", "shtml"];

/// Uppercase the first character of the supplied string.
///
/// Based on http://stackoverflow.com/a/38406885/2851815
///
/// # Examples
///
/// ```
/// # use https::util::uppercase_first;
/// assert_eq!(uppercase_first("abolish"), "Abolish".to_string());
/// ```
pub fn uppercase_first(s: &str) -> String {
    let mut c = s.chars();
    match c.next() {
        None => String::new(),
        Some(f) => f.to_uppercase().collect::<String>() + c.as_str(),
    }
}

/// Check if the specified file is to be considered "binary".
///
/// Basically checks is a file is UTF-8.
///
/// # Examples
///
/// ```
/// # use https::util::file_binary;
/// # #[cfg(target_os = "windows")]
/// # assert!(file_binary("target/debug/http.exe"));
/// # #[cfg(not(target_os = "windows"))]
/// assert!(file_binary("target/debug/http"));
/// assert!(!file_binary("Cargo.toml"));
/// ```
pub fn file_binary<P: AsRef<Path>>(path: P) -> bool {
    File::open(path).and_then(|f| BufReader::new(f).read_line(&mut String::new())).is_err()
}

/// Fill out an HTML template.
///
/// All fields must be addressed even if formatted to be empty.
///
/// # Examples
///
/// ```
/// # use https::util::{html_response, NOT_IMPLEMENTED_HTML};
/// println!(html_response(NOT_IMPLEMENTED_HTML, &["<p>Abolish the burgeoisie!</p>"]));
/// ```
pub fn html_response<S: AsRef<str>>(data: &str, format_strings: &[S]) -> String {
    ASSETS.iter().fold(format_strings.iter().enumerate().fold(data.to_string(), |d, (i, s)| d.replace(&format!("{{{}}}", i), s.as_ref())),
                       |d, (k, v)| d.replace(&format!("{{{}}}", k), v))
}

/// Return the path part of the URL.
///
/// # Example
///
/// ```
/// # extern crate iron;
/// # extern crate https;
/// # use iron::Url;
/// # use https::util::url_path;
/// let url = Url::parse("127.0.0.1:8000/capitalism/русский/");
/// assert_eq!(url_path(&url), "capitalism/русский/");
/// ```
pub fn url_path(url: &Url) -> String {
    let path = url.path();
    if path == [""] {
        "/".to_string()
    } else {
        path.into_iter().fold("".to_string(),
                              |cur, pp| format!("{}/{}", cur, percent_decode(pp).unwrap_or(Cow::Borrowed("<incorrect UTF8>"))))[1..]
            .to_string()
    }
}

/// Decode a percent-encoded string (like a part of a URL).
///
/// # Example
///
/// ```
/// # use https::util::percent_decode;
/// # use std::borrow::Cow;
/// assert_eq!(percent_decode("%D0%B0%D1%81%D0%B4%D1%84%20fdsa"), Some(Cow::Owned("асдф fdsa".to_string())));
/// assert_eq!(percent_decode("%D0%D1%81%D0%B4%D1%84%20fdsa"), None);
/// ```
pub fn percent_decode(s: &str) -> Option<Cow<str>> {
    percent_encoding::percent_decode(s.as_bytes()).decode_utf8().ok()
}

/// Get the timestamp of the file's last modification as a `time::Tm`.
pub fn file_time_modified(f: &Path) -> Tm {
    match f.metadata().unwrap().modified().unwrap().elapsed() {
        Ok(dur) => time::now() - Duration::from_std(dur).unwrap(),
        Err(ste) => time::now() + Duration::from_std(ste.duration()).unwrap(),
    }
}

/// Check, whether, in any place of the path, a file is treated like a directory.
///
/// A file is treated like a directory when it is treated as if it had a subpath, e.g., given:
///
/// ```sh
/// tree .
/// | dir0
/// | dir1
///   | file01
/// ```
///
/// This function would return true for `./dir1/file01/file010`, `./dir1/file01/dir010/file0100`, etc., but not
/// for `./dir0/file00`, `./dir0/dir00/file000`, `./dir1/file02/`, `./dir1/dir010/file0100`.
pub fn detect_file_as_dir(mut p: &Path) -> bool {
    while let Some(pnt) = p.parent() {
        if pnt.is_file() {
            return true;
        }

        p = pnt;
    }

    false
}

/// Check if a path refers to a symlink in a way that also works on Windows.
pub fn is_symlink<P: AsRef<Path>>(p: P) -> bool {
    p.as_ref().read_link().is_ok()
}

/// Construct string representing a human-readable size.
///
/// Stolen, adapted and inlined from [fielsize.js](http://filesizejs.com).
pub fn human_readable_size(s: u64) -> String {
    if s == 0 {
        "0 B".to_string()
    } else {
        let num = s as f64;
        let exp = cmp::min(cmp::max((num.log(f64::consts::E) / 1024f64.log(f64::consts::E)) as i32, 0), 8);

        let val = num / 2f64.powi(exp * 10);

        if exp > 0 {
                (val * 10f64).round() / 10f64
            } else {
                val.round()
            }
            .to_string() + " " + ["B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"][cmp::max(exp, 0) as usize]
    }
}
<|endoftext|>


<commit_before>#![feature(macro_rules)]

extern crate date;
use date::Date;

macro_rules! date(
    ($year:expr, $month:expr, $day:expr) => (
        Date { year: $year, month: $month, day: $day }
    )
)

#[test]
fn since_1904_test() {
    assert_eq!(Date::since(1904,          0), date!(1904, 01, 01));
    assert_eq!(Date::since(1904,    2678399), date!(1904, 01, 31));
    assert_eq!(Date::since(1904,    2678400), date!(1904, 02, 01));
    assert_eq!(Date::since(1904,    5184000), date!(1904, 03, 01));
    assert_eq!(Date::since(1904, 3491078399), date!(2014, 08, 16));
    assert_eq!(Date::since(1904, 3491078400), date!(2014, 08, 17));
}
<commit_msg>Renamed the test for date<commit_after>#![feature(macro_rules)]

extern crate date;
use date::Date;

macro_rules! date(
    ($year:expr, $month:expr, $day:expr) => (
        Date { year: $year, month: $month, day: $day }
    )
)

#[test]
fn since_test() {
    assert_eq!(Date::since(1904,          0), date!(1904, 01, 01));
    assert_eq!(Date::since(1904,    2678399), date!(1904, 01, 31));
    assert_eq!(Date::since(1904,    2678400), date!(1904, 02, 01));
    assert_eq!(Date::since(1904,    5184000), date!(1904, 03, 01));
    assert_eq!(Date::since(1904, 3491078399), date!(2014, 08, 16));
    assert_eq!(Date::since(1904, 3491078400), date!(2014, 08, 17));
}
<|endoftext|>


<commit_before>//! Song analysis module.
//!
//! Contains various functions to extract meaningful features from a `Song`,
//! e.g. tempo features, spectral features, etc.
#[cfg(feature = "aubio-lib")]
extern crate aubio_lib;

use aubio_rs::{bin_to_freq, silence_detection, OnsetMode, PVoc, SpecDesc, SpecShape, Tempo};

use super::utils::{mean, number_crossings};

struct ZeroCrossingRateDesc {
    values: Vec<u32>,
    number_samples: usize,
}

impl ZeroCrossingRateDesc {
    const HOP_SIZE: usize = 1024;

    pub fn new() -> Self {
        ZeroCrossingRateDesc {
            values: Vec::new(),
            number_samples: 0,
        }
    }

    pub fn do_(&mut self, chunk: &[f32]) {
        self.values.push(number_crossings(chunk));
        self.number_samples += chunk.len();
    }

    pub fn get_value(&mut self) -> f32 {
        (self.values.iter().sum::<u32>()) as f32 / self.number_samples as f32
    }
}

// TODO write proper doc
struct TempoDesc {
    aubio_obj: Tempo,
}

impl TempoDesc {
    const WINDOW_SIZE: usize = 1024;
    const HOP_SIZE: usize = TempoDesc::WINDOW_SIZE / 4;

    pub fn new(sample_rate: u32) -> Self {
        TempoDesc {
            aubio_obj: Tempo::new(
                OnsetMode::SpecDiff,
                TempoDesc::WINDOW_SIZE,
                TempoDesc::HOP_SIZE,
                sample_rate,
            )
            .unwrap(),
        }
    }

    pub fn do_(&mut self, chunk: &[f32]) {
        self.aubio_obj.do_result(chunk).unwrap();
    }

    /**
     * Compute score related to tempo.
     * Right now, basically returns the song's BPM.
     *
     * - `song` Song to compute score from
     */
    pub fn get_value(&mut self) -> f32 {
        self.aubio_obj.get_bpm()
    }
}

struct SpectralCentroidDesc {
    aubio_obj: SpecDesc,
    phase_vocoder: PVoc,
    // Values before being summarized through f.ex. a mean
    values: Vec<f32>,
    sample_rate: u32,
}

impl SpectralCentroidDesc {
    const WINDOW_SIZE: usize = 512;
    const HOP_SIZE: usize = SpectralCentroidDesc::WINDOW_SIZE / 4;

    pub fn new(sample_rate: u32) -> Self {
        SpectralCentroidDesc {
            aubio_obj: SpecDesc::new(SpecShape::Centroid, SpectralCentroidDesc::WINDOW_SIZE)
                .unwrap(),
            phase_vocoder: PVoc::new(
                SpectralCentroidDesc::WINDOW_SIZE,
                SpectralCentroidDesc::HOP_SIZE,
            )
            .unwrap(),
            // TODO vec with capacity?
            values: Vec::new(),
            sample_rate,
        }
    }

    pub fn do_(&mut self, chunk: &[f32]) {
        let mut fftgrain: Vec<f32> = vec![0.0; SpectralCentroidDesc::WINDOW_SIZE + 2];
        // If silence, centroid will be off, so skip instead
        if silence_detection(chunk, -60.0) {
            return;
        }

        self.phase_vocoder
            .do_(chunk, fftgrain.as_mut_slice())
            .unwrap();
        let bin = self.aubio_obj.do_result(fftgrain.as_slice()).unwrap();
        let freq = bin_to_freq(
            bin,
            self.sample_rate as f32,
            SpectralCentroidDesc::WINDOW_SIZE as f32,
        );
        self.values.push(freq);
    }

    /**
     * Compute score related to spectral centroid.
     * Returns the mean of computed spectral centroids over the song.
     *
     * - `song` Song to compute score from
     */
    pub fn get_value(&mut self) -> f32 {
        mean(&self.values)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::decode::decode_song;

    #[test]
    fn test_zcr() {
        let song = decode_song("data/s16_mono_22_5kHz.flac").unwrap();
        let mut zcr_desc = ZeroCrossingRateDesc::new();
        for chunk in song.sample_array.chunks(ZeroCrossingRateDesc::HOP_SIZE) {
            zcr_desc.do_(&chunk);
        }
        assert!(0.001 > (0.075 - zcr_desc.get_value()).abs());
    }

    #[test]
    fn test_tempo() {
        let song = decode_song("data/s16_mono_22_5kHz.flac").unwrap();
        let mut tempo_desc = TempoDesc::new(song.sample_rate);
        for chunk in song.sample_array.chunks(TempoDesc::HOP_SIZE) {
            tempo_desc.do_(&chunk);
        }
        assert!(0.01 > (142.38 - tempo_desc.get_value()).abs());
    }

    #[test]
    fn test_centroid() {
        let song = decode_song("data/s16_mono_22_5kHz.flac").unwrap();
        let mut centroid_desc = SpectralCentroidDesc::new(song.sample_rate);
        for chunk in song.sample_array.chunks(SpectralCentroidDesc::HOP_SIZE) {
            centroid_desc.do_(&chunk);
        }
        assert!(0.01 > (1236.39 - centroid_desc.get_value()).abs());
    }
}
<commit_msg>Add spectral rolloff<commit_after>//! Song analysis module.
//!
//! Contains various functions to extract meaningful features from a `Song`,
//! e.g. tempo features, spectral features, etc.
#[cfg(feature = "aubio-lib")]
extern crate aubio_lib;

use aubio_rs::{bin_to_freq, silence_detection, OnsetMode, PVoc, SpecDesc, SpecShape, Tempo};

use super::utils::{mean, number_crossings};

struct ZeroCrossingRateDesc {
    values: Vec<u32>,
    number_samples: usize,
}

impl ZeroCrossingRateDesc {
    const HOP_SIZE: usize = 1024;

    pub fn new() -> Self {
        ZeroCrossingRateDesc {
            values: Vec::new(),
            number_samples: 0,
        }
    }

    pub fn do_(&mut self, chunk: &[f32]) {
        self.values.push(number_crossings(chunk));
        self.number_samples += chunk.len();
    }

    pub fn get_value(&mut self) -> f32 {
        (self.values.iter().sum::<u32>()) as f32 / self.number_samples as f32
    }
}

// TODO write proper doc
struct TempoDesc {
    aubio_obj: Tempo,
}

impl TempoDesc {
    const WINDOW_SIZE: usize = 1024;
    const HOP_SIZE: usize = TempoDesc::WINDOW_SIZE / 4;

    pub fn new(sample_rate: u32) -> Self {
        TempoDesc {
            aubio_obj: Tempo::new(
                OnsetMode::SpecDiff,
                TempoDesc::WINDOW_SIZE,
                TempoDesc::HOP_SIZE,
                sample_rate,
            )
            .unwrap(),
        }
    }

    pub fn do_(&mut self, chunk: &[f32]) {
        self.aubio_obj.do_result(chunk).unwrap();
    }

    /**
     * Compute score related to tempo.
     * Right now, basically returns the song's BPM.
     *
     * - `song` Song to compute score from
     */
    pub fn get_value(&mut self) -> f32 {
        self.aubio_obj.get_bpm()
    }
}

struct SpectralRollOffDesc {
    aubio_obj: SpecDesc,
    phase_vocoder: PVoc,
    // Values before being summarized through f.ex. a mean
    values: Vec<f32>,
    sample_rate: u32,
}

struct SpectralCentroidDesc {
    aubio_obj: SpecDesc,
    phase_vocoder: PVoc,
    // Values before being summarized through f.ex. a mean
    values: Vec<f32>,
    sample_rate: u32,
}

impl SpectralRollOffDesc {
    const WINDOW_SIZE: usize = 512;
    const HOP_SIZE: usize = SpectralRollOffDesc::WINDOW_SIZE / 4;

    pub fn new(sample_rate: u32) -> Self {
        SpectralRollOffDesc {
            aubio_obj: SpecDesc::new(SpecShape::Rolloff, SpectralRollOffDesc::WINDOW_SIZE)
                .unwrap(),
            phase_vocoder: PVoc::new(
                SpectralRollOffDesc::WINDOW_SIZE,
                SpectralRollOffDesc::HOP_SIZE,
            )
            .unwrap(),
            values: Vec::new(),
            sample_rate,
        }
    }

    pub fn do_(&mut self, chunk: &[f32]) {
        let mut fftgrain: Vec<f32> = vec![0.0; SpectralRollOffDesc::WINDOW_SIZE + 2];

        self.phase_vocoder
            .do_(chunk, fftgrain.as_mut_slice())
            .unwrap();
        let bin = self.aubio_obj.do_result(fftgrain.as_slice()).unwrap();
        let freq = bin_to_freq(
            bin,
            self.sample_rate as f32,
            SpectralRollOffDesc::WINDOW_SIZE as f32,
        );
        self.values.push(freq);
    }

    /**
     * Compute score related to spectral centroid.
     * Returns the mean of computed spectral centroids over the song.
     *
     * - `song` Song to compute score from
     */
    pub fn get_value(&mut self) -> f32 {
        mean(&self.values)
    }
}

impl SpectralCentroidDesc {
    const WINDOW_SIZE: usize = 512;
    const HOP_SIZE: usize = SpectralCentroidDesc::WINDOW_SIZE / 4;

    pub fn new(sample_rate: u32) -> Self {
        SpectralCentroidDesc {
            aubio_obj: SpecDesc::new(SpecShape::Centroid, SpectralCentroidDesc::WINDOW_SIZE)
                .unwrap(),
            phase_vocoder: PVoc::new(
                SpectralCentroidDesc::WINDOW_SIZE,
                SpectralCentroidDesc::HOP_SIZE,
            )
            .unwrap(),
            // TODO vec with capacity?
            values: Vec::new(),
            sample_rate,
        }
    }

    pub fn do_(&mut self, chunk: &[f32]) {
        let mut fftgrain: Vec<f32> = vec![0.0; SpectralCentroidDesc::WINDOW_SIZE + 2];
        // If silence, centroid will be off, so skip instead
        if silence_detection(chunk, -60.0) {
            return;
        }

        self.phase_vocoder
            .do_(chunk, fftgrain.as_mut_slice())
            .unwrap();
        let bin = self.aubio_obj.do_result(fftgrain.as_slice()).unwrap();
        let freq = bin_to_freq(
            bin,
            self.sample_rate as f32,
            SpectralCentroidDesc::WINDOW_SIZE as f32,
        );
        self.values.push(freq);
    }

    /**
     * Compute score related to spectral centroid.
     * Returns the mean of computed spectral centroids over the song.
     *
     * - `song` Song to compute score from
     */
    pub fn get_value(&mut self) -> f32 {
        mean(&self.values)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::decode::decode_song;

    #[test]
    fn test_zcr() {
        let song = decode_song("data/s16_mono_22_5kHz.flac").unwrap();
        let mut zcr_desc = ZeroCrossingRateDesc::new();
        for chunk in song.sample_array.chunks(ZeroCrossingRateDesc::HOP_SIZE) {
            zcr_desc.do_(&chunk);
        }
        assert!(0.001 > (0.075 - zcr_desc.get_value()).abs());
    }

    #[test]
    fn test_tempo() {
        let song = decode_song("data/s16_mono_22_5kHz.flac").unwrap();
        let mut tempo_desc = TempoDesc::new(song.sample_rate);
        for chunk in song.sample_array.chunks(TempoDesc::HOP_SIZE) {
            tempo_desc.do_(&chunk);
        }
        assert!(0.01 > (142.38 - tempo_desc.get_value()).abs());
    }

    #[test]
    fn test_roll_off() {
        let song = decode_song("data/s16_mono_22_5kHz.flac").unwrap();
        let mut roll_off_desc = SpectralRollOffDesc::new(song.sample_rate);
        for chunk in song.sample_array.chunks(SpectralRollOffDesc::HOP_SIZE) {
            roll_off_desc.do_(&chunk);
        }
        assert!(0.01 > (2026.69 - roll_off_desc.get_value()).abs());
    }

    #[test]
    fn test_centroid() {
        let song = decode_song("data/s16_mono_22_5kHz.flac").unwrap();
        let mut centroid_desc = SpectralCentroidDesc::new(song.sample_rate);
        for chunk in song.sample_array.chunks(SpectralCentroidDesc::HOP_SIZE) {
            centroid_desc.do_(&chunk);
        }
        assert!(0.01 > (1236.39 - centroid_desc.get_value()).abs());
    }
}
<|endoftext|>


<commit_before>use crate::common::util::*;

#[test]
fn test_current_directory() {
    let (at, mut ucmd) = at_and_ucmd!();
    let actual = ucmd.arg(".").run().stdout;
    let expect = at.root_dir_resolved() + "\n";
    println!("actual: {:?}", actual);
    println!("expect: {:?}", expect);
    assert_eq!(actual, expect);
}

#[test]
fn test_long_redirection_to_current_dir() {
    let (at, mut ucmd) = at_and_ucmd!();
    // Create a 256-character path to current directory
    let dir = path_concat!(".", ..128);
    let actual = ucmd.arg(dir).run().stdout;
    let expect = at.root_dir_resolved() + "\n";
    println!("actual: {:?}", actual);
    println!("expect: {:?}", expect);
    assert_eq!(actual, expect);
}

#[test]
fn test_long_redirection_to_root() {
    // Create a 255-character path to root
    let dir = path_concat!("..", ..85);
    let actual = new_ucmd!().arg(dir).run().stdout;
    let expect = get_root_path().to_owned() + "\n";
    println!("actual: {:?}", actual);
    println!("expect: {:?}", expect);
    assert_eq!(actual, expect);
}

#[test]
fn test_file_and_links() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;

    at.touch("foo");
    at.symlink_file("foo", "bar");

    let actual = scene.ucmd().arg("foo").run().stdout;
    println!("actual: {:?}", actual);
    assert!(actual.contains("foo\n"));

    let actual = scene.ucmd().arg("bar").run().stdout;
    println!("actual: {:?}", actual);
    assert!(actual.contains("foo\n"));
}

#[test]
fn test_file_and_links_zero() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;

    at.touch("foo");
    at.symlink_file("foo", "bar");

    let actual = scene.ucmd().arg("foo").arg("-z").run().stdout;
    println!("actual: {:?}", actual);
    assert!(actual.contains("foo"));
    assert!(!actual.contains("\n"));

    let actual = scene.ucmd().arg("bar").arg("-z").run().stdout;
    println!("actual: {:?}", actual);
    assert!(actual.contains("foo"));
    assert!(!actual.contains("\n"));
}

#[test]
fn test_file_and_links_strip() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;

    at.touch("foo");
    at.symlink_file("foo", "bar");

    let actual = scene.ucmd().arg("foo").arg("-s").run().stdout;
    println!("actual: {:?}", actual);
    assert!(actual.contains("foo\n"));

    let actual = scene.ucmd().arg("bar").arg("-s").run().stdout;
    println!("actual: {:?}", actual);
    assert!(actual.contains("bar\n"));
}

#[test]
fn test_file_and_links_strip_zero() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;

    at.touch("foo");
    at.symlink_file("foo", "bar");

    let actual = scene.ucmd().arg("foo").arg("-s").arg("-z").run().stdout;
    println!("actual: {:?}", actual);
    assert!(actual.contains("foo"));
    assert!(!actual.contains("\n"));

    let actual = scene.ucmd().arg("bar").arg("-s").arg("-z").run().stdout;
    println!("actual: {:?}", actual);
    assert!(actual.contains("bar"));
    assert!(!actual.contains("\n"));
}
<commit_msg>realpath: refactor tests for #1982<commit_after>use crate::common::util::*;

#[test]
fn test_realpath_current_directory() {
    let (at, mut ucmd) = at_and_ucmd!();
    let expect = at.root_dir_resolved() + "\n";
    ucmd.arg(".").succeeds().stdout_is(expect);
}

#[test]
fn test_realpath_long_redirection_to_current_dir() {
    let (at, mut ucmd) = at_and_ucmd!();
    // Create a 256-character path to current directory
    let dir = path_concat!(".", ..128);
    let expect = at.root_dir_resolved() + "\n";
    ucmd.arg(dir).succeeds().stdout_is(expect);
}

#[test]
fn test_realpath_long_redirection_to_root() {
    // Create a 255-character path to root
    let dir = path_concat!("..", ..85);
    let expect = get_root_path().to_owned() + "\n";
    new_ucmd!().arg(dir).succeeds().stdout_is(expect);
}

#[test]
fn test_realpath_file_and_links() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;

    at.touch("foo");
    at.symlink_file("foo", "bar");

    scene.ucmd().arg("foo").succeeds().stdout_contains("foo\n");
    scene.ucmd().arg("bar").succeeds().stdout_contains("foo\n");
}

#[test]
fn test_realpath_file_and_links_zero() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;

    at.touch("foo");
    at.symlink_file("foo", "bar");

    scene
        .ucmd()
        .arg("foo")
        .arg("-z")
        .succeeds()
        .stdout_contains("foo\u{0}");

    scene
        .ucmd()
        .arg("bar")
        .arg("-z")
        .succeeds()
        .stdout_contains("foo\u{0}");
}

#[test]
fn test_realpath_file_and_links_strip() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;

    at.touch("foo");
    at.symlink_file("foo", "bar");

    scene
        .ucmd()
        .arg("foo")
        .arg("-s")
        .succeeds()
        .stdout_contains("foo\n");

    scene
        .ucmd()
        .arg("bar")
        .arg("-s")
        .succeeds()
        .stdout_contains("bar\n");
}

#[test]
fn test_realpath_file_and_links_strip_zero() {
    let scene = TestScenario::new(util_name!());
    let at = &scene.fixtures;

    at.touch("foo");
    at.symlink_file("foo", "bar");

    scene
        .ucmd()
        .arg("foo")
        .arg("-s")
        .arg("-z")
        .succeeds()
        .stdout_contains("foo\u{0}");

    scene
        .ucmd()
        .arg("bar")
        .arg("-s")
        .arg("-z")
        .succeeds()
        .stdout_contains("bar\u{0}");
}
<|endoftext|>


<commit_before>use std::cmp::PartialOrd;
use num::{Num, Signed, Zero, One, abs};
use Anchor;

#[derive(Copy, Clone, PartialEq, PartialOrd, Hash, Default, Debug, Serialize, Deserialize)]
pub struct Rect<T: Copy> {
    /// Top left (closest to the origin) corner of the rectange.
    pub top: [T; 2],
    /// Size of the rectangle, all elements are assumed to always be positive.
    pub size: [T; 2],
}

impl<T> Rect<T> where T: Num + PartialOrd + Signed + Copy
{
    /// Create a new rectangle from two corner points.
    pub fn new<V: Into<[T; 2]>>(p1: V, p2: V) -> Rect<T> {
        let (p1, p2): ([T; 2], [T; 2]) = (p1.into(), p2.into());

        Rect {
            top: [*min(&p1[0], &p2[0]), *min(&p1[1], &p2[1])],
            size: [abs(p2[0] - p1[0]), abs(p2[1] - p1[1])],
        }
    }

    pub fn point(&self, point: Anchor) -> [T; 2] {
        let one: T = One::one();
        let two = one + one;
        match point {
            Anchor::TopLeft => self.top,
            Anchor::TopRight => [self.top[0] + self.size[0], self.top[1]],
            Anchor::BottomLeft => [self.top[0], self.top[1] + self.size[1]],
            Anchor::BottomRight => [self.top[0] + self.size[0], self.top[1] + self.size[1]],
            Anchor::Top => [self.top[0] + self.size[0] / two, self.top[1]],
            Anchor::Left => [self.top[0], self.top[1] + self.size[1] / two],
            Anchor::Right => [self.top[0] + self.size[0], self.top[1] + self.size[1] / two],
            Anchor::Bottom => [self.top[0] + self.size[0] / two, self.top[1] + self.size[1]],
            Anchor::Center => [self.top[0] + self.size[0] / two, self.top[1] + self.size[1] / two],
        }
    }

    /// Iterate tiles of the given size inside the rectangle.
    ///
    /// The tiles are ordered from left to right, then from top to bottom. The
    /// first tile snaps to the top left corner of the rectangle, and parts
    /// along the right and bottom edges of the rectangle are left uncovered
    /// if a whole tile will not fit in them.
    ///
    /// ```
    /// use calx_layout::Rect;
    ///
    /// let x = Rect::new([0, 0], [8, 16]);
    /// // To iterate integer points in the rectangle, just use [1, 1] tiles.
    /// assert_eq!(x.tiles([1, 1]).map(|x| x.top).next(), Some([0, 0]));
    /// assert_eq!(x.tiles([1, 1]).count(), 8 * 16);
    ///
    /// let y = Rect::new([0.0, 0.0], [3.141, 2.718]);
    /// assert_eq!(y.tiles([1.0, 1.0]).count(), 3 * 2);
    /// ```
    pub fn tiles<'a, V: Into<[T; 2]>>(&'a self, dim: V) -> TileIter<'a, T> {
        TileIter::new(self, dim.into())
    }

    pub fn area(&self) -> T {
        self.size[0] * self.size[1]
    }
}

/// Iterator for packed left-to-right top-to-bottom subrectangles
pub struct TileIter<'a, T: 'a+Copy> {
    base: &'a Rect<T>,
    dim: [T; 2],
    x: T,
    y: T,
}

impl<'a, T: Num + PartialOrd + Copy + 'a> TileIter<'a, T> {
    fn new(base: &'a Rect<T>, dim: [T; 2]) -> TileIter<T> {
        assert!(dim[0] > Zero::zero() && dim[1] > Zero::zero());
        TileIter {
            base: base,
            dim: dim,
            x: Zero::zero(),
            y: Zero::zero(),
        }
    }
}

impl<'a, T: Num + PartialOrd + Copy> Iterator for TileIter<'a, T> {
    type Item = Rect<T>;

    fn next(&mut self) -> Option<Rect<T>> {
        if self.dim[0] > self.base.size[0] {
            return None;
        }

        if (self.x + One::one()) * self.dim[0] > self.base.size[0] {
            self.y = self.y + One::one();
            self.x = Zero::zero();
        }

        if (self.y + One::one()) * self.dim[1] > self.base.size[1] {
            return None;
        }

        let ret = Rect {
            top: [self.x * self.dim[0], self.y * self.dim[1]],
            size: self.dim,
        };
        self.x = self.x + One::one();
        Some(ret)
    }
}

fn min<'a, T: PartialOrd>(a: &'a T, b: &'a T) -> &'a T {
    if a.lt(b) {
        a
    } else {
        b
    }
}
<commit_msg>Rustfmt<commit_after>use std::cmp::PartialOrd;
use num::{Num, Signed, Zero, One, abs};
use Anchor;

#[derive(Copy, Clone, PartialEq, PartialOrd, Hash, Default, Debug, Serialize, Deserialize)]
pub struct Rect<T: Copy> {
    /// Top left (closest to the origin) corner of the rectange.
    pub top: [T; 2],
    /// Size of the rectangle, all elements are assumed to always be positive.
    pub size: [T; 2],
}

impl<T> Rect<T> where T: Num + PartialOrd + Signed + Copy
{
    /// Create a new rectangle from two corner points.
    pub fn new<V: Into<[T; 2]>>(p1: V, p2: V) -> Rect<T> {
        let (p1, p2): ([T; 2], [T; 2]) = (p1.into(), p2.into());

        Rect {
            top: [*min(&p1[0], &p2[0]), *min(&p1[1], &p2[1])],
            size: [abs(p2[0] - p1[0]), abs(p2[1] - p1[1])],
        }
    }

    pub fn point(&self, point: Anchor) -> [T; 2] {
        let one: T = One::one();
        let two = one + one;
        match point {
            Anchor::TopLeft => self.top,
            Anchor::TopRight => [self.top[0] + self.size[0], self.top[1]],
            Anchor::BottomLeft => [self.top[0], self.top[1] + self.size[1]],
            Anchor::BottomRight => {
                [self.top[0] + self.size[0], self.top[1] + self.size[1]]
            }
            Anchor::Top => [self.top[0] + self.size[0] / two, self.top[1]],
            Anchor::Left => [self.top[0], self.top[1] + self.size[1] / two],
            Anchor::Right => {
                [self.top[0] + self.size[0], self.top[1] + self.size[1] / two]
            }
            Anchor::Bottom => {
                [self.top[0] + self.size[0] / two, self.top[1] + self.size[1]]
            }
            Anchor::Center => {
                [self.top[0] + self.size[0] / two,
                 self.top[1] + self.size[1] / two]
            }
        }
    }

    /// Iterate tiles of the given size inside the rectangle.
    ///
    /// The tiles are ordered from left to right, then from top to bottom. The
    /// first tile snaps to the top left corner of the rectangle, and parts
    /// along the right and bottom edges of the rectangle are left uncovered
    /// if a whole tile will not fit in them.
    ///
    /// ```
    /// use calx_layout::Rect;
    ///
    /// let x = Rect::new([0, 0], [8, 16]);
    /// // To iterate integer points in the rectangle, just use [1, 1] tiles.
    /// assert_eq!(x.tiles([1, 1]).map(|x| x.top).next(), Some([0, 0]));
    /// assert_eq!(x.tiles([1, 1]).count(), 8 * 16);
    ///
    /// let y = Rect::new([0.0, 0.0], [3.141, 2.718]);
    /// assert_eq!(y.tiles([1.0, 1.0]).count(), 3 * 2);
    /// ```
    pub fn tiles<'a, V: Into<[T; 2]>>(&'a self, dim: V) -> TileIter<'a, T> {
        TileIter::new(self, dim.into())
    }

    pub fn area(&self) -> T {
        self.size[0] * self.size[1]
    }
}

/// Iterator for packed left-to-right top-to-bottom subrectangles
pub struct TileIter<'a, T: 'a + Copy> {
    base: &'a Rect<T>,
    dim: [T; 2],
    x: T,
    y: T,
}

impl<'a, T: Num + PartialOrd + Copy + 'a> TileIter<'a, T> {
    fn new(base: &'a Rect<T>, dim: [T; 2]) -> TileIter<T> {
        assert!(dim[0] > Zero::zero() && dim[1] > Zero::zero());
        TileIter {
            base: base,
            dim: dim,
            x: Zero::zero(),
            y: Zero::zero(),
        }
    }
}

impl<'a, T: Num + PartialOrd + Copy> Iterator for TileIter<'a, T> {
    type Item = Rect<T>;

    fn next(&mut self) -> Option<Rect<T>> {
        if self.dim[0] > self.base.size[0] {
            return None;
        }

        if (self.x + One::one()) * self.dim[0] > self.base.size[0] {
            self.y = self.y + One::one();
            self.x = Zero::zero();
        }

        if (self.y + One::one()) * self.dim[1] > self.base.size[1] {
            return None;
        }

        let ret = Rect {
            top: [self.x * self.dim[0], self.y * self.dim[1]],
            size: self.dim,
        };
        self.x = self.x + One::one();
        Some(ret)
    }
}

fn min<'a, T: PartialOrd>(a: &'a T, b: &'a T) -> &'a T {
    if a.lt(b) {
        a
    } else {
        b
    }
}
<|endoftext|>


<commit_before>/// If `num` is dividable by 3 and 5, return "FizzBuzz", if it is dividable by 3,
/// return "Fizz", if it is dividable by 5, return "Buzz", for all the other
/// cases, return the number.
fn fizz_buzz(number: i8) -> String {
	if number % 3 == 0 && number % 5 ==0 {
		return "FizzBuzz".to_string();
	} else if number % 3 == 0 {
		return "Fizz".to_string();
	} else if number % 5 == 0 {
		return "Buzz".to_string();
	} else {
		return number.to_string();
	}
}

/// Iterate numbers from 1 to 100 and write result of `fizzBuzz` function to
/// stdout.
fn main() {
	for number in 1..100 {
		println!("{}", fizz_buzz(number))
	}
}<commit_msg>Fixed count to 100 for Rust version<commit_after>/// If `num` is dividable by 3 and 5, return "FizzBuzz", if it is dividable by 3,
/// return "Fizz", if it is dividable by 5, return "Buzz", for all the other
/// cases, return the number.
fn fizz_buzz(number: i8) -> String {
	if number % 3 == 0 && number % 5 ==0 {
		return "FizzBuzz".to_string();
	} else if number % 3 == 0 {
		return "Fizz".to_string();
	} else if number % 5 == 0 {
		return "Buzz".to_string();
	} else {
		return number.to_string();
	}
}

/// Iterate numbers from 1 to 100 and write result of `fizzBuzz` function to
/// stdout.
fn main() {
	for number in 1..101 {
		println!("{}", fizz_buzz(number))
	}
}
<|endoftext|>


<commit_before>use crate::syntax::atom::Atom::{self, *};
use crate::syntax::improper::ImproperCtype;
use crate::syntax::report::Errors;
use crate::syntax::set::{OrderedSet as Set, UnorderedSet};
use crate::syntax::{
    toposort, Api, Derive, Enum, ExternFn, ExternType, Impl, Pair, ResolvableName, Struct, Type,
    TypeAlias,
};
use proc_macro2::Ident;
use quote::ToTokens;
use std::collections::BTreeMap as Map;

pub struct Types<'a> {
    pub all: Set<&'a Type>,
    pub structs: Map<&'a Ident, &'a Struct>,
    pub enums: Map<&'a Ident, &'a Enum>,
    pub cxx: Set<&'a Ident>,
    pub rust: Set<&'a Ident>,
    pub aliases: Map<&'a Ident, &'a TypeAlias>,
    pub untrusted: Map<&'a Ident, &'a ExternType>,
    pub required_trivial: Map<&'a Ident, TrivialReason<'a>>,
    pub explicit_impls: Set<&'a Impl>,
    pub resolutions: Map<&'a Ident, &'a Pair>,
    pub struct_improper_ctypes: UnorderedSet<&'a Ident>,
    pub toposorted_structs: Vec<&'a Struct>,
}

impl<'a> Types<'a> {
    pub fn collect(cx: &mut Errors, apis: &'a [Api]) -> Self {
        let mut all = Set::new();
        let mut structs = Map::new();
        let mut enums = Map::new();
        let mut cxx = Set::new();
        let mut rust = Set::new();
        let mut aliases = Map::new();
        let mut untrusted = Map::new();
        let mut explicit_impls = Set::new();
        let mut resolutions = Map::new();
        let struct_improper_ctypes = UnorderedSet::new();
        let toposorted_structs = Vec::new();

        fn visit<'a>(all: &mut Set<&'a Type>, ty: &'a Type) {
            all.insert(ty);
            match ty {
                Type::Ident(_) | Type::Str(_) | Type::Void(_) | Type::SliceRefU8(_) => {}
                Type::RustBox(ty)
                | Type::UniquePtr(ty)
                | Type::CxxVector(ty)
                | Type::RustVec(ty) => visit(all, &ty.inner),
                Type::Ref(r) => visit(all, &r.inner),
                Type::Slice(s) => visit(all, &s.inner),
                Type::Array(a) => visit(all, &a.inner),
                Type::Fn(f) => {
                    if let Some(ret) = &f.ret {
                        visit(all, ret);
                    }
                    for arg in &f.args {
                        visit(all, &arg.ty);
                    }
                }
            }
        }

        let mut add_resolution = |pair: &'a Pair| {
            resolutions.insert(&pair.rust, pair);
        };

        let mut type_names = UnorderedSet::new();
        let mut function_names = UnorderedSet::new();
        for api in apis {
            // The same identifier is permitted to be declared as both a shared
            // enum and extern C++ type, or shared struct and extern C++ type.
            // That indicates to not emit the C++ enum/struct definition because
            // it's defined by the included headers already.
            //
            // All other cases of duplicate identifiers are reported as an error.
            match api {
                Api::Include(_) => {}
                Api::Struct(strct) => {
                    let ident = &strct.name.rust;
                    if !type_names.insert(ident)
                        && (!cxx.contains(ident)
                            || structs.contains_key(ident)
                            || enums.contains_key(ident))
                    {
                        // If already declared as a struct or enum, or if
                        // colliding with something other than an extern C++
                        // type, then error.
                        duplicate_name(cx, strct, ident);
                    }
                    structs.insert(&strct.name.rust, strct);
                    for field in &strct.fields {
                        visit(&mut all, &field.ty);
                    }
                    add_resolution(&strct.name);
                }
                Api::Enum(enm) => {
                    all.insert(&enm.repr_type);
                    let ident = &enm.name.rust;
                    if !type_names.insert(ident)
                        && (!cxx.contains(ident)
                            || structs.contains_key(ident)
                            || enums.contains_key(ident))
                    {
                        // If already declared as a struct or enum, or if
                        // colliding with something other than an extern C++
                        // type, then error.
                        duplicate_name(cx, enm, ident);
                    }
                    enums.insert(ident, enm);
                    add_resolution(&enm.name);
                }
                Api::CxxType(ety) => {
                    let ident = &ety.name.rust;
                    if !type_names.insert(ident)
                        && (cxx.contains(ident)
                            || !structs.contains_key(ident) && !enums.contains_key(ident))
                    {
                        // If already declared as an extern C++ type, or if
                        // colliding with something which is neither struct nor
                        // enum, then error.
                        duplicate_name(cx, ety, ident);
                    }
                    cxx.insert(ident);
                    if !ety.trusted {
                        untrusted.insert(ident, ety);
                    }
                    add_resolution(&ety.name);
                }
                Api::RustType(ety) => {
                    let ident = &ety.name.rust;
                    if !type_names.insert(ident) {
                        duplicate_name(cx, ety, ident);
                    }
                    rust.insert(ident);
                    add_resolution(&ety.name);
                }
                Api::CxxFunction(efn) | Api::RustFunction(efn) => {
                    // Note: duplication of the C++ name is fine because C++ has
                    // function overloading.
                    if !function_names.insert((&efn.receiver, &efn.name.rust)) {
                        duplicate_name(cx, efn, &efn.name.rust);
                    }
                    for arg in &efn.args {
                        visit(&mut all, &arg.ty);
                    }
                    if let Some(ret) = &efn.ret {
                        visit(&mut all, ret);
                    }
                }
                Api::TypeAlias(alias) => {
                    let ident = &alias.name.rust;
                    if !type_names.insert(ident) {
                        duplicate_name(cx, alias, ident);
                    }
                    cxx.insert(ident);
                    aliases.insert(ident, alias);
                    add_resolution(&alias.name);
                }
                Api::Impl(imp) => {
                    visit(&mut all, &imp.ty);
                    explicit_impls.insert(imp);
                }
            }
        }

        // All these APIs may contain types passed by value. We need to ensure
        // we check that this is permissible. We do this _after_ scanning all
        // the APIs above, in case some function or struct references a type
        // which is declared subsequently.
        let mut required_trivial = Map::new();
        let mut insist_alias_types_are_trivial = |ty: &'a Type, reason| {
            if let Type::Ident(ident) = ty {
                if cxx.contains(&ident.rust)
                    && !structs.contains_key(&ident.rust)
                    && !enums.contains_key(&ident.rust)
                {
                    required_trivial.entry(&ident.rust).or_insert(reason);
                }
            }
        };
        for api in apis {
            match api {
                Api::Struct(strct) => {
                    let reason = TrivialReason::StructField(strct);
                    for field in &strct.fields {
                        insist_alias_types_are_trivial(&field.ty, reason);
                    }
                }
                Api::CxxFunction(efn) | Api::RustFunction(efn) => {
                    let reason = TrivialReason::FunctionArgument(efn);
                    for arg in &efn.args {
                        insist_alias_types_are_trivial(&arg.ty, reason);
                    }
                    if let Some(ret) = &efn.ret {
                        let reason = TrivialReason::FunctionReturn(efn);
                        insist_alias_types_are_trivial(&ret, reason);
                    }
                }
                _ => {}
            }
        }

        let mut types = Types {
            all,
            structs,
            enums,
            cxx,
            rust,
            aliases,
            untrusted,
            required_trivial,
            explicit_impls,
            resolutions,
            struct_improper_ctypes,
            toposorted_structs,
        };

        types.toposorted_structs = toposort::sort(cx, apis, &types);

        let mut unresolved_structs: Vec<&Ident> = types.structs.keys().copied().collect();
        let mut new_information = true;
        while new_information {
            new_information = false;
            unresolved_structs.retain(|ident| {
                let mut retain = false;
                for var in &types.structs[ident].fields {
                    if match types.determine_improper_ctype(&var.ty) {
                        ImproperCtype::Depends(inner) => {
                            retain = true;
                            types.struct_improper_ctypes.contains(inner)
                        }
                        ImproperCtype::Definite(improper) => improper,
                    } {
                        types.struct_improper_ctypes.insert(ident);
                        new_information = true;
                        return false;
                    }
                }
                // If all fields definite false, remove from unresolved_structs.
                retain
            });
        }

        types
    }

    pub fn needs_indirect_abi(&self, ty: &Type) -> bool {
        match ty {
            Type::Ident(ident) => {
                if let Some(strct) = self.structs.get(&ident.rust) {
                    !self.is_pod(strct)
                } else {
                    Atom::from(&ident.rust) == Some(RustString)
                }
            }
            Type::RustVec(_) => true,
            _ => false,
        }
    }

    pub fn is_pod(&self, strct: &Struct) -> bool {
        for derive in &strct.derives {
            if *derive == Derive::Copy {
                return true;
            }
        }
        false
    }

    // Types that trigger rustc's default #[warn(improper_ctypes)] lint, even if
    // they may be otherwise unproblematic to mention in an extern signature.
    // For example in a signature like `extern "C" fn(*const String)`, rustc
    // refuses to believe that C could know how to supply us with a pointer to a
    // Rust String, even though C could easily have obtained that pointer
    // legitimately from a Rust call.
    pub fn is_considered_improper_ctype(&self, ty: &Type) -> bool {
        match self.determine_improper_ctype(ty) {
            ImproperCtype::Definite(improper) => improper,
            ImproperCtype::Depends(ident) => self.struct_improper_ctypes.contains(ident),
        }
    }

    pub fn resolve(&self, ident: &ResolvableName) -> &Pair {
        self.resolutions
            .get(&ident.rust)
            .expect("Unable to resolve type")
    }
}

impl<'t, 'a> IntoIterator for &'t Types<'a> {
    type Item = &'a Type;
    type IntoIter = crate::syntax::set::Iter<'t, 'a, Type>;
    fn into_iter(self) -> Self::IntoIter {
        self.all.into_iter()
    }
}

#[derive(Copy, Clone)]
pub enum TrivialReason<'a> {
    StructField(&'a Struct),
    FunctionArgument(&'a ExternFn),
    FunctionReturn(&'a ExternFn),
}

fn duplicate_name(cx: &mut Errors, sp: impl ToTokens, ident: &Ident) {
    let msg = format!("the name `{}` is defined multiple times", ident);
    cx.error(sp, msg);
}
<commit_msg>Set needs_indirect_abi for Array<commit_after>use crate::syntax::atom::Atom::{self, *};
use crate::syntax::improper::ImproperCtype;
use crate::syntax::report::Errors;
use crate::syntax::set::{OrderedSet as Set, UnorderedSet};
use crate::syntax::{
    toposort, Api, Derive, Enum, ExternFn, ExternType, Impl, Pair, ResolvableName, Struct, Type,
    TypeAlias,
};
use proc_macro2::Ident;
use quote::ToTokens;
use std::collections::BTreeMap as Map;

pub struct Types<'a> {
    pub all: Set<&'a Type>,
    pub structs: Map<&'a Ident, &'a Struct>,
    pub enums: Map<&'a Ident, &'a Enum>,
    pub cxx: Set<&'a Ident>,
    pub rust: Set<&'a Ident>,
    pub aliases: Map<&'a Ident, &'a TypeAlias>,
    pub untrusted: Map<&'a Ident, &'a ExternType>,
    pub required_trivial: Map<&'a Ident, TrivialReason<'a>>,
    pub explicit_impls: Set<&'a Impl>,
    pub resolutions: Map<&'a Ident, &'a Pair>,
    pub struct_improper_ctypes: UnorderedSet<&'a Ident>,
    pub toposorted_structs: Vec<&'a Struct>,
}

impl<'a> Types<'a> {
    pub fn collect(cx: &mut Errors, apis: &'a [Api]) -> Self {
        let mut all = Set::new();
        let mut structs = Map::new();
        let mut enums = Map::new();
        let mut cxx = Set::new();
        let mut rust = Set::new();
        let mut aliases = Map::new();
        let mut untrusted = Map::new();
        let mut explicit_impls = Set::new();
        let mut resolutions = Map::new();
        let struct_improper_ctypes = UnorderedSet::new();
        let toposorted_structs = Vec::new();

        fn visit<'a>(all: &mut Set<&'a Type>, ty: &'a Type) {
            all.insert(ty);
            match ty {
                Type::Ident(_) | Type::Str(_) | Type::Void(_) | Type::SliceRefU8(_) => {}
                Type::RustBox(ty)
                | Type::UniquePtr(ty)
                | Type::CxxVector(ty)
                | Type::RustVec(ty) => visit(all, &ty.inner),
                Type::Ref(r) => visit(all, &r.inner),
                Type::Slice(s) => visit(all, &s.inner),
                Type::Array(a) => visit(all, &a.inner),
                Type::Fn(f) => {
                    if let Some(ret) = &f.ret {
                        visit(all, ret);
                    }
                    for arg in &f.args {
                        visit(all, &arg.ty);
                    }
                }
            }
        }

        let mut add_resolution = |pair: &'a Pair| {
            resolutions.insert(&pair.rust, pair);
        };

        let mut type_names = UnorderedSet::new();
        let mut function_names = UnorderedSet::new();
        for api in apis {
            // The same identifier is permitted to be declared as both a shared
            // enum and extern C++ type, or shared struct and extern C++ type.
            // That indicates to not emit the C++ enum/struct definition because
            // it's defined by the included headers already.
            //
            // All other cases of duplicate identifiers are reported as an error.
            match api {
                Api::Include(_) => {}
                Api::Struct(strct) => {
                    let ident = &strct.name.rust;
                    if !type_names.insert(ident)
                        && (!cxx.contains(ident)
                            || structs.contains_key(ident)
                            || enums.contains_key(ident))
                    {
                        // If already declared as a struct or enum, or if
                        // colliding with something other than an extern C++
                        // type, then error.
                        duplicate_name(cx, strct, ident);
                    }
                    structs.insert(&strct.name.rust, strct);
                    for field in &strct.fields {
                        visit(&mut all, &field.ty);
                    }
                    add_resolution(&strct.name);
                }
                Api::Enum(enm) => {
                    all.insert(&enm.repr_type);
                    let ident = &enm.name.rust;
                    if !type_names.insert(ident)
                        && (!cxx.contains(ident)
                            || structs.contains_key(ident)
                            || enums.contains_key(ident))
                    {
                        // If already declared as a struct or enum, or if
                        // colliding with something other than an extern C++
                        // type, then error.
                        duplicate_name(cx, enm, ident);
                    }
                    enums.insert(ident, enm);
                    add_resolution(&enm.name);
                }
                Api::CxxType(ety) => {
                    let ident = &ety.name.rust;
                    if !type_names.insert(ident)
                        && (cxx.contains(ident)
                            || !structs.contains_key(ident) && !enums.contains_key(ident))
                    {
                        // If already declared as an extern C++ type, or if
                        // colliding with something which is neither struct nor
                        // enum, then error.
                        duplicate_name(cx, ety, ident);
                    }
                    cxx.insert(ident);
                    if !ety.trusted {
                        untrusted.insert(ident, ety);
                    }
                    add_resolution(&ety.name);
                }
                Api::RustType(ety) => {
                    let ident = &ety.name.rust;
                    if !type_names.insert(ident) {
                        duplicate_name(cx, ety, ident);
                    }
                    rust.insert(ident);
                    add_resolution(&ety.name);
                }
                Api::CxxFunction(efn) | Api::RustFunction(efn) => {
                    // Note: duplication of the C++ name is fine because C++ has
                    // function overloading.
                    if !function_names.insert((&efn.receiver, &efn.name.rust)) {
                        duplicate_name(cx, efn, &efn.name.rust);
                    }
                    for arg in &efn.args {
                        visit(&mut all, &arg.ty);
                    }
                    if let Some(ret) = &efn.ret {
                        visit(&mut all, ret);
                    }
                }
                Api::TypeAlias(alias) => {
                    let ident = &alias.name.rust;
                    if !type_names.insert(ident) {
                        duplicate_name(cx, alias, ident);
                    }
                    cxx.insert(ident);
                    aliases.insert(ident, alias);
                    add_resolution(&alias.name);
                }
                Api::Impl(imp) => {
                    visit(&mut all, &imp.ty);
                    explicit_impls.insert(imp);
                }
            }
        }

        // All these APIs may contain types passed by value. We need to ensure
        // we check that this is permissible. We do this _after_ scanning all
        // the APIs above, in case some function or struct references a type
        // which is declared subsequently.
        let mut required_trivial = Map::new();
        let mut insist_alias_types_are_trivial = |ty: &'a Type, reason| {
            if let Type::Ident(ident) = ty {
                if cxx.contains(&ident.rust)
                    && !structs.contains_key(&ident.rust)
                    && !enums.contains_key(&ident.rust)
                {
                    required_trivial.entry(&ident.rust).or_insert(reason);
                }
            }
        };
        for api in apis {
            match api {
                Api::Struct(strct) => {
                    let reason = TrivialReason::StructField(strct);
                    for field in &strct.fields {
                        insist_alias_types_are_trivial(&field.ty, reason);
                    }
                }
                Api::CxxFunction(efn) | Api::RustFunction(efn) => {
                    let reason = TrivialReason::FunctionArgument(efn);
                    for arg in &efn.args {
                        insist_alias_types_are_trivial(&arg.ty, reason);
                    }
                    if let Some(ret) = &efn.ret {
                        let reason = TrivialReason::FunctionReturn(efn);
                        insist_alias_types_are_trivial(&ret, reason);
                    }
                }
                _ => {}
            }
        }

        let mut types = Types {
            all,
            structs,
            enums,
            cxx,
            rust,
            aliases,
            untrusted,
            required_trivial,
            explicit_impls,
            resolutions,
            struct_improper_ctypes,
            toposorted_structs,
        };

        types.toposorted_structs = toposort::sort(cx, apis, &types);

        let mut unresolved_structs: Vec<&Ident> = types.structs.keys().copied().collect();
        let mut new_information = true;
        while new_information {
            new_information = false;
            unresolved_structs.retain(|ident| {
                let mut retain = false;
                for var in &types.structs[ident].fields {
                    if match types.determine_improper_ctype(&var.ty) {
                        ImproperCtype::Depends(inner) => {
                            retain = true;
                            types.struct_improper_ctypes.contains(inner)
                        }
                        ImproperCtype::Definite(improper) => improper,
                    } {
                        types.struct_improper_ctypes.insert(ident);
                        new_information = true;
                        return false;
                    }
                }
                // If all fields definite false, remove from unresolved_structs.
                retain
            });
        }

        types
    }

    pub fn needs_indirect_abi(&self, ty: &Type) -> bool {
        match ty {
            Type::Ident(ident) => {
                if let Some(strct) = self.structs.get(&ident.rust) {
                    !self.is_pod(strct)
                } else {
                    Atom::from(&ident.rust) == Some(RustString)
                }
            }
            Type::RustVec(_) | Type::Array(_) => true,
            _ => false,
        }
    }

    pub fn is_pod(&self, strct: &Struct) -> bool {
        for derive in &strct.derives {
            if *derive == Derive::Copy {
                return true;
            }
        }
        false
    }

    // Types that trigger rustc's default #[warn(improper_ctypes)] lint, even if
    // they may be otherwise unproblematic to mention in an extern signature.
    // For example in a signature like `extern "C" fn(*const String)`, rustc
    // refuses to believe that C could know how to supply us with a pointer to a
    // Rust String, even though C could easily have obtained that pointer
    // legitimately from a Rust call.
    pub fn is_considered_improper_ctype(&self, ty: &Type) -> bool {
        match self.determine_improper_ctype(ty) {
            ImproperCtype::Definite(improper) => improper,
            ImproperCtype::Depends(ident) => self.struct_improper_ctypes.contains(ident),
        }
    }

    pub fn resolve(&self, ident: &ResolvableName) -> &Pair {
        self.resolutions
            .get(&ident.rust)
            .expect("Unable to resolve type")
    }
}

impl<'t, 'a> IntoIterator for &'t Types<'a> {
    type Item = &'a Type;
    type IntoIter = crate::syntax::set::Iter<'t, 'a, Type>;
    fn into_iter(self) -> Self::IntoIter {
        self.all.into_iter()
    }
}

#[derive(Copy, Clone)]
pub enum TrivialReason<'a> {
    StructField(&'a Struct),
    FunctionArgument(&'a ExternFn),
    FunctionReturn(&'a ExternFn),
}

fn duplicate_name(cx: &mut Errors, sp: impl ToTokens, ident: &Ident) {
    let msg = format!("the name `{}` is defined multiple times", ident);
    cx.error(sp, msg);
}
<|endoftext|>


<commit_before>use autograd::{Function, FuncIntf, FuncDelegate, FIWrap, OptVarKindList, Variable, VariableArgs, VarKind};
use tensor::{TensorKindList, OptTensorKindList};

pub struct Threshold {
    delegate: Function,
    saved_tensors: Vec<::tensor::TensorKind>,
    threshold: f64,
    value: f64,
    inplace: bool,
}

impl Threshold {
    pub fn new(threshold: f64, value: f64, inplace: bool) -> FIWrap<Self> {
        if inplace {
            panic!("in-place processing requires value ({}) to not \
                    exceed threshold ({})",
                   value,
                   threshold);
        }

        FIWrap::new(Threshold {
                        delegate: Function::new(),
                        saved_tensors: Vec::new(),
                        threshold: threshold,
                        value: value,
                        inplace: inplace,
                    })
    }
}

impl_func_delegate!(Threshold);

impl FuncIntf for Threshold {
    fn forward(&mut self, input_: &mut TensorKindList) -> TensorKindList {
        let mut input = input_.remove(0);
        let mut backend = input.backend();
        let mut output = if self.inplace {
            self.mark_dirty(&vec![input.clone()]);
            input.clone()
        } else {
            input.new(()).resize_as_(&input)
        };
        // XXX check if training
        self.saved_tensors.push(input.clone());
        backend.Threshold_updateOutput(&mut input,
                                       &mut output,
                                       self.threshold,
                                       self.value,
                                       self.inplace);
        vec![output]
    }
    fn backward(&mut self, grad_output_list: &mut OptTensorKindList) -> OptTensorKindList {
        let mut grad_output  = grad_output_list.remove(0).unwrap();
        let mut input = self.saved_tensors.remove(0);
        let needs_input_grad = self.needs_input_grad().clone();

        println!("Threshold backward");
        let grad_input = if needs_input_grad[0] {
            let mut grad_input = input.new(());
            let mut backend = input.backend();
            backend.Threshold_updateGradInput(
                &mut input,
                &mut grad_output,
                &mut grad_input,
                self.threshold,
                self.value,
                false
            );
            Some(grad_input)
        } else {
            None
        };
        vec![grad_input, None, None, None]
    }
}
<commit_msg>rustfmt<commit_after>use autograd::{Function, FuncIntf, FuncDelegate, FIWrap, OptVarKindList, Variable, VariableArgs,
               VarKind};
use tensor::{TensorKindList, OptTensorKindList};

pub struct Threshold {
    delegate: Function,
    saved_tensors: Vec<::tensor::TensorKind>,
    threshold: f64,
    value: f64,
    inplace: bool,
}

impl Threshold {
    pub fn new(threshold: f64, value: f64, inplace: bool) -> FIWrap<Self> {
        if inplace {
            panic!("in-place processing requires value ({}) to not \
                    exceed threshold ({})",
                   value,
                   threshold);
        }

        FIWrap::new(Threshold {
                        delegate: Function::new(),
                        saved_tensors: Vec::new(),
                        threshold: threshold,
                        value: value,
                        inplace: inplace,
                    })
    }
}

impl_func_delegate!(Threshold);

impl FuncIntf for Threshold {
    fn forward(&mut self, input_: &mut TensorKindList) -> TensorKindList {
        let mut input = input_.remove(0);
        let mut backend = input.backend();
        let mut output = if self.inplace {
            self.mark_dirty(&vec![input.clone()]);
            input.clone()
        } else {
            input.new(()).resize_as_(&input)
        };
        // XXX check if training
        self.saved_tensors.push(input.clone());
        backend.Threshold_updateOutput(&mut input,
                                       &mut output,
                                       self.threshold,
                                       self.value,
                                       self.inplace);
        vec![output]
    }
    fn backward(&mut self, grad_output_list: &mut OptTensorKindList) -> OptTensorKindList {
        let mut grad_output = grad_output_list.remove(0).unwrap();
        let mut input = self.saved_tensors.remove(0);
        let needs_input_grad = self.needs_input_grad().clone();

        println!("Threshold backward");
        let grad_input = if needs_input_grad[0] {
            let mut grad_input = input.new(());
            let mut backend = input.backend();
            backend.Threshold_updateGradInput(&mut input,
                                              &mut grad_output,
                                              &mut grad_input,
                                              self.threshold,
                                              self.value,
                                              false);
            Some(grad_input)
        } else {
            None
        };
        vec![grad_input, None, None, None]
    }
}
<|endoftext|>


<commit_before>extern crate security_framework;
extern crate tempdir;

use self::security_framework::base;
use self::security_framework::certificate::SecCertificate;
use self::security_framework::identity::SecIdentity;
use self::security_framework::import_export::Pkcs12ImportOptions;
use self::security_framework::random::SecRandom;
use self::security_framework::secure_transport::{self, SslContext, ProtocolSide, ConnectionType};
use self::security_framework::os::macos::keychain;
use self::security_framework::os::macos::import_export::Pkcs12ImportOptionsExt;
use self::tempdir::TempDir;
use std::fmt;
use std::io;
use std::error;

pub struct Error(base::Error);

impl error::Error for Error {
    fn description(&self) -> &str {
        error::Error::description(&self.0)
    }

    fn cause(&self) -> Option<&error::Error> {
        error::Error::cause(&self.0)
    }
}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.0, fmt)
    }
}

impl fmt::Debug for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, fmt)
    }
}

impl From<base::Error> for Error {
    fn from(error: base::Error) -> Error {
        Error(error)
    }
}

pub struct Certificate(SecCertificate);

pub struct Identity(SecIdentity);

pub struct Pkcs12 {
    pub identity: Identity,
    pub chain: Vec<Certificate>,
}

impl Pkcs12 {
    pub fn parse(buf: &[u8], pass: &str) -> Result<Pkcs12, Error> {
        let dir = TempDir::new("native_tls").unwrap(); //fixme
        let keychain = try!(keychain::CreateOptions::new()
            .password(pass) // FIXME maybe generate a secure random password here?
            .create(dir.path().join("keychain")));

        let mut import = try!(Pkcs12ImportOptions::new()
            .passphrase(pass)
            .keychain(keychain)
            .import(buf));
        let import = import.pop().unwrap();

        Ok(Pkcs12 {
            identity: Identity(import.identity),
            // FIXME filter out the identity's cert (we're sending it twice currently)
            chain: import.cert_chain.into_iter().map(Certificate).collect(),
        })
    }
}

pub enum HandshakeError<S> {
    Interrupted(MidHandshakeTlsStream<S>),
    Failure(Error),
}

impl<S> From<secure_transport::HandshakeError<S>> for HandshakeError<S> {
    fn from(e: secure_transport::HandshakeError<S>) -> HandshakeError<S> {
        match e {
            secure_transport::HandshakeError::Failure(e) => HandshakeError::Failure(e.into()),
            secure_transport::HandshakeError::Interrupted(s) => {
                HandshakeError::Interrupted(MidHandshakeTlsStream(s))
            }
        }
    }
}

impl<S> From<base::Error> for HandshakeError<S> {
    fn from(e: base::Error) -> HandshakeError<S> {
        HandshakeError::Failure(e.into())
    }
}

pub struct MidHandshakeTlsStream<S>(secure_transport::MidHandshakeSslStream<S>);

impl<S> fmt::Debug for MidHandshakeTlsStream<S>
    where S: fmt::Debug
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, fmt)
    }
}

impl<S> MidHandshakeTlsStream<S>
    where S: io::Read + io::Write
{
    pub fn get_ref(&self) -> &S {
        self.0.get_ref()
    }

    pub fn get_mut(&mut self) -> &mut S {
        self.0.get_mut()
    }

    pub fn handshake(self) -> Result<TlsStream<S>, HandshakeError<S>> {
        match self.0.handshake() {
            Ok(s) => Ok(TlsStream(s)),
            Err(e) => Err(e.into()),
        }
    }
}

pub struct ClientBuilder(());

impl ClientBuilder {
    pub fn new() -> Result<ClientBuilder, Error> {
        Ok(ClientBuilder(()))
    }

    pub fn handshake<S>(&mut self,
                        domain: &str,
                        stream: S)
                        -> Result<TlsStream<S>, HandshakeError<S>>
        where S: io::Read + io::Write
    {
        let mut ctx = try!(SslContext::new(ProtocolSide::Client, ConnectionType::Stream));
        try!(ctx.set_peer_domain_name(domain));
        match ctx.handshake(stream) {
            Ok(s) => Ok(TlsStream(s)),
            Err(e) => Err(e.into()),
        }
    }
}

pub struct ServerBuilder {
    identity: SecIdentity,
    chain: Vec<SecCertificate>,
}

impl ServerBuilder {
    pub fn new<I>(identity: Identity, chain: I) -> Result<ServerBuilder, Error>
        where I: IntoIterator<Item = Certificate>
    {
        Ok(ServerBuilder {
            identity: identity.0,
            chain: chain.into_iter().map(|c| c.0).collect(),
        })
    }

    pub fn handshake<S>(&mut self, stream: S) -> Result<TlsStream<S>, HandshakeError<S>>
        where S: io::Read + io::Write
    {
        let mut ctx = try!(SslContext::new(ProtocolSide::Server, ConnectionType::Stream));
        try!(ctx.set_certificate(&self.identity, &self.chain));
        match ctx.handshake(stream) {
            Ok(s) => Ok(TlsStream(s)),
            Err(e) => Err(e.into()),
        }
    }
}

pub struct TlsStream<S>(secure_transport::SslStream<S>);

impl<S: fmt::Debug> fmt::Debug for TlsStream<S> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, fmt)
    }
}

impl<S: io::Read + io::Write> TlsStream<S> {
    pub fn get_ref(&self) -> &S {
        self.0.get_ref()
    }

    pub fn get_mut(&mut self) -> &mut S {
        self.0.get_mut()
    }

    pub fn buffered_read_size(&self) -> Result<usize, Error> {
        Ok(try!(self.0.context().buffered_read_size()))
    }
}

impl<S: io::Read + io::Write> io::Read for TlsStream<S> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.0.read(buf)
    }
}

impl<S: io::Read + io::Write> io::Write for TlsStream<S> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.0.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.0.flush()
    }
}

/// Security Framework-specific extensions to `TlsStream`.
pub trait TlsStreamExt<S> {
    /// Returns a shared reference to the Security Framework `SslStream`.
    fn raw_stream(&self) -> &secure_transport::SslStream<S>;

    /// Returns a mutable reference to the Security Framework `SslStream`.
    fn raw_stream_mut(&mut self) -> &mut secure_transport::SslStream<S>;
}

impl<S> TlsStreamExt<S> for ::TlsStream<S> {
    fn raw_stream(&self) -> &secure_transport::SslStream<S> {
        &(self.0).0
    }

    fn raw_stream_mut(&mut self) -> &mut secure_transport::SslStream<S> {
        &mut (self.0).0
    }
}
<commit_msg>Cut out duplicated cert<commit_after>extern crate security_framework;
extern crate tempdir;

use self::security_framework::base;
use self::security_framework::certificate::SecCertificate;
use self::security_framework::identity::SecIdentity;
use self::security_framework::import_export::Pkcs12ImportOptions;
use self::security_framework::random::SecRandom;
use self::security_framework::secure_transport::{self, SslContext, ProtocolSide, ConnectionType};
use self::security_framework::os::macos::keychain;
use self::security_framework::os::macos::import_export::Pkcs12ImportOptionsExt;
use self::tempdir::TempDir;
use std::fmt;
use std::io;
use std::error;

pub struct Error(base::Error);

impl error::Error for Error {
    fn description(&self) -> &str {
        error::Error::description(&self.0)
    }

    fn cause(&self) -> Option<&error::Error> {
        error::Error::cause(&self.0)
    }
}

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.0, fmt)
    }
}

impl fmt::Debug for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, fmt)
    }
}

impl From<base::Error> for Error {
    fn from(error: base::Error) -> Error {
        Error(error)
    }
}

pub struct Certificate(SecCertificate);

pub struct Identity(SecIdentity);

pub struct Pkcs12 {
    pub identity: Identity,
    pub chain: Vec<Certificate>,
}

impl Pkcs12 {
    pub fn parse(buf: &[u8], pass: &str) -> Result<Pkcs12, Error> {
        let dir = TempDir::new("native_tls").unwrap(); //fixme
        let keychain = try!(keychain::CreateOptions::new()
            .password(pass) // FIXME maybe generate a secure random password here?
            .create(dir.path().join("keychain")));

        let mut import = try!(Pkcs12ImportOptions::new()
            .passphrase(pass)
            .keychain(keychain)
            .import(buf));
        let import = import.pop().unwrap();

        // The identity's cert shows up in the chain, so filter it out to avoid sending twice
        // FIXME should probably use CFEquals here
        let identity_cert = try!(import.identity.certificate()).to_der();

        Ok(Pkcs12 {
            identity: Identity(import.identity),
            chain: import.cert_chain
                .into_iter()
                .filter(|c| c.to_der() != identity_cert)
                .map(Certificate)
                .collect(),
        })
    }
}

pub enum HandshakeError<S> {
    Interrupted(MidHandshakeTlsStream<S>),
    Failure(Error),
}

impl<S> From<secure_transport::HandshakeError<S>> for HandshakeError<S> {
    fn from(e: secure_transport::HandshakeError<S>) -> HandshakeError<S> {
        match e {
            secure_transport::HandshakeError::Failure(e) => HandshakeError::Failure(e.into()),
            secure_transport::HandshakeError::Interrupted(s) => {
                HandshakeError::Interrupted(MidHandshakeTlsStream(s))
            }
        }
    }
}

impl<S> From<base::Error> for HandshakeError<S> {
    fn from(e: base::Error) -> HandshakeError<S> {
        HandshakeError::Failure(e.into())
    }
}

pub struct MidHandshakeTlsStream<S>(secure_transport::MidHandshakeSslStream<S>);

impl<S> fmt::Debug for MidHandshakeTlsStream<S>
    where S: fmt::Debug
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, fmt)
    }
}

impl<S> MidHandshakeTlsStream<S>
    where S: io::Read + io::Write
{
    pub fn get_ref(&self) -> &S {
        self.0.get_ref()
    }

    pub fn get_mut(&mut self) -> &mut S {
        self.0.get_mut()
    }

    pub fn handshake(self) -> Result<TlsStream<S>, HandshakeError<S>> {
        match self.0.handshake() {
            Ok(s) => Ok(TlsStream(s)),
            Err(e) => Err(e.into()),
        }
    }
}

pub struct ClientBuilder(());

impl ClientBuilder {
    pub fn new() -> Result<ClientBuilder, Error> {
        Ok(ClientBuilder(()))
    }

    pub fn handshake<S>(&mut self,
                        domain: &str,
                        stream: S)
                        -> Result<TlsStream<S>, HandshakeError<S>>
        where S: io::Read + io::Write
    {
        let mut ctx = try!(SslContext::new(ProtocolSide::Client, ConnectionType::Stream));
        try!(ctx.set_peer_domain_name(domain));
        match ctx.handshake(stream) {
            Ok(s) => Ok(TlsStream(s)),
            Err(e) => Err(e.into()),
        }
    }
}

pub struct ServerBuilder {
    identity: SecIdentity,
    chain: Vec<SecCertificate>,
}

impl ServerBuilder {
    pub fn new<I>(identity: Identity, chain: I) -> Result<ServerBuilder, Error>
        where I: IntoIterator<Item = Certificate>
    {
        Ok(ServerBuilder {
            identity: identity.0,
            chain: chain.into_iter().map(|c| c.0).collect(),
        })
    }

    pub fn handshake<S>(&mut self, stream: S) -> Result<TlsStream<S>, HandshakeError<S>>
        where S: io::Read + io::Write
    {
        let mut ctx = try!(SslContext::new(ProtocolSide::Server, ConnectionType::Stream));
        try!(ctx.set_certificate(&self.identity, &self.chain));
        match ctx.handshake(stream) {
            Ok(s) => Ok(TlsStream(s)),
            Err(e) => Err(e.into()),
        }
    }
}

pub struct TlsStream<S>(secure_transport::SslStream<S>);

impl<S: fmt::Debug> fmt::Debug for TlsStream<S> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, fmt)
    }
}

impl<S: io::Read + io::Write> TlsStream<S> {
    pub fn get_ref(&self) -> &S {
        self.0.get_ref()
    }

    pub fn get_mut(&mut self) -> &mut S {
        self.0.get_mut()
    }

    pub fn buffered_read_size(&self) -> Result<usize, Error> {
        Ok(try!(self.0.context().buffered_read_size()))
    }
}

impl<S: io::Read + io::Write> io::Read for TlsStream<S> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.0.read(buf)
    }
}

impl<S: io::Read + io::Write> io::Write for TlsStream<S> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.0.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.0.flush()
    }
}

/// Security Framework-specific extensions to `TlsStream`.
pub trait TlsStreamExt<S> {
    /// Returns a shared reference to the Security Framework `SslStream`.
    fn raw_stream(&self) -> &secure_transport::SslStream<S>;

    /// Returns a mutable reference to the Security Framework `SslStream`.
    fn raw_stream_mut(&mut self) -> &mut secure_transport::SslStream<S>;
}

impl<S> TlsStreamExt<S> for ::TlsStream<S> {
    fn raw_stream(&self) -> &secure_transport::SslStream<S> {
        &(self.0).0
    }

    fn raw_stream_mut(&mut self) -> &mut secure_transport::SslStream<S> {
        &mut (self.0).0
    }
}
<|endoftext|>