<commit_before>//! The main entry point for the Space API server.
//!
//! Running this code starts a HTTP server instance. The default port is 3000, but you can set your
//! own favorite port by exporting the `PORT` environment variable.

extern crate rustc_serialize;
extern crate iron;
extern crate spaceapi;

pub mod datastore;
pub mod redis_store;

use std::net::Ipv4Addr;
use std::sync::{Mutex, Arc};

use rustc_serialize::json::{Json, ToJson};
use iron::{Request, Response, IronResult, Iron, Set};
use iron::{status, headers, middleware};
use iron::modifiers::Header;

pub use datastore::DataStore;
use spaceapi::utils::Optional;
use spaceapi::SensorTemplate::{PeopleNowPresentSensorTemplate, TemperatureSensorTemplate};

/// A specification of a sensor.
///
/// The ``sensor`` field contains the static data of a sensor and the
/// ``data_key`` says how to find the sensor value in the datastore.
#[derive(Debug)]
pub struct SensorSpec {
    sensor: spaceapi::SensorTemplate,
    data_key: String,
    data_type: SensorValueType,
}

/// All possible value types a sensor can have.
#[derive(Debug)]
pub enum SensorValueType {
    Int,
    Float,
    Bool,
}

/// The actual sensor values.
#[derive(Debug)]
pub enum SensorValue {
    Int(i64),
    Float(f64),
    Bool(bool),
}

/// A datastore wrapped in an Arc, a Mutex and a Box. Safe for use in multithreaded situations.
pub type SafeDataStore = Arc<Mutex<Box<DataStore>>>;

/// A Space API server instance.
///
/// You can create a new instance using the ``new`` constructor method by
/// passing it the host, the port, the ``Status`` object and a datastore.
///
/// The ``SpaceapiServer`` includes a web server through
/// [Hyper](http://hyper.rs/hyper/hyper/server/index.html). Simply call the ``serve`` method.
pub struct SpaceapiServer {
    host: Ipv4Addr,
    port: u16,
    status: spaceapi::Status,
    datastore: SafeDataStore,
    sensors: Vec<SensorSpec>
}

impl SpaceapiServer {

    pub fn new(host: Ipv4Addr, port: u16, status: spaceapi::Status, datastore: SafeDataStore) -> SpaceapiServer {
        SpaceapiServer {
            host: host,
            port: port,
            status: status,
            datastore: datastore,
            sensors: vec![],
        }
    }

    /// Start a HTTP server listening on ``self.host:self.port``.
    ///
    /// This call is blocking. It can be interrupted with SIGINT (Ctrl+C).
    pub fn serve(self) {
        let host = self.host;
        let port = self.port;
        println!("Starting HTTP server on http://{}:{}...", host, port);
        Iron::new(self).http((host, port)).unwrap();
    }

    /// Register a new sensor.
    ///
    /// The first argument is a ``spaceapi::Sensor`` instance containing all static data. The
    /// second argument specifies how to get the actual sensor value from the datastore. And the
    /// third argument specifies the data type of the value.
    pub fn register_sensor(&mut self, sensor: spaceapi::SensorTemplate, data_key: String, data_type: SensorValueType) {
        self.sensors.push(
            SensorSpec { sensor: sensor, data_key: data_key, data_type: data_type }
        );
    }

    fn build_response_json(&self) -> Json {

        // Create a mutable copy of the status struct
        let mut status_copy = self.status.clone();

        // Prepare sensor vector
        let mut temperature_sensors: Vec<spaceapi::TemperatureSensor> = Vec::new();
        let mut people_now_present_sensors: Vec<spaceapi::PeopleNowPresentSensor> = Vec::new();

        // Process registered sensors
        if !self.sensors.is_empty() {

            // Get access to datastore
            let datastore_clone = self.datastore.clone();

            // Add sensor data
            for sensor_spec in &self.sensors {

                let value = sensor_spec.get_sensor_value(&datastore_clone);

                // If value is available, save sensor data
                if value.is_some() {
                    match sensor_spec.sensor {

                        // Create temperature sensor instance
                        TemperatureSensorTemplate { ref unit, ref location, ref name, ref description } => {
                            let sensor = spaceapi::TemperatureSensor {
                                unit: (*unit).clone(),
                                location: (*location).clone(),
                                name: (*name).clone(),
                                description: (*description).clone(),
                                value: match value.unwrap() {
                                    SensorValue::Float(v) => v,
                                    _ => unreachable!(),
                                },
                            };
                            temperature_sensors.push(sensor);
                        },

                        // Create people now present sensor instance
                        PeopleNowPresentSensorTemplate { ref location, ref name, ref names, ref description } => {
                            let sensor = spaceapi::PeopleNowPresentSensor {
                                location: (*location).clone(),
                                name: (*name).clone(),
                                names: (*names).clone(),
                                description: (*description).clone(),
                                value: match value.unwrap() {
                                    SensorValue::Int(v) => v,
                                    _ => unreachable!(),
                                },
                            };
                            people_now_present_sensors.push(sensor);
                        },

                    }
                }

            }

        }

        // Add sensors to status object
        status_copy.sensors = Optional::Value(spaceapi::Sensors {
            people_now_present: match people_now_present_sensors.is_empty() {
                true => Optional::Absent,
                false => Optional::Value(people_now_present_sensors),
            },
            temperature: match temperature_sensors.is_empty() {
                true => Optional::Absent,
                false => Optional::Value(temperature_sensors),
            },
        });

        // Serialize to JSON
        status_copy.to_json()
    }

}

trait SensorDataFetcher {
    fn get_sensor_value(&self, datastore: &SafeDataStore) -> Option<SensorValue>;
}

impl SensorDataFetcher for SensorSpec {

    /// Retrieve sensor value from the datastore.
    fn get_sensor_value(&self, datastore: &SafeDataStore) -> Option<SensorValue> {
        let datastore_lock = datastore.lock().unwrap();
        match datastore_lock.retrieve(&self.data_key) {
            Ok(v) => {
                match self.data_type {
                    SensorValueType::Float => match v.parse::<f64>() {
                        Ok(i) => Some(SensorValue::Float(i)),
                        Err(_) => None,
                    },
                    SensorValueType::Int => match v.parse::<i64>() {
                        Ok(i) => Some(SensorValue::Int(i)),
                        Err(_) => None,
                    },
                    SensorValueType::Bool => None,  // TODO
                }
            },
            Err(_) => None,
        }
    }

}

impl middleware::Handler for SpaceapiServer {

    fn handle(&self, _: &mut Request) -> IronResult<Response> {
        // Get response body
        let body = self.build_response_json().to_string();

        // Create response
        let mut response = Response::with((status::Ok, body));

        // Set headers
        response.set_mut(Header(headers::ContentType("application/json; charset=utf-8".parse().unwrap())));
        response.set_mut(Header(headers::CacheControl(vec![headers::CacheDirective::NoCache])));
        response.set_mut(Header(headers::AccessControlAllowOrigin::Any));

        Ok(response)
    }
}

#[cfg(test)]
mod test {
    extern crate spaceapi;
    extern crate rustc_serialize;

    use std::net::Ipv4Addr;
    use std::sync::{Mutex,Arc};
    use rustc_serialize::json::Json;
    use spaceapi::utils::Optional;
    use super::SpaceapiServer;
    use super::datastore::DataStore;
    use super::redis_store::RedisStore;

    fn get_test_data() -> Json {
        // Create minimal status object
        let status = spaceapi::Status::new(
            "ourspace".to_string(),
            "https://example.com/logo.png".to_string(),
            "https://example.com/".to_string(),
            spaceapi::Location {
                address: Optional::Value("Street 1, Zürich, Switzerland".to_string()),
                lat: 47.123,
                lon: 8.88,
            },
            spaceapi::Contact {
                irc: Optional::Absent,
                twitter: Optional::Absent,
                foursquare: Optional::Absent,
                email: Optional::Value("hi@example.com".to_string()),
            },
            vec![
                "email".to_string(),
                "twitter".to_string(),
            ],
        );

        // Create datastore (TODO: Create dummy store for testing?)
        let datastore = Arc::new(Mutex::new(Box::new(RedisStore::new().unwrap()) as Box<DataStore>));

        // Initialize server
        let server = SpaceapiServer::new(Ipv4Addr::new(127, 0, 0, 1), 3001, status, datastore);

        // Build JSON
        server.build_response_json()
    }

    #[test]
    /// Verify that the result is a JSON object.
    fn verify_json_obj() {
        let json = get_test_data();
        assert!(json.is_object());
    }

    #[test]
    /// Verify that the result has the correct keys.
    fn verify_json_keys() {
        let json = get_test_data();
        let status = json.as_object().unwrap();  // We get back a BTreeMap<String, Json>
        let keys: Vec<String> = status.keys().cloned().collect();  // Collect the keys
        assert_eq!(keys, ["api", "contact", "issue_report_channels", "location",
                          "logo", "sensors", "space", "state", "url"]);
    }

    #[test]
    /// Verify static data
    fn verify_json_static_data() {
        let json = get_test_data();
        let status = json.as_object().unwrap();  // We get back a BTreeMap<String, Json>

        // Strings
        assert_eq!(status.get("api").unwrap().as_string().unwrap(), "0.13");
        assert_eq!(status.get("space").unwrap().as_string().unwrap(), "ourspace");
        assert_eq!(status.get("url").unwrap().as_string().unwrap(), "https://example.com/");
        assert_eq!(status.get("logo").unwrap().as_string().unwrap(), "https://example.com/logo.png");

        // Channels
        let channels: &Vec<Json> = status.get("issue_report_channels").unwrap().as_array().unwrap();
        let channel_values: Vec<String> = channels.iter()
                                                  .cloned()
                                                  .map(|c| c.as_string().unwrap().to_string())
                                                  .collect();
        assert_eq!(vec!["email", "twitter"], channel_values);
    }

    #[test]
    /// Verify location
    fn verify_json_location() {
        let json = get_test_data();
        let status = json.as_object().unwrap();
        let location = status.get("location").unwrap().as_object().unwrap();

        // Verify data
        let address = location.get("address").unwrap().as_string().unwrap();
        assert_eq!("Street 1, Zürich, Switzerland".to_string(), address);
        assert_eq!(47.123, location.get("lat").unwrap().as_f64().unwrap());
        assert_eq!(8.88, location.get("lon").unwrap().as_f64().unwrap());
    }

    #[test]
    /// Verify contact
    fn verify_json_contact() {
        let json = get_test_data();
        let status = json.as_object().unwrap();
        let contact = status.get("contact").unwrap().as_object().unwrap();

        // Verify data
        let email = contact.get("email").unwrap().as_string().unwrap();
        assert_eq!("hi@example.com".to_string(), email);
    }

