<commit_before>//! Traits dealing with SQLite data types.
//!
//! SQLite uses a [dynamic type system](https://www.sqlite.org/datatype3.html). Implementations of
//! the `ToSql` and `FromSql` traits are provided for the basic types that SQLite provides methods
//! for:
//!
//! * Integers (`i32` and `i64`; SQLite uses `i64` internally, so getting an `i32` will truncate
//!   if the value is too large or too small).
//! * Reals (`f64`)
//! * Strings (`String` and `&str`)
//! * Blobs (`Vec<u8>` and `&[u8]`)
//!
//! Additionally, because it is such a common data type, implementations are provided for
//! `time::Timespec` that use a string for storage (using the same format string,
//! `"%Y-%m-%d %H:%M:%S"`, as SQLite's builtin
//! [datetime](https://www.sqlite.org/lang_datefunc.html) function.  Note that this storage
//! truncates timespecs to the nearest second. If you want different storage for timespecs, you can
//! use a newtype. For example, to store timespecs as `f64`s:
//!
//! ```rust,ignore
//! extern crate rusqlite;
//! extern crate libc;
//!
//! use rusqlite::types::{FromSql, ToSql, sqlite3_stmt};
//! use rusqlite::{Result};
//! use libc::c_int;
//! use time;
//!
//! pub struct TimespecSql(pub time::Timespec);
//!
//! impl FromSql for TimespecSql {
//!     fn column_result(value: ValueRef) -> Result<Self> {
//!         f64::column_result(value).map(|as_f64| {
//!             TimespecSql(time::Timespec{ sec: as_f64.trunc() as i64,
//!                                         nsec: (as_f64.fract() * 1.0e9) as i32 })
//!         })
//!     }
//! }
//!
//! impl ToSql for TimespecSql {
//!     unsafe fn bind_parameter(&self, stmt: *mut sqlite3_stmt, col: c_int) -> c_int {
//!         let TimespecSql(ts) = *self;
//!         let as_f64 = ts.sec as f64 + (ts.nsec as f64) / 1.0e9;
//!         as_f64.bind_parameter(stmt, col)
//!     }
//! }
//! ```
//!
//! `ToSql` and `FromSql` are also implemented for `Option<T>` where `T` implements `ToSql` or
//! `FromSql` for the cases where you want to know if a value was NULL (which gets translated to
//! `None`).

pub use ffi::sqlite3_stmt;

pub use self::from_sql::FromSql;
pub use self::to_sql::ToSql;
pub use self::value_ref::ValueRef;

mod value_ref;
mod from_sql;
mod to_sql;
mod time;
#[cfg(feature = "chrono")]
mod chrono;
#[cfg(feature = "serde_json")]
mod serde_json;

/// Empty struct that can be used to fill in a query parameter as `NULL`.
///
/// ## Example
///
/// ```rust,no_run
/// # extern crate libc;
/// # extern crate rusqlite;
/// # use rusqlite::{Connection, Result};
/// # use rusqlite::types::{Null};
/// # use libc::{c_int};
/// fn main() {
/// }
/// fn insert_null(conn: &Connection) -> Result<c_int> {
///     conn.execute("INSERT INTO people (name) VALUES (?)", &[&Null])
/// }
/// ```
#[derive(Copy,Clone)]
pub struct Null;

/// Owning [dynamic type value](http://sqlite.org/datatype3.html). Value's type is typically
/// dictated by SQLite (not by the caller).
///
/// See [`ValueRef`](enum.ValueRef.html) for a non-owning dynamic type value.
#[derive(Clone,Debug,PartialEq)]
pub enum Value {
    /// The value is a `NULL` value.
    Null,
    /// The value is a signed integer.
    Integer(i64),
    /// The value is a floating point number.
    Real(f64),
    /// The value is a text string.
    Text(String),
    /// The value is a blob of data
    Blob(Vec<u8>),
}

#[cfg(test)]
#[cfg_attr(feature="clippy", allow(similar_names))]
mod test {
    extern crate time;

    use Connection;
    use Error;
    use libc::{c_int, c_double};
    use std::f64::EPSILON;

    fn checked_memory_handle() -> Connection {
        let db = Connection::open_in_memory().unwrap();
        db.execute_batch("CREATE TABLE foo (b BLOB, t TEXT, i INTEGER, f FLOAT, n)").unwrap();
        db
    }

    #[test]
    fn test_blob() {
        let db = checked_memory_handle();

        let v1234 = vec![1u8, 2, 3, 4];
        db.execute("INSERT INTO foo(b) VALUES (?)", &[&v1234]).unwrap();

        let v: Vec<u8> = db.query_row("SELECT b FROM foo", &[], |r| r.get(0)).unwrap();
        assert_eq!(v, v1234);
    }

    #[test]
    fn test_str() {
        let db = checked_memory_handle();

        let s = "hello, world!";
        db.execute("INSERT INTO foo(t) VALUES (?)", &[&s.to_owned()]).unwrap();

        let from: String = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
        assert_eq!(from, s);
    }

    #[test]
    fn test_option() {
        let db = checked_memory_handle();

        let s = Some("hello, world!");
        let b = Some(vec![1u8, 2, 3, 4]);

        db.execute("INSERT INTO foo(t) VALUES (?)", &[&s]).unwrap();
        db.execute("INSERT INTO foo(b) VALUES (?)", &[&b]).unwrap();

        let mut stmt = db.prepare("SELECT t, b FROM foo ORDER BY ROWID ASC").unwrap();
        let mut rows = stmt.query(&[]).unwrap();

        {
            let row1 = rows.next().unwrap().unwrap();
            let s1: Option<String> = row1.get(0);
            let b1: Option<Vec<u8>> = row1.get(1);
            assert_eq!(s.unwrap(), s1.unwrap());
            assert!(b1.is_none());
        }

        {
            let row2 = rows.next().unwrap().unwrap();
            let s2: Option<String> = row2.get(0);
            let b2: Option<Vec<u8>> = row2.get(1);
            assert!(s2.is_none());
            assert_eq!(b, b2);
        }
    }

    #[test]
    #[cfg_attr(feature="clippy", allow(cyclomatic_complexity))]
    fn test_mismatched_types() {
        fn is_invalid_column_type(err: Error) -> bool {
            match err {
                Error::InvalidColumnType => true,
                _ => false,
            }
        }

        let db = checked_memory_handle();

        db.execute("INSERT INTO foo(b, t, i, f) VALUES (X'0102', 'text', 1, 1.5)",
                     &[])
            .unwrap();

        let mut stmt = db.prepare("SELECT b, t, i, f, n FROM foo").unwrap();
        let mut rows = stmt.query(&[]).unwrap();

        let row = rows.next().unwrap().unwrap();

        // check the correct types come back as expected
        assert_eq!(vec![1, 2], row.get_checked::<i32, Vec<u8>>(0).unwrap());
        assert_eq!("text", row.get_checked::<i32, String>(1).unwrap());
        assert_eq!(1, row.get_checked::<i32, c_int>(2).unwrap());
        assert!((1.5 - row.get_checked::<i32, c_double>(3).unwrap()).abs() < EPSILON);
        assert!(row.get_checked::<i32, Option<c_int>>(4).unwrap().is_none());
        assert!(row.get_checked::<i32, Option<c_double>>(4).unwrap().is_none());
        assert!(row.get_checked::<i32, Option<String>>(4).unwrap().is_none());

        // check some invalid types

        // 0 is actually a blob (Vec<u8>)
        assert!(is_invalid_column_type(row.get_checked::<i32, c_int>(0).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, c_int>(0).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, i64>(0).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, c_double>(0).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, String>(0).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, time::Timespec>(0).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, Option<c_int>>(0).err().unwrap()));

        // 1 is actually a text (String)
        assert!(is_invalid_column_type(row.get_checked::<i32, c_int>(1).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, i64>(1).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, c_double>(1).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, Vec<u8>>(1).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, Option<c_int>>(1).err().unwrap()));

        // 2 is actually an integer
        assert!(is_invalid_column_type(row.get_checked::<i32, String>(2).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, Vec<u8>>(2).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, Option<String>>(2).err().unwrap()));

        // 3 is actually a float (c_double)
        assert!(is_invalid_column_type(row.get_checked::<i32, c_int>(3).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, i64>(3).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, String>(3).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, Vec<u8>>(3).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, Option<c_int>>(3).err().unwrap()));

        // 4 is actually NULL
        assert!(is_invalid_column_type(row.get_checked::<i32, c_int>(4).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, i64>(4).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, c_double>(4).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, String>(4).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, Vec<u8>>(4).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, time::Timespec>(4).err().unwrap()));
    }

