<commit_before>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::error::Error;
use std::fmt;
use std::str;

use nom::IResult;

use super::ast;
use {Message, MessagePart};

/// An error resulting from `parse`.
#[derive(Clone,Debug)]
pub enum ParseError {
    /// The message could not be parsed.
    NotImplemented,
}

impl Error for ParseError {
    fn description(&self) -> &str {
        match *self {
            ParseError::NotImplemented => "Not implemented.",
        }
    }
}

impl fmt::Display for ParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        self.description().fmt(f)
    }
}

/// Given a name, create a `SimpleFormat`.
fn mk_simple(name: &str) -> Box<MessagePart> {
    Box::new(ast::SimpleFormat::new(name))
}

/// This grabs the variable name from a format, which is
/// the first thing after the '{' and extends to the first
/// ',' or '}'.
///
/// '{name}' has a variable name of 'name'.
named!(variable_name <&str, &str>, is_not_s!(",}"));

/// A simple format has only a name, delimited by braces.
named!(simple_format <&str, Box<MessagePart> >,
    map!(
        delimited!(
            tag_s!("{"),
            variable_name,
            tag_s!("}")),
        mk_simple));

named!(plural_format <&str, Box<MessagePart> >,
    delimited!(
        tag_s!("{"),
        chain!(
            name: variable_name ~
            tag_s!(",") ~
            tag_s!("plural"),
            || Box::new(ast::SimpleFormat::new(name))),
        tag_s!("}")));

named!(select_format <&str, Box<MessagePart> >,
    delimited!(
        tag_s!("{"),
        chain!(
            name: variable_name ~
            tag_s!(",") ~
            tag_s!("select"),
            || Box::new(ast::SimpleFormat::new(name))),
        tag_s!("}")));

/// Plain text extends up through to the start of the next format
/// block.
named!(plain_text <&str, Box<MessagePart> >,
    map!(is_not_s!("{"), |text| Box::new(ast::PlainText::new(text))));

/// Message parts must be 1 of the various part types. And there must
/// be at least one of them for now.
named!(message_parts <&str, Vec<Box<MessagePart> > >,
    many1!(
        alt!(call!(simple_format) |
             call!(plural_format) |
             call!(select_format) |
             call!(plain_text))));

/// Given a set of `MessagePart`s, create a `Message`.
named!(pub message_parser <&str, Message>,
    map!(message_parts, Message::new));

/// Parse some text and hopefully return a [`Message`].
///
/// [`Message`]: ../struct.Message.html
pub fn parse(message: &str) -> Result<Message, ParseError> {
    match message_parser(message) {
        IResult::Error(_) |
        IResult::Incomplete(_) => Err(ParseError::NotImplemented),
        IResult::Done(_, m) => Ok(m),
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use {arg, Context};
    use nom::IResult;

    #[test]
    fn it_works() {
        let ctx = Context::default();
        match parse("{name} is from {city}.") {
            Ok(m) => {
                assert_eq!(ctx.format(&m, &arg("name", "Hendrik").arg("city", "Berlin")),
                           "Hendrik is from Berlin.");
            }
            Err(e) => panic!("Parse failed: {}", e),
        }
    }

    #[test]
    fn incomplete_fails() {
        match message_parser("{name") {
            IResult::Incomplete(_) => {}
            IResult::Error(e) => panic!("Expected incomplete failure: Got {}", e),
            IResult::Done(_, _) => panic!("Expected incomplete failure, but succeeded."),
        }
    }

    #[test]
    fn all_text_works() {
        match message_parser("Hello, world!") {
            IResult::Done(_, _) => {}
            _ => panic!("Expected successful parse."),
        }
    }

    #[test]
    fn plural_format_works() {
        match message_parser("{count,plural}") {
            IResult::Done(_, _) => {}
            _ => panic!("Expected successful parse."),
        }
    }

    #[test]
    fn select_format_works() {
        match message_parser("{type,select}") {
            IResult::Done(_, _) => {}
            _ => panic!("Expected successful parse."),
        }
    }
}
<commit_msg>Ignore whitespace when parsing.<commit_after>// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::error::Error;
use std::fmt;
use std::str;

use nom::{IResult, multispace};

use super::ast;
use {Message, MessagePart};

/// An error resulting from `parse`.
#[derive(Clone,Debug)]
pub enum ParseError {
    /// The message could not be parsed.
    NotImplemented,
}

impl Error for ParseError {
    fn description(&self) -> &str {
        match *self {
            ParseError::NotImplemented => "Not implemented.",
        }
    }
}

impl fmt::Display for ParseError {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        self.description().fmt(f)
    }
}

/// Given a name, create a `SimpleFormat`.
fn mk_simple(name: &str) -> Box<MessagePart> {
    Box::new(ast::SimpleFormat::new(name))
}

/// This grabs the variable name from a format, which is
/// the first thing after the '{' and extends to the first
/// ',' or '}'.
///
/// '{name}' has a variable name of 'name'.
named!(variable_name <&str, &str>, is_not_s!(",}"));

/// A simple format has only a name, delimited by braces.
named!(simple_format <&str, Box<MessagePart> >,
    map!(
        delimited!(
            tag_s!("{"),
            variable_name,
            tag_s!("}")),
        mk_simple));

named!(plural_format <&str, Box<MessagePart> >,
    delimited!(
        tag_s!("{"),
        chain!(
            name: variable_name ~
            tag_s!(",") ~ opt!(multispace) ~
            tag_s!("plural") ~ opt!(multispace),
            || Box::new(ast::SimpleFormat::new(name))),
        tag_s!("}")));

named!(select_format <&str, Box<MessagePart> >,
    delimited!(
        tag_s!("{"),
        chain!(
            name: variable_name ~
            tag_s!(",") ~ opt!(multispace) ~
            tag_s!("select") ~ opt!(multispace),
            || Box::new(ast::SimpleFormat::new(name))),
        tag_s!("}")));

/// Plain text extends up through to the start of the next format
/// block.
named!(plain_text <&str, Box<MessagePart> >,
    map!(is_not_s!("{"), |text| Box::new(ast::PlainText::new(text))));

/// Message parts must be 1 of the various part types. And there must
/// be at least one of them for now.
named!(message_parts <&str, Vec<Box<MessagePart> > >,
    many1!(
        alt!(call!(simple_format) |
             call!(plural_format) |
             call!(select_format) |
             call!(plain_text))));

/// Given a set of `MessagePart`s, create a `Message`.
named!(pub message_parser <&str, Message>,
    map!(message_parts, Message::new));