    /* TODO: Update
    #[test]
    /// Verify sensor data
    fn verify_json_sensors() {
        let json = get_test_data();
        let status = json.as_object().unwrap();
        let sensors = status.get("sensors").unwrap().as_object().unwrap();
        let temperature_sensor = sensors.get("temperature").unwrap()
                                        .as_array().unwrap()[0]  // List of sensors
                                        .as_object().unwrap();  // Sensor object
        let people_sensor = sensors.get("people_now_present").unwrap()  // List of sensors
                                        .as_array().unwrap()[0]  // Sensor object
                                        .as_object().unwrap();

        // Verify temperature sensor
        let temp_location = temperature_sensor.get("location").unwrap().as_string().unwrap();
        let temp_name = temperature_sensor.get("name").unwrap().as_string().unwrap();
        let temp_unit = temperature_sensor.get("unit").unwrap().as_string().unwrap();
        let temp_value = temperature_sensor.get("value").unwrap().as_f64().unwrap();
        assert_eq!("Basement".to_string(), temp_location);
        assert_eq!("Raspberry CPU".to_string(), temp_name);
        assert_eq!("°C".to_string(), temp_unit);
        assert_eq!(42.5, temp_value);

        // Verify peoplesensor
        let people_location = people_sensor.get("location").unwrap().as_string().unwrap();
        let people_value = people_sensor.get("value").unwrap().as_u64().unwrap();
        assert_eq!("Hackerspace".to_string(), people_location);
        assert_eq!(23, people_value);
    }
    */

}
<commit_msg>Moved datastore out of build_response_json<commit_after>//! The main entry point for the Space API server.
//!
//! Running this code starts a HTTP server instance. The default port is 3000, but you can set your
//! own favorite port by exporting the `PORT` environment variable.

extern crate rustc_serialize;
extern crate iron;
extern crate spaceapi;

pub mod datastore;
pub mod redis_store;

use std::net::Ipv4Addr;
use std::sync::{Mutex, Arc};

use rustc_serialize::json::{Json, ToJson};
use iron::{Request, Response, IronResult, Iron, Set};
use iron::{status, headers, middleware};
use iron::modifiers::Header;

pub use datastore::DataStore;
use spaceapi::utils::Optional;
use spaceapi::SensorTemplate::{PeopleNowPresentSensorTemplate, TemperatureSensorTemplate};

/// A specification of a sensor.
///
/// The ``sensor`` field contains the static data of a sensor and the
/// ``data_key`` says how to find the sensor value in the datastore.
#[derive(Debug)]
pub struct SensorSpec {
    sensor: spaceapi::SensorTemplate,
    data_key: String,
    data_type: SensorValueType,
}

/// All possible value types a sensor can have.
#[derive(Debug)]
pub enum SensorValueType {
    Int,
    Float,
    Bool,
}

/// The actual sensor values.
#[derive(Debug)]
pub enum SensorValue {
    Int(i64),
    Float(f64),
    Bool(bool),
}

/// A datastore wrapped in an Arc, a Mutex and a Box. Safe for use in multithreaded situations.
pub type SafeDataStore = Arc<Mutex<Box<DataStore>>>;

/// A Space API server instance.
///
/// You can create a new instance using the ``new`` constructor method by
/// passing it the host, the port, the ``Status`` object and a datastore.
///
/// The ``SpaceapiServer`` includes a web server through
/// [Hyper](http://hyper.rs/hyper/hyper/server/index.html). Simply call the ``serve`` method.
pub struct SpaceapiServer {
    host: Ipv4Addr,
    port: u16,
    status: spaceapi::Status,
    datastore: SafeDataStore,
    sensors: Vec<SensorSpec>
}

impl SpaceapiServer {

    pub fn new(host: Ipv4Addr, port: u16, status: spaceapi::Status, datastore: SafeDataStore) -> SpaceapiServer {
        SpaceapiServer {
            host: host,
            port: port,
            status: status,
            datastore: datastore,
            sensors: vec![],
        }
    }

    /// Start a HTTP server listening on ``self.host:self.port``.
    ///
    /// This call is blocking. It can be interrupted with SIGINT (Ctrl+C).
    pub fn serve(self) {
        let host = self.host;
        let port = self.port;
        println!("Starting HTTP server on http://{}:{}...", host, port);
        Iron::new(self).http((host, port)).unwrap();
    }

    /// Register a new sensor.
    ///
    /// The first argument is a ``spaceapi::Sensor`` instance containing all static data. The
    /// second argument specifies how to get the actual sensor value from the datastore. And the
    /// third argument specifies the data type of the value.
    pub fn register_sensor(&mut self, sensor: spaceapi::SensorTemplate, data_key: String, data_type: SensorValueType) {
        self.sensors.push(
            SensorSpec { sensor: sensor, data_key: data_key, data_type: data_type }
        );
    }

    fn build_response_json(&self) -> Json {

        // Create a mutable copy of the status struct
        let mut status_copy = self.status.clone();

        // Prepare sensor vector
        let mut temperature_sensors: Vec<spaceapi::TemperatureSensor> = Vec::new();
        let mut people_now_present_sensors: Vec<spaceapi::PeopleNowPresentSensor> = Vec::new();

        // Process registered sensors
        if !self.sensors.is_empty() {

            // Add sensor data
            for sensor_spec in &self.sensors {

                let value = sensor_spec.get_sensor_value(&self.datastore);

                // If value is available, save sensor data
                if value.is_some() {
                    match sensor_spec.sensor {

                        // Create temperature sensor instance
                        TemperatureSensorTemplate { ref unit, ref location, ref name, ref description } => {
                            let sensor = spaceapi::TemperatureSensor {
                                unit: (*unit).clone(),
                                location: (*location).clone(),
                                name: (*name).clone(),
                                description: (*description).clone(),
                                value: match value.unwrap() {
                                    SensorValue::Float(v) => v,
                                    _ => unreachable!(),
                                },
                            };
                            temperature_sensors.push(sensor);
                        },

                        // Create people now present sensor instance
                        PeopleNowPresentSensorTemplate { ref location, ref name, ref names, ref description } => {
                            let sensor = spaceapi::PeopleNowPresentSensor {
                                location: (*location).clone(),
                                name: (*name).clone(),
                                names: (*names).clone(),
                                description: (*description).clone(),
                                value: match value.unwrap() {
                                    SensorValue::Int(v) => v,
                                    _ => unreachable!(),
                                },
                            };
                            people_now_present_sensors.push(sensor);
                        },

                    }
                }

            }

        }

        // Add sensors to status object
        status_copy.sensors = Optional::Value(spaceapi::Sensors {
            people_now_present: match people_now_present_sensors.is_empty() {
                true => Optional::Absent,
                false => Optional::Value(people_now_present_sensors),
            },
            temperature: match temperature_sensors.is_empty() {
                true => Optional::Absent,
                false => Optional::Value(temperature_sensors),
            },
        });

        // Serialize to JSON
        status_copy.to_json()
    }

}

trait SensorDataFetcher {
    fn get_sensor_value(&self, datastore: &SafeDataStore) -> Option<SensorValue>;
}

impl SensorDataFetcher for SensorSpec {

    /// Retrieve sensor value from the datastore.
    fn get_sensor_value(&self, datastore: &SafeDataStore) -> Option<SensorValue> {
        let datastore_clone = datastore.clone();
        let datastore_lock = datastore_clone.lock().unwrap();
        match datastore_lock.retrieve(&self.data_key) {
            Ok(v) => {
                match self.data_type {
                    SensorValueType::Float => match v.parse::<f64>() {
                        Ok(i) => Some(SensorValue::Float(i)),
                        Err(_) => None,
                    },
                    SensorValueType::Int => match v.parse::<i64>() {
                        Ok(i) => Some(SensorValue::Int(i)),
                        Err(_) => None,
                    },
                    SensorValueType::Bool => None,  // TODO
                }
            },
            Err(_) => None,
        }
    }

}

impl middleware::Handler for SpaceapiServer {

    fn handle(&self, _: &mut Request) -> IronResult<Response> {
        // Get response body
        let body = self.build_response_json().to_string();

        // Create response
        let mut response = Response::with((status::Ok, body));

        // Set headers
        response.set_mut(Header(headers::ContentType("application/json; charset=utf-8".parse().unwrap())));
        response.set_mut(Header(headers::CacheControl(vec![headers::CacheDirective::NoCache])));
        response.set_mut(Header(headers::AccessControlAllowOrigin::Any));

        Ok(response)
    }
}

#[cfg(test)]
mod test {
    extern crate spaceapi;
    extern crate rustc_serialize;

    use std::net::Ipv4Addr;
    use std::sync::{Mutex,Arc};
    use rustc_serialize::json::Json;
    use spaceapi::utils::Optional;
    use super::SpaceapiServer;
    use super::datastore::DataStore;
    use super::redis_store::RedisStore;

    fn get_test_data() -> Json {
        // Create minimal status object
        let status = spaceapi::Status::new(
            "ourspace".to_string(),
            "https://example.com/logo.png".to_string(),
            "https://example.com/".to_string(),
            spaceapi::Location {
                address: Optional::Value("Street 1, Zürich, Switzerland".to_string()),
                lat: 47.123,
                lon: 8.88,
            },
            spaceapi::Contact {
                irc: Optional::Absent,
                twitter: Optional::Absent,
                foursquare: Optional::Absent,
                email: Optional::Value("hi@example.com".to_string()),
            },
            vec![
                "email".to_string(),
                "twitter".to_string(),
            ],
        );

        // Create datastore (TODO: Create dummy store for testing?)
        let datastore = Arc::new(Mutex::new(Box::new(RedisStore::new().unwrap()) as Box<DataStore>));

        // Initialize server
        let server = SpaceapiServer::new(Ipv4Addr::new(127, 0, 0, 1), 3001, status, datastore);

        // Build JSON
        server.build_response_json()
    }

    #[test]
    /// Verify that the result is a JSON object.
    fn verify_json_obj() {
        let json = get_test_data();
        assert!(json.is_object());
    }

    #[test]
    /// Verify that the result has the correct keys.
    fn verify_json_keys() {
        let json = get_test_data();
        let status = json.as_object().unwrap();  // We get back a BTreeMap<String, Json>
        let keys: Vec<String> = status.keys().cloned().collect();  // Collect the keys
        assert_eq!(keys, ["api", "contact", "issue_report_channels", "location",
                          "logo", "sensors", "space", "state", "url"]);
    }

    #[test]
    /// Verify static data
    fn verify_json_static_data() {
        let json = get_test_data();
        let status = json.as_object().unwrap();  // We get back a BTreeMap<String, Json>

        // Strings
        assert_eq!(status.get("api").unwrap().as_string().unwrap(), "0.13");
        assert_eq!(status.get("space").unwrap().as_string().unwrap(), "ourspace");
        assert_eq!(status.get("url").unwrap().as_string().unwrap(), "https://example.com/");
        assert_eq!(status.get("logo").unwrap().as_string().unwrap(), "https://example.com/logo.png");

        // Channels
        let channels: &Vec<Json> = status.get("issue_report_channels").unwrap().as_array().unwrap();
        let channel_values: Vec<String> = channels.iter()
                                                  .cloned()
                                                  .map(|c| c.as_string().unwrap().to_string())
                                                  .collect();
        assert_eq!(vec!["email", "twitter"], channel_values);
    }

    #[test]
    /// Verify location
    fn verify_json_location() {
        let json = get_test_data();
        let status = json.as_object().unwrap();
        let location = status.get("location").unwrap().as_object().unwrap();

        // Verify data
        let address = location.get("address").unwrap().as_string().unwrap();
        assert_eq!("Street 1, Zürich, Switzerland".to_string(), address);
        assert_eq!(47.123, location.get("lat").unwrap().as_f64().unwrap());
        assert_eq!(8.88, location.get("lon").unwrap().as_f64().unwrap());
    }

    #[test]
    /// Verify contact
    fn verify_json_contact() {
        let json = get_test_data();
        let status = json.as_object().unwrap();
        let contact = status.get("contact").unwrap().as_object().unwrap();

        // Verify data
        let email = contact.get("email").unwrap().as_string().unwrap();
        assert_eq!("hi@example.com".to_string(), email);
    }