    #[test]
    fn test_dynamic_type() {
        use super::Value;
        let db = checked_memory_handle();

        db.execute("INSERT INTO foo(b, t, i, f) VALUES (X'0102', 'text', 1, 1.5)",
                     &[])
            .unwrap();

        let mut stmt = db.prepare("SELECT b, t, i, f, n FROM foo").unwrap();
        let mut rows = stmt.query(&[]).unwrap();

        let row = rows.next().unwrap().unwrap();
        assert_eq!(Value::Blob(vec![1, 2]),
                   row.get_checked::<i32, Value>(0).unwrap());
        assert_eq!(Value::Text(String::from("text")),
                   row.get_checked::<i32, Value>(1).unwrap());
        assert_eq!(Value::Integer(1), row.get_checked::<i32, Value>(2).unwrap());
        match row.get_checked::<i32, Value>(3).unwrap() {
            Value::Real(val) => assert!((1.5 - val).abs() < EPSILON),
            x => panic!("Invalid Value {:?}", x),
        }
        assert_eq!(Value::Null, row.get_checked::<i32, Value>(4).unwrap());
    }
}
<commit_msg>Add test with empty blob (issue #174).<commit_after>//! Traits dealing with SQLite data types.
//!
//! SQLite uses a [dynamic type system](https://www.sqlite.org/datatype3.html). Implementations of
//! the `ToSql` and `FromSql` traits are provided for the basic types that SQLite provides methods
//! for:
//!
//! * Integers (`i32` and `i64`; SQLite uses `i64` internally, so getting an `i32` will truncate
//!   if the value is too large or too small).
//! * Reals (`f64`)
//! * Strings (`String` and `&str`)
//! * Blobs (`Vec<u8>` and `&[u8]`)
//!
//! Additionally, because it is such a common data type, implementations are provided for
//! `time::Timespec` that use a string for storage (using the same format string,
//! `"%Y-%m-%d %H:%M:%S"`, as SQLite's builtin
//! [datetime](https://www.sqlite.org/lang_datefunc.html) function.  Note that this storage
//! truncates timespecs to the nearest second. If you want different storage for timespecs, you can
//! use a newtype. For example, to store timespecs as `f64`s:
//!
//! ```rust,ignore
//! extern crate rusqlite;
//! extern crate libc;
//!
//! use rusqlite::types::{FromSql, ToSql, sqlite3_stmt};
//! use rusqlite::{Result};
//! use libc::c_int;
//! use time;
//!
//! pub struct TimespecSql(pub time::Timespec);
//!
//! impl FromSql for TimespecSql {
//!     fn column_result(value: ValueRef) -> Result<Self> {
//!         f64::column_result(value).map(|as_f64| {
//!             TimespecSql(time::Timespec{ sec: as_f64.trunc() as i64,
//!                                         nsec: (as_f64.fract() * 1.0e9) as i32 })
//!         })
//!     }
//! }
//!
//! impl ToSql for TimespecSql {
//!     unsafe fn bind_parameter(&self, stmt: *mut sqlite3_stmt, col: c_int) -> c_int {
//!         let TimespecSql(ts) = *self;
//!         let as_f64 = ts.sec as f64 + (ts.nsec as f64) / 1.0e9;
//!         as_f64.bind_parameter(stmt, col)
//!     }
//! }
//! ```
//!
//! `ToSql` and `FromSql` are also implemented for `Option<T>` where `T` implements `ToSql` or
//! `FromSql` for the cases where you want to know if a value was NULL (which gets translated to
//! `None`).

pub use ffi::sqlite3_stmt;

pub use self::from_sql::FromSql;
pub use self::to_sql::ToSql;
pub use self::value_ref::ValueRef;

mod value_ref;
mod from_sql;
mod to_sql;
mod time;
#[cfg(feature = "chrono")]
mod chrono;
#[cfg(feature = "serde_json")]
mod serde_json;

/// Empty struct that can be used to fill in a query parameter as `NULL`.
///
/// ## Example
///
/// ```rust,no_run
/// # extern crate libc;
/// # extern crate rusqlite;
/// # use rusqlite::{Connection, Result};
/// # use rusqlite::types::{Null};
/// # use libc::{c_int};
/// fn main() {
/// }
/// fn insert_null(conn: &Connection) -> Result<c_int> {
///     conn.execute("INSERT INTO people (name) VALUES (?)", &[&Null])
/// }
/// ```
#[derive(Copy,Clone)]
pub struct Null;

/// Owning [dynamic type value](http://sqlite.org/datatype3.html). Value's type is typically
/// dictated by SQLite (not by the caller).
///
/// See [`ValueRef`](enum.ValueRef.html) for a non-owning dynamic type value.
#[derive(Clone,Debug,PartialEq)]
pub enum Value {
    /// The value is a `NULL` value.
    Null,
    /// The value is a signed integer.
    Integer(i64),
    /// The value is a floating point number.
    Real(f64),
    /// The value is a text string.
    Text(String),
    /// The value is a blob of data
    Blob(Vec<u8>),
}

#[cfg(test)]
#[cfg_attr(feature="clippy", allow(similar_names))]
mod test {
    extern crate time;

    use Connection;
    use Error;
    use libc::{c_int, c_double};
    use std::f64::EPSILON;

    fn checked_memory_handle() -> Connection {
        let db = Connection::open_in_memory().unwrap();
        db.execute_batch("CREATE TABLE foo (b BLOB, t TEXT, i INTEGER, f FLOAT, n)").unwrap();
        db
    }

    #[test]
    fn test_blob() {
        let db = checked_memory_handle();

        let v1234 = vec![1u8, 2, 3, 4];
        db.execute("INSERT INTO foo(b) VALUES (?)", &[&v1234]).unwrap();

        let v: Vec<u8> = db.query_row("SELECT b FROM foo", &[], |r| r.get(0)).unwrap();
        assert_eq!(v, v1234);
    }

    #[test]
    fn test_empty_blob() {
        let db = checked_memory_handle();

        let empty = vec![];
        db.execute("INSERT INTO foo(b) VALUES (?)", &[&empty]).unwrap();

        let v: Vec<u8> = db.query_row("SELECT b FROM foo", &[], |r| r.get(0)).unwrap();
        assert_eq!(v, empty);
    }

    #[test]
    fn test_str() {
        let db = checked_memory_handle();

        let s = "hello, world!";
        db.execute("INSERT INTO foo(t) VALUES (?)", &[&s.to_owned()]).unwrap();

        let from: String = db.query_row("SELECT t FROM foo", &[], |r| r.get(0)).unwrap();
        assert_eq!(from, s);
    }

    #[test]
    fn test_option() {
        let db = checked_memory_handle();

        let s = Some("hello, world!");
        let b = Some(vec![1u8, 2, 3, 4]);

        db.execute("INSERT INTO foo(t) VALUES (?)", &[&s]).unwrap();
        db.execute("INSERT INTO foo(b) VALUES (?)", &[&b]).unwrap();

        let mut stmt = db.prepare("SELECT t, b FROM foo ORDER BY ROWID ASC").unwrap();
        let mut rows = stmt.query(&[]).unwrap();

        {
            let row1 = rows.next().unwrap().unwrap();
            let s1: Option<String> = row1.get(0);
            let b1: Option<Vec<u8>> = row1.get(1);
            assert_eq!(s.unwrap(), s1.unwrap());
            assert!(b1.is_none());
        }

        {
            let row2 = rows.next().unwrap().unwrap();
            let s2: Option<String> = row2.get(0);
            let b2: Option<Vec<u8>> = row2.get(1);
            assert!(s2.is_none());
            assert_eq!(b, b2);
        }
    }

    #[test]
    #[cfg_attr(feature="clippy", allow(cyclomatic_complexity))]
    fn test_mismatched_types() {
        fn is_invalid_column_type(err: Error) -> bool {
            match err {
                Error::InvalidColumnType => true,
                _ => false,
            }
        }

        let db = checked_memory_handle();

        db.execute("INSERT INTO foo(b, t, i, f) VALUES (X'0102', 'text', 1, 1.5)",
                     &[])
            .unwrap();

        let mut stmt = db.prepare("SELECT b, t, i, f, n FROM foo").unwrap();
        let mut rows = stmt.query(&[]).unwrap();

        let row = rows.next().unwrap().unwrap();

        // check the correct types come back as expected
        assert_eq!(vec![1, 2], row.get_checked::<i32, Vec<u8>>(0).unwrap());
        assert_eq!("text", row.get_checked::<i32, String>(1).unwrap());
        assert_eq!(1, row.get_checked::<i32, c_int>(2).unwrap());
        assert!((1.5 - row.get_checked::<i32, c_double>(3).unwrap()).abs() < EPSILON);
        assert!(row.get_checked::<i32, Option<c_int>>(4).unwrap().is_none());
        assert!(row.get_checked::<i32, Option<c_double>>(4).unwrap().is_none());
        assert!(row.get_checked::<i32, Option<String>>(4).unwrap().is_none());

        // check some invalid types

        // 0 is actually a blob (Vec<u8>)
        assert!(is_invalid_column_type(row.get_checked::<i32, c_int>(0).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, c_int>(0).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, i64>(0).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, c_double>(0).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, String>(0).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, time::Timespec>(0).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, Option<c_int>>(0).err().unwrap()));

        // 1 is actually a text (String)
        assert!(is_invalid_column_type(row.get_checked::<i32, c_int>(1).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, i64>(1).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, c_double>(1).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, Vec<u8>>(1).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, Option<c_int>>(1).err().unwrap()));

        // 2 is actually an integer
        assert!(is_invalid_column_type(row.get_checked::<i32, String>(2).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, Vec<u8>>(2).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, Option<String>>(2).err().unwrap()));

        // 3 is actually a float (c_double)
        assert!(is_invalid_column_type(row.get_checked::<i32, c_int>(3).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, i64>(3).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, String>(3).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, Vec<u8>>(3).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, Option<c_int>>(3).err().unwrap()));

        // 4 is actually NULL
        assert!(is_invalid_column_type(row.get_checked::<i32, c_int>(4).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, i64>(4).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, c_double>(4).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, String>(4).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, Vec<u8>>(4).err().unwrap()));
        assert!(is_invalid_column_type(row.get_checked::<i32, time::Timespec>(4).err().unwrap()));
    }

    #[test]
    fn test_dynamic_type() {
        use super::Value;
        let db = checked_memory_handle();

        db.execute("INSERT INTO foo(b, t, i, f) VALUES (X'0102', 'text', 1, 1.5)",
                     &[])
            .unwrap();

        let mut stmt = db.prepare("SELECT b, t, i, f, n FROM foo").unwrap();
        let mut rows = stmt.query(&[]).unwrap();

        let row = rows.next().unwrap().unwrap();
        assert_eq!(Value::Blob(vec![1, 2]),
                   row.get_checked::<i32, Value>(0).unwrap());
        assert_eq!(Value::Text(String::from("text")),
                   row.get_checked::<i32, Value>(1).unwrap());
        assert_eq!(Value::Integer(1), row.get_checked::<i32, Value>(2).unwrap());
        match row.get_checked::<i32, Value>(3).unwrap() {
            Value::Real(val) => assert!((1.5 - val).abs() < EPSILON),
            x => panic!("Invalid Value {:?}", x),
        }
        assert_eq!(Value::Null, row.get_checked::<i32, Value>(4).unwrap());
    }
}
<|endoftext|>


<commit_before>use std::thread;
use std::sync::mpsc::{channel, Sender, Receiver, self};

use message::Message;

pub struct UserView<'a> {
    _incoming_sender: Sender<Message>,
    _view_guard: thread::JoinGuard<'a, ()>
}

pub fn start<'a>() -> UserView<'a> {
    let (tx, rx) = channel::<Message>();
    let view_guard = spawn_view(rx);

    UserView {
        _incoming_sender: tx,
        _view_guard: view_guard
    }
}

impl<'a> UserView<'a> {
    pub fn incoming_message(&self, message: Message) -> Result<(), mpsc::SendError<Message>> {
       self._incoming_sender.send(message)
    }
}

fn spawn_view<'b>(rx: Receiver<Message>) -> thread::JoinGuard<'b, ()> {
   thread::scoped(move || {
       loop {
           let message = rx.recv().ok().expect("Failed to print message");
           println!("{}", message);
       }
   })
}

<commit_msg>Add thread for UserInput and remove thread for view<commit_after>use std::io;
use std::thread;
use std::sync::mpsc;

use message::Message;

pub struct UserView<'a> {
    _input_recv: mpsc::Receiver<String>,
    _input_guard: thread::JoinGuard<'a, ()>
}

pub fn start<'a>() -> UserView<'a> {
    let (input_send, input_recv) = mpsc::channel::<String>();

    UserView {
        _input_recv: input_recv,
        _input_guard: spawn_input(input_send),
    }
}

impl<'a> UserView<'a> {
    pub fn incoming_message(&self, message: Message) -> Result<(), &'static str> {
       println!("{}", message);
       Ok(())
    }

    pub fn iter_user_input(&self) -> mpsc::Iter<String> {
       self._input_recv.iter()
    }
}

fn spawn_input<'b>(tx: mpsc::Sender<String>) -> thread::JoinGuard<'b, ()> {
   thread::scoped(move || {
      let mut stdin = io::stdin();

      loop {
         let mut input: String = "".to_string();
         stdin.read_line(&mut input);
         tx.send(input);
      }
   })
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::fmt::{Debug, Error, Formatter};
use std::sync::{Arc, RwLock};

lazy_static! {
    static ref SYMBOLICATOR: Symbolicator = Symbolicator::new();
}

pub fn symbolicate<S: Into<String>>(string: S) -> Symbol {
    (*SYMBOLICATOR).symbolicate(string)
}

pub fn desymbolicate<S: AsRef<Symbol>>(symbol: &S) -> Option<String> {
    (*SYMBOLICATOR).desymbolicate(symbol)
}

#[derive(Clone)]
struct Symbolicator(Arc<RwLock<InnerSymbolicator>>);

impl Symbolicator {
    fn new() -> Self {
        let inner = InnerSymbolicator::new();
        Self(Arc::new(RwLock::new(inner)))
    }

    pub fn symbolicate<S: Into<String>>(&self, string: S) -> Symbol {
        let string = string.into();
        {
            let reader = self.0.read().unwrap();
            if let Some(existing_id) = reader.symbols.get(&string) {
                return Symbol(*existing_id);
            }
        }
        let mut writer = self.0.write().unwrap();
        let next_id = writer.symbols.len() as u32;
        writer.symbols.insert(string, next_id);
        Symbol(next_id)
    }

    pub fn desymbolicate<S: AsRef<Symbol>>(&self, symbol: &S) -> Option<String> {
        let reader = self.0.read().unwrap();
        let id = symbol.as_ref().0;
        for (key, value) in reader.symbols.iter() {
            if *value == id {
                return Some(key.clone());
            }
        }
        None
    }
}

type SymbolId = u32;

#[derive(Clone, Copy, PartialEq)]
pub struct Symbol(SymbolId);

impl Symbol {
    pub fn id(&self) -> SymbolId {
        self.0
    }
}

impl AsRef<Symbol> for Symbol {
    fn as_ref(&self) -> &Symbol {
        &self
    }
}

#[cfg(not(test))]
impl Debug for Symbol {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        f.debug_tuple("Symbol")
            .field(&self.0)
            .field(&(*SYMBOLICATOR).desymbolicate(&self))
            .finish()
    }
}

#[cfg(test)]
impl Debug for Symbol {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        f.debug_tuple("Symbol").field(&self.0).finish()
    }
}

