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

//! Terminfo database interface.

use std::collections::HashMap;
use std::env;
use std::error;
use std::fmt;
use std::fs::File;
use std::io::prelude::*;
use std::io;
use std::io::BufReader;
use std::path::Path;

use Attr;
use color;
use Terminal;
use self::searcher::get_dbpath_for_term;
use self::parser::compiled::{parse, msys_terminfo};
use self::parm::{expand, Variables, Param};

/// A parsed terminfo database entry.
#[derive(Debug)]
pub struct TermInfo {
    /// Names for the terminal
    pub names: Vec<String>,
    /// Map of capability name to boolean value
    pub bools: HashMap<String, bool>,
    /// Map of capability name to numeric value
    pub numbers: HashMap<String, u16>,
    /// Map of capability name to raw (unexpanded) string
    pub strings: HashMap<String, Vec<u8>>,
}

/// A terminfo creation error.
#[derive(Debug)]
pub enum Error {
    /// TermUnset Indicates that the environment doesn't include enough information to find
    /// the terminfo entry.
    TermUnset,
    /// MalformedTerminfo indicates that parsing the terminfo entry failed.
    MalformedTerminfo(String),
    /// io::Error forwards any io::Errors encountered when finding or reading the terminfo entry.
    IoError(io::Error),
}

impl error::Error for Error {
    fn description(&self) -> &str {
        "failed to create TermInfo"
    }

    fn cause(&self) -> Option<&error::Error> {
        use self::Error::*;
        match self {
            &IoError(ref e) => Some(e),
            _ => None,
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Error::*;
        match self {
            &TermUnset => Ok(()),
            &MalformedTerminfo(ref e) => e.fmt(f),
            &IoError(ref e) => e.fmt(f),
        }
    }
}

impl TermInfo {
    /// Create a TermInfo based on current environment.
    pub fn from_env() -> Result<TermInfo, Error> {
        let term = match env::var("TERM") {
            Ok(name) => TermInfo::from_name(&name),
            Err(..) => return Err(Error::TermUnset),
        };

        if term.is_err() && env::var("MSYSCON").ok().map_or(false, |s| "mintty.exe" == s) {
            // msys terminal
            Ok(msys_terminfo())
        } else {
            term
        }
    }

    /// Create a TermInfo for the named terminal.
    pub fn from_name(name: &str) -> Result<TermInfo, Error> {
        get_dbpath_for_term(name)
            .ok_or_else(|| {
                Error::IoError(io::Error::new(io::ErrorKind::NotFound, "terminfo file not found"))
            })
            .and_then(|p| TermInfo::from_path(&(*p)))
    }

    /// Parse the given TermInfo.
    pub fn from_path<P: AsRef<Path>>(path: P) -> Result<TermInfo, Error> {
        Self::_from_path(path.as_ref())
    }
    // Keep the metadata small
    fn _from_path(path: &Path) -> Result<TermInfo, Error> {
        let file = File::open(path).map_err(|e| Error::IoError(e))?;
        let mut reader = BufReader::new(file);
        parse(&mut reader, false).map_err(|e| Error::MalformedTerminfo(e))
    }
}

pub mod searcher;

/// TermInfo format parsing.
pub mod parser {
    //! ncurses-compatible compiled terminfo format parsing (term(5))
    pub mod compiled;
}
pub mod parm;

fn cap_for_attr(attr: Attr) -> &'static str {
    match attr {
        Attr::Bold => "bold",
        Attr::Dim => "dim",
        Attr::Italic(true) => "sitm",
        Attr::Italic(false) => "ritm",
        Attr::Underline(true) => "smul",
        Attr::Underline(false) => "rmul",
        Attr::Blink => "blink",
        Attr::Standout(true) => "smso",
        Attr::Standout(false) => "rmso",
        Attr::Reverse => "rev",
        Attr::Secure => "invis",
        Attr::ForegroundColor(_) => "setaf",
        Attr::BackgroundColor(_) => "setab",
    }
}

/// A Terminal that knows how many colors it supports, with a reference to its
/// parsed Terminfo database record.
pub struct TerminfoTerminal<T> {
    num_colors: u16,
    out: T,
    ti: TermInfo,
}

impl<T: Write + Send> Terminal for TerminfoTerminal<T> {
    type Output = T;
    fn fg(&mut self, color: color::Color) -> io::Result<bool> {
        let color = self.dim_if_necessary(color);
        if self.num_colors > color {
            return self.apply_cap("setaf", &[Param::Number(color as i32)]);
        }
        Ok(false)
    }

    fn bg(&mut self, color: color::Color) -> io::Result<bool> {
        let color = self.dim_if_necessary(color);
        if self.num_colors > color {
            return self.apply_cap("setab", &[Param::Number(color as i32)]);
        }
        Ok(false)
    }

    fn attr(&mut self, attr: Attr) -> io::Result<bool> {
        match attr {
            Attr::ForegroundColor(c) => self.fg(c),
            Attr::BackgroundColor(c) => self.bg(c),
            _ => self.apply_cap(cap_for_attr(attr), &[]),
        }
    }

    fn supports_attr(&self, attr: Attr) -> bool {
        match attr {
            Attr::ForegroundColor(_) | Attr::BackgroundColor(_) => self.num_colors > 0,
            _ => {
                let cap = cap_for_attr(attr);
                self.ti.strings.get(cap).is_some()
            }
        }
    }

    fn reset(&mut self) -> io::Result<bool> {
        // are there any terminals that have color/attrs and not sgr0?
        // Try falling back to sgr, then op
        let cmd = match ["sg0", "sgr", "op"]
                            .iter()
                            .filter_map(|cap| self.ti.strings.get(*cap))
                            .next() {
            Some(op) => {
                match expand(&op, &[], &mut Variables::new()) {
                    Ok(cmd) => cmd,
                    Err(e) => return Err(io::Error::new(io::ErrorKind::InvalidData, e)),
                }
            }
            None => return Ok(false),
        };
        self.out.write_all(&cmd).and(Ok(true))
    }

    fn get_ref(&self) -> &T {
        &self.out
    }

    fn get_mut(&mut self) -> &mut T {
        &mut self.out
    }

    fn into_inner(self) -> T
        where Self: Sized
    {
        self.out
    }
}

impl<T: Write + Send> TerminfoTerminal<T> {
    /// Create a new TerminfoTerminal with the given TermInfo and Write.
    pub fn new_with_terminfo(out: T, terminfo: TermInfo) -> TerminfoTerminal<T> {
        let nc = if terminfo.strings.contains_key("setaf") &&
                    terminfo.strings.contains_key("setab") {
            terminfo.numbers.get("colors").map_or(0, |&n| n)
        } else {
            0
        };

        TerminfoTerminal {
            out: out,
            ti: terminfo,
            num_colors: nc,
        }
    }

    /// Create a new TerminfoTerminal for the current environment with the given Write.
    ///
    /// Returns `None` when the terminfo cannot be found or parsed.
    pub fn new(out: T) -> Option<TerminfoTerminal<T>> {
        TermInfo::from_env().map(move |ti| TerminfoTerminal::new_with_terminfo(out, ti)).ok()
    }

    fn dim_if_necessary(&self, color: color::Color) -> color::Color {
        if color >= self.num_colors && color >= 8 && color < 16 {
            color - 8
        } else {
            color
        }
    }

    fn apply_cap(&mut self, cmd: &str, params: &[Param]) -> io::Result<bool> {
        match self.ti.strings.get(cmd) {
            Some(cmd) => {
                match expand(&cmd, params, &mut Variables::new()) {
                    Ok(s) => self.out.write_all(&s).and(Ok(true)),
                    Err(e) => Err(io::Error::new(io::ErrorKind::InvalidData, e)),
                }
            }
            None => Ok(false),
        }
    }
}

impl<T: Write> Write for TerminfoTerminal<T> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.out.write(buf)
    }

    fn flush(&mut self) -> io::Result<()> {
        self.out.flush()
    }
}
<commit_msg>Rollup merge of #38660 - martijnvermaat:terminfo-reset-typo, r=alexcrichton<commit_after>// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Terminfo database interface.

use std::collections::HashMap;
use std::env;
use std::error;
use std::fmt;
use std::fs::File;
use std::io::prelude::*;
use std::io;
use std::io::BufReader;
use std::path::Path;

use Attr;
use color;
use Terminal;
use self::searcher::get_dbpath_for_term;
use self::parser::compiled::{parse, msys_terminfo};
use self::parm::{expand, Variables, Param};

/// A parsed terminfo database entry.
#[derive(Debug)]
pub struct TermInfo {
    /// Names for the terminal
    pub names: Vec<String>,
    /// Map of capability name to boolean value
    pub bools: HashMap<String, bool>,
    /// Map of capability name to numeric value
    pub numbers: HashMap<String, u16>,
    /// Map of capability name to raw (unexpanded) string
    pub strings: HashMap<String, Vec<u8>>,
}

/// A terminfo creation error.
#[derive(Debug)]
pub enum Error {
    /// TermUnset Indicates that the environment doesn't include enough information to find
    /// the terminfo entry.
    TermUnset,
    /// MalformedTerminfo indicates that parsing the terminfo entry failed.
    MalformedTerminfo(String),
    /// io::Error forwards any io::Errors encountered when finding or reading the terminfo entry.
    IoError(io::Error),
}

impl error::Error for Error {
    fn description(&self) -> &str {
        "failed to create TermInfo"
    }

    fn cause(&self) -> Option<&error::Error> {
        use self::Error::*;
        match self {
            &IoError(ref e) => Some(e),
            _ => None,
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Error::*;
        match self {
            &TermUnset => Ok(()),
            &MalformedTerminfo(ref e) => e.fmt(f),
            &IoError(ref e) => e.fmt(f),
        }
    }
}

impl TermInfo {
    /// Create a TermInfo based on current environment.
    pub fn from_env() -> Result<TermInfo, Error> {
        let term = match env::var("TERM") {
            Ok(name) => TermInfo::from_name(&name),
            Err(..) => return Err(Error::TermUnset),
        };

        if term.is_err() && env::var("MSYSCON").ok().map_or(false, |s| "mintty.exe" == s) {
            // msys terminal
            Ok(msys_terminfo())
        } else {
            term
        }
    }

    /// Create a TermInfo for the named terminal.
    pub fn from_name(name: &str) -> Result<TermInfo, Error> {
        get_dbpath_for_term(name)
            .ok_or_else(|| {
                Error::IoError(io::Error::new(io::ErrorKind::NotFound, "terminfo file not found"))
            })
            .and_then(|p| TermInfo::from_path(&(*p)))
    }