/// Parse some text and hopefully return a [`Message`].
///
/// [`Message`]: ../struct.Message.html
pub fn parse(message: &str) -> Result<Message, ParseError> {
    match message_parser(message) {
        IResult::Error(_) |
        IResult::Incomplete(_) => Err(ParseError::NotImplemented),
        IResult::Done(_, m) => Ok(m),
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use {arg, Context};
    use nom::IResult;

    #[test]
    fn it_works() {
        let ctx = Context::default();
        match parse("{name} is from {city}.") {
            Ok(m) => {
                assert_eq!(ctx.format(&m, &arg("name", "Hendrik").arg("city", "Berlin")),
                           "Hendrik is from Berlin.");
            }
            Err(e) => panic!("Parse failed: {}", e),
        }
    }

    #[test]
    fn incomplete_fails() {
        match message_parser("{name") {
            IResult::Incomplete(_) => {}
            IResult::Error(e) => panic!("Expected incomplete failure: Got {}", e),
            IResult::Done(_, _) => panic!("Expected incomplete failure, but succeeded."),
        }
    }

    #[test]
    fn all_text_works() {
        match message_parser("Hello, world!") {
            IResult::Done(_, _) => {}
            _ => panic!("Expected successful parse."),
        }
    }

    #[test]
    fn plural_format_works() {
        match message_parser("{count,plural}") {
            IResult::Done(_, _) => {}
            _ => panic!("Expected successful parse."),
        }
    }

    #[test]
    fn select_format_works() {
        match message_parser("{type,select}") {
            IResult::Done(_, _) => {}
            _ => panic!("Expected successful parse."),
        }
    }
}
<|endoftext|>


<commit_before>use std::io;

pub use self::posix::PosixInputHandler;

mod posix;

const CMD_PROMPT: &'static str = ">> ";

enum Key {
    Esc,
    Enter,
    Tab,

    Up,
    Down,
    Left,
    Right,
    Home,
    End,
    Insert,
    PgUp,
    PgDown,

    Backspace,
    Delete,

    Char(char),
    F(u32),

    Unknown,
}

pub enum InputCmd {
    None,
    Quit,
    Equation(String),
}

pub trait InputHandler {
    fn start(&mut self) -> io::Result<()>;
    fn stop(&mut self) -> io::Result<()>;
    fn handle_input(&mut self) -> InputCmd;
    fn print_prompt(&self);
}<commit_msg>Make the Key enum printable for debugging<commit_after>use std::io;

pub use self::posix::PosixInputHandler;

mod posix;

const CMD_PROMPT: &'static str = ">> ";

#[derive(Debug)]
enum Key {
    Esc,
    Enter,
    Tab,

    Up,
    Down,
    Left,
    Right,
    Home,
    End,
    Insert,
    PgUp,
    PgDown,

    Backspace,
    Delete,

    Char(char),
    F(u32),

    Unknown,
}

pub enum InputCmd {
    None,
    Quit,
    Equation(String),
}

pub trait InputHandler {
    fn start(&mut self) -> io::Result<()>;
    fn stop(&mut self) -> io::Result<()>;
    fn handle_input(&mut self) -> InputCmd;
    fn print_prompt(&self);
}<|endoftext|>


<commit_before>use super::connection::DBusConnection;
use super::error::DBusError;
use super::message::DBusMessage;
use super::value::{DBusSignature, DBusValue};

use std::cell::RefCell;
use std::collections::btree_map::{BTreeMap, Entry};
use std::rc::Rc;

type DBusMap<T> = BTreeMap<String, T>;

pub struct DBusArgument {
    name: String,
    signature: String,
}

pub struct DBusAnnotation {
    name: String,
    value: String,
}
type DBusAnnotations = Vec<DBusAnnotation>;

pub struct DBusErrorMessage {
    name: String,
    message: String,
}

pub type DBusMethodResult = Result<Vec<DBusValue>, DBusErrorMessage>;
pub type DBusMethodHandler = Box<FnMut(&mut DBusMessage) -> DBusMethodResult>;

pub struct DBusMethod {
    in_args: Vec<DBusArgument>,
    out_args: Vec<DBusArgument>,
    cb: DBusMethodHandler,
    anns: DBusAnnotations,
}

pub type DBusPropertyGetResult = Result<DBusValue, DBusErrorMessage>;
pub type DBusPropertySetResult = Result<(), DBusErrorMessage>;

pub trait DBusPropertyReadHandler {
    fn get(&self) -> DBusPropertyGetResult;
}

pub trait DBusPropertyWriteHandler {
    fn set(&self, &DBusValue) -> DBusPropertySetResult;
}

pub trait DBusPropertyReadWriteHandler {
    fn get(&self) -> DBusPropertyGetResult;
    fn set(&self, &DBusValue) -> DBusPropertySetResult;
}

enum PropertyAccess {
    RO(Box<DBusPropertyReadHandler>),
    RW(Box<DBusPropertyReadWriteHandler>),
    WO(Box<DBusPropertyWriteHandler>),
}

pub struct DBusProperty {
    signature: DBusSignature,
    access: PropertyAccess,
    anns: DBusAnnotations,
}

pub struct DBusSignal {
    args: Vec<DBusArgument>,
    anns: DBusAnnotations,
}

pub struct DBusInterface {
    methods: DBusMap<DBusMethod>,
    properties: DBusMap<DBusProperty>,
    signals: DBusMap<DBusSignal>,
}

type InterfaceMap = Rc<RefCell<DBusMap<DBusInterface>>>;

pub struct DBusInterfaceMap {
    map: InterfaceMap,
    finalized: bool,
}

impl DBusInterfaceMap {
    // Marked as mut for intent; Rc<> doesn't require it though.
    #[allow(unused_mut)]
    pub fn add_interface(mut self, name: &str, iface: DBusInterface) -> Result<DBusInterfaceMap, DBusError> {
        if self.finalized {
            return Err(DBusError::InterfaceMapFinalized(name.to_owned()));
        }

        {
            let mut map = self.map.borrow_mut();

            match map.entry(name.to_owned()) {
                Entry::Vacant(v)    => {
                    v.insert(iface);

                    Ok(())
                },
                Entry::Occupied(_)  => Err(DBusError::InterfaceAlreadyRegistered(name.to_owned())),
            }
        }.map(|_| self)
    }

    pub fn finalize(mut self) -> Result<DBusInterfaceMap, DBusError> {
        // TODO: Add core interfaces.

        self.finalized = true;
        Ok(self)
    }

    pub fn handle(&self, conn: &DBusConnection, msg: &mut DBusMessage) -> Option<Result<(), ()>> {
        msg.call_headers().and_then(|hdrs| {
            let iface_name = hdrs.interface;
            let method_name = hdrs.method;
            self.map.borrow_mut().get_mut(&iface_name).and_then(|iface| iface.methods.get_mut(&method_name)).map(|method| {
                // TODO: Verify input argument signature.

                let msg = match (method.cb)(msg) {
                    Ok(vals) => {
                        vals.iter().fold(msg.return_message(), |msg, val| {
                            msg.add_argument(val)
                        })
                    },
                    Err(err) => msg.error_message(&err.name)
                                   .add_argument(&err.message),
                };

                // TODO: Verify that the signature matches the return.

                conn.send(msg)
                    .map(|_| ())
                    .map_err(|_| ())
            })
        })
    }
}
<commit_msg>interface: add new method<commit_after>use super::connection::DBusConnection;
use super::error::DBusError;
use super::message::DBusMessage;
use super::value::{DBusSignature, DBusValue};

use std::cell::RefCell;
use std::collections::btree_map::{BTreeMap, Entry};
use std::rc::Rc;

type DBusMap<T> = BTreeMap<String, T>;

pub struct DBusArgument {
    name: String,
    signature: String,
}

pub struct DBusAnnotation {
    name: String,
    value: String,
}
type DBusAnnotations = Vec<DBusAnnotation>;

pub struct DBusErrorMessage {
    name: String,
    message: String,
}

pub type DBusMethodResult = Result<Vec<DBusValue>, DBusErrorMessage>;
pub type DBusMethodHandler = Box<FnMut(&mut DBusMessage) -> DBusMethodResult>;

pub struct DBusMethod {
    in_args: Vec<DBusArgument>,
    out_args: Vec<DBusArgument>,
    cb: DBusMethodHandler,
    anns: DBusAnnotations,
}

pub type DBusPropertyGetResult = Result<DBusValue, DBusErrorMessage>;
pub type DBusPropertySetResult = Result<(), DBusErrorMessage>;

pub trait DBusPropertyReadHandler {
    fn get(&self) -> DBusPropertyGetResult;
}

pub trait DBusPropertyWriteHandler {
    fn set(&self, &DBusValue) -> DBusPropertySetResult;
}

pub trait DBusPropertyReadWriteHandler {
    fn get(&self) -> DBusPropertyGetResult;
    fn set(&self, &DBusValue) -> DBusPropertySetResult;
}

enum PropertyAccess {
    RO(Box<DBusPropertyReadHandler>),
    RW(Box<DBusPropertyReadWriteHandler>),
    WO(Box<DBusPropertyWriteHandler>),
}

pub struct DBusProperty {
    signature: DBusSignature,
    access: PropertyAccess,
    anns: DBusAnnotations,
}

pub struct DBusSignal {
    args: Vec<DBusArgument>,
    anns: DBusAnnotations,
}

pub struct DBusInterface {
    methods: DBusMap<DBusMethod>,
    properties: DBusMap<DBusProperty>,
    signals: DBusMap<DBusSignal>,
}

type InterfaceMap = Rc<RefCell<DBusMap<DBusInterface>>>;

pub struct DBusInterfaceMap {
    map: InterfaceMap,
    finalized: bool,
}

impl DBusInterfaceMap {
    pub fn new() -> DBusInterfaceMap {
        DBusInterfaceMap {
            map: Rc::new(RefCell::new(DBusMap::new())),
            finalized: false,
        }
    }

    // Marked as mut for intent; Rc<> doesn't require it though.
    #[allow(unused_mut)]
    pub fn add_interface(mut self, name: &str, iface: DBusInterface) -> Result<DBusInterfaceMap, DBusError> {
        if self.finalized {
            return Err(DBusError::InterfaceMapFinalized(name.to_owned()));
        }

        {
            let mut map = self.map.borrow_mut();

            match map.entry(name.to_owned()) {
                Entry::Vacant(v)    => {
                    v.insert(iface);

                    Ok(())
                },
                Entry::Occupied(_)  => Err(DBusError::InterfaceAlreadyRegistered(name.to_owned())),
            }
        }.map(|_| self)
    }

    pub fn finalize(mut self) -> Result<DBusInterfaceMap, DBusError> {
        // TODO: Add core interfaces.

        self.finalized = true;
        Ok(self)
    }

    pub fn handle(&self, conn: &DBusConnection, msg: &mut DBusMessage) -> Option<Result<(), ()>> {
        msg.call_headers().and_then(|hdrs| {
            let iface_name = hdrs.interface;
            let method_name = hdrs.method;
            self.map.borrow_mut().get_mut(&iface_name).and_then(|iface| iface.methods.get_mut(&method_name)).map(|method| {
                // TODO: Verify input argument signature.

                let msg = match (method.cb)(msg) {
                    Ok(vals) => {
                        vals.iter().fold(msg.return_message(), |msg, val| {
                            msg.add_argument(val)
                        })
                    },
                    Err(err) => msg.error_message(&err.name)
                                   .add_argument(&err.message),
                };

                // TODO: Verify that the signature matches the return.

                conn.send(msg)
                    .map(|_| ())
                    .map_err(|_| ())
            })
        })
    }
}
<|endoftext|>


<commit_before>use std::ops::{Sub, Div};

#[derive(Copy, Clone)]
pub struct Point {
    x: f64,
    y: f64,
}

impl Point {
    pub fn new(x: f64, y: f64) -> Self {
        Point {
            x: x,
            y: y,
        }
    }

    fn cross(self, other: Point) -> f64 {
        return self.x*other.y - other.x*self.y;
    }

    fn dot(self, other: Point) -> f64 {
        return self.x*other.x + self.y*other.y;
    }
}

impl Sub<Point> for Point {
    type Output = Point;

    fn sub(self, other: Point) -> Self::Output {
        return Point{
            x: self.x - other.x,
            y: self.y - other.y,
        }
    }
}

impl Div<f64> for Point {
    type Output = Point;

    fn div(self, other: f64) -> Self::Output {
        return Point{
            x: self.x / other,
            y: self.y / other,
        }
    }
}

// Intersection of p, p+r and q, q+s
// For details, See: http://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect
// p + t r = q + u s
// t = ((q − p) × s) / (r × s)
// u = ((q − p) × r) / (r × s)

pub fn lines_intersect(l1: [f64; 4], l2: [f64; 4]) -> bool {
    let p = Point::new(l1[0], l1[1]);
    let q = Point::new(l2[0], l2[1]);
    let r = Point::new(l1[2] - l1[0], l1[3] - l1[1]);
    let s = Point::new(l2[2] - l2[0], l2[3] - l2[1]);

    //If r × s = 0 and (q − p) × r = 0, then the two lines are collinear.
    if r.cross(s) == 0.0 && (p - q).cross(r) == 0.0 {
        // If the interval between t0 and t1 intersects the interval [0, 1] then the line segments are collinear and overlapping; otherwise they are collinear and disjoint.
        // Note that if s and r point in opposite directions, then s · r < 0 and so the interval to be checked is [t1, t0] rather than [t0, t1].
        //t0 = (q − p) · r / (r · r)
        //t1 = (q + s − p) · r / (r · r) = t0 + s · r / (r · r)
        let t0 = (q - p).dot(r / r.dot(r));
        let t1 = t0 + s.dot(r / r.dot(r));
        return !(t0 < 0.0 && t1 < 0.0 || t0 > 1.0 && t1 > 1.0)
    }

    // If r × s = 0 and (q − p) × r ≠ 0, then the two lines are parallel and non-intersecting.
    if r.cross(s) == 0.0 {
        return false;
    }

    // t = (q − p) × s / (r × s)
    // u = (p − q) × r / (s × r)
    let t = (q - p).cross(s / (r.cross(s)));
    let u = (p - q).cross(r / (s.cross(r)));

    // If r × s ≠ 0 and 0 ≤ t ≤ 1 and 0 ≤ u ≤ 1, the two line segments meet at the point p + t r = q + u s.
    return 0.0 <= t && t <= 1.0 && 0.0 <= u && u <= 1.0;
}

#[cfg(test)]
#[test]
fn test_lines_intersect() {
    let line = [-1.0, -1.0, 1.0, 1.0];
    // Two lines intersect normally
    assert!(lines_intersect(line, [1.0, -1.0, -1.0, 1.0]));
    // Two lines don't intersect at all
    assert!(!lines_intersect(line, [-2.0, -2.0, -3.0, -3.0]));
    // Two lines are parallel and don't intersect
    assert!(!lines_intersect(line, [-1.0, 0.0, 1.0, 2.0]));
    // Two lines are co-linear and overlapping
    assert!(lines_intersect(line, [-1.5, -1.5, 0.5, 0.5]));
    assert!(lines_intersect(line, [0.5, 0.5, 1.5, 1.5]));
    // Two lines are co-linear and one contains the other
    assert!(lines_intersect(line, [-2.0, -2.0, 2.0, 2.0]));
    assert!(lines_intersect(line, [-0.5, -0.5, 0.5, 0.5]));
    // Two lines are co-linear and non-overlapping
    assert!(!lines_intersect(line, [-3.0, -3.0, -2.0, -2.0]));
    assert!(!lines_intersect(line, [2.0, 2.0, 3.0, 3.0]));
    // Two lines are the same
    assert!(lines_intersect(line, line));
    // Two lines intersect at one point
    assert!(lines_intersect(line, [1.0, 1.0, 2.0, 2.0]));
    assert!(lines_intersect(line, [1.0, 1.0, 1.0, 2.0]));
    // One line's point touches the other line
    assert!(lines_intersect(line, [0.0, 2.0, 2.0, 0.0]));
}

fn ray(point: Point) -> [f64; 4] {
    let Point{x, y} = point;
    return [-100000.0, y, x, y];
}

pub fn point_in<I: Iterator<Item=[f64; 4]>>(point: Point, edges: I) -> bool {
    let r = ray(point);
    return edges.fold(false, |inside, edge|
        inside ^ lines_intersect(r, edge)
    );
} <commit_msg>Added some tests for ray casting<commit_after>use std::ops::{Sub, Div};

#[derive(Copy, Clone)]
pub struct Point {
    x: f64,
    y: f64,
}

impl Point {
    pub fn new(x: f64, y: f64) -> Self {
        Point {
            x: x,
            y: y,
        }
    }

    fn cross(self, other: Point) -> f64 {
        return self.x*other.y - other.x*self.y;
    }

    fn dot(self, other: Point) -> f64 {
        return self.x*other.x + self.y*other.y;
    }
}

impl Sub<Point> for Point {
    type Output = Point;

    fn sub(self, other: Point) -> Self::Output {
        return Point{
            x: self.x - other.x,
            y: self.y - other.y,
        }
    }
}

impl Div<f64> for Point {
    type Output = Point;

    fn div(self, other: f64) -> Self::Output {
        return Point{
            x: self.x / other,
            y: self.y / other,
        }
    }
}

// Intersection of p, p+r and q, q+s
// For details, See: http://stackoverflow.com/questions/563198/how-do-you-detect-where-two-line-segments-intersect
// p + t r = q + u s
// t = ((q − p) × s) / (r × s)
// u = ((q − p) × r) / (r × s)

pub fn lines_intersect(l1: [f64; 4], l2: [f64; 4]) -> bool {
    let p = Point::new(l1[0], l1[1]);
    let q = Point::new(l2[0], l2[1]);
    let r = Point::new(l1[2] - l1[0], l1[3] - l1[1]);
    let s = Point::new(l2[2] - l2[0], l2[3] - l2[1]);

    //If r × s = 0 and (q − p) × r = 0, then the two lines are collinear.
    if r.cross(s) == 0.0 && (p - q).cross(r) == 0.0 {
        // If the interval between t0 and t1 intersects the interval [0, 1] then the line segments are collinear and overlapping; otherwise they are collinear and disjoint.
        // Note that if s and r point in opposite directions, then s · r < 0 and so the interval to be checked is [t1, t0] rather than [t0, t1].
        //t0 = (q − p) · r / (r · r)
        //t1 = (q + s − p) · r / (r · r) = t0 + s · r / (r · r)
        let t0 = (q - p).dot(r / r.dot(r));
        let t1 = t0 + s.dot(r / r.dot(r));
        return !(t0 < 0.0 && t1 < 0.0 || t0 > 1.0 && t1 > 1.0)
    }

    // If r × s = 0 and (q − p) × r ≠ 0, then the two lines are parallel and non-intersecting.
    if r.cross(s) == 0.0 {
        return false;
    }

    // t = (q − p) × s / (r × s)
    // u = (p − q) × r / (s × r)
    let t = (q - p).cross(s / (r.cross(s)));
    let u = (p - q).cross(r / (s.cross(r)));

    // If r × s ≠ 0 and 0 ≤ t ≤ 1 and 0 ≤ u ≤ 1, the two line segments meet at the point p + t r = q + u s.
    return 0.0 <= t && t <= 1.0 && 0.0 <= u && u <= 1.0;
}

#[cfg(test)]
#[test]
fn test_lines_intersect() {
    let line = [-1.0, -1.0, 1.0, 1.0];
    // Two lines intersect normally
    assert!(lines_intersect(line, [1.0, -1.0, -1.0, 1.0]));
    // Two lines don't intersect at all
    assert!(!lines_intersect(line, [-2.0, -2.0, -3.0, -3.0]));
    // Two lines are parallel and don't intersect
    assert!(!lines_intersect(line, [-1.0, 0.0, 1.0, 2.0]));
    // Two lines are co-linear and overlapping
    assert!(lines_intersect(line, [-1.5, -1.5, 0.5, 0.5]));
    assert!(lines_intersect(line, [0.5, 0.5, 1.5, 1.5]));
    // Two lines are co-linear and one contains the other
    assert!(lines_intersect(line, [-2.0, -2.0, 2.0, 2.0]));
    assert!(lines_intersect(line, [-0.5, -0.5, 0.5, 0.5]));
    // Two lines are co-linear and non-overlapping
    assert!(!lines_intersect(line, [-3.0, -3.0, -2.0, -2.0]));
    assert!(!lines_intersect(line, [2.0, 2.0, 3.0, 3.0]));
    // Two lines are the same
    assert!(lines_intersect(line, line));
    // Two lines intersect at one point
    assert!(lines_intersect(line, [1.0, 1.0, 2.0, 2.0]));
    assert!(lines_intersect(line, [1.0, 1.0, 1.0, 2.0]));
    // One line's point touches the other line
    assert!(lines_intersect(line, [0.0, 2.0, 2.0, 0.0]));
}

fn ray(point: Point) -> [f64; 4] {
    let Point{x, y} = point;
    return [-100000.0, y, x, y];
}

pub fn point_in<I: Iterator<Item=[f64; 4]>>(point: Point, edges: I) -> bool {
    let r = ray(point);
    return edges.fold(false, |inside, edge|
        inside ^ lines_intersect(r, edge)
    );
}

#[cfg(test)]
#[test]
fn test_point_in() {
    let box_points = vec![
        [-1.0, 0.0, 0.0, 1.0],
        [0.0, 1.0, 1.0, 0.0],
        [1.0, 0.0, 0.0, -1.0],
        [0.0, -1.0, -1.0, 0.0],
    ];
    let points = || box_points.iter().cloned();
    // Point outside the box
    assert!(!point_in(Point::new(-2.0, 0.0), points()));
    assert!(!point_in(Point::new(2.0, 0.0), points()));
    // Point inside the box
    assert!(point_in(Point::new(0.0, 0.0), points()));
    // Point touching the box
    assert!(point_in(Point::new(-1.0, 0.0), points()));
    assert!(point_in(Point::new(1.0, 0.0), points()));
    assert!(point_in(Point::new(-0.5, -0.5), points()));
}
<|endoftext|>


<commit_before>#![feature(core)]
#![feature(test)]

extern crate test;
extern crate wheel_timer;

use test::Bencher;

use wheel_timer::WheelTimer;

#[bench]
fn bench_wheel_timer_drain(b: &mut Bencher) {
  let max_interval = 20;
  let mut timer = WheelTimer::new(max_interval);

  b.iter(|| {
    // Fill
    for j in range(0us, 100) {
      timer.schedule(j%max_interval, j%max_interval);
    }

    // Drain
    for _ in range(0, 100) {
      timer.tick();
    }
  });
}

#[bench]
fn bench_wheel_timer_fill(b: &mut Bencher) {
  let max_interval = 20;
  let mut timer = WheelTimer::new(max_interval);
  let mut i = 0;

  b.iter(|| {
    timer.schedule(i%max_interval, i%max_interval);
    i = i + 1;
  });
}

#[bench]
fn bench_wheel_timer_fast(b: &mut Bencher) {
  let max_interval = 2;
  let mut timer = WheelTimer::new(max_interval);
  let mut i = 0;

  b.iter(|| {
    timer.schedule(i%max_interval, i%max_interval);
    timer.tick();
    i = i + 1;
  });
}
<commit_msg>Fixing benchmarks<commit_after>#![feature(test)]

extern crate test;
extern crate wheel_timer;

use test::Bencher;

use wheel_timer::WheelTimer;

#[bench]
fn bench_wheel_timer_drain(b: &mut Bencher) {
  let max_interval = 20;
  let mut timer = WheelTimer::new(max_interval);

  b.iter(|| {
    // Fill
    for j in 0..100 {
      timer.schedule(j%max_interval, j%max_interval);
    }

    // Drain
    for _ in 0..100 {
      timer.tick();
    }
  });
}

#[bench]
fn bench_wheel_timer_fill(b: &mut Bencher) {
  let max_interval = 20;
  let mut timer = WheelTimer::new(max_interval);
  let mut i = 0;

  b.iter(|| {
    timer.schedule(i%max_interval, i%max_interval);
    i = i + 1;
  });
}

#[bench]
fn bench_wheel_timer_fast(b: &mut Bencher) {
  let max_interval = 2;
  let mut timer = WheelTimer::new(max_interval);
  let mut i = 0;

  b.iter(|| {
    timer.schedule(i%max_interval, i%max_interval);
    timer.tick();
    i = i + 1;
  });
}
<|endoftext|>


<commit_before>#![allow(dead_code)] // not used on all platforms

use crate::collections::BTreeMap;
use crate::ptr;
use crate::sync::atomic::{AtomicUsize, Ordering};

pub type Key = usize;

type Dtor = unsafe extern fn(*mut u8);

static NEXT_KEY: AtomicUsize = AtomicUsize::new(0);

static mut KEYS: *mut BTreeMap<Key, Option<Dtor>> = ptr::null_mut();

#[thread_local]
static mut LOCALS: *mut BTreeMap<Key, *mut u8> = ptr::null_mut();

unsafe fn keys() -> &'static mut BTreeMap<Key, Option<Dtor>> {
    if KEYS == ptr::null_mut() {
        KEYS = Box::into_raw(Box::new(BTreeMap::new()));
    }
    &mut *KEYS
}