// Trick trait to enforce that the `Symbolicator` is thread-safe.
trait MustBeSendAndSync: Send + Sync {}

impl MustBeSendAndSync for Symbolicator {}

struct InnerSymbolicator {
    symbols: HashMap<String, SymbolId>,
}

impl InnerSymbolicator {
    pub fn new() -> Self {
        Self {
            symbols: HashMap::new(),
        }
    }
}

#[cfg(test)]
mod tests {
    use std::thread;

    use super::{Symbol, Symbolicator};
    use std::io::Write;

    #[test]
    fn it_symbolicates_and_desymbolicates() {
        let symbolicator = Symbolicator::new();
        let symbol = symbolicator.symbolicate("foo");
        assert_eq!(symbol, Symbol(0));
        assert_eq!(symbolicator.desymbolicate(&symbol), Some("foo".to_string()),);
        assert_eq!(symbolicator.desymbolicate(&Symbol(1)), None);
    }

    #[test]
    fn it_symbolicates_thread_safely() {
        let symbolicator = Symbolicator::new();

        // Spawn 10 of threads that will all race to symbolicate.
        (0..10)
            .into_iter()
            .map(|_| {
                let movable = symbolicator.clone();
                thread::spawn(move || {
                    assert_eq!(movable.symbolicate("foo"), Symbol(0));
                })
            })
            .map(|handle| handle.join().unwrap())
            .for_each(drop);

        // Spawn 20 of threads that will all race to symbolicate and desymbolicate.
        (0..20)
            .into_iter()
            .map(|index| {
                let movable = symbolicator.clone();
                thread::spawn(move || {
                    if index % 2 == 1 {
                        assert_eq!(movable.symbolicate("foo"), Symbol(0));
                    } else {
                        assert_eq!(movable.desymbolicate(&Symbol(0)), Some("foo".to_string()));
                    }
                })
            })
            .map(|handle| handle.join().unwrap())
            .for_each(drop);
    }
}
<commit_msg>Add constant function for an uninitialized symbol<commit_after>use std::collections::HashMap;
use std::fmt::{Debug, Error, Formatter};
use std::sync::{Arc, RwLock};

lazy_static! {
    static ref SYMBOLICATOR: Symbolicator = Symbolicator::new();
}

pub fn symbolicate<S: Into<String>>(string: S) -> Symbol {
    (*SYMBOLICATOR).symbolicate(string)
}

pub fn desymbolicate<S: AsRef<Symbol>>(symbol: &S) -> Option<String> {
    (*SYMBOLICATOR).desymbolicate(symbol)
}

#[derive(Clone)]
struct Symbolicator(Arc<RwLock<InnerSymbolicator>>);

impl Symbolicator {
    fn new() -> Self {
        let inner = InnerSymbolicator::new();
        Self(Arc::new(RwLock::new(inner)))
    }

    pub fn symbolicate<S: Into<String>>(&self, string: S) -> Symbol {
        let string = string.into();
        {
            let reader = self.0.read().unwrap();
            if let Some(existing_id) = reader.symbols.get(&string) {
                return Symbol(*existing_id);
            }
        }
        let mut writer = self.0.write().unwrap();
        let next_id = writer.symbols.len() as u32;
        if next_id == UNINITIALIZED_ID {
            panic!("Exhausted symbol space");
        }
        writer.symbols.insert(string, next_id);
        Symbol(next_id)
    }

    pub fn desymbolicate<S: AsRef<Symbol>>(&self, symbol: &S) -> Option<String> {
        let reader = self.0.read().unwrap();
        let symbol = symbol.as_ref();
        if *symbol == Symbol::uninitialized() {
            panic!("Attempting to desymbolicate uninitialized symbol");
        }
        let id = symbol.0;
        for (key, value) in reader.symbols.iter() {
            if *value == id {
                return Some(key.clone());
            }
        }
        None
    }
}

type SymbolId = u32;

const UNINITIALIZED_ID: SymbolId = std::u32::MAX;

#[derive(Clone, Copy, PartialEq)]
pub struct Symbol(SymbolId);

impl Symbol {
    pub const fn uninitialized() -> Symbol {
        Symbol(UNINITIALIZED_ID)
    }

    pub fn id(&self) -> SymbolId {
        self.0
    }
}

impl AsRef<Symbol> for Symbol {
    fn as_ref(&self) -> &Symbol {
        &self
    }
}

#[cfg(not(test))]
impl Debug for Symbol {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        f.debug_tuple("Symbol")
            .field(&self.0)
            .field(&(*SYMBOLICATOR).desymbolicate(&self))
            .finish()
    }
}

#[cfg(test)]
impl Debug for Symbol {
    fn fmt(&self, f: &mut Formatter) -> Result<(), Error> {
        f.debug_tuple("Symbol").field(&self.0).finish()
    }
}

// Trick trait to enforce that the `Symbolicator` is thread-safe.
trait MustBeSendAndSync: Send + Sync {}

impl MustBeSendAndSync for Symbolicator {}

struct InnerSymbolicator {
    symbols: HashMap<String, SymbolId>,
}

impl InnerSymbolicator {
    pub fn new() -> Self {
        Self {
            symbols: HashMap::new(),
        }
    }
}

#[cfg(test)]
mod tests {
    use std::thread;

    use super::{Symbol, Symbolicator};
    use std::io::Write;

    #[test]
    fn it_symbolicates_and_desymbolicates() {
        let symbolicator = Symbolicator::new();
        let symbol = symbolicator.symbolicate("foo");
        assert_eq!(symbol, Symbol(0));
        assert_eq!(symbolicator.desymbolicate(&symbol), Some("foo".to_string()),);
        assert_eq!(symbolicator.desymbolicate(&Symbol(1)), None);
    }

    #[test]
    fn it_symbolicates_thread_safely() {
        let symbolicator = Symbolicator::new();

        // Spawn 10 of threads that will all race to symbolicate.
        (0..10)
            .into_iter()
            .map(|_| {
                let movable = symbolicator.clone();
                thread::spawn(move || {
                    assert_eq!(movable.symbolicate("foo"), Symbol(0));
                })
            })
            .map(|handle| handle.join().unwrap())
            .for_each(drop);

        // Spawn 20 of threads that will all race to symbolicate and desymbolicate.
        (0..20)
            .into_iter()
            .map(|index| {
                let movable = symbolicator.clone();
                thread::spawn(move || {
                    if index % 2 == 1 {
                        assert_eq!(movable.symbolicate("foo"), Symbol(0));
                    } else {
                        assert_eq!(movable.desymbolicate(&Symbol(0)), Some("foo".to_string()));
                    }
                })
            })
            .map(|handle| handle.join().unwrap())
            .for_each(drop);
    }

    #[test]
    #[should_panic]
    fn it_doesnt_desymbolicate_unitialized() {
        let symbol = Symbol::uninitialized();
        let symbolicator = Symbolicator::new();
        symbolicator.desymbolicate(&symbol);
    }
}
<|endoftext|>


<commit_before>// Implements http://rosettacode.org/wiki/Hello_world/Web_server
#![cfg(not_tested)]

use std::io::net::tcp::{TcpListener, TcpStream};
use std::io::net::ip::{Ipv4Addr, SocketAddr};
use std::io::{Acceptor, Listener};

