<commit_before>// This file is part of Grust, GObject introspection bindings for Rust
//
// Copyright (C) 2014  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

use glib as ffi;
use gstr;
use quark::Quark;
use types::gint;

use std::default::Default;
use std::error::Error as ErrorTrait;
use std::fmt;
use std::mem;
use std::ptr;
use std::str;

pub mod raw {
    use glib as ffi;

    pub type GError = ffi::GError;
}

pub struct Error {
    ptr: *mut raw::GError
}

pub fn none() -> Error {
    Error { ptr: ptr::null_mut() }
}

#[derive(Show)]
pub enum Match<T> {
    NotInDomain,
    Known(T),
    Unknown(gint)
}

impl<T> PartialEq for Match<T> where T: PartialEq {
    fn eq(&self, other: &Match<T>) -> bool {
        match (self, other) {
            (&Match::Known(ref a), &Match::Known(ref b)) => *a == *b,
            (&Match::Unknown(a), &Match::Unknown(b)) => a == b,
            _ => false
        }
    }
}

unsafe impl Send for Error { }

impl Drop for Error {
    fn drop(&mut self) {
        if !self.ptr.is_null() {
            unsafe { ffi::g_error_free(self.ptr); }
        }
    }
}

impl Clone for Error {
    fn clone(&self) -> Error {
        if self.ptr.is_null() {
            none()
        } else {
            Error {
                ptr: unsafe {
                    ffi::g_error_copy(self.ptr as *const raw::GError)
                }
            }
        }
    }
}

impl Default for Error {
    #[inline]
    fn default() -> Error { none() }
}

impl Error {
    pub unsafe fn slot_ptr(&mut self) -> *mut *mut raw::GError {
        &mut self.ptr as *mut *mut raw::GError
    }

    pub fn is_set(&self) -> bool { !self.ptr.is_null() }

    pub fn key(&self) -> (Quark, gint) {
        if self.ptr.is_null() {
            panic!("use of an unset GError pointer slot");
        }
        unsafe {
            let raw = &*self.ptr;
            (Quark::from_raw(raw.domain), raw.code)
        }
    }
}

impl ErrorTrait for Error {
    fn description<'a>(&'a self) -> &'a str {
        if self.ptr.is_null() {
            return "no error";
        }
        let mut os: Option<&'a str> = None;
        let raw = unsafe { &*self.ptr };
        if !raw.message.is_null() {
            os = unsafe { gstr::parse_as_utf8(raw.message, self).ok() };
        }
        if os.is_none() {
            let domain = unsafe { Quark::from_raw(raw.domain) };
            os = str::from_utf8(domain.as_bytes()).ok().map(|s| {
                unsafe { mem::copy_lifetime(self, s) }
            });
        }
        if let Some(s) = os {
            s
        } else {
            "[non-UTF-8 message]"
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        if self.ptr.is_null() {
            write!(f, "no error")
        } else {
            let msg = unsafe {
                gstr::parse_as_bytes((*self.ptr).message, self)
            };
            write!(f, "{}", String::from_utf8_lossy(msg))
        }
    }
}
<commit_msg>error: A big overhaul<commit_after>// This file is part of Grust, GObject introspection bindings for Rust
//
// Copyright (C) 2014, 2015  Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

use gstr;
use quark::Quark;
use types::gint;
use util::escape_bytestring;

use glib as ffi;

use std::error::Error as ErrorTrait;
use std::error::FromError;
use std::fmt;
use std::num;

pub struct Error {
    ptr: *mut ffi::GError
}

pub struct DomainError<T> {
    inner: Error
}

#[derive(Copy, Debug)]
pub enum Code<T> {
    Known(T),
    Unknown(gint)
}

pub trait Domain : num::FromPrimitive {
    fn domain() -> Quark;
    fn name(&self) -> &'static str;
}

pub fn domain<T>() -> Quark where T: Domain {
    <T as Domain>::domain()
}

unsafe impl Send for Error { }

unsafe impl<T> Send for DomainError<T> { }

impl Drop for Error {
    fn drop(&mut self) {
        unsafe { ffi::g_error_free(self.ptr); }
    }
}

impl Clone for Error {
    fn clone(&self) -> Error {
        Error {
            ptr: unsafe { ffi::g_error_copy(self.ptr) }
        }
    }
}

impl<T> Clone for DomainError<T> {
    fn clone(&self) -> DomainError<T> {
        DomainError { inner: self.inner.clone() }
    }
}

impl Error {

    pub unsafe fn from_raw(ptr: *mut ffi::GError) -> Error {
        assert!(!ptr.is_null(), "GError pointer is not set");
        Error { ptr: ptr }
    }

    pub fn domain(&self) -> Quark {
        unsafe { Quark::from_raw((*self.ptr).domain) }
    }

    pub fn matches<T>(&self, code: T) -> bool where T: Domain + PartialEq {
        if self.domain() == domain::<T>() {
            let own_code_raw = unsafe { (*self.ptr).code };
            if let Some(own_code) = num::from_i32::<T>(own_code_raw as i32) {
                return own_code == code;
            }
        }
        false
    }

    pub fn key(&self) -> (Quark, gint) {
        unsafe {
            let raw = &*self.ptr;
            (Quark::from_raw(raw.domain), raw.code)
        }
    }

    pub fn in_domain<T>(&self) -> bool where T: Domain {
        self.domain() == domain::<T>()
    }

    pub fn into_domain<T>(self) -> Result<DomainError<T>, Error>
        where T: Domain
    {
        if self.in_domain::<T>() {
            Ok(DomainError { inner: self })
        } else {
            Err(self)
        }
    }

    fn message(&self) -> Option<&str> {
        let message = unsafe { (*self.ptr).message };
        let utf8_res = unsafe { gstr::parse_as_utf8(message, self) };
        utf8_res.ok()
    }

    fn message_bytes(&self) -> &[u8] {
        let message = unsafe { (*self.ptr).message };
        unsafe { gstr::parse_as_bytes(message, self) }
    }
}

impl<T> DomainError<T> where T: num::FromPrimitive {
    pub fn code(&self) -> Code<T> {
        let code = unsafe { (*self.inner.ptr).code };
        match num::from_i32(code as i32) {
            Some(domain_code) => Code::Known(domain_code),
            None              => Code::Unknown(code)
        }
    }
}

impl ErrorTrait for Error {
    fn description(&self) -> &str {
        if let Some(s) = self.message() {
            return s;
        }
        match self.domain().as_g_str().parse_as_utf8() {
            Ok(s)  => s,
            Err(_) => "GError (message and domain are not represented)"
        }
    }
}

impl<T> ErrorTrait for DomainError<T> where T: Domain {
    fn description(&self) -> &str {
        if let Some(s) = self.inner.message() {
            return s;
        }
        if let Code::Known(code) = self.code() {
            return code.name();
        }
        match self.inner.domain().as_g_str().parse_as_utf8() {
            Ok(s)  => s,
            Err(_) => "GError (message and domain are not represented; unknown code)"
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let bytes = self.message_bytes();
        write!(f, "{}", String::from_utf8_lossy(bytes))
    }
}

impl<T> fmt::Display for DomainError<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let bytes = self.inner.message_bytes();
        write!(f, "{}", String::from_utf8_lossy(bytes))
    }
}

impl fmt::Debug for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let (domain, code) = self.key();
        let message = escape_bytestring(self.message_bytes());
        write!(f,
               r#"GError{{domain={:?}, code={}, message="{}"}}"#,
               domain, code, message)
    }
}

impl<T> fmt::Debug for DomainError<T> where T: Domain {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let domain = self.inner.domain();
        let message = escape_bytestring(self.inner.message_bytes());
        match self.code() {
            Code::Known(code) => {
                write!(f,
                       r#"GError{{domain={:?}, code={}, message="{}"}}"#,
                       domain, code.name(), message)
            }
            Code::Unknown(int_code) => {
                write!(f,
                       r#"GError{{domain={:?}, code={}, message="{}"}}"#,
                       domain, int_code, message)
            }
        }
    }
}

impl<T> FromError<DomainError<T>> for Error {
    fn from_error(err: DomainError<T>) -> Error {
        err.inner
    }
}

impl<T> Code<T> {

    pub fn known(self) -> Option<T> {
        match self {
            Code::Known(code) => Some(code),
            Code::Unknown(_) => None
        }
    }
}

