<commit_before>extern crate libc;

use std::ffi::CStr;
use std::os::raw::c_char;
use libc::size_t;
use libc::strncpy;

mod rnc {
    #[test]
    fn add_i_i() {
        assert_eq!("II", add("I", "I"));
    }

    #[test]
    fn add_i_ii() {
        assert_eq!("III", add("I", "II"));
    }

    #[test]
    fn add_ii_iii() {
        assert_eq!("V", add("II", "III"));

    }

    pub fn add(num_l: &str, num_r: &str) -> String {
        let sum = String::from(num_l) + num_r;

        if sum == "IIIII" {
            String::from("V")
        } else {
            sum
        }
    }
}

use rnc::add;

#[no_mangle]
pub extern fn rnc_add(dst: *mut c_char, dstlen: size_t, num_l: *const c_char, num_r: *const c_char) {
    unsafe {
        let sum = add(CStr::from_ptr(num_l).to_str().unwrap(), CStr::from_ptr(num_r).to_str().unwrap());
        strncpy(dst, sum.as_ptr() as *const i8, dstlen);
    }
}
<commit_msg>Use more idiomatic rust testing<commit_after>extern crate libc;

use std::ffi::CStr;
use std::os::raw::c_char;
use libc::size_t;
use libc::strncpy;

mod rnc {
    pub fn add(num_l: &str, num_r: &str) -> String {
        let sum = String::from(num_l) + num_r;

        if sum == "IIIII" {
            String::from("V")
        } else {
            sum
        }
    }

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

        #[test]
        fn add_i_i() {
            assert_eq!("II", add("I", "I"));
        }

        #[test]
        fn add_i_ii() {
            assert_eq!("III", add("I", "II"));
        }

        #[test]
        fn add_ii_iii() {
            assert_eq!("V", add("II", "III"));

        }
    }
}

use rnc::add;

#[no_mangle]
pub extern fn rnc_add(dst: *mut c_char, dstlen: size_t, num_l: *const c_char, num_r: *const c_char) {
    unsafe {
        let sum = add(CStr::from_ptr(num_l).to_str().unwrap(), CStr::from_ptr(num_r).to_str().unwrap());
        strncpy(dst, sum.as_ptr() as *const i8, dstlen);
    }
}
<|endoftext|>


<commit_before>use futures::{Async, Poll};

use super::{helpers, HttpHandlerTask, Writer};
use http::{StatusCode, Version};
use Error;

pub(crate) struct ServerError(Version, StatusCode);

impl ServerError {
    pub fn err(ver: Version, status: StatusCode) -> Box<HttpHandlerTask> {
        Box::new(ServerError(ver, status))
    }
}

impl HttpHandlerTask for ServerError {
    fn poll_io(&mut self, io: &mut Writer) -> Poll<bool, Error> {
        {
            let bytes = io.buffer();
            //Buffer should have sufficient capacity for status line
            //and extra space
            bytes.reserve(helpers::STATUS_LINE_BUF_SIZE + 1);
            helpers::write_status_line(self.0, self.1.as_u16(), bytes);
        }
        io.set_date();
        Ok(Async::Ready(true))
    }
}
<commit_msg>include content-length to error response<commit_after>use futures::{Async, Poll};

use super::{helpers, HttpHandlerTask, Writer};
use http::{StatusCode, Version};
use Error;

pub(crate) struct ServerError(Version, StatusCode);

impl ServerError {
    pub fn err(ver: Version, status: StatusCode) -> Box<HttpHandlerTask> {
        Box::new(ServerError(ver, status))
    }
}

impl HttpHandlerTask for ServerError {
    fn poll_io(&mut self, io: &mut Writer) -> Poll<bool, Error> {
        {
            let bytes = io.buffer();
            // Buffer should have sufficient capacity for status line
            // and extra space
            bytes.reserve(helpers::STATUS_LINE_BUF_SIZE + 1);
            helpers::write_status_line(self.0, self.1.as_u16(), bytes);
        }
        io.buffer().extend_from_slice(b"\r\ncontent-length: 0\r\n");
        io.set_date();
        Ok(Async::Ready(true))
    }
}
<|endoftext|>


<commit_before>use diesel::insert_into;
use diesel::prelude::*;
use diesel::result::Error as DieselError;
use diesel::sqlite::SqliteConnection;

use dotenv;

use clap::{arg_enum, crate_version, value_t_or_exit, App, AppSettings, Arg};

use prettytable as pt;
use pt::{cell, row};

use ratfist_server::db::models::Node;
use ratfist_server::meteo::models::{Sensor, SensorTypeEnum};

/// Prints the supplied data to STDOUT as a formatted ASCII table
fn print_table(mut title_row: pt::Row, table_rows: Vec<pt::Row>) {
    let was_empty = table_rows.is_empty();
    let table_width = title_row.len();

    let mut table = pt::Table::init(table_rows);

    for title_cell in title_row.iter_mut() {
        title_cell.style(pt::Attr::ForegroundColor(pt::color::BLUE));
    }

    table.set_titles(title_row);

    if was_empty {
        let row = pt::Row::new(vec![pt::Cell::new_align(
            "(none)",
            pt::format::Alignment::CENTER,
        )
        .with_hspan(table_width)]);
        table.add_row(row);
    }

    table.printstd();
}

/// Returns a Result with a vector of all sensor nodes in the database
fn db_get_node_list(db_conn: &SqliteConnection) -> Result<Vec<Node>, DieselError> {
    use ratfist_server::db::schema::nodes::dsl::*;

    nodes.load::<Node>(db_conn)
}

/// Prints a table with all sensor nodes
fn list_all_nodes(db_conn: &SqliteConnection) {
    let nodes = db_get_node_list(db_conn).expect("database access error");

    print_table(
        row!["Public ID", "Name", "Route Type", "Route Type Parameters"],
        nodes
            .into_iter()
            .map(|node| {
                row![
                    node.public_id,
                    node.name,
                    node.route_type,
                    node.route_param.unwrap_or_else(|| "".to_string())
                ]
            })
            .collect(),
    );
}

/// Returns an Ok Result with a list of all sensors for a given node, or an Err
/// if no such node exists.
fn db_get_sensor_list(
    db_conn: &SqliteConnection,
    public_node_id: i32,
) -> Result<Vec<Sensor>, DieselError> {
    let nid = {
        use ratfist_server::db::schema::nodes::dsl::*;

        nodes
            .filter(public_id.eq(public_node_id))
            .first::<Node>(db_conn)?
            .id
    };

    let sensors = {
        use ratfist_server::meteo::schema::sensors::dsl::*;
        sensors.filter(node_id.eq(nid)).load::<Sensor>(db_conn)?
    };

    Ok(sensors)
}

/// Prints a table with the sensors for a given node ID
fn list_sensors_in_node(db_conn: &SqliteConnection, node_id: i32) {
    match db_get_sensor_list(db_conn, node_id) {
        Ok(sensors) => {
            println!("Sensors in node {}:", node_id);
            print_table(
                row!["Public ID", "Type", "Name"],
                sensors
                    .into_iter()
                    .map(|sensor| row![sensor.public_id, sensor.sensor_type.as_ref(), sensor.name])
                    .collect(),
            )
        }
        Err(DieselError::NotFound) => println!("No node with ID {} found.", node_id),
        Err(other_err) => {
            panic!("Unhandled error: {:?}", other_err);
        }
    }
}

/// Adds a new sensor node with the given paramenters.
fn db_add_node(
    db_conn: &SqliteConnection,
    node_id: i32,
    node_name: &str,
    route_type: RouteTypes,
) -> Result<(), DieselError> {
    let route_type_str: &str = route_type.as_ref();

    {
        use ratfist_server::db::schema::nodes::dsl::*;

        insert_into(nodes)
            .values((
                public_id.eq(node_id),
                name.eq(node_name),
                route_type.eq(route_type_str),
            ))
            .execute(db_conn)
            .map(|_| ())
    }
}

/// Adds a new sensor node and handles the result of the DB operation.
fn add_node(db_conn: &SqliteConnection, node_id: i32, node_name: &str, route_type: RouteTypes) {
    match db_add_node(db_conn, node_id, node_name, route_type) {
        Ok(_) => {
            println!(
                "Succesfully created new sensor node: public_id {}, name '{}', route type {}",
                node_id,
                node_name,
                route_type.as_ref()
            );
        }
        Err(DieselError::DatabaseError(error_kind, error_details)) => {
            println!(
                "Failed to add new sensor node because of a DB error: {:?}",
                error_kind
            );
            println!("Error details: {:?}", error_details);
        }
        Err(other_err) => {
            panic!("Unhandled error: {:?}", other_err);
        }
    }
}

/// Adds a new sensor to a given sensor node.
fn db_add_sensor(
    db_conn: &SqliteConnection,
    parent_node_id: i32,
    sensor_id: i32,
    sensor_name: &str,
    sensor_type: SensorTypes,
) -> Result<(), DieselError> {
    let sensor_type_enum: SensorTypeEnum = sensor_type.into();

    let nid = {
        use ratfist_server::db::schema::nodes::dsl::*;

        nodes
            .filter(public_id.eq(parent_node_id))
            .first::<Node>(db_conn)?
            .id
    };

    {
        use ratfist_server::meteo::schema::sensors::dsl::*;

        insert_into(sensors)
            .values((
                public_id.eq(sensor_id),
                node_id.eq(nid),
                name.eq(sensor_name),
                sensor_type.eq(sensor_type_enum),
                name.eq(sensor_name),
            ))
            .execute(db_conn)
            .map(|_| ())
    }
}

/// Adds a new sensor to a given sensor node, and handles the result of the DB
/// operation.
fn add_sensor(
    db_conn: &SqliteConnection,
    parent_node_id: i32,
    sensor_id: i32,
    sensor_name: &str,
    sensor_type: SensorTypes,
) {
    match db_add_sensor(db_conn, parent_node_id, sensor_id, sensor_name, sensor_type) {
        Ok(_) => {
            println!(
                "Succesfully created new sensor for node #{}: public_id {}, name '{}', type {}",
                parent_node_id,
                sensor_id,
                sensor_name,
                SensorTypeEnum::from(sensor_type).as_ref()
            );
        }
        Err(DieselError::DatabaseError(error_kind, error_details)) => {
            println!(
                "Failed to add new sensor because of a DB error: {:?}",
                error_kind
            );
            println!("Error details: {:?}", error_details);
        }
        Err(other_err) => {
            panic!(other_err);
        }
    }
}

arg_enum! {
    #[derive(Debug, Clone, Copy)]
    enum RouteTypes {
        Serial
    }
}

impl AsRef<str> for RouteTypes {
    fn as_ref(&self) -> &'static str {
        match &self {
            RouteTypes::Serial => "serial",
        }
    }
}

arg_enum! {
    #[derive(Debug, Clone, Copy)]
    enum SensorTypes {
        Pressure,
        Temperature,
        Humidity,
        LightLevel
    }
}

impl From<SensorTypes> for SensorTypeEnum {
    fn from(sensor_type: SensorTypes) -> SensorTypeEnum {
        match sensor_type {
            SensorTypes::Pressure => SensorTypeEnum::Pressure,
            SensorTypes::Temperature => SensorTypeEnum::Temperature,
            SensorTypes::Humidity => SensorTypeEnum::Humidity,
            SensorTypes::LightLevel => SensorTypeEnum::Humidity,
        }
    }
}

