<commit_before>//! Handlers for the server.

use std::collections::BTreeMap;

use rustc_serialize::json::{Json, ToJson};
use serde_json;
use iron::prelude::*;
use iron::{status, headers, middleware};
use iron::modifiers::Header;
use router::Router;

use urlencoded;

use ::api;
use ::types::RedisPool;
use ::sensors;
use ::modifiers;

#[derive(Debug)]
struct ErrorResponse {
    reason: String,
}

impl ToJson for ErrorResponse {
    /// Serialize an ErrorResponse object into a proper JSON structure.
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("status".into(), "error".to_json());
        d.insert("reason".into(), self.reason.to_json());
        Json::Object(d)
    }
}

pub struct ReadHandler {
    status: api::Status,
    redis_pool: RedisPool,
    sensor_specs: sensors::SafeSensorSpecs,
    status_modifiers: Vec<Box<modifiers::StatusModifier>>,
}

impl ReadHandler {
    pub fn new(status: api::Status,
               redis_pool: RedisPool,
               sensor_specs: sensors::SafeSensorSpecs,
               status_modifiers: Vec<Box<modifiers::StatusModifier>>)
               -> ReadHandler {
        ReadHandler {
            status: status,
            redis_pool: redis_pool,
            sensor_specs: sensor_specs,
            status_modifiers: status_modifiers,
        }
    }

    fn build_response_json(&self) -> String {

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

        // Process registered sensors
        for sensor_spec in self.sensor_specs.iter() {

            match sensor_spec.get_sensor_value(self.redis_pool.clone()) {

                // Value could be read successfullly
                Ok(value) => {
                    if status_copy.sensors.is_none() {
                        status_copy.sensors = Some(api::Sensors {
                            people_now_present: vec![],
                            temperature: vec![],
                        });
                    }
                    sensor_spec.template.to_sensor(&value, &mut status_copy.sensors.as_mut().unwrap());
                },

                // Value could not be read, do error logging
                Err(err) => {
                    warn!("Could not retrieve key '{}' from Redis, omiting the sensor", &sensor_spec.data_key);
                    match err {
                        sensors::SensorError::Redis(e) => debug!("Error: {:?}", e),
                        sensors::SensorError::R2d2(e) => debug!("Error: {:?}", e),
                        sensors::SensorError::UnknownSensor(e) => warn!("Error: {:?}", e),
                    }
                },
            }
        }

        for status_modifier in self.status_modifiers.iter() {
            status_modifier.modify(&mut status_copy);
        }

        // Serialize to JSON
        serde_json::to_string(&status_copy)
            .expect("Status object could not be serialized to JSON. \
                     Please open an issue at https://github.com/spaceapi-community/spaceapi-server-rs/issues")
    }
}

impl middleware::Handler for ReadHandler {

    /// Return the current status JSON.
    fn handle(&self, req: &mut Request) -> IronResult<Response> {

        info!("{} /{} from {}", req.method, req.url.path()[0], req.remote_addr);

        // Get response body
        let body = self.build_response_json();

        // Create response
        let response = Response::with((status::Ok, body))
            // Set headers
            .set(Header(headers::ContentType("application/json; charset=utf-8".parse().unwrap())))
            .set(Header(headers::CacheControl(vec![headers::CacheDirective::NoCache])))
            .set(Header(headers::AccessControlAllowOrigin::Any));

        Ok(response)
    }

}

pub struct UpdateHandler {
    redis_pool: RedisPool,
    sensor_specs: sensors::SafeSensorSpecs,
}

impl UpdateHandler {
    pub fn new(redis_pool: RedisPool, sensor_specs: sensors::SafeSensorSpecs)
               -> UpdateHandler {
        UpdateHandler {
            redis_pool: redis_pool,
            sensor_specs: sensor_specs,
        }
    }

    /// Update sensor value in Redis
    fn update_sensor(&self, sensor: &str, value: &str) -> Result<(), sensors::SensorError> {
        // Validate sensor
        let sensor_spec = try!(self.sensor_specs.iter()
                               .find(|&spec| spec.data_key == sensor)
                               .ok_or(sensors::SensorError::UnknownSensor(sensor.into())));

        // Store data
        sensor_spec.set_sensor_value(self.redis_pool.clone(), value)
    }

    /// Build an OK response with the `HTTP 204 No Content` status code.
    fn ok_response(&self) -> Response {
        Response::with((status::NoContent))
            // Set headers
            .set(Header(headers::ContentType("application/json; charset=utf-8".parse().unwrap())))
            .set(Header(headers::CacheControl(vec![headers::CacheDirective::NoCache])))
            .set(Header(headers::AccessControlAllowOrigin::Any))
    }

    /// Build an error response with the specified `error_code` and the specified `reason` text.
    fn err_response(&self, error_code: status::Status, reason: &str) -> Response {
        let error = ErrorResponse { reason: reason.into() };
        Response::with((error_code, error.to_json().to_string()))
            // Set headers
            .set(Header(headers::ContentType("application/json; charset=utf-8".parse().unwrap())))
            .set(Header(headers::CacheControl(vec![headers::CacheDirective::NoCache])))
            .set(Header(headers::AccessControlAllowOrigin::Any))
    }

}

impl middleware::Handler for UpdateHandler {

    /// Update the sensor, return correct status code.
    fn handle(&self, req: &mut Request) -> IronResult<Response> {

        // TODO: create macro for these info! invocations.
        info!("{} /{} from {}", req.method, req.url.path()[0], req.remote_addr);

        // Get sensor name
        let sensor_name;
        {
            // TODO: Properly propagate errors
            let params = req.extensions.get::<Router>().unwrap();
            sensor_name = params.find("sensor").unwrap().to_string();
        }

        // Get sensor value
        let sensor_value;
        {
            let params = req.get_ref::<urlencoded::UrlEncodedBody>().unwrap();
            sensor_value = match params.get("value") {
                Some(ref values) =>  match values.len() {
                    1 => values[0].to_string(),
                    _ => return Ok(self.err_response(status::BadRequest, "Too many values specified")),
                },
                None => return Ok(self.err_response(status::BadRequest, "\"value\" parameter not specified")),
            }
        }

        // Update values in Redis
        if let Err(e) = self.update_sensor(&sensor_name, &sensor_value) {
            error!("Updating sensor value for sensor \"{}\" failed: {:?}", &sensor_name, e);
            let response = match e {
                sensors::SensorError::UnknownSensor(sensor) =>
                    self.err_response(status::BadRequest, &format!("Unknown sensor: {}", sensor)),
                sensors::SensorError::Redis(_) | sensors::SensorError::R2d2(_) =>
                    self.err_response(status::InternalServerError, "Updating values in datastore failed"),
            };
            return Ok(response)
        };

        // Create response
        Ok(self.ok_response())
    }

}
<commit_msg>Fixed issues identified by Clippy in handler<commit_after>//! Handlers for the server.

use std::collections::BTreeMap;

use rustc_serialize::json::{Json, ToJson};
use serde_json;
use iron::prelude::*;
use iron::{status, headers, middleware};
use iron::modifiers::Header;
use router::Router;

use urlencoded;

use ::api;
use ::types::RedisPool;
use ::sensors;
use ::modifiers;

#[derive(Debug)]
struct ErrorResponse {
    reason: String,
}

impl ToJson for ErrorResponse {
    /// Serialize an ErrorResponse object into a proper JSON structure.
    fn to_json(&self) -> Json {
        let mut d = BTreeMap::new();
        d.insert("status".into(), "error".to_json());
        d.insert("reason".into(), self.reason.to_json());
        Json::Object(d)
    }
}

pub struct ReadHandler {
    status: api::Status,
    redis_pool: RedisPool,
    sensor_specs: sensors::SafeSensorSpecs,
    status_modifiers: Vec<Box<modifiers::StatusModifier>>,
}

impl ReadHandler {
    pub fn new(status: api::Status,
               redis_pool: RedisPool,
               sensor_specs: sensors::SafeSensorSpecs,
               status_modifiers: Vec<Box<modifiers::StatusModifier>>)
               -> ReadHandler {
        ReadHandler {
            status,
            redis_pool,
            sensor_specs,
            status_modifiers,
        }
    }

    fn build_response_json(&self) -> String {

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

        // Process registered sensors
        for sensor_spec in self.sensor_specs.iter() {

            match sensor_spec.get_sensor_value(self.redis_pool.clone()) {

                // Value could be read successfullly
                Ok(value) => {
                    if status_copy.sensors.is_none() {
                        status_copy.sensors = Some(api::Sensors {
                            people_now_present: vec![],
                            temperature: vec![],
                        });
                    }
                    sensor_spec.template.to_sensor(&value, &mut status_copy.sensors.as_mut().unwrap());
                },

                // Value could not be read, do error logging
                Err(err) => {
                    warn!("Could not retrieve key '{}' from Redis, omiting the sensor", &sensor_spec.data_key);
                    match err {
                        sensors::SensorError::Redis(e) => debug!("Error: {:?}", e),
                        sensors::SensorError::R2d2(e) => debug!("Error: {:?}", e),
                        sensors::SensorError::UnknownSensor(e) => warn!("Error: {:?}", e),
                    }
                },
            }
        }

        for status_modifier in &self.status_modifiers {
            status_modifier.modify(&mut status_copy);
        }

        // Serialize to JSON
        serde_json::to_string(&status_copy)
            .expect("Status object could not be serialized to JSON. \
                     Please open an issue at https://github.com/spaceapi-community/spaceapi-server-rs/issues")
    }
}

impl middleware::Handler for ReadHandler {

    /// Return the current status JSON.
    fn handle(&self, req: &mut Request) -> IronResult<Response> {

        info!("{} /{} from {}", req.method, req.url.path()[0], req.remote_addr);

        // Get response body
        let body = self.build_response_json();

        // Create response
        let response = Response::with((status::Ok, body))
            // Set headers
            .set(Header(headers::ContentType("application/json; charset=utf-8".parse().unwrap())))
            .set(Header(headers::CacheControl(vec![headers::CacheDirective::NoCache])))
            .set(Header(headers::AccessControlAllowOrigin::Any));

        Ok(response)
    }

}

pub struct UpdateHandler {
    redis_pool: RedisPool,
    sensor_specs: sensors::SafeSensorSpecs,
}

impl UpdateHandler {
    pub fn new(redis_pool: RedisPool, sensor_specs: sensors::SafeSensorSpecs)
               -> UpdateHandler {
        UpdateHandler {
            redis_pool,
            sensor_specs,
        }
    }

    /// Update sensor value in Redis
    fn update_sensor(&self, sensor: &str, value: &str) -> Result<(), sensors::SensorError> {
        // Validate sensor
        let sensor_spec = try!(self.sensor_specs.iter()
                               .find(|&spec| spec.data_key == sensor)
                               .ok_or_else(|| sensors::SensorError::UnknownSensor(sensor.into())));

        // Store data
        sensor_spec.set_sensor_value(self.redis_pool.clone(), value)
    }