    /// Parse the given TermInfo.
    pub fn from_path<P: AsRef<Path>>(path: P) -> Result<TermInfo, Error> {
        Self::_from_path(path.as_ref())
    }
    // Keep the metadata small
    fn _from_path(path: &Path) -> Result<TermInfo, Error> {
        let file = File::open(path).map_err(|e| Error::IoError(e))?;
        let mut reader = BufReader::new(file);
        parse(&mut reader, false).map_err(|e| Error::MalformedTerminfo(e))
    }
}

pub mod searcher;

/// TermInfo format parsing.
pub mod parser {
    //! ncurses-compatible compiled terminfo format parsing (term(5))
    pub mod compiled;
}
pub mod parm;

fn cap_for_attr(attr: Attr) -> &'static str {
    match attr {
        Attr::Bold => "bold",
        Attr::Dim => "dim",
        Attr::Italic(true) => "sitm",
        Attr::Italic(false) => "ritm",
        Attr::Underline(true) => "smul",
        Attr::Underline(false) => "rmul",
        Attr::Blink => "blink",
        Attr::Standout(true) => "smso",
        Attr::Standout(false) => "rmso",
        Attr::Reverse => "rev",
        Attr::Secure => "invis",
        Attr::ForegroundColor(_) => "setaf",
        Attr::BackgroundColor(_) => "setab",
    }
}

/// A Terminal that knows how many colors it supports, with a reference to its
/// parsed Terminfo database record.
pub struct TerminfoTerminal<T> {
    num_colors: u16,
    out: T,
    ti: TermInfo,
}

impl<T: Write + Send> Terminal for TerminfoTerminal<T> {
    type Output = T;
    fn fg(&mut self, color: color::Color) -> io::Result<bool> {
        let color = self.dim_if_necessary(color);
        if self.num_colors > color {
            return self.apply_cap("setaf", &[Param::Number(color as i32)]);
        }
        Ok(false)
    }

    fn bg(&mut self, color: color::Color) -> io::Result<bool> {
        let color = self.dim_if_necessary(color);
        if self.num_colors > color {
            return self.apply_cap("setab", &[Param::Number(color as i32)]);
        }
        Ok(false)
    }

    fn attr(&mut self, attr: Attr) -> io::Result<bool> {
        match attr {
            Attr::ForegroundColor(c) => self.fg(c),
            Attr::BackgroundColor(c) => self.bg(c),
            _ => self.apply_cap(cap_for_attr(attr), &[]),
        }
    }

    fn supports_attr(&self, attr: Attr) -> bool {
        match attr {
            Attr::ForegroundColor(_) | Attr::BackgroundColor(_) => self.num_colors > 0,
            _ => {
                let cap = cap_for_attr(attr);
                self.ti.strings.get(cap).is_some()
            }
        }
    }

    fn reset(&mut self) -> io::Result<bool> {
        // are there any terminals that have color/attrs and not sgr0?
        // Try falling back to sgr, then op
        let cmd = match ["sgr0", "sgr", "op"]
                            .iter()
                            .filter_map(|cap| self.ti.strings.get(*cap))
                            .next() {
            Some(op) => {
                match expand(&op, &[], &mut Variables::new()) {
                    Ok(cmd) => cmd,
                    Err(e) => return Err(io::Error::new(io::ErrorKind::InvalidData, e)),
                }
            }
            None => return Ok(false),
        };
        self.out.write_all(&cmd).and(Ok(true))
    }

    fn get_ref(&self) -> &T {
        &self.out
    }

    fn get_mut(&mut self) -> &mut T {
        &mut self.out
    }

    fn into_inner(self) -> T
        where Self: Sized
    {
        self.out
    }
}

impl<T: Write + Send> TerminfoTerminal<T> {
    /// Create a new TerminfoTerminal with the given TermInfo and Write.
    pub fn new_with_terminfo(out: T, terminfo: TermInfo) -> TerminfoTerminal<T> {
        let nc = if terminfo.strings.contains_key("setaf") &&
                    terminfo.strings.contains_key("setab") {
            terminfo.numbers.get("colors").map_or(0, |&n| n)
        } else {
            0
        };

        TerminfoTerminal {
            out: out,
            ti: terminfo,
            num_colors: nc,
        }
    }

    /// Create a new TerminfoTerminal for the current environment with the given Write.
    ///
    /// Returns `None` when the terminfo cannot be found or parsed.
    pub fn new(out: T) -> Option<TerminfoTerminal<T>> {
        TermInfo::from_env().map(move |ti| TerminfoTerminal::new_with_terminfo(out, ti)).ok()
    }

    fn dim_if_necessary(&self, color: color::Color) -> color::Color {
        if color >= self.num_colors && color >= 8 && color < 16 {
            color - 8
        } else {
            color
        }
    }

    fn apply_cap(&mut self, cmd: &str, params: &[Param]) -> io::Result<bool> {
        match self.ti.strings.get(cmd) {
            Some(cmd) => {
                match expand(&cmd, params, &mut Variables::new()) {
                    Ok(s) => self.out.write_all(&s).and(Ok(true)),
                    Err(e) => Err(io::Error::new(io::ErrorKind::InvalidData, e)),
                }
            }
            None => Ok(false),
        }
    }
}

impl<T: Write> Write for TerminfoTerminal<T> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.out.write(buf)
    }

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


<commit_before>use anyhow::{Context, Result};
use lazy_static::lazy_static;
use pretty_assertions::assert_eq;
use restack_testtools::gitscript;
use std::{fs, path};

const RESTACK: &str = env!("CARGO_BIN_EXE_restack");

lazy_static! {
    static ref FIXTURES_DIR: path::PathBuf =
        path::PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("fixtures");
    static ref DEFAULT_GITSCRIPT_GROUP: gitscript::Group =
        gitscript::Group::new(FIXTURES_DIR.as_path());
}

pub fn open_fixture<P>(script_path: P) -> Result<gitscript::Fixture<'static>>
where
    P: AsRef<path::Path>,
{
    DEFAULT_GITSCRIPT_GROUP.open(script_path)
}

#[test]
fn simple_stack() -> Result<()> {
    let repo_fixture = open_fixture("simple_stack.sh")?;

    duct::cmd!(
        "git",
        "config",
        "sequence.editor",
        format!("{} edit", RESTACK)
    )
    .dir(repo_fixture.dir())
    .run()?;

    duct::cmd!("git", "rebase", "--interactive", "main")
        .env("EDITOR", FIXTURES_DIR.join("bin/add_break.sh"))
        .dir(repo_fixture.dir())
        .run()?;

    // add_break.sh should have seen a rebase list
    // with instructions to update branches.
    // To verify this, introduce a new commit at the top of the stack,
    // and verify that that file is present in all branches after the rebase finishes.

    fs::write(repo_fixture.dir().join("README"), "wait for me")?;
    duct::cmd!(
        "bash",
        "-c",
        "git add README &&
        git commit -m 'add README' &&
        git rebase --continue"
    )
    .dir(repo_fixture.dir())
    .run()?;

    let branches = &["foo", "bar", "baz"];
    for br in branches {
        let got = duct::cmd!("git", "show", format!("{}:README", br))
            .dir(repo_fixture.dir())
            .read()
            .with_context(|| format!("Unable to print {}:README", br))?;

        assert_eq!(
            "wait for me", &got,
            "Contents of {}:README do not match",
            br
        );
    }

    Ok(())
}
<commit_msg>test/edit: Verify --editor flag, test editor failures<commit_after>use anyhow::{Context, Result};
use lazy_static::lazy_static;
use pretty_assertions::assert_eq;
use restack_testtools::gitscript;
use rstest::rstest;
use std::fmt::Write;
use std::{fs, path};

const RESTACK: &str = env!("CARGO_BIN_EXE_restack");

lazy_static! {
    static ref FIXTURES_DIR: path::PathBuf =
        path::PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("fixtures");
    static ref DEFAULT_GITSCRIPT_GROUP: gitscript::Group =
        gitscript::Group::new(FIXTURES_DIR.as_path());
}

pub fn open_fixture<P>(script_path: P) -> Result<gitscript::Fixture<'static>>
where
    P: AsRef<path::Path>,
{
    DEFAULT_GITSCRIPT_GROUP.open(script_path)
}

#[rstest]
#[case::editor_flag(true)]
#[case::editor_env(false)]
fn simple_stack(#[case] editor_flag: bool) -> Result<()> {
    let repo_fixture = open_fixture("simple_stack.sh")?;

    let editor = FIXTURES_DIR.join("bin/add_break.sh");

    let mut seq_editor = format!("{} edit", RESTACK);
    if editor_flag {
        write!(&mut seq_editor, " --editor {}", editor.display())?;
    }

    duct::cmd!("git", "config", "sequence.editor", seq_editor)
        .dir(repo_fixture.dir())
        .run()?;

    duct::cmd!("git", "rebase", "--interactive", "main")
        .env("EDITOR", FIXTURES_DIR.join("bin/add_break.sh"))
        .dir(repo_fixture.dir())
        .run()?;

    // add_break.sh should have seen a rebase list
    // with instructions to update branches.
    // To verify this, introduce a new commit at the top of the stack,
    // and verify that that file is present in all branches after the rebase finishes.

    fs::write(repo_fixture.dir().join("README"), "wait for me")?;
    duct::cmd!(
        "bash",
        "-c",
        "git add README &&
        git commit -m 'add README' &&
        git rebase --continue"
    )
    .dir(repo_fixture.dir())
    .run()?;

    let branches = &["foo", "bar", "baz"];
    for br in branches {
        let got = duct::cmd!("git", "show", format!("{}:README", br))
            .dir(repo_fixture.dir())
            .read()
            .with_context(|| format!("Unable to print {}:README", br))?;

        assert_eq!(
            "wait for me", &got,
            "Contents of {}:README do not match",
            br
        );
    }

    Ok(())
}

#[rstest]
#[case::empty("", "No editor specified: please use --editor")]
#[case::non_zero_status("false", "Editor returned non-zero status")]
#[case::malicious("rm", "Could not overwrite")]
fn editor_error(#[case] editor: &str, #[case] msg: &str) -> Result<()> {
    let repo_fixture = open_fixture("simple_stack.sh")?;

    let seq_editor = format!("{} edit", RESTACK);
    duct::cmd!("git", "config", "sequence.editor", seq_editor)
        .dir(repo_fixture.dir())
        .run()?;

    let out = duct::cmd!("git", "rebase", "--interactive", "main")
        .env("EDITOR", editor)
        .dir(repo_fixture.dir())
        .stderr_capture()
        .unchecked()
        .run()?;

    assert!(!out.status.success());
    let stderr = String::from_utf8(out.stderr)?;
    assert!(
        stderr.contains(msg),
        "unexpected stderr, must contain '{}':\n{}",
        msg,
        &stderr
    );

    Ok(())
}
<|endoftext|>


<commit_before>
extern crate ndarray;
extern crate ndarray_linalg as linalg;

use ndarray::prelude::*;
use linalg::SquareMatrix;