fn is_positive_integer_i32(arg: String) -> Result<(), String> {
    let err_string = format!("must be a positive integer in [0, {}]", std::i32::MAX);

    let val = arg.parse::<i32>().map_err(|_| err_string.clone())?;

    if val < 0 {
        Err(err_string)
    } else {
        Ok(())
    }
}

fn main() {
    let matches = App::new("meteo_cli")
        .version(crate_version!())
        .subcommands(vec![
            App::new("list")
                .subcommands(vec![
                    App::new("nodes"),
                    App::new("sensors").arg(
                        Arg::with_name("node_public_id")
                            .required(true)
                            .validator(is_positive_integer_i32),
                    ),
                ])
                .setting(AppSettings::SubcommandRequiredElseHelp),
            App::new("add")
                .subcommands(vec![
                    App::new("node").args(&[
                        Arg::with_name("public_id")
                            .required(true)
                            .validator(is_positive_integer_i32),
                        Arg::with_name("name").required(true),
                        Arg::with_name("route_type")
                            .required(true)
                            .possible_values(&RouteTypes::variants()),
                    ]),
                    App::new("sensor").args(&[
                        Arg::with_name("node_public_id")
                            .required(true)
                            .validator(is_positive_integer_i32),
                        Arg::with_name("sensor_public_id")
                            .required(true)
                            .validator(is_positive_integer_i32),
                        Arg::with_name("sensor_type")
                            .required(true)
                            .possible_values(&SensorTypes::variants()),
                        Arg::with_name("name").required(true),
                    ]),
                ])
                .setting(AppSettings::SubcommandRequiredElseHelp),
        ])
        .setting(AppSettings::SubcommandRequiredElseHelp)
        .get_matches();

    let db_url = dotenv::var("DATABASE_URL").expect("missing DATABASE_URL env variable");

    let db_conn = SqliteConnection::establish(&db_url)
        .unwrap_or_else(|_| panic!("failed to connect to DB: {}", db_url));

    match matches.subcommand() {
        ("list", Some(list_matches)) => match list_matches.subcommand() {
            ("nodes", _) => list_all_nodes(&db_conn),
            ("sensors", Some(sensors_matches)) => {
                let node_id = value_t_or_exit!(sensors_matches, "node_public_id", i32);

                list_sensors_in_node(&db_conn, node_id);
            }
            _ => unreachable!(),
        },
        ("add", Some(add_matches)) => match add_matches.subcommand() {
            ("node", Some(node_matches)) => {
                let node_id = value_t_or_exit!(node_matches, "public_id", i32);
                let node_name = node_matches
                    .value_of("name")
                    .expect("missing new node name");
                let route_type = value_t_or_exit!(node_matches, "route_type", RouteTypes);

                add_node(&db_conn, node_id, node_name, route_type);
            }
            ("sensor", Some(sensor_matches)) => {
                let node_id = value_t_or_exit!(sensor_matches, "node_public_id", i32);
                let sensor_id = value_t_or_exit!(sensor_matches, "sensor_public_id", i32);
                let sensor_name = sensor_matches
                    .value_of("name")
                    .expect("missing new sensor name");
                let sensor_type = value_t_or_exit!(sensor_matches, "sensor_type", SensorTypes);

                add_sensor(&db_conn, node_id, sensor_id, sensor_name, sensor_type);
            }
            _ => unreachable!(),
        },
        _ => unreachable!(),
    }
}
<commit_msg>Added route params to node creation command in meteo_cli<commit_after>use diesel::insert_into;
use diesel::prelude::*;
use diesel::result::Error as DieselError;
use diesel::sqlite::SqliteConnection;

use dotenv;

use clap::{arg_enum, crate_version, value_t_or_exit, App, AppSettings, Arg};

use prettytable as pt;
use pt::{cell, row};

use ratfist_server::db::models::Node;
use ratfist_server::meteo::models::{Sensor, SensorTypeEnum};

/// Prints the supplied data to STDOUT as a formatted ASCII table
fn print_table(mut title_row: pt::Row, table_rows: Vec<pt::Row>) {
    let was_empty = table_rows.is_empty();
    let table_width = title_row.len();

    let mut table = pt::Table::init(table_rows);

    for title_cell in title_row.iter_mut() {
        title_cell.style(pt::Attr::ForegroundColor(pt::color::BLUE));
    }

    table.set_titles(title_row);

    if was_empty {
        let row = pt::Row::new(vec![pt::Cell::new_align(
            "(none)",
            pt::format::Alignment::CENTER,
        )
        .with_hspan(table_width)]);
        table.add_row(row);
    }

    table.printstd();
}

/// Returns a Result with a vector of all sensor nodes in the database
fn db_get_node_list(db_conn: &SqliteConnection) -> Result<Vec<Node>, DieselError> {
    use ratfist_server::db::schema::nodes::dsl::*;

    nodes.load::<Node>(db_conn)
}

/// Prints a table with all sensor nodes
fn list_all_nodes(db_conn: &SqliteConnection) {
    let nodes = db_get_node_list(db_conn).expect("database access error");

    print_table(
        row!["Public ID", "Name", "Route Type", "Route Type Parameters"],
        nodes
            .into_iter()
            .map(|node| {
                row![
                    node.public_id,
                    node.name,
                    node.route_type,
                    node.route_param.unwrap_or_else(|| "".to_string())
                ]
            })
            .collect(),
    );
}

/// Returns an Ok Result with a list of all sensors for a given node, or an Err
/// if no such node exists.
fn db_get_sensor_list(
    db_conn: &SqliteConnection,
    public_node_id: i32,
) -> Result<Vec<Sensor>, DieselError> {
    let nid = {
        use ratfist_server::db::schema::nodes::dsl::*;

        nodes
            .filter(public_id.eq(public_node_id))
            .first::<Node>(db_conn)?
            .id
    };

    let sensors = {
        use ratfist_server::meteo::schema::sensors::dsl::*;
        sensors.filter(node_id.eq(nid)).load::<Sensor>(db_conn)?
    };

    Ok(sensors)
}

/// Prints a table with the sensors for a given node ID
fn list_sensors_in_node(db_conn: &SqliteConnection, node_id: i32) {
    match db_get_sensor_list(db_conn, node_id) {
        Ok(sensors) => {
            println!("Sensors in node {}:", node_id);
            print_table(
                row!["Public ID", "Type", "Name"],
                sensors
                    .into_iter()
                    .map(|sensor| row![sensor.public_id, sensor.sensor_type.as_ref(), sensor.name])
                    .collect(),
            )
        }
        Err(DieselError::NotFound) => println!("No node with ID {} found.", node_id),
        Err(other_err) => {
            panic!("Unhandled error: {:?}", other_err);
        }
    }
}

/// Adds a new sensor node with the given paramenters.
fn db_add_node(
    db_conn: &SqliteConnection,
    node_id: i32,
    node_name: &str,
    route_type: RouteTypes,
    route_param_str: &str,
) -> Result<(), DieselError> {
    let route_type_str: &str = route_type.as_ref();

    {
        use ratfist_server::db::schema::nodes::dsl::*;

        insert_into(nodes)
            .values((
                public_id.eq(node_id),
                name.eq(node_name),
                route_type.eq(route_type_str),
                route_param.eq(route_param_str),
            ))
            .execute(db_conn)
            .map(|_| ())
    }
}

/// Adds a new sensor node and handles the result of the DB operation.
fn add_node(
    db_conn: &SqliteConnection,
    node_id: i32,
    node_name: &str,
    route_type: RouteTypes,
    route_params: Option<&str>,
) {
    match db_add_node(
        db_conn,
        node_id,
        node_name,
        route_type,
        route_params.unwrap_or(""),
    ) {
        Ok(_) => {
            println!(
                "Succesfully created new sensor node: public_id {}, name '{}', route type {}, route params {:?}",
                node_id,
                node_name,
                route_type.as_ref(),
                route_params
            );
        }
        Err(DieselError::DatabaseError(error_kind, error_details)) => {
            println!(
                "Failed to add new sensor node because of a DB error: {:?}",
                error_kind
            );
            println!("Error details: {:?}", error_details);
        }
        Err(other_err) => {
            panic!("Unhandled error: {:?}", other_err);
        }
    }
}

/// Adds a new sensor to a given sensor node.
fn db_add_sensor(
    db_conn: &SqliteConnection,
    parent_node_id: i32,
    sensor_id: i32,
    sensor_name: &str,
    sensor_type: SensorTypes,
) -> Result<(), DieselError> {
    let sensor_type_enum: SensorTypeEnum = sensor_type.into();

    let nid = {
        use ratfist_server::db::schema::nodes::dsl::*;

        nodes
            .filter(public_id.eq(parent_node_id))
            .first::<Node>(db_conn)?
            .id
    };

    {
        use ratfist_server::meteo::schema::sensors::dsl::*;

        insert_into(sensors)
            .values((
                public_id.eq(sensor_id),
                node_id.eq(nid),
                name.eq(sensor_name),
                sensor_type.eq(sensor_type_enum),
                name.eq(sensor_name),
            ))
            .execute(db_conn)
            .map(|_| ())
    }
}

/// Adds a new sensor to a given sensor node, and handles the result of the DB
/// operation.
fn add_sensor(
    db_conn: &SqliteConnection,
    parent_node_id: i32,
    sensor_id: i32,
    sensor_name: &str,
    sensor_type: SensorTypes,
) {
    match db_add_sensor(db_conn, parent_node_id, sensor_id, sensor_name, sensor_type) {
        Ok(_) => {
            println!(
                "Succesfully created new sensor for node #{}: public_id {}, name '{}', type {}",
                parent_node_id,
                sensor_id,
                sensor_name,
                SensorTypeEnum::from(sensor_type).as_ref()
            );
        }
        Err(DieselError::DatabaseError(error_kind, error_details)) => {
            println!(
                "Failed to add new sensor because of a DB error: {:?}",
                error_kind
            );
            println!("Error details: {:?}", error_details);
        }
        Err(other_err) => {
            panic!(other_err);
        }
    }
}

arg_enum! {
    #[derive(Debug, Clone, Copy)]
    enum RouteTypes {
        Serial
    }
}

impl AsRef<str> for RouteTypes {
    fn as_ref(&self) -> &'static str {
        match &self {
            RouteTypes::Serial => "serial",
        }
    }
}

arg_enum! {
    #[derive(Debug, Clone, Copy)]
    enum SensorTypes {
        Pressure,
        Temperature,
        Humidity,
        LightLevel
    }
}

impl From<SensorTypes> for SensorTypeEnum {
    fn from(sensor_type: SensorTypes) -> SensorTypeEnum {
        match sensor_type {
            SensorTypes::Pressure => SensorTypeEnum::Pressure,
            SensorTypes::Temperature => SensorTypeEnum::Temperature,
            SensorTypes::Humidity => SensorTypeEnum::Humidity,
            SensorTypes::LightLevel => SensorTypeEnum::Humidity,
        }
    }
}

fn is_positive_integer_i32(arg: String) -> Result<(), String> {
    let err_string = format!("must be a positive integer in [0, {}]", std::i32::MAX);

    let val = arg.parse::<i32>().map_err(|_| err_string.clone())?;

    if val < 0 {
        Err(err_string)
    } else {
        Ok(())
    }
}