    /// Build an OK response with the `HTTP 204 No Content` status code.
    fn ok_response(&self) -> Response {
        Response::with(status::NoContent)
            // Set headers
            .set(Header(headers::ContentType("application/json; charset=utf-8".parse().unwrap())))
            .set(Header(headers::CacheControl(vec![headers::CacheDirective::NoCache])))
            .set(Header(headers::AccessControlAllowOrigin::Any))
    }

    /// Build an error response with the specified `error_code` and the specified `reason` text.
    fn err_response(&self, error_code: status::Status, reason: &str) -> Response {
        let error = ErrorResponse { reason: reason.into() };
        Response::with((error_code, error.to_json().to_string()))
            // Set headers
            .set(Header(headers::ContentType("application/json; charset=utf-8".parse().unwrap())))
            .set(Header(headers::CacheControl(vec![headers::CacheDirective::NoCache])))
            .set(Header(headers::AccessControlAllowOrigin::Any))
    }

}

impl middleware::Handler for UpdateHandler {

    /// Update the sensor, return correct status code.
    fn handle(&self, req: &mut Request) -> IronResult<Response> {

        // TODO: create macro for these info! invocations.
        info!("{} /{} from {}", req.method, req.url.path()[0], req.remote_addr);

        // Get sensor name
        let sensor_name;
        {
            // TODO: Properly propagate errors
            let params = req.extensions.get::<Router>().unwrap();
            sensor_name = params.find("sensor").unwrap().to_string();
        }

        // Get sensor value
        let sensor_value;
        {
            let params = req.get_ref::<urlencoded::UrlEncodedBody>().unwrap();
            sensor_value = match params.get("value") {
                Some(ref values) =>  match values.len() {
                    1 => values[0].to_string(),
                    _ => return Ok(self.err_response(status::BadRequest, "Too many values specified")),
                },
                None => return Ok(self.err_response(status::BadRequest, "\"value\" parameter not specified")),
            }
        }

        // Update values in Redis
        if let Err(e) = self.update_sensor(&sensor_name, &sensor_value) {
            error!("Updating sensor value for sensor \"{}\" failed: {:?}", &sensor_name, e);
            let response = match e {
                sensors::SensorError::UnknownSensor(sensor) =>
                    self.err_response(status::BadRequest, &format!("Unknown sensor: {}", sensor)),
                sensors::SensorError::Redis(_) | sensors::SensorError::R2d2(_) =>
                    self.err_response(status::InternalServerError, "Updating values in datastore failed"),
            };
            return Ok(response)
        };

        // Create response
        Ok(self.ok_response())
    }

}
<|endoftext|>


<commit_before>enum CompressionMode {
    CompressNone,
    CompressWhitespace,
    CompressWhitespaceNewline,
    DiscardNewline
}

impl CompressionMode : cmp::Eq {
    pure fn eq(other: &CompressionMode) -> bool {
        match (self, *other) {
            (CompressNone, CompressNone) => true,
            (CompressWhitespace, CompressWhitespace) => true,
            (CompressWhitespaceNewline, CompressWhitespaceNewline) => true,
            (DiscardNewline, DiscardNewline) => true,
            _ => false
        }
    }
    pure fn ne(other: &CompressionMode) -> bool {
        !self.eq(other)
    }
}

// ported from Gecko's nsTextFrameUtils::TransformText.
//
// High level TODOs:
// * consider incoming text state (preceding spaces, arabic, etc)
// * send outgoing text state (dual of above)
// * record skipped and kept chars for mapping original to new text
// * various edge cases for bidi, CJK, combining char seqs, etc.
pub fn transform_text(text: &str, mode: CompressionMode) -> ~str {
    let out_str: ~str = ~"";
    match mode {
        CompressNone | DiscardNewline => {
            do str::each_char(text) |ch: char| {
                if is_discardable_char(ch, mode) {
                    // TODO: record skipped char
                } else {
                    // TODO: record kept char
                    if ch == '\t' {
                        // TODO: set "has tab" flag
                    }
                    str::push_char(&out_str, ch);
                }

                true
            }
        },

        CompressWhitespace | CompressWhitespaceNewline => {
            let mut in_whitespace: bool = false;
            do str::each_char(text) |ch: char| {
                // TODO: discard newlines between CJK chars
                let mut next_in_whitespace: bool = match (ch, mode) {
                    // TODO: check for following char that may create
                    // a Unicode combining-character sequence with a
                    // space, in which case it shouldn't be  compressed.
                    (' ', _)  => true,
                    ('\t', _) => true,
                    ('\n', CompressWhitespaceNewline) => true,
                    (_, _)    => false
                };

                if next_in_whitespace {
                    if is_always_discardable_char(ch) {
                        // revert whitespace setting, since this char was discarded
                        next_in_whitespace = in_whitespace;
                        // TODO: record skipped char
                    } else {
                        // TODO: record kept char
                        str::push_char(&out_str, ch);
                    }
                } else {
                    if in_whitespace {
                        // TODO: record skipped char
                    } else {
                        // TODO: record kept char
                        str::push_char(&out_str, ch);
                    }
                }
                // save whitespace context for next char
                in_whitespace = next_in_whitespace;
                true
            } /* /do str::each_chari */
        }
    }

    return out_str;

    fn is_discardable_char(ch: char, mode: CompressionMode) -> bool {
        if is_always_discardable_char(ch) {
            return true;
        }
        match mode {
            DiscardNewline | CompressWhitespaceNewline => ch == '\n',
            _ => false
        }
    }

    fn is_always_discardable_char(_ch: char) -> bool {
        // TODO: check for bidi control chars, soft hyphens.
        false
    }
}

pub fn float_to_fixed(before: int, f: float) -> i32 {
    (1i32 << before) * (f as i32)
}

pub fn fixed_to_float(before: int, f: i32) -> float {
    f as float * 1.0f / ((1i32 << before) as float)
}

pub fn fixed_to_rounded_int(before: int, f: i32) -> int {
    let half = 1i32 << (before-1);
    if f > 0i32 {
        ((half + f) >> before) as int
    } else {
       -((half - f) >> before) as int
    }
}

/* Generate a 32-bit TrueType tag from its 4 characters */
pub fn true_type_tag(a: char, b: char, c: char, d: char) -> u32 {
    (a << 24 | b << 16 | c << 8 | d) as u32
}

#[test]
fn test_true_type_tag() {
    assert true_type_tag('c', 'm', 'a', 'p') == 0x_63_6D_61_70_u32;
}
<commit_msg>Fix logic bug in transform_text; convert do to for; add some simple tests for each compression mode.<commit_after>enum CompressionMode {
    CompressNone,
    CompressWhitespace,
    CompressWhitespaceNewline,
    DiscardNewline
}

impl CompressionMode : cmp::Eq {
    pure fn eq(other: &CompressionMode) -> bool {
        match (self, *other) {
            (CompressNone, CompressNone) => true,
            (CompressWhitespace, CompressWhitespace) => true,
            (CompressWhitespaceNewline, CompressWhitespaceNewline) => true,
            (DiscardNewline, DiscardNewline) => true,
            _ => false
        }
    }
    pure fn ne(other: &CompressionMode) -> bool {
        !self.eq(other)
    }
}

// ported from Gecko's nsTextFrameUtils::TransformText.
//
// High level TODOs:
// * consider incoming text state (preceding spaces, arabic, etc)
// * send outgoing text state (dual of above)
// * record skipped and kept chars for mapping original to new text
// * various edge cases for bidi, CJK, combining char seqs, etc.
pub fn transform_text(text: &str, mode: CompressionMode) -> ~str {
    let out_str: ~str = ~"";
    match mode {
        CompressNone | DiscardNewline => {
            for str::each_char(text) |ch: char| {
                if is_discardable_char(ch, mode) {
                    // TODO: record skipped char
                } else {
                    // TODO: record kept char
                    if ch == '\t' {
                        // TODO: set "has tab" flag
                    }
                    str::push_char(&out_str, ch);
                }
            }
        },

        CompressWhitespace | CompressWhitespaceNewline => {
            let mut in_whitespace: bool = false;
            for str::each_char(text) |ch: char| {
                // TODO: discard newlines between CJK chars
                let mut next_in_whitespace: bool = match (ch, mode) {
                    // TODO: check for following char that may create
                    // a Unicode combining-character sequence with a
                    // space, in which case it shouldn't be  compressed.
                    (' ', _)  => true,
                    ('\t', _) => true,
                    ('\n', CompressWhitespaceNewline) => true,
                    (_, _)    => false
                };

                if !next_in_whitespace {
                    if is_always_discardable_char(ch) {
                        // revert whitespace setting, since this char was discarded
                        next_in_whitespace = in_whitespace;
                        // TODO: record skipped char
                    } else {
                        // TODO: record kept char
                        str::push_char(&out_str, ch);
                    }
                } else { /* next_in_whitespace; possibly add a space char */
                    if in_whitespace {
                        // TODO: record skipped char
                    } else {
                        // TODO: record kept char
                        str::push_char(&out_str, ' ');
                    }
                }
                // save whitespace context for next char
                in_whitespace = next_in_whitespace;
            } /* /for str::each_char */
        }
    }

    return out_str;

    fn is_discardable_char(ch: char, mode: CompressionMode) -> bool {
        if is_always_discardable_char(ch) {
            return true;
        }
        match mode {
            DiscardNewline | CompressWhitespaceNewline => ch == '\n',
            _ => false
        }
    }

    fn is_always_discardable_char(_ch: char) -> bool {
        // TODO: check for bidi control chars, soft hyphens.
        false
    }
}

pub fn float_to_fixed(before: int, f: float) -> i32 {
    (1i32 << before) * (f as i32)
}

pub fn fixed_to_float(before: int, f: i32) -> float {
    f as float * 1.0f / ((1i32 << before) as float)
}

pub fn fixed_to_rounded_int(before: int, f: i32) -> int {
    let half = 1i32 << (before-1);
    if f > 0i32 {
        ((half + f) >> before) as int
    } else {
       -((half - f) >> before) as int
    }
}

/* Generate a 32-bit TrueType tag from its 4 characters */
pub fn true_type_tag(a: char, b: char, c: char, d: char) -> u32 {
    (a << 24 | b << 16 | c << 8 | d) as u32
}

#[test]
fn test_true_type_tag() {
    assert true_type_tag('c', 'm', 'a', 'p') == 0x_63_6D_61_70_u32;
}

#[test]
fn test_transform_compress_none() {

    let  test_strs : ~[~str] = ~[~"  foo bar",
                                 ~"foo bar  ",
                                 ~"foo\n bar",
                                 ~"foo \nbar",
                                 ~"  foo  bar  \nbaz",
                                 ~"foo bar baz",
                                 ~"foobarbaz\n\n"];
    let mode = CompressNone;

    for uint::range(0, test_strs.len()) |i| {
        assert transform_text(test_strs[i], mode) == test_strs[i];
    }
}