    /* TODO: Update
    #[test]
    /// Verify sensor data
    fn verify_json_sensors() {
        let json = get_test_data();
        let status = json.as_object().unwrap();
        let sensors = status.get("sensors").unwrap().as_object().unwrap();
        let temperature_sensor = sensors.get("temperature").unwrap()
                                        .as_array().unwrap()[0]  // List of sensors
                                        .as_object().unwrap();  // Sensor object
        let people_sensor = sensors.get("people_now_present").unwrap()  // List of sensors
                                        .as_array().unwrap()[0]  // Sensor object
                                        .as_object().unwrap();

        // Verify temperature sensor
        let temp_location = temperature_sensor.get("location").unwrap().as_string().unwrap();
        let temp_name = temperature_sensor.get("name").unwrap().as_string().unwrap();
        let temp_unit = temperature_sensor.get("unit").unwrap().as_string().unwrap();
        let temp_value = temperature_sensor.get("value").unwrap().as_f64().unwrap();
        assert_eq!("Basement".to_string(), temp_location);
        assert_eq!("Raspberry CPU".to_string(), temp_name);
        assert_eq!("°C".to_string(), temp_unit);
        assert_eq!(42.5, temp_value);

        // Verify peoplesensor
        let people_location = people_sensor.get("location").unwrap().as_string().unwrap();
        let people_value = people_sensor.get("value").unwrap().as_u64().unwrap();
        assert_eq!("Hackerspace".to_string(), people_location);
        assert_eq!(23, people_value);
    }
    */

}
<|endoftext|>


<commit_before>import std::run;
import std::run::spawn_process;
import std::io;
import std::os;
import io::writer_util;
import ctypes::{pid_t, fd_t};

export run;

#[cfg(target_os = "win32")]
fn target_env(lib_path: str, prog: str) -> option<[(str,str)]> {

    let env = std::generic_os::env();

    env = vec::map(env) {|pair|
        let (k,v) = pair;
        if k == "PATH" { ("PATH", v + ";" + lib_path) }
        else { (k,v) }
    };
    if str::ends_with(prog, "rustc.exe") {
        env += [("RUST_THREADS", "1")]
    }
    ret some(env);
}

#[cfg(target_os = "linux")]
#[cfg(target_os = "macos")]
#[cfg(target_os = "freebsd")]
fn target_env(lib_path: str, prog: str) -> option<[(str,str)]> {
    none
}

fn run(lib_path: str, prog: str, args: [str],
       input: option<str>) -> {status: int, out: str, err: str} {

    let pipe_in = os::pipe();
    let pipe_out = os::pipe();
    let pipe_err = os::pipe();
    let pid = spawn_process(prog, args, target_env(lib_path, prog), none,
                            pipe_in.in, pipe_out.out, pipe_err.out);

    os::close(pipe_in.in);
    os::close(pipe_out.out);
    os::close(pipe_err.out);
    if pid == -1i32 {
        os::close(pipe_in.out);
        os::close(pipe_out.in);
        os::close(pipe_err.in);
        fail;
    }

    writeclose(pipe_in.out, input);
    let output = readclose(pipe_out.in);
    let errput = readclose(pipe_err.in);
    let status = run::waitpid(pid);
    ret {status: status, out: output, err: errput};
}

fn writeclose(fd: fd_t, s: option<str>) {
    if option::is_some(s) {
        let writer = io::fd_writer(fd, false);
        writer.write_str(option::get(s));
    }

    os::close(fd);
}

fn readclose(fd: fd_t) -> str {
    // Copied from run::program_output
    let file = os::fd_FILE(fd);
    let reader = io::FILE_reader(file, false);
    let buf = "";
    while !reader.eof() {
        let bytes = reader.read_bytes(4096u);
        buf += str::from_bytes(bytes);
    }
    os::fclose(file);
    ret buf;
}
<commit_msg>Suppress warnings in compiletest<commit_after>import std::run;
import std::run::spawn_process;
import std::io;
import std::os;
import io::writer_util;
import ctypes::{pid_t, fd_t};

export run;

#[cfg(target_os = "win32")]
fn target_env(lib_path: str, prog: str) -> option<[(str,str)]> {

    let env = std::generic_os::env();

    env = vec::map(env) {|pair|
        let (k,v) = pair;
        if k == "PATH" { ("PATH", v + ";" + lib_path) }
        else { (k,v) }
    };
    if str::ends_with(prog, "rustc.exe") {
        env += [("RUST_THREADS", "1")]
    }
    ret some(env);
}

#[cfg(target_os = "linux")]
#[cfg(target_os = "macos")]
#[cfg(target_os = "freebsd")]
fn target_env(_lib_path: str, _prog: str) -> option<[(str,str)]> {
    none
}

fn run(lib_path: str, prog: str, args: [str],
       input: option<str>) -> {status: int, out: str, err: str} {

    let pipe_in = os::pipe();
    let pipe_out = os::pipe();
    let pipe_err = os::pipe();
    let pid = spawn_process(prog, args, target_env(lib_path, prog), none,
                            pipe_in.in, pipe_out.out, pipe_err.out);

    os::close(pipe_in.in);
    os::close(pipe_out.out);
    os::close(pipe_err.out);
    if pid == -1i32 {
        os::close(pipe_in.out);
        os::close(pipe_out.in);
        os::close(pipe_err.in);
        fail;
    }

    writeclose(pipe_in.out, input);
    let output = readclose(pipe_out.in);
    let errput = readclose(pipe_err.in);
    let status = run::waitpid(pid);
    ret {status: status, out: output, err: errput};
}

fn writeclose(fd: fd_t, s: option<str>) {
    if option::is_some(s) {
        let writer = io::fd_writer(fd, false);
        writer.write_str(option::get(s));
    }

    os::close(fd);
}

fn readclose(fd: fd_t) -> str {
    // Copied from run::program_output
    let file = os::fd_FILE(fd);
    let reader = io::FILE_reader(file, false);
    let buf = "";
    while !reader.eof() {
        let bytes = reader.read_bytes(4096u);
        buf += str::from_bytes(bytes);
    }
    os::fclose(file);
    ret buf;
}
<|endoftext|>


<commit_before>//! [Scott numerals](http://lucacardelli.name/Papers/Notes/scott2.pdf)

use term::{Term, abs, app};
use term::Term::*;

/// Produces a Scott-encoded number zero.
///
/// ZERO := λxy.x = λ λ 2
///
/// # Example
/// ```
/// use lambda_calculus::data::numerals::scott::zero;
/// use lambda_calculus::*;
///
/// assert_eq!(zero(), 0.into_scott());
/// ```
pub fn zero() -> Term { abs!(2, Var(2)) }

/// Applied to a Scott-encoded number it produces its successor.
///
/// SUCC := λnxy.y n = λ λ λ 1 3
///
/// # Example
/// ```
/// use lambda_calculus::data::numerals::scott::succ;
/// use lambda_calculus::*;
///
/// assert_eq!(beta(app(succ(), 0.into_scott()), NOR, 0), 1.into_scott());
/// assert_eq!(beta(app(succ(), 1.into_scott()), NOR, 0), 2.into_scott());
/// ```
pub fn succ() -> Term {
    abs!(3, app(Var(1), Var(3)))
}

/// Applied to a Scott-encoded number it produces its predecessor.
///
/// PRED := λn.n ZERO (λx.x) = λ 1 ZERO (λ 1)
///
/// # Example
/// ```
/// use lambda_calculus::data::numerals::scott::pred;
/// use lambda_calculus::*;
///
/// assert_eq!(beta(app(pred(), 1.into_scott()), NOR, 0), 0.into_scott());
/// assert_eq!(beta(app(pred(), 3.into_scott()), NOR, 0), 2.into_scott());
/// ```
pub fn pred() -> Term {
    abs(app!(Var(1), zero(), abs(Var(1))))
}
<commit_msg>add is_zero for Scott numerals<commit_after>//! [Scott numerals](http://lucacardelli.name/Papers/Notes/scott2.pdf)

use data::boolean::{tru, fls};
use term::{Term, abs, app};
use term::Term::*;

/// Produces a Scott-encoded number zero.
///
/// ZERO := λxy.x = λ λ 2
///
/// # Example
/// ```
/// use lambda_calculus::data::numerals::scott::zero;
/// use lambda_calculus::*;
///
/// assert_eq!(zero(), 0.into_scott());
/// ```
pub fn zero() -> Term { abs!(2, Var(2)) }

/// Applied to a Scott-encoded number it produces its successor.
///
/// SUCC := λnxy.y n = λ λ λ 1 3
///
/// # Example
/// ```
/// use lambda_calculus::data::numerals::scott::succ;
/// use lambda_calculus::*;
///
/// assert_eq!(beta(app(succ(), 0.into_scott()), NOR, 0), 1.into_scott());
/// assert_eq!(beta(app(succ(), 1.into_scott()), NOR, 0), 2.into_scott());
/// ```
pub fn succ() -> Term {
    abs!(3, app(Var(1), Var(3)))
}

/// Applied to a Scott-encoded number it produces its predecessor.
///
/// PRED := λn.n ZERO (λx.x) = λ 1 ZERO (λ 1)
///
/// # Example
/// ```
/// use lambda_calculus::data::numerals::scott::pred;
/// use lambda_calculus::*;
///
/// assert_eq!(beta(app(pred(), 1.into_scott()), NOR, 0), 0.into_scott());
/// assert_eq!(beta(app(pred(), 3.into_scott()), NOR, 0), 2.into_scott());
/// ```
pub fn pred() -> Term {
    abs(app!(Var(1), zero(), abs(Var(1))))
}

/// Applied to a Scott-encoded number it produces a lambda-encoded boolean, indicating whether its
/// argument is equal to zero.
///
/// IS_ZERO := λn.n TRUE (λx.FALSE) =  λ 1 TRUE (λ FALSE)
///
/// # Example
/// ```
/// use lambda_calculus::data::numerals::scott::is_zero;
/// use lambda_calculus::data::boolean::{tru, fls};
/// use lambda_calculus::*;
///
/// assert_eq!(beta(app(is_zero(), 0.into_scott()), NOR, 0), tru());
/// assert_eq!(beta(app(is_zero(), 1.into_scott()), NOR, 0), fls());
/// ```
pub fn is_zero() -> Term {
    abs(app!(Var(1), tru(), abs(fls())))
}
<|endoftext|>


<commit_before>use crate::{common::ui::{UIWriter,
                         UI},
            error::Result,
            hcore::package::PackageArchive};
use serde::Serialize;
use serde_json::{self,
                 Value as Json};
use std::path::Path;

fn convert_to_json<T>(src: &T) -> Json
    where T: Serialize
{
    serde_json::to_value(src).unwrap_or(Json::Null)
}

pub fn start(ui: &mut UI, src: &Path, to_json: bool) -> Result<()> {
    let ident = PackageArchive::new(src)?.ident()?;

    if to_json {
        println!("{}", convert_to_json(&ident));
    } else {
        ui.begin(format!("Reading PackageIdent from {}", &src.display()))?;
        ui.para("")?;

        println!("Package Path   : {}", &src.display());
        println!("Origin         : {}", &ident.origin);
        println!("Name           : {}", &ident.name);
        println!("Version        : {}", &ident.version.unwrap());
        println!("Release        : {}", &ident.release.unwrap());
    }
    Ok(())
}
<commit_msg>hab pkg info extended metadata<commit_after>use crate::{common::ui::{UIWriter,
                         UI},
            error::{Error,
                    Result},
            hcore::{crypto::artifact,
                    package::{PackageArchive,
                              PackageIdent,
                              PackageTarget}}};
use serde::Serialize;
use serde_json::{self,
                 Value as Json};
use std::path::Path;