#[test]
fn test_eigh() {
    let a = arr2(&[[3.0, 1.0, 1.0], [1.0, 3.0, 1.0], [1.0, 1.0, 3.0]]);
    let (e, vecs) = a.clone().eigh().unwrap();
    println!("eigenvalues = \n{:?}", e);
    println!("V = \n{:?}", vecs);
    let av = a.dot(&vecs);
    println!("AV = \n{:?}", av);
}
<commit_msg>Write valid test for eigh #7<commit_after>
extern crate ndarray;
extern crate ndarray_linalg as linalg;

use ndarray::prelude::*;
use linalg::SquareMatrix;

#[test]
fn test_eigh() {
    let a = arr2(&[[3.0, 1.0, 1.0], [1.0, 3.0, 1.0], [1.0, 1.0, 3.0]]);
    let (e, vecs) = a.clone().eigh().unwrap();
    assert!(e.all_close(&arr1(&[2.0, 2.0, 5.0]), 1.0e-7));
    for (i, v) in vecs.axis_iter(Axis(1)).enumerate() {
        let av = a.dot(&v);
        let ev = v.mapv(|x| e[i] * x);
        assert!(av.all_close(&ev, 1.0e-7));
    }
}
<|endoftext|>


<commit_before>mod migration;
mod migration_error;
mod schema;

pub use self::migration_error::*;
use self::migration::*;

use ::query_dsl::*;
use self::schema::NewMigration;
use self::schema::__diesel_schema_migrations::dsl::*;
use {Connection, QueryResult};

use std::collections::HashSet;
use std::env;
use std::path::{PathBuf, Path};

pub fn run_pending_migrations(conn: &Connection) -> Result<(), RunMigrationsError> {
    try!(create_schema_migrations_table_if_needed(conn));
    let already_run = try!(previously_run_migration_versions(conn));
    let migrations_dir = try!(find_migrations_directory());
    let all_migrations = try!(migrations_in_directory(&migrations_dir));
    let pending_migrations = all_migrations.into_iter().filter(|m| {
        !already_run.contains(m.version())
    });
    run_migrations(conn, pending_migrations)
}

fn create_schema_migrations_table_if_needed(conn: &Connection) -> QueryResult<usize> {
    conn.execute("CREATE TABLE IF NOT EXISTS __diesel_schema_migrations (
        version VARCHAR PRIMARY KEY NOT NULL,
        run_on TIMESTAMP NOT NULL DEFAULT NOW()
    )")
}

fn previously_run_migration_versions(conn: &Connection) -> QueryResult<HashSet<String>> {
    __diesel_schema_migrations.select(version)
        .load(&conn)
        .map(|r| r.collect())
}

fn migrations_in_directory(path: &Path) -> Result<Vec<Box<Migration>>, MigrationError> {
    use self::migration::migration_from;

    try!(path.read_dir())
        .filter_map(|entry| {
            let entry = match entry {
                Ok(e) => e,
                Err(e) => return Some(Err(e.into())),
            };
            if !entry.file_name().to_string_lossy().starts_with(".") {
                Some(migration_from(entry.path()))
            } else {
                None
            }
        }).collect()
}

fn run_migrations<T>(conn: &Connection, migrations: T)
    -> Result<(), RunMigrationsError> where
        T: Iterator<Item=Box<Migration>>
{
    use ::query_builder::insert;

    for migration in migrations {
        try!(conn.transaction(|| {
            println!("Running migration {}", migration.version());
            try!(migration.run(conn));
            try!(insert(&NewMigration(migration.version()))
                 .into(__diesel_schema_migrations)
                 .execute(&conn));
            Ok(())
        }));
    }
    Ok(())
}

/// Returns the directory containing migrations. Will look at for
/// $PWD/migrations. If it is not found, it will search the parents
/// of the current directory, until it reaches the directory containing
/// `Cargo.toml`. Returns `MigrationError::MigrationDirectoryNotFound`
/// if no directory is found.
fn find_migrations_directory() -> Result<PathBuf, MigrationError> {
    search_for_migrations_directory(&try!(env::current_dir()))
}

fn search_for_migrations_directory(path: &Path) -> Result<PathBuf, MigrationError> {
    let migration_path = path.join("migrations");
    if migration_path.is_dir() {
        Ok(migration_path)
    } else if path.join("Cargo.toml").exists() {
        Err(MigrationError::MigrationDirectoryNotFound)
    } else {
        path.parent().map(search_for_migrations_directory)
            .unwrap_or(Err(MigrationError::MigrationDirectoryNotFound))
    }
}

#[cfg(test)]
mod tests {
    extern crate tempdir;

    use super::*;
    use super::find_migrations_directory;

    use self::tempdir::TempDir;
    use std::{env, fs};

    #[test]
    fn migration_directory_not_found_if_no_migration_dir_exists() {
        let dir = TempDir::new("diesel").unwrap();

        env::set_current_dir(dir.path()).unwrap();

        assert_eq!(Err(MigrationError::MigrationDirectoryNotFound),
            find_migrations_directory());
    }

    #[test]
    fn migration_directory_defaults_to_pwd_slash_migrations() {
        let dir = TempDir::new("diesel").unwrap();
        let temp_path = dir.path();
        let migrations_path = temp_path.join("migrations");

        env::set_current_dir(temp_path).unwrap();
        fs::create_dir(&migrations_path).unwrap();

        assert_eq!(Ok(migrations_path), find_migrations_directory());
    }

    #[test]
    fn migration_directory_checks_parents() {
        let dir = TempDir::new("diesel").unwrap();
        let temp_path = dir.path();
        let migrations_path = temp_path.join("migrations");
        let child_path = temp_path.join("child");

        fs::create_dir(&child_path).unwrap();
        fs::create_dir(&migrations_path).unwrap();
        env::set_current_dir(child_path).unwrap();

        assert_eq!(Ok(migrations_path), find_migrations_directory());
    }

    #[test]
    fn migration_directory_stops_at_cargo_toml() {
        let dir = TempDir::new("diesel").unwrap();
        let temp_path = dir.path();
        let migrations_path = temp_path.join("migrations");
        let child_path = temp_path.join("child");
        let grandchild_path = child_path.join("grandchild");

        fs::create_dir_all(&grandchild_path).unwrap();
        fs::create_dir(&migrations_path).unwrap();
        fs::File::create(child_path.join("Cargo.toml")).unwrap();
        env::set_current_dir(grandchild_path).unwrap();

        assert_eq!(Err(MigrationError::MigrationDirectoryNotFound),
            find_migrations_directory());
    }
}
<commit_msg>Fix the build on Mac<commit_after>mod migration;
mod migration_error;
mod schema;

pub use self::migration_error::*;
use self::migration::*;

use ::query_dsl::*;
use self::schema::NewMigration;
use self::schema::__diesel_schema_migrations::dsl::*;
use {Connection, QueryResult};

use std::collections::HashSet;
use std::env;
use std::path::{PathBuf, Path};

pub fn run_pending_migrations(conn: &Connection) -> Result<(), RunMigrationsError> {
    try!(create_schema_migrations_table_if_needed(conn));
    let already_run = try!(previously_run_migration_versions(conn));
    let migrations_dir = try!(find_migrations_directory());
    let all_migrations = try!(migrations_in_directory(&migrations_dir));
    let pending_migrations = all_migrations.into_iter().filter(|m| {
        !already_run.contains(m.version())
    });
    run_migrations(conn, pending_migrations)
}

fn create_schema_migrations_table_if_needed(conn: &Connection) -> QueryResult<usize> {
    conn.execute("CREATE TABLE IF NOT EXISTS __diesel_schema_migrations (
        version VARCHAR PRIMARY KEY NOT NULL,
        run_on TIMESTAMP NOT NULL DEFAULT NOW()
    )")
}

fn previously_run_migration_versions(conn: &Connection) -> QueryResult<HashSet<String>> {
    __diesel_schema_migrations.select(version)
        .load(&conn)
        .map(|r| r.collect())
}

fn migrations_in_directory(path: &Path) -> Result<Vec<Box<Migration>>, MigrationError> {
    use self::migration::migration_from;

    try!(path.read_dir())
        .filter_map(|entry| {
            let entry = match entry {
                Ok(e) => e,
                Err(e) => return Some(Err(e.into())),
            };
            if !entry.file_name().to_string_lossy().starts_with(".") {
                Some(migration_from(entry.path()))
            } else {
                None
            }
        }).collect()
}

fn run_migrations<T>(conn: &Connection, migrations: T)
    -> Result<(), RunMigrationsError> where
        T: Iterator<Item=Box<Migration>>
{
    use ::query_builder::insert;

    for migration in migrations {
        try!(conn.transaction(|| {
            println!("Running migration {}", migration.version());
            try!(migration.run(conn));
            try!(insert(&NewMigration(migration.version()))
                 .into(__diesel_schema_migrations)
                 .execute(&conn));
            Ok(())
        }));
    }
    Ok(())
}

/// Returns the directory containing migrations. Will look at for
/// $PWD/migrations. If it is not found, it will search the parents
/// of the current directory, until it reaches the directory containing
/// `Cargo.toml`. Returns `MigrationError::MigrationDirectoryNotFound`
/// if no directory is found.
fn find_migrations_directory() -> Result<PathBuf, MigrationError> {
    search_for_migrations_directory(&try!(env::current_dir()))
}

fn search_for_migrations_directory(path: &Path) -> Result<PathBuf, MigrationError> {
    let migration_path = path.join("migrations");
    if migration_path.is_dir() {
        Ok(migration_path)
    } else if path.join("Cargo.toml").exists() {
        Err(MigrationError::MigrationDirectoryNotFound)
    } else {
        path.parent().map(search_for_migrations_directory)
            .unwrap_or(Err(MigrationError::MigrationDirectoryNotFound))
    }
}

#[cfg(test)]
mod tests {
    extern crate tempdir;

    use super::*;
    use super::find_migrations_directory;

    use self::tempdir::TempDir;
    use std::{env, fs};

    #[test]
    fn migration_directory_not_found_if_no_migration_dir_exists() {
        let dir = TempDir::new("diesel").unwrap();

        env::set_current_dir(dir.path()).unwrap();

        assert_eq!(Err(MigrationError::MigrationDirectoryNotFound),
            find_migrations_directory());
    }

    #[test]
    fn migration_directory_defaults_to_pwd_slash_migrations() {
        let dir = TempDir::new("diesel").unwrap();
        let temp_path = dir.path().canonicalize().unwrap();
        let migrations_path = temp_path.join("migrations");

        env::set_current_dir(temp_path).unwrap();
        fs::create_dir(&migrations_path).unwrap();

        assert_eq!(Ok(migrations_path), find_migrations_directory());
    }