impl<T> PartialEq for Code<T> where T: PartialEq {
    fn eq(&self, other: &Code<T>) -> bool {
        match (self, other) {
            (&Code::Known(ref a), &Code::Known(ref b)) => *a == *b,
            (&Code::Unknown(a), &Code::Unknown(b)) => a == b,
            _ => false
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;
    use glib as ffi;
    use gstr::GStrBuf;
    use quark::Quark;
    use types::gint;

    fn new_error(domain: Quark, code: gint, message: &[u8]) -> Error {
        let msg_buf = GStrBuf::from_bytes(message).unwrap();
        unsafe {
            let raw = ffi::g_error_new_literal(
                domain.to_raw(), code, msg_buf.as_ptr());
            Error::from_raw(raw)
        }
    }

    #[test]
    fn message() {
        let domain = Quark::from_static_str("foo\0");
        let message = "test message";
        let err = new_error(domain, 1, message.as_bytes());
        assert_eq!(err.message().unwrap(), message);
        let err = new_error(domain, 1, b"U can't parse this.\x9C Hammer time!");
        assert!(err.message().is_none());
    }
}
<|endoftext|>


<commit_before>// ignore-windows: File handling is not implemented yet
// compile-flags: -Zmiri-disable-isolation

use std::fs::{File, remove_file};
use std::io::{Read, Write};

fn main() {
    let path = "miri_test_fs.txt";
    let bytes = b"Hello, World!\n";
    // Test creating, writing and closing a file (closing is tested when `file` is dropped).
    let mut file = File::create(path).unwrap();
    // Writing 0 bytes should not change the file contents.
    file.write(&mut []).unwrap();

    file.write(bytes).unwrap();
    // Test opening, reading and closing a file.
    let mut file = File::open(path).unwrap();
    let mut contents = Vec::new();
    // Reading 0 bytes should not move the file pointer.
    file.read(&mut []).unwrap();
    // Reading until EOF should get the whole text.
    file.read_to_end(&mut contents).unwrap();
    assert_eq!(bytes, contents.as_slice());
    // Removing file should succeed
    remove_file(path).unwrap();
    // Opening non-existing file should fail
    assert!(File::open(path).is_err());
    // Removing non-existing file should fail
    assert!(remove_file(path).is_err());
}
<commit_msg>Auto merge of #988 - RalfJung:temp, r=RalfJung<commit_after>// ignore-windows: File handling is not implemented yet
// compile-flags: -Zmiri-disable-isolation

use std::fs::{File, remove_file};
use std::io::{Read, Write};

fn main() {
    let path = std::env::temp_dir().join("miri_test_fs.txt");
    let bytes = b"Hello, World!\n";
    // Test creating, writing and closing a file (closing is tested when `file` is dropped).
    let mut file = File::create(&path).unwrap();
    // Writing 0 bytes should not change the file contents.
    file.write(&mut []).unwrap();

    file.write(bytes).unwrap();
    // Test opening, reading and closing a file.
    let mut file = File::open(&path).unwrap();
    let mut contents = Vec::new();
    // Reading 0 bytes should not move the file pointer.
    file.read(&mut []).unwrap();
    // Reading until EOF should get the whole text.
    file.read_to_end(&mut contents).unwrap();
    assert_eq!(bytes, contents.as_slice());
    // Removing file should succeed
    remove_file(&path).unwrap();
    // Opening non-existing file should fail
    assert!(File::open(&path).is_err());
    // Removing non-existing file should fail
    assert!(remove_file(&path).is_err());
}
<|endoftext|>


<commit_before>use error::InputError;
use std::fmt::{Debug, Display};
use std::io;
use std::str::FromStr;

pub fn read_line() -> io::Result<String> {
    let mut buffer = String::new();
    io::stdin().read_line(&mut buffer)?;

    // Trim the right side of the buffer to remove the newline character
    Ok(buffer.trim_right().to_string())
}

pub fn read_range<T>(min: T, max: T) -> Result<T, InputError>
where
    T: Ord + FromStr + Debug + Display,
    <T as FromStr>::Err: Debug,
{
    loop {
        let input = read_line()
            .map_err(InputError::ReadFailed)?
            .parse()
            .map_err(|e| InputError::ParseFailed(format!("{:?}", e)))?;

        if input >= min && input <= max {
            return Ok(input);
        } else {
            println!("input must be between {}-{}", min, max);
        }
    }
}

#[derive(Debug)]
pub enum Answer {
    Yes,
    No,
}

impl Into<bool> for Answer {
    fn into(self) -> bool {
        match self {
            Answer::Yes => true,
            Answer::No => false,
        }
    }
}

pub fn read_yn(default: Answer) -> io::Result<bool> {
    let line = read_line()?;

    let answer = match line.as_str() {
        "y" | "Y" => true,
        "n" | "N" => false,
        _ => default.into(),
    };

    Ok(answer)
}
<commit_msg>Bind the T type in input::read_range to PartialOrd instead of Ord<commit_after>use error::InputError;
use std::fmt::{Debug, Display};
use std::io;
use std::str::FromStr;

pub fn read_line() -> io::Result<String> {
    let mut buffer = String::new();
    io::stdin().read_line(&mut buffer)?;

    // Trim the right side of the buffer to remove the newline character
    Ok(buffer.trim_right().to_string())
}

pub fn read_range<T>(min: T, max: T) -> Result<T, InputError>
where
    T: PartialOrd + FromStr + Debug + Display,
    <T as FromStr>::Err: Debug,
{
    loop {
        let input = read_line()
            .map_err(InputError::ReadFailed)?
            .parse()
            .map_err(|e| InputError::ParseFailed(format!("{:?}", e)))?;

        if input >= min && input <= max {
            return Ok(input);
        } else {
            println!("input must be between {}-{}", min, max);
        }
    }
}

#[derive(Debug)]
pub enum Answer {
    Yes,
    No,
}

impl Into<bool> for Answer {
    fn into(self) -> bool {
        match self {
            Answer::Yes => true,
            Answer::No => false,
        }
    }
}

pub fn read_yn(default: Answer) -> io::Result<bool> {
    let line = read_line()?;

    let answer = match line.as_str() {
        "y" | "Y" => true,
        "n" | "N" => false,
        _ => default.into(),
    };

    Ok(answer)
}
<|endoftext|>


<commit_before>extern crate vk_generator;
extern crate vk_api;

use std::path::Path;
use std::fs::{File, DirBuilder};
use std::env;
use std::process::Command;
use std::io::Write;
use std::str;

use vk_generator::VkVersion;

#[test]
fn default_global() {
    let out = env::var("OUT_DIR").unwrap();
    DirBuilder::new().recursive(true).create(&out).unwrap();

    let mut file = File::create(&Path::new(&out).join("default_global.rs")).unwrap();
    writeln!(file, "fn main() {{}} mod vk {{").unwrap();
    vk_generator::VkRegistry::new(vk_api::VK_XML).gen_global(&mut file,
                                                             VkVersion(1, 0),
                                                             &["VK_KHR_surface"],
                                                             Default::default());
    writeln!(file, "}}").unwrap();

    assert_eq!("", str::from_utf8(&Command::new("rustc").current_dir(&out).arg("default_global.rs").output().unwrap().stderr).unwrap());
}

#[test]
fn default_struct() {
    let out = env::var("OUT_DIR").unwrap();
    DirBuilder::new().recursive(true).create(&out).unwrap();

    let mut file = File::create(&Path::new(&out).join("default_struct.rs")).unwrap();
    writeln!(file, "fn main() {{}} mod vk {{").unwrap();
    vk_generator::VkRegistry::new(vk_api::VK_XML).gen_struct(&mut file,
                                                             VkVersion(1, 0),
                                                             &["VK_KHR_surface"],
                                                             Default::default());
    writeln!(file, "}}").unwrap();

    assert_eq!("", str::from_utf8(&Command::new("rustc").current_dir(&out).arg("default_struct.rs").output().unwrap().stderr).unwrap());
}<commit_msg>Upgraded test suite to test all non-default options but use_libc_types<commit_after>extern crate vk_generator;
extern crate vk_api;

use std::path::Path;
use std::fs::{File, DirBuilder};
use std::env;
use std::process::Command;
use std::io::Write;
use std::str;

use vk_generator::{VkVersion, GenConfig};

#[test]
fn default_global() {
    let out = env::var("OUT_DIR").unwrap();
    DirBuilder::new().recursive(true).create(&out).unwrap();

    let mut file = File::create(&Path::new(&out).join("default_global.rs")).unwrap();
    writeln!(file, "fn main() {{}} mod vk {{").unwrap();
    vk_generator::VkRegistry::new(vk_api::VK_XML)
        .gen_global(&mut file,
                    VkVersion(1, 0),
                    &["VK_KHR_surface", "VK_EXT_debug_report"],
                    Default::default());
    writeln!(file, "}}").unwrap();

    assert_eq!("", str::from_utf8(&Command::new("rustc").current_dir(&out).arg("default_global.rs").output().unwrap().stderr).unwrap());
}

#[test]
fn default_struct() {
    let out = env::var("OUT_DIR").unwrap();
    DirBuilder::new().recursive(true).create(&out).unwrap();

    let mut file = File::create(&Path::new(&out).join("default_struct.rs")).unwrap();
    writeln!(file, "fn main() {{}} mod vk {{").unwrap();
    vk_generator::VkRegistry::new(vk_api::VK_XML)
        .gen_struct(&mut file,
                    VkVersion(1, 0),
                    &["VK_KHR_surface", "VK_EXT_debug_report"],
                    Default::default());
    writeln!(file, "}}").unwrap();

    assert_eq!("", str::from_utf8(&Command::new("rustc").current_dir(&out).arg("default_struct.rs").output().unwrap().stderr).unwrap());
}

#[test]
fn nondefault_global() {
    let out = env::var("OUT_DIR").unwrap();
    DirBuilder::new().recursive(true).create(&out).unwrap();

    let mut file = File::create(&Path::new(&out).join("nondefault_global.rs")).unwrap();
    writeln!(file, "fn main() {{}} mod vk {{").unwrap();
    vk_generator::VkRegistry::new(vk_api::VK_XML)
        .gen_global(&mut file,
                    VkVersion(1, 0),
                    &["VK_KHR_surface", "VK_EXT_debug_report"],
                    GenConfig::new()
                        .remove_type_prefix(true)
                        .remove_vk_result_prefix(false)
                        .remove_command_prefix(false)
                        .remove_variant_padding(false)
                        .remove_bitmask_prefix(false)
                        .snake_case_commands(false)
                        .camel_case_variants(false)
                        .snake_case_members(false)
                        .wrap_bitmasks(false));
    writeln!(file, "}}").unwrap();

    assert_eq!("", str::from_utf8(&Command::new("rustc").current_dir(&out).arg("nondefault_global.rs").output().unwrap().stderr).unwrap());
}

#[test]
fn nondefault_struct() {
    let out = env::var("OUT_DIR").unwrap();
    DirBuilder::new().recursive(true).create(&out).unwrap();

    let mut file = File::create(&Path::new(&out).join("nondefault_struct.rs")).unwrap();
    writeln!(file, "fn main() {{}} mod vk {{").unwrap();
    vk_generator::VkRegistry::new(vk_api::VK_XML)
        .gen_struct(&mut file,
                    VkVersion(1, 0),
                    &["VK_KHR_surface", "VK_EXT_debug_report"],
                    GenConfig::new()
                        .remove_type_prefix(true)
                        .remove_vk_result_prefix(false)
                        .remove_command_prefix(false)
                        .remove_variant_padding(false)
                        .remove_bitmask_prefix(false)
                        .snake_case_commands(false)
                        .camel_case_variants(false)
                        .snake_case_members(false)
                        .wrap_bitmasks(false));
    writeln!(file, "}}").unwrap();

    assert_eq!("", str::from_utf8(&Command::new("rustc").current_dir(&out).arg("nondefault_struct.rs").output().unwrap().stderr).unwrap());
}
<|endoftext|>


<commit_before>use std::collections::HashMap;

use scanner::Scanner;
use regex::Regex;

const COMPARISON           : &'static str = r"^(==|!=|<>|<=?|>=?|contains)";
const SINGLE_STRING_LITERAL: &'static str = r"^'[^']*'";
const DOUBLE_STRING_LITERAL: &'static str = r#"^"[^"]*""#;
const NUMBER_LITERAL:        &'static str = r"^-?\d+(\.\d+)?";
const IDENTIFIER:            &'static str = r"^[a-zA-Z_][\w-]*\??";
const RANGE_OP:              &'static str = r"^\.\.";

#[derive(Clone, Debug, PartialEq)]
pub enum Token {
    Comparison,
    Identifier,
    Number,
    String,
    Range,
    Pipe,
    Dot,
    Colon,
    Comma,
    OpenSquare,
    CloseSquare,
    OpenRound,
    CloseRound,
    Question,
    Dash
}

pub type LexedToken = (Token, String);

macro_rules! token {
    (Range)                         => (token!(Range, ".."));
    (Pipe)                          => (token!(Pipe, "|"));
    (Dot)                           => (token!(Dot, "."));
    (Colon)                         => (token!(Colon, ":"));
    (Comma)                         => (token!(Comma, ","));
    (OpenSquare)                    => (token!(OpenSquare, "["));
    (CloseSquare)                   => (token!(CloseSquare, "]"));
    (OpenRound)                     => (token!(OpenRound, "("));
    (CloseRound)                    => (token!(CloseRound, ")"));
    (Question)                      => (token!(Question, "?"));
    (Dash)                          => (token!(Dash, "-"));
    ($tokenType:ident, $value:expr) => ((Token::$tokenType, String::from($value)));
}

pub struct Tokens<'t> {
    scanner: &'t Scanner<'t>,
    specials: HashMap<&'t str, Token>,
    matchers: Vec<Regex>
}

impl<'t> Tokens<'t> {
    fn new<'a>(scanner: &'a Scanner<'a>) -> Tokens<'a> {
        let mut specials = HashMap::new();
        specials.insert("|", Token::Pipe);
        specials.insert(".", Token::Dot);
        specials.insert(":", Token::Colon);
        specials.insert(",", Token::Comma);
        specials.insert("[", Token::OpenSquare);
        specials.insert("]", Token::CloseSquare);
        specials.insert("(", Token::OpenRound);
        specials.insert(")", Token::CloseRound);
        specials.insert("?", Token::Question);
        specials.insert("-", Token::Dash);

        let matchers = vec![
            Regex::new(COMPARISON).unwrap(),
            Regex::new(SINGLE_STRING_LITERAL).unwrap(),
            Regex::new(DOUBLE_STRING_LITERAL).unwrap(),
            Regex::new(NUMBER_LITERAL).unwrap(),
            Regex::new(IDENTIFIER).unwrap(),
            Regex::new(RANGE_OP).unwrap()
        ];

        Tokens { scanner: scanner, specials: specials, matchers: matchers }
    }

    fn token_for(&self, pattern: &Regex, value: &str) -> LexedToken {
        match pattern.as_str() {
            COMPARISON            => token!(Comparison, value),
            SINGLE_STRING_LITERAL => token!(String, value),
            DOUBLE_STRING_LITERAL => token!(String, value),
            NUMBER_LITERAL        => token!(Number, value),
            IDENTIFIER            => token!(Identifier, value),
            RANGE_OP              => token!(Range),
            _                     => unreachable!() // already been checked for existence
        }
    }

    fn next_match(&self) -> Option<LexedToken> {
        match self.matchers.iter().find(|&m| self.scanner.check(m)) {
            Some(regex) => self.matched_token(&regex),
            None => self.matched_special()
        }
    }

    fn matched_token(&self, pattern: &Regex) -> Option<LexedToken> {
        let value = self.scanner.scan(pattern).unwrap();
        Some(self.token_for(pattern, value))
    }

    fn matched_special(&self) -> Option<LexedToken> {
        match self.scanner.get_char() {
            Some(character) => {
                match self.specials.get(character) {
                    Some(token) => Some(((*token).clone(), character.into())),
                    None => unreachable!("Syntax Error")
                }
            },
            None => None
        }
    }
}

impl<'t> Iterator for Tokens<'t> {
    type Item = (Token, String);

    fn next(&mut self) -> Option<LexedToken> {
        self.next_match()
    }
}

pub struct Lexer<'t> {
    scanner: Scanner<'t>
}

impl<'t> Lexer<'t> {
    pub fn new<'a>(source: &'a str) -> Lexer<'a> {
        Lexer { scanner: Scanner::new(source) }
    }

    pub fn tokens(&self) -> Tokens {
        Tokens::new(&self.scanner)
    }
}

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

    fn compare_tokens(lexer: &Lexer, expectedTokens: Vec<LexedToken>) {
        let zipped = lexer.tokens().zip(expectedTokens);

        for token in zipped {
            let (actual, expected) = token;
            assert_eq!(expected, actual);
        }
    }

    #[test]
    fn new_creates_a_new_instance() {
        let lexer = Lexer::new("doSomthing | filter");
        assert_eq!("doSomthing | filter", lexer.scanner.rest().unwrap());
    }

    #[test]
    fn tokens_when_given_a_blank_string() {
        let lexer                   = Lexer::new("");
        let tokens: Vec<LexedToken> = lexer.tokens().collect();

        assert_eq!(0, tokens.len());
    }

    #[test]
    fn tokens_when_given_a_whitespace_only_string() {
        let lexer                   = Lexer::new("  \t \n\r ");
        let tokens: Vec<LexedToken> = lexer.tokens().collect();

        assert_eq!(0, tokens.len());
    }

    #[test]
    fn tokens_parses_identifiers() {
        let lexer    = Lexer::new("high five?");
        let expected = vec![
            token!(Identifier, "high"),
            token!(Identifier, "five?")
        ];

        compare_tokens(&lexer, expected);
    }

    #[test]
    fn tokens_knows_that_identifiers_dont_start_with_numbers() {
        let lexer    = Lexer::new("2foo 5.0bar");
        let expected = vec![
            token!(Number, "2"),
            token!(Identifier, "foo"),
            token!(Number, "5.0"),
            token!(Identifier, "bar")
        ];

        compare_tokens(&lexer, expected);
    }

    #[test]
    fn tokens_parses_string_literals() {
        let lexer    = Lexer::new(r#" 'this is a test""' "wat 'lol'" "#);
        let expected = vec![
            token!(String, r#"'this is a test""'"#),
            token!(String, r#""wat 'lol'""#)
        ];

        compare_tokens(&lexer, expected);
    }

    #[test]
    fn tokens_parses_integers() {
        let lexer    = Lexer::new("hi 50");
        let expected = vec![
            token!(Identifier, "hi"),
            token!(Number, "50")
        ];

        compare_tokens(&lexer, expected);
    }

    #[test]
    fn tokens_parses_floats() {
        let lexer    = Lexer::new("hi 5.0");
        let expected = vec![
            token!(Identifier, "hi"),
            token!(Number, "5.0")
        ];

        compare_tokens(&lexer, expected);
    }

    #[test]
    fn tokens_parses_comparisons() {
        let lexer    = Lexer::new("== <> contains");
        let expected = vec![
            token!(Comparison, "=="),
            token!(Comparison, "<>"),
            token!(Comparison, "contains")
        ];

        compare_tokens(&lexer, expected);
    }

    #[test]
    fn tokens_parses_range_operator() {
        let lexer    = Lexer::new("1..10");
        let expected = vec![
            token!(Number, "1"),
            token!(Range),
            token!(Number, "10")
        ];

        compare_tokens(&lexer, expected);
    }

    #[test]
    fn tokens_parses_special_characters() {
        let lexer    = Lexer::new("[hi], (| .:) - ?cool");
        let expected = vec![
            token!(OpenSquare),
            token!(Identifier, "hi"),
            token!(CloseSquare),
            token!(Comma),
            token!(OpenRound),
            token!(Pipe),
            token!(Dot),
            token!(Colon),
            token!(CloseRound),
            token!(Dash),
            token!(Question),
            token!(Identifier, "cool")
        ];

        compare_tokens(&lexer, expected);
    }

    #[test]
    fn tokens_skips_internal_whitespace() {
        let lexer    = Lexer::new("five|\n\t ==");
        let expected = vec![
            token!(Identifier, "five"),
            token!(Pipe),
            token!(Comparison, "==")
        ];

        compare_tokens(&lexer, expected);
    }

    #[test]
    #[should_panic(expected = "Syntax Error")]
    fn tokens_freaks_out_with_syntax_error() {
        let lexer                   = Lexer::new("%");
        let tokens: Vec<LexedToken> = lexer.tokens().collect();
    }
}
<commit_msg>using some FnOnce action on lexer.rs<commit_after>use std::collections::HashMap;

use scanner::Scanner;
use regex::Regex;

const COMPARISON           : &'static str = r"^(==|!=|<>|<=?|>=?|contains)";
const SINGLE_STRING_LITERAL: &'static str = r"^'[^']*'";
const DOUBLE_STRING_LITERAL: &'static str = r#"^"[^"]*""#;
const NUMBER_LITERAL:        &'static str = r"^-?\d+(\.\d+)?";
const IDENTIFIER:            &'static str = r"^[a-zA-Z_][\w-]*\??";
const RANGE_OP:              &'static str = r"^\.\.";

#[derive(Clone, Debug, PartialEq)]
pub enum Token {
    Comparison,
    Identifier,
    Number,
    String,
    Range,
    Pipe,
    Dot,
    Colon,
    Comma,
    OpenSquare,
    CloseSquare,
    OpenRound,
    CloseRound,
    Question,
    Dash
}

pub type LexedToken = (Token, String);

macro_rules! token {
    (Range)                         => (token!(Range, ".."));
    (Pipe)                          => (token!(Pipe, "|"));
    (Dot)                           => (token!(Dot, "."));
    (Colon)                         => (token!(Colon, ":"));
    (Comma)                         => (token!(Comma, ","));
    (OpenSquare)                    => (token!(OpenSquare, "["));
    (CloseSquare)                   => (token!(CloseSquare, "]"));
    (OpenRound)                     => (token!(OpenRound, "("));
    (CloseRound)                    => (token!(CloseRound, ")"));
    (Question)                      => (token!(Question, "?"));
    (Dash)                          => (token!(Dash, "-"));
    ($tokenType:ident, $value:expr) => ((Token::$tokenType, String::from($value)));
}

pub struct Tokens<'t> {
    scanner: &'t Scanner<'t>,
    specials: HashMap<&'t str, Token>,
    matchers: Vec<Regex>
}

impl<'t> Tokens<'t> {
    fn new<'a>(scanner: &'a Scanner<'a>) -> Tokens<'a> {
        let mut specials = HashMap::new();
        specials.insert("|", Token::Pipe);
        specials.insert(".", Token::Dot);
        specials.insert(":", Token::Colon);
        specials.insert(",", Token::Comma);
        specials.insert("[", Token::OpenSquare);
        specials.insert("]", Token::CloseSquare);
        specials.insert("(", Token::OpenRound);
        specials.insert(")", Token::CloseRound);
        specials.insert("?", Token::Question);
        specials.insert("-", Token::Dash);

        let matchers = vec![
            Regex::new(COMPARISON).unwrap(),
            Regex::new(SINGLE_STRING_LITERAL).unwrap(),
            Regex::new(DOUBLE_STRING_LITERAL).unwrap(),
            Regex::new(NUMBER_LITERAL).unwrap(),
            Regex::new(IDENTIFIER).unwrap(),
            Regex::new(RANGE_OP).unwrap()
        ];

        Tokens { scanner: scanner, specials: specials, matchers: matchers }
    }

    fn token_for(&self, pattern: &Regex, value: &str) -> LexedToken {
        match pattern.as_str() {
            COMPARISON            => token!(Comparison, value),
            SINGLE_STRING_LITERAL => token!(String, value),
            DOUBLE_STRING_LITERAL => token!(String, value),
            NUMBER_LITERAL        => token!(Number, value),
            IDENTIFIER            => token!(Identifier, value),
            RANGE_OP              => token!(Range),
            _                     => unreachable!() // already been checked for existence
        }
    }

    fn next_match(&self) -> Option<LexedToken> {
        self.matchers.iter().find(|&m| self.scanner.check(m))
            .and_then(|regex| self.matched_token(&regex))
            .or_else(|| self.matched_special())
    }

    fn matched_token(&self, pattern: &Regex) -> Option<LexedToken> {
        let value = self.scanner.scan(pattern).unwrap();
        Some(self.token_for(pattern, value))
    }

    fn matched_special(&self) -> Option<LexedToken> {
        self.scanner.get_char()
            .and_then(|character| {
                self.specials.get(character)
                    .and_then(|token| Some(((*token).clone(), character.into())))
                    .or_else(|| unreachable!("Syntax Error"))
            })
    }
}

impl<'t> Iterator for Tokens<'t> {
    type Item = (Token, String);

    fn next(&mut self) -> Option<LexedToken> {
        self.next_match()
    }
}

pub struct Lexer<'t> {
    scanner: Scanner<'t>
}

impl<'t> Lexer<'t> {
    pub fn new<'a>(source: &'a str) -> Lexer<'a> {
        Lexer { scanner: Scanner::new(source) }
    }

    pub fn tokens(&self) -> Tokens {
        Tokens::new(&self.scanner)
    }
}

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

    fn compare_tokens(lexer: &Lexer, expected_tokens: Vec<LexedToken>) {
        let zipped = lexer.tokens().zip(expected_tokens);

        for (actual, expected) in zipped {
            assert_eq!(expected, actual);
        }
    }

    #[test]
    fn new_creates_a_new_instance() {
        let lexer = Lexer::new("doSomthing | filter");
        assert_eq!("doSomthing | filter", lexer.scanner.rest().unwrap());
    }

    #[test]
    fn tokens_when_given_a_blank_string() {
        let lexer                   = Lexer::new("");
        let tokens: Vec<LexedToken> = lexer.tokens().collect();

        assert_eq!(0, tokens.len());
    }

    #[test]
    fn tokens_when_given_a_whitespace_only_string() {
        let lexer                   = Lexer::new("  \t \n\r ");
        let tokens: Vec<LexedToken> = lexer.tokens().collect();

        assert_eq!(0, tokens.len());
    }

    #[test]
    fn tokens_parses_identifiers() {
        let lexer    = Lexer::new("high five?");
        let expected = vec![
            token!(Identifier, "high"),
            token!(Identifier, "five?")
        ];

        compare_tokens(&lexer, expected);
    }

    #[test]
    fn tokens_knows_that_identifiers_dont_start_with_numbers() {
        let lexer    = Lexer::new("2foo 5.0bar");
        let expected = vec![
            token!(Number, "2"),
            token!(Identifier, "foo"),
            token!(Number, "5.0"),
            token!(Identifier, "bar")
        ];

        compare_tokens(&lexer, expected);
    }

    #[test]
    fn tokens_parses_string_literals() {
        let lexer    = Lexer::new(r#" 'this is a test""' "wat 'lol'" "#);
        let expected = vec![
            token!(String, r#"'this is a test""'"#),
            token!(String, r#""wat 'lol'""#)
        ];

        compare_tokens(&lexer, expected);
    }

    #[test]
    fn tokens_parses_integers() {
        let lexer    = Lexer::new("hi 50");
        let expected = vec![
            token!(Identifier, "hi"),
            token!(Number, "50")
        ];

        compare_tokens(&lexer, expected);
    }

    #[test]
    fn tokens_parses_floats() {
        let lexer    = Lexer::new("hi 5.0");
        let expected = vec![
            token!(Identifier, "hi"),
            token!(Number, "5.0")
        ];

        compare_tokens(&lexer, expected);
    }

    #[test]
    fn tokens_parses_comparisons() {
        let lexer    = Lexer::new("== <> contains");
        let expected = vec![
            token!(Comparison, "=="),
            token!(Comparison, "<>"),
            token!(Comparison, "contains")
        ];

        compare_tokens(&lexer, expected);
    }

    #[test]
    fn tokens_parses_range_operator() {
        let lexer    = Lexer::new("1..10");
        let expected = vec![
            token!(Number, "1"),
            token!(Range),
            token!(Number, "10")
        ];

        compare_tokens(&lexer, expected);
    }

    #[test]
    fn tokens_parses_special_characters() {
        let lexer    = Lexer::new("[hi], (| .:) - ?cool");
        let expected = vec![
            token!(OpenSquare),
            token!(Identifier, "hi"),
            token!(CloseSquare),
            token!(Comma),
            token!(OpenRound),
            token!(Pipe),
            token!(Dot),
            token!(Colon),
            token!(CloseRound),
            token!(Dash),
            token!(Question),
            token!(Identifier, "cool")
        ];

        compare_tokens(&lexer, expected);
    }

    #[test]
    fn tokens_skips_internal_whitespace() {
        let lexer    = Lexer::new("five|\n\t ==");
        let expected = vec![
            token!(Identifier, "five"),
            token!(Pipe),
            token!(Comparison, "==")
        ];

        compare_tokens(&lexer, expected);
    }

    #[test]
    #[should_panic(expected = "Syntax Error")]
    fn tokens_freaks_out_with_syntax_error() {
        let lexer                   = Lexer::new("%");
        let tokens: Vec<LexedToken> = lexer.tokens().collect();
    }
}
<|endoftext|>


<commit_before>#![cfg(feature="quickcheck")]
extern crate quickcheck;

extern crate petgraph;

use petgraph::{Graph, GraphMap, Undirected, Directed, EdgeType, Incoming, Outgoing};
use petgraph::algo::{min_spanning_tree, is_cyclic_undirected, is_isomorphic};
use petgraph::graph::{IndexType, node_index};

fn prop(g: Graph<(), u32>) -> bool {
    // filter out isolated nodes
    let no_singles = g.filter_map(
        |nx, w| g.neighbors_undirected(nx).next().map(|_| w),
        |_, w| Some(w));
    for i in no_singles.node_indices() {
        assert!(no_singles.neighbors_undirected(i).count() > 0);
    }
    assert_eq!(no_singles.edge_count(), g.edge_count());
    let mst = min_spanning_tree(&no_singles);
    assert!(!is_cyclic_undirected(&mst));
    true
}

fn prop_undir(g: Graph<(), u32, Undirected>) -> bool {
    // filter out isolated nodes
    let no_singles = g.filter_map(
        |nx, w| g.neighbors_undirected(nx).next().map(|_| w),
        |_, w| Some(w));
    for i in no_singles.node_indices() {
        assert!(no_singles.neighbors_undirected(i).count() > 0);
    }
    assert_eq!(no_singles.edge_count(), g.edge_count());
    let mst = min_spanning_tree(&no_singles);
    assert!(!is_cyclic_undirected(&mst));
    true
}

#[test]
fn arbitrary() {
    quickcheck::quickcheck(prop as fn(_) -> bool);
    quickcheck::quickcheck(prop_undir as fn(_) -> bool);
}

#[test]
fn reverse_undirected() {
    fn prop<Ty: EdgeType>(g: Graph<(), (), Ty>) -> bool {
        if g.edge_count() > 30 {
            return true; // iso too slow
        }
        let mut h = g.clone();
        h.reverse();
        is_isomorphic(&g, &h)
    }
    quickcheck::quickcheck(prop as fn(Graph<_, _, Undirected>) -> bool);
}

fn assert_graph_consistent<N, E, Ty, Ix>(g: &Graph<N, E, Ty, Ix>)
    where Ty: EdgeType,
          Ix: IndexType,
{
    assert_eq!(g.node_count(), g.node_indices().count());
    assert_eq!(g.edge_count(), g.edge_indices().count());
    for edge in g.raw_edges() {
        assert!(g.find_edge(edge.source(), edge.target()).is_some(),
                "Edge not in graph! {:?} to {:?}", edge.source(), edge.target());
    }
}

#[test]
fn reverse_directed() {
    fn prop<Ty: EdgeType>(mut g: Graph<(), (), Ty>) -> bool {
        let node_outdegrees = g.node_indices()
                                .map(|i| g.neighbors_directed(i, Outgoing).count())
                                .collect::<Vec<_>>();
        let node_indegrees = g.node_indices()
                                .map(|i| g.neighbors_directed(i, Incoming).count())
                                .collect::<Vec<_>>();

        g.reverse();
        let new_outdegrees = g.node_indices()
                                .map(|i| g.neighbors_directed(i, Outgoing).count())
                                .collect::<Vec<_>>();
        let new_indegrees = g.node_indices()
                                .map(|i| g.neighbors_directed(i, Incoming).count())
                                .collect::<Vec<_>>();
        assert_eq!(node_outdegrees, new_indegrees);
        assert_eq!(node_indegrees, new_outdegrees);
        assert_graph_consistent(&g);
        true
    }
    quickcheck::quickcheck(prop as fn(Graph<_, _, Directed>) -> bool);
}

#[test]
fn retain_nodes() {
    fn prop<Ty: EdgeType>(mut g: Graph<i32, (), Ty>) -> bool {
        // Remove all negative nodes, these should be randomly spread
        let og = g.clone();
        let nodes = g.node_count();
        let num_negs = g.raw_nodes().iter().filter(|n| n.weight < 0).count();
        let mut removed = 0;
        g.retain_nodes(|g, i| {
            let keep = g[i] >= 0;
            if !keep {
                removed += 1;
            }
            keep
        });
        let num_negs_post = g.raw_nodes().iter().filter(|n| n.weight < 0).count();
        let num_pos_post = g.raw_nodes().iter().filter(|n| n.weight >= 0).count();
        assert_eq!(num_negs_post, 0);
        assert_eq!(removed, num_negs);
        assert_eq!(num_negs + g.node_count(), nodes);
        assert_eq!(num_pos_post, g.node_count());
        if og.edge_count() < 30 {
            // check against filter_map
            let filtered = og.filter_map(|_, w| if *w >= 0 { Some(*w) } else { None },
                                         |_, w| Some(*w));
            assert_eq!(g.node_count(), filtered.node_count());
            assert!(is_isomorphic(&filtered, &g));
        }
        true
    }
    quickcheck::quickcheck(prop as fn(Graph<_, _, Directed>) -> bool);
    quickcheck::quickcheck(prop as fn(Graph<_, _, Undirected>) -> bool);
}

#[test]
fn retain_edges() {
    fn prop<Ty: EdgeType>(mut g: Graph<(), i32, Ty>) -> bool {
        // Remove all negative edges, these should be randomly spread
        let og = g.clone();
        let edges = g.edge_count();
        let num_negs = g.raw_edges().iter().filter(|n| n.weight < 0).count();
        let mut removed = 0;
        g.retain_edges(|g, i| {
            let keep = g[i] >= 0;
            if !keep {
                removed += 1;
            }
            keep
        });
        let num_negs_post = g.raw_edges().iter().filter(|n| n.weight < 0).count();
        let num_pos_post = g.raw_edges().iter().filter(|n| n.weight >= 0).count();
        assert_eq!(num_negs_post, 0);
        assert_eq!(removed, num_negs);
        assert_eq!(num_negs + g.edge_count(), edges);
        assert_eq!(num_pos_post, g.edge_count());
        if og.edge_count() < 30 {
            // check against filter_map
            let filtered = og.filter_map(
                |_, w| Some(*w),
                |_, w| if *w >= 0 { Some(*w) } else { None });
            assert_eq!(g.node_count(), filtered.node_count());
            assert!(is_isomorphic(&filtered, &g));
        }
        true
    }
    quickcheck::quickcheck(prop as fn(Graph<_, _, Directed>) -> bool);
    quickcheck::quickcheck(prop as fn(Graph<_, _, Undirected>) -> bool);
}

#[test]
fn graph_remove_edge() {
    fn prop<Ty: EdgeType>(mut g: Graph<(), (), Ty>, a: u8, b: u8) -> bool {
        let a = node_index(a as usize);
        let b = node_index(b as usize);
        let edge = g.find_edge(a, b);
        if !g.is_directed() {
            assert_eq!(edge.is_some(), g.find_edge(b, a).is_some());
        }
        if let Some(ex) = edge {
            assert!(g.remove_edge(ex).is_some());
        }
        assert_graph_consistent(&g);
        assert!(g.find_edge(a, b).is_none());
        assert!(g.neighbors(a).find(|x| *x == b).is_none());
        if !g.is_directed() {
            assert!(g.neighbors(b).find(|x| *x == a).is_none());
        }
        true
    }
    quickcheck::quickcheck(prop as fn(Graph<_, _, Undirected>, _, _) -> bool);
    quickcheck::quickcheck(prop as fn(Graph<_, _, Directed>, _, _) -> bool);
}

#[test]
fn graphmap_remove() {
    fn prop(mut g: GraphMap<i8, ()>, a: i8, b: i8) -> bool {
        let contains = g.contains_edge(a, b);
        assert_eq!(contains, g.contains_edge(b, a));
        assert_eq!(g.remove_edge(a, b).is_some(), contains);
        assert!(!g.contains_edge(a, b) &&
            g.neighbors(a).find(|x| *x == b).is_none() &&
            g.neighbors(b).find(|x| *x == a).is_none());
        assert!(g.remove_edge(a, b).is_none());
        true
    }
    quickcheck::quickcheck(prop as fn(_, _, _) -> bool);
}

#[test]
fn graphmap_add_remove() {
    fn prop(mut g: GraphMap<i8, ()>, a: i8, b: i8) -> bool {
        assert_eq!(g.contains_edge(a, b), g.add_edge(a, b, ()).is_some());
        g.remove_edge(a, b);
        !g.contains_edge(a, b) &&
            g.neighbors(a).find(|x| *x == b).is_none() &&
            g.neighbors(b).find(|x| *x == a).is_none()
    }
    quickcheck::quickcheck(prop as fn(_, _, _) -> bool);
}
<commit_msg>quickchecks: Only run isomorphism on small graphs<commit_after>#![cfg(feature="quickcheck")]
extern crate quickcheck;

extern crate petgraph;

use petgraph::{Graph, GraphMap, Undirected, Directed, EdgeType, Incoming, Outgoing};
use petgraph::algo::{min_spanning_tree, is_cyclic_undirected, is_isomorphic};
use petgraph::graph::{IndexType, node_index};

fn prop(g: Graph<(), u32>) -> bool {
    // filter out isolated nodes
    let no_singles = g.filter_map(
        |nx, w| g.neighbors_undirected(nx).next().map(|_| w),
        |_, w| Some(w));
    for i in no_singles.node_indices() {
        assert!(no_singles.neighbors_undirected(i).count() > 0);
    }
    assert_eq!(no_singles.edge_count(), g.edge_count());
    let mst = min_spanning_tree(&no_singles);
    assert!(!is_cyclic_undirected(&mst));
    true
}

fn prop_undir(g: Graph<(), u32, Undirected>) -> bool {
    // filter out isolated nodes
    let no_singles = g.filter_map(
        |nx, w| g.neighbors_undirected(nx).next().map(|_| w),
        |_, w| Some(w));
    for i in no_singles.node_indices() {
        assert!(no_singles.neighbors_undirected(i).count() > 0);
    }
    assert_eq!(no_singles.edge_count(), g.edge_count());
    let mst = min_spanning_tree(&no_singles);
    assert!(!is_cyclic_undirected(&mst));
    true
}

#[test]
fn arbitrary() {
    quickcheck::quickcheck(prop as fn(_) -> bool);
    quickcheck::quickcheck(prop_undir as fn(_) -> bool);
}

#[test]
fn reverse_undirected() {
    fn prop<Ty: EdgeType>(g: Graph<(), (), Ty>) -> bool {
        if g.edge_count() > 30 {
            return true; // iso too slow
        }
        let mut h = g.clone();
        h.reverse();
        is_isomorphic(&g, &h)
    }
    quickcheck::quickcheck(prop as fn(Graph<_, _, Undirected>) -> bool);
}

fn assert_graph_consistent<N, E, Ty, Ix>(g: &Graph<N, E, Ty, Ix>)
    where Ty: EdgeType,
          Ix: IndexType,
{
    assert_eq!(g.node_count(), g.node_indices().count());
    assert_eq!(g.edge_count(), g.edge_indices().count());
    for edge in g.raw_edges() {
        assert!(g.find_edge(edge.source(), edge.target()).is_some(),
                "Edge not in graph! {:?} to {:?}", edge.source(), edge.target());
    }
}

#[test]
fn reverse_directed() {
    fn prop<Ty: EdgeType>(mut g: Graph<(), (), Ty>) -> bool {
        let node_outdegrees = g.node_indices()
                                .map(|i| g.neighbors_directed(i, Outgoing).count())
                                .collect::<Vec<_>>();
        let node_indegrees = g.node_indices()
                                .map(|i| g.neighbors_directed(i, Incoming).count())
                                .collect::<Vec<_>>();

        g.reverse();
        let new_outdegrees = g.node_indices()
                                .map(|i| g.neighbors_directed(i, Outgoing).count())
                                .collect::<Vec<_>>();
        let new_indegrees = g.node_indices()
                                .map(|i| g.neighbors_directed(i, Incoming).count())
                                .collect::<Vec<_>>();
        assert_eq!(node_outdegrees, new_indegrees);
        assert_eq!(node_indegrees, new_outdegrees);
        assert_graph_consistent(&g);
        true
    }
    quickcheck::quickcheck(prop as fn(Graph<_, _, Directed>) -> bool);
}

#[test]
fn retain_nodes() {
    fn prop<Ty: EdgeType>(mut g: Graph<i32, (), Ty>) -> bool {
        // Remove all negative nodes, these should be randomly spread
        let og = g.clone();
        let nodes = g.node_count();
        let num_negs = g.raw_nodes().iter().filter(|n| n.weight < 0).count();
        let mut removed = 0;
        g.retain_nodes(|g, i| {
            let keep = g[i] >= 0;
            if !keep {
                removed += 1;
            }
            keep
        });
        let num_negs_post = g.raw_nodes().iter().filter(|n| n.weight < 0).count();
        let num_pos_post = g.raw_nodes().iter().filter(|n| n.weight >= 0).count();
        assert_eq!(num_negs_post, 0);
        assert_eq!(removed, num_negs);
        assert_eq!(num_negs + g.node_count(), nodes);
        assert_eq!(num_pos_post, g.node_count());
        if og.node_count() < 30 && og.edge_count() < 30 {
            // check against filter_map
            let filtered = og.filter_map(|_, w| if *w >= 0 { Some(*w) } else { None },
                                         |_, w| Some(*w));
            assert_eq!(g.node_count(), filtered.node_count());
            assert!(is_isomorphic(&filtered, &g));
        }
        true
    }
    quickcheck::quickcheck(prop as fn(Graph<_, _, Directed>) -> bool);
    quickcheck::quickcheck(prop as fn(Graph<_, _, Undirected>) -> bool);
}

#[test]
fn retain_edges() {
    fn prop<Ty: EdgeType>(mut g: Graph<(), i32, Ty>) -> bool {
        // Remove all negative edges, these should be randomly spread
        let og = g.clone();
        let edges = g.edge_count();
        let num_negs = g.raw_edges().iter().filter(|n| n.weight < 0).count();
        let mut removed = 0;
        g.retain_edges(|g, i| {
            let keep = g[i] >= 0;
            if !keep {
                removed += 1;
            }
            keep
        });
        let num_negs_post = g.raw_edges().iter().filter(|n| n.weight < 0).count();
        let num_pos_post = g.raw_edges().iter().filter(|n| n.weight >= 0).count();
        assert_eq!(num_negs_post, 0);
        assert_eq!(removed, num_negs);
        assert_eq!(num_negs + g.edge_count(), edges);
        assert_eq!(num_pos_post, g.edge_count());
        if og.edge_count() < 30 {
            // check against filter_map
            let filtered = og.filter_map(
                |_, w| Some(*w),
                |_, w| if *w >= 0 { Some(*w) } else { None });
            assert_eq!(g.node_count(), filtered.node_count());
            assert!(is_isomorphic(&filtered, &g));
        }
        true
    }
    quickcheck::quickcheck(prop as fn(Graph<_, _, Directed>) -> bool);
    quickcheck::quickcheck(prop as fn(Graph<_, _, Undirected>) -> bool);
}

#[test]
fn graph_remove_edge() {
    fn prop<Ty: EdgeType>(mut g: Graph<(), (), Ty>, a: u8, b: u8) -> bool {
        let a = node_index(a as usize);
        let b = node_index(b as usize);
        let edge = g.find_edge(a, b);
        if !g.is_directed() {
            assert_eq!(edge.is_some(), g.find_edge(b, a).is_some());
        }
        if let Some(ex) = edge {
            assert!(g.remove_edge(ex).is_some());
        }
        assert_graph_consistent(&g);
        assert!(g.find_edge(a, b).is_none());
        assert!(g.neighbors(a).find(|x| *x == b).is_none());
        if !g.is_directed() {
            assert!(g.neighbors(b).find(|x| *x == a).is_none());
        }
        true
    }
    quickcheck::quickcheck(prop as fn(Graph<_, _, Undirected>, _, _) -> bool);
    quickcheck::quickcheck(prop as fn(Graph<_, _, Directed>, _, _) -> bool);
}

#[test]
fn graphmap_remove() {
    fn prop(mut g: GraphMap<i8, ()>, a: i8, b: i8) -> bool {
        let contains = g.contains_edge(a, b);
        assert_eq!(contains, g.contains_edge(b, a));
        assert_eq!(g.remove_edge(a, b).is_some(), contains);
        assert!(!g.contains_edge(a, b) &&
            g.neighbors(a).find(|x| *x == b).is_none() &&
            g.neighbors(b).find(|x| *x == a).is_none());
        assert!(g.remove_edge(a, b).is_none());
        true
    }
    quickcheck::quickcheck(prop as fn(_, _, _) -> bool);
}

#[test]
fn graphmap_add_remove() {
    fn prop(mut g: GraphMap<i8, ()>, a: i8, b: i8) -> bool {
        assert_eq!(g.contains_edge(a, b), g.add_edge(a, b, ()).is_some());
        g.remove_edge(a, b);
        !g.contains_edge(a, b) &&
            g.neighbors(a).find(|x| *x == b).is_none() &&
            g.neighbors(b).find(|x| *x == a).is_none()
    }
    quickcheck::quickcheck(prop as fn(_, _, _) -> bool);
}
<|endoftext|>


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

extern crate devicemapper;
extern crate env_logger;
extern crate libstratis;
extern crate log;
extern crate serde_json;

mod util;

use std::fs::OpenOptions;
use std::path::{Path, PathBuf};

use serde_json::{Value, from_reader};

use self::devicemapper::{Bytes, Sectors};

use libstratis::engine::IEC;
use libstratis::engine::strat_engine::device::wipe_sectors;

use util::logger::init_logger;
use util::simple_tests::test_basic_metadata;
use util::simple_tests::test_empty_pool;
use util::simple_tests::test_force_flag_dirty;
use util::simple_tests::test_force_flag_stratis;
use util::simple_tests::test_linear_device;
use util::simple_tests::test_pool_blockdevs;
use util::simple_tests::test_setup;
use util::simple_tests::test_teardown;
use util::simple_tests::test_thinpool_device;

pub struct RealTestDev {
    path: PathBuf,
}

impl RealTestDev {
    /// Construct a new test device
    pub fn new(path: &str) -> RealTestDev {
        let dev_path = PathBuf::from(path);
        wipe_sectors(dev_path.as_path(), Sectors(0), Bytes(IEC::Mi).sectors()).unwrap();
        RealTestDev { path: dev_path }
    }

    fn as_path(&self) -> &Path {
        &self.path.as_path()
    }
}

impl Drop for RealTestDev {
    fn drop(&mut self) {
        wipe_sectors(self.as_path(), Sectors(0), Bytes(IEC::Mi).sectors()).unwrap();
    }
}

/// Set up count devices from configuration file.
/// Wipe first MiB on each device.
fn get_devices(count: u8) -> Option<Vec<RealTestDev>> {

    let file = OpenOptions::new()
        .read(true)
        .open("tests/test_config.json")
        .unwrap();
    let config: Value = from_reader(&file).unwrap();
    let devpaths = config
        .get("ok_to_destroy_dev_array_key")
        .unwrap()
        .as_array()
        .unwrap();
    if devpaths.len() < count as usize {
        return None;
    }
    let devices: Vec<RealTestDev> = devpaths
        .iter()
        .take(count as usize)
        .map(|x| RealTestDev::new(x.as_str().unwrap()))
        .collect();

    Some(devices)
}

/// Run test on count real devices.
fn test_with_spec<F>(count: u8, test: F) -> ()
    where F: Fn(&[&Path]) -> ()
{
    init_logger();
    let devices = get_devices(count).unwrap();
    let device_paths: Vec<&Path> = devices.iter().map(|x| x.as_path()).collect();
    test(&device_paths);
}

#[test]
pub fn real_test_force_flag_stratis() {
    test_with_spec(2, test_force_flag_stratis);
    test_with_spec(3, test_force_flag_stratis);
}

#[test]
pub fn real_test_linear_device() {
    test_with_spec(2, test_linear_device);
    test_with_spec(3, test_linear_device);
}

#[test]
pub fn real_test_thinpool_device() {
    test_with_spec(3, test_thinpool_device);
}

#[test]
pub fn real_test_pool_blockdevs() {
    test_with_spec(3, test_pool_blockdevs);
}

#[test]
pub fn real_test_force_flag_dirty() {
    test_with_spec(3, test_force_flag_dirty);
}

#[test]
pub fn real_test_teardown() {
    test_with_spec(2, test_teardown);
}

#[test]
pub fn real_test_setup() {
    test_with_spec(4, test_setup);
}

#[test]
pub fn real_test_empty_pool() {
    test_with_spec(0, test_empty_pool)
}

#[test]
pub fn real_test_basic_metadata() {
    test_with_spec(4, test_basic_metadata);
}
<commit_msg>Make some use of the expanded argument type in wipe_sectors<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

extern crate devicemapper;
extern crate env_logger;
extern crate libstratis;
extern crate log;
extern crate serde_json;

mod util;

use std::fs::OpenOptions;
use std::path::{Path, PathBuf};

use serde_json::{Value, from_reader};

use self::devicemapper::{Bytes, Sectors};

use libstratis::engine::IEC;
use libstratis::engine::strat_engine::device::wipe_sectors;

use util::logger::init_logger;
use util::simple_tests::test_basic_metadata;
use util::simple_tests::test_empty_pool;
use util::simple_tests::test_force_flag_dirty;
use util::simple_tests::test_force_flag_stratis;
use util::simple_tests::test_linear_device;
use util::simple_tests::test_pool_blockdevs;
use util::simple_tests::test_setup;
use util::simple_tests::test_teardown;
use util::simple_tests::test_thinpool_device;

pub struct RealTestDev {
    path: PathBuf,
}

impl RealTestDev {
    /// Construct a new test device
    pub fn new(path: &str) -> RealTestDev {
        wipe_sectors(path, Sectors(0), Bytes(IEC::Mi).sectors()).unwrap();
        RealTestDev { path: PathBuf::from(path) }
    }

    fn as_path(&self) -> &Path {
        &self.path.as_path()
    }
}

impl Drop for RealTestDev {
    fn drop(&mut self) {
        wipe_sectors(&self.path, Sectors(0), Bytes(IEC::Mi).sectors()).unwrap();
    }
}

/// Set up count devices from configuration file.
/// Wipe first MiB on each device.
fn get_devices(count: u8) -> Option<Vec<RealTestDev>> {

    let file = OpenOptions::new()
        .read(true)
        .open("tests/test_config.json")
        .unwrap();
    let config: Value = from_reader(&file).unwrap();
    let devpaths = config
        .get("ok_to_destroy_dev_array_key")
        .unwrap()
        .as_array()
        .unwrap();
    if devpaths.len() < count as usize {
        return None;
    }
    let devices: Vec<RealTestDev> = devpaths
        .iter()
        .take(count as usize)
        .map(|x| RealTestDev::new(x.as_str().unwrap()))
        .collect();

    Some(devices)
}

/// Run test on count real devices.
fn test_with_spec<F>(count: u8, test: F) -> ()
    where F: Fn(&[&Path]) -> ()
{
    init_logger();
    let devices = get_devices(count).unwrap();
    let device_paths: Vec<&Path> = devices.iter().map(|x| x.as_path()).collect();
    test(&device_paths);
}

#[test]
pub fn real_test_force_flag_stratis() {
    test_with_spec(2, test_force_flag_stratis);
    test_with_spec(3, test_force_flag_stratis);
}

#[test]
pub fn real_test_linear_device() {
    test_with_spec(2, test_linear_device);
    test_with_spec(3, test_linear_device);
}

#[test]
pub fn real_test_thinpool_device() {
    test_with_spec(3, test_thinpool_device);
}

#[test]
pub fn real_test_pool_blockdevs() {
    test_with_spec(3, test_pool_blockdevs);
}

#[test]
pub fn real_test_force_flag_dirty() {
    test_with_spec(3, test_force_flag_dirty);
}

#[test]
pub fn real_test_teardown() {
    test_with_spec(2, test_teardown);
}

#[test]
pub fn real_test_setup() {
    test_with_spec(4, test_setup);
}

#[test]
pub fn real_test_empty_pool() {
    test_with_spec(0, test_empty_pool)
}

#[test]
pub fn real_test_basic_metadata() {
    test_with_spec(4, test_basic_metadata);
}
<|endoftext|>


<commit_before>use clap::{Arg, App};
use std::path::Path;
use std::ffi::OsStr;
use regex::Regex;

use inkwell::memory_buffer::MemoryBuffer;
use inkwell::context::Context;
use inkwell::module::Module;
use inkwell::module::Linkage;
use inkwell::values::{FunctionValue, GlobalValue, PointerValue};
use inkwell::values::{AnyValue, BasicValueEnum};
use inkwell::types::{FunctionType};

fn main() {
    // Command line argument parsing (using clap)
    let matches = App::new("Test inkwell")
        // .version("0.1.0")
        // .author("")
        // .about("")
        .arg(Arg::with_name("INPUT")
             .help("Input file name")
             .required(true)
             .index(1))
        .arg(Arg::with_name("OUTPUT")
             .help("Output file name")
             .short("o")
             .long("output")
             .takes_value(true)
             .default_value("out"))
        .get_matches();

    let path_in  = matches.value_of("INPUT")
        .expect("ERROR: missing input file name argument.");
    let path_in  = Path::new(path_in);

    let path_out = matches.value_of("OUTPUT")
        .expect("ERROR: missing output file name argument.");
    let path_out = Path::new(path_out);

    // Read the input file
    let memory_buffer = MemoryBuffer::create_from_file(path_in)
        .expect("ERROR: failed to open file.");

    let context = Context::create();
    let mut module = context.create_module_from_ir(memory_buffer)
        .expect("ERROR: failed to create module.");

    handle_initializers(&context, &mut module);

    handle_main(&module);

    handle_panic(&module);

    replace_def_with_dec(&module, &Regex::new(r"^_ZN3std2io5stdio7_eprint17h[a-f0-9]{16}E$").unwrap());
    replace_def_with_dec(&module, &Regex::new(r"^_ZN3std2io5stdio6_print17h[a-f0-9]{16}E$").unwrap());

    // Write output file
    if path_out.extension() == Some(OsStr::new("bc")) {
        // output bitcode
        // TODO: this function returns bool but the doc doesn't say anything about it.
        module.write_bitcode_to_path(path_out);
    } else {
        // output disassembled bitcode
        module.print_to_file(path_out)
            .expect("ERROR: failed to write to file.");
    }
}

////////////////////////////////////////////////////////////////
// Transformations associated with initializers
////////////////////////////////////////////////////////////////

fn handle_initializers(context: &Context, module: &mut Module) {
    let _ = collect_initializers(context, module, ".init_array", "my_initializer");
}

/// Collect all the initializers in a section (whose name starts with 'prefix')
/// into a single function that calls all the initializers.
fn collect_initializers<'a>(context: &Context, module: &mut Module<'a>, prefix: &str, nm: &str) -> Option<FunctionValue<'a>> {
    let vs = collect_variables_in_section(module, prefix);
    // println!("Global name: {} initializer: {:?}", v.get_name().to_str().unwrap(), fp);

    let fps : Vec<PointerValue> = vs.iter().map(get_initializer_function).collect();

    if ! fps.is_empty() {
        let fp = fps[0];

        // dereference the pointer type
        let fp_type = fp.get_type().get_element_type().into_function_type();
        println!("type {:?}", fp_type);

        Some(build_fanout(context, module, nm, fp_type, fps))
    } else {
        None
    }
}