#[derive(Deserialize, Serialize)]
struct PackageArchiveInfo {
    format_version:    String,
    key_name:          String,
    hash_type:         String,
    signature_raw:     String,
    origin:            String,
    name:              String,
    version:           Option<String>,
    release:           Option<String>,
    checksum:          Option<String>,
    target:            PackageTarget,
    is_a_service:      bool,
    deps:              Vec<PackageIdent>,
    tdeps:             Vec<PackageIdent>,
    build_deps:        Vec<PackageIdent>,
    build_tdeps:       Vec<PackageIdent>,
    exposes:           Vec<u16>,
    pkg_services:      Vec<PackageIdent>,
    resolved_services: Vec<PackageIdent>,
    manifest:          Option<String>,
    config:            Option<String>,
    svc_user:          Option<String>,
    ld_run_path:       Option<String>,
    ldflags:           Option<String>,
    cflags:            Option<String>,
}

fn convert_to_json<T>(src: &T) -> Result<Json>
    where T: Serialize
{
    serde_json::to_value(src).map_err(|e| habitat_core::Error::RenderContextSerialization(e).into())
}

pub fn start(ui: &mut UI, src: &Path, to_json: bool) -> Result<()> {
    let header = artifact::get_artifact_header(src)?;
    let mut archive = PackageArchive::new(src)?;
    let ident = archive.ident()?;
    let info =
        PackageArchiveInfo { format_version:    header.format_version,
                             key_name:          header.key_name,
                             hash_type:         header.hash_type,
                             signature_raw:     header.signature_raw,
                             origin:            ident.origin.clone(),
                             name:              ident.name.clone(),
                             version:           ident.version,
                             release:           ident.release,
                             checksum:          archive.checksum().ok(),
                             target:            archive.target().expect("pkg info archive target"),
                             deps:              archive.deps().unwrap_or(Vec::new()),
                             build_deps:        archive.build_deps().unwrap_or(Vec::new()),
                             tdeps:             archive.tdeps().unwrap_or(Vec::new()),
                             build_tdeps:       archive.build_tdeps().unwrap_or(Vec::new()),
                             exposes:           archive.exposes().unwrap_or(Vec::new()),
                             pkg_services:      archive.pkg_services().unwrap_or(Vec::new()),
                             resolved_services: archive.resolved_services().unwrap_or(Vec::new()),
                             manifest:
                                 archive.manifest()
                                        .map_or_else(|_| None, |v| Some(v.to_string())),
                             config:            archive.config().and_then(|v| Some(v.to_string())),
                             svc_user:
                                 archive.svc_user()
                                        .map_or_else(|_| None, |v| Some(v.to_string())),
                             ld_run_path:       archive.ld_run_path()
                                                       .and_then(|v| Some(v.to_string())),
                             ldflags:           archive.ldflags().and_then(|v| Some(v.to_string())),
                             cflags:            archive.cflags().and_then(|v| Some(v.to_string())),
                             is_a_service:      archive.is_a_service(), };

    if to_json {
        match convert_to_json(&info) {
            Ok(content) => {
                println!("{}", content);
                return Ok(());
            }
            Err(e) => {
                ui.fatal(format!("Failed to deserialize into json! {:?}.", e))?;
                return Err(Error::from(e));
            }
        }
    } else {
        ui.begin(format!("Reading PackageIdent from {}", &src.display()))?;
        ui.para("")?;

        println!("Package Path   : {}", &src.display());
        println!("Origin         : {}", info.origin);
        println!("Name           : {}", info.name);
        println!("Version        : {}",
                 info.version.unwrap_or("".to_string()));
        println!("Release        : {}",
                 info.release.unwrap_or("".to_string()));
    }
    Ok(())
}
<|endoftext|>


<commit_before>// Copyright (c) 2017, All Contributors (see CONTRIBUTORS file)
//
// 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/.
//!
//! This program is used to run doctests defined in doc/script
//!
#![feature(slice_patterns)]
extern crate glob;
extern crate pumpkindb;
extern crate regex;
extern crate crossbeam;
extern crate tempdir;
extern crate lmdb_zero as lmdb;
extern crate nom;

use std::io::prelude::*;
use std::fs;
use std::fs::File;
use std::sync::mpsc;

use regex::Regex;
use glob::glob;

use pumpkindb::script::{RequestMessage, ResponseMessage, EnvId, Env, VM};
use pumpkindb::script::{textparser, binparser};
use pumpkindb::pubsub;

use tempdir::TempDir;

fn eval(name: &[u8], script: &[u8]) {
    let dir = TempDir::new("pumpkindb").unwrap();
    let path = dir.path().to_str().unwrap();
    fs::create_dir_all(path).expect("can't create directory");
    let env = unsafe {
        lmdb::EnvBuilder::new()
            .expect("can't create env builder")
            .open(path, lmdb::open::Flags::empty(), 0o600)
            .expect("can't open env")
    };
    let name = String::from(std::str::from_utf8(name).unwrap());

    let db = lmdb::Database::open(&env,
                                  None,
                                  &lmdb::DatabaseOptions::new(lmdb::db::CREATE))
        .expect("can't open database");
    crossbeam::scope(|scope| {
        let mut publisher = pubsub::Publisher::new();
        let publisher_accessor = publisher.accessor();
        let publisher_thread = scope.spawn(move || publisher.run());
        let mut vm = VM::new(&env, &db, publisher_accessor.clone());
        let sender = vm.sender();
        let handle = scope.spawn(move || vm.run());
        let (callback, receiver) = mpsc::channel::<ResponseMessage>();
        let _ = sender.send(RequestMessage::ScheduleEnv(EnvId::new(), Vec::from(script), callback));
        match receiver.recv() {
            Ok(ResponseMessage::EnvTerminated(_, stack, stack_size)) => {
                let _ = sender.send(RequestMessage::Shutdown);
                publisher_accessor.shutdown();
                let mut script_env = Env::new_with_stack(stack, stack_size).unwrap();
                let val = script_env.pop().unwrap();
                assert_eq!(Vec::from(val), vec![1], "{} was expected to succeeed", &name);
                println!(" * {}", &name);
            }
            Ok(ResponseMessage::EnvFailed(_, err, _, _)) => {
                let _ = sender.send(RequestMessage::Shutdown);
                publisher_accessor.shutdown();
                panic!("Error while executing {:?}: {:?}", &name, err)
            }
            Err(err) => {
               let _ = sender.send(RequestMessage::Shutdown);
               publisher_accessor.shutdown();
               panic!("recv error: {:?}", err);
            }
        }
        let _ = handle.join();
        let _ = publisher_thread.join();
    });
}

fn main() {
    let re = Regex::new(r"```test\n((.+\n?)+)```").unwrap();
    for entry in glob("doc/script/**/*.md").expect("Failed to read glob pattern") {
        match entry {
            Ok(path) => {
                println!("{}:", path.to_str().unwrap());
                let mut f = File::open(path).expect("can't open file");
                let mut s = String::new();
                f.read_to_string(&mut s).expect("can't read file");
                for cap in re.captures_iter(s.as_ref()) {
                    let programs = textparser::programs(cap[1].as_ref()).unwrap().1;
                    for program in programs {
                        if program.len() > 0 {
                            match binparser::word(program.as_slice()) {
                                nom::IResult::Done(&[0x81, b':', ref rest..], program) => {
                                    eval(&program[1..], rest);
                                },
                                other => panic!("test definition parse error {:?}", other)
                            }
                        }
                    }

                }
            },
            Err(_) => (),
        }
    }
}
<commit_msg>Problem: can't execute doctests in Windows<commit_after>// Copyright (c) 2017, All Contributors (see CONTRIBUTORS file)
//
// 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/.
//!
//! This program is used to run doctests defined in doc/script
//!
#![feature(slice_patterns)]
extern crate glob;
extern crate pumpkindb;
extern crate regex;
extern crate crossbeam;
extern crate tempdir;
extern crate lmdb_zero as lmdb;
extern crate nom;

use std::io::prelude::*;
use std::fs;
use std::fs::File;
use std::sync::mpsc;

use regex::Regex;
use glob::glob;

use pumpkindb::script::{RequestMessage, ResponseMessage, EnvId, Env, VM};
use pumpkindb::script::{textparser, binparser};
use pumpkindb::pubsub;

use tempdir::TempDir;

fn eval(name: &[u8], script: &[u8]) {
    let dir = TempDir::new("pumpkindb").unwrap();
    let path = dir.path().to_str().unwrap();
    fs::create_dir_all(path).expect("can't create directory");
    let env = unsafe {
        lmdb::EnvBuilder::new()
            .expect("can't create env builder")
            .open(path, lmdb::open::Flags::empty(), 0o600)
            .expect("can't open env")
    };
    let name = String::from(std::str::from_utf8(name).unwrap());

    let db = lmdb::Database::open(&env,
                                  None,
                                  &lmdb::DatabaseOptions::new(lmdb::db::CREATE))
        .expect("can't open database");
    crossbeam::scope(|scope| {
        let mut publisher = pubsub::Publisher::new();
        let publisher_accessor = publisher.accessor();
        let publisher_thread = scope.spawn(move || publisher.run());
        let mut vm = VM::new(&env, &db, publisher_accessor.clone());
        let sender = vm.sender();
        let handle = scope.spawn(move || vm.run());
        let (callback, receiver) = mpsc::channel::<ResponseMessage>();
        let _ = sender.send(RequestMessage::ScheduleEnv(EnvId::new(), Vec::from(script), callback));
        match receiver.recv() {
            Ok(ResponseMessage::EnvTerminated(_, stack, stack_size)) => {
                let _ = sender.send(RequestMessage::Shutdown);
                publisher_accessor.shutdown();
                let mut script_env = Env::new_with_stack(stack, stack_size).unwrap();
                let val = script_env.pop().unwrap();
                assert_eq!(Vec::from(val), vec![1], "{} was expected to succeeed", &name);
                println!(" * {}", &name);
            }
            Ok(ResponseMessage::EnvFailed(_, err, _, _)) => {
                let _ = sender.send(RequestMessage::Shutdown);
                publisher_accessor.shutdown();
                panic!("Error while executing {:?}: {:?}", &name, err)
            }
            Err(err) => {
               let _ = sender.send(RequestMessage::Shutdown);
               publisher_accessor.shutdown();
               panic!("recv error: {:?}", err);
            }
        }
        let _ = handle.join();
        let _ = publisher_thread.join();
    });
}

fn main() {
    let re = Regex::new(r"```test\r?\n((.+\r?\n?)+)```").unwrap();
    for entry in glob("doc/script/**/*.md").expect("Failed to read glob pattern") {
        match entry {
            Ok(path) => {
                println!("{}:", path.to_str().unwrap());
                let mut f = File::open(path).expect("can't open file");
                let mut s = String::new();
                f.read_to_string(&mut s).expect("can't read file");
                for cap in re.captures_iter(s.as_ref()) {
                    let programs = textparser::programs(cap[1].as_ref()).unwrap().1;
                    for program in programs {
                        if program.len() > 0 {
                            match binparser::word(program.as_slice()) {
                                nom::IResult::Done(&[0x81, b':', ref rest..], program) => {
                                    eval(&program[1..], rest);
                                },
                                other => panic!("test definition parse error {:?}", other)
                            }
                        }
                    }

                }
            },
            Err(_) => (),
        }
    }
}
<|endoftext|>


<commit_before>
use inefficient_flat_time_steward as s;
use ::{TimeSteward, DeterministicRandomId, Column, ColumnId, RowId, Mutator,
       TimeStewardLifetimedMethods, Accessor, MomentaryAccessor, PredictorAccessor};