fn handle_client(mut stream: TcpStream) {
    let response = bytes!(
"HTTP/1.1 200 OK
Content-Type: text/html;
charset=UTF-8

<doctype !html>

        <title>Bye-bye baby bye-bye</title>

Goodbye, world!

");
    match stream.write(response) {
        Ok(_) => println!("Response sent!"),
        Err(e) => println!("Failed sending response: {}!", e),
    }
}

fn main() {
    let addr = SocketAddr { ip: Ipv4Addr(127, 0, 0, 1), port: 80 };
    let listener = TcpListener::bind(addr).unwrap();

    let mut acceptor = listener.listen();
    println!("Listening for connections on port {}", addr.port);

    for stream in acceptor.incoming() {
        spawn(proc() {
            handle_client(stream.unwrap());
        });
    }
}
<commit_msg>Fix webserver<commit_after>// Implements http://rosettacode.org/wiki/Hello_world/Web_server
#![cfg(not_tested)]

use std::io::net::tcp::{TcpListener, TcpStream};
use std::io::{Acceptor, Listener};

fn handle_client(mut stream: TcpStream) {
    let response = bytes!(
"HTTP/1.1 200 OK
Content-Type: text/html;
charset=UTF-8

<doctype !html>

        <title>Bye-bye baby bye-bye</title>

Goodbye, world!

");
    match stream.write(response) {
        Ok(_) => println!("Response sent!"),
        Err(e) => println!("Failed sending response: {}!", e),
    }
}

fn main() {
    let (ip, port) = ("127.0.0.1", 80);
    let listener = TcpListener::bind(ip, port).unwrap();

    let mut acceptor = listener.listen();
    println!("Listening for connections on port {}", port);

    for stream in acceptor.incoming() {
        spawn(proc() {
            handle_client(stream.unwrap());
        });
    }
}
<|endoftext|>


<commit_before>use buffer;
use buffer::Buffer;
use std::old_io::IoError;

pub struct Workspace {
    path: Path,
    buffers: Vec<Buffer>,
    current_buffer_index: Option<usize>,
}

impl Workspace {
    pub fn add_buffer(&mut self, buf: Buffer) {
        self.buffers.push(buf);
        self.current_buffer_index = Some(self.buffers.len()-1);
    }

    pub fn current_buffer(&mut self) -> Option<&mut Buffer> {
        match self.current_buffer_index {
            Some(index) => Some(&mut self.buffers[index]),
            None => None,
        }
    }

    pub fn close_current_buffer(&mut self) {
        match self.current_buffer_index {
            Some(index) => {
                self.buffers.remove(index);

                if self.buffers.is_empty() {
                    self.current_buffer_index = None;
                } else {
                    self.current_buffer_index = Some(self.buffers.len()-1);
                }
            }
            None => return,
        };
    }

    pub fn previous_buffer(&mut self) {
        match self.current_buffer_index {
            Some(index) => {
                if index > 0 {
                    self.current_buffer_index = Some(index-1);
                } else {
                    self.current_buffer_index = Some(self.buffers.len()-1);
                }
            },
            None => return,
        }
    }
}

pub fn new(path: Path) -> Workspace {
    Workspace{ path: path, buffers: Vec::new(), current_buffer_index: None }
}

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

    #[test]
    fn add_buffer_adds_and_selects_the_passed_buffer() {
        let mut workspace = new(Path::new("tests/sample"));
        let buf = buffer::from_file(Path::new("tests/sample/file")).unwrap();
        workspace.add_buffer(buf);

        assert_eq!(workspace.buffers.len(), 1);
        assert_eq!(workspace.current_buffer().unwrap().data(), "it works!\n");
    }

    #[test]
    fn current_buffer_returns_none_when_there_are_no_buffers() {
        let mut workspace = new(Path::new("tests/sample"));
        assert!(workspace.current_buffer().is_none());
    }

    #[test]
    fn current_buffer_returns_one_when_there_are_buffers() {
        let mut workspace = new(Path::new("tests/sample"));
        let buf = buffer::from_file(Path::new("tests/sample/file")).unwrap();
        workspace.add_buffer(buf);
        assert!(workspace.current_buffer().is_some());
    }

    #[test]
    fn close_current_buffer_does_nothing_when_none_are_open() {
        let mut workspace = new(Path::new("tests/sample"));
        workspace.close_current_buffer();
        assert!(workspace.current_buffer().is_none());
    }

    #[test]
    fn close_current_buffer_cleans_up_when_only_one_buffer_is_open() {
        let mut workspace = new(Path::new("tests/sample"));
        workspace.add_buffer(buffer::new());
        workspace.close_current_buffer();
        assert!(workspace.current_buffer().is_none());
        assert!(workspace.current_buffer_index.is_none());
    }

    #[test]
    fn close_current_buffer_when_two_are_open_selects_the_other() {
        let mut workspace = new(Path::new("tests/sample"));

        // Create two buffers and add them to the workspace.
        let mut first_buffer = buffer::new();
        let mut second_buffer = buffer::new();
        first_buffer.insert("first buffer");
        second_buffer.insert("second buffer");
        workspace.add_buffer(first_buffer);
        workspace.add_buffer(second_buffer);

        // Ensure that the second buffer is currently selected.
        assert_eq!(workspace.current_buffer().unwrap().data(), "second buffer");

        workspace.close_current_buffer();
        assert_eq!(workspace.current_buffer().unwrap().data(), "first buffer");
    }

    #[test]
    fn previous_buffer_does_nothing_when_no_buffers_are_open() {
        let mut workspace = new(Path::new("tests/sample"));
        workspace.previous_buffer();
        assert!(workspace.current_buffer().is_none());
    }

    #[test]
    fn previous_buffer_when_two_are_open_selects_the_first_and_cycles_back_to_the_last() {
        let mut workspace = new(Path::new("tests/sample"));

        // Create two buffers and add them to the workspace.
        let mut first_buffer = buffer::new();
        let mut second_buffer = buffer::new();
        first_buffer.insert("first buffer");
        second_buffer.insert("second buffer");
        workspace.add_buffer(first_buffer);
        workspace.add_buffer(second_buffer);

        // Ensure that the second buffer is currently selected.
        assert_eq!(workspace.current_buffer().unwrap().data(), "second buffer");

        // Ensure that the first buffer is returned.
        workspace.previous_buffer();
        assert_eq!(workspace.current_buffer().unwrap().data(), "first buffer");

        // Ensure that the second buffer is returned.
        workspace.previous_buffer();
        assert_eq!(workspace.current_buffer().unwrap().data(), "second buffer");
    }
}
<commit_msg>Test previous_buffer using three buffers instead of two.<commit_after>use buffer;
use buffer::Buffer;
use std::old_io::IoError;

pub struct Workspace {
    path: Path,
    buffers: Vec<Buffer>,
    current_buffer_index: Option<usize>,
}

impl Workspace {
    pub fn add_buffer(&mut self, buf: Buffer) {
        self.buffers.push(buf);
        self.current_buffer_index = Some(self.buffers.len()-1);
    }

    pub fn current_buffer(&mut self) -> Option<&mut Buffer> {
        match self.current_buffer_index {
            Some(index) => Some(&mut self.buffers[index]),
            None => None,
        }
    }

    pub fn close_current_buffer(&mut self) {
        match self.current_buffer_index {
            Some(index) => {
                self.buffers.remove(index);

                if self.buffers.is_empty() {
                    self.current_buffer_index = None;
                } else {
                    self.current_buffer_index = Some(self.buffers.len()-1);
                }
            }
            None => return,
        };
    }

    pub fn previous_buffer(&mut self) {
        match self.current_buffer_index {
            Some(index) => {
                if index > 0 {
                    self.current_buffer_index = Some(index-1);
                } else {
                    self.current_buffer_index = Some(self.buffers.len()-1);
                }
            },
            None => return,
        }
    }
}

pub fn new(path: Path) -> Workspace {
    Workspace{ path: path, buffers: Vec::new(), current_buffer_index: None }
}

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

    #[test]
    fn add_buffer_adds_and_selects_the_passed_buffer() {
        let mut workspace = new(Path::new("tests/sample"));
        let buf = buffer::from_file(Path::new("tests/sample/file")).unwrap();
        workspace.add_buffer(buf);

        assert_eq!(workspace.buffers.len(), 1);
        assert_eq!(workspace.current_buffer().unwrap().data(), "it works!\n");
    }

    #[test]
    fn current_buffer_returns_none_when_there_are_no_buffers() {
        let mut workspace = new(Path::new("tests/sample"));
        assert!(workspace.current_buffer().is_none());
    }

    #[test]
    fn current_buffer_returns_one_when_there_are_buffers() {
        let mut workspace = new(Path::new("tests/sample"));
        let buf = buffer::from_file(Path::new("tests/sample/file")).unwrap();
        workspace.add_buffer(buf);
        assert!(workspace.current_buffer().is_some());
    }

    #[test]
    fn close_current_buffer_does_nothing_when_none_are_open() {
        let mut workspace = new(Path::new("tests/sample"));
        workspace.close_current_buffer();
        assert!(workspace.current_buffer().is_none());
    }

    #[test]
    fn close_current_buffer_cleans_up_when_only_one_buffer_is_open() {
        let mut workspace = new(Path::new("tests/sample"));
        workspace.add_buffer(buffer::new());
        workspace.close_current_buffer();
        assert!(workspace.current_buffer().is_none());
        assert!(workspace.current_buffer_index.is_none());
    }

    #[test]
    fn close_current_buffer_when_two_are_open_selects_the_other() {
        let mut workspace = new(Path::new("tests/sample"));

        // Create two buffers and add them to the workspace.
        let mut first_buffer = buffer::new();
        let mut second_buffer = buffer::new();
        first_buffer.insert("first buffer");
        second_buffer.insert("second buffer");
        workspace.add_buffer(first_buffer);
        workspace.add_buffer(second_buffer);

        // Ensure that the second buffer is currently selected.
        assert_eq!(workspace.current_buffer().unwrap().data(), "second buffer");

        workspace.close_current_buffer();
        assert_eq!(workspace.current_buffer().unwrap().data(), "first buffer");
    }

    #[test]
    fn previous_buffer_does_nothing_when_no_buffers_are_open() {
        let mut workspace = new(Path::new("tests/sample"));
        workspace.previous_buffer();
        assert!(workspace.current_buffer().is_none());
    }

    #[test]
    fn previous_buffer_when_three_are_open_selects_previous_wrapping_to_last() {
        let mut workspace = new(Path::new("tests/sample"));

        // Create two buffers and add them to the workspace.
        let mut first_buffer = buffer::new();
        let mut second_buffer = buffer::new();
        let mut third_buffer = buffer::new();
        first_buffer.insert("first buffer");
        second_buffer.insert("second buffer");
        third_buffer.insert("third buffer");
        workspace.add_buffer(first_buffer);
        workspace.add_buffer(second_buffer);
        workspace.add_buffer(third_buffer);

        // Ensure that the third buffer is currently selected.
        assert_eq!(workspace.current_buffer().unwrap().data(), "third buffer");

        // Ensure that the second buffer is returned.
        workspace.previous_buffer();
        assert_eq!(workspace.current_buffer().unwrap().data(), "second buffer");

        // Ensure that the first buffer is returned.
        workspace.previous_buffer();
        assert_eq!(workspace.current_buffer().unwrap().data(), "first buffer");

        // Ensure that it wraps back to the third buffer.
        workspace.previous_buffer();
        assert_eq!(workspace.current_buffer().unwrap().data(), "third buffer");
    }
}
<|endoftext|>


<commit_before>
///
/// Systems are a set of event handlers and optionally some associated state.
///
/// The event handlers are invoked with a list of event data and have access to component
/// lists. This access can be immutable or mutable which is made explicit so that
/// the event handler scheduler might parallelize handler invocations.
///
/// To properly enforce this I guess the scheduler would acquire the locks on the component
/// lists.
///
/// So the context of the handler function would consist of:
///
///   The handler state
///   The event data list
///   Immutable components lists
///   Mutable components lists
///
/// For example the following invocation:
///
/// system! my_system {
///   state! { i: i64 }
///   on!(event_name, { positions: Position}, { descriptions: Description }) {
///     state.i += 1;
///     let position = positions[0];
///     descriptions[0].set(format!("Position = {},{}", position.x, position.y));
///   }
/// }
///
/// Expands to:
///
/// pub mod my_system {
///   struct State { i: i64 }
///
///   pub fn event_name(state: &mut State, data: &Vec<event_name::Data>, positions: &Vec<Position>, descriptions: &mut Vec<Description> ) {
///     let position = positions[0];
///     descriptions[0].set(format!("Position = {},{}", position.x, position.y));
///   }
///
///   pub fn register() {
///      events::register_handler(event_name); // etc..
///   }
/// }
///
/// How are we going to register this handler at the event loop?
///
/// Ideally we would have just one 'register' call per system. But to have that the register call should enable
/// all nested handlers. We could also just have one handler per system. That would make things easier..
/// Maybe there's some scheme using recursive macros that we could use to generate a register_system that collects
/// all on! calls. Ok this is definitely a possibility. We could simply match the on! macro in the system! macro
/// and use that to populate the register function.
///
/// How are we going to store/invoke these handlers.
///
/// To invoke the handler it will require the state, the components and the data list passed in the right order.
/// we could have a separate invoker function that invokes event_name with the arguments passed in. Its arguments
/// would be the component lists in two vecs, as well as the event data list.
///
/// This could work!
///

#[macro_export]
macro_rules! system {
	( $system_name:ident { $($contents:tt)* } ) => {
		pub mod $system_name {
			use std::any::Any;
			use shared_mutex::{ SharedMutex };
			use entity_rust::entities::{ ComponentList };
			use shared_mutex::{ MappedSharedMutexReadGuard, MappedSharedMutexWriteGuard };

			system_contents!{ ( $($contents)* ) [ ] }
		}
	}
}

#[macro_export]
macro_rules! system_contents {
	// Consume on! invocations
	(
		(
			on! (
				$event_name:ident, $($event_declaration:tt)*
			) $_self:ident, $_data:ident => $event_body:block $($rest:tt)*
		) [
			$( $saved_decl:tt ),*
		]
	) => (
		on! { ($event_name, $( $event_declaration)* ) $_self , $_data => $event_body }

		system_contents!{
			( $($rest)* )
			[ ( $event_name, $( $event_declaration)* ) $(, $saved_decl)* ]
		}
	);

	(
		(
			state! { $($state_declaration:tt)* } $($rest:tt)*
		) [
			$( $saved_decl:tt ),*
		]
	) => (
		state! { $($state_declaration)* }

		system_contents!{
			( $($rest)* )
			[ $( $saved_decl ),* ]
		}
	);

	// When all content has been consumed emit register macro
	(
		() [ $( $event_declaration:tt ),* ]
	) => (
		system_register!{ $( $event_declaration ),* }
	)
}

#[macro_export]
macro_rules! on {
	( ($event_name:ident, { $( $mut_name:ident : $mut_typ:ty )* } , { $($name:ident : $typ:ty)* } )
		$_self:ident, $_data:ident => $event_body:block ) => (

		impl State {
			#[allow(unused_variables)]
			pub fn $event_name(&mut $_self,
				$_data: &Vec<super::$event_name::Data>,
				$( $name : &MappedSharedMutexReadGuard<ComponentList<$typ>>),*
				$( $mut_name : &MappedSharedMutexWriteGuard<ComponentList<$mut_typ>> ),* ) $event_body

		}

		#[allow(unused_variables)]
		#[allow(unused_mut)]
		pub fn $event_name(
				data: &Vec<super::$event_name::Data>,
				components: Vec<MappedSharedMutexReadGuard<Any>>,
				mut_components: Vec<MappedSharedMutexWriteGuard<Any>>
			) {
			let mut components_iter = components.into_iter();
			let mut mut_components_iter = mut_components.into_iter();

			$(
				let $name : MappedSharedMutexReadGuard<ComponentList<$typ>> = components_iter
					.next().expect("Event components list too short.")
					.map(|v| v.downcast_ref().expect("Event component not of expected type."));
			)*

			$(
				let $mut_name: MappedSharedMutexWriteGuard<ComponentList<$mut_typ>> = mut_components_iter
					.next().expect("Event mut_components list too short.")
					.map(|v| v.downcast_mut().expect("Event component not of expected type."));
			)*

			STATE.write().expect("Event state corrupted").$event_name(
				data,
				&$($name),*
				&$($mut_name),*
			);
		}
	)
}

#[macro_export]
macro_rules! state {
	( $( $name:ident : $field:ty ),* ) => (
		#[derive(Default)]
		pub struct State {
			$(pub $name : $field),*
		}

		lazy_static! {
			pub static ref STATE: SharedMutex<State> = SharedMutex::new(State::default());
		}
	)
}