#[test]
fn test_transform_discard_newline() {

    let  test_strs : ~[~str] = ~[~"  foo bar",
                                 ~"foo bar  ",
                                 ~"foo\n bar",
                                 ~"foo \nbar",
                                 ~"  foo  bar  \nbaz",
                                 ~"foo bar baz",
                                 ~"foobarbaz\n\n"];

    let  oracle_strs : ~[~str] = ~[~"  foo bar",
                                   ~"foo bar  ",
                                   ~"foo bar",
                                   ~"foo bar",
                                   ~"  foo  bar  baz",
                                   ~"foo bar baz",
                                   ~"foobarbaz"];

    assert vec::same_length(test_strs, oracle_strs);
    let mode = DiscardNewline;

    for uint::range(0, test_strs.len()) |i| {
        assert transform_text(test_strs[i], mode) == oracle_strs[i];
    }
}

#[test]
fn test_transform_compress_whitespace() {
    let  test_strs : ~[~str] = ~[~"  foo bar",
                                 ~"foo bar  ",
                                 ~"foo\n bar",
                                 ~"foo \nbar",
                                 ~"  foo  bar  \nbaz",
                                 ~"foo bar baz",
                                 ~"foobarbaz\n\n"];

    let oracle_strs : ~[~str] = ~[~" foo bar",
                                 ~"foo bar ",
                                 ~"foo\n bar",
                                 ~"foo \nbar",
                                 ~" foo bar \nbaz",
                                 ~"foo bar baz",
                                 ~"foobarbaz\n\n"];

    assert vec::same_length(test_strs, oracle_strs);
    let mode = CompressWhitespace;

    for uint::range(0, test_strs.len()) |i| {
        assert transform_text(test_strs[i], mode) == oracle_strs[i];
    }
}

#[test]
fn test_transform_compress_whitespace_newline() {
    let  test_strs : ~[~str] = ~[~"  foo bar",
                                 ~"foo bar  ",
                                 ~"foo\n bar",
                                 ~"foo \nbar",
                                 ~"  foo  bar  \nbaz",
                                 ~"foo bar baz",
                                 ~"foobarbaz\n\n"];

    let oracle_strs : ~[~str] = ~[~" foo bar",
                                 ~"foo bar ",
                                 ~"foo bar",
                                 ~"foo bar",
                                 ~" foo bar baz",
                                 ~"foo bar baz",
                                 ~"foobarbaz "];

    assert vec::same_length(test_strs, oracle_strs);
    let mode = CompressWhitespaceNewline;

    for uint::range(0, test_strs.len()) |i| {
        assert transform_text(test_strs[i], mode) == oracle_strs[i];
    }
}<|endoftext|>


<commit_before>//! Users interface

use {Github, Result};

/// User information
#[derive(Debug, Deserialize)]
pub struct User {
    pub login: String,
    pub id: u64,
    pub avatar_url: String,
    pub gravatar_id: String,
    pub url: String,
    pub html_url: String,
    pub followers_url: String,
    pub following_url: String,
    pub gists_url: String,
    pub starred_url: String,
    pub subscriptions_url: String,
    pub organizations_url: String,
    pub repos_url: String,
    pub events_url: String,
    pub received_events_url: String,
    // type (keyword)
    pub site_admin: bool,
}

/// Information about current authenticated user
#[derive(Debug, Deserialize)]
pub struct AuthenticatedUser {
    pub login: String,
    pub id: u64,
    pub avatar_url: String,
    pub gravatar_id: String,
    pub url: String,
    pub html_url: String,
    pub followers_url: String,
    pub following_url: String,
    pub gists_url: String,
    pub starred_url: String,
    pub subscriptions_url: String,
    pub organizations_url: String,
    pub repos_url: String,
    pub events_url: String,
    pub received_events_url: String,
    // type (keyword)
    pub site_admin: bool,

    // extend over `User`:
    pub name: String,
    pub company: String,
    pub blog: String,
    pub location: String,
    pub email: String,
    pub hireable: String,
    pub bio: String,
    pub public_repos: u64,
    pub public_gists: u64,
    pub followers: u64,
    pub following: u64,
    pub created_at: String, // TODO: change to `DateTime`?
    pub updated_at: String, // TODO: change to `DateTime`?
}

/// Query user information
pub struct Users<'a> {
    github: &'a Github,
}

impl<'a> Users<'a> {
    pub fn new(github: &'a Github) -> Users<'a> {
        Users {
            github: github,
        }
    }

    /// Information about current authenticated user
    pub fn authenticated(&self) -> Result<AuthenticatedUser> {
        self.github.get::<AuthenticatedUser>(&"/user")
    }
}
<commit_msg>Fix `AuthenticatedUser::hireable` field type<commit_after>//! Users interface

use {Github, Result};

/// User information
#[derive(Debug, Deserialize)]
pub struct User {
    pub login: String,
    pub id: u64,
    pub avatar_url: String,
    pub gravatar_id: String,
    pub url: String,
    pub html_url: String,
    pub followers_url: String,
    pub following_url: String,
    pub gists_url: String,
    pub starred_url: String,
    pub subscriptions_url: String,
    pub organizations_url: String,
    pub repos_url: String,
    pub events_url: String,
    pub received_events_url: String,
    // type (keyword)
    pub site_admin: bool,
}

/// Information about current authenticated user
#[derive(Debug, Deserialize)]
pub struct AuthenticatedUser {
    pub login: String,
    pub id: u64,
    pub avatar_url: String,
    pub gravatar_id: String,
    pub url: String,
    pub html_url: String,
    pub followers_url: String,
    pub following_url: String,
    pub gists_url: String,
    pub starred_url: String,
    pub subscriptions_url: String,
    pub organizations_url: String,
    pub repos_url: String,
    pub events_url: String,
    pub received_events_url: String,
    // type (keyword)
    pub site_admin: bool,

    // extend over `User`:
    pub name: String,
    pub company: String,
    pub blog: String,
    pub location: String,
    pub email: String,
    pub hireable: Option<bool>,
    pub bio: String,
    pub public_repos: u64,
    pub public_gists: u64,
    pub followers: u64,
    pub following: u64,
    pub created_at: String, // TODO: change to `DateTime`?
    pub updated_at: String, // TODO: change to `DateTime`?
}

/// Query user information
pub struct Users<'a> {
    github: &'a Github,
}

impl<'a> Users<'a> {
    pub fn new(github: &'a Github) -> Users<'a> {
        Users {
            github: github,
        }
    }

    /// Information about current authenticated user
    pub fn authenticated(&self) -> Result<AuthenticatedUser> {
        self.github.get::<AuthenticatedUser>(&"/user")
    }
}
<|endoftext|>


<commit_before>/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Joseph Crail <jbcrail@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

// Based on the pattern using by Cargo, I created a shim over the
// standard PathExt trait, so that the unstable path methods could
// be backported to stable (<= 1.1). This will likely be dropped
// when the path trait stabilizes.

use ::libc;
use std::env;
use std::fs;
use std::io::{Error, ErrorKind, Result};
use std::path::{Component, Path, PathBuf};

pub trait UUPathExt {
    fn uu_exists(&self) -> bool;
    fn uu_is_file(&self) -> bool;
    fn uu_is_dir(&self) -> bool;
    fn uu_metadata(&self) -> Result<fs::Metadata>;
}

impl UUPathExt for Path {
    fn uu_exists(&self) -> bool {
        fs::metadata(self).is_ok()
    }

    fn uu_is_file(&self) -> bool {
        fs::metadata(self).map(|m| m.is_file()).unwrap_or(false)
    }

    fn uu_is_dir(&self) -> bool {
        fs::metadata(self).map(|m| m.is_dir()).unwrap_or(false)
    }

    fn uu_metadata(&self) -> Result<fs::Metadata> {
        fs::metadata(self)
    }
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum CanonicalizeMode {
    None,
    Normal,
    Existing,
    Missing,
}

fn resolve<P: AsRef<Path>>(original: P) -> Result<PathBuf> {
    const MAX_LINKS_FOLLOWED: u32 = 255;
    let mut followed = 0;
    let mut result = original.as_ref().to_path_buf();
    loop {
        if followed == MAX_LINKS_FOLLOWED {
            return Err(Error::new(ErrorKind::InvalidInput, "maximum links followed"));
        }

        match fs::metadata(&result) {
            Err(e) => return Err(e),
            Ok(ref m) if !m.file_type().is_symlink() => break,
            Ok(..) => {
                followed += 1;
                match fs::read_link(&result) {
                    Ok(path) => {
                        result.pop();
                        result.push(path);
                    },
                    Err(e) => {
                        return Err(e);
                    }
                }
            }
        }
    }
    Ok(result)
}

pub fn canonicalize<P: AsRef<Path>>(original: P, can_mode: CanonicalizeMode) -> Result<PathBuf> {
    // Create an absolute path
    let original = original.as_ref();
    let original = if original.is_absolute() {
        original.to_path_buf()
    } else {
        env::current_dir().unwrap().join(original)
    };

    let mut result = PathBuf::new();
    let mut parts = vec!();

    // Split path by directory separator; add prefix (Windows-only) and root
    // directory to final path buffer; add remaining parts to temporary
    // vector for canonicalization.
    for part in original.components() {
        match part {
            Component::Prefix(_) | Component::RootDir => {
                result.push(part.as_os_str());
            },
            Component::CurDir => {},
            Component::ParentDir => {
                parts.pop();
            },
            Component::Normal(_) => {
                parts.push(part.as_os_str());
            }
        }
    }

    // Resolve the symlinks where possible
    if parts.len() > 0 {
        for part in parts[..parts.len()-1].iter() {
            result.push(part);

            if can_mode == CanonicalizeMode::None {
                continue;
            }

            match resolve(&result) {
                Err(e) => match can_mode {
                    CanonicalizeMode::Missing => continue,
                    _ => return Err(e)
                },
                Ok(path) => {
                    result.pop();
                    result.push(path);
                }
            }
        }

        result.push(parts.last().unwrap());

        match resolve(&result) {
            Err(e) => { if can_mode == CanonicalizeMode::Existing { return Err(e); } },
            Ok(path) => {
                result.pop();
                result.push(path);
            }
        }
    }
    Ok(result)
}

#[cfg(unix)]
pub fn is_stdin_interactive() -> bool {
    unsafe { libc::isatty(libc::STDIN_FILENO) == 1 }
}

#[cfg(windows)]
pub fn is_stdin_interactive() -> bool {
    0
}

#[cfg(unix)]
pub fn is_stdout_interactive() -> bool {
    unsafe { libc::isatty(libc::STDOUT_FILENO) == 1 }
}

#[cfg(windows)]
pub fn is_stdout_interactive() -> bool {
    0
}

#[cfg(unix)]
pub fn is_stderr_interactive() -> bool {
    unsafe { libc::isatty(libc::STDERR_FILENO) == 1 }
}

#[cfg(windows)]
pub fn is_stderr_interactive() -> bool {
    0
}
<commit_msg>Fix errors with bools represented as ints.<commit_after>/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Joseph Crail <jbcrail@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

// Based on the pattern using by Cargo, I created a shim over the
// standard PathExt trait, so that the unstable path methods could
// be backported to stable (<= 1.1). This will likely be dropped
// when the path trait stabilizes.

use ::libc;
use std::env;
use std::fs;
use std::io::{Error, ErrorKind, Result};
use std::path::{Component, Path, PathBuf};

pub trait UUPathExt {
    fn uu_exists(&self) -> bool;
    fn uu_is_file(&self) -> bool;
    fn uu_is_dir(&self) -> bool;
    fn uu_metadata(&self) -> Result<fs::Metadata>;
}

impl UUPathExt for Path {
    fn uu_exists(&self) -> bool {
        fs::metadata(self).is_ok()
    }