use std::rc::Rc;
use rand::Rng;

use std::io::Write;
macro_rules! printlnerr(
    ($($arg:tt)*) => { {
        let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
        r.expect("failed printing to stderr");
    } }
);

type Time = i64;

const HOW_MANY_PHILOSOPHERS: i32 = 7;

#[derive(Clone)]
struct Basics;
impl ::Basics for Basics {
  type Time = Time;
  type Constants = ();
}

#[derive(Clone)]
struct Philosopher {
  // This is sometimes in the future because
  // they muse philosophically about handshakes
  // for a while, whenever one of them happens.
  time_when_next_initiates_handshake: Time,
}
impl Column for Philosopher {
  type FieldType = Self;
  fn column_id() -> ColumnId {
    ColumnId(0x4084d1501468b6dd)
  }
}

type Steward = s::Steward<Basics>;

fn get_philosopher_id(index: i32) -> RowId {
  DeterministicRandomId::new(&(0x2302c38efb47e0d0u64, index))
}

pub fn testfunc() {

  let mut stew: Steward = ::TimeSteward::new_empty((),
                                                   vec![s::Predictor {
                                                          predictor_id: 0x0e7f27c7643f8167,
                                                          column_id: Philosopher::column_id(),
                                                          function: Rc::new(|pa, whodunnit| {
      printlnerr!("Planning {}", whodunnit);
      let me = pa.get::<Philosopher>(whodunnit).unwrap().clone();
      pa.predict_at_time(&me.time_when_next_initiates_handshake,
                         Rc::new(move |m| {
        let now = *m.now();
        let friend_id = get_philosopher_id(m.rng().gen_range(0, HOW_MANY_PHILOSOPHERS));
        let awaken_time_1 = now + m.rng().gen_range(-1, 4);
        let awaken_time_2 = now + m.rng().gen_range(-1, 7);
        printlnerr!("SHAKE!!! @{}. {}={}; {}={}", now, whodunnit, awaken_time_2, friend_id, awaken_time_1);
        // IF YOU SHAKE YOUR OWN HAND YOU RECOVER
        // IN THE SECOND TIME APPARENTLY
        m.set::<Philosopher>(friend_id,
                             Some(Philosopher {
                               time_when_next_initiates_handshake: awaken_time_1,
                             }));
        m.set::<Philosopher>(whodunnit,
                             Some(Philosopher {
                               time_when_next_initiates_handshake: awaken_time_2,
                             }));
      }));
    }),
                                                        }]);

  stew.insert_fiat_event(0,
                         DeterministicRandomId::new(&0x32e1570766e768a7u64),
                         Rc::new(|m| {
    printlnerr!("FIAT!!!!!");
    for i in 0..HOW_MANY_PHILOSOPHERS {
      m.set::<Philosopher>(get_philosopher_id(i),
                           Some(Philosopher {
                             time_when_next_initiates_handshake: (i + 1) as Time,
                           }));
    }
  }));

  stew.snapshot_before(&50);

  // panic!("anyway")
}

#[test]
fn actuallytest() {
  testfunc();
}
<commit_msg>handshakes test a longer simulation<commit_after>
use inefficient_flat_time_steward as s;
use ::{TimeSteward, DeterministicRandomId, Column, ColumnId, RowId, Mutator,
       TimeStewardLifetimedMethods, Accessor, MomentaryAccessor, PredictorAccessor};
use std::rc::Rc;
use rand::Rng;

use std::io::Write;
macro_rules! printlnerr(
    ($($arg:tt)*) => { {
        let r = writeln!(&mut ::std::io::stderr(), $($arg)*);
        r.expect("failed printing to stderr");
    } }
);

type Time = i64;

const HOW_MANY_PHILOSOPHERS: i32 = 7;

#[derive(Clone)]
struct Basics;
impl ::Basics for Basics {
  type Time = Time;
  type Constants = ();
}

#[derive(Clone)]
struct Philosopher {
  // This is sometimes in the future because
  // they muse philosophically about handshakes
  // for a while, whenever one of them happens.
  time_when_next_initiates_handshake: Time,
}
impl Column for Philosopher {
  type FieldType = Self;
  fn column_id() -> ColumnId {
    ColumnId(0x4084d1501468b6dd)
  }
}

type Steward = s::Steward<Basics>;

fn get_philosopher_id(index: i32) -> RowId {
  DeterministicRandomId::new(&(0x2302c38efb47e0d0u64, index))
}

pub fn testfunc() {

  let mut stew: Steward = ::TimeSteward::new_empty((),
                                                   vec![s::Predictor {
                                                          predictor_id: 0x0e7f27c7643f8167,
                                                          column_id: Philosopher::column_id(),
                                                          function: Rc::new(|pa, whodunnit| {
      printlnerr!("Planning {}", whodunnit);
      let me = pa.get::<Philosopher>(whodunnit).unwrap().clone();
      pa.predict_at_time(&me.time_when_next_initiates_handshake,
                         Rc::new(move |m| {
        let now = *m.now();
        let friend_id = get_philosopher_id(m.rng().gen_range(0, HOW_MANY_PHILOSOPHERS));
        let awaken_time_1 = now + m.rng().gen_range(-1, 4);
        let awaken_time_2 = now + m.rng().gen_range(-1, 7);
        printlnerr!("SHAKE!!! @{}. {}={}; {}={}", now, whodunnit, awaken_time_2, friend_id, awaken_time_1);
        // IF YOU SHAKE YOUR OWN HAND YOU RECOVER
        // IN THE SECOND TIME APPARENTLY
        m.set::<Philosopher>(friend_id,
                             Some(Philosopher {
                               time_when_next_initiates_handshake: awaken_time_1,
                             }));
        m.set::<Philosopher>(whodunnit,
                             Some(Philosopher {
                               time_when_next_initiates_handshake: awaken_time_2,
                             }));
      }));
    }),
                                                        }]);

  stew.insert_fiat_event(0,
                         DeterministicRandomId::new(&0x32e1570766e768a7u64),
                         Rc::new(|m| {
    printlnerr!("FIAT!!!!!");
    for i in 0..HOW_MANY_PHILOSOPHERS {
      m.set::<Philosopher>(get_philosopher_id(i),
                           Some(Philosopher {
                             time_when_next_initiates_handshake: (i + 1) as Time,
                           }));
    }
  }));

  stew.snapshot_before(&50000);

  // panic!("anyway")
}

#[test]
fn actuallytest() {
  testfunc();
}
<|endoftext|>


<commit_before>//! Implementations of the default callbacks exposed by wlc.
//! These functions are the main entry points into Way Cooler from user action.
//! This is the default mode that Way Cooler is in at initilization
use std::process::{Command};
use std::path::PathBuf;
use std::io;
use rustwlc::*;
use rustwlc::wayland::wlc_view_get_wl_client;
use rustwlc::input::pointer;
use uuid::Uuid;
use wayland_sys::server::wl_client;

use super::{Mode, Modes, Default, write_current_mode};
use super::{EVENT_BLOCKED, EVENT_PASS_THROUGH};
use ::render::screen_scrape::{read_screen_scrape_lock, scraped_pixels_lock,
                              sync_scrape};
use ::layout::try_lock_tree;
use ::registry;

use rustwlc::{ResizeEdge, WlcView, Geometry, Point};
use rustwlc::types::VIEW_ACTIVATED;
use nix::libc::pid_t;

/// A lock screen program, that has been spawned by Way Cooler.
///
/// The PID is what is returned from spawning the subprocess.
///
/// The view is optional, because after spawning it we must find it in the
/// `view_created` callback.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct LockScreen {
    /// Lists of clients that want to lock the screen.
    ///
    /// Multiple clients can attempt to lock a screen.
    /// The normal mode of operation is that they are the same client,
    /// but with different connections.
    ///
    ///The usize is the client id, and the view is the view it's associated with
    /// (if it has been spawned yet)
    ///
    /// The WlcOutput is the output the view should be associated with.
    pub clients: Vec<(usize, WlcOutput, Option<WlcView>)>,
    /// Flag that is set when a view is destroyed, either because the user
    /// closed it OR if the program failed to spawn.
    removed: bool
}

impl LockScreen {
    /// Creates a new Lock Screen from the PID
    ///
    /// The view is set to `None`, because we haven't found it yet in the
    /// `view_created` callback. This should be updated once it is found,
    /// so that we can start locking the screen.
    pub fn new(client: *mut wl_client, output: WlcOutput) -> Self {
        LockScreen {
            clients: vec![(client as _, output, None)],
            removed: false
        }
    }

    /// Adds the view to the `LockScreen` if it's PID matches the stored one.
    ///
    /// If there is already here, false is always returned.
    ///
    /// If the view's PID matches this PID, then it's automatically focused,
    /// and the geometry of it is set to the size of it's `WlcOutput`'s size.
    fn add_view_if_match(&mut self, view: WlcView) -> bool {
        let cur_client = unsafe {
            wlc_view_get_wl_client(view.0 as _) as _
        };
        warn!("Checkng view {:#?}", view);
        for client in &mut self.clients {
            if client.0 == cur_client && client.2 == None {
                error!("Found a match, setting to output {:#?}", client.1);
                view.set_output(client.1);
                client.2 = Some(view);
                let output = view.get_output();
                let resolution = output.get_resolution()
                    .expect("Output was invalid: had no resolution");
                let geo = Geometry {
                    origin: Point { x: 0, y: 0 },
                    size: resolution
                };
                view.set_geometry(ResizeEdge::empty(), geo);
                view.set_state(VIEW_ACTIVATED, true);
                view.focus();
                view.set_mask(1);
                view.bring_to_front();
                return true
            }
        }
        false
    }

    /// Removes the lockscreen if provided view matches the stored view.
    ///
    /// Does not compare the PID, because the passed in `WlcView` should be
    /// considered invalidated because this function is probably being called
    /// from `view_destroyed`.
    ///
    /// To protect against failing programs, the child handler should be
    /// checked to see if the program is still running.
    /// HOWEVER, this is blocked because this is still a nightly feature.
    /// See https://github.com/rust-lang/rust/issues/38903
    fn remove_if_match(&mut self, cur_view: WlcView) -> Option<WlcView> {
        for &mut (_, _, ref mut view) in &mut self.clients {
            if *view == Some(cur_view) {
                self.removed = true;
                // invalidate this view so we can't do anything to it.
                return view.take()
            }
        }
        None
    }

    fn eval_if_lockscreen<F, T>(&mut self, cur_view: WlcView, eval: F) -> T
        where F: Fn(WlcView) -> T,
              T: ::std::default::Default
    {
        for &(_, _, ref view) in &self.clients {
            if *view == Some(cur_view) {
                return eval(view.unwrap())
            }
        }
        T::default()
    }
}

#[allow(unused)]
impl Mode for LockScreen {
    fn output_render_post(&mut self, output: WlcOutput) {
        Default.output_render_post(output);
        // TODO Uncomment
        // we should allow this some other way
        /*// Don't allow screen scraping during lock screen
        let need_to_fetch = read_screen_scrape_lock();
        if *need_to_fetch {
            if let Ok(mut scraped_pixels) = scraped_pixels_lock() {
                let resolution = output.get_resolution()
                    .expect("Output had no resolution");
                // Give them zero-ed out pixels
                *scraped_pixels = vec![0; resolution.w as usize * resolution.h as usize * 4];
                sync_scrape();
            }
        }*/
    }

    fn view_created(&mut self, view: WlcView) -> bool {
        // this will focus and set the size if necessary.
        if self.add_view_if_match(view) {
            trace!("Adding lockscreen");
            true
        } else {
            false
        }
    }