/// Collect variables that are assigned to a section whose name matches prefix
fn collect_variables_in_section<'a>(module: &Module<'a>, prefix: &str) -> Vec<GlobalValue<'a>> {
    let mut vs = Vec::new();
    // todo: should implement an iterator for global values so that the following loop
    // becomes just iter().filter_map().filter_map().filter()
    let mut og = module.get_first_global();
    while let Some(g) = og {
        if let Some(s) = g.get_section() {
            if let Ok(s) = s.to_str() {
                if s.starts_with(prefix) {
                    vs.push(g)
                }
            }
        }
        og = g.get_next_global();
    }
    vs
}

/// Convert the contents of an initializer section to a function pointer.
///
/// Initializer sections contain structs where the first field is a function pointer cast to
/// some other type.
fn get_initializer_function<'a>(v: &GlobalValue<'a>) -> PointerValue<'a> {
        let i = v.get_initializer().unwrap().into_struct_value();
        assert!(i.get_num_operands() == 2); // expecting two fields in struct
        let i = i.get_operand(0).unwrap();
        assert!(i.get_num_operands() == 1); // expecting bitcast
        let fp = i.get_operand(0).unwrap();
        fp.into_pointer_value()
}

/// Given a list of functions of type 'ty', build a function that calls each function in order
///
/// Assumes (without checking) that return type is void
///
///     define void @fanout(i32 %0, i32 %1) {
///     entry:
///       call void @f1(i32 %0, i32 %1)
///       call void @f2(i32 %0, i32 %1)
///       call void @f3(i32 %0, i32 %1)
///       ret void
///     }
///
fn build_fanout<'a>(context: &Context, module: &mut Module<'a>, nm: &str, ty: FunctionType<'a>, fps: Vec<PointerValue<'a>>) -> FunctionValue<'a> {
    let function = module.add_function(nm, ty, None);
    let args : Vec<BasicValueEnum> = (0 .. function.count_params()).map(|i| function.get_nth_param(i).unwrap()).collect();
    let basic_block = context.append_basic_block(function, "entry");
    let builder = context.create_builder();
    builder.position_at_end(basic_block);

    for fp in fps {
        builder.build_call(fp, &args, "");
        builder.build_return(None);
        println!("Built function {:?}", function)
    }

    function
}