fn main() {
    let matches = App::new("meteo_cli")
        .version(crate_version!())
        .subcommands(vec![
            App::new("list")
                .subcommands(vec![
                    App::new("nodes"),
                    App::new("sensors").arg(
                        Arg::with_name("node_public_id")
                            .required(true)
                            .validator(is_positive_integer_i32),
                    ),
                ])
                .setting(AppSettings::SubcommandRequiredElseHelp),
            App::new("add")
                .subcommands(vec![
                    App::new("node").args(&[
                        Arg::with_name("public_id")
                            .required(true)
                            .validator(is_positive_integer_i32),
                        Arg::with_name("name").required(true),
                        Arg::with_name("route_type")
                            .required(true)
                            .possible_values(&RouteTypes::variants()),
                        Arg::with_name("route_params"),
                    ]),
                    App::new("sensor").args(&[
                        Arg::with_name("node_public_id")
                            .required(true)
                            .validator(is_positive_integer_i32),
                        Arg::with_name("sensor_public_id")
                            .required(true)
                            .validator(is_positive_integer_i32),
                        Arg::with_name("sensor_type")
                            .required(true)
                            .possible_values(&SensorTypes::variants()),
                        Arg::with_name("name").required(true),
                    ]),
                ])
                .setting(AppSettings::SubcommandRequiredElseHelp),
        ])
        .setting(AppSettings::SubcommandRequiredElseHelp)
        .get_matches();

    let db_url = dotenv::var("DATABASE_URL").expect("missing DATABASE_URL env variable");

    let db_conn = SqliteConnection::establish(&db_url)
        .unwrap_or_else(|_| panic!("failed to connect to DB: {}", db_url));

    match matches.subcommand() {
        ("list", Some(list_matches)) => match list_matches.subcommand() {
            ("nodes", _) => list_all_nodes(&db_conn),
            ("sensors", Some(sensors_matches)) => {
                let node_id = value_t_or_exit!(sensors_matches, "node_public_id", i32);

                list_sensors_in_node(&db_conn, node_id);
            }
            _ => unreachable!(),
        },
        ("add", Some(add_matches)) => match add_matches.subcommand() {
            ("node", Some(node_matches)) => {
                let node_id = value_t_or_exit!(node_matches, "public_id", i32);
                let node_name = node_matches
                    .value_of("name")
                    .expect("missing new node name");
                let route_type = value_t_or_exit!(node_matches, "route_type", RouteTypes);

                let route_params = match route_type {
                    RouteTypes::Serial => {
                        let param_str =
                            node_matches.value_of("route_params").unwrap_or_else(|| {
                                panic!("route_params parameter is required with route_type Serial")
                            });

                        is_positive_integer_i32(param_str.to_string())
                            .unwrap_or_else(|s| panic!("route_params validation error: {}", s));

                        Some(param_str)
                    }
                };

                add_node(&db_conn, node_id, node_name, route_type, route_params);
            }
            ("sensor", Some(sensor_matches)) => {
                let node_id = value_t_or_exit!(sensor_matches, "node_public_id", i32);
                let sensor_id = value_t_or_exit!(sensor_matches, "sensor_public_id", i32);
                let sensor_name = sensor_matches
                    .value_of("name")
                    .expect("missing new sensor name");
                let sensor_type = value_t_or_exit!(sensor_matches, "sensor_type", SensorTypes);

                add_sensor(&db_conn, node_id, sensor_id, sensor_name, sensor_type);
            }
            _ => unreachable!(),
        },
        _ => unreachable!(),
    }
}
<|endoftext|>


<commit_before>use std::process::exit;
use chrono::naive::datetime::NaiveDateTime;

use libimagdiary::diary::Diary;
use libimagdiary::diaryid::DiaryId;
use libimagrt::runtime::Runtime;
use libimagerror::trace::trace_error_exit;
use libimagtimeui::datetime::DateTime;
use libimagtimeui::parse::Parse;

use util::get_diary_name;

pub fn delete(rt: &Runtime) {
    use libimaginteraction::ask::ask_bool;

    let diaryname = get_diary_name(rt);
    if diaryname.is_none() {
        warn!("No diary selected. Use either the configuration file or the commandline option");
        exit(1);
    }
    let diaryname = diaryname.unwrap();

    let diary = Diary::open(rt.store(), &diaryname[..]);
    debug!("Diary opened: {:?}", diary);

    let datetime : Option<NaiveDateTime> = rt
        .cli()
        .subcommand_matches("delete")
        .unwrap()
        .value_of("datetime")
        .map(|dt| { debug!("DateTime = {:?}", dt); dt })
        .and_then(DateTime::parse)
        .map(|dt| dt.into());

    let to_del = match datetime {
        Some(dt) => Some(diary.retrieve(DiaryId::from_datetime(diaryname.clone(), dt))),
        None     => diary.get_youngest_entry(),
    };

    let to_del = match to_del {
        Some(Ok(e)) => e,

        Some(Err(e)) => trace_error_exit(&e, 1),
        None => {
            warn!("No entry");
            exit(1);
        },
    };

    if !ask_bool(&format!("Deleting {:?}", to_del.get_location())[..], Some(true)) {
        info!("Aborting delete action");
        return;
    }

    if let Err(e) = diary.delete_entry(to_del) {
        trace_error_exit(&e, 1)
    }

    info!("Ok!");
}

<commit_msg>Replace is_none() -> unwrap() with unwrap_or_else()<commit_after>use std::process::exit;
use chrono::naive::datetime::NaiveDateTime;

use libimagdiary::diary::Diary;
use libimagdiary::diaryid::DiaryId;
use libimagrt::runtime::Runtime;
use libimagerror::trace::trace_error_exit;
use libimagtimeui::datetime::DateTime;
use libimagtimeui::parse::Parse;

use util::get_diary_name;

pub fn delete(rt: &Runtime) {
    use libimaginteraction::ask::ask_bool;

    let diaryname = get_diary_name(rt).unwrap_or_else(|| {
        warn!("No diary selected. Use either the configuration file or the commandline option");
        exit(1);
    });

    let diary = Diary::open(rt.store(), &diaryname[..]);
    debug!("Diary opened: {:?}", diary);

    let datetime : Option<NaiveDateTime> = rt
        .cli()
        .subcommand_matches("delete")
        .unwrap()
        .value_of("datetime")
        .map(|dt| { debug!("DateTime = {:?}", dt); dt })
        .and_then(DateTime::parse)
        .map(|dt| dt.into());

    let to_del = match datetime {
        Some(dt) => Some(diary.retrieve(DiaryId::from_datetime(diaryname.clone(), dt))),
        None     => diary.get_youngest_entry(),
    };

    let to_del = match to_del {
        Some(Ok(e)) => e,

        Some(Err(e)) => trace_error_exit(&e, 1),
        None => {
            warn!("No entry");
            exit(1);
        },
    };

    if !ask_bool(&format!("Deleting {:?}", to_del.get_location())[..], Some(true)) {
        info!("Aborting delete action");
        return;
    }

    if let Err(e) = diary.delete_entry(to_del) {
        trace_error_exit(&e, 1)
    }

    info!("Ok!");
}

<|endoftext|>


<commit_before>use scene::{BoxedScene, Scene, SceneChangeEvent, SceneName};
use text_renderer::TextRenderer;
use sdl2::pixels::Color;
use std::io::Result;
use std::path::Path;
use uorustlibs::skills::Skills;

use sdl2::render::{Renderer, Texture, TextureQuery};
use sdl2::rect::Rect;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;

pub struct SkillsScene {
    pages: Vec<Texture>,
}

impl SkillsScene {
    pub fn new(text_renderer: &TextRenderer, renderer: &mut Renderer) -> BoxedScene<SceneName> {
        let skills = Skills::new(&Path::new("./assets/skills.idx"), &Path::new("./assets/skills.mul"));
        let text = match skills {
            Ok(skills) => {
                let items: Vec<Texture> = skills.skills.chunks(30).map(|chunk| {
                    let skills: Vec<String> = chunk.iter().map(|skill| {
                        let glyph = if skill.clickable {
                            "+"
                        } else {
                            "-"
                        };
                        format!("{} {}", glyph, skill.name)
                    }).collect();
                    text_renderer.create_text(renderer, &skills.join("\n"), Color::RGBA(255, 255, 255, 255))
                }).collect();
                items
            },
            Err(error) => {
                let text = format!("{}", error);
                let texture = text_renderer.create_text(renderer, &text, Color::RGBA(255, 255, 255, 255));
                vec![texture]
            }
        };
        Box::new(SkillsScene {
            pages: text,
        })
    }
}

impl<T> Scene<T> for SkillsScene {
    fn render(&self, renderer: &mut Renderer) {
        renderer.clear();
        let mut last_width = 0;
        for page in self.pages.iter() {
            let TextureQuery {width, height, .. } = page.query();
            let target = Rect::new(last_width, 0, width, height);
            renderer.copy(page, None, Some(target)).unwrap();
            last_width += width as i32;
        }
        renderer.present();
    }

    fn handle_event(&mut self, event: &Event) -> Option<SceneChangeEvent<T>> {
        match *event {
            Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
                Some(SceneChangeEvent::PopScene)
            },
            Event::KeyDown { keycode: Some(Keycode::Num1), .. } => {
                println!("2");
                None
            },
             _ => None
        }
    }
}
<commit_msg>Remove unused event<commit_after>use scene::{BoxedScene, Scene, SceneChangeEvent, SceneName};
use text_renderer::TextRenderer;
use sdl2::pixels::Color;
use std::io::Result;
use std::path::Path;
use uorustlibs::skills::Skills;

use sdl2::render::{Renderer, Texture, TextureQuery};
use sdl2::rect::Rect;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;

pub struct SkillsScene {
    pages: Vec<Texture>,
}

impl SkillsScene {
    pub fn new(text_renderer: &TextRenderer, renderer: &mut Renderer) -> BoxedScene<SceneName> {
        let skills = Skills::new(&Path::new("./assets/skills.idx"), &Path::new("./assets/skills.mul"));
        let text = match skills {
            Ok(skills) => {
                let items: Vec<Texture> = skills.skills.chunks(30).map(|chunk| {
                    let skills: Vec<String> = chunk.iter().map(|skill| {
                        let glyph = if skill.clickable {
                            "+"
                        } else {
                            "-"
                        };
                        format!("{} {}", glyph, skill.name)
                    }).collect();
                    text_renderer.create_text(renderer, &skills.join("\n"), Color::RGBA(255, 255, 255, 255))
                }).collect();
                items
            },
            Err(error) => {
                let text = format!("{}", error);
                let texture = text_renderer.create_text(renderer, &text, Color::RGBA(255, 255, 255, 255));
                vec![texture]
            }
        };
        Box::new(SkillsScene {
            pages: text,
        })
    }
}

impl<T> Scene<T> for SkillsScene {
    fn render(&self, renderer: &mut Renderer) {
        renderer.clear();
        let mut last_width = 0;
        for page in self.pages.iter() {
            let TextureQuery {width, height, .. } = page.query();
            let target = Rect::new(last_width, 0, width, height);
            renderer.copy(page, None, Some(target)).unwrap();
            last_width += width as i32;
        }
        renderer.present();
    }

    fn handle_event(&mut self, event: &Event) -> Option<SceneChangeEvent<T>> {
        match *event {
            Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
                Some(SceneChangeEvent::PopScene)
            },
             _ => None
        }
    }
}
<|endoftext|>


<commit_before>use screen::*;
use piston_window;
use conrod::{self, Widget, Frameable, Positionable, Sizeable, Labelable};
use conrod::color::Colorable;

pub struct MainMenuScreen {
    ui: conrod::Ui<piston_window::Glyphs>,
    new_game: bool,
    exit: bool,
}

impl MainMenuScreen {
    pub fn new(window: &piston_window::PistonWindow, context: &mut Context) -> MainMenuScreen {
        MainMenuScreen { ui: create_ui(&window, &context.assets_path), new_game: false, exit: false, }
    }
}