    fn view_destroyed(&mut self, view: WlcView) {
        // Always remove the destroyed view from the tree.
        Default.view_destroyed(view);
        // View is automatically removed from the internal lock screen struct.
        if self.remove_if_match(view).is_some() {
            trace!("Removing lock screen");
            // Update the active container in the tree to the active path end.
            if let Ok(mut tree) = try_lock_tree() {
                tree.reset_focus()
                    .unwrap_or_else(|_| {
                        warn!("Could not reset focus\
                              after removing lock screen");
                    })
            }
            unlock_screen(self.clients[0].0 as _)
        }
    }

    fn view_focused(&mut self, current: WlcView, focused: bool) {
        // Do nothing
    }

    fn view_request_state(&mut self, view: WlcView, state: ViewState, toggle: bool) {
        // Do nothing
    }

    fn view_request_move(&mut self, view: WlcView, _dest: Point) {
        // Do nothing
    }

    fn view_request_resize(&mut self, view: WlcView, edge: ResizeEdge, point: Point) {
        // Do nothing
    }

    fn on_keyboard_key(&mut self, view: WlcView, _time: u32, mods: KeyboardModifiers,
                            key: u32, state: KeyState) -> bool {
        !self.eval_if_lockscreen(view, |view| {
            view.focus();
            true
        })
    }

    fn on_pointer_button(&mut self, view: WlcView, _time: u32,
                            mods: KeyboardModifiers, button: u32,
                                state: ButtonState, point: Point) -> bool {
        self.eval_if_lockscreen(view, |view| {
            view.focus();
            true
        })
    }

    fn on_pointer_scroll(&mut self, view: WlcView, _time: u32,
                            _mods_ptr: KeyboardModifiers, _axis: ScrollAxis,
                            _heights: [f64; 2]) -> bool {
        self.eval_if_lockscreen(view, |view| {
            view.focus();
            true
        })
    }

    fn on_pointer_motion(&mut self, view: WlcView, _time: u32, point: Point) -> bool {
        !self.eval_if_lockscreen(view, |view| {
            view.focus();
            pointer::set_position(point);
            // false because default is false, but true is the base case here
            false
        })
    }
}

#[derive(Debug)]
pub enum LockScreenErr {
    /// IO error while trying to lock screen.
    /// e.g: Couldn't open lock screen program.
    IO(io::Error),
    /// Lock screen was already locked.
    AlreadyLocked
}

/*
/// Locks the screen, with the stored path from the registry.
///
/// If it fails to lock the screen, then a warning is raised in
/// the log and it other wise continues.
///
/// If you want to handle the error yourself, please use
/// `lock_screen_with_path`.
pub fn spawn_lock_screen() {
    let lock = registry::clients_read();
    let client = lock.client(Uuid::nil()).unwrap();
    let handle = registry::ReadHandle::new(&client);
    let path = handle.read("programs".into()).ok()
        .and_then(|programs| programs.get("lock_screen"))
        .and_then(|lock_screen| lock_screen.as_string());
    match path {
        None => warn!("No lock screen program set!"),
        Some(path) => {
            let path = path.into();
            lock_screen_with_path(path).unwrap_or_else(|err| {
                warn!("Could not lock screen: {:?}", err)
            })
        }
    }
}
*/

/*
/// Locks the screen by spawning the program at the given path.
///
/// This modifies the global `LOCK_SCREEN` singleton,
/// so that it can be used by wlc callbacks.
///
/// If the program could not be spawned, an `Err` is returned.
pub fn lock_screen_with_path(path: PathBuf) -> Result<(), LockScreenErr> {
    let mut mode = write_current_mode();
    match *mode {
        Modes::LockScreen(_) =>
            return Err(LockScreenErr::AlreadyLocked),
        _ => {}
    };
    // TODO This can fail badly, and we should use child_try_wait.
    // It's possible the program can fail to spawn a window, which
    // means we'll be waiting forever.
    // HOWEVER that's behind a nightly flag, so we must wait.
    let child = Command::new(path).spawn()
        .map_err(|io_er| LockScreenErr::IO(io_er))?;
    let id = child.id();
    *mode = Modes::LockScreen(LockScreen::new(id as pid_t));
    Ok(())
}
*/

pub fn lock_screen(client: *mut wl_client, output: WlcOutput) -> Result<(), LockScreenErr> {
    let mut mode = write_current_mode();
    warn!("Locking screen w/ mode {:#?}", mode);
    {
        match *mode {
            Modes::LockScreen(ref mut lock_mode) => {
                warn!("Found another view");
                lock_mode.clients.push((client as _, output, None));
                return Ok(())
            },
            _ => {}
        }
    }
    *mode = Modes::LockScreen(LockScreen::new(client, output));
    Ok(())
}

pub fn unlock_screen(client: *mut wl_client) {
    error!("Unlocking screen");
    let mut mode = write_current_mode();
    match *mode {
        Modes::LockScreen(ref lock_mode) => {
            for &(_, _, view) in &lock_mode.clients {
                view.map(WlcView::close);
            }
        },
        _ => {}
    }
    *mode = Modes::Default(Default);
}
<commit_msg>Delete old code<commit_after>//! Implementations of the default callbacks exposed by wlc.
//! These functions are the main entry points into Way Cooler from user action.
//! This is the default mode that Way Cooler is in at initilization
use std::process::{Command};
use std::path::PathBuf;
use std::io;
use rustwlc::*;
use rustwlc::wayland::wlc_view_get_wl_client;
use rustwlc::input::pointer;
use uuid::Uuid;
use wayland_sys::server::wl_client;

use super::{Mode, Modes, Default, write_current_mode};
use super::{EVENT_BLOCKED, EVENT_PASS_THROUGH};
use ::render::screen_scrape::{read_screen_scrape_lock, scraped_pixels_lock,
                              sync_scrape};
use ::layout::try_lock_tree;
use ::registry;

use rustwlc::{ResizeEdge, WlcView, Geometry, Point};
use rustwlc::types::VIEW_ACTIVATED;
use nix::libc::pid_t;

/// A lock screen program, that has been spawned by Way Cooler.
///
/// The PID is what is returned from spawning the subprocess.
///
/// The view is optional, because after spawning it we must find it in the
/// `view_created` callback.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct LockScreen {
    /// Lists of clients that want to lock the screen.
    ///
    /// Multiple clients can attempt to lock a screen.
    /// The normal mode of operation is that they are the same client,
    /// but with different connections.
    ///
    ///The usize is the client id, and the view is the view it's associated with
    /// (if it has been spawned yet)
    ///
    /// The WlcOutput is the output the view should be associated with.
    pub clients: Vec<(usize, WlcOutput, Option<WlcView>)>,
    /// Flag that is set when a view is destroyed, either because the user
    /// closed it OR if the program failed to spawn.
    removed: bool
}

impl LockScreen {
    /// Creates a new Lock Screen from the PID
    ///
    /// The view is set to `None`, because we haven't found it yet in the
    /// `view_created` callback. This should be updated once it is found,
    /// so that we can start locking the screen.
    pub fn new(client: *mut wl_client, output: WlcOutput) -> Self {
        LockScreen {
            clients: vec![(client as _, output, None)],
            removed: false
        }
    }

    /// Adds the view to the `LockScreen` if it's PID matches the stored one.
    ///
    /// If there is already here, false is always returned.
    ///
    /// If the view's PID matches this PID, then it's automatically focused,
    /// and the geometry of it is set to the size of it's `WlcOutput`'s size.
    fn add_view_if_match(&mut self, view: WlcView) -> bool {
        let cur_client = unsafe {
            wlc_view_get_wl_client(view.0 as _) as _
        };
        warn!("Checkng view {:#?}", view);
        for client in &mut self.clients {
            if client.0 == cur_client && client.2 == None {
                error!("Found a match, setting to output {:#?}", client.1);
                view.set_output(client.1);
                client.2 = Some(view);
                let output = view.get_output();
                let resolution = output.get_resolution()
                    .expect("Output was invalid: had no resolution");
                let geo = Geometry {
                    origin: Point { x: 0, y: 0 },
                    size: resolution
                };
                view.set_geometry(ResizeEdge::empty(), geo);
                view.set_state(VIEW_ACTIVATED, true);
                view.focus();
                view.set_mask(1);
                view.bring_to_front();
                return true
            }
        }
        false
    }

    /// Removes the lockscreen if provided view matches the stored view.
    ///
    /// Does not compare the PID, because the passed in `WlcView` should be
    /// considered invalidated because this function is probably being called
    /// from `view_destroyed`.
    ///
    /// To protect against failing programs, the child handler should be
    /// checked to see if the program is still running.
    /// HOWEVER, this is blocked because this is still a nightly feature.
    /// See https://github.com/rust-lang/rust/issues/38903
    fn remove_if_match(&mut self, cur_view: WlcView) -> Option<WlcView> {
        for &mut (_, _, ref mut view) in &mut self.clients {
            if *view == Some(cur_view) {
                self.removed = true;
                // invalidate this view so we can't do anything to it.
                return view.take()
            }
        }
        None
    }

    fn eval_if_lockscreen<F, T>(&mut self, cur_view: WlcView, eval: F) -> T
        where F: Fn(WlcView) -> T,
              T: ::std::default::Default
    {
        for &(_, _, ref view) in &self.clients {
            if *view == Some(cur_view) {
                return eval(view.unwrap())
            }
        }
        T::default()
    }
}

#[allow(unused)]
impl Mode for LockScreen {
    fn output_render_post(&mut self, output: WlcOutput) {
        Default.output_render_post(output);
        // TODO Uncomment
        // we should allow this some other way
        /*// Don't allow screen scraping during lock screen
        let need_to_fetch = read_screen_scrape_lock();
        if *need_to_fetch {
            if let Ok(mut scraped_pixels) = scraped_pixels_lock() {
                let resolution = output.get_resolution()
                    .expect("Output had no resolution");
                // Give them zero-ed out pixels
                *scraped_pixels = vec![0; resolution.w as usize * resolution.h as usize * 4];
                sync_scrape();
            }
        }*/
    }

    fn view_created(&mut self, view: WlcView) -> bool {
        // this will focus and set the size if necessary.
        if self.add_view_if_match(view) {
            trace!("Adding lockscreen");
            true
        } else {
            false
        }
    }

    fn view_destroyed(&mut self, view: WlcView) {
        // Always remove the destroyed view from the tree.
        Default.view_destroyed(view);
        // View is automatically removed from the internal lock screen struct.
        if self.remove_if_match(view).is_some() {
            trace!("Removing lock screen");
            // Update the active container in the tree to the active path end.
            if let Ok(mut tree) = try_lock_tree() {
                tree.reset_focus()
                    .unwrap_or_else(|_| {
                        warn!("Could not reset focus\
                              after removing lock screen");
                    })
            }
            unlock_screen(self.clients[0].0 as _)
        }
    }

    fn view_focused(&mut self, current: WlcView, focused: bool) {
        // Do nothing
    }

    fn view_request_state(&mut self, view: WlcView, state: ViewState, toggle: bool) {
        // Do nothing
    }

    fn view_request_move(&mut self, view: WlcView, _dest: Point) {
        // Do nothing
    }

    fn view_request_resize(&mut self, view: WlcView, edge: ResizeEdge, point: Point) {
        // Do nothing
    }

    fn on_keyboard_key(&mut self, view: WlcView, _time: u32, mods: KeyboardModifiers,
                            key: u32, state: KeyState) -> bool {
        !self.eval_if_lockscreen(view, |view| {
            view.focus();
            true
        })
    }