////////////////////////////////////////////////////////////////
// Transformations associated with SeaHorn
////////////////////////////////////////////////////////////////

fn handle_main(module: &Module) {
    // Remove the main function rustc generates.
    if let Some(main) = module.get_function("main") {
        unsafe { main.delete(); }
    }

    // Change the linkage of mangled main function from internal to external.
    if let Some(main) = get_function(module, &Regex::new(r"4main17h[a-f0-9]{16}E$").unwrap()) {
        // main.set_linkage(Linkage::External);
        println!("MAIN: {}", main.get_name().to_str().unwrap());
    }
}

fn get_function<'ctx>(module: &'ctx Module, re: &Regex) -> Option<FunctionValue<'ctx>> {
    let mut op_fun = module.get_first_function();
    while let Some(fun) = op_fun {
        if re.is_match(fun.get_name().to_str()
                       .expect("ERROR: function name is not in valid UTF-8")) {
            return Some(fun);
        }
        op_fun = fun.get_next_function();
    }
    None
}

fn handle_panic(module: &Module) {
    // TODO: make "spanic" a CL arg.
    if let Some(spanic) = module.get_function("spanic") {
        if let Some(unwind) = module.get_function("rust_begin_unwind") {
            unwind.replace_all_uses_with(spanic);
        }
    }
}