unsafe fn locals() -> &'static mut BTreeMap<Key, *mut u8> {
    if LOCALS == ptr::null_mut() {
        LOCALS = Box::into_raw(Box::new(BTreeMap::new()));
    }
    &mut *LOCALS
}

#[inline]
pub unsafe fn create(dtor: Option<Dtor>) -> Key {
    let key = NEXT_KEY.fetch_add(1, Ordering::SeqCst);
    keys().insert(key, dtor);
    key
}

#[inline]
pub unsafe fn get(key: Key) -> *mut u8 {
    if let Some(&entry) = locals().get(&key) {
        entry
    } else {
        ptr::null_mut()
    }
}

#[inline]
pub unsafe fn set(key: Key, value: *mut u8) {
    locals().insert(key, value);
}

#[inline]
pub unsafe fn destroy(key: Key) {
    keys().remove(&key);
}

#[inline]
pub fn requires_synchronized_create() -> bool {
    false
}
<commit_msg>protect creation of destructors by a mutex<commit_after>#![allow(dead_code)] // not used on all platforms

use crate::collections::BTreeMap;
use crate::ptr;
use crate::sync::atomic::{AtomicUsize, Ordering};
use crate::sys_common::mutex::Mutex;

pub type Key = usize;

type Dtor = unsafe extern fn(*mut u8);