    fn uu_is_file(&self) -> bool {
        fs::metadata(self).map(|m| m.is_file()).unwrap_or(false)
    }

    fn uu_is_dir(&self) -> bool {
        fs::metadata(self).map(|m| m.is_dir()).unwrap_or(false)
    }

    fn uu_metadata(&self) -> Result<fs::Metadata> {
        fs::metadata(self)
    }
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum CanonicalizeMode {
    None,
    Normal,
    Existing,
    Missing,
}

fn resolve<P: AsRef<Path>>(original: P) -> Result<PathBuf> {
    const MAX_LINKS_FOLLOWED: u32 = 255;
    let mut followed = 0;
    let mut result = original.as_ref().to_path_buf();
    loop {
        if followed == MAX_LINKS_FOLLOWED {
            return Err(Error::new(ErrorKind::InvalidInput, "maximum links followed"));
        }

        match fs::metadata(&result) {
            Err(e) => return Err(e),
            Ok(ref m) if !m.file_type().is_symlink() => break,
            Ok(..) => {
                followed += 1;
                match fs::read_link(&result) {
                    Ok(path) => {
                        result.pop();
                        result.push(path);
                    },
                    Err(e) => {
                        return Err(e);
                    }
                }
            }
        }
    }
    Ok(result)
}

pub fn canonicalize<P: AsRef<Path>>(original: P, can_mode: CanonicalizeMode) -> Result<PathBuf> {
    // Create an absolute path
    let original = original.as_ref();
    let original = if original.is_absolute() {
        original.to_path_buf()
    } else {
        env::current_dir().unwrap().join(original)
    };

    let mut result = PathBuf::new();
    let mut parts = vec!();

    // Split path by directory separator; add prefix (Windows-only) and root
    // directory to final path buffer; add remaining parts to temporary
    // vector for canonicalization.
    for part in original.components() {
        match part {
            Component::Prefix(_) | Component::RootDir => {
                result.push(part.as_os_str());
            },
            Component::CurDir => {},
            Component::ParentDir => {
                parts.pop();
            },
            Component::Normal(_) => {
                parts.push(part.as_os_str());
            }
        }
    }

    // Resolve the symlinks where possible
    if parts.len() > 0 {
        for part in parts[..parts.len()-1].iter() {
            result.push(part);

            if can_mode == CanonicalizeMode::None {
                continue;
            }

            match resolve(&result) {
                Err(e) => match can_mode {
                    CanonicalizeMode::Missing => continue,
                    _ => return Err(e)
                },
                Ok(path) => {
                    result.pop();
                    result.push(path);
                }
            }
        }

        result.push(parts.last().unwrap());

        match resolve(&result) {
            Err(e) => { if can_mode == CanonicalizeMode::Existing { return Err(e); } },
            Ok(path) => {
                result.pop();
                result.push(path);
            }
        }
    }
    Ok(result)
}

#[cfg(unix)]
pub fn is_stdin_interactive() -> bool {
    unsafe { libc::isatty(libc::STDIN_FILENO) == 1 }
}

#[cfg(windows)]
pub fn is_stdin_interactive() -> bool {
    false
}

#[cfg(unix)]
pub fn is_stdout_interactive() -> bool {
    unsafe { libc::isatty(libc::STDOUT_FILENO) == 1 }
}

#[cfg(windows)]
pub fn is_stdout_interactive() -> bool {
    false
}

#[cfg(unix)]
pub fn is_stderr_interactive() -> bool {
    unsafe { libc::isatty(libc::STDERR_FILENO) == 1 }
}

#[cfg(windows)]
pub fn is_stderr_interactive() -> bool {
    false
}
<|endoftext|>


<commit_before>use super::*;

#[test]
pub fn test_open_close() {
    unsafe {
        let mrb = mrb_open();

        mrb_close(mrb);
    }
}

#[test]
pub fn test_exec_context() {
    unsafe {
        let mrb = mrb_open();
        let context = mrbc_context_new(mrb);

        mrbc_filename(mrb, context, "script.rb\0".as_ptr());

        let code = "'' + 0\0".as_ptr();

        mrb_load_string_cxt(mrb, code, context);

        assert_eq!(mrb_ext_get_exc(mrb).to_str(mrb).unwrap(), "script.rb:1: expected String (TypeError)");

        mrb_close(mrb);
    }
}

#[test]
pub fn test_create_run_proc() {
    unsafe {
        let mrb = mrb_open();
        let context = mrbc_context_new(mrb);

        let code = "1 + 1\0".as_ptr();
        let parser = mrb_parse_string(mrb, code, context);
        let prc = mrb_generate_code(mrb, parser);

        let result = mrb_run(mrb, prc, mrb_top_self(mrb));

        assert_eq!(result.to_i32().unwrap(), 2);

        mrb_close(mrb);
    }
}

#[test]
pub fn test_class_defined() {
    unsafe {
        let mrb = mrb_open();

        let obj_class = "Object\0".as_ptr();

        assert_eq!(mrb_class_defined(mrb, obj_class), 1);

        mrb_close(mrb);
    }
}

#[test]
pub fn test_define_class() {
    unsafe {
        let mrb = mrb_open();

        let obj_class = "Object\0".as_ptr();
        let new_class = "Mine\0".as_ptr();

        let obj_class = mrb_class_get(mrb, "Object\0".as_ptr());

        mrb_define_class(mrb, new_class, obj_class);

        assert_eq!(mrb_class_defined(mrb, new_class), 1);

        mrb_close(mrb);
    }
}

#[test]
pub fn test_define_module() {
    unsafe {
        let mrb = mrb_open();

        let new_module = "Mine\0".as_ptr();

        mrb_define_module(mrb, new_module);

        mrb_module_get(mrb, new_module);

        mrb_close(mrb);
    }
}

#[test]
pub fn test_include_module() {
    unsafe {
        let mrb = mrb_open();

        let kernel = "Kernel\0".as_ptr();
        let new_module = "Mine\0".as_ptr();

        let new_module = mrb_define_module(mrb, new_module);
        let kernel = mrb_module_get(mrb, kernel);

        mrb_include_module(mrb, kernel, new_module);

        mrb_close(mrb);
    }
}

#[test]
pub fn test_prepend_module() {
    unsafe {
        let mrb = mrb_open();

        let kernel = "Kernel\0".as_ptr();
        let new_module = "Mine\0".as_ptr();

        let new_module = mrb_define_module(mrb, new_module);
        let kernel = mrb_module_get(mrb, kernel);

        mrb_prepend_module(mrb, kernel, new_module);

        mrb_close(mrb);
    }
}

#[test]
pub fn test_define_method() {
    unsafe {
        let mrb = mrb_open();
        let context = mrbc_context_new(mrb);

        let obj_class = "Object\0".as_ptr();
        let new_class = "Mine\0".as_ptr();

        let obj_class = mrb_class_get(mrb, "Object\0".as_ptr());
        let new_class = mrb_define_class(mrb, new_class, obj_class);

        extern "C" fn job(mrb: *mut MRState, slf: MRValue) -> MRValue {
            unsafe {
                MRValue::fixnum(2)
            }
        }

        mrb_define_method(mrb, new_class, "job\0".as_ptr(), job, 0);

        let code = "Mine.new.job\0".as_ptr();

        assert_eq!(mrb_load_string_cxt(mrb, code, context).to_i32().unwrap(), 2);

        mrb_close(mrb);
    }
}

#[test]
pub fn test_define_class_method() {
    unsafe {
        let mrb = mrb_open();
        let context = mrbc_context_new(mrb);

        let obj_class = "Object\0".as_ptr();
        let new_class = "Mine\0".as_ptr();

        let obj_class = mrb_class_get(mrb, "Object\0".as_ptr());
        let new_class = mrb_define_class(mrb, new_class, obj_class);

        extern "C" fn job(mrb: *mut MRState, slf: MRValue) -> MRValue {
            unsafe {
                MRValue::fixnum(2)
            }
        }

        mrb_define_class_method(mrb, new_class, "job\0".as_ptr(), job, 0);

        let code = "Mine.job\0".as_ptr();

        assert_eq!(mrb_load_string_cxt(mrb, code, context).to_i32().unwrap(), 2);

        mrb_close(mrb);
    }
}

#[test]
pub fn test_define_module_function() {
    unsafe {
        let mrb = mrb_open();
        let context = mrbc_context_new(mrb);

        let new_module = "Mine\0".as_ptr();
        let new_module = mrb_define_module(mrb, new_module);

        extern "C" fn job(mrb: *mut MRState, slf: MRValue) -> MRValue {
            unsafe {
                MRValue::fixnum(2)
            }
        }

        mrb_define_module_function(mrb, new_module, "job\0".as_ptr(), job, 0);

        let code = "Mine.job\0".as_ptr();

        assert_eq!(mrb_load_string_cxt(mrb, code, context).to_i32().unwrap(), 2);

        mrb_close(mrb);
    }
}

#[test]
pub fn test_obj_new() {
    use std::ptr;

    unsafe {
        let mrb = mrb_open();
        let context = mrbc_context_new(mrb);

        let obj_class = "Object\0".as_ptr();
        let obj_class = mrb_class_get(mrb, "Object\0".as_ptr());

        mrb_obj_new(mrb, obj_class, 0, ptr::null() as *const MRValue);

        mrb_close(mrb);
    }
}

#[test]
pub fn test_proc_new_cfunc() {
    use std::ptr;

    unsafe {
        let mrb = mrb_open();
        let context = mrbc_context_new(mrb);

        extern "C" fn job(mrb: *mut MRState, slf: MRValue) -> MRValue {
            unsafe {
                MRValue::fixnum(2)
            }
        }

        let prc = MRValue::prc(mrb, mrb_proc_new_cfunc(mrb, job));

        mrb_funcall_with_block(mrb, MRValue::fixnum(5), mrb_intern_cstr(mrb, "times\0".as_ptr()), 0, ptr::null() as *const MRValue, prc);

        mrb_close(mrb);
    }
}
<commit_msg>Added MRValue tests.<commit_after>use super::*;

#[test]
fn test_open_close() {
    unsafe {
        let mrb = mrb_open();

        mrb_close(mrb);
    }
}

#[test]
fn test_exec_context() {
    unsafe {
        let mrb = mrb_open();
        let context = mrbc_context_new(mrb);

        mrbc_filename(mrb, context, "script.rb\0".as_ptr());

        let code = "'' + 0\0".as_ptr();

        mrb_load_string_cxt(mrb, code, context);

        assert_eq!(mrb_ext_get_exc(mrb).to_str(mrb).unwrap(), "script.rb:1: expected String (TypeError)");

        mrb_close(mrb);
    }
}

#[test]
fn test_create_run_proc() {
    unsafe {
        let mrb = mrb_open();
        let context = mrbc_context_new(mrb);

        let code = "1 + 1\0".as_ptr();
        let parser = mrb_parse_string(mrb, code, context);
        let prc = mrb_generate_code(mrb, parser);

        let result = mrb_run(mrb, prc, mrb_top_self(mrb));

        assert_eq!(result.to_i32().unwrap(), 2);

        mrb_close(mrb);
    }
}

#[test]
fn test_class_defined() {
    unsafe {
        let mrb = mrb_open();

        let obj_class = "Object\0".as_ptr();

        assert_eq!(mrb_class_defined(mrb, obj_class), 1);

        mrb_close(mrb);
    }
}

#[test]
fn test_define_class() {
    unsafe {
        let mrb = mrb_open();

        let obj_class = "Object\0".as_ptr();
        let new_class = "Mine\0".as_ptr();

        let obj_class = mrb_class_get(mrb, "Object\0".as_ptr());

        mrb_define_class(mrb, new_class, obj_class);

        assert_eq!(mrb_class_defined(mrb, new_class), 1);

        mrb_close(mrb);
    }
}

#[test]
fn test_define_module() {
    unsafe {
        let mrb = mrb_open();

        let new_module = "Mine\0".as_ptr();

        mrb_define_module(mrb, new_module);

        mrb_module_get(mrb, new_module);

        mrb_close(mrb);
    }
}

#[test]
fn test_include_module() {
    unsafe {
        let mrb = mrb_open();

        let kernel = "Kernel\0".as_ptr();
        let new_module = "Mine\0".as_ptr();

        let new_module = mrb_define_module(mrb, new_module);
        let kernel = mrb_module_get(mrb, kernel);

        mrb_include_module(mrb, kernel, new_module);

        mrb_close(mrb);
    }
}

#[test]
fn test_prepend_module() {
    unsafe {
        let mrb = mrb_open();

        let kernel = "Kernel\0".as_ptr();
        let new_module = "Mine\0".as_ptr();

        let new_module = mrb_define_module(mrb, new_module);
        let kernel = mrb_module_get(mrb, kernel);

        mrb_prepend_module(mrb, kernel, new_module);

        mrb_close(mrb);
    }
}

#[test]
fn test_define_method() {
    unsafe {
        let mrb = mrb_open();
        let context = mrbc_context_new(mrb);

        let obj_class = "Object\0".as_ptr();
        let new_class = "Mine\0".as_ptr();

        let obj_class = mrb_class_get(mrb, "Object\0".as_ptr());
        let new_class = mrb_define_class(mrb, new_class, obj_class);

        extern "C" fn job(mrb: *mut MRState, slf: MRValue) -> MRValue {
            unsafe {
                MRValue::fixnum(2)
            }
        }

        mrb_define_method(mrb, new_class, "job\0".as_ptr(), job, 0);

        let code = "Mine.new.job\0".as_ptr();

        assert_eq!(mrb_load_string_cxt(mrb, code, context).to_i32().unwrap(), 2);

        mrb_close(mrb);
    }
}

#[test]
fn test_define_class_method() {
    unsafe {
        let mrb = mrb_open();
        let context = mrbc_context_new(mrb);

        let obj_class = "Object\0".as_ptr();
        let new_class = "Mine\0".as_ptr();

        let obj_class = mrb_class_get(mrb, "Object\0".as_ptr());
        let new_class = mrb_define_class(mrb, new_class, obj_class);

        extern "C" fn job(mrb: *mut MRState, slf: MRValue) -> MRValue {
            unsafe {
                MRValue::fixnum(2)
            }
        }

        mrb_define_class_method(mrb, new_class, "job\0".as_ptr(), job, 0);

        let code = "Mine.job\0".as_ptr();

        assert_eq!(mrb_load_string_cxt(mrb, code, context).to_i32().unwrap(), 2);

        mrb_close(mrb);
    }
}

#[test]
fn test_define_module_function() {
    unsafe {
        let mrb = mrb_open();
        let context = mrbc_context_new(mrb);

        let new_module = "Mine\0".as_ptr();
        let new_module = mrb_define_module(mrb, new_module);

        extern "C" fn job(mrb: *mut MRState, slf: MRValue) -> MRValue {
            unsafe {
                MRValue::fixnum(2)
            }
        }

        mrb_define_module_function(mrb, new_module, "job\0".as_ptr(), job, 0);

        let code = "Mine.job\0".as_ptr();

        assert_eq!(mrb_load_string_cxt(mrb, code, context).to_i32().unwrap(), 2);

        mrb_close(mrb);
    }
}

#[test]
fn test_obj_new() {
    use std::ptr;

    unsafe {
        let mrb = mrb_open();
        let context = mrbc_context_new(mrb);

        let obj_class = "Object\0".as_ptr();
        let obj_class = mrb_class_get(mrb, "Object\0".as_ptr());

        mrb_obj_new(mrb, obj_class, 0, ptr::null() as *const MRValue);

        mrb_close(mrb);
    }
}

#[test]
fn test_proc_new_cfunc() {
    use std::ptr;

    unsafe {
        let mrb = mrb_open();
        let context = mrbc_context_new(mrb);

        extern "C" fn job(mrb: *mut MRState, slf: MRValue) -> MRValue {
            unsafe {
                MRValue::fixnum(2)
            }
        }

        let prc = MRValue::prc(mrb, mrb_proc_new_cfunc(mrb, job));

        mrb_funcall_with_block(mrb, MRValue::fixnum(5), mrb_intern_cstr(mrb, "times\0".as_ptr()), 0, ptr::null() as *const MRValue, prc);

        mrb_close(mrb);
    }
}

#[test]
fn test_nil() {
    unsafe {
        let mrb = mrb_open();

        let nil = MRValue::nil();
        let result = mrb_funcall(mrb, nil, "to_s\0".as_ptr(), 0);

        assert_eq!(result.to_str(mrb).unwrap(), "");

        mrb_close(mrb);
    }
}

#[test]
fn test_bool_true() {
    unsafe {
        let bool_true = MRValue::bool(true);
        assert_eq!(bool_true.to_bool().unwrap(), true);
    }
}

#[test]
fn test_bool_false() {
    unsafe {
        let bool_false = MRValue::bool(false);
        assert_eq!(bool_false.to_bool().unwrap(), false);
    }
}

#[test]
fn test_fixnum() {
    unsafe {
        let number = MRValue::fixnum(-1291657);
        assert_eq!(number.to_i32().unwrap(), -1291657);
    }
}

#[test]
fn test_float() {
    unsafe {
        let mrb = mrb_open();

        let number = MRValue::float(mrb, -1291657.37);
        assert_eq!(number.to_f64().unwrap(), -1291657.37);

        mrb_close(mrb);
    }
}

#[test]
fn test_string() {
    unsafe {
        let mrb = mrb_open();

        let string_value = MRValue::str(mrb, "qwerty\0");
        assert_eq!(string_value.to_str(mrb).unwrap(), "qwerty");

        mrb_close(mrb);
    }
}

#[test]
fn test_proc() {
    unsafe {
        let mrb = mrb_open();
        let context = mrbc_context_new(mrb);

        let code = "1 + 1\0".as_ptr();
        let parser = mrb_parse_string(mrb, code, context);
        let prc = mrb_generate_code(mrb, parser);

        let result = mrb_run(mrb, MRValue::prc(mrb, prc).to_prc().unwrap(), mrb_top_self(mrb));

        assert_eq!(result.to_i32().unwrap(), 2);

        mrb_close(mrb);
    }
}

#[test]
fn test_object() {
    unsafe {
        let mrb = mrb_open();

        #[derive(Clone, Copy, Debug, PartialEq)]
        struct Container {
            value: i32
        }

        let container = Container { value: 42 };
        let obj = MRValue::obj::<Container>(mrb, &container);

        assert_eq!(obj.to_obj::<Container>().unwrap(), container);

        mrb_close(mrb);
    }
}
<|endoftext|>


<commit_before>//
//
//
use _common::{Option,Some,None};
use core::ptr::PtrExt;
use _common::Send;
use core::ops::FnOnce;
use lib::mem::Box;

pub use self::queue::Queue;
pub use self::vec_map::VecMap;
pub use self::vec::Vec;
pub use self::string::String;

pub mod thunk;

//pub mod clone;

pub mod mem;
#[macro_use]
pub mod queue;
pub mod vec;
pub mod string;

pub mod vec_map;

pub mod num
{
	use core::num::Int;
	pub fn round_up<T: Int>(val: T, target: T) -> T
	{
		return (val + target - Int::one()) / target * target;
	}
}

pub mod collections
{
	pub trait MutableSeq<T>
	{
		fn push(&mut self, t: T);
		fn pop(&mut self) -> ::core::option::Option<T>;
	}
}

//pub struct LazyStatic<T>(pub Option<Box<T>>);
pub struct LazyStatic<T>(pub Option<T>);

impl<T> LazyStatic<T>
{
	pub fn prep<Fcn: FnOnce()->T>(&mut self, fcn: Fcn) {
		if self.0.is_none() {
			self.0 = Some(fcn());
		}
	}