fn replace_def_with_dec(module: &Module, re: &Regex) {
    if let Some(fun) = get_function(module, re) {
        for bb in fun.get_basic_blocks() {
            unsafe { bb.delete().unwrap(); }
        }
        fun.remove_personality_function();
        fun.set_linkage(Linkage::External);
    }
}

////////////////////////////////////////////////////////////////
// End
////////////////////////////////////////////////////////////////
<commit_msg>Add -i and -s flags to control transforms<commit_after>use clap::{Arg, App};
use std::path::Path;
use std::ffi::OsStr;
use regex::Regex;

use inkwell::memory_buffer::MemoryBuffer;
use inkwell::context::Context;
use inkwell::module::Module;
use inkwell::module::Linkage;
use inkwell::values::{FunctionValue, GlobalValue, PointerValue};
use inkwell::values::{AnyValue, BasicValueEnum};
use inkwell::types::{FunctionType};

fn main() {
    // Command line argument parsing (using clap)
    let matches = App::new("Test inkwell")
        // .version("0.1.0")
        // .author("")
        // .about("")
        .arg(Arg::with_name("initializers")
             .short("i")
             .help("Call initializers from main"))
        .arg(Arg::with_name("seahorn")
             .short("s")
             .help("SeaHorn preparation (conflicts with --initializers)"))
        .arg(Arg::with_name("INPUT")
             .help("Input file name")
             .required(true)
             .index(1))
        .arg(Arg::with_name("OUTPUT")
             .help("Output file name")
             .short("o")
             .long("output")
             .takes_value(true)
             .default_value("out"))
        .get_matches();

    let path_in  = matches.value_of("INPUT")
        .expect("ERROR: missing input file name argument.");
    let path_in  = Path::new(path_in);

    let path_out = matches.value_of("OUTPUT")
        .expect("ERROR: missing output file name argument.");
    let path_out = Path::new(path_out);

    // Read the input file
    let memory_buffer = MemoryBuffer::create_from_file(path_in)
        .expect("ERROR: failed to open file.");

    let context = Context::create();
    let mut module = context.create_module_from_ir(memory_buffer)
        .expect("ERROR: failed to create module.");

    if matches.is_present("initializers") {
        handle_initializers(&context, &mut module);
    }

    if matches.is_present("seahorn") {
        handle_main(&module);

        handle_panic(&module);

        replace_def_with_dec(&module, &Regex::new(r"^_ZN3std2io5stdio7_eprint17h[a-f0-9]{16}E$").unwrap());
        replace_def_with_dec(&module, &Regex::new(r"^_ZN3std2io5stdio6_print17h[a-f0-9]{16}E$").unwrap());
    }

    // Write output file
    if path_out.extension() == Some(OsStr::new("bc")) {
        // output bitcode
        // TODO: this function returns bool but the doc doesn't say anything about it.
        module.write_bitcode_to_path(path_out);
    } else {
        // output disassembled bitcode
        module.print_to_file(path_out)
            .expect("ERROR: failed to write to file.");
    }
}