impl Screen for MainMenuScreen {
    fn on_input(&mut self,
                input: &piston_window::Input,
                window: &piston_window::PistonWindow,
                context: &mut Context)
                -> InputResults {
        use piston_window::{Input, Button, MouseButton};

        let mut result = Vec::new();

        match input {
            &Input::Press(Button::Mouse(MouseButton::Left)) => {
                result.push(InputResult::PopScreen);
                result.push(InputResult::PushScreen(Box::new(BattleScreen::new(&window, context))));
            }
            _ => {}
        }

        result
    }

    fn on_draw(&mut self, args: &piston_window::RenderArgs, window: &piston_window::PistonWindow) {
        self.ui.handle_event(window);
        window.draw_2d(|context, graphics| self.ui.draw_if_changed(context, graphics));
    }

    fn on_update(&mut self, args: &piston_window::UpdateArgs) {
        handle_on_update(&mut self.ui, &mut self.new_game, &mut self.exit);
    }
}

widget_ids! {
    CANVAS,
    TITLE,
    NEW_GAME_BUTTON,
    EXIT_BUTTON,
}

fn create_ui(window: &piston_window::PistonWindow,
             assets_path: &::std::path::Path)
             -> conrod::Ui<piston_window::Glyphs> {
    let font_path = assets_path.join("NotoSans-Regular.ttf");
    let theme = conrod::Theme::default();
    let glyph_cache = piston_window::Glyphs::new(&font_path, window.factory.borrow().clone());
    conrod::Ui::new(glyph_cache.unwrap(), theme)
}

fn handle_on_update(ui: &mut conrod::Ui<piston_window::Glyphs>, new_game: &mut bool, exit: &mut bool) {
    // TODO: Remove?
    const FRAME_WIDTH: f64 = 1.;

    ui.set_widgets(|ui| {
        conrod::Canvas::new()
            .frame(FRAME_WIDTH)
            .pad(30.)
            .color(conrod::color::rgb(0.2, 0.35, 0.45))
            .scroll_kids()
            .set(CANVAS, ui);

        conrod::Button::new()
            .w_h(200.0, 50.0)
            .mid_left_of(CANVAS)
            .rgb(0.4, 0.75, 0.6)
            .frame(FRAME_WIDTH)
            .label("New game")
            .react(|| *new_game = true)
            .set(NEW_GAME_BUTTON, ui);

        conrod::Button::new()
            .w_h(200.0, 50.0)
            .mid_left_of(CANVAS)
            .down_from(NEW_GAME_BUTTON, 45.0)
            .rgb(0.4, 0.75, 0.6)
            .frame(FRAME_WIDTH)
            .label("Exit")
            .react(|| *exit = true)
            .set(EXIT_BUTTON, ui);
    });
}
<commit_msg>FRAME_WIDTH has been removed<commit_after>use screen::*;
use piston_window;
use conrod::{self, Widget, Frameable, Positionable, Sizeable, Labelable};
use conrod::color::Colorable;

pub struct MainMenuScreen {
    ui: conrod::Ui<piston_window::Glyphs>,
    new_game: bool,
    exit: bool,
}

impl MainMenuScreen {
    pub fn new(window: &piston_window::PistonWindow, context: &mut Context) -> MainMenuScreen {
        MainMenuScreen { ui: create_ui(&window, &context.assets_path), new_game: false, exit: false, }
    }
}

impl Screen for MainMenuScreen {
    fn on_input(&mut self,
                input: &piston_window::Input,
                window: &piston_window::PistonWindow,
                context: &mut Context)
                -> InputResults {
        use piston_window::{Input, Button, MouseButton};

        let mut result = Vec::new();

        match input {
            &Input::Press(Button::Mouse(MouseButton::Left)) => {
                result.push(InputResult::PopScreen);
                result.push(InputResult::PushScreen(Box::new(BattleScreen::new(&window, context))));
            }
            _ => {}
        }

        result
    }

    fn on_draw(&mut self, args: &piston_window::RenderArgs, window: &piston_window::PistonWindow) {
        self.ui.handle_event(window);
        window.draw_2d(|context, graphics| self.ui.draw_if_changed(context, graphics));
    }

    fn on_update(&mut self, args: &piston_window::UpdateArgs) {
        handle_on_update(&mut self.ui, &mut self.new_game, &mut self.exit);
    }
}

widget_ids! {
    CANVAS,
    TITLE,
    NEW_GAME_BUTTON,
    EXIT_BUTTON,
}

fn create_ui(window: &piston_window::PistonWindow,
             assets_path: &::std::path::Path)
             -> conrod::Ui<piston_window::Glyphs> {
    let font_path = assets_path.join("NotoSans-Regular.ttf");
    let theme = conrod::Theme::default();
    let glyph_cache = piston_window::Glyphs::new(&font_path, window.factory.borrow().clone());
    conrod::Ui::new(glyph_cache.unwrap(), theme)
}

fn handle_on_update(ui: &mut conrod::Ui<piston_window::Glyphs>, new_game: &mut bool, exit: &mut bool) {
    ui.set_widgets(|ui| {
        conrod::Canvas::new()
            .pad(30.)
            .color(conrod::color::rgb(0.2, 0.35, 0.45))
            .scroll_kids()
            .set(CANVAS, ui);

        conrod::Button::new()
            .w_h(200.0, 50.0)
            .mid_left_of(CANVAS)
            .rgb(0.4, 0.75, 0.6)
            .label("New game")
            .react(|| *new_game = true)
            .set(NEW_GAME_BUTTON, ui);

        conrod::Button::new()
            .w_h(200.0, 50.0)
            .mid_left_of(CANVAS)
            .down_from(NEW_GAME_BUTTON, 45.0)
            .rgb(0.4, 0.75, 0.6)
            .label("Exit")
            .react(|| *exit = true)
            .set(EXIT_BUTTON, ui);
    });
}
<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! `x86_64` execution contexts.
//!
//! This is inteded to be general-purpose and composable, so that the same
//! code can be reused for interrupts and for multithreading.

use core::mem;
use core::fmt;
use super::flags::Flags;
use super::segment;

/// Registers pushed to the stack when handling an interrupt or context switch.
#[repr(C, packed)]
#[derive(Copy, Clone)]
pub struct Registers { pub rsi: u64
                     , pub rdi: u64
                     , pub r11: u64
                     , pub r10: u64
                     , pub r9:  u64
                     , pub r8:  u64
                     , pub rdx: u64
                     , pub rcx: u64
                     , pub rax: u64
                     }

 impl Registers {
     /// Transform this struct into an array of `u64`s
     /// (if you would ever want to do this)
     pub unsafe fn to_array(&self) -> [u64; 9] {
        //  [ self.rsi, self.rdi, self.r11
        //  , self.r10, self.r9, self.r8
        //  , self.rdx, self.rcx, self.rax
        //  ]
        // using transmute is probably faster and we're already unsafe...
        mem::transmute(*self)
     }

     /// Create a new empty set of Registers
     pub const fn empty() -> Self {
         Registers { rsi: 0, rdi: 0, r11: 0
                   , r10: 0, r9:  0, r8:  0
                   , rdx: 0, rcx: 0, rax: 0
                   }
     }

     /// Push the caller-saved registers to the stack
     /// (such as when handling a context switch or interrupt).
     ///
     /// THIS FUNCTION IS NAKED. DO NOT CALL IT NORMALLY.
     #[naked]
     #[inline(always)]
     pub unsafe fn push() {
         asm!( "push rax
                push rcx
                push rdx
                push r8
                push r9
                push r10
                push r11
                push rdi
                push rsi"
             :::: "intel"
                , "volatile");
     }

     /// Push the caller-saved registers off the stack
     /// (such as when handling a context switch or interrupt).
     ///
     /// THIS FUNCTION IS NAKED. DO NOT CALL IT NORMALLY.
     #[naked]
     #[inline(always)]
     pub unsafe fn pop() {
         asm!( "pop rsi
                pop rdi
                pop r11
                pop r10
                pop r9
                pop r8
                pop rdx
                pop rcx
                pop rax"
             :::: "intel"
                , "volatile");
     }
 }

 impl fmt::Debug for Registers {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!( f
               , "    RSI: {:#018x} RDI: {:#018x} R11: {:#018x}\n    \
                      R10: {:#018x} R9:  {:#018x} R8:  {:#018x}\n    \
                      RDX: {:#018x} RCX: {:#018x} RAX: {:#018x}"
              , self.rsi, self.rdi, self.r11
              , self.r10, self.r9,  self.r8
              , self.rdx, self.rcx, self.rax)
     }
}

#[derive(Debug)]
#[repr(C)]
pub struct InterruptFrame {
    //  this is the actual value of the interrupt stack frame context,
    //  not the old one (which is wrong). note that the old one seems to cause
    //  stack misalignment.
    //          -- eliza, october 4th, 2016
    /// Value of the instruction pointer (`$rip`) register
    pub rip: u64
  , __pad_1: u32
  , __pad_2: u16
  , /// Value of the code segment (`$cs`) register
    pub cs: segment::Selector
  , /// Value of the CPU flags (`$rflags`) register
    pub rflags: Flags
  , /// Value of the stack pointer (`$rsp`) register
    //  TODO: should this actually be a pointer?
    pub rsp: u64
  , __pad_3: u32
  , __pad_4: u16
  , /// Value of the stack segment (`$ss`) register
    pub ss: segment::Selector
}

/// Thread execution context
#[repr(C, packed)]
pub struct Context { /// Value of the stack pointer (`rsp`) register
                     pub rsp: *mut u8
                   , /// Value of the caller-saved registers
                     pub registers: Registers
                   , /// Value of the instruction pointer (`rip`) register
                     pub rip: *mut u8
                 //, pub stack: [u8] // TODO: should be box
                   }

impl Context {
    pub fn empty() -> Self {
        unsafe {
            Context { rsp: mem::transmute(0u64)
                    , registers: Registers::empty()
                    , rip: mem::transmute(0u64)
                  //, stack: [0u8; 8]
                    }
        }
    }
}
<commit_msg>[x86_64] improve interrupt frame prettyprinting<commit_after>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! `x86_64` execution contexts.
//!
//! This is inteded to be general-purpose and composable, so that the same
//! code can be reused for interrupts and for multithreading.

use core::mem;
use core::fmt;
use super::flags::Flags;
use super::segment;

/// Registers pushed to the stack when handling an interrupt or context switch.
#[repr(C, packed)]
#[derive(Copy, Clone)]
pub struct Registers { pub rsi: u64
                     , pub rdi: u64
                     , pub r11: u64
                     , pub r10: u64
                     , pub r9:  u64
                     , pub r8:  u64
                     , pub rdx: u64
                     , pub rcx: u64
                     , pub rax: u64
                     }

 impl Registers {
     /// Transform this struct into an array of `u64`s
     /// (if you would ever want to do this)
     pub unsafe fn to_array(&self) -> [u64; 9] {
        //  [ self.rsi, self.rdi, self.r11
        //  , self.r10, self.r9, self.r8
        //  , self.rdx, self.rcx, self.rax
        //  ]
        // using transmute is probably faster and we're already unsafe...
        mem::transmute(*self)
     }

     /// Create a new empty set of Registers
     pub const fn empty() -> Self {
         Registers { rsi: 0, rdi: 0, r11: 0
                   , r10: 0, r9:  0, r8:  0
                   , rdx: 0, rcx: 0, rax: 0
                   }
     }

     /// Push the caller-saved registers to the stack
     /// (such as when handling a context switch or interrupt).
     ///
     /// THIS FUNCTION IS NAKED. DO NOT CALL IT NORMALLY.
     #[naked]
     #[inline(always)]
     pub unsafe fn push() {
         asm!( "push rax
                push rcx
                push rdx
                push r8
                push r9
                push r10
                push r11
                push rdi
                push rsi"
             :::: "intel"
                , "volatile");
     }

     /// Push the caller-saved registers off the stack
     /// (such as when handling a context switch or interrupt).
     ///
     /// THIS FUNCTION IS NAKED. DO NOT CALL IT NORMALLY.
     #[naked]
     #[inline(always)]
     pub unsafe fn pop() {
         asm!( "pop rsi
                pop rdi
                pop r11
                pop r10
                pop r9
                pop r8
                pop rdx
                pop rcx
                pop rax"
             :::: "intel"
                , "volatile");
     }
 }