	/// A fully unsafe prep function that is only valid to call when you _know_ that no races will occur
	pub unsafe fn prep_unsafe<Fcn: FnOnce()->T>(&self, fcn: Fcn) {
		assert!( self.0.is_none() );
		let mut_self: &mut LazyStatic<T> = ::core::mem::transmute(self);
		log_debug!("prep_unsafe {:p}", mut_self);
		mut_self.prep(fcn)
	}
}
impl<T> ::core::ops::Deref for LazyStatic<T>
{
	type Target = T;
	fn deref(&self) -> &T {
		&*self.0.as_ref().expect("Dereferencing LazyStatic without initialising")
	}
}
impl<T> ::core::ops::DerefMut for LazyStatic<T>
{
	fn deref_mut(&mut self) -> &mut T {
		&mut *self.0.as_mut().expect("Dereferencing LazyStatic without initialising")
	}
}

/// An equivalemnt of Option<*const T> which cannot be NULL
pub struct OptPtr<T>(pub *const T);
unsafe impl<T: Send> Send for OptPtr<T> {}
/// An equivalemnt of Option<*mut T> which cannot be NULL
pub struct OptMutPtr<T>(pub *mut T);
unsafe impl<T: Send> Send for OptMutPtr<T> {}

impl<T> OptPtr<T>
{
	pub fn is_none(&self) -> bool {
		self.0.is_null()
	}
	pub fn is_some(&self) -> bool {
		!self.0.is_null()
	}
	pub fn unwrap(&self) -> *const T {
		assert!( !self.0.is_null() );
		self.0
	}
	pub unsafe fn as_ref(&self) -> Option<&T> {
		if (self.0).is_null() {
			None
		}
		else {
			Some(&*self.0)
		}
	}
	pub unsafe fn as_mut(&self) -> OptMutPtr<T> {
		::core::mem::transmute(self)
	}
	/// This is HIGHLY unsafe
	pub unsafe fn as_mut_ref(&self) -> Option<&mut T> {
		::core::mem::transmute(self.as_ref())
	}
}

impl<T> OptMutPtr<T>
{
	pub fn is_none(&self) -> bool {
		self.0.is_null()
	}
	pub fn is_some(&self) -> bool {
		!self.0.is_null()
	}
	pub fn unwrap(&self) -> *mut T {
		assert!( !self.0.is_null() );
		self.0
	}
	pub unsafe fn as_ref(&self) -> Option<&mut T> {
		if (self.0).is_null() {
			None
		}
		else {
			Some(&mut *self.0)
		}
	}
}

pub trait UintBits
{
	fn bit(&self, idx: u8) -> Self;
	fn bits(&self, idx: u8, idx2: u8) -> Self;
}

impl UintBits for u16 {
	fn bit(&self, idx: u8) -> u16 { (*self >> idx as usize) & 1 }
	fn bits(&self, idx: u8, idx2: u8) -> u16 {
		(*self >> idx as usize) & ((1 << (idx2 - idx) as usize)-1)
	}
}

// vim: ft=rust

<commit_msg>Minor tweaks to RawString prining<commit_after>//
//
//
use _common::{Option,Some,None};
use core::ptr::PtrExt;
use _common::Send;
use core::ops::FnOnce;
use lib::mem::Box;

pub use self::queue::Queue;
pub use self::vec_map::VecMap;
pub use self::vec::Vec;
pub use self::string::String;

pub mod thunk;

//pub mod clone;

pub mod mem;
#[macro_use]
pub mod queue;
pub mod vec;
pub mod string;

pub mod vec_map;

pub mod num
{
	use core::num::Int;
	pub fn round_up<T: Int>(val: T, target: T) -> T
	{
		return (val + target - Int::one()) / target * target;
	}
}

pub mod collections
{
	pub trait MutableSeq<T>
	{
		fn push(&mut self, t: T);
		fn pop(&mut self) -> ::core::option::Option<T>;
	}
}

//pub struct LazyStatic<T>(pub Option<Box<T>>);
pub struct LazyStatic<T>(pub Option<T>);

impl<T> LazyStatic<T>
{
	pub fn prep<Fcn: FnOnce()->T>(&mut self, fcn: Fcn) {
		if self.0.is_none() {
			self.0 = Some(fcn());
		}
	}