////////////////////////////////////////////////////////////////
// Transformations associated with initializers
////////////////////////////////////////////////////////////////

fn handle_initializers(context: &Context, module: &mut Module) {
    let _ = collect_initializers(context, module, ".init_array", "my_initializer");
}

/// Collect all the initializers in a section (whose name starts with 'prefix')
/// into a single function that calls all the initializers.
fn collect_initializers<'a>(context: &Context, module: &mut Module<'a>, prefix: &str, nm: &str) -> Option<FunctionValue<'a>> {
    let vs = collect_variables_in_section(module, prefix);
    // println!("Global name: {} initializer: {:?}", v.get_name().to_str().unwrap(), fp);

    let fps : Vec<PointerValue> = vs.iter().map(get_initializer_function).collect();

    if ! fps.is_empty() {
        let fp = fps[0];

        // dereference the pointer type
        let fp_type = fp.get_type().get_element_type().into_function_type();
        println!("type {:?}", fp_type);

        Some(build_fanout(context, module, nm, fp_type, fps))
    } else {
        None
    }
}

/// Collect variables that are assigned to a section whose name matches prefix
fn collect_variables_in_section<'a>(module: &Module<'a>, prefix: &str) -> Vec<GlobalValue<'a>> {
    let mut vs = Vec::new();
    // todo: should implement an iterator for global values so that the following loop
    // becomes just iter().filter_map().filter_map().filter()
    let mut og = module.get_first_global();
    while let Some(g) = og {
        if let Some(s) = g.get_section() {
            if let Ok(s) = s.to_str() {
                if s.starts_with(prefix) {
                    vs.push(g)
                }
            }
        }
        og = g.get_next_global();
    }
    vs
}