    #[test]
    fn migration_directory_checks_parents() {
        let dir = TempDir::new("diesel").unwrap();
        let temp_path = dir.path().canonicalize().unwrap();
        let migrations_path = temp_path.join("migrations");
        let child_path = temp_path.join("child");

        fs::create_dir(&child_path).unwrap();
        fs::create_dir(&migrations_path).unwrap();
        env::set_current_dir(child_path).unwrap();

        assert_eq!(Ok(migrations_path), find_migrations_directory());
    }

    #[test]
    fn migration_directory_stops_at_cargo_toml() {
        let dir = TempDir::new("diesel").unwrap();
        let temp_path = dir.path();
        let migrations_path = temp_path.join("migrations");
        let child_path = temp_path.join("child");
        let grandchild_path = child_path.join("grandchild");

        fs::create_dir_all(&grandchild_path).unwrap();
        fs::create_dir(&migrations_path).unwrap();
        fs::File::create(child_path.join("Cargo.toml")).unwrap();
        env::set_current_dir(grandchild_path).unwrap();

        assert_eq!(Err(MigrationError::MigrationDirectoryNotFound),
            find_migrations_directory());
    }
}
<|endoftext|>


<commit_before>use byteorder::{ReadBytesExt, WriteBytesExt, NetworkEndian};
use std::error::Error;
use std::fmt;
use std::io::Write;

use pg::{Pg, PgTypeMetadata, PgMetadataLookup};
use query_source::Queryable;
use types::*;

impl<T> HasSqlType<Array<T>> for Pg where
    Pg: HasSqlType<T>,
{
    fn metadata(lookup: &PgMetadataLookup) -> PgTypeMetadata {
        PgTypeMetadata {
            oid: <Pg as HasSqlType<T>>::metadata(lookup).array_oid,
            array_oid: 0,
        }
    }
}

impl_query_id!(Array<T>);

impl<T> NotNull for Array<T> {
}

impl<T> SingleValue for Array<T> {
}

impl<T, ST> FromSql<Array<ST>, Pg> for Vec<T> where
    T: FromSql<ST, Pg>,
    Pg: HasSqlType<ST>,
{
    fn from_sql(bytes: Option<&[u8]>) -> Result<Self, Box<Error+Send+Sync>> {
        let mut bytes = not_none!(bytes);
        let num_dimensions = try!(bytes.read_i32::<NetworkEndian>());
        let has_null = try!(bytes.read_i32::<NetworkEndian>()) != 0;
        let _oid = try!(bytes.read_i32::<NetworkEndian>());

        if num_dimensions == 0 {
            return Ok(Vec::new())
        }

        let num_elements = try!(bytes.read_i32::<NetworkEndian>());
        let lower_bound = try!(bytes.read_i32::<NetworkEndian>());

        assert_eq!(num_dimensions, 1, "multi-dimensional arrays are not supported");
        assert_eq!(lower_bound, 1, "lower bound must be 1");

        (0..num_elements).map(|_| {
            let elem_size = try!(bytes.read_i32::<NetworkEndian>());
            if has_null && elem_size == -1 {
                T::from_sql(None)
            } else {
                let (elem_bytes, new_bytes) = bytes.split_at(elem_size as usize);
                bytes = new_bytes;
                T::from_sql(Some(elem_bytes))
            }
        }).collect()
    }
}

impl<T, ST> FromSqlRow<Array<ST>, Pg> for Vec<T> where
    Pg: HasSqlType<ST>,
    Vec<T>: FromSql<Array<ST>, Pg>,
{
    fn build_from_row<R: ::row::Row<Pg>>(row: &mut R) -> Result<Self, Box<Error+Send+Sync>> {
        FromSql::<Array<ST>, Pg>::from_sql(row.take())
    }
}

impl<T, ST> Queryable<Array<ST>, Pg> for Vec<T> where
    T: FromSql<ST, Pg> + Queryable<ST, Pg>,
    Pg: HasSqlType<ST>,
{
    type Row = Self;
    fn build(row: Self) -> Self {
        row
    }
}

use expression::AsExpression;
use expression::bound::Bound;

macro_rules! array_as_expression {
    ($ty:ty, $sql_type:ty) => {
        impl<'a, 'b, ST, T> AsExpression<$sql_type> for $ty where
            Pg: HasSqlType<ST>,
        {
            type Expression = Bound<$sql_type, Self>;

            fn as_expression(self) -> Self::Expression {
                Bound::new(self)
            }
        }
    }
}