static NEXT_KEY: AtomicUsize = AtomicUsize::new(0);

static mut KEYS: *mut BTreeMap<Key, Option<Dtor>> = ptr::null_mut();
static KEYS_LOCK: Mutex = Mutex::new();

#[thread_local]
static mut LOCALS: *mut BTreeMap<Key, *mut u8> = ptr::null_mut();

unsafe fn keys() -> &'static mut BTreeMap<Key, Option<Dtor>> {
    if KEYS == ptr::null_mut() {
        KEYS = Box::into_raw(Box::new(BTreeMap::new()));
    }
    &mut *KEYS
}

unsafe fn locals() -> &'static mut BTreeMap<Key, *mut u8> {
    if LOCALS == ptr::null_mut() {
        LOCALS = Box::into_raw(Box::new(BTreeMap::new()));
    }
    &mut *LOCALS
}

#[inline]
pub unsafe fn create(dtor: Option<Dtor>) -> Key {
    let key = NEXT_KEY.fetch_add(1, Ordering::SeqCst);
    let _guard = KEYS_LOCK.lock();
    keys().insert(key, dtor);
    key
}

#[inline]
pub unsafe fn get(key: Key) -> *mut u8 {
    if let Some(&entry) = locals().get(&key) {
        entry
    } else {
        ptr::null_mut()
    }
}

#[inline]
pub unsafe fn set(key: Key, value: *mut u8) {
    locals().insert(key, value);
}

#[inline]
pub unsafe fn destroy(key: Key) {
    keys().remove(&key);
}

#[inline]
pub fn requires_synchronized_create() -> bool {
    false
}
<|endoftext|>


<commit_before>use std::io::Read;
use std::error::Error;

use hyper;
use hyper::net::Fresh;
use hyper::server::{Server, Request, Response};
use hyper::uri::RequestUri;
use hyper::Url;
use hyper::header::{Headers,ContentType,Location,SetCookie};
use cookie::Cookie;

use mime::Mime;

use url::SchemeData::Relative;

use rustc_serialize::json;

use websocket::{Message, Sender};

use client::*;
use value::Value;

#[derive(RustcDecodable, RustcEncodable, Debug, Clone)]
pub struct Session {
	pub client: String,
	pub id: String,
	pub user_id: String,
	pub object: String,
	pub created_at: f64,
	pub expires_at: f64,
	pub ip: String,
	pub user: User,
}

#[derive(RustcDecodable, RustcEncodable, Debug, Clone)]
pub struct User {
	pub custom: Custom,
	pub id: String,
	pub realm_id: String,
	pub username: String,
	pub state: String,
	pub user_type: String,
	pub reference: Option<String>,
	pub name: String,
	pub email: String,
	pub object: String,
	pub last_login_at: f64,
	pub last_login_on: f64,
	pub created_at: f64,
	pub first_name: Option<String>,
	pub last_name: Option<String>,
	pub credentials: Vec<Credential>,
	pub membership_count: f64,
}

#[derive(RustcDecodable, RustcEncodable, Debug, Clone)]
pub struct Custom;

#[derive(RustcDecodable, RustcEncodable, Debug, Clone)]
pub struct Credential {
	id: String,
	credential_type: String,
	object: String,
}

pub fn run() {
    Server::http(auth).listen("0.0.0.0:8080").unwrap();
}

fn auth(req: Request, mut res: Response<Fresh>) {

	match (&req.method.clone(), &req.uri.clone()) {
		(&hyper::Get, &RequestUri::AbsolutePath(ref relative_path)) => {

			// Form a url from the path
			let absolute_path = "http://localhost".to_string() + relative_path;
			let url = Url::parse(&*absolute_path).unwrap();

			// Get the file name
			let scheme_data = &url.scheme_data;

			let requested_file = match scheme_data {
				&Relative(ref rsd) => rsd.path[0].clone(),
				_ => panic!("Expected relative path"),
			};

			// Parse the query string
			let query_pairs = &url.query_pairs();

			// Handle login
			match &*requested_file {
				"auth.html" => {
					println!("Authenticating User");
					let pairs = query_pairs.clone().unwrap();
					match &pairs[..] {
						[(ref token_type, ref token)] if token_type.clone() == "token".to_string() => {

							// We have a login token, now to authenticate
							let mut client = hyper::client::Client::new();
							let api_call = "https://api-e1.authrocket.com/v1/sessions/".to_string() + token;
							let req = client.request(hyper::method::Method::Get,&*api_call);

							// Set the appropriate headers for authorocket
							let json: Mime = "application/json".parse().unwrap();
							let accept = Accept("application/json".to_string());
							let content_type = ContentType(json);
							let account = AuthrocketAccount("org_0vC7wPw9XphPGQnSqYB6bz".to_string());
							let key = AuthrocketApiKey("key_jtnCRWxQvDD0p5HATR9RBIe4WnxnwV6pWNzwmZQLnSZ".to_string());
							let realm = AuthrocketRealm("rl_0vC7wd03CqwhpK7kT8fvAc".to_string());

							let mut headers = Headers::new();
							headers.set(account);
							headers.set(key);
							headers.set(realm);
							headers.set(accept);
							headers.set(content_type);

							// Send the request and receive a response with session data
							let mut client_res = req.headers(headers).send().unwrap();

							match client_res.status_raw() {

								&hyper::http::RawStatus(200,_) => {

									let mut body = String::new();
									client_res.read_to_string(&mut body).unwrap();
									let session_data: Session = json::decode(&body).unwrap();
									println!("Welcome to Eve, {:?}!",session_data.user.username);
									println!("Login Successful. Redirecting to user area.");

									// Connect to the Eve runtime and add the user to the eveusers table
									let ws_result = open_websocket("ws://192.168.137.38:2794");
									match ws_result {
										// If things went okay, redirect to the Eve UI
										Ok((mut send_thread,receive_thread)) => {
										//Ok((mut send_thread,receive_thread)) => {
											// Form the response
											*res.status_mut() = hyper::status::StatusCode::PermanentRedirect;

											// Form the response headers
											let mut headers = Headers::new();
											let location = Location("http://192.168.137.38:1234/editor.html".to_string());
											let user_cookie = Cookie::new("userid".to_string(),session_data.user.id.clone());
											let cookies = SetCookie(vec![user_cookie]);
											headers.set(location);
											headers.set(cookies);
											*res.headers_mut() = headers;

											// Create an eveuser table
											let table_name = "eveusers";
											let table_fields = vec!["id","username"];
											let row_data = vec![
																Value::String(session_data.user.id.clone()),
																Value::String(session_data.user.username.clone())
														   	   ];

											// TODO figure out how to do this without a new scope
											{
												send_event(&create_table(&table_name,&table_fields),&mut send_thread);
											}
											{
												send_event(&insert_fact(&table_name,&table_fields,&row_data),&mut send_thread);
											}
											send_thread.send_message(Message::Close(None)).unwrap();

											//let _ = send_thread.join();
											let _ = receive_thread.join();

										}
										// Otherwise, throw an error... maybe redirect to a special page.
										Err(e) => {
											println!("ERROR: Had trouble connecting to the Eve runtime: {}",e);
											*res.status_mut() = hyper::status::StatusCode::NotFound;
											panic!("Oh no!");
											//serve_file("404.html",res);
										}
									}

									println!("Login complete.");

								}
								_ => {
									println!("ERROR: Could not authenticate user with token {}",token);
									*res.status_mut() = hyper::status::StatusCode::Forbidden;
									panic!("Oh no!");
									//serve_file("404.html",res);
								}
							};
						},
						_ => panic!("Oh no!"), //serve_file("404.html",res),
					}
				},
				_ => panic!("Oh no!"), //serve_file(&*requested_file,res),
			};
		}
		_ => panic!("Oh no!"),
	}
}

#[derive(Clone, Debug, PartialEq)]
pub struct AuthrocketAccount(pub String);

impl hyper::header::Header for AuthrocketAccount {
	fn header_name() -> &'static str {
	    "X-Authrocket-Account"
	}
	fn parse_header(raw: &[Vec<u8>]) -> Option<Self> {
	    hyper::header::parsing::from_one_raw_str(raw).map(AuthrocketAccount)
	}
}

impl hyper::header::HeaderFormat for AuthrocketAccount {
	fn fmt_header(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
	    ::std::fmt::Display::fmt(&self.0, f)
	}
}

impl ::std::fmt::Display for AuthrocketAccount {
	fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
	    ::std::fmt::Display::fmt(&self.0, f)
	}
}

#[derive(Clone, Debug, PartialEq)]
pub struct AuthrocketApiKey(pub String);

impl hyper::header::Header for AuthrocketApiKey {
	fn header_name() -> &'static str {
	    "X-Authrocket-Api-Key"
	}
	fn parse_header(raw: &[Vec<u8>]) -> Option<Self> {
	    hyper::header::parsing::from_one_raw_str(raw).map(AuthrocketApiKey)
	}
}