#[macro_export]
macro_rules! system_register {
	( $( (
			$event_name:ident,
			{ $( $mut_name:ident : $mut_typ:ty )* } ,
			{ $( $name:ident : $typ:ty )* }
		)
	),* ) => (
		pub fn register() {
			use std::any::TypeId;
			$(
				let mut_ts = vec![ $( TypeId::of::< $mut_typ >() ),* ];
				let ts = vec![ $( TypeId::of::< $typ >() ),* ];
				super::$event_name::register_handler($event_name, ts, mut_ts);
			)*
		}
	)
}
<commit_msg>fix bug in event invocation macro<commit_after>
///
/// Systems are a set of event handlers and optionally some associated state.
///
/// The event handlers are invoked with a list of event data and have access to component
/// lists. This access can be immutable or mutable which is made explicit so that
/// the event handler scheduler might parallelize handler invocations.
///
/// To properly enforce this I guess the scheduler would acquire the locks on the component
/// lists.
///
/// So the context of the handler function would consist of:
///
///   The handler state
///   The event data list
///   Immutable components lists
///   Mutable components lists
///
/// For example the following invocation:
///
/// system! my_system {
///   state! { i: i64 }
///   on!(event_name, { positions: Position}, { descriptions: Description }) {
///     state.i += 1;
///     let position = positions[0];
///     descriptions[0].set(format!("Position = {},{}", position.x, position.y));
///   }
/// }
///
/// Expands to:
///
/// pub mod my_system {
///   struct State { i: i64 }
///
///   pub fn event_name(state: &mut State, data: &Vec<event_name::Data>, positions: &Vec<Position>, descriptions: &mut Vec<Description> ) {
///     let position = positions[0];
///     descriptions[0].set(format!("Position = {},{}", position.x, position.y));
///   }
///
///   pub fn register() {
///      events::register_handler(event_name); // etc..
///   }
/// }
///
/// How are we going to register this handler at the event loop?
///
/// Ideally we would have just one 'register' call per system. But to have that the register call should enable
/// all nested handlers. We could also just have one handler per system. That would make things easier..
/// Maybe there's some scheme using recursive macros that we could use to generate a register_system that collects
/// all on! calls. Ok this is definitely a possibility. We could simply match the on! macro in the system! macro
/// and use that to populate the register function.
///
/// How are we going to store/invoke these handlers.
///
/// To invoke the handler it will require the state, the components and the data list passed in the right order.
/// we could have a separate invoker function that invokes event_name with the arguments passed in. Its arguments
/// would be the component lists in two vecs, as well as the event data list.
///
/// This could work!
///

#[macro_export]
macro_rules! system {
	( $system_name:ident { $($contents:tt)* } ) => {
		pub mod $system_name {
			use std::any::Any;
			use shared_mutex::{ SharedMutex };
			use entity_rust::entities::{ ComponentList };
			use shared_mutex::{ MappedSharedMutexReadGuard, MappedSharedMutexWriteGuard };

			system_contents!{ ( $($contents)* ) [ ] }
		}
	}
}

#[macro_export]
macro_rules! system_contents {
	// Consume on! invocations
	(
		(
			on! (
				$event_name:ident, $($event_declaration:tt)*
			) $_self:ident, $_data:ident => $event_body:block $($rest:tt)*
		) [
			$( $saved_decl:tt ),*
		]
	) => (
		on! { ($event_name, $( $event_declaration)* ) $_self , $_data => $event_body }

		system_contents!{
			( $($rest)* )
			[ ( $event_name, $( $event_declaration)* ) $(, $saved_decl)* ]
		}
	);

	(
		(
			state! { $($state_declaration:tt)* } $($rest:tt)*
		) [
			$( $saved_decl:tt ),*
		]
	) => (
		state! { $($state_declaration)* }

		system_contents!{
			( $($rest)* )
			[ $( $saved_decl ),* ]
		}
	);

	// When all content has been consumed emit register macro
	(
		() [ $( $event_declaration:tt ),* ]
	) => (
		system_register!{ $( $event_declaration ),* }
	)
}

#[macro_export]
macro_rules! on {
	( ($event_name:ident, { $( $mut_name:ident : $mut_typ:ty )* } , { $($name:ident : $typ:ty)* } )
		$_self:ident, $_data:ident => $event_body:block ) => (

		impl State {
			#[allow(unused_variables)]
			pub fn $event_name(&mut $_self,
				$_data: &Vec<super::$event_name::Data>,
				$( $name : &MappedSharedMutexReadGuard<ComponentList<$typ>>),*
				$( $mut_name : &MappedSharedMutexWriteGuard<ComponentList<$mut_typ>> ),* ) $event_body

		}

		#[allow(unused_variables)]
		#[allow(unused_mut)]
		pub fn $event_name(
				data: &Vec<super::$event_name::Data>,
				components: Vec<MappedSharedMutexReadGuard<Any>>,
				mut_components: Vec<MappedSharedMutexWriteGuard<Any>>
			) {
			let mut components_iter = components.into_iter();
			let mut mut_components_iter = mut_components.into_iter();

			$(
				let $name : MappedSharedMutexReadGuard<ComponentList<$typ>> = components_iter
					.next().expect("Event components list too short.")
					.map(|v| v.downcast_ref().expect("Event component not of expected type."));
			)*

			$(
				let $mut_name: MappedSharedMutexWriteGuard<ComponentList<$mut_typ>> = mut_components_iter
					.next().expect("Event mut_components list too short.")
					.map(|v| v.downcast_mut().expect("Event component not of expected type."));
			)*

			STATE.write().expect("Event state corrupted").$event_name(
				data,
				$(&$name),*
				$(&$mut_name),*
			);
		}
	)
}

#[macro_export]
macro_rules! state {
	( $( $name:ident : $field:ty ),* ) => (
		#[derive(Default)]
		pub struct State {
			$(pub $name : $field),*
		}

		lazy_static! {
			pub static ref STATE: SharedMutex<State> = SharedMutex::new(State::default());
		}
	)
}

#[macro_export]
macro_rules! system_register {
	( $( (
			$event_name:ident,
			{ $( $mut_name:ident : $mut_typ:ty )* } ,
			{ $( $name:ident : $typ:ty )* }
		)
	),* ) => (
		pub fn register() {
			use std::any::TypeId;
			$(
				let mut_ts = vec![ $( TypeId::of::< $mut_typ >() ),* ];
				let ts = vec![ $( TypeId::of::< $typ >() ),* ];
				super::$event_name::register_handler($event_name, ts, mut_ts);
			)*
		}
	)
}
<|endoftext|>


<commit_before>#![feature(test)]
extern crate test;
extern crate regex;

extern crate betabear;

use test::Bencher;

static DICTIONARY: &'static str = include_str!("/usr/share/dict/words");

#[bench]
fn build_1(b: &mut Bencher) {
    let given_letters = "noraanoraanoraa";
    let word = "aaronaaronaaron";

    b.iter(|| {
        let mut given_letters = given_letters.chars().collect::<Vec<char>>();
        given_letters.sort(); // For binary_search down the road

        for letter in word.chars() {
            if let Ok(index) = given_letters.binary_search(&letter) {
                given_letters.remove(index);
            } else {
                return false;
            }
        }

        true
    })
}

#[bench]
fn build_1_prepare_first(b: &mut Bencher) {
    let word = "aaronaaronaaron";
    let given_letters = "noraanoraanoraa";

    let mut given_letters = given_letters.chars().collect::<Vec<char>>();
    given_letters.sort(); // For binary_search down the road

    b.iter(|| {
        let mut given_letters = given_letters.clone();
        for letter in word.chars() {
            if let Ok(index) = given_letters.binary_search(&letter) {
                given_letters.remove(index);
            } else {
                return false;
            }
        }

        true
    })
}

#[bench]
fn build_1_check_len_first(b: &mut Bencher) {
    let given_letters = "noraanoraanoraa";
    let word = "aaronaaronaaron";

    b.iter(|| {
        let mut given_letters = given_letters.chars().collect::<Vec<char>>();

        if given_letters.len() < word.chars().count() {
            return false;
        }

        given_letters.sort(); // For binary_search down the road

        for letter in word.chars() {
            if let Ok(index) = given_letters.binary_search(&letter) {
                given_letters.remove(index);
            } else {
                return false;
            }
        }

        true
    })
}

#[bench]
fn build_no_binary_search(b: &mut Bencher) {
    let given_letters = "noraanoraanoraa";
    let word = "aaronaaronaaron";

    b.iter(|| {
        let mut given_letters = given_letters.chars().collect::<Vec<char>>();

        for letter in word.chars() {
            if let Some(index) = given_letters.iter().position(|&x| x == letter) {
                given_letters.remove(index);
            } else {
                return false;
            }
        }

        true
    })
}

#[bench]
fn build_no_binary_search_prepared(b: &mut Bencher) {
    let given_letters = "noraanoraanoraa";
    let word = "aaronaaronaaron";

    let given_letters = given_letters.chars().collect::<Vec<char>>();

    b.iter(|| {
        let mut given_letters = given_letters.clone();

        for letter in word.chars() {
            if let Some(index) = given_letters.iter().position(|&x| x == letter) {
                given_letters.remove(index);
            } else {
                return false;
            }
        }

        true
    })
}

#[bench]
fn build_no_binary_search_prepared_and_sorted(b: &mut Bencher) {
    let given_letters = "noraanoraanoraa";
    let word = "aaronaaronaaron";

    let mut given_letters = given_letters.chars().collect::<Vec<char>>();
    given_letters.sort();

    b.iter(|| {
        let mut given_letters = given_letters.clone();

        for letter in word.chars() {
            if let Some(index) = given_letters.iter().position(|&x| x == letter) {
                given_letters.remove(index);
            } else {
                return false;
            }
        }

        true
    })
}

#[bench]
#[ignore]
fn search_1(b: &mut Bencher) {
    let letters = "noraa";
    let letters = letters.trim().chars().collect::<Vec<char>>();

    b.iter(|| {
        let mut matches = DICTIONARY.lines()
                                    .filter(|word| betabear::build_with_letters(&letters, word))
                                    .map(|word| (word, word.chars().count()))
                                    .collect::<Vec<(&str, usize)>>();

        matches.sort_by(|a, b| b.1.cmp(&a.1));

        matches
    })
}

#[bench]
#[ignore]
fn search_1_with_regex(b: &mut Bencher) {
    let letters = "noraa";

    let regex = regex::Regex::new(&format!("^[{}]+$", letters))
                    .expect("String of given letters is malformed.");

    let letters = letters.trim().chars().collect::<Vec<char>>();

    b.iter(|| {
        let mut matches = DICTIONARY.lines()
                                    .filter(|word| regex.is_match(word))
                                    .filter(|word| betabear::build_with_letters(&letters, word))
                                    .map(|word| (word, word.chars().count()))
                                    .collect::<Vec<(&str, usize)>>();

        matches.sort_by(|a, b| b.1.cmp(&a.1));

        matches
    })
}
<commit_msg>Add some benches<commit_after>#![feature(test)]
extern crate test;
extern crate regex;

extern crate betabear;

use test::Bencher;

static DICTIONARY: &'static str = include_str!("/usr/share/dict/words");

#[bench]
fn build_binary_search(b: &mut Bencher) {
    let given_letters = "noraanoraanoraa";
    let word = "aaronaaronaaron";

    b.bytes = given_letters.len() as u64;

    b.iter(|| {
        let mut given_letters = given_letters.chars().collect::<Vec<char>>();
        given_letters.sort(); // For binary_search down the road

        for letter in word.chars() {
            if let Ok(index) = given_letters.binary_search(&letter) {
                given_letters.remove(index);
            } else {
                return false;
            }
        }

        true
    })
}

#[bench]
fn build_binary_search_prepare_first(b: &mut Bencher) {
    let word = "aaronaaronaaron";
    let given_letters = "noraanoraanoraa";

    b.bytes = given_letters.len() as u64;

    let mut given_letters = given_letters.chars().collect::<Vec<char>>();
    given_letters.sort(); // For binary_search down the road

    b.iter(|| {
        let mut given_letters = given_letters.clone();
        for letter in word.chars() {
            if let Ok(index) = given_letters.binary_search(&letter) {
                given_letters.remove(index);
            } else {
                return false;
            }
        }

        true
    })
}