array_as_expression!(&'a [T], Array<ST>);
array_as_expression!(&'a [T], Nullable<Array<ST>>);
array_as_expression!(&'a &'b [T], Array<ST>);
array_as_expression!(&'a &'b [T], Nullable<Array<ST>>);
array_as_expression!(Vec<T>, Array<ST>);
array_as_expression!(Vec<T>, Nullable<Array<ST>>);
array_as_expression!(&'a Vec<T>, Array<ST>);
array_as_expression!(&'a Vec<T>, Nullable<Array<ST>>);

impl<'a, ST, T> ToSql<Array<ST>, Pg> for &'a [T] where
    Pg: HasSqlType<ST>,
    T: ToSql<ST, Pg>,
{
    fn to_sql<W: Write>(&self, out: &mut ToSqlOutput<W, Pg>) -> Result<IsNull, Box<Error+Send+Sync>> {
        let num_dimensions = 1;
        try!(out.write_i32::<NetworkEndian>(num_dimensions));
        let flags = 0;
        try!(out.write_i32::<NetworkEndian>(flags));
        let element_oid = Pg::metadata(out.metadata_lookup()).oid;
        try!(out.write_u32::<NetworkEndian>(element_oid));
        try!(out.write_i32::<NetworkEndian>(self.len() as i32));
        let lower_bound = 1;
        try!(out.write_i32::<NetworkEndian>(lower_bound));

        let mut buffer = out.with_buffer(Vec::new());
        for elem in self.iter() {
            let is_null = try!(elem.to_sql(&mut buffer));
            if let IsNull::No = is_null {
                try!(out.write_i32::<NetworkEndian>(buffer.len() as i32));
                try!(out.write_all(&buffer));
                buffer.clear();
            } else {
                // https://github.com/postgres/postgres/blob/82f8107b92c9104ec9d9465f3f6a4c6dab4c124a/src/backend/utils/adt/arrayfuncs.c#L1461
                try!(out.write_i32::<NetworkEndian>(-1));
            }
        }

        Ok(IsNull::No)
    }
}

impl<'a, ST, T> ToSql<Nullable<Array<ST>>, Pg> for &'a [T] where
    Pg: HasSqlType<ST>,
    &'a [T]: ToSql<Array<ST>, Pg>,
{
    fn to_sql<W: Write>(&self, out: &mut ToSqlOutput<W, Pg>) -> Result<IsNull, Box<Error+Send+Sync>> {
        ToSql::<Array<ST>, Pg>::to_sql(self, out)
    }
}

impl<ST, T> ToSql<Array<ST>, Pg> for Vec<T> where
    Pg: HasSqlType<ST>,
    for<'a> &'a [T]: ToSql<Array<ST>, Pg>,
    T: fmt::Debug,
{
    fn to_sql<W: Write>(&self, out: &mut ToSqlOutput<W, Pg>) -> Result<IsNull, Box<Error+Send+Sync>> {
        (self as &[T]).to_sql(out)
    }
}

impl<ST, T> ToSql<Nullable<Array<ST>>, Pg> for Vec<T> where
    Pg: HasSqlType<ST>,
    Vec<T>: ToSql<Array<ST>, Pg>,
{
    fn to_sql<W: Write>(&self, out: &mut ToSqlOutput<W, Pg>) -> Result<IsNull, Box<Error+Send+Sync>> {
        ToSql::<Array<ST>, Pg>::to_sql(self, out)
    }
}
<commit_msg>Don't panic on unsupported arrays<commit_after>use byteorder::{ReadBytesExt, WriteBytesExt, NetworkEndian};
use std::error::Error;
use std::fmt;
use std::io::Write;

use pg::{Pg, PgTypeMetadata, PgMetadataLookup};
use query_source::Queryable;
use types::*;

impl<T> HasSqlType<Array<T>> for Pg where
    Pg: HasSqlType<T>,
{
    fn metadata(lookup: &PgMetadataLookup) -> PgTypeMetadata {
        PgTypeMetadata {
            oid: <Pg as HasSqlType<T>>::metadata(lookup).array_oid,
            array_oid: 0,
        }
    }
}

impl_query_id!(Array<T>);

impl<T> NotNull for Array<T> {
}

impl<T> SingleValue for Array<T> {
}

impl<T, ST> FromSql<Array<ST>, Pg> for Vec<T> where
    T: FromSql<ST, Pg>,
    Pg: HasSqlType<ST>,
{
    fn from_sql(bytes: Option<&[u8]>) -> Result<Self, Box<Error+Send+Sync>> {
        let mut bytes = not_none!(bytes);
        let num_dimensions = try!(bytes.read_i32::<NetworkEndian>());
        let has_null = try!(bytes.read_i32::<NetworkEndian>()) != 0;
        let _oid = try!(bytes.read_i32::<NetworkEndian>());

        if num_dimensions == 0 {
            return Ok(Vec::new())
        }

        let num_elements = try!(bytes.read_i32::<NetworkEndian>());
        let lower_bound = try!(bytes.read_i32::<NetworkEndian>());

        if num_dimensions != 1 {
            return Err("multi-dimensional arrays are not supported".into());
        }
        if lower_bound != 1 {
            return Err("lower bound must be 1".into())
        }

        (0..num_elements).map(|_| {
            let elem_size = try!(bytes.read_i32::<NetworkEndian>());
            if has_null && elem_size == -1 {
                T::from_sql(None)
            } else {
                let (elem_bytes, new_bytes) = bytes.split_at(elem_size as usize);
                bytes = new_bytes;
                T::from_sql(Some(elem_bytes))
            }
        }).collect()
    }
}

impl<T, ST> FromSqlRow<Array<ST>, Pg> for Vec<T> where
    Pg: HasSqlType<ST>,
    Vec<T>: FromSql<Array<ST>, Pg>,
{
    fn build_from_row<R: ::row::Row<Pg>>(row: &mut R) -> Result<Self, Box<Error+Send+Sync>> {
        FromSql::<Array<ST>, Pg>::from_sql(row.take())
    }
}

impl<T, ST> Queryable<Array<ST>, Pg> for Vec<T> where
    T: FromSql<ST, Pg> + Queryable<ST, Pg>,
    Pg: HasSqlType<ST>,
{
    type Row = Self;
    fn build(row: Self) -> Self {
        row
    }
}

use expression::AsExpression;
use expression::bound::Bound;

macro_rules! array_as_expression {
    ($ty:ty, $sql_type:ty) => {
        impl<'a, 'b, ST, T> AsExpression<$sql_type> for $ty where
            Pg: HasSqlType<ST>,
        {
            type Expression = Bound<$sql_type, Self>;

            fn as_expression(self) -> Self::Expression {
                Bound::new(self)
            }
        }
    }
}

array_as_expression!(&'a [T], Array<ST>);
array_as_expression!(&'a [T], Nullable<Array<ST>>);
array_as_expression!(&'a &'b [T], Array<ST>);
array_as_expression!(&'a &'b [T], Nullable<Array<ST>>);
array_as_expression!(Vec<T>, Array<ST>);
array_as_expression!(Vec<T>, Nullable<Array<ST>>);
array_as_expression!(&'a Vec<T>, Array<ST>);
array_as_expression!(&'a Vec<T>, Nullable<Array<ST>>);

impl<'a, ST, T> ToSql<Array<ST>, Pg> for &'a [T] where
    Pg: HasSqlType<ST>,
    T: ToSql<ST, Pg>,
{
    fn to_sql<W: Write>(&self, out: &mut ToSqlOutput<W, Pg>) -> Result<IsNull, Box<Error+Send+Sync>> {
        let num_dimensions = 1;
        try!(out.write_i32::<NetworkEndian>(num_dimensions));
        let flags = 0;
        try!(out.write_i32::<NetworkEndian>(flags));
        let element_oid = Pg::metadata(out.metadata_lookup()).oid;
        try!(out.write_u32::<NetworkEndian>(element_oid));
        try!(out.write_i32::<NetworkEndian>(self.len() as i32));
        let lower_bound = 1;
        try!(out.write_i32::<NetworkEndian>(lower_bound));

        let mut buffer = out.with_buffer(Vec::new());
        for elem in self.iter() {
            let is_null = try!(elem.to_sql(&mut buffer));
            if let IsNull::No = is_null {
                try!(out.write_i32::<NetworkEndian>(buffer.len() as i32));
                try!(out.write_all(&buffer));
                buffer.clear();
            } else {
                // https://github.com/postgres/postgres/blob/82f8107b92c9104ec9d9465f3f6a4c6dab4c124a/src/backend/utils/adt/arrayfuncs.c#L1461
                try!(out.write_i32::<NetworkEndian>(-1));
            }
        }

        Ok(IsNull::No)
    }
}

impl<'a, ST, T> ToSql<Nullable<Array<ST>>, Pg> for &'a [T] where
    Pg: HasSqlType<ST>,
    &'a [T]: ToSql<Array<ST>, Pg>,
{
    fn to_sql<W: Write>(&self, out: &mut ToSqlOutput<W, Pg>) -> Result<IsNull, Box<Error+Send+Sync>> {
        ToSql::<Array<ST>, Pg>::to_sql(self, out)
    }
}

impl<ST, T> ToSql<Array<ST>, Pg> for Vec<T> where
    Pg: HasSqlType<ST>,
    for<'a> &'a [T]: ToSql<Array<ST>, Pg>,
    T: fmt::Debug,
{
    fn to_sql<W: Write>(&self, out: &mut ToSqlOutput<W, Pg>) -> Result<IsNull, Box<Error+Send+Sync>> {
        (self as &[T]).to_sql(out)
    }
}

impl<ST, T> ToSql<Nullable<Array<ST>>, Pg> for Vec<T> where
    Pg: HasSqlType<ST>,
    Vec<T>: ToSql<Array<ST>, Pg>,
{
    fn to_sql<W: Write>(&self, out: &mut ToSqlOutput<W, Pg>) -> Result<IsNull, Box<Error+Send+Sync>> {
        ToSql::<Array<ST>, Pg>::to_sql(self, out)
    }
}
<|endoftext|>


<commit_before>extern crate glib_sys;
extern crate glib;
extern crate cairo;
extern crate cairo_sys;
extern crate libc;

use self::glib::translate::*;

use color::*;
use error::*;
use opacity::*;
use node::RsvgNode;
use node::NodeType;
use path_builder::RsvgPathBuilder;
use state::RsvgState;

pub enum RsvgDrawingCtx {}

extern "C" {
    fn rsvg_drawing_ctx_get_dpi (draw_ctx: *const RsvgDrawingCtx,
                                 out_dpi_x: *mut f64,
                                 out_dpi_y: *mut f64);

    fn rsvg_drawing_ctx_get_normalized_font_size (draw_ctx: *const RsvgDrawingCtx) -> f64;

    fn rsvg_drawing_ctx_get_view_box_size (draw_ctx: *const RsvgDrawingCtx,
                                           out_x: *mut f64,
                                           out_y: *mut f64);

    fn rsvg_drawing_ctx_push_view_box (draw_ctx: *const RsvgDrawingCtx,
                                       width:     f64,
                                       height:    f64);

    fn rsvg_drawing_ctx_pop_view_box (draw_ctx: *const RsvgDrawingCtx);

    fn rsvg_drawing_ctx_acquire_node (draw_ctx: *const RsvgDrawingCtx,
                                      url:      *const libc::c_char) -> *mut RsvgNode;

    fn rsvg_drawing_ctx_acquire_node_of_type (draw_ctx:  *const RsvgDrawingCtx,
                                              url:       *const libc::c_char,
                                              node_type: NodeType) -> *mut RsvgNode;

    fn rsvg_drawing_ctx_release_node (draw_ctx: *const RsvgDrawingCtx,
                                      node:     *mut RsvgNode);

    fn rsvg_drawing_ctx_get_current_state_affine (draw_ctx: *const RsvgDrawingCtx) -> cairo::Matrix;

    fn rsvg_drawing_ctx_set_current_state_affine (draw_ctx: *const RsvgDrawingCtx,
                                                  affine:   *const cairo::Matrix);

    fn rsvg_drawing_ctx_add_clipping_rect (draw_ctx: *const RsvgDrawingCtx,
                                           x: f64,
                                           y: f64,
                                           w: f64,
                                           h: f64);

    fn rsvg_drawing_ctx_draw_node_from_stack (draw_ctx: *const RsvgDrawingCtx,
                                              node:     *const RsvgNode,
                                              dominate: i32);

    fn rsvg_current_state (draw_ctx: *const RsvgDrawingCtx) -> *mut RsvgState;
    fn rsvg_state_new () -> *mut RsvgState;
    fn rsvg_state_reinit (state: *mut RsvgState);
    fn rsvg_state_reconstruct (state: *mut RsvgState, node: *const RsvgNode);
    fn rsvg_state_is_overflow (state: *const RsvgState) -> glib_sys::gboolean;
    fn rsvg_state_has_overflow (state: *const RsvgState) -> glib_sys::gboolean;
    fn rsvg_state_get_cond_true (state: *const RsvgState) -> glib_sys::gboolean;
    fn rsvg_state_get_stop_color (state: *const RsvgState) -> *const ColorSpec;
    fn rsvg_state_get_current_color (state: *const RsvgState) -> u32;

    fn rsvg_state_push (draw_ctx: *const RsvgDrawingCtx);
    fn rsvg_state_pop (draw_ctx: *const RsvgDrawingCtx);

    fn rsvg_state_reinherit_top (draw_ctx: *const RsvgDrawingCtx,
                                 state: *mut RsvgState,
                                 dominate: libc::c_int);

    fn rsvg_push_discrete_layer (draw_ctx: *const RsvgDrawingCtx);
    fn rsvg_pop_discrete_layer (draw_ctx: *const RsvgDrawingCtx);

    fn rsvg_render_path_builder (draw_ctx: *const RsvgDrawingCtx,
                                 builder: *const RsvgPathBuilder);

    fn rsvg_cairo_get_cairo_context (draw_ctx: *const RsvgDrawingCtx) -> *mut cairo_sys::cairo_t;
    fn rsvg_cairo_set_cairo_context (draw_ctx: *const RsvgDrawingCtx, cr: *const cairo_sys::cairo_t);
}

pub fn get_dpi (draw_ctx: *const RsvgDrawingCtx) -> (f64, f64) {
    let mut dpi_x: f64 = 0.0;
    let mut dpi_y: f64 = 0.0;

    unsafe { rsvg_drawing_ctx_get_dpi (draw_ctx, &mut dpi_x, &mut dpi_y); }

    (dpi_x, dpi_y)
}

pub fn get_normalized_font_size (draw_ctx: *const RsvgDrawingCtx) -> f64 {
    unsafe { rsvg_drawing_ctx_get_normalized_font_size (draw_ctx) }
}

pub fn get_view_box_size (draw_ctx: *const RsvgDrawingCtx) -> (f64, f64) {
    let mut w: f64 = 0.0;
    let mut h: f64 = 0.0;

    unsafe { rsvg_drawing_ctx_get_view_box_size (draw_ctx, &mut w, &mut h); }

    (w, h)
}

pub fn push_view_box (draw_ctx: *const RsvgDrawingCtx,
                      width:     f64,
                      height:    f64)
{
    unsafe { rsvg_drawing_ctx_push_view_box (draw_ctx, width, height); }
}

pub fn pop_view_box (draw_ctx: *const RsvgDrawingCtx) {
    unsafe { rsvg_drawing_ctx_pop_view_box (draw_ctx); }
}

pub fn acquire_node (draw_ctx: *const RsvgDrawingCtx,
                     url:      &str) -> *mut RsvgNode {
    unsafe { rsvg_drawing_ctx_acquire_node (draw_ctx, str::to_glib_none (url).0) }
}

pub fn acquire_node_of_type (draw_ctx:  *const RsvgDrawingCtx,
                             url:       &str,
                             node_type: NodeType) -> *mut RsvgNode {
    unsafe { rsvg_drawing_ctx_acquire_node_of_type (draw_ctx, str::to_glib_none (url).0, node_type) }
}

pub fn release_node (draw_ctx: *const RsvgDrawingCtx,
                     node:     *mut RsvgNode) {
    unsafe { rsvg_drawing_ctx_release_node (draw_ctx, node); }
}

pub fn state_reinherit_top (draw_ctx: *const RsvgDrawingCtx,
                            state: *mut RsvgState,
                            dominate: i32) {
    unsafe { rsvg_state_reinherit_top (draw_ctx, state, dominate); }
}

pub fn push_discrete_layer (draw_ctx: *const RsvgDrawingCtx) {
    unsafe { rsvg_push_discrete_layer (draw_ctx); }
}

pub fn pop_discrete_layer (draw_ctx: *const RsvgDrawingCtx) {
    unsafe { rsvg_pop_discrete_layer (draw_ctx); }
}

pub fn render_path_builder (draw_ctx: *const RsvgDrawingCtx,
                            builder: &RsvgPathBuilder) {
    unsafe { rsvg_render_path_builder (draw_ctx, builder); }
}

pub fn get_cairo_context (draw_ctx: *const RsvgDrawingCtx) -> cairo::Context {
    unsafe {
        let raw_cr = rsvg_cairo_get_cairo_context (draw_ctx);

        let cr = cairo::Context::from_glib_none (raw_cr);

        cr
    }
}

pub fn set_cairo_context (draw_ctx: *const RsvgDrawingCtx, cr: &cairo::Context) {
    unsafe {
        let raw_cr = cr.to_glib_none ().0;

        rsvg_cairo_set_cairo_context (draw_ctx, raw_cr);
    }
}

pub fn get_current_state_affine (draw_ctx: *const RsvgDrawingCtx) -> cairo::Matrix {
    unsafe {
        rsvg_drawing_ctx_get_current_state_affine (draw_ctx)
    }
}

pub fn set_current_state_affine (draw_ctx: *const RsvgDrawingCtx, affine: cairo::Matrix) {
    unsafe {
        rsvg_drawing_ctx_set_current_state_affine (draw_ctx, &affine);
    }
}

pub fn add_clipping_rect (draw_ctx: *const RsvgDrawingCtx,
                          x: f64,
                          y: f64,
                          w: f64,
                          h: f64) {
    unsafe { rsvg_drawing_ctx_add_clipping_rect (draw_ctx, x, y, w, h); }
}

pub fn draw_node_from_stack (draw_ctx: *const RsvgDrawingCtx,
                             node:     *const RsvgNode,
                             dominate: i32) {
    unsafe { rsvg_drawing_ctx_draw_node_from_stack (draw_ctx, node, dominate); }
}

pub fn get_current_state (draw_ctx: *const RsvgDrawingCtx) -> *mut RsvgState {
    unsafe { rsvg_current_state (draw_ctx) }
}

pub fn state_new () -> *mut RsvgState {
    unsafe { rsvg_state_new () }
}

pub fn state_reinit (state: *mut RsvgState) {
    unsafe { rsvg_state_reinit (state); }
}

pub fn state_reconstruct (state: *mut RsvgState, node: *const RsvgNode) {
    unsafe { rsvg_state_reconstruct (state, node); }
}

pub fn state_is_overflow (state: *const RsvgState) -> bool {
    unsafe { from_glib (rsvg_state_is_overflow (state)) }
}

pub fn state_has_overflow (state: *const RsvgState) -> bool {
    unsafe { from_glib (rsvg_state_has_overflow (state)) }
}

pub fn state_get_cond_true (state: *const RsvgState) -> bool {
    unsafe { from_glib (rsvg_state_get_cond_true (state)) }
}

pub fn state_push (draw_ctx: *const RsvgDrawingCtx) {
    unsafe {
        rsvg_state_push (draw_ctx);
    }
}

pub fn state_pop (draw_ctx: *const RsvgDrawingCtx) {
    unsafe {
        rsvg_state_pop (draw_ctx);
    }
}

pub fn state_get_stop_color (state: *const RsvgState) -> Result<Option<Color>, AttributeError> {
    unsafe {
        let spec_ptr = rsvg_state_get_stop_color (state);

        if spec_ptr.is_null () {
            Ok (None)
        } else {
            Color::from_color_spec (&*spec_ptr).map (|color| Some (color))
        }
    }
}

pub fn state_get_current_color (state: *const RsvgState) -> u32 {
    unsafe {
        rsvg_state_get_current_color (state)
    }
}
<commit_msg>drawing_ctx::state_get_stop_opacity() - Analogous to ::state_get_stop_color()<commit_after>extern crate glib_sys;
extern crate glib;
extern crate cairo;
extern crate cairo_sys;
extern crate libc;

use self::glib::translate::*;

use color::*;
use error::*;
use opacity::*;
use node::RsvgNode;
use node::NodeType;
use path_builder::RsvgPathBuilder;
use state::RsvgState;

pub enum RsvgDrawingCtx {}

extern "C" {
    fn rsvg_drawing_ctx_get_dpi (draw_ctx: *const RsvgDrawingCtx,
                                 out_dpi_x: *mut f64,
                                 out_dpi_y: *mut f64);

    fn rsvg_drawing_ctx_get_normalized_font_size (draw_ctx: *const RsvgDrawingCtx) -> f64;

    fn rsvg_drawing_ctx_get_view_box_size (draw_ctx: *const RsvgDrawingCtx,
                                           out_x: *mut f64,
                                           out_y: *mut f64);

    fn rsvg_drawing_ctx_push_view_box (draw_ctx: *const RsvgDrawingCtx,
                                       width:     f64,
                                       height:    f64);

    fn rsvg_drawing_ctx_pop_view_box (draw_ctx: *const RsvgDrawingCtx);

    fn rsvg_drawing_ctx_acquire_node (draw_ctx: *const RsvgDrawingCtx,
                                      url:      *const libc::c_char) -> *mut RsvgNode;

    fn rsvg_drawing_ctx_acquire_node_of_type (draw_ctx:  *const RsvgDrawingCtx,
                                              url:       *const libc::c_char,
                                              node_type: NodeType) -> *mut RsvgNode;

    fn rsvg_drawing_ctx_release_node (draw_ctx: *const RsvgDrawingCtx,
                                      node:     *mut RsvgNode);

    fn rsvg_drawing_ctx_get_current_state_affine (draw_ctx: *const RsvgDrawingCtx) -> cairo::Matrix;

    fn rsvg_drawing_ctx_set_current_state_affine (draw_ctx: *const RsvgDrawingCtx,
                                                  affine:   *const cairo::Matrix);

    fn rsvg_drawing_ctx_add_clipping_rect (draw_ctx: *const RsvgDrawingCtx,
                                           x: f64,
                                           y: f64,
                                           w: f64,
                                           h: f64);

    fn rsvg_drawing_ctx_draw_node_from_stack (draw_ctx: *const RsvgDrawingCtx,
                                              node:     *const RsvgNode,
                                              dominate: i32);

    fn rsvg_current_state (draw_ctx: *const RsvgDrawingCtx) -> *mut RsvgState;
    fn rsvg_state_new () -> *mut RsvgState;
    fn rsvg_state_reinit (state: *mut RsvgState);
    fn rsvg_state_reconstruct (state: *mut RsvgState, node: *const RsvgNode);
    fn rsvg_state_is_overflow (state: *const RsvgState) -> glib_sys::gboolean;
    fn rsvg_state_has_overflow (state: *const RsvgState) -> glib_sys::gboolean;
    fn rsvg_state_get_cond_true (state: *const RsvgState) -> glib_sys::gboolean;
    fn rsvg_state_get_stop_color (state: *const RsvgState) -> *const ColorSpec;
    fn rsvg_state_get_stop_opacity (state: *const RsvgState) -> *const OpacitySpec;
    fn rsvg_state_get_current_color (state: *const RsvgState) -> u32;

    fn rsvg_state_push (draw_ctx: *const RsvgDrawingCtx);
    fn rsvg_state_pop (draw_ctx: *const RsvgDrawingCtx);

    fn rsvg_state_reinherit_top (draw_ctx: *const RsvgDrawingCtx,
                                 state: *mut RsvgState,
                                 dominate: libc::c_int);

    fn rsvg_push_discrete_layer (draw_ctx: *const RsvgDrawingCtx);
    fn rsvg_pop_discrete_layer (draw_ctx: *const RsvgDrawingCtx);

    fn rsvg_render_path_builder (draw_ctx: *const RsvgDrawingCtx,
                                 builder: *const RsvgPathBuilder);

    fn rsvg_cairo_get_cairo_context (draw_ctx: *const RsvgDrawingCtx) -> *mut cairo_sys::cairo_t;
    fn rsvg_cairo_set_cairo_context (draw_ctx: *const RsvgDrawingCtx, cr: *const cairo_sys::cairo_t);
}

pub fn get_dpi (draw_ctx: *const RsvgDrawingCtx) -> (f64, f64) {
    let mut dpi_x: f64 = 0.0;
    let mut dpi_y: f64 = 0.0;

    unsafe { rsvg_drawing_ctx_get_dpi (draw_ctx, &mut dpi_x, &mut dpi_y); }

    (dpi_x, dpi_y)
}

pub fn get_normalized_font_size (draw_ctx: *const RsvgDrawingCtx) -> f64 {
    unsafe { rsvg_drawing_ctx_get_normalized_font_size (draw_ctx) }
}

pub fn get_view_box_size (draw_ctx: *const RsvgDrawingCtx) -> (f64, f64) {
    let mut w: f64 = 0.0;
    let mut h: f64 = 0.0;

    unsafe { rsvg_drawing_ctx_get_view_box_size (draw_ctx, &mut w, &mut h); }

    (w, h)
}

pub fn push_view_box (draw_ctx: *const RsvgDrawingCtx,
                      width:     f64,
                      height:    f64)
{
    unsafe { rsvg_drawing_ctx_push_view_box (draw_ctx, width, height); }
}

pub fn pop_view_box (draw_ctx: *const RsvgDrawingCtx) {
    unsafe { rsvg_drawing_ctx_pop_view_box (draw_ctx); }
}

pub fn acquire_node (draw_ctx: *const RsvgDrawingCtx,
                     url:      &str) -> *mut RsvgNode {
    unsafe { rsvg_drawing_ctx_acquire_node (draw_ctx, str::to_glib_none (url).0) }
}

pub fn acquire_node_of_type (draw_ctx:  *const RsvgDrawingCtx,
                             url:       &str,
                             node_type: NodeType) -> *mut RsvgNode {
    unsafe { rsvg_drawing_ctx_acquire_node_of_type (draw_ctx, str::to_glib_none (url).0, node_type) }
}

pub fn release_node (draw_ctx: *const RsvgDrawingCtx,
                     node:     *mut RsvgNode) {
    unsafe { rsvg_drawing_ctx_release_node (draw_ctx, node); }
}

pub fn state_reinherit_top (draw_ctx: *const RsvgDrawingCtx,
                            state: *mut RsvgState,
                            dominate: i32) {
    unsafe { rsvg_state_reinherit_top (draw_ctx, state, dominate); }
}

pub fn push_discrete_layer (draw_ctx: *const RsvgDrawingCtx) {
    unsafe { rsvg_push_discrete_layer (draw_ctx); }
}

pub fn pop_discrete_layer (draw_ctx: *const RsvgDrawingCtx) {
    unsafe { rsvg_pop_discrete_layer (draw_ctx); }
}

pub fn render_path_builder (draw_ctx: *const RsvgDrawingCtx,
                            builder: &RsvgPathBuilder) {
    unsafe { rsvg_render_path_builder (draw_ctx, builder); }
}

pub fn get_cairo_context (draw_ctx: *const RsvgDrawingCtx) -> cairo::Context {
    unsafe {
        let raw_cr = rsvg_cairo_get_cairo_context (draw_ctx);

        let cr = cairo::Context::from_glib_none (raw_cr);

        cr
    }
}

pub fn set_cairo_context (draw_ctx: *const RsvgDrawingCtx, cr: &cairo::Context) {
    unsafe {
        let raw_cr = cr.to_glib_none ().0;

        rsvg_cairo_set_cairo_context (draw_ctx, raw_cr);
    }
}

pub fn get_current_state_affine (draw_ctx: *const RsvgDrawingCtx) -> cairo::Matrix {
    unsafe {
        rsvg_drawing_ctx_get_current_state_affine (draw_ctx)
    }
}

pub fn set_current_state_affine (draw_ctx: *const RsvgDrawingCtx, affine: cairo::Matrix) {
    unsafe {
        rsvg_drawing_ctx_set_current_state_affine (draw_ctx, &affine);
    }
}

pub fn add_clipping_rect (draw_ctx: *const RsvgDrawingCtx,
                          x: f64,
                          y: f64,
                          w: f64,
                          h: f64) {
    unsafe { rsvg_drawing_ctx_add_clipping_rect (draw_ctx, x, y, w, h); }
}

pub fn draw_node_from_stack (draw_ctx: *const RsvgDrawingCtx,
                             node:     *const RsvgNode,
                             dominate: i32) {
    unsafe { rsvg_drawing_ctx_draw_node_from_stack (draw_ctx, node, dominate); }
}

pub fn get_current_state (draw_ctx: *const RsvgDrawingCtx) -> *mut RsvgState {
    unsafe { rsvg_current_state (draw_ctx) }
}

pub fn state_new () -> *mut RsvgState {
    unsafe { rsvg_state_new () }
}

pub fn state_reinit (state: *mut RsvgState) {
    unsafe { rsvg_state_reinit (state); }
}

pub fn state_reconstruct (state: *mut RsvgState, node: *const RsvgNode) {
    unsafe { rsvg_state_reconstruct (state, node); }
}

pub fn state_is_overflow (state: *const RsvgState) -> bool {
    unsafe { from_glib (rsvg_state_is_overflow (state)) }
}

pub fn state_has_overflow (state: *const RsvgState) -> bool {
    unsafe { from_glib (rsvg_state_has_overflow (state)) }
}

pub fn state_get_cond_true (state: *const RsvgState) -> bool {
    unsafe { from_glib (rsvg_state_get_cond_true (state)) }
}

pub fn state_push (draw_ctx: *const RsvgDrawingCtx) {
    unsafe {
        rsvg_state_push (draw_ctx);
    }
}

pub fn state_pop (draw_ctx: *const RsvgDrawingCtx) {
    unsafe {
        rsvg_state_pop (draw_ctx);
    }
}

pub fn state_get_stop_color (state: *const RsvgState) -> Result<Option<Color>, AttributeError> {
    unsafe {
        let spec_ptr = rsvg_state_get_stop_color (state);

        if spec_ptr.is_null () {
            Ok (None)
        } else {
            Color::from_color_spec (&*spec_ptr).map (|color| Some (color))
        }
    }
}

pub fn state_get_stop_opacity (state: *const RsvgState) -> Result<Option<Opacity>, AttributeError> {
    unsafe {
        let opacity_ptr = rsvg_state_get_stop_opacity (state);

        if opacity_ptr.is_null () {
            Ok (None)
        } else {
            Opacity::from_opacity_spec (&*opacity_ptr).map (|opacity| Some (opacity))
        }
    }
}

pub fn state_get_current_color (state: *const RsvgState) -> u32 {
    unsafe {
        rsvg_state_get_current_color (state)
    }
}
<|endoftext|>


<commit_before>//!Bindings and rewrites of include/linux/time.h and include/linux/time64.h

extern crate linux_api;

use linux_api::*;

///Checks to see if two timespecs are equal
pub fn timespec_equal(a: &timespec, b: &timespec) -> c_int {
    return ((a.tv_sec == b.tv_sec) && (a.tv_nsec == b.tv_nsec)) as c_int;
}

///Compares two timespecs
///
///If lhs < rhs, return < 0
///If lhs == rhs, return 0
///If lhs > rhs, return > 0
pub fn timespec_compare(lhs: &timespec, rhs: &timespec) -> c_int {
    if lhs.tv_sec < rhs.tv_sec { return -1; }
    if lhs.tv_sec > rhs.tv_sec { return 1; }
    return (lhs.tv_nsec - rhs.tv_nsec) as c_int;
}

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

    #[test]
    fn test_timespec_equal_when_equal() {
        let one: timespec = timespec { tv_sec: 77, tv_nsec: 77 };
        let two: timespec = timespec { tv_sec: 77, tv_nsec: 77 };

        assert_eq!(1, timespec_equal(&one, &two));
    }

    #[test]
    fn test_timespec_equal_when_inequal() {
        let one: timespec = timespec { tv_sec: 0, tv_nsec: 266 };
        let two: timespec = timespec { tv_sec: 4, tv_nsec: 0 };

        assert_eq!(0, timespec_equal(&one, &two));
    }

    #[test]
    fn test_timespec_compare_same() {
        let one = timespec { tv_sec: 10, tv_nsec: 0 };
        let two = timespec { tv_sec: 10, tv_nsec: 0 };

        assert_eq!(0, timespec_compare(&one, &two));
    }

    #[test]
    fn test_timespec_compare_larger() {
        let one = timespec { tv_sec: 11, tv_nsec: 0 };
        let two = timespec { tv_sec: 10, tv_nsec: 0 };

        assert_eq!(1, timespec_compare(&one, &two));
    }

    #[test]
    fn test_timespec_compare_smaller() {
        let one = timespec { tv_sec: 9, tv_nsec: 0 };
        let two = timespec { tv_sec: 10, tv_nsec: 0 };

        assert_eq!(-1, timespec_compare(&one, &two));
    }

}<commit_msg>Add some validity functions for timeval and timespec<commit_after>//!Bindings and rewrites of include/linux/time.h and include/linux/time64.h

extern crate linux_api;

use linux_api::*;

///Checks to see if two timespecs are equal
pub fn timespec_equal(a: &timespec, b: &timespec) -> c_int {
    return ((a.tv_sec == b.tv_sec) && (a.tv_nsec == b.tv_nsec)) as c_int;
}

///Compares two timespecs
///
///If lhs < rhs, return < 0
///If lhs == rhs, return 0
///If lhs > rhs, return > 0
pub fn timespec_compare(lhs: &timespec, rhs: &timespec) -> c_int {
    if lhs.tv_sec < rhs.tv_sec { return -1; }
    if lhs.tv_sec > rhs.tv_sec { return 1; }
    return (lhs.tv_nsec - rhs.tv_nsec) as c_int;
}

///Compares two timevals
///
///If lhs < rhs, return < 0
///If lhs == rhs, return 0
///If lhs > rhs, return > 0
pub fn timeval_compare(lhs: &timeval, rhs: &timeval) -> c_int {
    if lhs.tv_sec < rhs.tv_sec { return -1; }
    if lhs.tv_sec > rhs.tv_sec { return 1; }
    return (lhs.tv_usec - rhs.tv_usec) as c_int;
}

//TODO: mktime64
//TODO: mktime
//TODO: set_normalized_timespec

//TODO: timespec_add_safe, timespec_add, timespec_sub

pub fn timespec_valid(ts: &timespec) -> bool {
    //Dates before 1970 are bogus
    if ts.tv_sec < 0 {
        return false;
    }

    //Can't have more nanoseconds than a second
    if ts.tv_nsec >= NSEC_PER_SEC {
        return false;
    }

    //Okay, all looks good
    return true;
}

pub fn timespec_valid_strict(ts: &timespec) -> bool {
    if !timespec_valid(ts) {
        return false;
    }

    //Okay, we've validated it quickly
    //Disallow values that could overflow ktime_t
    if ts.tv_sec >= KTIME_SEC_MAX {
        return false;
    }

    return true;
}

pub fn timeval_valid(tv: &timeval) -> bool {
    //Dates before 1970 are bogus
    if tv.tv_sec < 0 {
        return false;
    }

    //Can't have more microseconds than a second
    if tv.tv_usec >= USEC_PER_SEC {
        return false;
    }

    //Okay, all looks good
    return true;
}

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

    #[test]
    fn test_timespec_valid() {
        let atime: timespec = timespec { tv_sec: 0, tv_nsec: 4262 };

        assert!(timespec_valid(&atime));
    }

    #[test]
    fn test_timespec_too_many_seconds_valid() {
        let atime: timespec = timespec { tv_sec: KTIME_SEC_MAX + 365, tv_nsec: 4262 };

        assert!(!timespec_valid_strict(&atime));
    }

    #[test]
    fn test_timespec_before_1970_invalid() {
        let atime: timespec = timespec { tv_sec: -63, tv_nsec: 4262 };

        assert!(!timespec_valid(&atime));
    }

    #[test]
    fn test_timespec_too_many_nanoseconds_invalid() {
        let atime: timespec = timespec { tv_sec: 0, tv_nsec: NSEC_PER_SEC + 2 };

        assert!(!timespec_valid(&atime));
    }

    #[test]
    fn test_timeval_valid() {
        let atime: timeval = timeval { tv_sec: 0, tv_usec: 4262 };

        assert!(timeval_valid(&atime));
    }

    #[test]
    fn test_timeval_before_1970_invalid() {
        let atime: timeval = timeval { tv_sec: -63, tv_usec: 4262 };

        assert!(!timeval_valid(&atime));
    }

    #[test]
    fn test_timeval_too_many_nanoseconds_invalid() {
        let atime: timeval = timeval { tv_sec: 0, tv_usec: USEC_PER_SEC + 2 };

        assert!(!timeval_valid(&atime));
    }

    #[test]
    fn test_timespec_equal_when_equal() {
        let one: timespec = timespec { tv_sec: 77, tv_nsec: 77 };
        let two: timespec = timespec { tv_sec: 77, tv_nsec: 77 };

        assert_eq!(1, timespec_equal(&one, &two));
    }

    #[test]
    fn test_timespec_equal_when_inequal() {
        let one: timespec = timespec { tv_sec: 0, tv_nsec: 266 };
        let two: timespec = timespec { tv_sec: 4, tv_nsec: 0 };

        assert_eq!(0, timespec_equal(&one, &two));
    }

    #[test]
    fn test_timespec_compare_same() {
        let one = timespec { tv_sec: 10, tv_nsec: 0 };
        let two = timespec { tv_sec: 10, tv_nsec: 0 };

        assert_eq!(0, timespec_compare(&one, &two));
    }

    #[test]
    fn test_timespec_compare_larger() {
        let one = timespec { tv_sec: 11, tv_nsec: 0 };
        let two = timespec { tv_sec: 10, tv_nsec: 0 };

        assert_eq!(1, timespec_compare(&one, &two));
    }

    #[test]
    fn test_timespec_compare_smaller() {
        let one = timespec { tv_sec: 9, tv_nsec: 0 };
        let two = timespec { tv_sec: 10, tv_nsec: 0 };

        assert_eq!(-1, timespec_compare(&one, &two));
    }

    #[test]
    fn test_timeval_compare_same() {
        let one = timeval { tv_sec: 10, tv_usec: 0 };
        let two = timeval { tv_sec: 10, tv_usec: 0 };

        assert_eq!(0, timeval_compare(&one, &two));
    }

    #[test]
    fn test_timeval_compare_larger() {
        let one = timeval { tv_sec: 11, tv_usec: 0 };
        let two = timeval { tv_sec: 10, tv_usec: 0 };

        assert_eq!(1, timeval_compare(&one, &two));
    }

    #[test]
    fn test_timeval_compare_smaller() {
        let one = timeval { tv_sec: 9, tv_usec: 0 };
        let two = timeval { tv_sec: 10, tv_usec: 0 };

        assert_eq!(-1, timeval_compare(&one, &two));
    }

}<|endoftext|>


<commit_before>extern crate websocat;

extern crate env_logger;
extern crate futures;
extern crate tokio_core;
extern crate tokio_timer;

use futures::future::Future;

use tokio_core::reactor::Core;
use websocat::{spec, Options, WebsocatConfiguration};

fn dflt() -> Options {
    Default::default()
}

macro_rules! wt {
    ($core:ident, $s1:expr, $s2:expr,noopts,delay = $ms:expr) => {
        wt!($core, $s1, $s2, opts = Default::default(), delay = $ms);
    };
    ($core:ident, $s1:expr, $s2:expr,noopts,nodelay) => {
        wt!($core, $s1, $s2, opts = Default::default(), nodelay);
    };
    ($core:ident, $s1:expr, $s2:expr,opts = $opts:expr,delay = $ms:expr) => {{
        let s1 = spec($s1).unwrap();
        let s2 = spec($s2).unwrap();
        let h2 = $core.handle();

        let websocat = WebsocatConfiguration {
            opts: $opts,
            s1,
            s2,
        };

        let t = tokio_timer::wheel().build();
        let delay = t
            .sleep(std::time::Duration::new(0, $ms * 1_000_000))
            .map_err(|_| ());

        delay.and_then(|()| wt!(wss, websocat, h2))
    }};
    ($core:ident, $s1:expr, $s2:expr,opts = $opts:expr,nodelay) => {{
        let s1 = spec($s1).unwrap();
        let s2 = spec($s2).unwrap();
        let h2 = $core.handle();

        let websocat = WebsocatConfiguration {
            opts: $opts,
            s1,
            s2,
        };

        wt!(wss, websocat, h2)
    }};
    (wss, $websocat:ident, $h2:ident) => {
        $websocat.serve(
            $h2,
            std::rc::Rc::new(|e| {
                eprintln!("{}", e);
                panic!();
            }),
        )
    };
}

macro_rules! prepare {
    ($core:ident) => {
        let _ = env_logger::try_init();
        let mut $core = Core::new().unwrap();
    };
}
macro_rules! run {
    ($core:ident, $prog:expr) => {
        $core.run($prog).map_err(|()| panic!()).unwrap();
    };
}

#[test]
fn trivial() {
    prepare!(core);
    let prog = wt!(core, "literal:qwerty", "assert:qwerty", noopts, nodelay);
    run!(core, prog);
}

#[test]
fn tcp() {
    prepare!(core);
    let prog1 = wt!(
        core,
        "literal:qwert2y",
        "tcp-l:127.0.0.1:45912",
        noopts,
        nodelay
    );
    let prog2 = wt!(
        core,
        "tcp:127.0.0.1:45912",
        "assert:qwert2y",
        noopts,
        delay = 200
    );

    let prog = prog1.join(prog2);
    run!(core, prog);
}

#[test]
fn ws() {
    prepare!(core);
    let prog1 = wt!(
        core,
        "literal:qwert3y",
        "ws-l:127.0.0.1:45913",
        noopts,
        nodelay
    );
    let prog2 = wt!(
        core,
        "ws://127.0.0.1:45913/ololo",
        "assert:qwert3y",
        noopts,
        delay = 200
    );

    let prog = prog1.join(prog2);
    run!(core, prog);
}

#[test]
fn ws_persist() {
    prepare!(core);
    let prog1 = wt!(
        core,
        "ws-l:127.0.0.1:45914",
        "literal:qwert4y",
        noopts,
        nodelay
    );
    let prog2 = wt!(
        core,
        "literal:invalid_connection_request",
        "tcp:127.0.0.1:45914",
        noopts,
        delay = 200
    );
    let prog3 = wt!(
        core,
        "ws://127.0.0.1:45914/ololo",
        "assert:qwert4y",
        noopts,
        delay = 400
    );

    core.handle().spawn(prog1);
    core.handle().spawn(prog2);
    let prog = prog3;
    run!(core, prog);
}

#[test]
#[cfg(unix)]
fn unix() {
    prepare!(core);
    let prog1 = wt!(
        core,
        "literal:qwert3y",
        "unix-l:zxc",
        opts = Options {
            unlink_unix_socket: true,
            ..dflt()
        },
        nodelay
    );
    let prog2 = wt!(core, "unix-c:zxc", "assert:qwert3y", noopts, delay = 200);

    let prog = prog1.join(prog2);
    run!(core, prog);
    let _ = ::std::fs::remove_file("zxc");
}

#[test]
#[cfg(any(target_os = "linux", target_os = "android"))]
fn abstract_() {
    prepare!(core);
    let prog1 = wt!(core, "literal:qwert4y", "abstract-l:zxc", noopts, nodelay);
    let prog2 = wt!(
        core,
        "abstract-c:zxc",
        "assert:qwert4y",
        noopts,
        delay = 200
    );

    let prog = prog1.join(prog2);
    run!(core, prog);
}
<commit_msg>Fix the test<commit_after>extern crate websocat;

extern crate env_logger;
extern crate futures;
extern crate tokio_core;
extern crate tokio_timer;

use futures::future::Future;

use tokio_core::reactor::Core;
use websocat::{spec, Options, WebsocatConfiguration};

fn dflt() -> Options {
    Default::default()
}

macro_rules! wt {
    ($core:ident, $s1:expr, $s2:expr,delay = $ms:expr, $($rest:tt)*) => {{
        let s1 = spec($s1).unwrap();
        let s2 = spec($s2).unwrap();
        let h2 = $core.handle();

        let t = tokio_timer::wheel().build();
        let delay = t
            .sleep(std::time::Duration::new(0, $ms * 1_000_000))
            .map_err(|_| ());

        delay.and_then(|()| wt!(stage2, h2, s1, s2, $($rest)*) )
    }};
    ($core:ident, $s1:expr, $s2:expr,nodelay,$($rest:tt)*) => {{
        let s1 = spec($s1).unwrap();
        let s2 = spec($s2).unwrap();
        let h2 = $core.handle();

        wt!(stage2, h2, s1, s2, $($rest)*)
    }};
    (stage2, $h2:ident, $s1:ident, $s2:ident, noopts,$($rest:tt)*) => {
        wt!(stage2, $h2, $s1, $s2, opts=Default::default(),$($rest)*)
    };
    (stage2, $h2:ident, $s1:ident, $s2:ident, opts=$opts:expr,$($rest:tt)*) => {{

        let websocat = WebsocatConfiguration {
            opts: $opts,
            $s1,
            $s2,
        };

        websocat.serve(
            $h2,
            wt!(stage3, $($rest)*),
        )
    }};
    (stage3, errpanic,) => {
        std::rc::Rc::new(|e| {
            eprintln!("{}", e);
            panic!();
        })
    };
    (stage3, errignore,) => {
        std::rc::Rc::new(|_| {

        })
    };
}

macro_rules! prepare {
    ($core:ident) => {
        let _ = env_logger::try_init();
        let mut $core = Core::new().unwrap();
    };
}
macro_rules! run {
    ($core:ident, $prog:expr) => {
        $core.run($prog).map_err(|()| panic!()).unwrap();
    };
}

#[test]
fn trivial() {
    prepare!(core);
    let prog = wt!(core,
        "literal:qwerty",
        "assert:qwerty",
        nodelay,
        noopts,
        errpanic,
    );
    run!(core, prog);
}

#[test]
fn tcp() {
    prepare!(core);
    let prog1 = wt!(
        core,
        "literal:qwert2y",
        "tcp-l:127.0.0.1:45912",
        nodelay,
        noopts,
        errpanic,
    );
    let prog2 = wt!(
        core,
        "tcp:127.0.0.1:45912",
        "assert:qwert2y",
        delay = 200,
        noopts,
        errpanic,
    );

    let prog = prog1.join(prog2);
    run!(core, prog);
}

#[test]
fn ws() {
    prepare!(core);
    let prog1 = wt!(
        core,
        "literal:qwert3y",
        "ws-l:127.0.0.1:45913",
        nodelay,
        noopts,
        errpanic,
    );
    let prog2 = wt!(
        core,
        "ws://127.0.0.1:45913/ololo",
        "assert:qwert3y",
        delay = 200,
        noopts,
        errpanic,
    );

    let prog = prog1.join(prog2);
    run!(core, prog);
}

#[test]
fn ws_persist() {
    prepare!(core);
    let prog1 = wt!(
        core,
        "ws-l:127.0.0.1:45914",
        "literal:qwert4y",
        nodelay,
        noopts,
        errignore,
    );
    let prog2 = wt!(
        core,
        "literal:invalid_connection_request",
        "tcp:127.0.0.1:45914",
        delay = 200,
        noopts,
        errpanic,
    );
    let prog3 = wt!(
        core,
        "ws://127.0.0.1:45914/ololo",
        "assert:qwert4y",
        delay = 400,
        noopts,
        errpanic,
    );

    core.handle().spawn(prog1);
    core.handle().spawn(prog2);
    let prog = prog3;
    run!(core, prog);
}

#[test]
#[cfg(unix)]
fn unix() {
    prepare!(core);
    let prog1 = wt!(
        core,
        "literal:qwert3y",
        "unix-l:zxc",
        nodelay,
        opts = Options {
            unlink_unix_socket: true,
            ..dflt()
        },
        errpanic,
    );
    let prog2 = wt!(core,
        "unix-c:zxc",
        "assert:qwert3y",
        delay = 200,
        noopts,
        errpanic,
    );

    let prog = prog1.join(prog2);
    run!(core, prog);
    let _ = ::std::fs::remove_file("zxc");
}

#[test]
#[cfg(any(target_os = "linux", target_os = "android"))]
fn abstract_() {
    prepare!(core);
    let prog1 = wt!(core,
        "literal:qwert4y",
        "abstract-l:zxc",
        nodelay,
        noopts,
        errpanic,
    );
    let prog2 = wt!(
        core,
        "abstract-c:zxc",
        "assert:qwert4y",
        delay = 200,
        noopts,
        errpanic,
    );

    let prog = prog1.join(prog2);
    run!(core, prog);
}

<|endoftext|>