impl fmt::Debug for Registers {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!( f
               , "    RSI: {:#018x} RDI: {:#018x} R11: {:#018x}\n    \
                      R10: {:#018x} R9:  {:#018x} R8:  {:#018x}\n    \
                      RDX: {:#018x} RCX: {:#018x} RAX: {:#018x}"
              , self.rsi, self.rdi, self.r11
              , self.r10, self.r9,  self.r8
              , self.rdx, self.rcx, self.rax)
     }
}

#[repr(C)]
pub struct InterruptFrame {
    //  this is the actual value of the interrupt stack frame context,
    //  not the old one (which is wrong). note that the old one seems to cause
    //  stack misalignment.
    //          -- eliza, october 4th, 2016
    /// Value of the instruction pointer (`$rip`) register
    pub rip: u64
  // , __pad_1: u32
  // , __pad_2: u16
  , /// Value of the code segment (`$cs`) register
    pub cs: u64
  , /// Value of the CPU flags (`$rflags`) register
    pub rflags: u64
  , /// Value of the stack pointer (`$rsp`) register
    //  TODO: should this actually be a pointer?
    pub rsp: u64
  // , __pad_3: u32
  // , __pad_4: u16
  , /// Value of the stack segment (`$ss`) register
    pub ss: u64
}

impl fmt::Debug for InterruptFrame {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!( f
              , "Interrupt Frame: \
                \n   instruction pointer: {:#018x} \
                \n   code segment selector: {:#018x} \
                \n   rflags: {:#018x} \
                \n   stack pointer: {:#018x} \
                \n   stack segment selector: {:#018x}"
             , self.rip, self.cs, self.rflags, self.rsp, self.ss)
    }
}

/// Thread execution context
#[repr(C, packed)]
pub struct Context { /// Value of the stack pointer (`rsp`) register
                     pub rsp: *mut u8
                   , /// Value of the caller-saved registers
                     pub registers: Registers
                   , /// Value of the instruction pointer (`rip`) register
                     pub rip: *mut u8
                 //, pub stack: [u8] // TODO: should be box
                   }

impl Context {
    pub fn empty() -> Self {
        unsafe {
            Context { rsp: mem::transmute(0u64)
                    , registers: Registers::empty()
                    , rip: mem::transmute(0u64)
                  //, stack: [0u8; 8]
                    }
        }
    }
}
<|endoftext|>


<commit_before>// mrusty. mruby safe bindings for Rust
// Copyright (C) 2016  Dragoș Tiselice
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use super::super::*;

#[test]
fn mrusty_initialize_empty() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def!("initialize", || {
            Cont
        });
    });

    Cont::require(mruby.clone());

    mruby.run("Container.new").unwrap();
}

#[test]
fn mrusty_initialize_only_values() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def!("initialize", |_v: i32| {
            Cont
        });
    });

    Cont::require(mruby.clone());

    mruby.run("Container.new 3").unwrap();
}

#[test]
fn mrusty_initialize_only_mruby() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def!("initialize", |_mruby| {
            Cont
        });
    });

    Cont::require(mruby.clone());

    mruby.run("Container.new").unwrap();
}

#[test]
fn mrusty_initialize_mruby_values() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def!("initialize", |_mruby, _v: i32| {
            Cont
        });
    });

    Cont::require(mruby.clone());

    mruby.run("Container.new 3").unwrap();
}

#[test]
fn mrusty_instance_empty() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def!("hi", |slf: Value| {
            slf
        });
    });

    Cont::require(mruby.clone());

    mruby.run("Container.new.hi").unwrap();
}

#[test]
fn mrusty_instance_only_values() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def!("hi", |slf: Value, _v: i32| {
            slf
        });
    });

    Cont::require(mruby.clone());

    mruby.run("Container.new.hi 3").unwrap();
}

#[test]
fn mrusty_instance_only_mruby() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def!("hi", |_mruby, slf: Value| {
            slf
        });
    });

    Cont::require(mruby.clone());

    mruby.run("Container.new.hi").unwrap();
}

#[test]
fn mrusty_instance_mruby_values() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def!("hi", |mruby, _slf: Value, v: i32| {
            mruby.fixnum(v)
        });
    });

    Cont::require(mruby.clone());

    let result = mruby.run("Container.new.hi 3").unwrap();

    assert_eq!(result.to_i32().unwrap(), 3);
}

#[test]
fn mrusty_class_empty() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def_self!("hi", |slf: Class| {
            slf.to_value()
        });
    });

    Cont::require(mruby.clone());

    let result = mruby.run("Container.hi == Container").unwrap();

    assert_eq!(result.to_bool().unwrap(), true);
}

#[test]
fn mrusty_class_only_values() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def_self!("hi", |_slf: Class, other: Class| {
            other.to_value()
        });
    });

    Cont::require(mruby.clone());

    let result = mruby.run("Container.hi(Fixnum) == Fixnum").unwrap();

    assert_eq!(result.to_bool().unwrap(), true);
}

#[test]
fn mrusty_class_only_mruby() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def_self!("hi", |_mruby, slf: Class| {
            slf.to_value()
        });
    });

    Cont::require(mruby.clone());

    let result = mruby.run("Container.hi == Container").unwrap();

    assert_eq!(result.to_bool().unwrap(), true);
}

#[test]
fn mrusty_class_mruby_values() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def_self!("hi", |_mruby, _slf: Class, other: Class| {
            other.to_value()
        });
    });

    Cont::require(mruby.clone());

    let result = mruby.run("Container.hi(Fixnum) == Fixnum").unwrap();

    assert_eq!(result.to_bool().unwrap(), true);
}

#[test]
fn mrusty_initialize_args_only_values() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def!("initialize", |_v: i32; _args| {
            Cont
        });
    });

    Cont::require(mruby.clone());

    mruby.run("Container.new 1, 2, 3").unwrap();
}

#[test]
fn mrusty_initialize_args_only_mruby() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def!("initialize", |_mruby; _args| {
            Cont
        });
    });

    Cont::require(mruby.clone());

    mruby.run("Container.new 1, 2, 3").unwrap();
}

#[test]
fn mrusty_initialize_args_mruby_values() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def!("initialize", |_mruby, _v: i32; _args| {
            Cont
        });
    });

    Cont::require(mruby.clone());

    mruby.run("Container.new 1, 2, 3").unwrap();
}

#[test]
fn mrusty_instance_args_empty() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def!("hi", |_slf: Value; args| {
            args[2].clone()
        });
    });

    Cont::require(mruby.clone());

    let result = mruby.run("Container.new.hi 1, 2, 3").unwrap();

    assert_eq!(result.to_i32().unwrap(), 3);
}

#[test]
fn mrusty_instance_args_only_values() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def!("hi", |_slf: Value, _v: i32; args| {
            args[1].clone()
        });
    });

    Cont::require(mruby.clone());

    let result = mruby.run("Container.new.hi 1, 2, 3").unwrap();

    assert_eq!(result.to_i32().unwrap(), 3);
}

#[test]
fn mrusty_instance_args_only_mruby() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def!("hi", |_mruby, _slf: Value; args| {
            args[2].clone()
        });
    });

    Cont::require(mruby.clone());

    let result = mruby.run("Container.new.hi 1, 2, 3").unwrap();

    assert_eq!(result.to_i32().unwrap(), 3);
}

#[test]
fn mrusty_instance_args_mruby_values() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def!("hi", |_mruby, _slf: Value, _v: i32; args| {
            args[1].clone()
        });
    });

    Cont::require(mruby.clone());

    let result = mruby.run("Container.new.hi 1, 2, 3").unwrap();

    assert_eq!(result.to_i32().unwrap(), 3);
}

#[test]
fn mrusty_class_args_empty() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def_self!("hi", |_slf: Class; args| {
            args[2].clone()
        });
    });

    Cont::require(mruby.clone());

    let result = mruby.run("Container.hi 1, 2, 3").unwrap();

    assert_eq!(result.to_i32().unwrap(), 3);
}

#[test]
fn mrusty_class_args_only_values() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def_self!("hi", |_slf: Class, _v: i32; args| {
            args[1].clone()
        });
    });

    Cont::require(mruby.clone());

    let result = mruby.run("Container.hi 1, 2, 3").unwrap();

    assert_eq!(result.to_i32().unwrap(), 3);
}

#[test]
fn mrusty_class_args_only_mruby() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def_self!("hi", |_mruby, _slf: Class; args| {
            args[2].clone()
        });
    });

    Cont::require(mruby.clone());

    let result = mruby.run("Container.hi 1, 2, 3").unwrap();

    assert_eq!(result.to_i32().unwrap(), 3);
}

#[test]
fn mrusty_class_args_mruby_values() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def_self!("hi", |_mruby, _slf: Class, _v: i32; args| {
            args[1].clone()
        });
    });

    Cont::require(mruby.clone());

    let result = mruby.run("Container.hi 1, 2, 3").unwrap();

    assert_eq!(result.to_i32().unwrap(), 3);
}
<commit_msg>Added mruby_class testing.<commit_after>// mrusty. mruby safe bindings for Rust
// Copyright (C) 2016  Dragoș Tiselice
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use super::super::*;

#[test]
fn mrusty_initialize_empty() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def!("initialize", || {
            Cont
        });
    });

    Cont::require(mruby.clone());

    mruby.run("Container.new").unwrap();
}

#[test]
fn mrusty_initialize_only_values() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def!("initialize", |_v: i32| {
            Cont
        });
    });

    Cont::require(mruby.clone());

    mruby.run("Container.new 3").unwrap();
}

#[test]
fn mrusty_initialize_only_mruby() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def!("initialize", |_mruby| {
            Cont
        });
    });

    Cont::require(mruby.clone());

    mruby.run("Container.new").unwrap();
}

#[test]
fn mrusty_initialize_mruby_values() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def!("initialize", |_mruby, _v: i32| {
            Cont
        });
    });

    Cont::require(mruby.clone());

    mruby.run("Container.new 3").unwrap();
}

#[test]
fn mrusty_instance_empty() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def!("hi", |slf: Value| {
            slf
        });
    });

    Cont::require(mruby.clone());

    mruby.run("Container.new.hi").unwrap();
}

#[test]
fn mrusty_instance_only_values() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def!("hi", |slf: Value, _v: i32| {
            slf
        });
    });

    Cont::require(mruby.clone());

    mruby.run("Container.new.hi 3").unwrap();
}

#[test]
fn mrusty_instance_only_mruby() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def!("hi", |_mruby, slf: Value| {
            slf
        });
    });

    Cont::require(mruby.clone());

    mruby.run("Container.new.hi").unwrap();
}