    fn on_pointer_button(&mut self, view: WlcView, _time: u32,
                            mods: KeyboardModifiers, button: u32,
                                state: ButtonState, point: Point) -> bool {
        self.eval_if_lockscreen(view, |view| {
            view.focus();
            true
        })
    }

    fn on_pointer_scroll(&mut self, view: WlcView, _time: u32,
                            _mods_ptr: KeyboardModifiers, _axis: ScrollAxis,
                            _heights: [f64; 2]) -> bool {
        self.eval_if_lockscreen(view, |view| {
            view.focus();
            true
        })
    }

    fn on_pointer_motion(&mut self, view: WlcView, _time: u32, point: Point) -> bool {
        !self.eval_if_lockscreen(view, |view| {
            view.focus();
            pointer::set_position(point);
            // false because default is false, but true is the base case here
            false
        })
    }
}

#[derive(Debug)]
pub enum LockScreenErr {
    /// IO error while trying to lock screen.
    /// e.g: Couldn't open lock screen program.
    IO(io::Error),
    /// Lock screen was already locked.
    AlreadyLocked
}

pub fn lock_screen(client: *mut wl_client, output: WlcOutput) -> Result<(), LockScreenErr> {
    let mut mode = write_current_mode();
    warn!("Locking screen w/ mode {:#?}", mode);
    {
        match *mode {
            Modes::LockScreen(ref mut lock_mode) => {
                warn!("Found another view");
                lock_mode.clients.push((client as _, output, None));
                return Ok(())
            },
            _ => {}
        }
    }
    *mode = Modes::LockScreen(LockScreen::new(client, output));
    Ok(())
}

pub fn unlock_screen(client: *mut wl_client) {
    error!("Unlocking screen");
    let mut mode = write_current_mode();
    match *mode {
        Modes::LockScreen(ref lock_mode) => {
            for &(_, _, view) in &lock_mode.clients {
                view.map(WlcView::close);
            }
        },
        _ => {}
    }
    *mode = Modes::Default(Default);
}
<|endoftext|>


<commit_before>use world::WorldView;
use glium::Surface;
use super::{Camera, GameContext};
use std::rc::Rc;

use glium::texture::texture2d::Texture2d;
use glium::texture::{UncompressedFloatFormat, MipmapsOption, DepthFormat, DepthTexture2d};
use glium::framebuffer::MultiOutputFrameBuffer;
use glium::VertexBuffer;
use glium::{IndexBuffer, Program};
use glium::index::PrimitiveType;
use glium::backend::Facade;

pub struct Renderer {
    context: Rc<GameContext>,
    quad_tex: Texture2d,
    depth_texture: DepthTexture2d,
    tonemapping_program: Program,
    quad_vertex_buffer: VertexBuffer<Vertex>,
    quad_index_buffer: IndexBuffer<u16>,
}

impl Renderer {
    pub fn new(context: Rc<GameContext>) -> Self {
        let resolution = context.get_facade().get_framebuffer_dimensions();
        let quad_tex_temp = Texture2d::empty_with_format(context.get_facade(),
                                                         UncompressedFloatFormat::F32F32F32F32,
                                                         MipmapsOption::NoMipmap,
                                                         resolution.0,
                                                         resolution.1)
            .unwrap();

        let depth_texture = DepthTexture2d::empty_with_format(context.get_facade(),
                                                              DepthFormat::F32,
                                                              MipmapsOption::NoMipmap,
                                                              resolution.0,
                                                              resolution.1)
            .unwrap();

        let ibuf = IndexBuffer::new(context.get_facade(),
                                    PrimitiveType::TrianglesList,
                                    &[0u16, 1, 2, 0, 2, 3])
            .unwrap();

        let tonemapping_program = Program::from_source(context.get_facade(),
                                                       include_str!("tonemapping.vert"),
                                                       include_str!("tonemapping.frag"),
                                                       None)
            .unwrap();

        Renderer {
            context: context.clone(),
            quad_tex: quad_tex_temp,
            tonemapping_program: tonemapping_program,
            depth_texture: depth_texture,
            quad_vertex_buffer: Renderer::create_vertex_buf(context.get_facade()),
            quad_index_buffer: ibuf,
        }
    }

    /// Is called once every main loop iteration
    pub fn render(&self, world_view: &WorldView, camera: &Camera) -> Result<(), ()> {
        // ===================================================================
        // Rendering into HDR framebuffer
        // ===================================================================
        let output = &[("color", &self.quad_tex)];
        let mut hdr_buffer = MultiOutputFrameBuffer::with_depth_buffer(self.context.get_facade(),
                                                                       output.iter().cloned(),
                                                                       &self.depth_texture)
            .unwrap();
        hdr_buffer.clear_color_and_depth((0.0, 0.0, 1.0, 1.0), 1.0);

        world_view.draw(&mut hdr_buffer, camera);

        // ===================================================================
        // Tonemapping
        // ===================================================================
        let mut target = self.context.get_facade().draw();
        target.clear_color_and_depth((0.0, 0.0, 1.0, 1.0), 1.0);

        let uniforms = uniform! {
            decal_texture: &self.quad_tex,
        };

        target.draw(&self.quad_vertex_buffer,
                  &self.quad_index_buffer,
                  &self.tonemapping_program,
                  &uniforms,
                  &Default::default())
            .unwrap();

        target.finish().unwrap();

        Ok(())
    }

    fn create_vertex_buf<F: Facade>(facade: &F) -> VertexBuffer<Vertex> {

        VertexBuffer::new(facade,
                          &[Vertex {
                                position: [-1.0, -1.0, 0.0, 1.0],
                                texcoord: [0.0, 0.0],
                            },
                            Vertex {
                                position: [1.0, -1.0, 0.0, 1.0],
                                texcoord: [1.0, 0.0],
                            },
                            Vertex {
                                position: [1.0, 1.0, 0.0, 1.0],
                                texcoord: [1.0, 1.0],
                            },
                            Vertex {
                                position: [-1.0, 1.0, 0.0, 1.0],
                                texcoord: [0.0, 1.0],
                            }])
            .unwrap()
    }
}

#[derive(Copy, Clone)]
struct Vertex {
    position: [f32; 4],
    texcoord: [f32; 2],
}

implement_vertex!(Vertex, position, texcoord);
<commit_msg>fixed format<commit_after>use world::WorldView;
use glium::Surface;
use super::{Camera, GameContext};
use std::rc::Rc;

use glium::texture::texture2d::Texture2d;
use glium::texture::{DepthFormat, DepthTexture2d, MipmapsOption, UncompressedFloatFormat};
use glium::framebuffer::MultiOutputFrameBuffer;
use glium::VertexBuffer;
use glium::{IndexBuffer, Program};
use glium::index::PrimitiveType;
use glium::backend::Facade;

pub struct Renderer {
    context: Rc<GameContext>,
    quad_tex: Texture2d,
    depth_texture: DepthTexture2d,
    tonemapping_program: Program,
    quad_vertex_buffer: VertexBuffer<Vertex>,
    quad_index_buffer: IndexBuffer<u16>,
}

impl Renderer {
    pub fn new(context: Rc<GameContext>) -> Self {
        let resolution = context.get_facade().get_framebuffer_dimensions();
        let quad_tex_temp = Texture2d::empty_with_format(context.get_facade(),
                                                         UncompressedFloatFormat::F32F32F32F32,
                                                         MipmapsOption::NoMipmap,
                                                         resolution.0,
                                                         resolution.1)
            .unwrap();

        let depth_texture = DepthTexture2d::empty_with_format(context.get_facade(),
                                                              DepthFormat::F32,
                                                              MipmapsOption::NoMipmap,
                                                              resolution.0,
                                                              resolution.1)
            .unwrap();

        let ibuf = IndexBuffer::new(context.get_facade(),
                                    PrimitiveType::TrianglesList,
                                    &[0u16, 1, 2, 0, 2, 3])
            .unwrap();

        let tonemapping_program = Program::from_source(context.get_facade(),
                                                       include_str!("tonemapping.vert"),
                                                       include_str!("tonemapping.frag"),
                                                       None)
            .unwrap();

        Renderer {
            context: context.clone(),
            quad_tex: quad_tex_temp,
            tonemapping_program: tonemapping_program,
            depth_texture: depth_texture,
            quad_vertex_buffer: Renderer::create_vertex_buf(context.get_facade()),
            quad_index_buffer: ibuf,
        }
    }

    /// Is called once every main loop iteration
    pub fn render(&self, world_view: &WorldView, camera: &Camera) -> Result<(), ()> {
        // ===================================================================
        // Rendering into HDR framebuffer
        // ===================================================================
        let output = &[("color", &self.quad_tex)];
        let mut hdr_buffer = MultiOutputFrameBuffer::with_depth_buffer(self.context.get_facade(),
                                                                       output.iter().cloned(),
                                                                       &self.depth_texture)
            .unwrap();
        hdr_buffer.clear_color_and_depth((0.0, 0.0, 1.0, 1.0), 1.0);

        world_view.draw(&mut hdr_buffer, camera);

        // ===================================================================
        // Tonemapping
        // ===================================================================
        let mut target = self.context.get_facade().draw();
        target.clear_color_and_depth((0.0, 0.0, 1.0, 1.0), 1.0);

        let uniforms = uniform! {
            decal_texture: &self.quad_tex,
        };

        target.draw(&self.quad_vertex_buffer,
                  &self.quad_index_buffer,
                  &self.tonemapping_program,
                  &uniforms,
                  &Default::default())
            .unwrap();

        target.finish().unwrap();

        Ok(())
    }

    fn create_vertex_buf<F: Facade>(facade: &F) -> VertexBuffer<Vertex> {

        VertexBuffer::new(facade,
                          &[Vertex {
                                position: [-1.0, -1.0, 0.0, 1.0],
                                texcoord: [0.0, 0.0],
                            },
                            Vertex {
                                position: [1.0, -1.0, 0.0, 1.0],
                                texcoord: [1.0, 0.0],
                            },
                            Vertex {
                                position: [1.0, 1.0, 0.0, 1.0],
                                texcoord: [1.0, 1.0],
                            },
                            Vertex {
                                position: [-1.0, 1.0, 0.0, 1.0],
                                texcoord: [0.0, 1.0],
                            }])
            .unwrap()
    }
}

#[derive(Copy, Clone)]
struct Vertex {
    position: [f32; 4],
    texcoord: [f32; 2],
}

implement_vertex!(Vertex, position, texcoord);
<|endoftext|>


<commit_before>use addressable::Addressable;
use addressable::AddressableUtil;
use ram::Ram;

enum Operand {
	Implied,							// OPC				// operand implied
	Immediate(u8),						// OPC #$BB			// operand is byte (BB)
	Accumulator,						// OPC A			// operand is AC
	Relative(i8),						// OPC $BB			// branch target is PC + offset (BB), bit 7 signifies negative offset
	Absolute(u16),						// OPC $HHLL		// operand is address $HHLL
	AbsoluteIndexedWithX(u16),			// OPC $HHLL,X		// operand is address $HHLL incremented by X with carry
	AbsoluteIndexedWithY(u16),			// OPC $HHLL,Y		// operand is address $HHLL incremented by Y with carry
	Indirect(u16),						// OPC ($HHLL)		// operand is effective address; effective address is value of address
	ZeroPage(u8),						// OPC $LL			// operand is address $00LL
	ZeroPageIndexedWithX(u8),			// OPC $LL,X		// operand is address $00LL incremented by X, no page transition
	ZeroPageIndexedWithY(u8),			// OPC $LL,Y		// operand is address $00LL incremented by Y, no page transition
	ZeroPageIndexedWithXIndirect(u8),	// OPC ($LL,X)		// operand is effective address; effective address is $00LL incremented by X without carry
	ZeroPageIndirectIndexedWithY(u8),	// OPC ($LL),Y		// operand is effective address incremented by Y with carry; effective address is word at $00LL
}