	/// A fully unsafe prep function that is only valid to call when you _know_ that no races will occur
	pub unsafe fn prep_unsafe<Fcn: FnOnce()->T>(&self, fcn: Fcn) {
		assert!( self.0.is_none() );
		let mut_self: &mut LazyStatic<T> = ::core::mem::transmute(self);
		log_debug!("prep_unsafe {:p}", mut_self);
		mut_self.prep(fcn)
	}
}
impl<T> ::core::ops::Deref for LazyStatic<T>
{
	type Target = T;
	fn deref(&self) -> &T {
		&*self.0.as_ref().expect("Dereferencing LazyStatic without initialising")
	}
}
impl<T> ::core::ops::DerefMut for LazyStatic<T>
{
	fn deref_mut(&mut self) -> &mut T {
		&mut *self.0.as_mut().expect("Dereferencing LazyStatic without initialising")
	}
}

/// An equivalemnt of Option<*const T> which cannot be NULL
pub struct OptPtr<T>(pub *const T);
unsafe impl<T: Send> Send for OptPtr<T> {}
/// An equivalemnt of Option<*mut T> which cannot be NULL
pub struct OptMutPtr<T>(pub *mut T);
unsafe impl<T: Send> Send for OptMutPtr<T> {}

impl<T> OptPtr<T>
{
	pub fn is_none(&self) -> bool {
		self.0.is_null()
	}
	pub fn is_some(&self) -> bool {
		!self.0.is_null()
	}
	pub fn unwrap(&self) -> *const T {
		assert!( !self.0.is_null() );
		self.0
	}
	pub unsafe fn as_ref(&self) -> Option<&T> {
		if (self.0).is_null() {
			None
		}
		else {
			Some(&*self.0)
		}
	}
	pub unsafe fn as_mut(&self) -> OptMutPtr<T> {
		::core::mem::transmute(self)
	}
	/// This is HIGHLY unsafe
	pub unsafe fn as_mut_ref(&self) -> Option<&mut T> {
		::core::mem::transmute(self.as_ref())
	}
}

impl<T> OptMutPtr<T>
{
	pub fn is_none(&self) -> bool {
		self.0.is_null()
	}
	pub fn is_some(&self) -> bool {
		!self.0.is_null()
	}
	pub fn unwrap(&self) -> *mut T {
		assert!( !self.0.is_null() );
		self.0
	}
	pub unsafe fn as_ref(&self) -> Option<&mut T> {
		if (self.0).is_null() {
			None
		}
		else {
			Some(&mut *self.0)
		}
	}
}

pub trait UintBits
{
	fn bit(&self, idx: u8) -> Self;
	fn bits(&self, idx: u8, idx2: u8) -> Self;
}

impl UintBits for u16 {
	fn bit(&self, idx: u8) -> u16 { (*self >> idx as usize) & 1 }
	fn bits(&self, idx: u8, idx2: u8) -> u16 {
		(*self >> idx as usize) & ((1 << (idx2 - idx) as usize)-1)
	}
}

/// Printing helper for raw strings
pub struct RawString<'a>(pub &'a [u8]);

impl<'a> ::core::fmt::Debug for RawString<'a>
{
	fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result
	{
		try!(write!(f, "b\""));
		for &b in self.0
		{
			match b
			{
			b'\\' => try!(write!(f, "\\\\")),
			b'\n' => try!(write!(f, "\\n")),
			b'\r' => try!(write!(f, "\\r")),
			b'"' => try!(write!(f, "\\\"")),
			b'\0' => try!(write!(f, "\\0")),
			// ASCII printable characters
			32...127 => try!(write!(f, "{}", b as char)),
			_ => try!(write!(f, "\\x{:02x}", b)),
			}
		}
		try!(write!(f, "\""));
		::core::result::Result::Ok( () )
	}
}

// vim: ft=rust

<|endoftext|>


<commit_before>//! Wrapper for wlr_seat. For more information about what a seat is, please
//! consult the Wayland documentation ([libinput docs](https://wayland.freedesktop.org/libinput/doc/latest/seats.html), [wayland docs](https://wayland.freedesktop.org/docs/html/apa.html#protocol-spec-wl_seat))

use std::time::Duration;

use wlroots_sys::{wlr_axis_orientation, wlr_seat, wlr_seat_client, wlr_seat_create,
                  wlr_seat_destroy, wlr_seat_keyboard_clear_focus, wlr_seat_keyboard_end_grab,
                  wlr_seat_keyboard_enter, wlr_seat_keyboard_has_grab,
                  wlr_seat_keyboard_notify_enter, wlr_seat_keyboard_notify_key,
                  wlr_seat_keyboard_notify_modifiers, wlr_seat_keyboard_send_key,
                  wlr_seat_keyboard_send_modifiers, wlr_seat_keyboard_start_grab,
                  wlr_seat_pointer_clear_focus, wlr_seat_pointer_end_grab, wlr_seat_pointer_enter,
                  wlr_seat_pointer_has_grab, wlr_seat_pointer_notify_axis,
                  wlr_seat_pointer_notify_button, wlr_seat_pointer_notify_enter,
                  wlr_seat_pointer_notify_motion, wlr_seat_pointer_send_axis,
                  wlr_seat_pointer_send_button, wlr_seat_pointer_send_motion,
                  wlr_seat_pointer_start_grab, wlr_seat_pointer_surface_has_focus,
                  wlr_seat_set_capabilities, wlr_seat_set_keyboard, wlr_seat_set_name,
                  wlr_seat_touch_end_grab, wlr_seat_touch_has_grab, wlr_seat_touch_notify_down,
                  wlr_seat_touch_notify_motion, wlr_seat_touch_notify_up,
                  wlr_seat_touch_num_points, wlr_seat_touch_point_clear_focus,
                  wlr_seat_touch_point_focus, wlr_seat_touch_send_down,
                  wlr_seat_touch_send_motion, wlr_seat_touch_send_up, wlr_seat_touch_start_grab,
                  wlr_touch_point};
use wlroots_sys::wayland_server::protocol::wl_seat::Capability;

use compositor::Compositor;
use utils::{c_to_rust_string, safe_as_cstring};

use super::grab::{KeyboardGrab, PointerGrab, TouchGrab};
use types::surface::Surface;

/// A wrapper around `wlr_seat`.
pub struct Seat {
    seat: *mut wlr_seat
}

impl Seat {
    /// Allocates a new `wlr_seat` and adds a wl_seat global to the display.
    pub fn create(compositor: &mut Compositor, name: String) -> Option<Self> {
        unsafe {
            let name = safe_as_cstring(name);
            let seat = wlr_seat_create(compositor.display() as _, name.as_ptr());
            if seat.is_null() {
                None
            } else {
                Some(Seat { seat })
            }
        }
    }

    /// Get the name of the seat.
    pub fn name(&self) -> Option<String> {
        unsafe {
            let name_ptr = (*self.seat).name;
            if name_ptr.is_null() {
                return None
            }
            c_to_rust_string(name_ptr)
        }
    }

    /// Updates the name of this seat.
    /// Will automatically send it to all clients.
    pub fn set_name(&mut self, name: String) {
        let name = safe_as_cstring(name);
        unsafe {
            wlr_seat_set_name(self.seat, name.as_ptr());
        }
    }

    /// Gets the capabilities of this seat.
    pub fn capabilities(&self) -> Capability {
        unsafe {
            Capability::from_raw((*self.seat).capabilities).expect("Invalid capabilities")
        }
    }

    /// Updates the capabilities available on this seat.
    /// Will automatically send it to all clients.
    pub fn set_capabilities(&mut self, capabilities: Capability) {
        unsafe { wlr_seat_set_capabilities(self.seat, capabilities.bits()) }
    }

    /// Determines if the surface has pointer focus.
    pub fn pointer_surface_has_focus(&mut self, surface: Surface) -> bool {
        unsafe { wlr_seat_pointer_surface_has_focus(self.seat, surface.as_ptr()) }
    }

    // Sends a pointer enter event to the given surface and considers it to be
    // the focused surface for the pointer.
    //
    // This will send a leave event to the last surface that was entered.
    //
    // Coordinates for the enter event are surface-local.
    //
    // Compositor should use `Seat::notify_enter` to
    // change pointer focus to respect pointer grabs.
    pub fn pointer_enter(&mut self, surface: Surface, sx: f64, sy: f64) {
        unsafe {
            wlr_seat_pointer_enter(self.seat, surface.as_ptr(), sx, sy);
        }
    }