#[bench]
fn build_binary_search_check_len_first(b: &mut Bencher) {
    let given_letters = "noraanoraanoraa";
    let word = "aaronaaronaaron";

    b.bytes = given_letters.len() as u64;

    b.iter(|| {
        let mut given_letters = given_letters.chars().collect::<Vec<char>>();

        if given_letters.len() < word.chars().count() {
            return false;
        }

        given_letters.sort(); // For binary_search down the road

        for letter in word.chars() {
            if let Ok(index) = given_letters.binary_search(&letter) {
                given_letters.remove(index);
            } else {
                return false;
            }
        }

        true
    })
}

#[bench]
fn build_trivial_search(b: &mut Bencher) {
    let given_letters = "noraanoraanoraa";
    let word = "aaronaaronaaron";

    b.bytes = given_letters.len() as u64;

    b.iter(|| {
        let mut given_letters = given_letters.chars().collect::<Vec<char>>();

        for letter in word.chars() {
            if let Some(index) = given_letters.iter().position(|&x| x == letter) {
                given_letters.remove(index);
            } else {
                return false;
            }
        }

        true
    })
}

#[bench]
fn build_trivial_search_prepared(b: &mut Bencher) {
    let given_letters = "noraanoraanoraa";
    let word = "aaronaaronaaron";

    b.bytes = given_letters.len() as u64;

    let given_letters = given_letters.chars().collect::<Vec<char>>();

    b.iter(|| {
        let mut given_letters = given_letters.clone();

        for letter in word.chars() {
            if let Some(index) = given_letters.iter().position(|&x| x == letter) {
                given_letters.remove(index);
            } else {
                return false;
            }
        }

        true
    })
}

#[bench]
fn build_trivial_search_prepared_len_check(b: &mut Bencher) {
    let given_letters = "noraanoraanoraa";
    let word = "aaronaaronaaron";

    b.bytes = given_letters.len() as u64;

    let given_letters = given_letters.chars().collect::<Vec<char>>();

    b.iter(|| {
        let mut given_letters = given_letters.clone();

        if given_letters.len() < word.chars().count() {
            return false;
        }

        for letter in word.chars() {
            if let Some(index) = given_letters.iter().position(|&x| x == letter) {
                given_letters.remove(index);
            } else {
                return false;
            }
        }

        true
    })
}

#[bench]
fn build_trivial_search_prepared_and_sorted(b: &mut Bencher) {
    let given_letters = "noraanoraanoraa";
    let word = "aaronaaronaaron";

    b.bytes = given_letters.len() as u64;

    let mut given_letters = given_letters.chars().collect::<Vec<char>>();
    given_letters.sort();

    b.iter(|| {
        let mut given_letters = given_letters.clone();

        for letter in word.chars() {
            if let Some(index) = given_letters.iter().position(|&x| x == letter) {
                given_letters.remove(index);
            } else {
                return false;
            }
        }

        true
    })
}

#[bench]
fn build_trivial_search_with_chars_everywhere(b: &mut Bencher) {
    let given_letters = "noraanoraanoraa";
    let word = "aaronaaronaaron";

    b.bytes = given_letters.len() as u64;

    let given_letters = given_letters.chars().collect::<Vec<char>>();
    let word = word.chars().collect::<Vec<char>>();

    b.iter(|| {
        let mut given_letters = given_letters.clone();

        for letter in &word {
            if let Some(index) = given_letters.iter().position(|&x| x == *letter) {
                given_letters.remove(index);
            } else {
                return false;
            }
        }

        true
    })
}

#[bench]
fn build_trivial_search_with_sorted_chars_everywhere(b: &mut Bencher) {
    let given_letters = "noraanoraanoraa";
    let word = "aaronaaronaaron";

    b.bytes = given_letters.len() as u64;

    let mut given_letters = given_letters.chars().collect::<Vec<char>>();
    given_letters.sort();

    let mut word = word.chars().collect::<Vec<char>>();
    word.sort();

    b.iter(|| {
        let mut given_letters = given_letters.clone();

        for letter in &word {
            if let Some(index) = given_letters.iter().position(|&x| x == *letter) {
                given_letters.remove(index);
            } else {
                return false;
            }
        }

        true
    })
}

#[bench]
#[ignore]
fn search_1(b: &mut Bencher) {
    b.bytes = DICTIONARY.len() as u64;

    let letters = "noraa";
    let letters = letters.trim().chars().collect::<Vec<char>>();

    b.iter(|| {
        let mut matches = DICTIONARY.lines()
                                    .filter(|word| betabear::build_with_letters(&letters, word))
                                    .map(|word| (word, word.chars().count()))
                                    .collect::<Vec<(&str, usize)>>();

        matches.sort_by(|a, b| b.1.cmp(&a.1));

        matches
    })
}

#[bench]
#[ignore]
fn search_1_with_regex(b: &mut Bencher) {
    b.bytes = DICTIONARY.len() as u64;

    let letters = "noraa";

    let regex = regex::Regex::new(&format!("^[{}]+$", letters))
                    .expect("String of given letters is malformed.");

    let letters = letters.trim().chars().collect::<Vec<char>>();

    b.iter(|| {
        let mut matches = DICTIONARY.lines()
                                    .filter(|word| regex.is_match(word))
                                    .filter(|word| betabear::build_with_letters(&letters, word))
                                    .map(|word| (word, word.chars().count()))
                                    .collect::<Vec<(&str, usize)>>();

        matches.sort_by(|a, b| b.1.cmp(&a.1));

        matches
    })
}

#[bench]
#[ignore]
fn search_1_with_better_regex(b: &mut Bencher) {
    b.bytes = DICTIONARY.len() as u64;

    let letters = "noraa";

    let regex = regex::Regex::new(&format!("^[{}]{{1,{num}}}$",
                                           letters,
                                           num = letters.chars().count()))
                    .expect("String of given letters is malformed.");

    let letters = letters.trim().chars().collect::<Vec<char>>();

    b.iter(|| {
        let mut matches = DICTIONARY.lines()
                                    .filter(|word| regex.is_match(word))
                                    .filter(|word| betabear::build_with_letters(&letters, word))
                                    .map(|word| (word, word.chars().count()))
                                    .collect::<Vec<(&str, usize)>>();

        matches.sort_by(|a, b| b.1.cmp(&a.1));

        matches
    })
}
<|endoftext|>


<commit_before>use llvm_sys::core::LLVMGetTypeKind;
use llvm_sys::LLVMTypeKind;
use llvm_sys::prelude::LLVMTypeRef;

use crate::types::{IntType, VoidType, FunctionType, PointerType, VectorType, ArrayType, StructType, FloatType};
use crate::types::traits::AsTypeRef;
use crate::values::IntValue;

use std::convert::TryFrom;

macro_rules! enum_type_set {
    ($(#[$enum_attrs:meta])* $enum_name:ident: { $($(#[$variant_attrs:meta])* $args:ident,)+ }) => (
        #[derive(Debug, PartialEq, Eq, Clone, Copy)]
        $(#[$enum_attrs])*
        pub enum $enum_name<'ctx> {
            $(
                $(#[$variant_attrs])*
                $args($args<'ctx>),
            )*
        }

        impl AsTypeRef for $enum_name<'_> {
            fn as_type_ref(&self) -> LLVMTypeRef {
                match *self {
                    $(
                        $enum_name::$args(ref t) => t.as_type_ref(),
                    )*
                }
            }
        }

        $(
            impl<'ctx> From<$args<'ctx>> for $enum_name<'ctx> {
                fn from(value: $args) -> $enum_name {
                    $enum_name::$args(value)
                }
            }

            impl<'ctx> TryFrom<$enum_name<'ctx>> for $args<'ctx> {
                type Error = ();

                fn try_from(value: $enum_name<'ctx>) -> Result<Self, Self::Error> {
                    match value {
                        $enum_name::$args(ty) => Ok(ty),
                        _ => Err(()),
                    }
                }
            }
        )*
    );
}

enum_type_set! {
    /// A wrapper for any `BasicType`, `VoidType`, or `FunctionType`.
    AnyTypeEnum: {
        /// A contiguous homogeneous container type.
        ArrayType,
        /// A floating point type.
        FloatType,
        /// A function return and parameter definition.
        FunctionType,
        /// An integer type.
        IntType,
        /// A pointer type.
        PointerType,
        /// A contiguous heterogeneous container type.
        StructType,
        /// A contiguous homogeneous "SIMD" container type.
        VectorType,
        /// A valueless type.
        VoidType,
    }
}
enum_type_set! {
    /// A wrapper for any `BasicType`.
    BasicTypeEnum: {
        /// A contiguous homogeneous container type.
        ArrayType,
        /// A floating point type.
        FloatType,
        // An integer type.
        IntType,
        /// A pointer type.
        PointerType,
        /// A contiguous heterogeneous container type.
        StructType,
        /// A contiguous homogeneous "SIMD" container type.
        VectorType,
    }
}

impl<'ctx> AnyTypeEnum<'ctx> {
    pub(crate) fn new(type_: LLVMTypeRef) -> Self {
        let type_kind = unsafe {
            LLVMGetTypeKind(type_)
        };

        match type_kind {
            LLVMTypeKind::LLVMVoidTypeKind => AnyTypeEnum::VoidType(VoidType::new(type_)),
            LLVMTypeKind::LLVMHalfTypeKind |
            LLVMTypeKind::LLVMFloatTypeKind |
            LLVMTypeKind::LLVMDoubleTypeKind |
            LLVMTypeKind::LLVMX86_FP80TypeKind |
            LLVMTypeKind::LLVMFP128TypeKind |
            LLVMTypeKind::LLVMPPC_FP128TypeKind => AnyTypeEnum::FloatType(FloatType::new(type_)),
            #[cfg(feature = "llvm11-0")]
            LLVMTypeKind::LLVMBFloatTypeKind => AnyTypeEnum::FloatType(FloatType::new(type_)),
            LLVMTypeKind::LLVMLabelTypeKind => panic!("FIXME: Unsupported type: Label"),
            LLVMTypeKind::LLVMIntegerTypeKind => AnyTypeEnum::IntType(IntType::new(type_)),
            LLVMTypeKind::LLVMFunctionTypeKind => AnyTypeEnum::FunctionType(FunctionType::new(type_)),
            LLVMTypeKind::LLVMStructTypeKind => AnyTypeEnum::StructType(StructType::new(type_)),
            LLVMTypeKind::LLVMArrayTypeKind => AnyTypeEnum::ArrayType(ArrayType::new(type_)),
            LLVMTypeKind::LLVMPointerTypeKind => AnyTypeEnum::PointerType(PointerType::new(type_)),
            LLVMTypeKind::LLVMVectorTypeKind => AnyTypeEnum::VectorType(VectorType::new(type_)),
            #[cfg(feature = "llvm11-0")]
            LLVMTypeKind::LLVMScalableVectorTypeKind => AnyTypeEnum::VectorType(VectorType::new(type_)),
            LLVMTypeKind::LLVMMetadataTypeKind => panic!("FIXME: Unsupported type: Metadata"),
            LLVMTypeKind::LLVMX86_MMXTypeKind => panic!("FIXME: Unsupported type: MMX"),
            #[cfg(not(any(feature = "llvm3-6", feature = "llvm3-7")))]
            LLVMTypeKind::LLVMTokenTypeKind => panic!("FIXME: Unsupported type: Token"),
        }
    }