impl hyper::header::HeaderFormat for AuthrocketApiKey {
	fn fmt_header(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
	    ::std::fmt::Display::fmt(&self.0, f)
	}
}

impl ::std::fmt::Display for AuthrocketApiKey {
	fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
	    ::std::fmt::Display::fmt(&self.0, f)
	}
}

#[derive(Clone, Debug, PartialEq)]
pub struct AuthrocketRealm(pub String);

impl hyper::header::Header for AuthrocketRealm {
	fn header_name() -> &'static str {
	    "X-Authrocket-Realm"
	}
	fn parse_header(raw: &[Vec<u8>]) -> Option<Self> {
	    hyper::header::parsing::from_one_raw_str(raw).map(AuthrocketRealm)
	}
}

impl hyper::header::HeaderFormat for AuthrocketRealm {
	fn fmt_header(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
	    ::std::fmt::Display::fmt(&self.0, f)
	}
}

impl ::std::fmt::Display for AuthrocketRealm {
	fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
	    ::std::fmt::Display::fmt(&self.0, f)
	}
}

#[derive(Clone, Debug, PartialEq)]
pub struct Accept(pub String);

impl hyper::header::Header for Accept {
	fn header_name() -> &'static str {
	    "Accept"
	}
	fn parse_header(raw: &[Vec<u8>]) -> Option<Self> {
	    hyper::header::parsing::from_one_raw_str(raw).map(Accept)
	}
}

impl hyper::header::HeaderFormat for Accept {
	fn fmt_header(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
	    ::std::fmt::Display::fmt(&self.0, f)
	}
}

impl ::std::fmt::Display for Accept {
	fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
	    ::std::fmt::Display::fmt(&self.0, f)
	}
}<commit_msg>Cleaned up some code in authenticate.rs<commit_after>use std::io::Read;
use std::error::Error;

use hyper;
use hyper::net::Fresh;
use hyper::server::{Server, Request, Response};
use hyper::uri::RequestUri;
use hyper::Url;
use hyper::header::{Headers,ContentType,Location,SetCookie};
use cookie::Cookie;

use mime::Mime;

use url::SchemeData::Relative;

use rustc_serialize::json;

use websocket::{Message, Sender};

use client::*;
use value::Value;

#[derive(RustcDecodable, RustcEncodable, Debug, Clone)]
pub struct Session {
	pub client: String,
	pub id: String,
	pub user_id: String,
	pub object: String,
	pub created_at: f64,
	pub expires_at: f64,
	pub ip: String,
	pub user: User,
}

#[derive(RustcDecodable, RustcEncodable, Debug, Clone)]
pub struct User {
	pub custom: Custom,
	pub id: String,
	pub realm_id: String,
	pub username: String,
	pub state: String,
	pub user_type: String,
	pub reference: Option<String>,
	pub name: String,
	pub email: String,
	pub object: String,
	pub last_login_at: f64,
	pub last_login_on: f64,
	pub created_at: f64,
	pub first_name: Option<String>,
	pub last_name: Option<String>,
	pub credentials: Vec<Credential>,
	pub membership_count: f64,
}

#[derive(RustcDecodable, RustcEncodable, Debug, Clone)]
pub struct Custom;

#[derive(RustcDecodable, RustcEncodable, Debug, Clone)]
pub struct Credential {
	id: String,
	credential_type: String,
	object: String,
}

pub fn run() {
    Server::http(auth).listen("0.0.0.0:8080").unwrap();
}

fn auth(req: Request, mut res: Response<Fresh>) {

	match (&req.method.clone(), &req.uri.clone()) {
		(&hyper::Get, &RequestUri::AbsolutePath(ref relative_path)) => {

			// Form a url from the path
			let absolute_path = "http://localhost".to_string() + relative_path;
			let url = Url::parse(&*absolute_path).unwrap();

			// Get the file name
			let scheme_data = &url.scheme_data;

			let requested_file = match scheme_data {
				&Relative(ref rsd) => rsd.path[0].clone(),
				_ => panic!("Expected relative path"),
			};

			// Parse the query string
			let query_pairs = &url.query_pairs();

			// Handle login
			match &*requested_file {
				"auth.html" => {
					println!("Authenticating User");
					let pairs = query_pairs.clone().unwrap();
					match &pairs[..] {
						[(ref token_type, ref token)] if token_type.clone() == "token".to_string() => {

							// We have a login token, now to authenticate
							let mut client = hyper::client::Client::new();
							let api_call = "https://api-e1.authrocket.com/v1/sessions/".to_string() + token;
							let req = client.request(hyper::method::Method::Get,&*api_call);

							// Set the appropriate headers for authorocket
							let mut headers = Headers::new();
							let json: Mime = "application/json".parse().unwrap();
							let content_type = ContentType(json);
							headers.set_raw("X-Authrocket-Account",vec!["org_0vC7wPw9XphPGQnSqYB6bz".to_string().into_bytes()]);  //AuthrocketAccount("org_0vC7wPw9XphPGQnSqYB6bz".to_string());
							headers.set_raw("X-Authrocket-Api-Key",vec!["key_jtnCRWxQvDD0p5HATR9RBIe4WnxnwV6pWNzwmZQLnSZ".to_string().into_bytes()]);
							headers.set_raw("X-Authrocket-Realm",vec!["rl_0vC7wd03CqwhpK7kT8fvAc".to_string().into_bytes()]);
							headers.set_raw("Accept",vec!["application/json".to_string().into_bytes()]);
							headers.set(content_type);

							// Send the request and receive a response with session data
							let mut client_res = req.headers(headers).send().unwrap();

							match client_res.status_raw() {

								&hyper::http::RawStatus(200,_) => {

									let mut body = String::new();
									client_res.read_to_string(&mut body).unwrap();
									let session_data: Session = json::decode(&body).unwrap();
									println!("Welcome to Eve, {:?}!",session_data.user.username);
									println!("Login Successful. Redirecting to user area.");

									// Connect to the Eve runtime and add the user to the eveusers table
									let ws_result = open_websocket("ws://192.168.137.38:2794");
									match ws_result {
										// If things went okay, redirect to the Eve UI
										Ok((mut send_thread,receive_thread)) => {
										//Ok((mut send_thread,receive_thread)) => {
											// Form the response
											*res.status_mut() = hyper::status::StatusCode::PermanentRedirect;

											// Form the response headers
											let mut headers = Headers::new();
											let location = Location("http://192.168.137.38:1234/editor.html".to_string());
											let user_cookie = Cookie::new("userid".to_string(),session_data.user.id.clone());
											let cookies = SetCookie(vec![user_cookie]);
											headers.set(location);
											headers.set(cookies);
											*res.headers_mut() = headers;

											// Create an eveuser table
											let table_name = "eveusers";
											let table_fields = vec!["id","username"];
											let row_data = vec![
																Value::String(session_data.user.id.clone()),
																Value::String(session_data.user.username.clone())
														   	   ];

											// TODO figure out how to do this without a new scope
											{
												send_event(&create_table(&table_name,&table_fields),&mut send_thread);
											}
											{
												send_event(&insert_fact(&table_name,&table_fields,&row_data),&mut send_thread);
											}
											send_thread.send_message(Message::Close(None)).unwrap();

											//let _ = send_thread.join();
											let _ = receive_thread.join();

										}
										// Otherwise, throw an error... maybe redirect to a special page.
										Err(e) => {
											println!("ERROR: Had trouble connecting to the Eve runtime: {}",e);
											*res.status_mut() = hyper::status::StatusCode::NotFound;
											panic!("Oh no!");
											//serve_file("404.html",res);
										}
									}

									println!("Login complete.");

								}
								_ => {
									println!("ERROR: Could not authenticate user with token {}",token);
									*res.status_mut() = hyper::status::StatusCode::Forbidden;
									panic!("Oh no!");
									//serve_file("404.html",res);
								}
							};
						},
						_ => panic!("Oh no!"), //serve_file("404.html",res),
					}
				},
				_ => panic!("Oh no!"), //serve_file(&*requested_file,res),
			};
		}
		_ => panic!("Oh no!"),
	}
}<|endoftext|>


<commit_before>pub fn annotate(minefield: &[&str]) -> Vec<String> {
    let field = split(minefield);
    let mut annotated: Vec<String> = Vec::new();

    for (y, row) in field.iter().enumerate() {
        let mut annotated_row = String::new();
        for (x, token) in row.iter().enumerate() {
            match token {
                '*' => annotated_row.push('*'),
                ' ' => {
                    let neighbor_mines = num_neighbor_mines(&field, y as u32, x as u32);
                    let annotated_location = if neighbor_mines == 0 {
                        " ".to_string()
                    } else {
                        neighbor_mines.to_string()
                    };
                    annotated_row.push_str(&annotated_location)
                }
                _ => panic!("unsupported token"),
            }
        }
        annotated.push(annotated_row)
    }

    annotated
}

fn split(minefield: &[&str]) -> Vec<Vec<char>> {
    let mut field: Vec<Vec<char>> = Vec::new();

    for row in minefield {
        field.push(row.chars().collect());
    }
    field
}

fn num_neighbor_mines(field: &Vec<Vec<char>>, y: u32, x: u32) -> usize {
    return get_neighbors(field, y, x)
        .iter()
        .filter(|neighbor| neighbor == &&'*')
        .count();
}

fn get_neighbors(field: &Vec<Vec<char>>, y: u32, x: u32) -> Vec<char> {
    let mut neighbors = Vec::new();
    let y = y as i32;
    let x = x as i32;

    let delta_ys: Vec<i32> = (-1..=1).collect();
    for delta_y in delta_ys {
        let delta_xs: Vec<i32> = (-1..=1).collect();
        for delta_x in delta_xs {
            if delta_y == 0 && delta_x == 0 {
                continue;
            }
            if y + delta_y < 0 || y + delta_y >= field.len() as i32 {
                continue;
            }
            if x + delta_x < 0 || x + delta_x >= field[0].len() as i32 {
                continue;
            }
            println!("{} {}", y + delta_y, x + delta_x);
            let neighbor = field[(y + delta_y) as usize][(x + delta_x) as usize];
            neighbors.push(neighbor)
        }
    }

    neighbors
}
<commit_msg>Remove debug line<commit_after>pub fn annotate(minefield: &[&str]) -> Vec<String> {
    let field = split(minefield);
    let mut annotated: Vec<String> = Vec::new();

    for (y, row) in field.iter().enumerate() {
        let mut annotated_row = String::new();
        for (x, token) in row.iter().enumerate() {
            match token {
                '*' => annotated_row.push('*'),
                ' ' => {
                    let neighbor_mines = num_neighbor_mines(&field, y as u32, x as u32);
                    let annotated_location = if neighbor_mines == 0 {
                        " ".to_string()
                    } else {
                        neighbor_mines.to_string()
                    };
                    annotated_row.push_str(&annotated_location)
                }
                _ => panic!("unsupported token"),
            }
        }
        annotated.push(annotated_row)
    }

    annotated
}