#[test]
fn mrusty_instance_mruby_values() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def!("hi", |mruby, _slf: Value, v: i32| {
            mruby.fixnum(v)
        });
    });

    Cont::require(mruby.clone());

    let result = mruby.run("Container.new.hi 3").unwrap();

    assert_eq!(result.to_i32().unwrap(), 3);
}

#[test]
fn mrusty_class_empty() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def_self!("hi", |slf: Class| {
            slf.to_value()
        });
    });

    Cont::require(mruby.clone());

    let result = mruby.run("Container.hi == Container").unwrap();

    assert_eq!(result.to_bool().unwrap(), true);
}

#[test]
fn mrusty_class_only_values() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def_self!("hi", |_slf: Class, other: Class| {
            other.to_value()
        });
    });

    Cont::require(mruby.clone());

    let result = mruby.run("Container.hi(Fixnum) == Fixnum").unwrap();

    assert_eq!(result.to_bool().unwrap(), true);
}

#[test]
fn mrusty_class_only_mruby() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def_self!("hi", |_mruby, slf: Class| {
            slf.to_value()
        });
    });

    Cont::require(mruby.clone());

    let result = mruby.run("Container.hi == Container").unwrap();

    assert_eq!(result.to_bool().unwrap(), true);
}

#[test]
fn mrusty_class_mruby_values() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def_self!("hi", |_mruby, _slf: Class, other: Class| {
            other.to_value()
        });
    });

    Cont::require(mruby.clone());

    let result = mruby.run("Container.hi(Fixnum) == Fixnum").unwrap();

    assert_eq!(result.to_bool().unwrap(), true);
}

#[test]
fn mrusty_initialize_args_only_values() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def!("initialize", |_v: i32; _args| {
            Cont
        });
    });

    Cont::require(mruby.clone());

    mruby.run("Container.new 1, 2, 3").unwrap();
}

#[test]
fn mrusty_initialize_args_only_mruby() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def!("initialize", |_mruby; _args| {
            Cont
        });
    });

    Cont::require(mruby.clone());

    mruby.run("Container.new 1, 2, 3").unwrap();
}

#[test]
fn mrusty_initialize_args_mruby_values() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def!("initialize", |_mruby, _v: i32; _args| {
            Cont
        });
    });

    Cont::require(mruby.clone());

    mruby.run("Container.new 1, 2, 3").unwrap();
}

#[test]
fn mrusty_instance_args_empty() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def!("hi", |_slf: Value; args| {
            args[2].clone()
        });
    });

    Cont::require(mruby.clone());

    let result = mruby.run("Container.new.hi 1, 2, 3").unwrap();

    assert_eq!(result.to_i32().unwrap(), 3);
}

#[test]
fn mrusty_instance_args_only_values() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def!("hi", |_slf: Value, _v: i32; args| {
            args[1].clone()
        });
    });

    Cont::require(mruby.clone());

    let result = mruby.run("Container.new.hi 1, 2, 3").unwrap();

    assert_eq!(result.to_i32().unwrap(), 3);
}

#[test]
fn mrusty_instance_args_only_mruby() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def!("hi", |_mruby, _slf: Value; args| {
            args[2].clone()
        });
    });

    Cont::require(mruby.clone());

    let result = mruby.run("Container.new.hi 1, 2, 3").unwrap();

    assert_eq!(result.to_i32().unwrap(), 3);
}

#[test]
fn mrusty_instance_args_mruby_values() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def!("hi", |_mruby, _slf: Value, _v: i32; args| {
            args[1].clone()
        });
    });

    Cont::require(mruby.clone());

    let result = mruby.run("Container.new.hi 1, 2, 3").unwrap();

    assert_eq!(result.to_i32().unwrap(), 3);
}

#[test]
fn mrusty_class_args_empty() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def_self!("hi", |_slf: Class; args| {
            args[2].clone()
        });
    });

    Cont::require(mruby.clone());

    let result = mruby.run("Container.hi 1, 2, 3").unwrap();

    assert_eq!(result.to_i32().unwrap(), 3);
}

#[test]
fn mrusty_class_args_only_values() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def_self!("hi", |_slf: Class, _v: i32; args| {
            args[1].clone()
        });
    });

    Cont::require(mruby.clone());

    let result = mruby.run("Container.hi 1, 2, 3").unwrap();

    assert_eq!(result.to_i32().unwrap(), 3);
}

#[test]
fn mrusty_class_args_only_mruby() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def_self!("hi", |_mruby, _slf: Class; args| {
            args[2].clone()
        });
    });

    Cont::require(mruby.clone());

    let result = mruby.run("Container.hi 1, 2, 3").unwrap();

    assert_eq!(result.to_i32().unwrap(), 3);
}

#[test]
fn mrusty_class_args_mruby_values() {
    let mruby = Mruby::new();

    struct Cont;

    mrusty_class!(Cont, "Container", {
        def_self!("hi", |_mruby, _slf: Class, _v: i32; args| {
            args[1].clone()
        });
    });

    Cont::require(mruby.clone());

    let result = mruby.run("Container.hi 1, 2, 3").unwrap();

    assert_eq!(result.to_i32().unwrap(), 3);
}

#[test]
fn mruby_instance_empty() {
    let mruby = Mruby::new();

    mruby_class!(mruby, "Container", {
        def!("hi", |slf: Value| {
            slf
        });
    });

    mruby.run("Container.new.hi").unwrap();
}

#[test]
fn mruby_instance_only_values() {
    let mruby = Mruby::new();

    mruby_class!(mruby, "Container", {
        def!("hi", |slf: Value, _v: i32| {
            slf
        });
    });

    mruby.run("Container.new.hi 3").unwrap();
}

#[test]
fn mruby_instance_only_mruby() {
    let mruby = Mruby::new();

    mruby_class!(mruby, "Container", {
        def!("hi", |_mruby, slf: Value| {
            slf
        });
    });

    mruby.run("Container.new.hi").unwrap();
}

#[test]
fn mruby_instance_mruby_values() {
    let mruby = Mruby::new();

    mruby_class!(mruby, "Container", {
        def!("hi", |mruby, _slf: Value, v: i32| {
            mruby.fixnum(v)
        });
    });

    let result = mruby.run("Container.new.hi 3").unwrap();

    assert_eq!(result.to_i32().unwrap(), 3);
}

#[test]
fn mruby_class_empty() {
    let mruby = Mruby::new();

    mruby_class!(mruby, "Container", {
        def_self!("hi", |slf: Class| {
            slf.to_value()
        });
    });

    let result = mruby.run("Container.hi == Container").unwrap();

    assert_eq!(result.to_bool().unwrap(), true);
}

#[test]
fn mruby_class_only_values() {
    let mruby = Mruby::new();

    mruby_class!(mruby, "Container", {
        def_self!("hi", |_slf: Class, other: Class| {
            other.to_value()
        });
    });

    let result = mruby.run("Container.hi(Fixnum) == Fixnum").unwrap();

    assert_eq!(result.to_bool().unwrap(), true);
}

#[test]
fn mruby_class_only_mruby() {
    let mruby = Mruby::new();

    mruby_class!(mruby, "Container", {
        def_self!("hi", |_mruby, slf: Class| {
            slf.to_value()
        });
    });

    let result = mruby.run("Container.hi == Container").unwrap();

    assert_eq!(result.to_bool().unwrap(), true);
}

#[test]
fn mruby_class_mruby_values() {
    let mruby = Mruby::new();

    mruby_class!(mruby, "Container", {
        def_self!("hi", |_mruby, _slf: Class, other: Class| {
            other.to_value()
        });
    });

    let result = mruby.run("Container.hi(Fixnum) == Fixnum").unwrap();

    assert_eq!(result.to_bool().unwrap(), true);
}

#[test]
fn mruby_instance_args_empty() {
    let mruby = Mruby::new();

    mruby_class!(mruby, "Container", {
        def!("hi", |_slf: Value; args| {
            args[2].clone()
        });
    });

    let result = mruby.run("Container.new.hi 1, 2, 3").unwrap();

    assert_eq!(result.to_i32().unwrap(), 3);
}

#[test]
fn mruby_instance_args_only_values() {
    let mruby = Mruby::new();

    mruby_class!(mruby, "Container", {
        def!("hi", |_slf: Value, _v: i32; args| {
            args[1].clone()
        });
    });

    let result = mruby.run("Container.new.hi 1, 2, 3").unwrap();

    assert_eq!(result.to_i32().unwrap(), 3);
}

#[test]
fn mruby_instance_args_only_mruby() {
    let mruby = Mruby::new();

    mruby_class!(mruby, "Container", {
        def!("hi", |_mruby, _slf: Value; args| {
            args[2].clone()
        });
    });

    let result = mruby.run("Container.new.hi 1, 2, 3").unwrap();

    assert_eq!(result.to_i32().unwrap(), 3);
}

#[test]
fn mruby_instance_args_mruby_values() {
    let mruby = Mruby::new();

    mruby_class!(mruby, "Container", {
        def!("hi", |_mruby, _slf: Value, _v: i32; args| {
            args[1].clone()
        });
    });

    let result = mruby.run("Container.new.hi 1, 2, 3").unwrap();

    assert_eq!(result.to_i32().unwrap(), 3);
}

#[test]
fn mruby_class_args_empty() {
    let mruby = Mruby::new();

    mruby_class!(mruby, "Container", {
        def_self!("hi", |_slf: Class; args| {
            args[2].clone()
        });
    });

    let result = mruby.run("Container.hi 1, 2, 3").unwrap();

    assert_eq!(result.to_i32().unwrap(), 3);
}

#[test]
fn mruby_class_args_only_values() {
    let mruby = Mruby::new();

    mruby_class!(mruby, "Container", {
        def_self!("hi", |_slf: Class, _v: i32; args| {
            args[1].clone()
        });
    });

    let result = mruby.run("Container.hi 1, 2, 3").unwrap();

    assert_eq!(result.to_i32().unwrap(), 3);
}

#[test]
fn mruby_class_args_only_mruby() {
    let mruby = Mruby::new();

    mruby_class!(mruby, "Container", {
        def_self!("hi", |_mruby, _slf: Class; args| {
            args[2].clone()
        });
    });

    let result = mruby.run("Container.hi 1, 2, 3").unwrap();

    assert_eq!(result.to_i32().unwrap(), 3);
}

#[test]
fn mruby_class_args_mruby_values() {
    let mruby = Mruby::new();

    mruby_class!(mruby, "Container", {
        def_self!("hi", |_mruby, _slf: Class, _v: i32; args| {
            args[1].clone()
        });
    });

    let result = mruby.run("Container.hi 1, 2, 3").unwrap();

    assert_eq!(result.to_i32().unwrap(), 3);
}
<|endoftext|>


<commit_before>extern crate rand;

use rand::distributions::{Distribution, Weighted, WeightedChoice};
use rand::prelude::*;

const DATA: [(&str, f64); 8] = [
    ("aleph", 1.0 / 5.0),
    ("beth", 1.0 / 6.0),
    ("gimel", 1.0 / 7.0),
    ("daleth", 1.0 / 8.0),
    ("he", 1.0 / 9.0),
    ("waw", 1.0 / 10.0),
    ("zayin", 1.0 / 11.0),
    ("heth", 1759.0 / 27720.0),
];

const SAMPLES: usize = 1_000_000;

/// Generate a mapping to be used by `WeightedChoice`
fn gen_mapping() -> Vec<Weighted<usize>> {
    DATA.iter()
        .enumerate()
        .map(|(i, &(_, p))| Weighted {
            // `WeightedChoice` requires `u32` weights rather than raw probabilities.  For each
            // probability, we convert it to a `u32` weight, and associate it with an index. We
            // multiply by a constant because small numbers such as 0.2 when casted to `u32`
            // become `0`.  This conversion decreases the accuracy of the mapping, which is why we
            // provide an implementation which uses `f64`s for the best accuracy.
            weight: (p * 1_000_000_000.0) as u32,
            item: i,
        })
        .collect()
}