    /// This will panic if type is a void or function type.
    pub(crate) fn to_basic_type_enum(&self) -> BasicTypeEnum<'ctx> {
        BasicTypeEnum::new(self.as_type_ref())
    }

    pub fn into_array_type(self) -> ArrayType<'ctx> {
        if let AnyTypeEnum::ArrayType(t) = self {
            t
        } else {
            panic!("Found {:?} but expected another variant", self);
        }
    }

    pub fn into_float_type(self) -> FloatType<'ctx> {
        if let AnyTypeEnum::FloatType(t) = self {
            t
        } else {
            panic!("Found {:?} but expected another variant", self);
        }
    }

    pub fn into_function_type(self) -> FunctionType<'ctx> {
        if let AnyTypeEnum::FunctionType(t) = self {
            t
        } else {
            panic!("Found {:?} but expected another variant", self);
        }
    }

    pub fn into_int_type(self) -> IntType<'ctx> {
        if let AnyTypeEnum::IntType(t) = self {
            t
        } else {
            panic!("Found {:?} but expected another variant", self);
        }
    }

    pub fn into_pointer_type(self) -> PointerType<'ctx> {
        if let AnyTypeEnum::PointerType(t) = self {
            t
        } else {
            panic!("Found {:?} but expected another variant", self);
        }
    }

    pub fn into_struct_type(self) -> StructType<'ctx> {
        if let AnyTypeEnum::StructType(t) = self {
            t
        } else {
            panic!("Found {:?} but expected another variant", self);
        }
    }

    pub fn into_vector_type(self) -> VectorType<'ctx> {
        if let AnyTypeEnum::VectorType(t) = self {
            t
        } else {
            panic!("Found {:?} but expected another variant", self);
        }
    }

    pub fn into_void_type(self) -> VoidType<'ctx> {
        if let AnyTypeEnum::VoidType(t) = self {
            t
        } else {
            panic!("Found {:?} but expected another variant", self);
        }
    }

    pub fn is_array_type(self) -> bool {
        if let AnyTypeEnum::ArrayType(_) = self {
            true
        } else {
            false
        }
    }

    pub fn is_float_type(self) -> bool {
        if let AnyTypeEnum::FloatType(_) = self {
            true
        } else {
            false
        }
    }

    pub fn is_function_type(self) -> bool {
        if let AnyTypeEnum::FunctionType(_) = self {
            true
        } else {
            false
        }
    }

    pub fn is_int_type(self) -> bool {
        if let AnyTypeEnum::IntType(_) = self {
            true
        } else {
            false
        }
    }

    pub fn is_pointer_type(self) -> bool {
        if let AnyTypeEnum::PointerType(_) = self {
            true
        } else {
            false
        }
    }

    pub fn is_struct_type(self) -> bool {
        if let AnyTypeEnum::StructType(_) = self {
            true
        } else {
            false
        }
    }

    pub fn is_vector_type(self) -> bool {
        if let AnyTypeEnum::VectorType(_) = self {
            true
        } else {
            false
        }
    }

    pub fn is_void_type(self) -> bool {
        if let AnyTypeEnum::VoidType(_) = self {
            true
        } else {
            false
        }
    }

    pub fn size_of(&self) -> Option<IntValue<'ctx>> {
        match self {
            AnyTypeEnum::ArrayType(t) => t.size_of(),
            AnyTypeEnum::FloatType(t) => Some(t.size_of()),
            AnyTypeEnum::IntType(t) => Some(t.size_of()),
            AnyTypeEnum::PointerType(t) => Some(t.size_of()),
            AnyTypeEnum::StructType(t) => t.size_of(),
            AnyTypeEnum::VectorType(t) => t.size_of(),
            AnyTypeEnum::VoidType(_) => None,
            AnyTypeEnum::FunctionType(_) => None,
        }
    }
}

impl<'ctx> BasicTypeEnum<'ctx> {
    pub(crate) fn new(type_: LLVMTypeRef) -> Self {
        let type_kind = unsafe {
            LLVMGetTypeKind(type_)
        };

        match type_kind {
            LLVMTypeKind::LLVMHalfTypeKind |
            LLVMTypeKind::LLVMFloatTypeKind |
            LLVMTypeKind::LLVMDoubleTypeKind |
            LLVMTypeKind::LLVMX86_FP80TypeKind |
            LLVMTypeKind::LLVMFP128TypeKind |
            LLVMTypeKind::LLVMPPC_FP128TypeKind => BasicTypeEnum::FloatType(FloatType::new(type_)),
            #[cfg(feature= "llvm11-0")]
            LLVMTypeKind::LLVMBFloatTypeKind => BasicTypeEnum::FloatType(FloatType::new(type_)),
            LLVMTypeKind::LLVMIntegerTypeKind => BasicTypeEnum::IntType(IntType::new(type_)),
            LLVMTypeKind::LLVMStructTypeKind => BasicTypeEnum::StructType(StructType::new(type_)),
            LLVMTypeKind::LLVMPointerTypeKind => BasicTypeEnum::PointerType(PointerType::new(type_)),
            LLVMTypeKind::LLVMArrayTypeKind => BasicTypeEnum::ArrayType(ArrayType::new(type_)),
            LLVMTypeKind::LLVMVectorTypeKind => BasicTypeEnum::VectorType(VectorType::new(type_)),
            #[cfg(feature= "llvm11-0")]
            LLVMTypeKind::LLVMScalableVectorTypeKind => BasicTypeEnum::VectorType(VectorType::new(type_)),
            LLVMTypeKind::LLVMMetadataTypeKind => unreachable!("Unsupported basic type: Metadata"),
            LLVMTypeKind::LLVMX86_MMXTypeKind => unreachable!("Unsupported basic type: MMX"),
            LLVMTypeKind::LLVMLabelTypeKind => unreachable!("Unsupported basic type: Label"),
            LLVMTypeKind::LLVMVoidTypeKind => unreachable!("Unsupported basic type: VoidType"),
            LLVMTypeKind::LLVMFunctionTypeKind => unreachable!("Unsupported basic type: FunctionType"),
            #[cfg(not(any(feature = "llvm3-6", feature = "llvm3-7")))]
            LLVMTypeKind::LLVMTokenTypeKind => unreachable!("Unsupported basic type: Token"),
        }
    }

    pub fn into_array_type(self) -> ArrayType<'ctx> {
        if let BasicTypeEnum::ArrayType(t) = self {
            t
        } else {
            panic!("Found {:?} but expected another variant", self);
        }
    }

    pub fn into_float_type(self) -> FloatType<'ctx> {
        if let BasicTypeEnum::FloatType(t) = self {
            t
        } else {
            panic!("Found {:?} but expected another variant", self);
        }
    }

    pub fn into_int_type(self) -> IntType<'ctx> {
        if let BasicTypeEnum::IntType(t) = self {
            t
        } else {
            panic!("Found {:?} but expected another variant", self);
        }
    }

    pub fn into_pointer_type(self) -> PointerType<'ctx> {
        if let BasicTypeEnum::PointerType(t) = self {
            t
        } else {
            panic!("Found {:?} but expected another variant", self);
        }
    }

    pub fn into_struct_type(self) -> StructType<'ctx> {
        if let BasicTypeEnum::StructType(t) = self {
            t
        } else {
            panic!("Found {:?} but expected another variant", self);
        }
    }

    pub fn into_vector_type(self) -> VectorType<'ctx> {
        if let BasicTypeEnum::VectorType(t) = self {
            t
        } else {
            panic!("Found {:?} but expected another variant", self);
        }
    }

    pub fn is_array_type(self) -> bool {
        if let BasicTypeEnum::ArrayType(_) = self {
            true
        } else {
            false
        }
    }

    pub fn is_float_type(self) -> bool {
        if let BasicTypeEnum::FloatType(_) = self {
            true
        } else {
            false
        }
    }

    pub fn is_int_type(self) -> bool {
        if let BasicTypeEnum::IntType(_) = self {
            true
        } else {
            false
        }
    }

    pub fn is_pointer_type(self) -> bool {
        if let BasicTypeEnum::PointerType(_) = self {
            true
        } else {
            false
        }
    }

    pub fn is_struct_type(self) -> bool {
        if let BasicTypeEnum::StructType(_) = self {
            true
        } else {
            false
        }
    }

    pub fn is_vector_type(self) -> bool {
        if let BasicTypeEnum::VectorType(_) = self {
            true
        } else {
            false
        }
    }
}

impl<'ctx> TryFrom<AnyTypeEnum<'ctx>> for BasicTypeEnum<'ctx> {
    type Error = ();

    fn try_from(value: AnyTypeEnum<'ctx>) -> Result<Self, Self::Error> {
        Ok(match value {
            AnyTypeEnum::ArrayType(at) => at.into(),
            AnyTypeEnum::FloatType(ft) => ft.into(),
            AnyTypeEnum::IntType(it) => it.into(),
            AnyTypeEnum::PointerType(pt) => pt.into(),
            AnyTypeEnum::StructType(st) => st.into(),
            AnyTypeEnum::VectorType(vt) => vt.into(),
            _ => return Err(()),
        })
    }
}
<commit_msg>Fix typo, this comment was meant to be a doc-comment.<commit_after>use llvm_sys::core::LLVMGetTypeKind;
use llvm_sys::LLVMTypeKind;
use llvm_sys::prelude::LLVMTypeRef;

use crate::types::{IntType, VoidType, FunctionType, PointerType, VectorType, ArrayType, StructType, FloatType};
use crate::types::traits::AsTypeRef;
use crate::values::IntValue;

use std::convert::TryFrom;

macro_rules! enum_type_set {
    ($(#[$enum_attrs:meta])* $enum_name:ident: { $($(#[$variant_attrs:meta])* $args:ident,)+ }) => (
        #[derive(Debug, PartialEq, Eq, Clone, Copy)]
        $(#[$enum_attrs])*
        pub enum $enum_name<'ctx> {
            $(
                $(#[$variant_attrs])*
                $args($args<'ctx>),
            )*
        }

        impl AsTypeRef for $enum_name<'_> {
            fn as_type_ref(&self) -> LLVMTypeRef {
                match *self {
                    $(
                        $enum_name::$args(ref t) => t.as_type_ref(),
                    )*
                }
            }
        }

        $(
            impl<'ctx> From<$args<'ctx>> for $enum_name<'ctx> {
                fn from(value: $args) -> $enum_name {
                    $enum_name::$args(value)
                }
            }

            impl<'ctx> TryFrom<$enum_name<'ctx>> for $args<'ctx> {
                type Error = ();

                fn try_from(value: $enum_name<'ctx>) -> Result<Self, Self::Error> {
                    match value {
                        $enum_name::$args(ty) => Ok(ty),
                        _ => Err(()),
                    }
                }
            }
        )*
    );
}

enum_type_set! {
    /// A wrapper for any `BasicType`, `VoidType`, or `FunctionType`.
    AnyTypeEnum: {
        /// A contiguous homogeneous container type.
        ArrayType,
        /// A floating point type.
        FloatType,
        /// A function return and parameter definition.
        FunctionType,
        /// An integer type.
        IntType,
        /// A pointer type.
        PointerType,
        /// A contiguous heterogeneous container type.
        StructType,
        /// A contiguous homogeneous "SIMD" container type.
        VectorType,
        /// A valueless type.
        VoidType,
    }
}
enum_type_set! {
    /// A wrapper for any `BasicType`.
    BasicTypeEnum: {
        /// A contiguous homogeneous container type.
        ArrayType,
        /// A floating point type.
        FloatType,
        /// An integer type.
        IntType,
        /// A pointer type.
        PointerType,
        /// A contiguous heterogeneous container type.
        StructType,
        /// A contiguous homogeneous "SIMD" container type.
        VectorType,
    }
}