    /// Clears the focused surface for the pointer and leaves all entered
    /// surfaces.
    pub fn clear_focus(&mut self) {
        unsafe { wlr_seat_pointer_clear_focus(self.seat) }
    }

    /// Sends a motion event to the surface with pointer focus.
    ///
    /// Coordinates for the motion event are surface-local.
    ///
    /// Compositors should use `Seat::notify_motion` to
    /// send motion events to the respect pointer grabs.
    pub fn send_motion(&mut self, time: Duration, sx: f64, sy: f64) {
        let seconds_delta = time.as_secs() as u32;
        let nano_delta = time.subsec_nanos();
        let ms = (seconds_delta * 1000) + nano_delta / 1000000;
        unsafe {
            // TODO FIXME what kind of time? ms? s?
            // I'm just guessing it's ms, there's no documentation on this.
            wlr_seat_pointer_send_motion(self.seat, ms, sx, sy)
        }
    }

    // TODO Button and State should probably be wrapped in some sort of type...

    /// Send a button event to the surface with pointer focus.
    ///
    /// Coordinates for the button event are surface-local.
    ///
    /// Returns the serial.
    ///
    /// Compositors should use `Seat::notify_button` to
    /// send button events to respect pointer grabs.
    pub fn send_button(&mut self, time: Duration, button: u32, state: u32) -> u32 {
        let seconds_delta = time.as_secs() as u32;
        let nano_delta = time.subsec_nanos();
        let ms = (seconds_delta * 1000) + nano_delta / 1000000;
        unsafe { wlr_seat_pointer_send_button(self.seat, ms, button, state) }
    }

    /// Send an axis event to the surface with pointer focus.
    ///
    /// Compositors should use `Seat::notify_axis` to
    /// send axis events to respect pointer grabs.
    pub fn send_axis(&mut self, time: Duration, orientation: wlr_axis_orientation, value: f64) {
        let seconds_delta = time.as_secs() as u32;
        let nano_delta = time.subsec_nanos();
        let ms = (seconds_delta * 1000) + nano_delta / 1000000;
        unsafe {
            wlr_seat_pointer_send_axis(self.seat, ms, orientation, value);
        }
    }

    /// Start a grab of the pointer of this seat. The grabber is responsible for
    /// handling all pointer events until the grab ends.
    pub fn pointer_start_grab(&mut self, grab: PointerGrab) {
        unsafe { wlr_seat_pointer_start_grab(self.seat, grab.as_ptr()) }
    }

    /// End the grab of the pointer of this seat. This reverts the grab back to the
    /// default grab for the pointer.
    pub fn pointer_end_grab(&mut self) {
        unsafe { wlr_seat_pointer_end_grab(self.seat) }
    }

    /// Whether or not the pointer has a grab other than the default grab.
    pub fn pointer_has_grab(&self) -> bool {
        unsafe { wlr_seat_pointer_has_grab(self.seat) }
    }

    /// Start a grab of the keyboard of this seat. The grabber is responsible for
    /// handling all keyboard events until the grab ends.
    pub fn keyboard_start_grab(&mut self, grab: KeyboardGrab) {
        unsafe { wlr_seat_keyboard_start_grab(self.seat, grab.as_ptr()) }
    }

    /// End the grab of the keyboard of this seat. This reverts the grab back to the
    /// default grab for the keyboard.
    pub fn keyboard_end_grab(&mut self) {
        unsafe { wlr_seat_keyboard_end_grab(self.seat) }
    }

    /// Whether or not the keyboard has a grab other than the default grab
    pub fn keyboard_has_grab(&self) -> bool {
        unsafe { wlr_seat_keyboard_has_grab(self.seat) }
    }

    /// Start a grab of the touch device of this seat. The grabber is responsible for
    /// handling all touch events until the grab ends.
    pub fn touch_start_grab(&mut self, grab: TouchGrab) {
        unsafe { wlr_seat_touch_start_grab(self.seat, grab.as_ptr()) }
    }

    /// End the grab of the touch device of this seat. This reverts the grab back to
    /// the default grab for the touch device.
    pub fn touch_end_grab(&mut self) {
        unsafe { wlr_seat_touch_end_grab(self.seat) }
    }

    /// Whether or not the seat has a touch grab other than the default grab.
    pub fn touch_has_grab(&self) -> bool {
        unsafe { wlr_seat_touch_has_grab(self.seat) }
    }

    // TODO notify and some other specific input misc functions

    pub unsafe fn to_ptr(&self) -> *mut wlr_seat {
        self.seat
    }
}

impl Drop for Seat {
    fn drop(&mut self) {
        unsafe { wlr_seat_destroy(self.seat) }
    }
}
<commit_msg>Added {pointer,keyboard}_clear_focus<commit_after>//! Wrapper for wlr_seat. For more information about what a seat is, please
//! consult the Wayland documentation ([libinput docs](https://wayland.freedesktop.org/libinput/doc/latest/seats.html), [wayland docs](https://wayland.freedesktop.org/docs/html/apa.html#protocol-spec-wl_seat))

use std::time::Duration;

use wlroots_sys::{wlr_axis_orientation, wlr_seat, wlr_seat_client, wlr_seat_create,
                  wlr_seat_destroy, wlr_seat_keyboard_clear_focus, wlr_seat_keyboard_end_grab,
                  wlr_seat_keyboard_enter, wlr_seat_keyboard_has_grab,
                  wlr_seat_keyboard_notify_enter, wlr_seat_keyboard_notify_key,
                  wlr_seat_keyboard_notify_modifiers, wlr_seat_keyboard_send_key,
                  wlr_seat_keyboard_send_modifiers, wlr_seat_keyboard_start_grab,
                  wlr_seat_pointer_clear_focus, wlr_seat_pointer_end_grab, wlr_seat_pointer_enter,
                  wlr_seat_pointer_has_grab, wlr_seat_pointer_notify_axis,
                  wlr_seat_pointer_notify_button, wlr_seat_pointer_notify_enter,
                  wlr_seat_pointer_notify_motion, wlr_seat_pointer_send_axis,
                  wlr_seat_pointer_send_button, wlr_seat_pointer_send_motion,
                  wlr_seat_pointer_start_grab, wlr_seat_pointer_surface_has_focus,
                  wlr_seat_set_capabilities, wlr_seat_set_keyboard, wlr_seat_set_name,
                  wlr_seat_touch_end_grab, wlr_seat_touch_has_grab, wlr_seat_touch_notify_down,
                  wlr_seat_touch_notify_motion, wlr_seat_touch_notify_up,
                  wlr_seat_touch_num_points, wlr_seat_touch_point_clear_focus,
                  wlr_seat_touch_point_focus, wlr_seat_touch_send_down,
                  wlr_seat_touch_send_motion, wlr_seat_touch_send_up, wlr_seat_touch_start_grab,
                  wlr_touch_point};
use wlroots_sys::wayland_server::protocol::wl_seat::Capability;

use compositor::Compositor;
use utils::{c_to_rust_string, safe_as_cstring};

use super::grab::{KeyboardGrab, PointerGrab, TouchGrab};
use types::surface::Surface;

/// A wrapper around `wlr_seat`.
pub struct Seat {
    seat: *mut wlr_seat
}

impl Seat {
    /// Allocates a new `wlr_seat` and adds a wl_seat global to the display.
    pub fn create(compositor: &mut Compositor, name: String) -> Option<Self> {
        unsafe {
            let name = safe_as_cstring(name);
            let seat = wlr_seat_create(compositor.display() as _, name.as_ptr());
            if seat.is_null() {
                None
            } else {
                Some(Seat { seat })
            }
        }
    }

    /// Get the name of the seat.
    pub fn name(&self) -> Option<String> {
        unsafe {
            let name_ptr = (*self.seat).name;
            if name_ptr.is_null() {
                return None
            }
            c_to_rust_string(name_ptr)
        }
    }

    /// Updates the name of this seat.
    /// Will automatically send it to all clients.
    pub fn set_name(&mut self, name: String) {
        let name = safe_as_cstring(name);
        unsafe {
            wlr_seat_set_name(self.seat, name.as_ptr());
        }
    }

    /// Gets the capabilities of this seat.
    pub fn capabilities(&self) -> Capability {
        unsafe {
            Capability::from_raw((*self.seat).capabilities).expect("Invalid capabilities")
        }
    }

    /// Updates the capabilities available on this seat.
    /// Will automatically send it to all clients.
    pub fn set_capabilities(&mut self, capabilities: Capability) {
        unsafe { wlr_seat_set_capabilities(self.seat, capabilities.bits()) }
    }

    /// Determines if the surface has pointer focus.
    pub fn pointer_surface_has_focus(&mut self, surface: Surface) -> bool {
        unsafe { wlr_seat_pointer_surface_has_focus(self.seat, surface.as_ptr()) }
    }

    // Sends a pointer enter event to the given surface and considers it to be
    // the focused surface for the pointer.
    //
    // This will send a leave event to the last surface that was entered.
    //
    // Coordinates for the enter event are surface-local.
    //
    // Compositor should use `Seat::notify_enter` to
    // change pointer focus to respect pointer grabs.
    pub fn pointer_enter(&mut self, surface: Surface, sx: f64, sy: f64) {
        unsafe {
            wlr_seat_pointer_enter(self.seat, surface.as_ptr(), sx, sy);
        }
    }

    /// Clears the focused surface for the pointer and leaves all entered
    /// surfaces.
    pub fn clear_focus(&mut self) {
        unsafe { wlr_seat_pointer_clear_focus(self.seat) }
    }

    /// Sends a motion event to the surface with pointer focus.
    ///
    /// Coordinates for the motion event are surface-local.
    ///
    /// Compositors should use `Seat::notify_motion` to
    /// send motion events to the respect pointer grabs.
    pub fn send_motion(&mut self, time: Duration, sx: f64, sy: f64) {
        let seconds_delta = time.as_secs() as u32;
        let nano_delta = time.subsec_nanos();
        let ms = (seconds_delta * 1000) + nano_delta / 1000000;
        unsafe {
            // TODO FIXME what kind of time? ms? s?
            // I'm just guessing it's ms, there's no documentation on this.
            wlr_seat_pointer_send_motion(self.seat, ms, sx, sy)
        }
    }

    // TODO Button and State should probably be wrapped in some sort of type...

    /// Send a button event to the surface with pointer focus.
    ///
    /// Coordinates for the button event are surface-local.
    ///
    /// Returns the serial.
    ///
    /// Compositors should use `Seat::notify_button` to
    /// send button events to respect pointer grabs.
    pub fn send_button(&mut self, time: Duration, button: u32, state: u32) -> u32 {
        let seconds_delta = time.as_secs() as u32;
        let nano_delta = time.subsec_nanos();
        let ms = (seconds_delta * 1000) + nano_delta / 1000000;
        unsafe { wlr_seat_pointer_send_button(self.seat, ms, button, state) }
    }