/// Generate a mapping of the raw probabilities
fn gen_mapping_float() -> Vec<f64> {
    // This does the work of `WeightedChoice::new`, splitting a number into various ranges.  The
    // `item` of `Weighted` is represented here merely by the probability's position in the `Vec`.
    let mut running_total = 0.0;
    DATA.iter()
        .map(|&(_, p)| {
            running_total += p;
            running_total
        })
        .collect()
}

/// An implementation of `WeightedChoice` which uses probabilities rather than weights.  Refer to
/// the `WeightedChoice` source for serious usage.
struct WcFloat {
    mapping: Vec<f64>,
}

impl WcFloat {
    fn new(mapping: &[f64]) -> Self {
        Self {
            mapping: mapping.to_vec(),
        }
    }

    // This is roughly the same logic as `WeightedChoice::ind_sample` (though is likely slower)
    fn search(&self, sample_prob: f64) -> usize {
        let idx = self
            .mapping
            .binary_search_by(|p| p.partial_cmp(&sample_prob).unwrap());
        match idx {
            Ok(i) | Err(i) => i,
        }
    }
}

impl Distribution<usize> for WcFloat {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> usize {
        // Because we know the total is exactly 1.0, we can merely use a raw float value.
        // Otherwise caching `Range::new(0.0, running_total)` and sampling with
        // `range.ind_sample(&mut rng)` is recommended.
        let sample_prob = rng.gen::<f64>();
        self.search(sample_prob)
    }
}

fn take_samples<R: Rng>(rng: &mut R, wc: &impl Distribution<usize>) -> [usize; 8] {
    let mut counts = [0; 8];
    for _ in 0..SAMPLES {
        let sample = rng.sample(wc);
        counts[sample] += 1;
    }
    counts
}

fn print_mapping(counts: &[usize]) {
    println!("Item   | Expected | Actual   ");
    println!("-------+----------+----------");
    for (&(name, expected), &count) in DATA.iter().zip(counts.iter()) {
        let real = count as f64 / SAMPLES as f64;
        println!("{:06} | {:.6} | {:.6}", name, expected, real);
    }
}

fn main() {
    let mut rng = SmallRng::from_entropy();

    println!("    ~~~ U32 METHOD ~~~");
    let mut mapping = gen_mapping();
    let wc = WeightedChoice::new(&mut mapping);

    let counts = take_samples(&mut rng, &wc);
    print_mapping(&counts);

    println!();

    println!("   ~~~ FLOAT METHOD ~~~");
    // initialize the float version of `WeightedChoice`
    let mapping = gen_mapping_float();
    let wc = WcFloat::new(&mapping);

    let counts = take_samples(&mut rng, &wc);
    print_mapping(&counts);
}

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

    fn test_sample_logic(samples: usize) {
        let mut rng = SmallRng::from_entropy();

        let mapping = gen_mapping_float();
        let wc = WcFloat::new(&mapping);

        for _ in 0..samples {
            let prob = rng.gen::<f64>();
            let i = wc.search(prob);

            assert!(prob <= mapping[i], "p:{} m:{}", prob, mapping[i]);
            if i != 0 {
                assert!(mapping[i - 1] <= prob, "p:{} m:{}", prob, mapping[i - 1]);
            }
        }
    }

    #[test]
    fn small_logic() {
        test_sample_logic(1000);
    }

    #[test]
    #[ignore]
    fn large_logic() {
        test_sample_logic(100_000_000);
    }

    fn test_deviation<T: Distribution<usize>>(wc: T) {
        let mut rng = SmallRng::from_entropy();

        let counts = take_samples(&mut rng, &wc);
        for (&(_, expected), &count) in DATA.iter().zip(counts.iter()) {
            let real = count as f64 / SAMPLES as f64;
            let dev = (1.0 - real / expected).abs();
            assert!(dev < 0.01, "{}", dev);
        }
    }

    #[test]
    fn wcf_deviation() {
        let mapping = gen_mapping_float();
        let wc = WcFloat::new(&mapping);

        test_deviation(wc);
    }

    #[test]
    fn wc_deviation() {
        let mut mapping = gen_mapping();
        let wc = WeightedChoice::new(&mut mapping);

        test_deviation(wc);
    }
}
<commit_msg>ignore randomness tests<commit_after>extern crate rand;

use rand::distributions::{Distribution, Weighted, WeightedChoice};
use rand::prelude::*;

const DATA: [(&str, f64); 8] = [
    ("aleph", 1.0 / 5.0),
    ("beth", 1.0 / 6.0),
    ("gimel", 1.0 / 7.0),
    ("daleth", 1.0 / 8.0),
    ("he", 1.0 / 9.0),
    ("waw", 1.0 / 10.0),
    ("zayin", 1.0 / 11.0),
    ("heth", 1759.0 / 27720.0),
];

const SAMPLES: usize = 1_000_000;

/// Generate a mapping to be used by `WeightedChoice`
fn gen_mapping() -> Vec<Weighted<usize>> {
    DATA.iter()
        .enumerate()
        .map(|(i, &(_, p))| Weighted {
            // `WeightedChoice` requires `u32` weights rather than raw probabilities.  For each
            // probability, we convert it to a `u32` weight, and associate it with an index. We
            // multiply by a constant because small numbers such as 0.2 when casted to `u32`
            // become `0`.  This conversion decreases the accuracy of the mapping, which is why we
            // provide an implementation which uses `f64`s for the best accuracy.
            weight: (p * 1_000_000_000.0) as u32,
            item: i,
        })
        .collect()
}

/// Generate a mapping of the raw probabilities
fn gen_mapping_float() -> Vec<f64> {
    // This does the work of `WeightedChoice::new`, splitting a number into various ranges.  The
    // `item` of `Weighted` is represented here merely by the probability's position in the `Vec`.
    let mut running_total = 0.0;
    DATA.iter()
        .map(|&(_, p)| {
            running_total += p;
            running_total
        })
        .collect()
}

/// An implementation of `WeightedChoice` which uses probabilities rather than weights.  Refer to
/// the `WeightedChoice` source for serious usage.
struct WcFloat {
    mapping: Vec<f64>,
}

impl WcFloat {
    fn new(mapping: &[f64]) -> Self {
        Self {
            mapping: mapping.to_vec(),
        }
    }

    // This is roughly the same logic as `WeightedChoice::ind_sample` (though is likely slower)
    fn search(&self, sample_prob: f64) -> usize {
        let idx = self
            .mapping
            .binary_search_by(|p| p.partial_cmp(&sample_prob).unwrap());
        match idx {
            Ok(i) | Err(i) => i,
        }
    }
}

impl Distribution<usize> for WcFloat {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> usize {
        // Because we know the total is exactly 1.0, we can merely use a raw float value.
        // Otherwise caching `Range::new(0.0, running_total)` and sampling with
        // `range.ind_sample(&mut rng)` is recommended.
        let sample_prob = rng.gen::<f64>();
        self.search(sample_prob)
    }
}

fn take_samples<R: Rng>(rng: &mut R, wc: &impl Distribution<usize>) -> [usize; 8] {
    let mut counts = [0; 8];
    for _ in 0..SAMPLES {
        let sample = rng.sample(wc);
        counts[sample] += 1;
    }
    counts
}

fn print_mapping(counts: &[usize]) {
    println!("Item   | Expected | Actual   ");
    println!("-------+----------+----------");
    for (&(name, expected), &count) in DATA.iter().zip(counts.iter()) {
        let real = count as f64 / SAMPLES as f64;
        println!("{:06} | {:.6} | {:.6}", name, expected, real);
    }
}

fn main() {
    let mut rng = SmallRng::from_entropy();

    println!("    ~~~ U32 METHOD ~~~");
    let mut mapping = gen_mapping();
    let wc = WeightedChoice::new(&mut mapping);

    let counts = take_samples(&mut rng, &wc);
    print_mapping(&counts);

    println!();

    println!("   ~~~ FLOAT METHOD ~~~");
    // initialize the float version of `WeightedChoice`
    let mapping = gen_mapping_float();
    let wc = WcFloat::new(&mapping);

    let counts = take_samples(&mut rng, &wc);
    print_mapping(&counts);
}

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

    fn test_sample_logic(samples: usize) {
        let mut rng = SmallRng::from_entropy();

        let mapping = gen_mapping_float();
        let wc = WcFloat::new(&mapping);

        for _ in 0..samples {
            let prob = rng.gen::<f64>();
            let i = wc.search(prob);

            assert!(prob <= mapping[i], "p:{} m:{}", prob, mapping[i]);
            if i != 0 {
                assert!(mapping[i - 1] <= prob, "p:{} m:{}", prob, mapping[i - 1]);
            }
        }
    }

    #[test]
    fn small_logic() {
        test_sample_logic(1000);
    }

    #[test]
    #[ignore]
    fn large_logic() {
        test_sample_logic(100_000_000);
    }

    fn test_deviation<T: Distribution<usize>>(wc: T) {
        let mut rng = SmallRng::from_entropy();

        let counts = take_samples(&mut rng, &wc);
        for (&(_, expected), &count) in DATA.iter().zip(counts.iter()) {
            let real = count as f64 / SAMPLES as f64;
            let dev = (1.0 - real / expected).abs();
            assert!(dev < 0.01, "{}", dev);
        }
    }

    #[test]
    #[ignore]
    fn wcf_deviation() {
        let mapping = gen_mapping_float();
        let wc = WcFloat::new(&mapping);

        test_deviation(wc);
    }

    #[test]
    #[ignore]
    fn wc_deviation() {
        let mut mapping = gen_mapping();
        let wc = WeightedChoice::new(&mut mapping);

        test_deviation(wc);
    }
}
<|endoftext|>


<commit_before>// BatWarn
// Low Battery Warning Utility
// Polls battery status and pops up warning when low.

#![allow(unstable)]
extern crate collections;
extern crate regex;
use std::io::IoResult;
use std::io::timer::sleep;
use std::io::fs::File;
use std::io::process::{Command, Process, ProcessOutput};
use std::time::duration::Duration;
use std::num::from_str_radix;
use collections::string::String;
use regex::Regex;

static PERCENT_DANGER:     i32 = 20;
static PERCENT_CRITICAL:   i32 = 8;

#[derive(Debug)]
struct BatteryState {
    discharging: bool,
    percent: i32,
}

fn main() {
    // let poll_delay: Duration = Duration::minutes(5);
    let poll_delay: Duration = Duration::seconds(1);

    let mut nagproc: Option<Process> = None;

    loop {
        // Kill existing warnings
        nagproc = nagproc.and_then(|mut nagproc| {
            match nagproc.signal_kill() {
                Err(err) => {
                    println!("ERROR: {}", err);
                    Some(nagproc)
                },
                Ok(()) => None
            }
        });

        println!("spawn");
        match Command::new("i3-nagbar").arg("10").spawn() {
            Err(err) =>
                println!("ERROR: {}", err),
            Ok(child) =>
                nagproc = Some(child),
        };

        // Check battery status
        match acpi_battery_state() {
            Err(err) => {
                println!("ERROR: {}", err)
            },
            Ok(batstat) => {
                println!("{:?}", batstat);

                if !batstat.discharging {
                    // Do nothing
                } else if batstat.percent <= PERCENT_CRITICAL {
                    // Battery critically low.
                    // TODO
                } else if batstat.percent <= PERCENT_DANGER {
                    // Battery low.
                    // TODO
                } else {
                    // Battery discharging normally.
                }

            },
        }

        sleep(poll_delay);
    }
}