impl<'ctx> AnyTypeEnum<'ctx> {
    pub(crate) fn new(type_: LLVMTypeRef) -> Self {
        let type_kind = unsafe {
            LLVMGetTypeKind(type_)
        };

        match type_kind {
            LLVMTypeKind::LLVMVoidTypeKind => AnyTypeEnum::VoidType(VoidType::new(type_)),
            LLVMTypeKind::LLVMHalfTypeKind |
            LLVMTypeKind::LLVMFloatTypeKind |
            LLVMTypeKind::LLVMDoubleTypeKind |
            LLVMTypeKind::LLVMX86_FP80TypeKind |
            LLVMTypeKind::LLVMFP128TypeKind |
            LLVMTypeKind::LLVMPPC_FP128TypeKind => AnyTypeEnum::FloatType(FloatType::new(type_)),
            #[cfg(feature = "llvm11-0")]
            LLVMTypeKind::LLVMBFloatTypeKind => AnyTypeEnum::FloatType(FloatType::new(type_)),
            LLVMTypeKind::LLVMLabelTypeKind => panic!("FIXME: Unsupported type: Label"),
            LLVMTypeKind::LLVMIntegerTypeKind => AnyTypeEnum::IntType(IntType::new(type_)),
            LLVMTypeKind::LLVMFunctionTypeKind => AnyTypeEnum::FunctionType(FunctionType::new(type_)),
            LLVMTypeKind::LLVMStructTypeKind => AnyTypeEnum::StructType(StructType::new(type_)),
            LLVMTypeKind::LLVMArrayTypeKind => AnyTypeEnum::ArrayType(ArrayType::new(type_)),
            LLVMTypeKind::LLVMPointerTypeKind => AnyTypeEnum::PointerType(PointerType::new(type_)),
            LLVMTypeKind::LLVMVectorTypeKind => AnyTypeEnum::VectorType(VectorType::new(type_)),
            #[cfg(feature = "llvm11-0")]
            LLVMTypeKind::LLVMScalableVectorTypeKind => AnyTypeEnum::VectorType(VectorType::new(type_)),
            LLVMTypeKind::LLVMMetadataTypeKind => panic!("FIXME: Unsupported type: Metadata"),
            LLVMTypeKind::LLVMX86_MMXTypeKind => panic!("FIXME: Unsupported type: MMX"),
            #[cfg(not(any(feature = "llvm3-6", feature = "llvm3-7")))]
            LLVMTypeKind::LLVMTokenTypeKind => panic!("FIXME: Unsupported type: Token"),
        }
    }

    /// This will panic if type is a void or function type.
    pub(crate) fn to_basic_type_enum(&self) -> BasicTypeEnum<'ctx> {
        BasicTypeEnum::new(self.as_type_ref())
    }

    pub fn into_array_type(self) -> ArrayType<'ctx> {
        if let AnyTypeEnum::ArrayType(t) = self {
            t
        } else {
            panic!("Found {:?} but expected another variant", self);
        }
    }

    pub fn into_float_type(self) -> FloatType<'ctx> {
        if let AnyTypeEnum::FloatType(t) = self {
            t
        } else {
            panic!("Found {:?} but expected another variant", self);
        }
    }

    pub fn into_function_type(self) -> FunctionType<'ctx> {
        if let AnyTypeEnum::FunctionType(t) = self {
            t
        } else {
            panic!("Found {:?} but expected another variant", self);
        }
    }

    pub fn into_int_type(self) -> IntType<'ctx> {
        if let AnyTypeEnum::IntType(t) = self {
            t
        } else {
            panic!("Found {:?} but expected another variant", self);
        }
    }

    pub fn into_pointer_type(self) -> PointerType<'ctx> {
        if let AnyTypeEnum::PointerType(t) = self {
            t
        } else {
            panic!("Found {:?} but expected another variant", self);
        }
    }

    pub fn into_struct_type(self) -> StructType<'ctx> {
        if let AnyTypeEnum::StructType(t) = self {
            t
        } else {
            panic!("Found {:?} but expected another variant", self);
        }
    }

    pub fn into_vector_type(self) -> VectorType<'ctx> {
        if let AnyTypeEnum::VectorType(t) = self {
            t
        } else {
            panic!("Found {:?} but expected another variant", self);
        }
    }

    pub fn into_void_type(self) -> VoidType<'ctx> {
        if let AnyTypeEnum::VoidType(t) = self {
            t
        } else {
            panic!("Found {:?} but expected another variant", self);
        }
    }

    pub fn is_array_type(self) -> bool {
        if let AnyTypeEnum::ArrayType(_) = self {
            true
        } else {
            false
        }
    }

    pub fn is_float_type(self) -> bool {
        if let AnyTypeEnum::FloatType(_) = self {
            true
        } else {
            false
        }
    }

    pub fn is_function_type(self) -> bool {
        if let AnyTypeEnum::FunctionType(_) = self {
            true
        } else {
            false
        }
    }

    pub fn is_int_type(self) -> bool {
        if let AnyTypeEnum::IntType(_) = self {
            true
        } else {
            false
        }
    }

    pub fn is_pointer_type(self) -> bool {
        if let AnyTypeEnum::PointerType(_) = self {
            true
        } else {
            false
        }
    }

    pub fn is_struct_type(self) -> bool {
        if let AnyTypeEnum::StructType(_) = self {
            true
        } else {
            false
        }
    }

    pub fn is_vector_type(self) -> bool {
        if let AnyTypeEnum::VectorType(_) = self {
            true
        } else {
            false
        }
    }

    pub fn is_void_type(self) -> bool {
        if let AnyTypeEnum::VoidType(_) = self {
            true
        } else {
            false
        }
    }

    pub fn size_of(&self) -> Option<IntValue<'ctx>> {
        match self {
            AnyTypeEnum::ArrayType(t) => t.size_of(),
            AnyTypeEnum::FloatType(t) => Some(t.size_of()),
            AnyTypeEnum::IntType(t) => Some(t.size_of()),
            AnyTypeEnum::PointerType(t) => Some(t.size_of()),
            AnyTypeEnum::StructType(t) => t.size_of(),
            AnyTypeEnum::VectorType(t) => t.size_of(),
            AnyTypeEnum::VoidType(_) => None,
            AnyTypeEnum::FunctionType(_) => None,
        }
    }
}

impl<'ctx> BasicTypeEnum<'ctx> {
    pub(crate) fn new(type_: LLVMTypeRef) -> Self {
        let type_kind = unsafe {
            LLVMGetTypeKind(type_)
        };

        match type_kind {
            LLVMTypeKind::LLVMHalfTypeKind |
            LLVMTypeKind::LLVMFloatTypeKind |
            LLVMTypeKind::LLVMDoubleTypeKind |
            LLVMTypeKind::LLVMX86_FP80TypeKind |
            LLVMTypeKind::LLVMFP128TypeKind |
            LLVMTypeKind::LLVMPPC_FP128TypeKind => BasicTypeEnum::FloatType(FloatType::new(type_)),
            #[cfg(feature= "llvm11-0")]
            LLVMTypeKind::LLVMBFloatTypeKind => BasicTypeEnum::FloatType(FloatType::new(type_)),
            LLVMTypeKind::LLVMIntegerTypeKind => BasicTypeEnum::IntType(IntType::new(type_)),
            LLVMTypeKind::LLVMStructTypeKind => BasicTypeEnum::StructType(StructType::new(type_)),
            LLVMTypeKind::LLVMPointerTypeKind => BasicTypeEnum::PointerType(PointerType::new(type_)),
            LLVMTypeKind::LLVMArrayTypeKind => BasicTypeEnum::ArrayType(ArrayType::new(type_)),
            LLVMTypeKind::LLVMVectorTypeKind => BasicTypeEnum::VectorType(VectorType::new(type_)),
            #[cfg(feature= "llvm11-0")]
            LLVMTypeKind::LLVMScalableVectorTypeKind => BasicTypeEnum::VectorType(VectorType::new(type_)),
            LLVMTypeKind::LLVMMetadataTypeKind => unreachable!("Unsupported basic type: Metadata"),
            LLVMTypeKind::LLVMX86_MMXTypeKind => unreachable!("Unsupported basic type: MMX"),
            LLVMTypeKind::LLVMLabelTypeKind => unreachable!("Unsupported basic type: Label"),
            LLVMTypeKind::LLVMVoidTypeKind => unreachable!("Unsupported basic type: VoidType"),
            LLVMTypeKind::LLVMFunctionTypeKind => unreachable!("Unsupported basic type: FunctionType"),
            #[cfg(not(any(feature = "llvm3-6", feature = "llvm3-7")))]
            LLVMTypeKind::LLVMTokenTypeKind => unreachable!("Unsupported basic type: Token"),
        }
    }

    pub fn into_array_type(self) -> ArrayType<'ctx> {
        if let BasicTypeEnum::ArrayType(t) = self {
            t
        } else {
            panic!("Found {:?} but expected another variant", self);
        }
    }

    pub fn into_float_type(self) -> FloatType<'ctx> {
        if let BasicTypeEnum::FloatType(t) = self {
            t
        } else {
            panic!("Found {:?} but expected another variant", self);
        }
    }

    pub fn into_int_type(self) -> IntType<'ctx> {
        if let BasicTypeEnum::IntType(t) = self {
            t
        } else {
            panic!("Found {:?} but expected another variant", self);
        }
    }

    pub fn into_pointer_type(self) -> PointerType<'ctx> {
        if let BasicTypeEnum::PointerType(t) = self {
            t
        } else {
            panic!("Found {:?} but expected another variant", self);
        }
    }

    pub fn into_struct_type(self) -> StructType<'ctx> {
        if let BasicTypeEnum::StructType(t) = self {
            t
        } else {
            panic!("Found {:?} but expected another variant", self);
        }
    }

    pub fn into_vector_type(self) -> VectorType<'ctx> {
        if let BasicTypeEnum::VectorType(t) = self {
            t
        } else {
            panic!("Found {:?} but expected another variant", self);
        }
    }

    pub fn is_array_type(self) -> bool {
        if let BasicTypeEnum::ArrayType(_) = self {
            true
        } else {
            false
        }
    }

    pub fn is_float_type(self) -> bool {
        if let BasicTypeEnum::FloatType(_) = self {
            true
        } else {
            false
        }
    }

    pub fn is_int_type(self) -> bool {
        if let BasicTypeEnum::IntType(_) = self {
            true
        } else {
            false
        }
    }

    pub fn is_pointer_type(self) -> bool {
        if let BasicTypeEnum::PointerType(_) = self {
            true
        } else {
            false
        }
    }

    pub fn is_struct_type(self) -> bool {
        if let BasicTypeEnum::StructType(_) = self {
            true
        } else {
            false
        }
    }

    pub fn is_vector_type(self) -> bool {
        if let BasicTypeEnum::VectorType(_) = self {
            true
        } else {
            false
        }
    }
}

impl<'ctx> TryFrom<AnyTypeEnum<'ctx>> for BasicTypeEnum<'ctx> {
    type Error = ();

    fn try_from(value: AnyTypeEnum<'ctx>) -> Result<Self, Self::Error> {
        Ok(match value {
            AnyTypeEnum::ArrayType(at) => at.into(),
            AnyTypeEnum::FloatType(ft) => ft.into(),
            AnyTypeEnum::IntType(it) => it.into(),
            AnyTypeEnum::PointerType(pt) => pt.into(),
            AnyTypeEnum::StructType(st) => st.into(),
            AnyTypeEnum::VectorType(vt) => vt.into(),
            _ => return Err(()),
        })
    }
}
<|endoftext|>


<commit_before>use alloc::collections::BinaryHeap;
use core::cmp::Ord;

pub(crate) fn k_smallest<T: Ord, I: Iterator<Item = T>>(mut iter: I, k: usize) -> BinaryHeap<T> {
    if k == 0 { return BinaryHeap::new(); }

    let mut heap = iter.by_ref().take(k).collect::<BinaryHeap<_>>();

    for i in iter {
        debug_assert_eq!(heap.len(), k);
        // Equivalent to heap.push(min(i, heap.pop())) but more efficient.
        // This should be done with a single `.peek_mut().unwrap()` but
        //  `PeekMut` sifts-down unconditionally on Rust 1.46.0 and prior.
        if *heap.peek().unwrap() > i {
            *heap.peek_mut().unwrap() = i;
        }
    }

    heap
}
<commit_msg>Use internal iteration in k_smallest<commit_after>use alloc::collections::BinaryHeap;
use core::cmp::Ord;

pub(crate) fn k_smallest<T: Ord, I: Iterator<Item = T>>(mut iter: I, k: usize) -> BinaryHeap<T> {
    if k == 0 { return BinaryHeap::new(); }

    let mut heap = iter.by_ref().take(k).collect::<BinaryHeap<_>>();

    iter.for_each(|i| {
        debug_assert_eq!(heap.len(), k);
        // Equivalent to heap.push(min(i, heap.pop())) but more efficient.
        // This should be done with a single `.peek_mut().unwrap()` but
        //  `PeekMut` sifts-down unconditionally on Rust 1.46.0 and prior.
        if *heap.peek().unwrap() > i {
            *heap.peek_mut().unwrap() = i;
        }
    });

    heap
}
<|endoftext|>