    /// Send an axis event to the surface with pointer focus.
    ///
    /// Compositors should use `Seat::notify_axis` to
    /// send axis events to respect pointer grabs.
    pub fn send_axis(&mut self, time: Duration, orientation: wlr_axis_orientation, value: f64) {
        let seconds_delta = time.as_secs() as u32;
        let nano_delta = time.subsec_nanos();
        let ms = (seconds_delta * 1000) + nano_delta / 1000000;
        unsafe {
            wlr_seat_pointer_send_axis(self.seat, ms, orientation, value);
        }
    }

    /// Start a grab of the pointer of this seat. The grabber is responsible for
    /// handling all pointer events until the grab ends.
    pub fn pointer_start_grab(&mut self, grab: PointerGrab) {
        unsafe { wlr_seat_pointer_start_grab(self.seat, grab.as_ptr()) }
    }

    /// End the grab of the pointer of this seat. This reverts the grab back to the
    /// default grab for the pointer.
    pub fn pointer_end_grab(&mut self) {
        unsafe { wlr_seat_pointer_end_grab(self.seat) }
    }

    /// Whether or not the pointer has a grab other than the default grab.
    pub fn pointer_has_grab(&self) -> bool {
        unsafe { wlr_seat_pointer_has_grab(self.seat) }
    }

    /// Clear the focused surface for the pointer and leave all entered
    /// surfaces.
    pub fn pointer_clear_focus(&mut self) {
        unsafe { wlr_seat_pointer_clear_focus(self.seat) }
    }

    /// Start a grab of the keyboard of this seat. The grabber is responsible for
    /// handling all keyboard events until the grab ends.
    pub fn keyboard_start_grab(&mut self, grab: KeyboardGrab) {
        unsafe { wlr_seat_keyboard_start_grab(self.seat, grab.as_ptr()) }
    }

    /// End the grab of the keyboard of this seat. This reverts the grab back to the
    /// default grab for the keyboard.
    pub fn keyboard_end_grab(&mut self) {
        unsafe { wlr_seat_keyboard_end_grab(self.seat) }
    }

    /// Whether or not the keyboard has a grab other than the default grab
    pub fn keyboard_has_grab(&self) -> bool {
        unsafe { wlr_seat_keyboard_has_grab(self.seat) }
    }

    /// Clear the focused surface for the keyboard and leave all entered
    /// surfaces.
    pub fn keyboard_clear_focus(&mut self) {
        unsafe { wlr_seat_keyboard_clear_focus(self.seat) }
    }

    /// Start a grab of the touch device of this seat. The grabber is responsible for
    /// handling all touch events until the grab ends.
    pub fn touch_start_grab(&mut self, grab: TouchGrab) {
        unsafe { wlr_seat_touch_start_grab(self.seat, grab.as_ptr()) }
    }

    /// End the grab of the touch device of this seat. This reverts the grab back to
    /// the default grab for the touch device.
    pub fn touch_end_grab(&mut self) {
        unsafe { wlr_seat_touch_end_grab(self.seat) }
    }

    /// Whether or not the seat has a touch grab other than the default grab.
    pub fn touch_has_grab(&self) -> bool {
        unsafe { wlr_seat_touch_has_grab(self.seat) }
    }

    // TODO notify and some other specific input misc functions

    pub unsafe fn to_ptr(&self) -> *mut wlr_seat {
        self.seat
    }
}

impl Drop for Seat {
    fn drop(&mut self) {
        unsafe { wlr_seat_destroy(self.seat) }
    }
}
<|endoftext|>


<commit_before>use time::precise_time_ns;

use std::sync::mpsc::{channel, Sender};
use std::thread::Thread;

use search;

use super::types::{Cmd, Response};
use super::state::{State, Mode};
use self::time_start::time_start;

mod go_param;
mod time_start;
mod pos;

pub fn process(state: &mut State, cmd: Cmd, output: &Sender<Response>) {
    match cmd {
        Cmd::Debug(val) => {
            state.is_debug = val;
            state.search_tx.as_ref().map(|tx| { let _ = tx.send(search::Cmd::Stop); } );
        },
        Cmd::IsReady => {
            // TODO implement IsReady
            unimplemented!();
        },
        Cmd::Register(ref param) => {
            // TODO register
            unimplemented!();
        },
        cmd => {
            match state.mode {
                Mode::Init => {
                    if cmd == Cmd::Uci {
                        // TODO print id/option/uciok
                        state.mode = Mode::Wait;
                        unimplemented!();
                    }
                },
                Mode::Wait => {
                    match cmd {
                        Cmd::SetOption(ref name, ref val_opt) => {
                            // TODO maybe initialize
                            // TODO set options
                            unimplemented!();
                        },
                        Cmd::UciNewGame => {
                            *state = State {
                                is_debug: state.is_debug,
                                mode: Mode::NewGame,
                                ucinewgame_support: true,
                                ..State::new()
                            };
                        },
                        Cmd::SetupPosition(pos, from_to_vec) => {
                            if state.ucinewgame_support {
                                pos::setup_same(&mut state.search_state, pos, from_to_vec);
                                state.mode = Mode::Ready;
                            } else {
                                process(state, Cmd::UciNewGame, output);
                                state.ucinewgame_support = false;
                                process(state, Cmd::SetupPosition(pos, from_to_vec), output);
                            }
                        },
                        _ => {},
                    }
                },
                Mode::NewGame => {
                    if let Cmd::SetupPosition(pos, from_to_vec) = cmd {
                        pos::setup_new(&mut state.search_state, pos, from_to_vec);
                        state.mode = Mode::Ready;
                    }
                },
                Mode::Ready => {
                    assert!(state.search_state.is_some());
                    if let Cmd::Go(param) = cmd {
                        go_param::setup(state, param);
                        let (search_tx, search_rx) = channel::<search::Cmd>();
                        let search_state = state.search_state.as_ref().unwrap().clone();
                        let output = output.clone();
                        let temp = Thread::scoped(move ||
                                                  search::start(search_state, search_rx, output));

                        state.search_tx = Some(search_tx);
                        state.search_guard = Some(temp);

                        if !state.search_state.as_ref().unwrap().param.ponder {
                            time_start(state);
                        }

                        state.mode = Mode::Search;
                    }
                },
                Mode::Search => {
                    assert!(state.search_state.is_some());
                    assert!(state.search_guard.is_some());
                    assert!(state.search_tx.is_some());
                    match cmd {
                        Cmd::PonderHit => {
                            if !state.search_state.as_ref().unwrap().param.ponder {
                                return;
                            }
                            let _ = state.search_tx.as_ref().unwrap().send(search::Cmd::PonderHit);
                            state.search_state.as_mut().unwrap().param.ponder = false;
                            state.start_move_time = Some(precise_time_ns());
                            time_start(state);
                        },
                        Cmd::Stop => {
                            let _ = state.search_tx.as_ref().unwrap().send(search::Cmd::Stop);
                            let _ = state.search_guard.take().unwrap().join();
                            state.search_tx = None;
                            state.start_search_time = None;
                            state.start_move_time = None;
                            state.time_data = None;
                            if let Some(time_kill_tx) = state.time_kill_tx.take() {
                                let _ = time_kill_tx.send(());
                            }
                            state.time_rx = None;
                            state.mode = Mode::Wait;
                        },
                        _ => {},
                    }
                },
            }
        },
    }
}
<commit_msg>Implement isready<commit_after>use time::precise_time_ns;

use std::sync::mpsc::{channel, Sender};
use std::thread::Thread;

use search;

use super::types::{Cmd, Response};
use super::state::{State, Mode};
use self::time_start::time_start;

mod go_param;
mod time_start;
mod pos;

pub fn process(state: &mut State, cmd: Cmd, output: &Sender<Response>) {
    match cmd {
        Cmd::Debug(val) => {
            state.is_debug = val;
            state.search_tx.as_ref().map(|tx| { let _ = tx.send(search::Cmd::Stop); } );
        },
        Cmd::IsReady => {
            let _ = output.send(Response::ReadyOk);
        },
        Cmd::Register(ref param) => {
            // TODO register
            unimplemented!();
        },
        cmd => {
            match state.mode {
                Mode::Init => {
                    if cmd == Cmd::Uci {
                        // TODO print id/option/uciok
                        state.mode = Mode::Wait;
                        unimplemented!();
                    }
                },
                Mode::Wait => {
                    match cmd {
                        Cmd::SetOption(ref name, ref val_opt) => {
                            // TODO maybe initialize
                            // TODO set options
                            unimplemented!();
                        },
                        Cmd::UciNewGame => {
                            *state = State {
                                is_debug: state.is_debug,
                                mode: Mode::NewGame,
                                ucinewgame_support: true,
                                ..State::new()
                            };
                        },
                        Cmd::SetupPosition(pos, from_to_vec) => {
                            if state.ucinewgame_support {
                                pos::setup_same(&mut state.search_state, pos, from_to_vec);
                                state.mode = Mode::Ready;
                            } else {
                                process(state, Cmd::UciNewGame, output);
                                state.ucinewgame_support = false;
                                process(state, Cmd::SetupPosition(pos, from_to_vec), output);
                            }
                        },
                        _ => {},
                    }
                },
                Mode::NewGame => {
                    if let Cmd::SetupPosition(pos, from_to_vec) = cmd {
                        pos::setup_new(&mut state.search_state, pos, from_to_vec);
                        state.mode = Mode::Ready;
                    }
                },
                Mode::Ready => {
                    assert!(state.search_state.is_some());
                    if let Cmd::Go(param) = cmd {
                        go_param::setup(state, param);
                        let (search_tx, search_rx) = channel::<search::Cmd>();
                        let search_state = state.search_state.as_ref().unwrap().clone();
                        let output = output.clone();
                        let temp = Thread::scoped(move ||
                                                  search::start(search_state, search_rx, output));

                        state.search_tx = Some(search_tx);
                        state.search_guard = Some(temp);

                        if !state.search_state.as_ref().unwrap().param.ponder {
                            time_start(state);
                        }

                        state.mode = Mode::Search;
                    }
                },
                Mode::Search => {
                    assert!(state.search_state.is_some());
                    assert!(state.search_guard.is_some());
                    assert!(state.search_tx.is_some());
                    match cmd {
                        Cmd::PonderHit => {
                            if !state.search_state.as_ref().unwrap().param.ponder {
                                return;
                            }
                            let _ = state.search_tx.as_ref().unwrap().send(search::Cmd::PonderHit);
                            state.search_state.as_mut().unwrap().param.ponder = false;
                            state.start_move_time = Some(precise_time_ns());
                            time_start(state);
                        },
                        Cmd::Stop => {
                            let _ = state.search_tx.as_ref().unwrap().send(search::Cmd::Stop);
                            let _ = state.search_guard.take().unwrap().join();
                            state.search_tx = None;
                            state.start_search_time = None;
                            state.start_move_time = None;
                            state.time_data = None;
                            if let Some(time_kill_tx) = state.time_kill_tx.take() {
                                let _ = time_kill_tx.send(());
                            }
                            state.time_rx = None;
                            state.mode = Mode::Wait;
                        },
                        _ => {},
                    }
                },
            }
        },
    }
}
<|endoftext|>