// Parse output from `acpi --battery`
fn acpi_battery_state() -> Result<BatteryState, String> {
    // ACPI output format: "Battery #{number}: #{state}, #{percent}%..."
    match acpi_battery_string() {
        Err(err) => Err(err),
        Ok(s) => {
            let re = Regex::new(r"Battery \d+: (\w+), (\d+)%.*").unwrap();
            match re.captures(s.as_slice()) {
                None => Err(String::from_str("malformed acpi output")),
                Some(captures) => {
                    let state = captures.at(1).unwrap();
                    let percent_str = captures.at(2).unwrap();
                    let percent = from_str_radix::<i32>(percent_str, 10).unwrap();
                    Ok(BatteryState {
                        discharging: state == "Discharging",
                        percent: percent,})
                }
            }
        },
    }
}

// Get output from `acpi --battery`
fn acpi_battery_string() -> Result<String, String> {
    let mut cmd = Command::new("acpi");
    cmd.arg("--battery");
    match cmd.output() {
        Err(err) => Err(String::from_str(err.desc)),
        Ok(ProcessOutput { status: exit, output: stdout, error: _ }) => {
            match exit.success() {
                false => Err(String::from_str("acpi returned with non-zero exit status")),
                true => {
                    let stdout = String::from_utf8(stdout).unwrap();
                    Ok(stdout)
                },
            }
        },
    }
}

// Read battery state from /proc.
#[allow(dead_code)]
fn read_battery_state_string() -> IoResult<String> {
    let path = Path::new("/proc/acpi/battery/BAT0/state");
    match File::open(&path) {
        Err(err) => Err(err),
        Ok(mut file) => file.read_to_string(),
    }
}

<commit_msg>show danger<commit_after>// BatWarn
// Low Battery Warning Utility
// Polls battery status and pops up warning when low.

#![allow(unstable)]
extern crate collections;
extern crate regex;
use std::io::IoResult;
use std::io::timer::sleep;
use std::io::fs::File;
use std::io::process::{Command, Process, ProcessOutput};
use std::time::duration::Duration;
use std::num::from_str_radix;
use collections::string::String;
use regex::Regex;

static PERCENT_DANGER:     i32 = 94;
static PERCENT_CRITICAL:   i32 = 8;

#[derive(Debug)]
struct BatteryState {
    discharging: bool,
    percent: i32,
}

fn main() {
    // let poll_delay: Duration = Duration::minutes(5);
    let poll_delay: Duration = Duration::seconds(1);

    let mut nagproc: Option<Process> = None;

    loop {
        // Kill existing warnings
        nagproc = nagproc.and_then(|mut nagproc| {
            match nagproc.signal_kill() {
                Err(err) => {
                    println!("ERROR: {}", err);
                    Some(nagproc)
                },
                Ok(()) => None
            }
        });

        // Check battery status
        match acpi_battery_state() {
            Err(err) => {
                println!("ERROR: {}", err)
            },
            Ok(batstat) => {
                println!("{:?}", batstat);

                if !batstat.discharging {
                    // Do nothing
                } else if batstat.percent <= PERCENT_CRITICAL {
                    // Battery critically low.
                    match Command::new("i3-nagbar").arg("10").spawn() {
                        Err(err) =>
                            println!("ERROR: {}", err),
                        Ok(child) =>
                            nagproc = Some(child),
                    };
                } else if batstat.percent <= PERCENT_DANGER {
                    // Battery low.
                    let message = "WARNING: Battery low!";
                    let child = Command::new("i3-nagbar")
                        .arg("-t warning")
                        .arg(format!("-m {}", message))
                        .arg("10")
                        .spawn();
                    match child {
                        Err(err) =>
                            println!("ERROR: {}", err),
                        Ok(child) =>
                            nagproc = Some(child),
                    };
                } else {
                    // Battery discharging normally.
                }

            },
        }

        sleep(poll_delay);
    }
}

// Parse output from `acpi --battery`
fn acpi_battery_state() -> Result<BatteryState, String> {
    // ACPI output format: "Battery #{number}: #{state}, #{percent}%..."
    match acpi_battery_string() {
        Err(err) => Err(err),
        Ok(s) => {
            let re = Regex::new(r"Battery \d+: (\w+), (\d+)%.*").unwrap();
            match re.captures(s.as_slice()) {
                None => Err(String::from_str("malformed acpi output")),
                Some(captures) => {
                    let state = captures.at(1).unwrap();
                    let percent_str = captures.at(2).unwrap();
                    let percent = from_str_radix::<i32>(percent_str, 10).unwrap();
                    Ok(BatteryState {
                        discharging: state == "Discharging",
                        percent: percent,})
                }
            }
        },
    }
}

// Get output from `acpi --battery`
fn acpi_battery_string() -> Result<String, String> {
    let mut cmd = Command::new("acpi");
    cmd.arg("--battery");
    match cmd.output() {
        Err(err) => Err(String::from_str(err.desc)),
        Ok(ProcessOutput { status: exit, output: stdout, error: _ }) => {
            match exit.success() {
                false => Err(String::from_str("acpi returned with non-zero exit status")),
                true => {
                    let stdout = String::from_utf8(stdout).unwrap();
                    Ok(stdout)
                },
            }
        },
    }
}

// Read battery state from /proc.
#[allow(dead_code)]
fn read_battery_state_string() -> IoResult<String> {
    let path = Path::new("/proc/acpi/battery/BAT0/state");
    match File::open(&path) {
        Err(err) => Err(err),
        Ok(mut file) => file.read_to_string(),
    }
}

<|endoftext|>


<commit_before>#![allow(unstable)]
// BatWarn
// Low Battery Warning Utility
// Polls battery status and pops up warning when low.

extern crate collections;
use std::io::timer::sleep;
use std::io::fs::File;
use std::io::IoResult;
use std::time::duration::Duration;
use collections::string::String;
use std::io::process::{Command, ProcessOutput};

static PERCENT_DANGER:     i32 = 20;
static PERCENT_CRITICAL:   i32 = 8;

fn main() {
    // let poll_delay: Duration = Duration::minutes(5);
    let poll_delay: Duration = Duration::seconds(1);

    loop {
        println!("loop body");

        // Check battery status
        read_battery_state().map(|s| {
            println!("{}", s);
        });
        acpi_battery_state();
        let percent = 72;
        let charging = false;

        // Kill existing warnings

        if charging {
            // Do nothing
        } else if percent <= PERCENT_CRITICAL {
            // Battery critically low.
        } else if percent <= PERCENT_DANGER {
            // Battery low.
        } else {
            // Battery discharging normally.
        }

        sleep(poll_delay);
    }
}

fn read_battery_state() -> IoResult<String> {
    let path = Path::new("/proc/acpi/battery/BAT0/state");
    match File::open(&path) {
        Err(err) => Err(err),
        Ok(mut file) => file.read_to_string(),
    }
}

fn acpi_battery_state() {
    let mut cmd = Command::new("rustc");
    cmd.arg("--version");
    match cmd.output() {
        Err(_) =>
            println!("failed"),
        Ok(ProcessOutput { status: exit, output: stdout, error: _ }) => {
            match exit.success() {
                false => println!("failed"),
                true => {
                    let stdout = String::from_utf8(stdout).unwrap();
                    println!("acpi out {}", stdout);
                },
            }
        },
    }
}
<commit_msg>parse some stuff<commit_after>// BatWarn
// Low Battery Warning Utility
// Polls battery status and pops up warning when low.

#![allow(unstable)]
extern crate collections;
extern crate regex;
use std::io::IoResult;
use std::io::timer::sleep;
use std::io::fs::File;
use std::io::process::{Command, ProcessOutput};
use std::time::duration::Duration;
use std::num::from_str_radix;
use collections::string::String;
use regex::Regex;

static PERCENT_DANGER:     i32 = 20;
static PERCENT_CRITICAL:   i32 = 8;

struct BatteryState {
    p1: i32,
}

fn main() {
    // let poll_delay: Duration = Duration::minutes(5);
    let poll_delay: Duration = Duration::seconds(1);

    loop {
        println!("loop body");

        // Check battery status
        read_battery_state().map(|s| {
            println!("{}", s);
        });
        acpi_battery_state().map(|s| {
            println!("{}", s);
        });
        let percent = 72;
        let charging = false;

        // Kill existing warnings

        if charging {
            // Do nothing
        } else if percent <= PERCENT_CRITICAL {
            // Battery critically low.
        } else if percent <= PERCENT_DANGER {
            // Battery low.
        } else {
            // Battery discharging normally.
        }

        sleep(poll_delay);
    }
}

fn read_battery_state() -> IoResult<String> {
    let path = Path::new("/proc/acpi/battery/BAT0/state");
    match File::open(&path) {
        Err(err) => Err(err),
        Ok(mut file) => file.read_to_string(),
    }
}

fn acpi_battery_state() -> Result<String, String> {
    // ACPI output format: "Battery #{number}: #{state}, #{percent}%..."
    match acpi_battery_string() {
        Err(err) => Err(err),
        Ok(s) => {
            let re = Regex::new(r"Battery \d+: (\w+), (\d+)%.*").unwrap();
            match re.captures(s.as_slice()) {
                None => Err(String::from_str("malformed acpi output")),
                Some(captures) => {
                    let state = captures.at(1).unwrap();
                    // Full Discharging Charging
                    let percent_str = captures.at(2).unwrap();
                    let percent = from_str_radix::<i32>(percent_str, 10).unwrap();
                    Ok(format!("state:{}({}) percent:{}", state, state=="Discharging", percent))
                }
            }
        },
    }
}

fn acpi_battery_string() -> Result<String, String> {
    let mut cmd = Command::new("acpi");
    cmd.arg("--battery");
    match cmd.output() {
        Err(err) => Err(String::from_str(err.desc)),
        Ok(ProcessOutput { status: exit, output: stdout, error: _ }) => {
            match exit.success() {
                false => Err(String::from_str("acpi returned with non-zero exit status")),
                true => {
                    let stdout = String::from_utf8(stdout).unwrap();
                    Ok(stdout)
                },
            }
        },
    }
}
<|endoftext|>


<commit_before>fn main() {
    let mut nums = vec![1, 2, 3];

    for num in nums.iter_mut() {
        *num *= 2;
    }

    for num in &mut nums {
        *num *= 2;
    }

    for num in &nums {
        println!("{}", num);
    }

    for num in nums.iter() {
        println!("{}", num);
    }

    for num in nums.into_iter() {
        println!("{}", num);
    }

    //for num in nums.iter() {
    //    println!("{}", num);
    //}
}<commit_msg>added comments<commit_after>fn main() {
    let mut nums = vec![1, 2, 3];

    for num in nums.iter_mut() {
        *num *= 2;
    }

    for num in &mut nums {
        *num *= 2;
    }

    for num in &nums {
        println!("{}", num);
    }

    // x.iter() ... iter() borrows x and returns an iterator to it
    // and once the iterator is dropped you can use x again
    for num in nums.iter() {
        println!("{}", num);
    }

    // x.into_iter() ... it borrows x and returns borrowed references into x
    // with into_iter you can never use x again because it moved away
    for num in nums.into_iter() {
        println!("{}", num);
    }

    //for num in nums.iter() {
    //    println!("{}", num);
    //}
}<|endoftext|>