/// Convert the contents of an initializer section to a function pointer.
///
/// Initializer sections contain structs where the first field is a function pointer cast to
/// some other type.
fn get_initializer_function<'a>(v: &GlobalValue<'a>) -> PointerValue<'a> {
        let i = v.get_initializer().unwrap().into_struct_value();
        assert!(i.get_num_operands() == 2); // expecting two fields in struct
        let i = i.get_operand(0).unwrap();
        assert!(i.get_num_operands() == 1); // expecting bitcast
        let fp = i.get_operand(0).unwrap();
        fp.into_pointer_value()
}

/// Given a list of functions of type 'ty', build a function that calls each function in order
///
/// Assumes (without checking) that return type is void
///
///     define void @fanout(i32 %0, i32 %1) {
///     entry:
///       call void @f1(i32 %0, i32 %1)
///       call void @f2(i32 %0, i32 %1)
///       call void @f3(i32 %0, i32 %1)
///       ret void
///     }
///
fn build_fanout<'a>(context: &Context, module: &mut Module<'a>, nm: &str, ty: FunctionType<'a>, fps: Vec<PointerValue<'a>>) -> FunctionValue<'a> {
    let function = module.add_function(nm, ty, None);
    let args : Vec<BasicValueEnum> = (0 .. function.count_params()).map(|i| function.get_nth_param(i).unwrap()).collect();
    let basic_block = context.append_basic_block(function, "entry");
    let builder = context.create_builder();
    builder.position_at_end(basic_block);

    for fp in fps {
        builder.build_call(fp, &args, "");
        builder.build_return(None);
        println!("Built function {:?}", function)
    }

    function
}