fn split(minefield: &[&str]) -> Vec<Vec<char>> {
    let mut field: Vec<Vec<char>> = Vec::new();

    for row in minefield {
        field.push(row.chars().collect());
    }
    field
}

fn num_neighbor_mines(field: &Vec<Vec<char>>, y: u32, x: u32) -> usize {
    return get_neighbors(field, y, x)
        .iter()
        .filter(|neighbor| neighbor == &&'*')
        .count();
}

fn get_neighbors(field: &Vec<Vec<char>>, y: u32, x: u32) -> Vec<char> {
    let mut neighbors = Vec::new();
    let y = y as i32;
    let x = x as i32;

    let delta_ys: Vec<i32> = (-1..=1).collect();
    for delta_y in delta_ys {
        let delta_xs: Vec<i32> = (-1..=1).collect();
        for delta_x in delta_xs {
            if delta_y == 0 && delta_x == 0 {
                continue;
            }
            if y + delta_y < 0 || y + delta_y >= field.len() as i32 {
                continue;
            }
            if x + delta_x < 0 || x + delta_x >= field[0].len() as i32 {
                continue;
            }
            let neighbor = field[(y + delta_y) as usize][(x + delta_x) as usize];
            neighbors.push(neighbor)
        }
    }

    neighbors
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2018 Boucher, Antoni <bouanto@zoho.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#![feature(proc_macro)]

extern crate gtk;
#[macro_use]
extern crate relm;
extern crate relm_attributes;
#[macro_use]
extern crate relm_derive;

use gtk::{
    Inhibit,
    WidgetExt,
};
use relm::{Component, Widget, init};
use relm_attributes::widget;

use self::Msg::*;

#[widget]
impl Widget for SecondaryWin {
    fn model() -> () {
    }

    fn update(&mut self, _msg: Msg) {
    }

    view! {
        gtk::Window {
            delete_event(_, _) => (Quit, Inhibit(false)),
        }
    }
}

// Define the structure of the model.
pub struct Model {
    counter: i32,
    _win: Component<SecondaryWin>,
}

// The messages that can be sent to the update function.
#[derive(Msg)]
pub enum Msg {
    Decrement,
    Increment,
    Quit,
}

#[widget]
impl Widget for Win {
    fn model() -> Model {
        Model {
            counter: 0,
            _win: init::<SecondaryWin>(()).expect("secondary window"),
        }
    }

    fn update(&mut self, event: Msg) {
        match event {
            Decrement => self.model.counter -= 1,
            Increment => self.model.counter += 1,
            Quit => gtk::main_quit(),
        }
    }

    view! {
        gtk::Window {
            delete_event(_, _) => (Quit, Inhibit(false)),
        }
    }
}

fn main() {
    Win::run(()).unwrap();
}
<commit_msg>Clean multi-window example<commit_after>/*
 * Copyright (c) 2018 Boucher, Antoni <bouanto@zoho.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#![feature(proc_macro)]

extern crate gtk;
#[macro_use]
extern crate relm;
extern crate relm_attributes;
#[macro_use]
extern crate relm_derive;

use gtk::{
    Inhibit,
    WidgetExt,
};
use relm::{Component, Widget, init};
use relm_attributes::widget;

use self::Msg::*;

#[widget]
impl Widget for SecondaryWin {
    fn model() -> () {
    }

    fn update(&mut self, _msg: Msg) {
    }

    view! {
        gtk::Window {
            delete_event(_, _) => (Quit, Inhibit(false)),
        }
    }
}

pub struct Model {
    _win: Component<SecondaryWin>,
}

#[derive(Msg)]
pub enum Msg {
    Quit,
}

#[widget]
impl Widget for Win {
    fn model() -> Model {
        Model {
            _win: init::<SecondaryWin>(()).expect("secondary window"),
        }
    }

    fn update(&mut self, event: Msg) {
        match event {
            Quit => gtk::main_quit(),
        }
    }

    view! {
        gtk::Window {
            delete_event(_, _) => (Quit, Inhibit(false)),
        }
    }
}

fn main() {
    Win::run(()).unwrap();
}
<|endoftext|>


<commit_before>use std::ptr::null_mut;

use gdk_pixbuf_sys::GdkPixbuf;
use gdk_pixbuf_sys::{
    GdkPixbufFormat, GdkPixbufModule, GdkPixbufModulePattern, GdkPixbufModulePreparedFunc,
    GdkPixbufModuleSizeFunc, GdkPixbufModuleUpdatedFunc, GDK_PIXBUF_FORMAT_SCALABLE,
    GDK_PIXBUF_FORMAT_THREADSAFE,
};

use glib::translate::IntoGlib;
use glib::translate::ToGlibPtr;
use glib_sys::{gboolean, GError};
use gobject_sys::GObject;
use libc::{c_char, c_int, c_uint};

use gio::prelude::MemoryInputStreamExt;
use gio::MemoryInputStream;
use glib::Bytes;
use librsvg::Loader;

use cstr::cstr;
use librsvg::rsvg_convert_only::LegacySize;

struct SvgContext {
    size_func: GdkPixbufModuleSizeFunc,
    prep_func: GdkPixbufModulePreparedFunc,
    update_func: GdkPixbufModuleUpdatedFunc,
    user_data: glib_sys::gpointer,
    stream: MemoryInputStream,
}

#[no_mangle]
unsafe extern "C" fn begin_load(
    size_func: GdkPixbufModuleSizeFunc,
    prep_func: GdkPixbufModulePreparedFunc,
    update_func: GdkPixbufModuleUpdatedFunc,
    user_data: glib_sys::gpointer,
    error: *mut *mut GError,
) -> glib_sys::gpointer {
    if error != null_mut() {
        *error = null_mut();
    }

    let stream = MemoryInputStream::new();
    let ctx = Box::new(SvgContext {
        size_func,
        prep_func,
        update_func,
        user_data,
        stream,
    });

    Box::into_raw(ctx) as glib_sys::gpointer
}

#[no_mangle]
unsafe extern "C" fn load_increment(
    user_data: glib_sys::gpointer,
    buffer: *const u8,
    size: c_uint,
    error: *mut *mut GError,
) -> gboolean {
    if error != null_mut() {
        *error = null_mut();
    }

    let ctx = user_data as *mut SvgContext;

    let data = std::slice::from_raw_parts(buffer, size as usize);
    (&*ctx).stream.add_bytes(&Bytes::from(data));
    true.into_glib()
}

#[no_mangle]
unsafe extern "C" fn stop_load(user_data: glib_sys::gpointer, error: *mut *mut GError) -> gboolean {
    let ctx = Box::from_raw(user_data as *mut SvgContext);
    if error != null_mut() {
        *error = null_mut();
    }

    fn _inner_stop_load(ctx: &Box<SvgContext>) -> Result<gdk_pixbuf::Pixbuf, String> {
        let handle = Loader::new()
            .read_stream::<_, gio::File, gio::Cancellable>(&ctx.stream, None, None)
            .map_err(|e| e.to_string())?;

        let renderer = librsvg::CairoRenderer::new(&handle);
        let (w, h) = renderer.legacy_document_size().map_err(|e| e.to_string())?;
        let mut w = w.ceil() as c_int;
        let mut h = h.ceil() as c_int;

        if let Some(size_func) = ctx.size_func {
            let mut tmp_w: c_int = w;
            let mut tmp_h: c_int = h;
            unsafe {
                size_func(
                    &mut tmp_w as *mut c_int,
                    &mut tmp_h as *mut c_int,
                    ctx.user_data,
                )
            };
            if tmp_w != 0 && tmp_h != 0 {
                w = tmp_w;
                h = tmp_h;
            }
        }

        let pb = librsvg::c_api::pixbuf_utils::render_to_pixbuf_at_size(
            &renderer, w as f64, h as f64, w as f64, h as f64,
        )
        .map_err(|e| e.to_string())?;

        Ok(pb)
    }

    let pixbuf = match _inner_stop_load(&ctx) {
        Ok(r) => r,
        Err(e) => {
            let gerr = glib::Error::new(gdk_pixbuf::PixbufError::Failed, &e.to_string());
            *error = gerr.into_raw();
            return false.into_glib();
        }
    };

    let w = pixbuf.width();
    let h = pixbuf.height();
    let pixbuf: *mut GdkPixbuf = pixbuf.to_glib_full();

    if let Some(prep_func) = ctx.prep_func {
        prep_func(pixbuf, null_mut(), ctx.user_data);
    }
    if let Some(update_func) = ctx.update_func {
        update_func(pixbuf, 0, 0, w, h, ctx.user_data);
    }

    // The module loader increases a ref so we drop the pixbuf here
    gobject_sys::g_object_unref(pixbuf as *mut GObject);

    true.into_glib()
}

#[no_mangle]
extern "C" fn fill_vtable(module: &mut GdkPixbufModule) {
    module.begin_load = Some(begin_load);
    module.stop_load = Some(stop_load);
    module.load_increment = Some(load_increment);
}

const SIGNATURE: [GdkPixbufModulePattern; 3] = [
    GdkPixbufModulePattern {
        prefix: cstr!(" <svg").as_ptr() as *mut c_char,
        mask: cstr!("*    ").as_ptr() as *mut c_char,
        relevance: 100,
    },
    GdkPixbufModulePattern {
        prefix: cstr!(" <!DOCTYPE svg").as_ptr() as *mut c_char,
        mask: cstr!("*             ").as_ptr() as *mut c_char,
        relevance: 100,
    },
    GdkPixbufModulePattern {
        prefix: std::ptr::null_mut(),
        mask: std::ptr::null_mut(),
        relevance: 0,
    },
];

const MIME_TYPES: [*const c_char; 7] = [
    cstr!("image/svg+xml").as_ptr(),
    cstr!("image/svg").as_ptr(),
    cstr!("image/svg-xml").as_ptr(),
    cstr!("image/vnd.adobe.svg+xml").as_ptr(),
    cstr!("text/xml-svg").as_ptr(),
    cstr!("image/svg+xml-compressed").as_ptr(),
    std::ptr::null(),
];

const EXTENSIONS: [*const c_char; 4] = [
    cstr!("svg").as_ptr(),
    cstr!("svgz").as_ptr(),
    cstr!("svg.gz").as_ptr(),
    std::ptr::null(),
];

#[no_mangle]
extern "C" fn fill_info(info: &mut GdkPixbufFormat) {
    info.name = cstr!("svg").as_ptr() as *mut c_char;
    info.signature = SIGNATURE.as_ptr() as *mut GdkPixbufModulePattern;
    info.description = cstr!("Scalable Vector Graphics").as_ptr() as *mut c_char; //TODO: Gettext this
    info.mime_types = MIME_TYPES.as_ptr() as *mut *mut c_char;
    info.extensions = EXTENSIONS.as_ptr() as *mut *mut c_char;
    info.flags = GDK_PIXBUF_FORMAT_SCALABLE | GDK_PIXBUF_FORMAT_THREADSAFE;
    info.license = cstr!("LGPL").as_ptr() as *mut c_char;
}

#[cfg(test)]
mod tests {
    use gdk_pixbuf_sys::{
        GdkPixbufFormat, GDK_PIXBUF_FORMAT_SCALABLE, GDK_PIXBUF_FORMAT_THREADSAFE,
    };
    use glib::translate::IntoGlib;

    use crate::{EXTENSIONS, MIME_TYPES};
    use libc::c_char;
    use std::ptr::{null, null_mut};

    fn pb_format_new() -> GdkPixbufFormat {
        let mut info = super::GdkPixbufFormat {
            name: null_mut(),
            signature: null_mut(),
            description: null_mut(),
            mime_types: null_mut(),
            extensions: null_mut(),
            flags: 0,
            license: null_mut(),
            disabled: false.into_glib(),
            domain: null_mut(),
        };

        super::fill_info(&mut info);
        info
    }

    #[test]
    fn fill_info() {
        let info = pb_format_new();

        assert_ne!(info.name, null_mut());
        assert_ne!(info.signature, null_mut());
        assert_ne!(info.description, null_mut());
        assert_ne!(info.mime_types, null_mut());
        assert_ne!(info.extensions, null_mut());
        assert_eq!(
            info.flags,
            GDK_PIXBUF_FORMAT_SCALABLE | GDK_PIXBUF_FORMAT_THREADSAFE
        );
        assert_ne!(info.license, null_mut());
    }

    fn check_null_terminated_arr_cstrings(arr: &[*const c_char]) {
        let n_strings = arr
            .iter()
            .filter(|e| e != &&null())
            .map(|e| {
                if e != &null() {
                    // We use strlen in all of them to ensure some safety
                    // We could use CStr instead but it'd be a bit more cumbersome
                    assert!(unsafe { libc::strlen(*e as *const c_char) } > 0)
                }
            })
            .count(); // Count all non_null items

        // Ensure last item is null and is the only null item
        assert_eq!(n_strings, arr.len() - 1);
        assert!(arr.last().unwrap() == &null());
    }

    #[test]
    fn extensions_bounds() {
        check_null_terminated_arr_cstrings(&EXTENSIONS);
    }

    #[test]
    fn mime_bounds() {
        check_null_terminated_arr_cstrings(&MIME_TYPES)
    }

    #[test]
    fn signature() {
        let info = pb_format_new();

        for i in 0..2 {
            let ptr = unsafe { info.signature.offset(i) };
            if i == 2 {
                assert_eq!(unsafe { (*ptr).prefix }, null_mut());
                continue;
            } else {
                assert_ne!(unsafe { (*ptr).prefix }, null_mut());
                if unsafe { (*ptr).mask } != null_mut() {
                    // Mask can be null
                    assert_eq!(
                        unsafe { libc::strlen((*ptr).prefix as *mut c_char) },
                        unsafe { libc::strlen((*ptr).mask as *mut c_char) }
                    );
                }
                // Relevance must be 0 to 100
                assert!(unsafe { (*ptr).relevance } >= 0);
                assert!(unsafe { (*ptr).relevance } <= 100);
            }
        }
    }

    const SVG_DATA: &'static str = r#"<?xml version="1.0" encoding="UTF-8" standalone="no"?>
                                    <svg
                                    width="100px"
                                    height="150px"
                                    viewBox="0 0 26.458333 26.458333"
                                    version="1.1"
                                    id="svg5"
                                    xmlns="http://www.w3.org/2000/svg"
                                    xmlns:svg="http://www.w3.org/2000/svg">
                                    <rect
                                        style="fill:#aa1144;stroke-width:0.0344347"
                                        width="26.458332"
                                        height="39.6875"
                                        x="4.691162e-07"
                                        y="-6.6145835"
                                        id="rect2" />
                                    </svg>
    "#;

    #[test]
    fn minimal_svg() {
        unsafe extern "C" fn prep_cb(
            pb: *mut gdk_pixbuf_sys::GdkPixbuf,
            pba: *mut gdk_pixbuf_sys::GdkPixbufAnimation,
            user_data: *mut libc::c_void,
        ) {
            assert_eq!(user_data, null_mut());
            assert_eq!(pba, null_mut());

            let w = gdk_pixbuf_sys::gdk_pixbuf_get_width(pb);
            let h = gdk_pixbuf_sys::gdk_pixbuf_get_height(pb);
            let stride = gdk_pixbuf_sys::gdk_pixbuf_get_rowstride(pb);
            assert_eq!(w, 100);
            assert_eq!(h, 150);

            let pixels = gdk_pixbuf_sys::gdk_pixbuf_get_pixels(pb);

            // Upper left pixel, black with full opacity #000000ff
            assert_eq!(*pixels, 0xaa);
            assert_eq!(*pixels.offset(1), 0x11);
            assert_eq!(*pixels.offset(2), 0x44);
            assert_eq!(*pixels.offset(3), 0xff);

            // Bottom left pixel
            assert_eq!(*pixels.offset((stride * (h - 1)) as isize), 0xaa);
            assert_eq!(*pixels.offset((stride * (h - 1)) as isize + 1), 0x11);
            assert_eq!(*pixels.offset((stride * (h - 1)) as isize + 2), 0x44);
            assert_eq!(*pixels.offset((stride * (h - 1)) as isize + 3), 0xff);

            // Bottom right pixel
            assert_eq!(
                *pixels.offset((stride * (h - 1)) as isize + (w as isize - 1) * 4),
                0xaa
            );
            assert_eq!(
                *pixels.offset((stride * (h - 1)) as isize + (w as isize - 1) * 4 + 1),
                0x11
            );
            assert_eq!(
                *pixels.offset((stride * (h - 1)) as isize + (w as isize - 1) * 4 + 2),
                0x44
            );
            assert_eq!(
                *pixels.offset((stride * (h - 1)) as isize + (w as isize - 1) * 4 + 3),
                0xff
            );
        }

        let ctx = unsafe { crate::begin_load(None, Some(prep_cb), None, null_mut(), null_mut()) };
        assert_ne!(ctx, null_mut());

        let inc = unsafe {
            crate::load_increment(ctx, SVG_DATA.as_ptr(), SVG_DATA.len() as u32, null_mut())
        };
        assert_ne!(inc, 0);

        unsafe { crate::stop_load(ctx, null_mut()) };
    }
}
<commit_msg>pixbuf-loader: remove redundant to_string()<commit_after>use std::ptr::null_mut;

use gdk_pixbuf_sys::GdkPixbuf;
use gdk_pixbuf_sys::{
    GdkPixbufFormat, GdkPixbufModule, GdkPixbufModulePattern, GdkPixbufModulePreparedFunc,
    GdkPixbufModuleSizeFunc, GdkPixbufModuleUpdatedFunc, GDK_PIXBUF_FORMAT_SCALABLE,
    GDK_PIXBUF_FORMAT_THREADSAFE,
};

use glib::translate::IntoGlib;
use glib::translate::ToGlibPtr;
use glib_sys::{gboolean, GError};
use gobject_sys::GObject;
use libc::{c_char, c_int, c_uint};

use gio::prelude::MemoryInputStreamExt;
use gio::MemoryInputStream;
use glib::Bytes;
use librsvg::Loader;

use cstr::cstr;
use librsvg::rsvg_convert_only::LegacySize;

struct SvgContext {
    size_func: GdkPixbufModuleSizeFunc,
    prep_func: GdkPixbufModulePreparedFunc,
    update_func: GdkPixbufModuleUpdatedFunc,
    user_data: glib_sys::gpointer,
    stream: MemoryInputStream,
}

#[no_mangle]
unsafe extern "C" fn begin_load(
    size_func: GdkPixbufModuleSizeFunc,
    prep_func: GdkPixbufModulePreparedFunc,
    update_func: GdkPixbufModuleUpdatedFunc,
    user_data: glib_sys::gpointer,
    error: *mut *mut GError,
) -> glib_sys::gpointer {
    if error != null_mut() {
        *error = null_mut();
    }

    let stream = MemoryInputStream::new();
    let ctx = Box::new(SvgContext {
        size_func,
        prep_func,
        update_func,
        user_data,
        stream,
    });

    Box::into_raw(ctx) as glib_sys::gpointer
}

#[no_mangle]
unsafe extern "C" fn load_increment(
    user_data: glib_sys::gpointer,
    buffer: *const u8,
    size: c_uint,
    error: *mut *mut GError,
) -> gboolean {
    if error != null_mut() {
        *error = null_mut();
    }

    let ctx = user_data as *mut SvgContext;

    let data = std::slice::from_raw_parts(buffer, size as usize);
    (&*ctx).stream.add_bytes(&Bytes::from(data));
    true.into_glib()
}

#[no_mangle]
unsafe extern "C" fn stop_load(user_data: glib_sys::gpointer, error: *mut *mut GError) -> gboolean {
    let ctx = Box::from_raw(user_data as *mut SvgContext);
    if error != null_mut() {
        *error = null_mut();
    }

    fn _inner_stop_load(ctx: &Box<SvgContext>) -> Result<gdk_pixbuf::Pixbuf, String> {
        let handle = Loader::new()
            .read_stream::<_, gio::File, gio::Cancellable>(&ctx.stream, None, None)
            .map_err(|e| e.to_string())?;

        let renderer = librsvg::CairoRenderer::new(&handle);
        let (w, h) = renderer.legacy_document_size().map_err(|e| e.to_string())?;
        let mut w = w.ceil() as c_int;
        let mut h = h.ceil() as c_int;

        if let Some(size_func) = ctx.size_func {
            let mut tmp_w: c_int = w;
            let mut tmp_h: c_int = h;
            unsafe {
                size_func(
                    &mut tmp_w as *mut c_int,
                    &mut tmp_h as *mut c_int,
                    ctx.user_data,
                )
            };
            if tmp_w != 0 && tmp_h != 0 {
                w = tmp_w;
                h = tmp_h;
            }
        }

        let pb = librsvg::c_api::pixbuf_utils::render_to_pixbuf_at_size(
            &renderer, w as f64, h as f64, w as f64, h as f64,
        )
        .map_err(|e| e.to_string())?;

        Ok(pb)
    }

    let pixbuf = match _inner_stop_load(&ctx) {
        Ok(r) => r,
        Err(e) => {
            let gerr = glib::Error::new(gdk_pixbuf::PixbufError::Failed, &e);
            *error = gerr.into_raw();
            return false.into_glib();
        }
    };

    let w = pixbuf.width();
    let h = pixbuf.height();
    let pixbuf: *mut GdkPixbuf = pixbuf.to_glib_full();

    if let Some(prep_func) = ctx.prep_func {
        prep_func(pixbuf, null_mut(), ctx.user_data);
    }
    if let Some(update_func) = ctx.update_func {
        update_func(pixbuf, 0, 0, w, h, ctx.user_data);
    }

    // The module loader increases a ref so we drop the pixbuf here
    gobject_sys::g_object_unref(pixbuf as *mut GObject);

    true.into_glib()
}

#[no_mangle]
extern "C" fn fill_vtable(module: &mut GdkPixbufModule) {
    module.begin_load = Some(begin_load);
    module.stop_load = Some(stop_load);
    module.load_increment = Some(load_increment);
}

const SIGNATURE: [GdkPixbufModulePattern; 3] = [
    GdkPixbufModulePattern {
        prefix: cstr!(" <svg").as_ptr() as *mut c_char,
        mask: cstr!("*    ").as_ptr() as *mut c_char,
        relevance: 100,
    },
    GdkPixbufModulePattern {
        prefix: cstr!(" <!DOCTYPE svg").as_ptr() as *mut c_char,
        mask: cstr!("*             ").as_ptr() as *mut c_char,
        relevance: 100,
    },
    GdkPixbufModulePattern {
        prefix: std::ptr::null_mut(),
        mask: std::ptr::null_mut(),
        relevance: 0,
    },
];

const MIME_TYPES: [*const c_char; 7] = [
    cstr!("image/svg+xml").as_ptr(),
    cstr!("image/svg").as_ptr(),
    cstr!("image/svg-xml").as_ptr(),
    cstr!("image/vnd.adobe.svg+xml").as_ptr(),
    cstr!("text/xml-svg").as_ptr(),
    cstr!("image/svg+xml-compressed").as_ptr(),
    std::ptr::null(),
];

const EXTENSIONS: [*const c_char; 4] = [
    cstr!("svg").as_ptr(),
    cstr!("svgz").as_ptr(),
    cstr!("svg.gz").as_ptr(),
    std::ptr::null(),
];

#[no_mangle]
extern "C" fn fill_info(info: &mut GdkPixbufFormat) {
    info.name = cstr!("svg").as_ptr() as *mut c_char;
    info.signature = SIGNATURE.as_ptr() as *mut GdkPixbufModulePattern;
    info.description = cstr!("Scalable Vector Graphics").as_ptr() as *mut c_char; //TODO: Gettext this
    info.mime_types = MIME_TYPES.as_ptr() as *mut *mut c_char;
    info.extensions = EXTENSIONS.as_ptr() as *mut *mut c_char;
    info.flags = GDK_PIXBUF_FORMAT_SCALABLE | GDK_PIXBUF_FORMAT_THREADSAFE;
    info.license = cstr!("LGPL").as_ptr() as *mut c_char;
}

#[cfg(test)]
mod tests {
    use gdk_pixbuf_sys::{
        GdkPixbufFormat, GDK_PIXBUF_FORMAT_SCALABLE, GDK_PIXBUF_FORMAT_THREADSAFE,
    };
    use glib::translate::IntoGlib;

    use crate::{EXTENSIONS, MIME_TYPES};
    use libc::c_char;
    use std::ptr::{null, null_mut};

    fn pb_format_new() -> GdkPixbufFormat {
        let mut info = super::GdkPixbufFormat {
            name: null_mut(),
            signature: null_mut(),
            description: null_mut(),
            mime_types: null_mut(),
            extensions: null_mut(),
            flags: 0,
            license: null_mut(),
            disabled: false.into_glib(),
            domain: null_mut(),
        };

        super::fill_info(&mut info);
        info
    }

    #[test]
    fn fill_info() {
        let info = pb_format_new();

        assert_ne!(info.name, null_mut());
        assert_ne!(info.signature, null_mut());
        assert_ne!(info.description, null_mut());
        assert_ne!(info.mime_types, null_mut());
        assert_ne!(info.extensions, null_mut());
        assert_eq!(
            info.flags,
            GDK_PIXBUF_FORMAT_SCALABLE | GDK_PIXBUF_FORMAT_THREADSAFE
        );
        assert_ne!(info.license, null_mut());
    }

    fn check_null_terminated_arr_cstrings(arr: &[*const c_char]) {
        let n_strings = arr
            .iter()
            .filter(|e| e != &&null())
            .map(|e| {
                if e != &null() {
                    // We use strlen in all of them to ensure some safety
                    // We could use CStr instead but it'd be a bit more cumbersome
                    assert!(unsafe { libc::strlen(*e as *const c_char) } > 0)
                }
            })
            .count(); // Count all non_null items

        // Ensure last item is null and is the only null item
        assert_eq!(n_strings, arr.len() - 1);
        assert!(arr.last().unwrap() == &null());
    }

    #[test]
    fn extensions_bounds() {
        check_null_terminated_arr_cstrings(&EXTENSIONS);
    }

    #[test]
    fn mime_bounds() {
        check_null_terminated_arr_cstrings(&MIME_TYPES)
    }

    #[test]
    fn signature() {
        let info = pb_format_new();

        for i in 0..2 {
            let ptr = unsafe { info.signature.offset(i) };
            if i == 2 {
                assert_eq!(unsafe { (*ptr).prefix }, null_mut());
                continue;
            } else {
                assert_ne!(unsafe { (*ptr).prefix }, null_mut());
                if unsafe { (*ptr).mask } != null_mut() {
                    // Mask can be null
                    assert_eq!(
                        unsafe { libc::strlen((*ptr).prefix as *mut c_char) },
                        unsafe { libc::strlen((*ptr).mask as *mut c_char) }
                    );
                }
                // Relevance must be 0 to 100
                assert!(unsafe { (*ptr).relevance } >= 0);
                assert!(unsafe { (*ptr).relevance } <= 100);
            }
        }
    }

    const SVG_DATA: &'static str = r#"<?xml version="1.0" encoding="UTF-8" standalone="no"?>
                                    <svg
                                    width="100px"
                                    height="150px"
                                    viewBox="0 0 26.458333 26.458333"
                                    version="1.1"
                                    id="svg5"
                                    xmlns="http://www.w3.org/2000/svg"
                                    xmlns:svg="http://www.w3.org/2000/svg">
                                    <rect
                                        style="fill:#aa1144;stroke-width:0.0344347"
                                        width="26.458332"
                                        height="39.6875"
                                        x="4.691162e-07"
                                        y="-6.6145835"
                                        id="rect2" />
                                    </svg>
    "#;

    #[test]
    fn minimal_svg() {
        unsafe extern "C" fn prep_cb(
            pb: *mut gdk_pixbuf_sys::GdkPixbuf,
            pba: *mut gdk_pixbuf_sys::GdkPixbufAnimation,
            user_data: *mut libc::c_void,
        ) {
            assert_eq!(user_data, null_mut());
            assert_eq!(pba, null_mut());

            let w = gdk_pixbuf_sys::gdk_pixbuf_get_width(pb);
            let h = gdk_pixbuf_sys::gdk_pixbuf_get_height(pb);
            let stride = gdk_pixbuf_sys::gdk_pixbuf_get_rowstride(pb);
            assert_eq!(w, 100);
            assert_eq!(h, 150);

            let pixels = gdk_pixbuf_sys::gdk_pixbuf_get_pixels(pb);

            // Upper left pixel, black with full opacity #000000ff
            assert_eq!(*pixels, 0xaa);
            assert_eq!(*pixels.offset(1), 0x11);
            assert_eq!(*pixels.offset(2), 0x44);
            assert_eq!(*pixels.offset(3), 0xff);

            // Bottom left pixel
            assert_eq!(*pixels.offset((stride * (h - 1)) as isize), 0xaa);
            assert_eq!(*pixels.offset((stride * (h - 1)) as isize + 1), 0x11);
            assert_eq!(*pixels.offset((stride * (h - 1)) as isize + 2), 0x44);
            assert_eq!(*pixels.offset((stride * (h - 1)) as isize + 3), 0xff);

            // Bottom right pixel
            assert_eq!(
                *pixels.offset((stride * (h - 1)) as isize + (w as isize - 1) * 4),
                0xaa
            );
            assert_eq!(
                *pixels.offset((stride * (h - 1)) as isize + (w as isize - 1) * 4 + 1),
                0x11
            );
            assert_eq!(
                *pixels.offset((stride * (h - 1)) as isize + (w as isize - 1) * 4 + 2),
                0x44
            );
            assert_eq!(
                *pixels.offset((stride * (h - 1)) as isize + (w as isize - 1) * 4 + 3),
                0xff
            );
        }

        let ctx = unsafe { crate::begin_load(None, Some(prep_cb), None, null_mut(), null_mut()) };
        assert_ne!(ctx, null_mut());

        let inc = unsafe {
            crate::load_increment(ctx, SVG_DATA.as_ptr(), SVG_DATA.len() as u32, null_mut())
        };
        assert_ne!(inc, 0);

        unsafe { crate::stop_load(ctx, null_mut()) };
    }
}
<|endoftext|>


<commit_before>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

fn matcher(x: option<int>) {
    match x {
      ref some(i) => {} //~ ERROR expected identifier, found enum pattern
      none => {}
    }
}

fn main() {}
<commit_msg>Fix Option camel case in a compile-fail test<commit_after>// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

fn matcher(x: Option<int>) {
    match x {
      ref Some(i) => {} //~ ERROR expected identifier, found enum pattern
      None => {}
    }
}

fn main() {}
<|endoftext|>