impl Operand {
	fn addr (&self, cpu: &CPU) -> u16 {
		match * self {
			Implied								=> fail!("mos6510: Implied operand is never targetted to an address"),
			Immediate(_)						=> fail!("mos6510: Immediade operand is never targetted to an address"),
			Accumulator							=> fail!("mos6510: Accumulator operand is never targetted to an address"),
			Relative(offset)					=> cpu.pc + offset as u16,
			Absolute(addr)						=> addr,
			AbsoluteIndexedWithX(addr)			=> addr + cpu.x as u16,
			AbsoluteIndexedWithY(addr)			=> addr + cpu.y as u16,
			Indirect(addr)						=> cpu.get_le(addr),
			ZeroPage(addr)						=> addr as u16,
			ZeroPageIndexedWithX(addr)			=> (addr + cpu.x) as u16,				// no page transition
			ZeroPageIndexedWithY(addr)			=> (addr + cpu.y) as u16,				// no page transition
			ZeroPageIndexedWithXIndirect(addr)	=> cpu.get_le((addr + cpu.x) as u16),	// no page transition
			ZeroPageIndirectIndexedWithY(addr)	=> { let iaddr: u16 = cpu.get_le(addr as u16); iaddr + cpu.y as u16 },
		}
	}

	fn get (&self, cpu: &CPU) -> u8 {
		match *self {
			Implied								=> fail!("mos6510: Implied operand never has a value"),
			Immediate(val)						=> val,
			Accumulator							=> cpu.ac,
			Relative(_target)					=> fail!("mos6510: Relative operand never has a value"),
			op									=> { let addr = op.addr(cpu); cpu.get(addr) },
		}
	}

	fn set (&self, val: u8, cpu: &mut CPU) {
		match *self {
			Implied								=> fail!("mos6510: Implied operand never sets a value"),
			Immediate(_)						=> fail!("mos6510: Immediate operand never sets a value"),
			Accumulator							=> cpu.ac = val,
			Relative(_target)					=> fail!("mos6510: Relative operand never sets a value"),
			op									=> { let addr = op.addr(cpu); cpu.set(addr, val); },
		}
	}
}

static nmi_vector: u16 = 0xfffa;
static reset_vector: u16 = 0xfffc;
static irq_vector: u16 = 0xfffe;

pub struct CPU {
	pc: u16,				// program counter
	ac: u8,					// accumulator
	x: u8,					// x register
	y: u8,					// y register
	sr: u8,					// status register (NV-BDIZC: Negative, oVerflow, Break, Decimal, Interrupt, Zero, Carry)
	sp: u8,					// stack pointer
	mem: Ram<u16>,
}

impl Addressable<u16> for CPU {
	pub fn get (&self, addr: u16) -> u8 {
		// TODO: addresses $0000 (data direction) and $0001 (data) are hardwired for the processor I/O port
		self.mem.get(addr)
	}

	pub fn set (&mut self, addr: u16, data: u8) {
		// TODO: addresses $0000 (data direction) and $0001 (data) are hardwired for the processor I/O port
		self.mem.set(addr, data);
	}
}
<commit_msg>Added CPU constructor<commit_after>use addressable::Addressable;
use addressable::AddressableUtil;
use ram::Ram;

enum Operand {
	Implied,							// OPC				// operand implied
	Immediate(u8),						// OPC #$BB			// operand is byte (BB)
	Accumulator,						// OPC A			// operand is AC
	Relative(i8),						// OPC $BB			// branch target is PC + offset (BB), bit 7 signifies negative offset
	Absolute(u16),						// OPC $HHLL		// operand is address $HHLL
	AbsoluteIndexedWithX(u16),			// OPC $HHLL,X		// operand is address $HHLL incremented by X with carry
	AbsoluteIndexedWithY(u16),			// OPC $HHLL,Y		// operand is address $HHLL incremented by Y with carry
	Indirect(u16),						// OPC ($HHLL)		// operand is effective address; effective address is value of address
	ZeroPage(u8),						// OPC $LL			// operand is address $00LL
	ZeroPageIndexedWithX(u8),			// OPC $LL,X		// operand is address $00LL incremented by X, no page transition
	ZeroPageIndexedWithY(u8),			// OPC $LL,Y		// operand is address $00LL incremented by Y, no page transition
	ZeroPageIndexedWithXIndirect(u8),	// OPC ($LL,X)		// operand is effective address; effective address is $00LL incremented by X without carry
	ZeroPageIndirectIndexedWithY(u8),	// OPC ($LL),Y		// operand is effective address incremented by Y with carry; effective address is word at $00LL
}

impl Operand {
	fn addr (&self, cpu: &CPU) -> u16 {
		match * self {
			Implied								=> fail!("mos6510: Implied operand is never targetted to an address"),
			Immediate(_)						=> fail!("mos6510: Immediade operand is never targetted to an address"),
			Accumulator							=> fail!("mos6510: Accumulator operand is never targetted to an address"),
			Relative(offset)					=> cpu.pc + offset as u16,
			Absolute(addr)						=> addr,
			AbsoluteIndexedWithX(addr)			=> addr + cpu.x as u16,
			AbsoluteIndexedWithY(addr)			=> addr + cpu.y as u16,
			Indirect(addr)						=> cpu.get_le(addr),
			ZeroPage(addr)						=> addr as u16,
			ZeroPageIndexedWithX(addr)			=> (addr + cpu.x) as u16,				// no page transition
			ZeroPageIndexedWithY(addr)			=> (addr + cpu.y) as u16,				// no page transition
			ZeroPageIndexedWithXIndirect(addr)	=> cpu.get_le((addr + cpu.x) as u16),	// no page transition
			ZeroPageIndirectIndexedWithY(addr)	=> { let iaddr: u16 = cpu.get_le(addr as u16); iaddr + cpu.y as u16 },
		}
	}

	fn get (&self, cpu: &CPU) -> u8 {
		match *self {
			Implied								=> fail!("mos6510: Implied operand never has a value"),
			Immediate(val)						=> val,
			Accumulator							=> cpu.ac,
			Relative(_target)					=> fail!("mos6510: Relative operand never has a value"),
			op									=> { let addr = op.addr(cpu); cpu.get(addr) },
		}
	}

	fn set (&self, val: u8, cpu: &mut CPU) {
		match *self {
			Implied								=> fail!("mos6510: Implied operand never sets a value"),
			Immediate(_)						=> fail!("mos6510: Immediate operand never sets a value"),
			Accumulator							=> cpu.ac = val,
			Relative(_target)					=> fail!("mos6510: Relative operand never sets a value"),
			op									=> { let addr = op.addr(cpu); cpu.set(addr, val); },
		}
	}
}

static nmi_vector: u16 = 0xfffa;
static reset_vector: u16 = 0xfffc;
static irq_vector: u16 = 0xfffe;

pub struct CPU {
	pc: u16,				// program counter
	ac: u8,					// accumulator
	x: u8,					// x register
	y: u8,					// y register
	sr: u8,					// status register (NV-BDIZC: Negative, oVerflow, Break, Decimal, Interrupt, Zero, Carry)
	sp: u8,					// stack pointer
	mem: Ram<u16>,
}

impl Addressable<u16> for CPU {
	pub fn get (&self, addr: u16) -> u8 {
		// TODO: addresses $0000 (data direction) and $0001 (data) are hardwired for the processor I/O port
		self.mem.get(addr)
	}

	pub fn set (&mut self, addr: u16, data: u8) {
		// TODO: addresses $0000 (data direction) and $0001 (data) are hardwired for the processor I/O port
		self.mem.set(addr, data);
	}
}

impl CPU {
	pub fn new () -> CPU {
		CPU { pc: 0, ac: 0, x: 0, y: 0, sr: 0, sp: 0, mem: Ram::new() }
	}
}
<|endoftext|>


<commit_before>use rand;
use rand::Rng;

use bot::{Bot, Node, RoomEvent};

const SIZE:usize = 6;

pub struct Roulette {
    rounds: [u8; SIZE],
    state: u8,
}

impl Roulette {
    pub fn new() -> Self {
        let mut x = Self {
            rounds: [0; SIZE],
            state: 0,
        };

        Self::reset(&mut x);

        return x;
    }

    fn fire(&mut self) -> bool {
        self.state = (self.state + 1) % (SIZE as u8);
        self.rounds[self.state as usize] == 1
    }

    fn reset(&mut self) {
        let mut rng = rand::thread_rng();
        /*
        for i in (0..SIZE) {
            self.rounds[i] = 0;
        }
        */
        self.rounds = [0; SIZE];
        self.state = (SIZE as u8) - 1;

        let i = rng.gen_range(0, SIZE);
        self.rounds[i] = 1;
    }
}

impl<'a> Node<'a> for Roulette {
    fn handle(&mut self, bot: &Bot, event: RoomEvent) {
        let revent = &event.raw_event;
        if revent.type_ == "m.room.message" &&
           revent.content["msgtype"] == "m.text" {

            let body = revent.content["body"].as_str().unwrap();

            if body.starts_with("roulette") {
                println!("Found roulette state: {}, rounds: {:?}", self.state, self.rounds);

                match self.fire() {
                    true => {
                        bot.kick(event.room_id, &revent.sender, Some("Bang!"));
                        bot.reply(&event, "bang!")
                    },
                    false => bot.reply(&event, "click"),
                };
            }
        }
    }
}
<commit_msg>Fix bug in roulette not resetting after bang<commit_after>use rand;
use rand::Rng;

use bot::{Bot, Node, RoomEvent};

const SIZE:usize = 6;

pub struct Roulette {
    rounds: [u8; SIZE],
    state: u8,
}

impl Roulette {
    pub fn new() -> Self {
        let mut x = Self {
            rounds: [0; SIZE],
            state: 0,
        };

        Self::reset(&mut x);

        return x;
    }

    fn fire(&mut self) -> bool {
        self.state = (self.state + 1) % (SIZE as u8);
        self.rounds[self.state as usize] == 1
    }

    fn reset(&mut self) {
        let mut rng = rand::thread_rng();

        self.rounds = [0; SIZE];
        self.state = (SIZE as u8) - 1;

        let i = rng.gen_range(0, SIZE);
        self.rounds[i] = 1;
    }
}

impl<'a> Node<'a> for Roulette {
    fn handle(&mut self, bot: &Bot, event: RoomEvent) {
        let revent = &event.raw_event;
        if revent.type_ == "m.room.message" &&
           revent.content["msgtype"] == "m.text" {

            let body = revent.content["body"].as_str().unwrap();

            if body.starts_with("roulette") {
                println!("Found roulette state: {}, rounds: {:?}", self.state, self.rounds);

                match self.fire() {
                    true => {
                        self.reset();
                        bot.kick(event.room_id, &revent.sender, Some("Bang!"));
                        bot.reply(&event, "bang!")
                    },
                    false => bot.reply(&event, "click"),
                };
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate core;

fn main()
{
  println!("Hello, CUI world!");
  core::test();
}
<commit_msg>Command line arguments<commit_after>extern crate core;

use std::os;

fn main()
{
  let args = os::args();

  println!("Hello, CUI world!");
  core::test();
}
<|endoftext|>