////////////////////////////////////////////////////////////////
// Transformations associated with SeaHorn
////////////////////////////////////////////////////////////////

fn handle_main(module: &Module) {
    // Remove the main function rustc generates.
    if let Some(main) = module.get_function("main") {
        unsafe { main.delete(); }
    }

    // Change the linkage of mangled main function from internal to external.
    if let Some(main) = get_function(module, &Regex::new(r"4main17h[a-f0-9]{16}E$").unwrap()) {
        // main.set_linkage(Linkage::External);
        println!("MAIN: {}", main.get_name().to_str().unwrap());
    }
}

fn get_function<'ctx>(module: &'ctx Module, re: &Regex) -> Option<FunctionValue<'ctx>> {
    let mut op_fun = module.get_first_function();
    while let Some(fun) = op_fun {
        if re.is_match(fun.get_name().to_str()
                       .expect("ERROR: function name is not in valid UTF-8")) {
            return Some(fun);
        }
        op_fun = fun.get_next_function();
    }
    None
}

fn handle_panic(module: &Module) {
    // TODO: make "spanic" a CL arg.
    if let Some(spanic) = module.get_function("spanic") {
        if let Some(unwind) = module.get_function("rust_begin_unwind") {
            unwind.replace_all_uses_with(spanic);
        }
    }
}

fn replace_def_with_dec(module: &Module, re: &Regex) {
    if let Some(fun) = get_function(module, re) {
        for bb in fun.get_basic_blocks() {
            unsafe { bb.delete().unwrap(); }
        }
        fun.remove_personality_function();
        fun.set_linkage(Linkage::External);
    }
}

////////////////////////////////////////////////////////////////
// End
////////////////////////////////////////////////////////////////
<|endoftext|>


<commit_before>extern crate regex;

use self::regex::Regex;

pub fn day_04(s: String) {
    for line in s.lines() {
        parse_line(line);
    }
}

fn parse_line(s: &str) {
    let re = Regex::new(
        r"\[(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2}) (?P<hour>\d{2}):(?P<minute>\d{2})\]"
    ).unwrap();
    let caps = re.captures(s).unwrap();
    println!("{:?}", caps);
}

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

    #[test]
    fn frequency_works() {
        assert_eq!(1, 1);
    }

}
<commit_msg>Parse timestamps into ISO8601<commit_after>extern crate regex;

use self::regex::Regex;

pub fn day_04(s: String) {
    let mut v = vec![];
    for line in s.lines() {
        v.push(parse_line(line));
    }
    v.sort();
    println!("{:?}", v);
}

fn parse_line(s: &str) -> String {
    let re = Regex::new(
        r"\[(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2}) (?P<hour>\d{2}):(?P<minute>\d{2})\]"
    ).unwrap();
    let caps = re.captures(s).unwrap();
    //println!("{:?}", caps);
    let iso8601 = format!(
        "{}-{:02}-{:02}T{:02}:{:02}:00Z",
        &caps["year"],
        &caps["month"],
        &caps["day"],
        &caps["hour"],
        &caps["minute"],
    );
    //println!("{}", iso8601);
    iso8601
}

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

    #[test]
    fn frequency_works() {
        assert_eq!(1, 1);
    }

}
<|endoftext|>


<commit_before>fn main() {
    let numbers = vec![1, 3, 2, 5, 0];

    let mut largest = numbers[0];

    for number in numbers {
        if number > largest {
            largest = number;
        }
    }

    println!("The largest number is {}", largest);
}
<commit_msg>Refactor to function<commit_after>fn largest(list: &[i32]) -> i32 {
    let mut largest = list[0];

    for &item in list.iter() {
        if item > largest {
            largest = item;
        }
    }

    largest
}

fn main() {
    let numbers = vec![1, 3, 2, 5, 0];

    let result = largest(&numbers);

    println!("The largest number is {}", result);
}
<|endoftext|>


<commit_before>use super::One;
use rect::Rect;
use std::ops::{Add, Sub, Mul};
use std::cmp::{Ord};

pub trait Position2D<T> {
    fn x(&self) -> T;
    fn y(&self) -> T;

    fn x_mut(&mut self) -> &mut T;
    fn y_mut(&mut self) -> &mut T;
}

#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct Point<T> {
    x: T,
    y: T
}

impl<T> Point<T> {
    pub fn new(x: T, y: T) -> Point<T> {
        Point::<T> { x: x, y: y }
    }
}

impl<T> Default for Point<T>
    where T: Default
{
    fn default() -> Point<T> {
        Point::<T>::new(T::default(), T::default())
    }
}

impl<T> Point<T>
    where T: Add<i32, Output=T> +
             Add<T, Output=T> +
             Sub<T, Output=T> +
             Mul<T, Output=T> +
             Ord + One<T> + Default + Copy + Clone
{
    pub fn rect(self, other: Point<T>) -> Rect<T> {
        Rect::from_points(self, other)
    }
}

impl<T> Position2D<T> for Point<T>
    where T: Copy + Clone
{
    fn x(&self) -> T {
        self.x
    }

    fn y(&self) -> T {
        self.y
    }

    fn x_mut(&mut self) -> &mut T {
        &mut self.x
    }

    fn y_mut(&mut self) -> &mut T {
        &mut self.y
    }
}

impl<T> Add<Point<T>> for Point<T>
    where Point<T>: Position2D<T>,
          T: Add<T, Output=T>
{
    type Output = Point<T>;
    fn add(self, other: Point<T>) -> Point<T> {
        Point::<T>::new(self.x() + other.x(), self.y() + other.y())
    }
}

impl<T> Add<T> for Point<T>
    where Point<T>: Position2D<T>,
          T: Add<T, Output=T> + Clone + Copy
{
    type Output = Point<T>;
    fn add(self, other: T) -> Point<T> {
        Point::<T>::new(self.x() + other, self.y() + other)
    }
}

impl<T> Sub<Point<T>> for Point<T>
    where Point<T>: Position2D<T>,
          T: Sub<T, Output=T>
{
    type Output = Point<T>;
    fn sub(self, other: Point<T>) -> Point<T> {
        Point::<T>::new(self.x() - other.x(), self.y() - other.y())
    }
}

impl<T> Sub<T> for Point<T>
    where Point<T>: Position2D<T>,
          T: Sub<T, Output=T> + Clone + Copy
{
    type Output = Point<T>;
    fn sub(self, other: T) -> Point<T> {
        Point::<T>::new(self.x() - other, self.y() - other)
    }
}
<commit_msg>Update point module documentation<commit_after>use super::One;
use rect::Rect;
use std::ops::{Add, Sub, Mul};
use std::cmp::{Ord};

/// A type with `x` and `y` coordinates.
pub trait Position2D<T> {
    /// Returns a copy of the `x` coordinate of the position.
    fn x(&self) -> T;

    /// Returns a copy of the `y` coordinate of the position.
    fn y(&self) -> T;

    /// Returns a mutable reference to the `x` coordinate of the position.
    fn x_mut(&mut self) -> &mut T;

    /// Returns a mutable reference to the `y` coordinate of the position.
    fn y_mut(&mut self) -> &mut T;
}

/// A generic two-dimensional point structure.
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct Point<T> {
    x: T,
    y: T
}

impl<T> Point<T> {
    /// Returns a new `Point` with the given `x` and `y` coordinates.
    pub fn new(x: T, y: T) -> Point<T> {
        Point::<T> { x: x, y: y }
    }
}

impl<T> Default for Point<T>
    where T: Default
{
    /// Returns a new `Point` with the `x` and `y` coordinates being that of the default value of `T`.
    fn default() -> Point<T> {
        Point::<T>::new(T::default(), T::default())
    }
}

impl<T> Point<T>
    where T: Add<i32, Output=T> +
             Add<T, Output=T> +
             Sub<T, Output=T> +
             Mul<T, Output=T> +
             Ord + One<T> + Default + Copy + Clone
{
    /// Returns a new `Rect` with the top-left point being the value of `self`
    /// and the bottom-right point being the value of `other`.
    pub fn rect(self, other: Point<T>) -> Rect<T> {
        Rect::from_points(self, other)
    }
}

impl<T> Position2D<T> for Point<T>
    where T: Copy + Clone
{
    /// Returns a copy of the `x` coordinate of the point.
    fn x(&self) -> T {
        self.x
    }

    /// Returns a copy of the `y` coordinate of the point.
    fn y(&self) -> T {
        self.y
    }

    /// Returns a mutable reference to the `x` coordinate of the point.
    fn x_mut(&mut self) -> &mut T {
        &mut self.x
    }

    /// Returns a mutable reference to the `x` coordinate of the point.
    fn y_mut(&mut self) -> &mut T {
        &mut self.y
    }
}

impl<T> Add<Point<T>> for Point<T>
    where Point<T>: Position2D<T>,
          T: Add<T, Output=T>
{
    type Output = Point<T>;
    fn add(self, other: Point<T>) -> Point<T> {
        Point::<T>::new(self.x() + other.x(), self.y() + other.y())
    }
}

impl<T> Add<T> for Point<T>
    where Point<T>: Position2D<T>,
          T: Add<T, Output=T> + Clone + Copy
{
    type Output = Point<T>;
    fn add(self, other: T) -> Point<T> {
        Point::<T>::new(self.x() + other, self.y() + other)
    }
}

impl<T> Sub<Point<T>> for Point<T>
    where Point<T>: Position2D<T>,
          T: Sub<T, Output=T>
{
    type Output = Point<T>;
    fn sub(self, other: Point<T>) -> Point<T> {
        Point::<T>::new(self.x() - other.x(), self.y() - other.y())
    }
}

impl<T> Sub<T> for Point<T>
    where Point<T>: Position2D<T>,
          T: Sub<T, Output=T> + Clone + Copy
{
    type Output = Point<T>;
    fn sub(self, other: T) -> Point<T> {
        Point::<T>::new(self.x() - other, self.y() - other)
    }
}
<|endoftext|>