<commit_before>#![feature(libc)]

extern crate libc;
use std::ffi::CString;
use std::slice;
use std::ptr;

mod ffi;

#[derive(Debug, Copy, Clone)]
pub struct Env {
    env: ffi::Voidptr
}

#[derive(Debug, Copy, Clone)]
pub struct Db {
    db: ffi::Voidptr
}

// XXX: Use Arc
unsafe impl Sync for Db {}
unsafe impl Send for Db {}
unsafe impl Sync for Env {}
unsafe impl Send for Env {}

use std::marker::PhantomData;

#[macro_export]
macro_rules! obj {
    (
        $db:ident ;
        $(
            $name:ident : $x:expr
        ),*
    ) => {{
        let mut obj = $db.obj();
        $(
            obj.$name($x)
        );*
        ;obj
    }}
}

#[derive(Debug)]
pub struct DbObject<'a> {
    o: ffi::Voidptr,
    phantom: PhantomData<&'a ()>,
}

impl<'a> DbObject<'a> {
    // We name it attr(), to not mix it up with the set() method.
    pub fn attr<'b>(&'b mut self, path: &str, data: &'b[u8]) {
        let path = CString::new(path).unwrap();
        unsafe {ffi::setstring(self.o, path.as_bytes(), data); }
    }

    // Shortcut for attr("key", ...)
    pub fn key<'b>(&'b mut self, data: &'b[u8]) {
        unsafe {ffi::setstring(self.o, "key\0".as_bytes(), data); }
    }

    // Shortcut for attr("key_b", ...)
    // This allows setting a secondary key.
    pub fn key_b<'b>(&'b mut self, data: &'b[u8]) {
        unsafe {ffi::setstring(self.o, "key_b\0".as_bytes(), data); }
    }

    // Shortcut for attr("value", ...)
    pub fn value<'b>(&'b mut self, data: &'b[u8]) {
        unsafe {ffi::setstring(self.o, "value\0".as_bytes(), data); }
    }

    // Shortcut for attr("val", ...)
    pub fn val<'b>(&'b mut self, data: &'b[u8]) {
        self.value(data)
    }

    // Shortcut for attr("order", ...)
    pub fn order<'b>(&'b mut self, data: &'b[u8]) {
        unsafe {ffi::setstring(self.o, "order\0".as_bytes(), data); }
    }

    // Shortcut for attr("prefix", ...)
    pub fn prefix<'b>(&'b mut self, data: &'b[u8]) {
        unsafe {ffi::setstring(self.o, "prefix\0".as_bytes(), data); }
    }
}

impl<'a> Drop for DbObject<'a> {
    fn drop(&mut self) {
        if !self.o.is_null() {
            unsafe {ffi::sp_destroy(self.o)};
        }
    }
}

#[derive(Debug)]
pub struct DbResultObject<'a> {
    o: ffi::Voidptr,
    phantom: PhantomData<&'a ()>,
}

impl<'a> DbResultObject<'a> {
    fn get_<'b>(&'b self, key: &'b [u8]) -> Option<&'b[u8]> {
        unsafe {
            let mut sz = 0;
            let valptr = ffi::sp_getstring(self.o, key.as_ptr(), &mut sz);

            // XXX: what if we stored an empty value?
            if valptr.is_null() {
                return None;
            }

            let s = slice::from_raw_parts(valptr as *const u8, sz as usize);
            return Some(s);
        }

    }
    pub fn get_value<'b>(&'b self) -> Option<&'b[u8]> {
        self.get_(b"value\0")
    }

    pub fn get_key<'b>(&'b self) -> Option<&'b[u8]> {
        self.get_(b"key\0")
    }

    pub fn get_key_b<'b>(&'b self) -> Option<&'b[u8]> {
        self.get_(b"key_b\0")
    }
}

impl<'a> Drop for DbResultObject<'a> {
    fn drop(&mut self) {
        if !self.o.is_null() {
            unsafe {ffi::sp_destroy(self.o)};
        }
    }
}

#[derive(Debug)]
pub struct Transaction<'a> {
    tx: ffi::Voidptr,
    phantom: PhantomData<&'a ()>
}

impl<'a> Drop for Transaction<'a> {
    // Unless commit() is called, this will roll back the transaction
    fn drop(&mut self) {
        if !self.tx.is_null() {
            unsafe {ffi::sp_destroy(self.tx);}
        }
    }
}

pub struct Cursor<'a> {
    obj: ffi::Voidptr,
    phantom: PhantomData<&'a ()>
}

impl<'a> Drop for Cursor<'a> {
    fn drop(&mut self) {
        unsafe {ffi::sp_destroy(self.obj);}
    }
}

impl<'a> Cursor<'a> {
    pub fn next<'b>(&'b self) -> Option<DbResultObject<'b>> {
        let res = unsafe { ffi::sp_get(self.obj, ptr::null_mut()) };
        if res.is_null() {
            None
        }
        else {
            Some(DbResultObject{o: res, phantom: PhantomData})
        }
    }
}

pub trait SetGetOps {
    fn backend(&self) -> ffi::Voidptr;

    // Consumes the DbObject
    fn set<'a>(&self, obj: DbObject<'a>) {
        let mut obj = obj;
        unsafe {ffi::sp_set(self.backend(), obj.o)}; // XXX: Check error code
        obj.o = ptr::null_mut(); // sp_set drops it
    }

    // XXX: Make sure self.db == dbobject.db
    fn get<'a, 'b>(&'a self, pattern: DbObject<'b>) -> Option<DbResultObject<'a>> {
        unsafe {
            let res = ffi::sp_get(self.backend(), pattern.o);
            if res.is_null() {
                return None;
            }
            let n = DbResultObject {
                o: pattern.o,
                phantom: PhantomData
            };
            let mut pattern = pattern;
            pattern.o = ptr::null_mut();
            return Some(n);
        }
    }

    fn cursor<'a, 'b>(&'a self, pattern: DbObject<'b>) -> Cursor<'a> {
        unsafe {
            let cursor = ffi::sp_cursor(self.backend(), pattern.o);
            assert!(!cursor.is_null());

            // pattern is freed as part of the Cursor
            let mut pattern = pattern;
            pattern.o = ptr::null_mut();

            Cursor {obj: cursor, phantom: PhantomData}
        }
    }
}

impl<'a> Transaction<'a> {
    pub fn commit(mut self) -> i32 {
        let rc = unsafe{ffi::sp_commit(self.tx)};
        self.tx = ptr::null_mut();
        rc as i32
    }
}

impl<'a> SetGetOps for Transaction<'a> {
    fn backend(&self) -> ffi::Voidptr { self.tx }
}

impl Env {
    pub fn new() -> Env {
        Env {env: unsafe{ffi::sp_env()}}
    }

    pub fn destroy(self) {
        unsafe{ffi::sp_destroy(self.env)};
    }

    pub fn db(&mut self, dbname: &str) {
        // XXX: is dbname copied?
        let dbname = CString::new(dbname).unwrap();
        unsafe {ffi::setstring(self.env, "db\0".as_bytes(), dbname.as_bytes()) };
    }

    pub fn open(&mut self) {
        unsafe {ffi::sp_open(self.env)};
    }

    pub fn begin<'a>(&'a self) -> Transaction<'a> {
        let tx = unsafe{ffi::sp_begin(self.env)};
        assert!(!tx.is_null());
        Transaction {
            tx: tx,
            phantom: PhantomData
        }
    }

    pub fn get_db(&self, dbname: &str) -> Option<Db> {
        let dbstr = "db.".to_string() + dbname;
        let attr = CString::new(&dbstr[..]).unwrap();
        unsafe {
            let obj = ffi::sp_getobject(self.env, attr.as_ptr() as *const u8);
            if obj.is_null() {
                None
            }
            else {
                Some(Db {db: obj})
            }
        }
    }

    pub fn setattr(&mut self, key: &str, val: &str) {
        let key = CString::new(key).unwrap();
        let val = CString::new(val).unwrap();
        unsafe {ffi::setstring(self.env, key.as_bytes(), val.as_bytes()) };
    }

    pub fn setintattr(&mut self, key: &str, val: i64) {
        let key = CString::new(key).unwrap();
        unsafe {ffi::sp_setint(self.env, key.as_ptr(), val) };
    }
}

impl SetGetOps for Db {
    fn backend(&self) -> ffi::Voidptr { self.db }
}

impl Db {
    pub fn obj<'a>(&'a self) -> DbObject<'a> {
        let obj = unsafe { ffi::sp_object(self.db) };
        assert!(!obj.is_null());
        DbObject{o: obj, phantom: PhantomData}
    }

}
<commit_msg>Rename DbObject -> Object, DbResultObject -> ResultObject<commit_after>#![feature(libc)]

extern crate libc;
use std::ffi::CString;
use std::slice;
use std::ptr;

mod ffi;

#[derive(Debug, Copy, Clone)]
pub struct Env {
    env: ffi::Voidptr
}

#[derive(Debug, Copy, Clone)]
pub struct Db {
    db: ffi::Voidptr
}

// XXX: Use Arc
unsafe impl Sync for Db {}
unsafe impl Send for Db {}
unsafe impl Sync for Env {}
unsafe impl Send for Env {}

use std::marker::PhantomData;

#[macro_export]
macro_rules! obj {
    (
        $db:ident ;
        $(
            $name:ident : $x:expr
        ),*
    ) => {{
        let mut obj = $db.obj();
        $(
            obj.$name($x)
        );*
        ;obj
    }}
}

#[derive(Debug)]
pub struct Object<'a> {
    o: ffi::Voidptr,
    phantom: PhantomData<&'a ()>,
}

impl<'a> Object<'a> {
    // We name it attr(), to not mix it up with the set() method.
    pub fn attr<'b>(&'b mut self, path: &str, data: &'b[u8]) {
        let path = CString::new(path).unwrap();
        unsafe {ffi::setstring(self.o, path.as_bytes(), data); }
    }

    // Shortcut for attr("key", ...)
    pub fn key<'b>(&'b mut self, data: &'b[u8]) {
        unsafe {ffi::setstring(self.o, "key\0".as_bytes(), data); }
    }

    // Shortcut for attr("key_b", ...)
    // This allows setting a secondary key.
    pub fn key_b<'b>(&'b mut self, data: &'b[u8]) {
        unsafe {ffi::setstring(self.o, "key_b\0".as_bytes(), data); }
    }

    // Shortcut for attr("value", ...)
    pub fn value<'b>(&'b mut self, data: &'b[u8]) {
        unsafe {ffi::setstring(self.o, "value\0".as_bytes(), data); }
    }

    // Shortcut for attr("val", ...)
    pub fn val<'b>(&'b mut self, data: &'b[u8]) {
        self.value(data)
    }

    // Shortcut for attr("order", ...)
    pub fn order<'b>(&'b mut self, data: &'b[u8]) {
        unsafe {ffi::setstring(self.o, "order\0".as_bytes(), data); }
    }

    // Shortcut for attr("prefix", ...)
    pub fn prefix<'b>(&'b mut self, data: &'b[u8]) {
        unsafe {ffi::setstring(self.o, "prefix\0".as_bytes(), data); }
    }
}

impl<'a> Drop for Object<'a> {
    fn drop(&mut self) {
        if !self.o.is_null() {
            unsafe {ffi::sp_destroy(self.o)};
        }
    }
}

#[derive(Debug)]
pub struct ResultObject<'a> {
    o: ffi::Voidptr,
    phantom: PhantomData<&'a ()>,
}

impl<'a> ResultObject<'a> {
    fn get_<'b>(&'b self, key: &'b [u8]) -> Option<&'b[u8]> {
        unsafe {
            let mut sz = 0;
            let valptr = ffi::sp_getstring(self.o, key.as_ptr(), &mut sz);

            // XXX: what if we stored an empty value?
            if valptr.is_null() {
                return None;
            }

            let s = slice::from_raw_parts(valptr as *const u8, sz as usize);
            return Some(s);
        }

    }
    pub fn get_value<'b>(&'b self) -> Option<&'b[u8]> {
        self.get_(b"value\0")
    }

    pub fn get_key<'b>(&'b self) -> Option<&'b[u8]> {
        self.get_(b"key\0")
    }

    pub fn get_key_b<'b>(&'b self) -> Option<&'b[u8]> {
        self.get_(b"key_b\0")
    }
}

impl<'a> Drop for ResultObject<'a> {
    fn drop(&mut self) {
        if !self.o.is_null() {
            unsafe {ffi::sp_destroy(self.o)};
        }
    }
}

#[derive(Debug)]
pub struct Transaction<'a> {
    tx: ffi::Voidptr,
    phantom: PhantomData<&'a ()>
}

impl<'a> Drop for Transaction<'a> {
    // Unless commit() is called, this will roll back the transaction
    fn drop(&mut self) {
        if !self.tx.is_null() {
            unsafe {ffi::sp_destroy(self.tx);}
        }
    }
}

pub struct Cursor<'a> {
    obj: ffi::Voidptr,
    phantom: PhantomData<&'a ()>
}

impl<'a> Drop for Cursor<'a> {
    fn drop(&mut self) {
        unsafe {ffi::sp_destroy(self.obj);}
    }
}

impl<'a> Cursor<'a> {
    pub fn next<'b>(&'b self) -> Option<ResultObject<'b>> {
        let res = unsafe { ffi::sp_get(self.obj, ptr::null_mut()) };
        if res.is_null() {
            None
        }
        else {
            Some(ResultObject{o: res, phantom: PhantomData})
        }
    }
}

pub trait SetGetOps {
    fn backend(&self) -> ffi::Voidptr;

    // Consumes the Object
    fn set<'a>(&self, obj: Object<'a>) {
        let mut obj = obj;
        unsafe {ffi::sp_set(self.backend(), obj.o)}; // XXX: Check error code
        obj.o = ptr::null_mut(); // sp_set drops it
    }

    // XXX: Make sure self.db == dbobject.db
    fn get<'a, 'b>(&'a self, pattern: Object<'b>) -> Option<ResultObject<'a>> {
        unsafe {
            let res = ffi::sp_get(self.backend(), pattern.o);
            if res.is_null() {
                return None;
            }
            let n = ResultObject {
                o: pattern.o,
                phantom: PhantomData
            };
            let mut pattern = pattern;
            pattern.o = ptr::null_mut();
            return Some(n);
        }
    }

    fn cursor<'a, 'b>(&'a self, pattern: Object<'b>) -> Cursor<'a> {
        unsafe {
            let cursor = ffi::sp_cursor(self.backend(), pattern.o);
            assert!(!cursor.is_null());

            // pattern is freed as part of the Cursor
            let mut pattern = pattern;
            pattern.o = ptr::null_mut();

            Cursor {obj: cursor, phantom: PhantomData}
        }
    }
}

impl<'a> Transaction<'a> {
    pub fn commit(mut self) -> i32 {
        let rc = unsafe{ffi::sp_commit(self.tx)};
        self.tx = ptr::null_mut();
        rc as i32
    }
}

impl<'a> SetGetOps for Transaction<'a> {
    fn backend(&self) -> ffi::Voidptr { self.tx }
}

impl Env {
    pub fn new() -> Env {
        Env {env: unsafe{ffi::sp_env()}}
    }

    pub fn destroy(self) {
        unsafe{ffi::sp_destroy(self.env)};
    }

    pub fn db(&mut self, dbname: &str) {
        // XXX: is dbname copied?
        let dbname = CString::new(dbname).unwrap();
        unsafe {ffi::setstring(self.env, "db\0".as_bytes(), dbname.as_bytes()) };
    }

    pub fn open(&mut self) {
        unsafe {ffi::sp_open(self.env)};
    }

    pub fn begin<'a>(&'a self) -> Transaction<'a> {
        let tx = unsafe{ffi::sp_begin(self.env)};
        assert!(!tx.is_null());
        Transaction {
            tx: tx,
            phantom: PhantomData
        }
    }

    pub fn get_db(&self, dbname: &str) -> Option<Db> {
        let dbstr = "db.".to_string() + dbname;
        let attr = CString::new(&dbstr[..]).unwrap();
        unsafe {
            let obj = ffi::sp_getobject(self.env, attr.as_ptr() as *const u8);
            if obj.is_null() {
                None
            }
            else {
                Some(Db {db: obj})
            }
        }
    }

    pub fn setattr(&mut self, key: &str, val: &str) {
        let key = CString::new(key).unwrap();
        let val = CString::new(val).unwrap();
        unsafe {ffi::setstring(self.env, key.as_bytes(), val.as_bytes()) };
    }

    pub fn setintattr(&mut self, key: &str, val: i64) {
        let key = CString::new(key).unwrap();
        unsafe {ffi::sp_setint(self.env, key.as_ptr(), val) };
    }
}

impl SetGetOps for Db {
    fn backend(&self) -> ffi::Voidptr { self.db }
}

impl Db {
    pub fn obj<'a>(&'a self) -> Object<'a> {
        let obj = unsafe { ffi::sp_object(self.db) };
        assert!(!obj.is_null());
        Object{o: obj, phantom: PhantomData}
    }

}
<|endoftext|>


<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2015 Johan Johansson
//
// 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.

//! Capture the screen with xlib

#![feature(unique)]
#![allow(dead_code, non_upper_case_globals)]

extern crate x11;
extern crate libc;

use ffi::*;
use x11::{xlib, xrandr};
use libc::c_int;
use std::ffi::CString;
use std::ptr::{self, Unique};
use std::slice;

pub mod ffi;

#[derive(Debug, Eq, PartialEq, Clone, Copy)]
#[repr(C)]
pub struct Bgr8 {
    pub b: u8,
    pub g: u8,
    pub r: u8,
    _pad: u8,
}

pub enum Display {
    Address(&'static str),
    Default,
}

#[derive(Clone, Copy)]
pub enum Screen {
    Specific(c_int),
    Default,
}

#[derive(Clone, Copy)]
pub enum Window {
    Window(xlib::Window),
    Desktop,
}

struct WindowConnection {
    display: Unique<xlib::Display>,
    window: xlib::Window,
    width: u32,
    height: u32,
}
impl WindowConnection {
    unsafe fn new(display: Display,
                  screen: Screen,
                  window: Window)
                  -> Result<WindowConnection, ()> {
        let addr = if let Display::Address(address) = display {
            match CString::new(address) {
                Ok(s) => s.as_ptr(),
                Err(_) => return Err(()),
            }
        } else {
            ptr::null()
        };

        let display_ptr = Unique::new(xlib::XOpenDisplay(addr));

        if !display_ptr.is_null() {
            let screen_num = if let Screen::Specific(n) = screen {
                n
            } else {
                xlib::XDefaultScreen(*display_ptr)
            };

            let mut window_id = if let Window::Window(id) = window {
                id
            } else {
                xlib::XRootWindow(*display_ptr, screen_num)
            };

            let (mut window_width, mut window_height) = (0, 0);

            let geo_result = xlib::XGetGeometry(*display_ptr,
                                                window_id,
                                                &mut window_id,
                                                &mut 0,
                                                &mut 0,
                                                &mut window_width,
                                                &mut window_height,
                                                &mut 0,
                                                &mut 0);

            if geo_result != 0 {
                Ok(WindowConnection {
                    display: display_ptr,
                    window: window_id,
                    width: window_width,
                    height: window_height,
                })
            } else {
                Err(())
            }
        } else {
            Err(())
        }
    }
}
impl Drop for WindowConnection {
    fn drop(&mut self) {
        unsafe {
            xlib::XCloseDisplay(*self.display);
        }
    }
}

/// Possible errors when capturing
#[derive(Debug)]
pub enum CaptureError {
    Fail(&'static str),
}

/// Capture either a region of the total display area,
/// or capture the output of a specific monitor
pub enum CaptureSource {
    Region {
        x: i32,
        y: i32,
        width: u32,
        height: u32,
    },
    Monitor(usize),
}

#[derive(Clone, Copy)]
pub struct Geometry {
    pub x: i32,
    pub y: i32,
    pub width: u32,
    pub height: u32,
}

pub struct Capturer {
    window_conn: WindowConnection,
    geo: Geometry,
}
impl Capturer {
    pub fn new(capture_src: CaptureSource) -> Result<Capturer, ()> {
        match unsafe { WindowConnection::new(Display::Default, Screen::Default, Window::Desktop) } {
            Ok(conn) => {
                let (x, y, w, h) = match capture_src {
                    CaptureSource::Region { x, y, width, height } => (x, y, width, height),
                    CaptureSource::Monitor(mon_i) => {
                        let mut n_mons = 0;
                        let mons = unsafe {
                            xrandr::XRRGetMonitors(*conn.display, conn.window, 1, &mut n_mons)
                        };
                        let mons = unsafe { slice::from_raw_parts_mut(mons, n_mons as usize) };
                        let mon = mons[mon_i];
                        (mon.x, mon.y, mon.width as u32, mon.height as u32)
                    }
                };

                Ok(Capturer {
                    window_conn: conn,
                    geo: Geometry {
                        width: w,
                        height: h,
                        x: x,
                        y: y,
                    },
                })
            }
            Err(_) => Err(()),
        }
    }

    pub fn get_geometry(&self) -> Geometry {
        self.geo
    }

    pub fn capture_frame(&mut self) -> Result<Vec<Bgr8>, CaptureError> {
        let image_ptr = unsafe {
            xlib::XGetImage(*self.window_conn.display,
                            self.window_conn.window,
                            self.geo.x,
                            self.geo.y,
                            self.geo.width,
                            self.geo.height,
                            AllPlanes,
                            ZPixmap)
        };

        if !image_ptr.is_null() {
            let image = unsafe { &mut *image_ptr };

            unsafe {
                if image.depth == 24 && image.bits_per_pixel == 32 &&
                   image.red_mask == 0xFF0000 && image.green_mask == 0xFF00 &&
                   image.blue_mask == 0xFF {

                    // It's plain (Bgr8 + padding)s in memory
                    let raw_img_data = slice::from_raw_parts(image.data as *mut Bgr8,
                                                             image.width as usize *
                                                             image.height as usize)
                        .to_vec();

                    xlib::XDestroyImage(image_ptr);

                    Ok(raw_img_data)
                } else {
                    xlib::XDestroyImage(image_ptr as *mut _);

                    Err(CaptureError::Fail("WRONG LAYOUT"))
                }
            }
        } else {
            Err(CaptureError::Fail("XGetImage returned null pointer"))
        }
    }
}
<commit_msg>On master: return Image<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2015 Johan Johansson
//
// 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.

//! Capture the screen with xlib

#![feature(unique)]
#![allow(dead_code, non_upper_case_globals)]

extern crate x11;
extern crate libc;

use ffi::*;
use libc::c_int;
use std::ffi::CString;
use std::ptr::{self, Unique};
use std::slice;
use x11::{xlib, xrandr};

pub mod ffi;

#[derive(Debug, Eq, PartialEq, Clone, Copy)]
#[repr(C)]
pub struct Bgr8 {
    pub b: u8,
    pub g: u8,
    pub r: u8,
    _pad: u8,
}

enum Display {
    Address(&'static str),
    Default,
}

#[derive(Clone, Copy)]
enum Screen {
    Specific(c_int),
    Default,
}

#[derive(Clone, Copy)]
enum Window {
    Window(xlib::Window),
    Desktop,
}

struct WindowConnection {
    display: Unique<xlib::Display>,
    window: xlib::Window,
    width: u32,
    height: u32,
}
impl WindowConnection {
    unsafe fn new(display: Display,
                  screen: Screen,
                  window: Window)
                  -> Result<WindowConnection, ()> {
        let addr = if let Display::Address(address) = display {
            match CString::new(address) {
                Ok(s) => s.as_ptr(),
                Err(_) => return Err(()),
            }
        } else {
            ptr::null()
        };

        let display_ptr = Unique::new(xlib::XOpenDisplay(addr));

        if !display_ptr.is_null() {
            let screen_num = if let Screen::Specific(n) = screen {
                n
            } else {
                xlib::XDefaultScreen(*display_ptr)
            };

            let mut window_id = if let Window::Window(id) = window {
                id
            } else {
                xlib::XRootWindow(*display_ptr, screen_num)
            };

            let (mut window_width, mut window_height) = (0, 0);

            let geo_result = xlib::XGetGeometry(*display_ptr,
                                                window_id,
                                                &mut window_id,
                                                &mut 0,
                                                &mut 0,
                                                &mut window_width,
                                                &mut window_height,
                                                &mut 0,
                                                &mut 0);

            if geo_result != 0 {
                Ok(WindowConnection {
                    display: display_ptr,
                    window: window_id,
                    width: window_width,
                    height: window_height,
                })
            } else {
                Err(())
            }
        } else {
            Err(())
        }
    }
}
impl Drop for WindowConnection {
    fn drop(&mut self) {
        unsafe {
            xlib::XCloseDisplay(*self.display);
        }
    }
}

/// Possible errors when capturing
#[derive(Debug)]
pub enum CaptureError {
    Fail(&'static str),
}

/// Capture either a region of the total display area,
/// or capture the output of a specific monitor
pub enum CaptureSource {
    Region {
        x: i32,
        y: i32,
        width: u32,
        height: u32,
    },
    Monitor(usize),
}

#[derive(Clone, Copy)]
pub struct Geometry {
    pub x: i32,
    pub y: i32,
    pub width: u32,
    pub height: u32,
}

/// A captured image
///
/// Wrapper that guarantees correct destruction
#[derive(Debug)]
pub struct Image {
    image: *mut xlib::XImage,
}

impl Image {
    pub fn as_slice(&self) -> &[Bgr8] {
        // It's plain (Bgr8 + padding)s in memory
        unsafe {
            slice::from_raw_parts((*self.image).data as *const _,
                                  (*self.image).width as usize * (*self.image).height as usize)
        }
    }

    pub fn get_dimensions(&self) -> (u32, u32) {
        unsafe { ((*self.image).width as u32, (*self.image).height as u32) }
    }
}

impl Drop for Image {
    fn drop(&mut self) {
        unsafe {
            xlib::XDestroyImage(self.image);
        }
    }
}

pub struct Capturer {
    window_conn: WindowConnection,
    geo: Geometry,
}
impl Capturer {
    pub fn new(capture_src: CaptureSource) -> Result<Capturer, ()> {
        match unsafe { WindowConnection::new(Display::Default, Screen::Default, Window::Desktop) } {
            Ok(conn) => {
                let (x, y, w, h) = match capture_src {
                    CaptureSource::Region { x, y, width, height } => (x, y, width, height),
                    CaptureSource::Monitor(mon_i) => {
                        let mut n_mons = 0;
                        let mons = unsafe {
                            xrandr::XRRGetMonitors(*conn.display, conn.window, 1, &mut n_mons)
                        };
                        let mons = unsafe { slice::from_raw_parts_mut(mons, n_mons as usize) };
                        let mon = mons[mon_i];
                        (mon.x, mon.y, mon.width as u32, mon.height as u32)
                    }
                };

                Ok(Capturer {
                    window_conn: conn,
                    geo: Geometry {
                        width: w,
                        height: h,
                        x: x,
                        y: y,
                    },
                })
            }
            Err(_) => Err(()),
        }
    }

    pub fn get_geometry(&self) -> Geometry {
        self.geo
    }

    pub fn capture_frame(&mut self) -> Result<Image, CaptureError> {
        let image_ptr = unsafe {
            xlib::XGetImage(*self.window_conn.display,
                            self.window_conn.window,
                            self.geo.x,
                            self.geo.y,
                            self.geo.width,
                            self.geo.height,
                            AllPlanes,
                            ZPixmap)
        };

        if !image_ptr.is_null() {
            let image = unsafe { &mut *image_ptr };

            unsafe {
                if image.depth == 24 && image.bits_per_pixel == 32 &&
                   image.red_mask == 0xFF0000 && image.green_mask == 0xFF00 &&
                   image.blue_mask == 0xFF {

                    let image = Image { image: image_ptr };

                    Ok(image)
                } else {
                    xlib::XDestroyImage(image_ptr as *mut _);

                    Err(CaptureError::Fail("Wrong layout"))
                }
            }
        } else {
            Err(CaptureError::Fail("XGetImage returned null pointer"))
        }
    }
}
<|endoftext|>


<commit_before>//! indicatif is a library for Rust that helps you build command line
//! interfaces that report progress to users.  It comes with various
//! tools and utilities for formatting anything that indicates progress.
//!
//! Platform support:
//!
//! * Linux
//! * OS X
//! * Windows (colors require Windows 10)
//!
//! Best paired with other libraries in the family:
//!
//! * [console](https://docs.rs/console)
//! * [dialoguer](https://docs.rs/dialoguer)
//!
//! # Crate Contents
//!
//! * **Progress bars**
//!   * [`ProgressBar`](struct.ProgressBar.html) for bars and spinners
//!   * [`MultiProgress`](struct.MultiProgress.html) for multiple bars
//! * **Data Formatting**
//!   * [`HumanBytes`](struct.HumanBytes.html) for formatting bytes
//!   * [`DecimalBytes`](struct.DecimalBytes.html) for formatting bytes using SI prefixes
//!   * [`BinaryBytes`](struct.BinaryBytes.html) for formatting bytes using ISO/IEC prefixes
//!   * [`HumanDuration`](struct.HumanDuration.html) for formatting durations
//!
//! # Progress Bars and Spinners
//!
//! indicatif comes with a `ProgressBar` type that supports both bounded
//! progress bar uses as well as unbounded "spinner" type progress reports.
//! Progress bars are `Sync` and `Send` objects which means that they are
//! internally locked and can be passed from thread to thread.
//!
//! Additionally a `MultiProgress` utility is provided that can manage
//! rendering multiple progress bars at once (eg: from multiple threads).
//!
//! To whet your appetite, this is what this can look like:
//!
//!
//!
//! Progress bars are manually advanced and by default draw to stderr.
//! When you are done, the progress bar can be finished either visibly
//! (eg: the progress bar stays on the screen) or cleared (the progress
//! bar will be removed).
//!
//! ```rust
//! use indicatif::ProgressBar;
//!
//! let bar = ProgressBar::new(1000);
//! for _ in 0..1000 {
//!     bar.inc(1);
//!     // ...
//! }
//! bar.finish();
//! ```
//!
//! General progress bar behaviors:
//!
//! * if a non terminal is detected the progress bar will be completely
//!   hidden.  This makes piping programs to logfiles make sense out of
//!   the box.
//! * a progress bar only starts drawing when `set_message`, `inc`, `set_position`
//!   or `tick` are called.  In some situations you might have to call `tick`
//!   once to draw it.
//! * progress bars should be explicitly finished to reset the rendering
//!   for others.  Either by also clearing them or by replacing them with
//!   a new message / retaining the current message.
//! * the default template renders neither message nor prefix.
//!
//! # Iterators
//!
//! Similar to [tqdm](https://github.com/tqdm/tqdm), progress bars can be
//! associated with an iterator. For example:
//!
//! ```rust
//! use indicatif::ProgressIterator;
//!
//! for _ in (0..1000).progress() {
//!     // ...
//! }
//! ```
//!
//! See the [`ProgressIterator`](trait.ProgressIterator.html) trait for more
//! methods to configure the number of elements in the iterator or change
//! the progress bar style. Indicatif also has optional support for parallel
//! iterators with [Rayon](https://github.com/rayon-rs/rayon). In your
//! `cargo.toml`, use the "rayon" feature:
//!
//! ```toml
//! [dependencies]
//! indicatif = {version = "*", features = ["rayon"]}
//! ```
//!
//! And then use it like this:
//!
//! ```rust,ignore
//! # extern crate rayon;
//! use indicatif::ParallelProgressIterator;
//! use rayon::iter::{ParallelIterator, IntoParallelRefIterator};
//!
//! let v: Vec<_> = (0..100000).collect();
//! let v2: Vec<_> = v.par_iter().progress().map(|i| i + 1).collect();
//! assert_eq!(v2[0], 1);
//! ```
//!
//! # Templates
//!
//! Progress bars can be styled with simple format strings similar to the
//! ones in Rust itself.  The format for a placeholder is `{key:options}`
//! where the `options` part is optional.  If provided the format is this:
//!
//! ```text
//! [<^>]           for an optional alignment specification
//! WIDTH           an optional width as positive integer
//! !               an optional exclamation mark to enable truncation
//! .STYLE          an optional dot separated style string
//! /STYLE          an optional dot separated alternative style string
//! ```
//!
//! For the style component see [`Style::from_dotted_str`](https://docs.rs/console/0.7.5/console/struct.Style.html#method.from_dotted_str)
//! for more information.  Indicatif uses the `console` base crate for all
//! colorization and formatting options.
//!
//! Some examples for templates:
//!
//! ```text
//! [{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}
//! ```
//!
//! This sets a progress bar that is 40 characters wide and has cyan
//! as primary style color and blue as alternative style color.
//! Alternative styles are currently only used for progress bars.
//!
//! Example configuration:
//!
//! ```ignore
//! bar.set_style(ProgressStyle::default_bar()
//!     .template("[{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}")
//!     .progress_chars("##-"));
//! ```
//!
//! The following keys exist:
//!
//! * `bar`: renders a progress bar. By default 20 characters wide.  The
//!   style string is used to color the elapsed part, the alternative
//!   style is used for the bar that is yet to render.
//! * `wide_bar`: like `bar` but always fills the remaining space.
//! * `spinner`: renders the spinner (current tick string).
//! * `prefix`: renders the prefix set on the progress bar.
//! * `msg`: renders the currently set message on the progress bar.
//! * `wide_msg`: like `msg` but always fills the remaining space and truncates.
//! * `pos`: renders the current position of the bar as integer
//! * `len`: renders the total length of the bar as integer
//! * `bytes`: renders the current position of the bar as bytes.
//! * `percent`: renders the current position of the bar as a percentage of the total length.
//! * `total_bytes`: renders the total length of the bar as bytes.
//! * `elapsed_precise`: renders the elapsed time as `HH:MM:SS`.
//! * `elapsed`: renders the elapsed time as `42s`, `1m` etc.
//! * `per_sec`: renders the speed in steps per second.
//! * `bytes_per_sec`: renders the speed in bytes per second.
//! * `eta_precise`: the remaining time (like `elapsed_precise`).
//! * `eta`: the remaining time (like `elapsed`).
//! * `duration_precise`: the extrapolated total duration (like `elapsed_precise`).
//! * `duration`: the extrapolated total duration time (like `elapsed`).

//!
//! The design of the progress bar can be altered with the integrated
//! template functionality.  The template can be set by changing a
//! `ProgressStyle` and attaching it to the progress bar.
//!
//! # Human Readable Formatting
//!
//! There are some formatting wrappers for showing elapsed time and
//! file sizes for human users:
//!
//! ```ignore
//! use std::time::Instant;
//! use indicatif::{HumanDuration, HumanBytes};
//!
//! let started = Instant::now();
//! println!("The file is {} large", HumanBytes(file.size));
//! println!("The script took {}", HumanDuration(started.elapsed()));
//! ```
//!
//! # Feature Flags
//!
//! * `rayon`: adds rayon support
//! * `improved_unicode`: adds improved unicode support (graphemes, better width calculation)

mod format;
mod iter;
mod progress;
mod style;
mod utils;

pub use crate::format::{BinaryBytes, DecimalBytes, FormattedDuration, HumanBytes, HumanDuration};
pub use crate::iter::{ProgressBarIter, ProgressIterator};
pub use crate::progress::{
    MultiProgress, ProgressBar, ProgressBarWrap, ProgressDrawTarget, WeakProgressBar,
};
pub use crate::style::ProgressStyle;

#[cfg(feature = "rayon")]
pub use iter::rayon_support::{ParProgressBarIter, ParallelProgressIterator};
<commit_msg>Various minor lib.rs improvements<commit_after>//! indicatif is a library for Rust that helps you build command line
//! interfaces that report progress to users.  It comes with various
//! tools and utilities for formatting anything that indicates progress.
//!
//! Platform support:
//!
//! * Linux
//! * OS X
//! * Windows (colors require Windows 10)
//!
//! Best paired with other libraries in the family:
//!
//! * [console](https://docs.rs/console)
//! * [dialoguer](https://docs.rs/dialoguer)
//!
//! # Crate Contents
//!
//! * **Progress bars**
//!   * [`ProgressBar`](struct.ProgressBar.html) for bars and spinners
//!   * [`MultiProgress`](struct.MultiProgress.html) for multiple bars
//! * **Data Formatting**
//!   * [`HumanBytes`](struct.HumanBytes.html) for formatting bytes
//!   * [`DecimalBytes`](struct.DecimalBytes.html) for formatting bytes using SI prefixes
//!   * [`BinaryBytes`](struct.BinaryBytes.html) for formatting bytes using ISO/IEC prefixes
//!   * [`HumanDuration`](struct.HumanDuration.html) for formatting durations
//!
//! # Progress Bars and Spinners
//!
//! indicatif comes with a `ProgressBar` type that supports both bounded
//! progress bar uses as well as unbounded "spinner" type progress reports.
//! Progress bars are `Sync` and `Send` objects which means that they are
//! internally locked and can be passed from thread to thread.
//!
//! Additionally a `MultiProgress` utility is provided that can manage
//! rendering multiple progress bars at once (eg: from multiple threads).
//!
//! To whet your appetite, this is what this can look like:
//!
//!
//!
//! Progress bars are manually advanced and by default draw to stderr.
//! When you are done, the progress bar can be finished either visibly
//! (eg: the progress bar stays on the screen) or cleared (the progress
//! bar will be removed).
//!
//! ```rust
//! use indicatif::ProgressBar;
//!
//! let bar = ProgressBar::new(1000);
//! for _ in 0..1000 {
//!     bar.inc(1);
//!     // ...
//! }
//! bar.finish();
//! ```
//!
//! General progress bar behaviors:
//!
//! * if a non terminal is detected the progress bar will be completely
//!   hidden.  This makes piping programs to logfiles make sense out of
//!   the box.
//! * a progress bar only starts drawing when `set_message`, `inc`, `set_position`
//!   or `tick` are called.  In some situations you might have to call `tick`
//!   once to draw it.
//! * progress bars should be explicitly finished to reset the rendering
//!   for others.  Either by also clearing them or by replacing them with
//!   a new message / retaining the current message.
//! * the default template renders neither message nor prefix.
//!
//! # Iterators
//!
//! Similar to [tqdm](https://github.com/tqdm/tqdm), progress bars can be
//! associated with an iterator. For example:
//!
//! ```rust
//! use indicatif::ProgressIterator;
//!
//! for _ in (0..1000).progress() {
//!     // ...
//! }
//! ```
//!
//! See the [`ProgressIterator`](trait.ProgressIterator.html) trait for more
//! methods to configure the number of elements in the iterator or change
//! the progress bar style. Indicatif also has optional support for parallel
//! iterators with [Rayon](https://github.com/rayon-rs/rayon). In your
//! `Cargo.toml`, use the "rayon" feature:
//!
//! ```toml
//! [dependencies]
//! indicatif = {version = "*", features = ["rayon"]}
//! ```
//!
//! And then use it like this:
//!
//! ```rust,ignore
//! # extern crate rayon;
//! use indicatif::ParallelProgressIterator;
//! use rayon::iter::{ParallelIterator, IntoParallelRefIterator};
//!
//! let v: Vec<_> = (0..100000).collect();
//! let v2: Vec<_> = v.par_iter().progress_count(v.len() as u64).map(|i| i + 1).collect();
//! assert_eq!(v2[0], 1);
//! ```
//!
//! # Templates
//!
//! Progress bars can be styled with simple format strings similar to the
//! ones in Rust itself.  The format for a placeholder is `{key:options}`
//! where the `options` part is optional.  If provided the format is this:
//!
//! ```text
//! [<^>]           for an optional alignment specification
//! WIDTH           an optional width as positive integer
//! !               an optional exclamation mark to enable truncation
//! .STYLE          an optional dot separated style string
//! /STYLE          an optional dot separated alternative style string
//! ```
//!
//! For the style component see [`Style::from_dotted_str`](https://docs.rs/console/0.7.5/console/struct.Style.html#method.from_dotted_str)
//! for more information.  Indicatif uses the `console` base crate for all
//! colorization and formatting options.
//!
//! Some examples for templates:
//!
//! ```text
//! [{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}
//! ```
//!
//! This sets a progress bar that is 40 characters wide and has cyan
//! as primary style color and blue as alternative style color.
//! Alternative styles are currently only used for progress bars.
//!
//! Example configuration:
//!
//! ```rust
//! # use indicatif::{ProgressBar, ProgressStyle};
//! # let bar = ProgressBar::new(0);
//! bar.set_style(ProgressStyle::default_bar()
//!     .template("[{elapsed_precise}] {bar:40.cyan/blue} {pos:>7}/{len:7} {msg}")
//!     .progress_chars("##-"));
//! ```
//!
//! The following keys exist:
//!
//! * `bar`: renders a progress bar. By default 20 characters wide.  The
//!   style string is used to color the elapsed part, the alternative
//!   style is used for the bar that is yet to render.
//! * `wide_bar`: like `bar` but always fills the remaining space.
//! * `spinner`: renders the spinner (current tick string).
//! * `prefix`: renders the prefix set on the progress bar.
//! * `msg`: renders the currently set message on the progress bar.
//! * `wide_msg`: like `msg` but always fills the remaining space and truncates.
//! * `pos`: renders the current position of the bar as integer
//! * `len`: renders the total length of the bar as integer
//! * `bytes`: renders the current position of the bar as bytes.
//! * `percent`: renders the current position of the bar as a percentage of the total length.
//! * `total_bytes`: renders the total length of the bar as bytes.
//! * `elapsed_precise`: renders the elapsed time as `HH:MM:SS`.
//! * `elapsed`: renders the elapsed time as `42s`, `1m` etc.
//! * `per_sec`: renders the speed in steps per second.
//! * `bytes_per_sec`: renders the speed in bytes per second.
//! * `eta_precise`: the remaining time (like `elapsed_precise`).
//! * `eta`: the remaining time (like `elapsed`).
//! * `duration_precise`: the extrapolated total duration (like `elapsed_precise`).
//! * `duration`: the extrapolated total duration time (like `elapsed`).

//!
//! The design of the progress bar can be altered with the integrated
//! template functionality.  The template can be set by changing a
//! `ProgressStyle` and attaching it to the progress bar.
//!
//! # Human Readable Formatting
//!
//! There are some formatting wrappers for showing elapsed time and
//! file sizes for human users:
//!
//! ```rust
//! # use std::time::Duration;
//! use indicatif::{HumanDuration, HumanBytes};
//!
//! assert_eq!("3.00MB", HumanBytes(3*1024*1024).to_string());
//! assert_eq!("8 seconds", HumanDuration(Duration::from_secs(8)).to_string());
//! ```
//!
//! # Feature Flags
//!
//! * `rayon`: adds rayon support
//! * `improved_unicode`: adds improved unicode support (graphemes, better width calculation)

mod format;
mod iter;
mod progress;
mod style;
mod utils;

pub use crate::format::{BinaryBytes, DecimalBytes, FormattedDuration, HumanBytes, HumanDuration};
pub use crate::iter::{ProgressBarIter, ProgressIterator};
pub use crate::progress::{
    MultiProgress, ProgressBar, ProgressBarWrap, ProgressDrawTarget, WeakProgressBar,
};
pub use crate::style::ProgressStyle;

#[cfg(feature = "rayon")]
pub use iter::rayon_support::{ParProgressBarIter, ParallelProgressIterator};
<|endoftext|>


<commit_before>//! A [TOML]-parsing library
//!
//! [TOML]: https://github.com/toml-lang/toml
//!
//! This library implements a [TOML] v0.4.0 compatible parser. This crate also
//! primarily supports the [`serde`] library for encoding/decoding support to
//! various types in Rust.
//!
//! TOML itself is a simple, ergonomic, and readable configuration format:
//!
//! ```toml
//! [package]
//! name = "toml"
//! version = "0.2.1"
//! authors = ["Alex Crichton <alex@alexcrichton.com>"]
//!
//! [dependencies]
//! serde = "0.9"
//! ```
//!
//! The TOML format tends to be relatively common throughout the Rust community
//! for configuration, notably being used by [Cargo], Rust's package manager.
//!
//! ## TOML values
//!
//! A value in TOML is represented with the `Value` enum in this crate:
//!
//! ```rust,ignore
//! pub enum Value {
//!     String(String),
//!     Integer(i64),
//!     Float(f64),
//!     Boolean(bool),
//!     Datetime(Datetime),
//!     Array(Array),
//!     Table(Table),
//! }
//! ```
//!
//! You'll note that TOML is very similar to JSON with the notable addition of a
//! `Datetime` type. In general TOML and JSON are interchangeable in terms of
//! formats.
//!
//! ## Parsing TOML
//!
//! The easiest way to parse a TOML document is via the `Value` type:
//!
//! ```rust
//! use toml::Value;
//!
//! let value = "foo = 'bar'".parse::<Value>().unwrap();
//!
//! assert_eq!(value["foo"].as_str(), Some("bar"));
//! ```
//!
//! The `Value` type implements a number of convenience methods and traits,
//! where the example above is using `FromStr` to parse a `str` into a `Value`.
//!
//! ## Deserialization and Serialization
//!
//! This crate currently supports [`serde`] 0.9 with a number of
//! implementations of the `Deserialize`, `Serialize`, `Deserializer`, and
//! `Serializer` traits. Namely, you'll find in this crate:
//!
//! * `Deserialize for Value`
//! * `Serialize for Value`
//! * `Deserialize for Datetime`
//! * `Serialize for Datetime`
//!
//! * `Deserializer for de::Deserializer`
//! * `Serializer for ser::Serializer`
//! * `Deserializer for Value`
//!
//! This notably means that you can use Serde to deserialize/serialize the
//! `Value` type as well as the `Datetime` type in this crate. Similarly you can
//! use the `Deserializer`, `Serializer`, or `Value` type itself to act as
//! a deserializer/serializer for arbitrary types.
//!
//! An example of deserializing with TOML is:
//!
//! ```rust
//! #[macro_use]
//! extern crate serde_derive;
//! extern crate toml;
//!
//! #[derive(Deserialize)]
//! struct Config {
//!     ip: String,
//!     port: Option<u16>,
//!     keys: Keys,
//! }
//!
//! #[derive(Deserialize)]
//! struct Keys {
//!     github: String,
//!     travis: Option<String>,
//! }
//!
//! fn main() {
//!     let config: Config = toml::from_str(r#"
//!         ip = '127.0.0.1'
//!
//!         [keys]
//!         github = 'xxxxxxxxxxxxxxxxx'
//!         travis = 'yyyyyyyyyyyyyyyyy'
//!     "#).unwrap();
//!
//!     assert_eq!(config.ip, "127.0.0.1");
//!     assert_eq!(config.port, None);
//!     assert_eq!(config.keys.github, "xxxxxxxxxxxxxxxxx");
//!     assert_eq!(config.keys.travis.as_ref().unwrap(), "yyyyyyyyyyyyyyyyy");
//! }
//! ```
//!
//! Similarly you can serialize types in a similar fashion:
//!
//! ```rust
//! #[macro_use]
//! extern crate serde_derive;
//! extern crate toml;
//!
//! #[derive(Serialize)]
//! struct Config {
//!     ip: String,
//!     port: Option<u16>,
//!     keys: Keys,
//! }
//!
//! #[derive(Serialize)]
//! struct Keys {
//!     github: String,
//!     travis: Option<String>,
//! }
//!
//! fn main() {
//!     let config = Config {
//!         ip: "127.0.0.1".to_string(),
//!         port: None,
//!         keys: Keys {
//!             github: "xxxxxxxxxxxxxxxxx".to_string(),
//!             travis: Some("yyyyyyyyyyyyyyyyy".to_string()),
//!         },
//!     };
//!
//!     let toml = toml::to_string(&config).unwrap();
//! }
//! ```
//!
//! [Cargo]: https://crates.io/
//! [`serde`]: https://serde.rs/

#![doc(html_root_url = "https://docs.rs/toml/0.3")]
#![deny(missing_docs)]

#[macro_use]
extern crate serde;

pub mod value;
mod datetime;
#[doc(no_inline)]
pub use value::Value;

pub mod ser;
#[doc(no_inline)]
pub use ser::{to_string, to_vec, Serializer};
pub mod de;
#[doc(no_inline)]
pub use de::{from_slice, from_str, Deserializer};
mod tokens;
<commit_msg>Tighten up the crate-level docs<commit_after>//! A [TOML]-parsing library
//!
//! [TOML]: https://github.com/toml-lang/toml
//!
//! This library implements a [TOML] v0.4.0 compatible parser,
//! primarily supporting the [`serde`] library for encoding/decoding
//! various types in Rust.
//!
//! TOML itself is a simple, ergonomic, and readable configuration format:
//!
//! ```toml
//! [package]
//! name = "toml"
//! version = "0.2.1"
//! authors = ["Alex Crichton <alex@alexcrichton.com>"]
//!
//! [dependencies]
//! serde = "0.9"
//! ```
//!
//! The TOML format tends to be relatively common throughout the Rust community
//! for configuration, notably being used by [Cargo], Rust's package manager.
//!
//! ## TOML values
//!
//! A value in TOML is represented with the `Value` enum in this crate:
//!
//! ```rust,ignore
//! pub enum Value {
//!     String(String),
//!     Integer(i64),
//!     Float(f64),
//!     Boolean(bool),
//!     Datetime(Datetime),
//!     Array(Array),
//!     Table(Table),
//! }
//! ```
//!
//! TOML is similar to JSON with the notable addition of a `Datetime`
//! type. In general, TOML and JSON are interchangeable in terms of
//! formats.
//!
//! ## Parsing TOML
//!
//! The easiest way to parse a TOML document is via the `Value` type:
//!
//! ```rust
//! use toml::Value;
//!
//! let value = "foo = 'bar'".parse::<Value>().unwrap();
//!
//! assert_eq!(value["foo"].as_str(), Some("bar"));
//! ```
//!
//! The `Value` type implements a number of convenience methods and
//! traits; the example above uses `FromStr` to parse a `str` into a
//! `Value`.
//!
//! ## Deserialization and Serialization
//!
//! This crate supports [`serde`] 0.9 with a number of
//! implementations of the `Deserialize`, `Serialize`, `Deserializer`, and
//! `Serializer` traits. Namely, you'll find:
//!
//! * `Deserialize for Value`
//! * `Serialize for Value`
//! * `Deserialize for Datetime`
//! * `Serialize for Datetime`
//!
//! * `Deserializer for de::Deserializer`
//! * `Serializer for ser::Serializer`
//! * `Deserializer for Value`
//!
//! This means that you can use Serde to deserialize/serialize the
//! `Value` type as well as the `Datetime` type in this crate. You can also
//! use the `Deserializer`, `Serializer`, or `Value` type itself to act as
//! a deserializer/serializer for arbitrary types.
//!
//! An example of deserializing with TOML is:
//!
//! ```rust
//! #[macro_use]
//! extern crate serde_derive;
//! extern crate toml;
//!
//! #[derive(Deserialize)]
//! struct Config {
//!     ip: String,
//!     port: Option<u16>,
//!     keys: Keys,
//! }
//!
//! #[derive(Deserialize)]
//! struct Keys {
//!     github: String,
//!     travis: Option<String>,
//! }
//!
//! fn main() {
//!     let config: Config = toml::from_str(r#"
//!         ip = '127.0.0.1'
//!
//!         [keys]
//!         github = 'xxxxxxxxxxxxxxxxx'
//!         travis = 'yyyyyyyyyyyyyyyyy'
//!     "#).unwrap();
//!
//!     assert_eq!(config.ip, "127.0.0.1");
//!     assert_eq!(config.port, None);
//!     assert_eq!(config.keys.github, "xxxxxxxxxxxxxxxxx");
//!     assert_eq!(config.keys.travis.as_ref().unwrap(), "yyyyyyyyyyyyyyyyy");
//! }
//! ```
//!
//! You can serialize types in a similar fashion:
//!
//! ```rust
//! #[macro_use]
//! extern crate serde_derive;
//! extern crate toml;
//!
//! #[derive(Serialize)]
//! struct Config {
//!     ip: String,
//!     port: Option<u16>,
//!     keys: Keys,
//! }
//!
//! #[derive(Serialize)]
//! struct Keys {
//!     github: String,
//!     travis: Option<String>,
//! }
//!
//! fn main() {
//!     let config = Config {
//!         ip: "127.0.0.1".to_string(),
//!         port: None,
//!         keys: Keys {
//!             github: "xxxxxxxxxxxxxxxxx".to_string(),
//!             travis: Some("yyyyyyyyyyyyyyyyy".to_string()),
//!         },
//!     };
//!
//!     let toml = toml::to_string(&config).unwrap();
//! }
//! ```
//!
//! [Cargo]: https://crates.io/
//! [`serde`]: https://serde.rs/

#![doc(html_root_url = "https://docs.rs/toml/0.3")]
#![deny(missing_docs)]

#[macro_use]
extern crate serde;

pub mod value;
mod datetime;
#[doc(no_inline)]
pub use value::Value;

pub mod ser;
#[doc(no_inline)]
pub use ser::{to_string, to_vec, Serializer};
pub mod de;
#[doc(no_inline)]
pub use de::{from_slice, from_str, Deserializer};
mod tokens;
<|endoftext|>


<commit_before>//! This crate parses and processes hyper::server::Request data
//! containing multipart/form-data formatted data in a streaming
//! fashion.

#![feature(buf_stream,collections)]

extern crate hyper;

#[cfg(test)]
mod mock;
mod buf;
<commit_msg>expose BufReadPlus<commit_after>//! This crate parses and processes hyper::server::Request data
//! containing multipart/form-data formatted data in a streaming
//! fashion.

#![feature(buf_stream,collections)]

extern crate hyper;

#[cfg(test)]
mod mock;
pub mod buf;

pub use buf::BufReadPlus;
<|endoftext|>


<commit_before>//! Eudex is a Soundex-esque phonetic reduction/hashing algorithm, providing locality sensitive
//! "hashes" of words, based on the spelling and pronunciation.

#![cfg_attr(test, feature(test))]
#[cfg(test)]
extern crate test;

/// The sound table.
///
/// The first bit each describes a certain property of the phone:
///
/// | Position | Modifier | Property    | Phones   |
/// |----------|----------|-------------|----------|
/// | 1        | 1        | Nasal       | mn       |
/// | 2        | 2        | Plosive     | pbtdcgqk |
/// | 3        | 4        | Fricative   | fvsjxzhc |
/// | 4        | 8        | Approximant | vrhjwc   |
/// | 5        | 16       | Trill       | r        |
/// | 6        | 32       | Lateral     | l        |
/// | 7        | 64       | Type²       | mpbfv    |
/// | 8        | 128      | Confident¹  | lrxzq    |
///
/// ¹hard to misspell.
/// ²1 means labial or dorsal, 0 means apical.
const PHONES: [u64; LETTERS as usize] = [
    0, // a
    0b01000010, // b
    0b00001110, // c
    0b00000010, // d
    0, // e
    0b01000100, // f
    0b00000010, // g
    0b00001100, // h
    0, // i
    0b00001100, // j
    0b00000010, // k
    0b10100000, // l
    0b01000001, // m
    0b00000001, // n
    0, // o
    0b01000010, // p
    0b10000010, // q
    0b10011000, // r
    0b00000100, // s
    0b00000010, // t
    0, // u
    0b01001100, // v
    0b00001000, // w
    0b10000100, // x
    0, // y
    0b10000100, // z
];
const LETTERS: u8 =  26;

/// Phonetically hash this string.
///
/// This hashing function is based upon a phonetic reduction algorithm, and is locality sensitive.
///
/// This will map the string a Soundex-esque value, although to similar sounding strings will not
/// necessarily be mapped to the same, but will map to nearby values (nearby in this case means the
/// XOR having a low Hamming weight).
///
/// This is two orders of magnitude faster than Soundex, and several orders of magnitude faster
/// than Levenshtein distance, making it feasible to run on large sets of strings in very short
/// time.
///
/// A word containing too many non-duplicate consonants will overflow and possibly cause
/// unspecified behavior, although observations shows that it affect the end result relatively
/// little.
///
/// Each byte in the string will be mapped to a value from a table, such that similarly sounding
/// characters have many overlapping bits. This way you ensure that strings sounding alike will be
/// mapped nearby each other. Vowels and duplicates will be skipped.
///
/// The first byte, however, is skipped and left in the most significant place, making it most
/// influential to the hash.
///
/// Case has no effect.
pub fn hash(s: &str) -> u64 {
    let mut bytes = s.bytes();
    let first_byte = bytes.next().map_or(0, |x| {
        let phone = phone(x);
        if phone == 0 { x as u64 } else { phone }
    });
    let mut res = 0;

    for i in bytes {
        let x = phone(i);
        if x != 0 && res & 255 != x {
            res <<= 8;
            res |= x;
        }
    }

    res | (first_byte << 56)
}

/// Get the "sound" of this character.
///
/// This is designed such that similar sounding characters will have a low XOR. Vowels or skipgrams
/// will return 0.
#[inline(always)]
fn phone(b: u8) -> u64 {
    let entry = (b | 32).wrapping_sub(b'a');
    if entry < LETTERS {
        PHONES[entry as usize]
    } else { 0 }
}

/// Calculate the Eudex distance between two words.
///
/// This metric will only measure the bitwise distance between two strings, which is a XOR-like
/// metric, making it unfit for certain purposes.  Generally speaking, the lower this is, the more
/// similar are the two words, although each byte carries different weight (the first one carries
/// the most, and the following's weights are simply half the weight of the previous byte).
///
/// # Example
///
/// ```rust
/// let distance = eudex::distance("write", "right").count_ones();
/// // Hamming weight of the Eudex distance gives a "smoother" word metric.
///
/// assert_eq!(distance, 6);
/// ```
pub fn distance(a: &str, b: &str) -> u64 {
    hash(a) ^ hash(b)
}

/// Check if two sentences sound "similar".
pub fn similar(a: &str, b: &str) -> bool {
    distance(a, b) < 670000
}

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

    #[test]
    fn test_exact() {
        assert_eq!(hash("lal"), hash("lel"));
        assert_eq!(hash("rupert"), hash("ropert"));
        assert_eq!(hash("rrr"), hash("rraaaa"));
        assert_eq!(hash("random"), hash("rondom"));
        assert_eq!(hash("java"), hash("jiva"));
        assert_eq!(hash("JAva"), hash("jAva"));
        assert_eq!(hash("triggered"), hash("TRIGGERED"));
        assert_eq!(hash("comp-uter"), hash("computer"));
        assert_eq!(hash("comp@u#te?r"), hash("computer"));
        assert_eq!(hash("c0mp^tər"), hash("computer"));
    }

    #[test]
    fn test_mismatch() {
        assert!(hash("reddit") != hash("eddit"));
        assert!(hash("lol") != hash("lulz"));
        assert!(hash("ijava") != hash("java"));
        assert!(hash("jesus") != hash("iesus"));
        assert!(hash("aesus") != hash("iesus"));
    }

    #[test]
    fn test_distance() {
        assert!(distance("lizzard", "wizzard") > distance("rick", "rolled"));
        assert!(distance("bannana", "panana") >= distance("apple", "abple"));
        //assert!(distance("franco", "sranco") < distance("unicode", "ASCII"));
        assert!(distance("trump", "drumpf") < distance("gangam", "style"));
        assert!(distance("right", "write").count_zeros() > distance("write", "abdominohysterotomy").count_zeros());
    }

    #[test]
    fn test_reflexivity() {
        assert_eq!(distance("a", "b"), distance("b", "a"));
        assert_eq!(distance("youtube", "facebook"), distance("facebook", "youtube"));
        assert_eq!(distance("Rust", "Go"), distance("Go", "Rust"));
        assert_eq!(distance("rick", "rolled"), distance("rolled", "rick"));
    }

    #[test]
    fn test_similar() {
        // Similar.
        assert!(similar("yay", "yuy"));
        assert!(distance("crack", "crakk").count_ones() < 10);
        assert!(similar("what", "wat"));
        assert!(similar("jesus", "jeuses"));
        assert!(similar("", ""));
        assert!(similar("jumpo", "jumbo"));
        assert!(similar("lol", "lulz"));
        assert!(similar("goth", "god"));

        // Not similar.
        assert!(!similar("youtube", "reddit"));
        assert!(!similar("yet", "vet"));
        assert!(!similar("hacker", "4chan"));
        assert!(!similar("awesome", "me"));
        assert!(!similar("prisco", "vkisco"));
        assert!(!similar("no", "go"));
        assert!(!similar("horse", "norse"));
        assert!(!similar("nice", "mice"));
    }

    #[bench]
    fn bench_dict(b: &mut Bencher) {
        use std::fs;
        use std::io::{BufRead, BufReader};

        b.iter(|| {
            let dict = fs::File::open("/usr/share/dict/american-english").unwrap();
            let mut vec = Vec::new();

            for i in BufReader::new(dict).lines() {
                vec.push(hash(&i.unwrap()));
            }

            vec
        });
    }
}
<commit_msg>Update internal docs<commit_after>//! Eudex is a Soundex-esque phonetic reduction/hashing algorithm, providing locality sensitive
//! "hashes" of words, based on the spelling and pronunciation.

#![cfg_attr(test, feature(test))]
#[cfg(test)]
extern crate test;

/// The sound table.
///
/// The first bit each describes a certain property of the phone:
///
/// | Position | Modifier | Property    | Phones   |
/// |----------|----------|-------------|----------|
/// | 1        | 1        | Nasal       | mn       |
/// | 2        | 2        | Plosive     | pbtdcgqk |
/// | 3        | 4        | Fricative   | fvsjxzhc |
/// | 4        | 8        | Approximant | vrhjwc   |
/// | 5        | 16       | Trill       | r        |
/// | 6        | 32       | Lateral     | l        |
/// | 7        | 64       | Type¹       | mpbfv    |
/// | 8        | 128      | Confident²  | lrxzq    |
///
/// ¹1 means labial or dorsal, 0 means apical.
/// ²hard to misspell.
const PHONES: [u64; LETTERS as usize] = [
    0, // a
    0b01000010, // b
    0b00001110, // c
    0b00000010, // d
    0, // e
    0b01000100, // f
    0b00000010, // g
    0b00001100, // h
    0, // i
    0b00001100, // j
    0b00000010, // k
    0b10100000, // l
    0b01000001, // m
    0b00000001, // n
    0, // o
    0b01000010, // p
    0b10000010, // q
    0b10011000, // r
    0b00000100, // s
    0b00000010, // t
    0, // u
    0b01001100, // v
    0b00001000, // w
    0b10000100, // x
    0, // y
    0b10000100, // z
];
/// Number of letters in our phone map.
const LETTERS: u8 =  26;

/// Phonetically hash this string.
///
/// This hashing function is based upon a phonetic reduction algorithm, and is locality sensitive.
///
/// This will map the string a Soundex-esque value, although to similar sounding strings will not
/// necessarily be mapped to the same, but will map to nearby values (nearby in this case means the
/// XOR having a low Hamming weight).
///
/// This is two orders of magnitude faster than Soundex, and several orders of magnitude faster
/// than Levenshtein distance, making it feasible to run on large sets of strings in very short
/// time.
///
/// A word containing too many non-duplicate consonants will overflow and possibly cause
/// unspecified behavior, although observations shows that it affect the end result relatively
/// little.
///
/// Each byte in the string will be mapped to a value from a table, such that similarly sounding
/// characters have many overlapping bits. This way you ensure that strings sounding alike will be
/// mapped nearby each other. Vowels and duplicates will be skipped.
///
/// The first byte, however, is skipped and left in the most significant place, making it most
/// influential to the hash.
///
/// Case has no effect.
pub fn hash(s: &str) -> u64 {
    let mut bytes = s.bytes();
    let first_byte = bytes.next().map_or(0, |x| {
        let phone = phone(x);
        if phone == 0 { x as u64 } else { phone }
    });
    let mut res = 0;

    for i in bytes {
        let x = phone(i);
        if x != 0 && res & 255 != x {
            res <<= 8;
            res |= x;
        }
    }

    res | (first_byte << 56)
}

/// Get the "sound" of this character.
///
/// This is designed such that similar sounding characters will have a low XOR. Vowels or skipgrams
/// will return 0.
#[inline(always)]
fn phone(b: u8) -> u64 {
    let entry = (b | 32).wrapping_sub(b'a');
    if entry < LETTERS {
        PHONES[entry as usize]
    } else { 0 }
}

/// Calculate the Eudex distance between two words.
///
/// This metric will only measure the bitwise distance between two strings, which is a XOR-like
/// metric, making it unfit for certain purposes.  Generally speaking, the lower this is, the more
/// similar are the two words, although each byte carries different weight (the first one carries
/// the most, and the following's weights are simply half the weight of the previous byte).
///
/// # Example
///
/// ```rust
/// let distance = eudex::distance("write", "right").count_ones();
/// // Hamming weight of the Eudex distance gives a "smoother" word metric.
///
/// assert_eq!(distance, 6);
/// ```
pub fn distance(a: &str, b: &str) -> u64 {
    hash(a) ^ hash(b)
}

/// Check if two sentences sound "similar".
pub fn similar(a: &str, b: &str) -> bool {
    distance(a, b) < 670000
}

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

    #[test]
    fn test_exact() {
        assert_eq!(hash("lal"), hash("lel"));
        assert_eq!(hash("rupert"), hash("ropert"));
        assert_eq!(hash("rrr"), hash("rraaaa"));
        assert_eq!(hash("random"), hash("rondom"));
        assert_eq!(hash("java"), hash("jiva"));
        assert_eq!(hash("JAva"), hash("jAva"));
        assert_eq!(hash("triggered"), hash("TRIGGERED"));
        assert_eq!(hash("comp-uter"), hash("computer"));
        assert_eq!(hash("comp@u#te?r"), hash("computer"));
        assert_eq!(hash("c0mp^tər"), hash("computer"));
    }

    #[test]
    fn test_mismatch() {
        assert!(hash("reddit") != hash("eddit"));
        assert!(hash("lol") != hash("lulz"));
        assert!(hash("ijava") != hash("java"));
        assert!(hash("jesus") != hash("iesus"));
        assert!(hash("aesus") != hash("iesus"));
    }

    #[test]
    fn test_distance() {
        assert!(distance("lizzard", "wizzard") > distance("rick", "rolled"));
        assert!(distance("bannana", "panana") >= distance("apple", "abple"));
        //assert!(distance("franco", "sranco") < distance("unicode", "ASCII"));
        assert!(distance("trump", "drumpf") < distance("gangam", "style"));
        assert!(distance("right", "write").count_zeros() > distance("write", "abdominohysterotomy").count_zeros());
    }

    #[test]
    fn test_reflexivity() {
        assert_eq!(distance("a", "b"), distance("b", "a"));
        assert_eq!(distance("youtube", "facebook"), distance("facebook", "youtube"));
        assert_eq!(distance("Rust", "Go"), distance("Go", "Rust"));
        assert_eq!(distance("rick", "rolled"), distance("rolled", "rick"));
    }

    #[test]
    fn test_similar() {
        // Similar.
        assert!(similar("yay", "yuy"));
        assert!(distance("crack", "crakk").count_ones() < 10);
        assert!(similar("what", "wat"));
        assert!(similar("jesus", "jeuses"));
        assert!(similar("", ""));
        assert!(similar("jumpo", "jumbo"));
        assert!(similar("lol", "lulz"));
        assert!(similar("goth", "god"));

        // Not similar.
        assert!(!similar("youtube", "reddit"));
        assert!(!similar("yet", "vet"));
        assert!(!similar("hacker", "4chan"));
        assert!(!similar("awesome", "me"));
        assert!(!similar("prisco", "vkisco"));
        assert!(!similar("no", "go"));
        assert!(!similar("horse", "norse"));
        assert!(!similar("nice", "mice"));
    }

    #[bench]
    fn bench_dict(b: &mut Bencher) {
        use std::fs;
        use std::io::{BufRead, BufReader};

        b.iter(|| {
            let dict = fs::File::open("/usr/share/dict/american-english").unwrap();
            let mut vec = Vec::new();

            for i in BufReader::new(dict).lines() {
                vec.push(hash(&i.unwrap()));
            }

            vec
        });
    }
}
<|endoftext|>


<commit_before>#![crate_id = "graphics"]
#![deny(missing_doc)]

//! A library for 2D graphics that works with multiple back-ends.
//!
//! To implement your own back-end, use the BackEnd trait.
//!
//! ## Usage
//!
//! To draw to the back-end, you need a context.
//! The context contains the information necessary to perform the drawing.
//! Unlike other graphics libraries, this library is not bound to the back-end.
//! You do not have to specify which back-end to use before doing the actual drawing.
//!
//! For example, assuming we have a back-end called `back_end`:
//!
//! ```
//! Context::new().rect(x, y, w, h).rgba(r, g, b, a).fill(&mut back_end);
//! ```
//!
//! ## Important!
//!
//! Because the context is built using borrowed pointers,
//! it is not possible to do two or more steps at a time and assign it to a variable:
//!
//! ```
//! // ERROR: Borrowed value does not live long enough
//! let rect = Context::new().rect(x, y, w, h);
//! ```
//!
//! This is because the lifetime of the first step only lives inside the expression.
//! To solve this problem, break the statement into two parts, one for each step:
//!
//! ```
//! let c = Context::new();
//! let rect = c.rect(x, y, w, h);
//! ```
//!
//! This is only the case when you are assigning the context to a variable.

extern crate std;

pub use Context = context::Context;
pub use BackEnd = back_end::BackEnd;
pub use RelativeTransform2d = relative_transform2d::RelativeTransform2d;
pub use AddColor = add_color::AddColor;
pub use AddEllipse = add_ellipse::AddEllipse;
pub use AddImage = add_image::AddImage;
pub use AddPolygon = add_polygon::AddPolygon;
pub use AddPolygons = add_polygons::AddPolygons;
pub use AddRectangle = add_rectangle::AddRectangle;
pub use AddRound = add_round::AddRound;
pub use AddRoundBorder = add_round_border::AddRoundBorder;
pub use AddTween = add_tween::AddTween;
pub use RelativeColor = relative_color::RelativeColor;
pub use RelativeRectangle = relative_rectangle::RelativeRectangle;
pub use Draw = draw::Draw;
pub use Fill = fill::Fill;
pub use Clear = clear::Clear;
pub use ColorContext = color_context::ColorContext;
pub use EllipseContext = ellipse_context::EllipseContext;
pub use EllipseColorContext = ellipse_color_context::EllipseColorContext;
pub use ImageRectangleContext = image_rectangle_context::ImageRectangleContext;
pub use ImageRectangleColorContext = image_rectangle_color_context::ImageRectangleColorContext;
pub use LineContext = line_context::LineContext;
pub use RoundBorderLineContext = round_border_line_context::RoundBorderLineContext;
pub use RoundBorderLineColorContext = round_border_line_color_context::RoundBorderLineColorContext;
pub use PolygonContext = polygon_context::PolygonContext;
pub use PolygonColorContext = polygon_color_context::PolygonColorContext;
pub use RectangleContext = rectangle_context::RectangleContext;
pub use RectangleColorContext = rectangle_color_context::RectangleColorContext;
pub use RoundRectangleContext = round_rectangle_context::RoundRectangleContext;
pub use RoundRectangleColorContext = round_rectangle_color_context::RoundRectangleColorContext;
pub use TweenContext = tween_context::TweenContext;
pub use TweenColorContext = tween_color_context::TweenColorContext;
pub use TweenPolygonsContext = tween_polygons_context::TweenPolygonsContext;
pub use TweenPolygonsColorContext = tween_polygons_color_context::TweenPolygonsColorContext;
pub use View = view::View;

mod internal;
mod context;
mod back_end;
mod relative_transform2d;
mod add_color;
mod add_ellipse;
mod add_image;
mod add_polygon;
mod add_polygons;
mod add_rectangle;
mod add_round;
mod add_round_border;
mod add_tween;
mod relative_color;
mod relative_rectangle;
mod draw;
mod fill;
mod clear;
mod color_context;
mod ellipse_context;
mod ellipse_color_context;
mod image_rectangle_context;
mod image_rectangle_color_context;
mod line_context;
mod polygon_context;
mod polygon_color_context;
mod rectangle_context;
mod rectangle_color_context;
mod round_border_line_context;
mod round_border_line_color_context;
mod round_rectangle_context;
mod round_rectangle_color_context;
mod tween_context;
mod tween_color_context;
mod tween_polygons_context;
mod tween_polygons_color_context;
mod view;
pub mod vecmath;
pub mod triangulation;
pub mod interpolation;
pub mod modular_index;

/// [red, green, blue, alpha]
pub type Color = [f32, ..4];

/// [x1, y1, x2, y2]
pub type Line = [f64, ..4];

/// [x, y, dir_x, dir_y]
pub type Ray = [f64, ..4];

/// [radius, width]
pub type RoundBorder = [f64, ..2];

/// [m00, m01, m02, m10, m11, m12]
///
/// The first 3 numbers transforms `x`,
/// the last 3 numbers transforms `y`:
///
/// ```
/// tx = m00 * x + m01 * y + m02;
/// ty = m10 * x + m11 * y + m12;
/// ```
pub type Matrix2d = [f64, ..6];

/// [x, y, w, h]
pub type PixelRectangle = [u32, ..4];

/// [x, y, w, h]
pub type Rectangle = [f64, ..4];

/// [x1, y1, x2, y2, x3, y3]
pub type Triangle = [f64, ..6];

/// [x, y]
pub type Vec2d = [f64, ..2];

/// A structure that might contain a value or a borrowed value.
/// This is to used as building block to create data structure
/// that is partially based on an existing structure.
pub enum Field<'a, T> {
    /// Contains a value.
    Value(T),
    /// Contains a borrowed pointer.
    Borrowed(&'a T),
}

impl<'a, T> Field<'a, T> {
    /// Gets a read only value.
    #[inline(always)]
    pub fn get(&'a self) -> &'a T {
        match *self {
            Value(ref val) => val,
            Borrowed(rval) => rval,
        }
    }
}

/// Represents an image.
///
/// Images are often packed together in sprite sheets.
/// For this reason it refers to a rectangle within a texture.
///
/// The texture is a unique identifier recognized by the back-end.
/// An image contains the size of a texture to be able to
/// compute normalized coordinates.
///
/// There is no garbage collection of textures,
/// this responsibility is given to the back-end.
pub struct Image {
    /// A unique identifier of the texture, recognizable by back-end.
    pub texture_id: uint,
    /// The pixel width of the texture.
    pub texture_width: u32,
    /// The pixel height of the texture.
    pub texture_height: u32,
    /// The source rectangle in the texture.
    pub source_rect: PixelRectangle,
}

<commit_msg>Arranged `pub use` alphabetically<commit_after>#![crate_id = "graphics"]
#![deny(missing_doc)]

//! A library for 2D graphics that works with multiple back-ends.
//!
//! To implement your own back-end, use the BackEnd trait.
//!
//! ## Usage
//!
//! To draw to the back-end, you need a context.
//! The context contains the information necessary to perform the drawing.
//! Unlike other graphics libraries, this library is not bound to the back-end.
//! You do not have to specify which back-end to use before doing the actual drawing.
//!
//! For example, assuming we have a back-end called `back_end`:
//!
//! ```
//! Context::new().rect(x, y, w, h).rgba(r, g, b, a).fill(&mut back_end);
//! ```
//!
//! ## Important!
//!
//! Because the context is built using borrowed pointers,
//! it is not possible to do two or more steps at a time and assign it to a variable:
//!
//! ```
//! // ERROR: Borrowed value does not live long enough
//! let rect = Context::new().rect(x, y, w, h);
//! ```
//!
//! This is because the lifetime of the first step only lives inside the expression.
//! To solve this problem, break the statement into two parts, one for each step:
//!
//! ```
//! let c = Context::new();
//! let rect = c.rect(x, y, w, h);
//! ```
//!
//! This is only the case when you are assigning the context to a variable.

extern crate std;

pub use AddColor = add_color::AddColor;
pub use AddEllipse = add_ellipse::AddEllipse;
pub use AddImage = add_image::AddImage;
pub use AddPolygon = add_polygon::AddPolygon;
pub use AddPolygons = add_polygons::AddPolygons;
pub use AddRectangle = add_rectangle::AddRectangle;
pub use AddRound = add_round::AddRound;
pub use AddRoundBorder = add_round_border::AddRoundBorder;
pub use AddTween = add_tween::AddTween;
pub use BackEnd = back_end::BackEnd;
pub use Clear = clear::Clear;
pub use ColorContext = color_context::ColorContext;
pub use Context = context::Context;
pub use Draw = draw::Draw;
pub use EllipseContext = ellipse_context::EllipseContext;
pub use EllipseColorContext = ellipse_color_context::EllipseColorContext;
pub use Fill = fill::Fill;
pub use ImageRectangleContext = image_rectangle_context::ImageRectangleContext;
pub use ImageRectangleColorContext = image_rectangle_color_context::ImageRectangleColorContext;
pub use LineContext = line_context::LineContext;
pub use PolygonContext = polygon_context::PolygonContext;
pub use PolygonColorContext = polygon_color_context::PolygonColorContext;
pub use RectangleContext = rectangle_context::RectangleContext;
pub use RectangleColorContext = rectangle_color_context::RectangleColorContext;
pub use RelativeColor = relative_color::RelativeColor;
pub use RelativeRectangle = relative_rectangle::RelativeRectangle;
pub use RelativeTransform2d = relative_transform2d::RelativeTransform2d;
pub use RoundBorderLineContext = round_border_line_context::RoundBorderLineContext;
pub use RoundBorderLineColorContext = round_border_line_color_context::RoundBorderLineColorContext;
pub use RoundRectangleContext = round_rectangle_context::RoundRectangleContext;
pub use RoundRectangleColorContext = round_rectangle_color_context::RoundRectangleColorContext;
pub use TweenContext = tween_context::TweenContext;
pub use TweenColorContext = tween_color_context::TweenColorContext;
pub use TweenPolygonsContext = tween_polygons_context::TweenPolygonsContext;
pub use TweenPolygonsColorContext = tween_polygons_color_context::TweenPolygonsColorContext;
pub use View = view::View;

mod internal;
mod context;
mod back_end;
mod relative_transform2d;
mod add_color;
mod add_ellipse;
mod add_image;
mod add_polygon;
mod add_polygons;
mod add_rectangle;
mod add_round;
mod add_round_border;
mod add_tween;
mod relative_color;
mod relative_rectangle;
mod draw;
mod fill;
mod clear;
mod color_context;
mod ellipse_context;
mod ellipse_color_context;
mod image_rectangle_context;
mod image_rectangle_color_context;
mod line_context;
mod polygon_context;
mod polygon_color_context;
mod rectangle_context;
mod rectangle_color_context;
mod round_border_line_context;
mod round_border_line_color_context;
mod round_rectangle_context;
mod round_rectangle_color_context;
mod tween_context;
mod tween_color_context;
mod tween_polygons_context;
mod tween_polygons_color_context;
mod view;
pub mod vecmath;
pub mod triangulation;
pub mod interpolation;
pub mod modular_index;

/// [red, green, blue, alpha]
pub type Color = [f32, ..4];

/// [x1, y1, x2, y2]
pub type Line = [f64, ..4];

/// [x, y, dir_x, dir_y]
pub type Ray = [f64, ..4];

/// [radius, width]
pub type RoundBorder = [f64, ..2];

/// [m00, m01, m02, m10, m11, m12]
///
/// The first 3 numbers transforms `x`,
/// the last 3 numbers transforms `y`:
///
/// ```
/// tx = m00 * x + m01 * y + m02;
/// ty = m10 * x + m11 * y + m12;
/// ```
pub type Matrix2d = [f64, ..6];

/// [x, y, w, h]
pub type PixelRectangle = [u32, ..4];

/// [x, y, w, h]
pub type Rectangle = [f64, ..4];

/// [x1, y1, x2, y2, x3, y3]
pub type Triangle = [f64, ..6];

/// [x, y]
pub type Vec2d = [f64, ..2];

/// A structure that might contain a value or a borrowed value.
/// This is to used as building block to create data structure
/// that is partially based on an existing structure.
pub enum Field<'a, T> {
    /// Contains a value.
    Value(T),
    /// Contains a borrowed pointer.
    Borrowed(&'a T),
}

impl<'a, T> Field<'a, T> {
    /// Gets a read only value.
    #[inline(always)]
    pub fn get(&'a self) -> &'a T {
        match *self {
            Value(ref val) => val,
            Borrowed(rval) => rval,
        }
    }
}

/// Represents an image.
///
/// Images are often packed together in sprite sheets.
/// For this reason it refers to a rectangle within a texture.
///
/// The texture is a unique identifier recognized by the back-end.
/// An image contains the size of a texture to be able to
/// compute normalized coordinates.
///
/// There is no garbage collection of textures,
/// this responsibility is given to the back-end.
pub struct Image {
    /// A unique identifier of the texture, recognizable by back-end.
    pub texture_id: uint,
    /// The pixel width of the texture.
    pub texture_width: u32,
    /// The pixel height of the texture.
    pub texture_height: u32,
    /// The source rectangle in the texture.
    pub source_rect: PixelRectangle,
}

<|endoftext|>


<commit_before>//! jsonrpc http server.
//!
//! ```no_run
//! extern crate jsonrpc_core;
//! extern crate jsonrpc_http_server;
//!
//! use std::sync::Arc;
//! use jsonrpc_core::*;
//! use jsonrpc_http_server::*;
//!
//! struct SayHello;
//! impl MethodCommand for SayHello {
//! 	fn execute(&self, _params: Params) -> Result<Value, Error> {
//! 		Ok(Value::String("hello".to_string()))
//! 	}
//! }
//!
//! fn main() {
//! 	let io = IoHandler::new();
//! 	io.add_method("say_hello", SayHello);
//! 	let _server = ServerBuilder::new(Arc::new(io)).start_http(&"127.0.0.1:3030".parse().unwrap());
//! }
//! ```

#![warn(missing_docs)]

extern crate hyper;
extern crate unicase;
extern crate jsonrpc_core as jsonrpc;

pub mod request_response;
mod cors;
mod handler;
mod hosts_validator;
#[cfg(test)]
mod tests;

use std::sync::{Arc, Mutex};
use std::net::SocketAddr;
use std::thread;
use hyper::server;
use jsonrpc::IoHandler;

pub use hyper::header::AccessControlAllowOrigin;
pub use handler::{PanicHandler, ServerHandler};
pub use hosts_validator::is_host_header_valid;

/// Result of starting the Server.
pub type ServerResult = Result<Server, RpcServerError>;

/// RPC Server startup error.
#[derive(Debug)]
pub enum RpcServerError {
	/// IO Error
	IoError(std::io::Error),
	/// Other Error (hyper)
	Other(hyper::error::Error),
}

impl From<hyper::error::Error> for RpcServerError {
	fn from(err: hyper::error::Error) -> Self {
		match err {
			hyper::error::Error::Io(e) => RpcServerError::IoError(e),
			e => RpcServerError::Other(e)
		}
	}
}

/// Specifies if domains should be validated.
pub enum DomainsValidation<T> {
	/// Allow only domains on the list.
	AllowOnly(Vec<T>),
	/// Disable domains validation completely.
	Disabled,
}

impl<T> Into<Option<Vec<T>>> for DomainsValidation<T> {
	fn into(self) -> Option<Vec<T>> {
		use DomainsValidation::*;
		match self {
			AllowOnly(list) => Some(list),
			Disabled => None,
		}
	}
}

impl<T> From<Option<Vec<T>>> for DomainsValidation<T> {
	fn from(other: Option<Vec<T>>) -> Self {
		match other {
			Some(list) => DomainsValidation::AllowOnly(list),
			None => DomainsValidation::Disabled,
		}
	}
}

/// Convenient JSON-RPC HTTP Server builder.
pub struct ServerBuilder {
	jsonrpc_handler: Arc<IoHandler>,
	cors_domains: Option<Vec<AccessControlAllowOrigin>>,
	allowed_hosts: Option<Vec<String>>,
	panic_handler: Option<Box<Fn() -> () + Send>>,
}

impl ServerBuilder {
	/// Creates new `ServerBuilder` with specified `IoHandler`.
	///
	/// By default:
	/// 1. Server is not sending any CORS headers.
	/// 2. Server is validating `Host` header.
	pub fn new(jsonrpc_handler: Arc<IoHandler>) -> Self {
		ServerBuilder {
			jsonrpc_handler: jsonrpc_handler,
			cors_domains: None,
			allowed_hosts: None,
			panic_handler: None,
		}
	}

	/// Sets handler invoked in case of server panic.
	pub fn panic_handler<F>(mut self, handler: F) -> Self where F : Fn() -> () + Send + 'static {
		self.panic_handler = Some(Box::new(handler));
		self
	}

	/// Configures a list of allowed CORS origins.
	pub fn cors(mut self, cors_domains: DomainsValidation<AccessControlAllowOrigin>) -> Self {
		self.cors_domains = cors_domains.into();
		self
	}

	/// Allow connections only with `Host` header set to binding address.
	pub fn allow_only_bind_host(mut self) -> Self {
		self.allowed_hosts = Some(Vec::new());
		self
	}

	/// Specify a list of valid `Host` headers. Binding address is allowed automatically.
	pub fn allowed_hosts(mut self, allowed_hosts: DomainsValidation<String>) -> Self {
		self.allowed_hosts = allowed_hosts.into();
		self
	}

	/// Start this JSON-RPC HTTP server trying to bind to specified `SocketAddr`.
	pub fn start_http(self, addr: &SocketAddr) -> ServerResult {
		let panic_for_server = Arc::new(Mutex::new(self.panic_handler));
		let jsonrpc_handler = self.jsonrpc_handler;
		let cors_domains = self.cors_domains;
		let hosts = Arc::new(Mutex::new(self.allowed_hosts));
		let hosts_setter = hosts.clone();

		let (l, srv) = try!(try!(hyper::Server::http(addr)).handle(move |_| {
			let handler = PanicHandler { handler: panic_for_server.clone() };
			let hosts = hosts.lock().unwrap().clone();
			ServerHandler::new(jsonrpc_handler.clone(), cors_domains.clone(), hosts, handler)
		}));

		// Add current host to allowed headers.
		// NOTE: we need to use `l.addr()` instead of `addr`
		// it might be different!
		{
			let mut hosts = hosts_setter.lock().unwrap();
			if let Some(ref mut hosts) = *hosts {
				let address = l.addr().to_string();
				hosts.push(address.clone());
				hosts.push(address.replace("127.0.0.1", "localhost"));
			}
		}

		let handle = thread::spawn(move || {
			srv.run();
		});

		Ok(Server {
			server: Some(l),
			handle: Some(handle),
		})
	}
}

/// jsonrpc http server instance
pub struct Server {
	server: Option<server::Listening>,
	handle: Option<thread::JoinHandle<()>>,
}

impl Server {
	/// Returns address of this server
	pub fn addr(&self) -> &SocketAddr {
		self.server.as_ref().unwrap().addr()
	}

	/// Will block waiting for the server to finish.
	pub fn wait(mut self) -> thread::Result<()> {
		self.handle.take().unwrap().join()
	}
}

impl Drop for Server {
	fn drop(&mut self) {
		self.server.take().unwrap().close()
	}
}
<commit_msg>Convenience method to close server<commit_after>//! jsonrpc http server.
//!
//! ```no_run
//! extern crate jsonrpc_core;
//! extern crate jsonrpc_http_server;
//!
//! use std::sync::Arc;
//! use jsonrpc_core::*;
//! use jsonrpc_http_server::*;
//!
//! struct SayHello;
//! impl MethodCommand for SayHello {
//! 	fn execute(&self, _params: Params) -> Result<Value, Error> {
//! 		Ok(Value::String("hello".to_string()))
//! 	}
//! }
//!
//! fn main() {
//! 	let io = IoHandler::new();
//! 	io.add_method("say_hello", SayHello);
//! 	let _server = ServerBuilder::new(Arc::new(io)).start_http(&"127.0.0.1:3030".parse().unwrap());
//! }
//! ```

#![warn(missing_docs)]

extern crate hyper;
extern crate unicase;
extern crate jsonrpc_core as jsonrpc;

pub mod request_response;
mod cors;
mod handler;
mod hosts_validator;
#[cfg(test)]
mod tests;

use std::sync::{Arc, Mutex};
use std::net::SocketAddr;
use std::thread;
use hyper::server;
use jsonrpc::IoHandler;

pub use hyper::header::AccessControlAllowOrigin;
pub use handler::{PanicHandler, ServerHandler};
pub use hosts_validator::is_host_header_valid;

/// Result of starting the Server.
pub type ServerResult = Result<Server, RpcServerError>;

/// RPC Server startup error.
#[derive(Debug)]
pub enum RpcServerError {
	/// IO Error
	IoError(std::io::Error),
	/// Other Error (hyper)
	Other(hyper::error::Error),
}

impl From<hyper::error::Error> for RpcServerError {
	fn from(err: hyper::error::Error) -> Self {
		match err {
			hyper::error::Error::Io(e) => RpcServerError::IoError(e),
			e => RpcServerError::Other(e)
		}
	}
}

/// Specifies if domains should be validated.
pub enum DomainsValidation<T> {
	/// Allow only domains on the list.
	AllowOnly(Vec<T>),
	/// Disable domains validation completely.
	Disabled,
}

impl<T> Into<Option<Vec<T>>> for DomainsValidation<T> {
	fn into(self) -> Option<Vec<T>> {
		use DomainsValidation::*;
		match self {
			AllowOnly(list) => Some(list),
			Disabled => None,
		}
	}
}

impl<T> From<Option<Vec<T>>> for DomainsValidation<T> {
	fn from(other: Option<Vec<T>>) -> Self {
		match other {
			Some(list) => DomainsValidation::AllowOnly(list),
			None => DomainsValidation::Disabled,
		}
	}
}

/// Convenient JSON-RPC HTTP Server builder.
pub struct ServerBuilder {
	jsonrpc_handler: Arc<IoHandler>,
	cors_domains: Option<Vec<AccessControlAllowOrigin>>,
	allowed_hosts: Option<Vec<String>>,
	panic_handler: Option<Box<Fn() -> () + Send>>,
}

impl ServerBuilder {
	/// Creates new `ServerBuilder` with specified `IoHandler`.
	///
	/// By default:
	/// 1. Server is not sending any CORS headers.
	/// 2. Server is validating `Host` header.
	pub fn new(jsonrpc_handler: Arc<IoHandler>) -> Self {
		ServerBuilder {
			jsonrpc_handler: jsonrpc_handler,
			cors_domains: None,
			allowed_hosts: None,
			panic_handler: None,
		}
	}

	/// Sets handler invoked in case of server panic.
	pub fn panic_handler<F>(mut self, handler: F) -> Self where F : Fn() -> () + Send + 'static {
		self.panic_handler = Some(Box::new(handler));
		self
	}

	/// Configures a list of allowed CORS origins.
	pub fn cors(mut self, cors_domains: DomainsValidation<AccessControlAllowOrigin>) -> Self {
		self.cors_domains = cors_domains.into();
		self
	}

	/// Allow connections only with `Host` header set to binding address.
	pub fn allow_only_bind_host(mut self) -> Self {
		self.allowed_hosts = Some(Vec::new());
		self
	}

	/// Specify a list of valid `Host` headers. Binding address is allowed automatically.
	pub fn allowed_hosts(mut self, allowed_hosts: DomainsValidation<String>) -> Self {
		self.allowed_hosts = allowed_hosts.into();
		self
	}

	/// Start this JSON-RPC HTTP server trying to bind to specified `SocketAddr`.
	pub fn start_http(self, addr: &SocketAddr) -> ServerResult {
		let panic_for_server = Arc::new(Mutex::new(self.panic_handler));
		let jsonrpc_handler = self.jsonrpc_handler;
		let cors_domains = self.cors_domains;
		let hosts = Arc::new(Mutex::new(self.allowed_hosts));
		let hosts_setter = hosts.clone();

		let (l, srv) = try!(try!(hyper::Server::http(addr)).handle(move |_| {
			let handler = PanicHandler { handler: panic_for_server.clone() };
			let hosts = hosts.lock().unwrap().clone();
			ServerHandler::new(jsonrpc_handler.clone(), cors_domains.clone(), hosts, handler)
		}));

		// Add current host to allowed headers.
		// NOTE: we need to use `l.addr()` instead of `addr`
		// it might be different!
		{
			let mut hosts = hosts_setter.lock().unwrap();
			if let Some(ref mut hosts) = *hosts {
				let address = l.addr().to_string();
				hosts.push(address.clone());
				hosts.push(address.replace("127.0.0.1", "localhost"));
			}
		}

		let handle = thread::spawn(move || {
			srv.run();
		});

		Ok(Server {
			server: Some(l),
			handle: Some(handle),
		})
	}
}

/// jsonrpc http server instance
pub struct Server {
	server: Option<server::Listening>,
	handle: Option<thread::JoinHandle<()>>,
}

impl Server {
	/// Returns address of this server
	pub fn addr(&self) -> &SocketAddr {
		self.server.as_ref().unwrap().addr()
	}

	/// Closes the server.
	pub fn close(mut self) {
		self.server.take().unwrap().close()
	}

	/// Will block, waiting for the server to finish.
	pub fn wait(mut self) -> thread::Result<()> {
		self.handle.take().unwrap().join()
	}
}

impl Drop for Server {
	fn drop(&mut self) {
		self.server.take().unwrap().close()
	}
}
<|endoftext|>


<commit_before>#![crate_name = "input"]
#![deny(missing_docs)]
#![deny(missing_copy_implementations)]
#![feature(core)]

//! A flexible structure for user interactions
//! to be used in window frameworks and widgets libraries.

#[macro_use]
extern crate bitflags;
extern crate "rustc-serialize" as rustc_serialize;

pub use mouse::MouseButton;
pub use keyboard::Key;

pub mod keyboard;
pub mod mouse;

/// Models different kinds of buttons.
#[derive(Copy, Clone, RustcDecodable, RustcEncodable, PartialEq, Eq, Debug)]
pub enum Button {
    /// A keyboard button.
    Keyboard(Key),
    /// A mouse button.
    Mouse(MouseButton),
}

/// Models different kinds of motion.
#[derive(Copy, Clone, RustcDecodable, RustcEncodable, PartialEq, Debug)]
pub enum Motion {
    /// x and y in window coordinates.
    MouseCursor(f64, f64),
    /// x and y in relative coordinates.
    MouseRelative(f64, f64),
    /// x and y in scroll ticks.
    MouseScroll(f64, f64),
}

/// Models input events.
#[derive(Clone, RustcDecodable, RustcEncodable, PartialEq, Debug)]
pub enum Input {
    /// Pressed a button.
    Press(Button),
    /// Released a button.
    Release(Button),
    /// Moved mouse cursor.
    Move(Motion),
    /// Text (usually from keyboard).
    Text(String),
    /// Window got resized.
    Resize(u32, u32),
    /// Window gained or lost focus.
    Focus(bool),
}
<commit_msg>hypens are no longer allowed in crate names<commit_after>#![crate_name = "input"]
#![deny(missing_docs)]
#![deny(missing_copy_implementations)]
#![feature(core)]

//! A flexible structure for user interactions
//! to be used in window frameworks and widgets libraries.

#[macro_use]
extern crate bitflags;
extern crate rustc_serialize;

pub use mouse::MouseButton;
pub use keyboard::Key;

pub mod keyboard;
pub mod mouse;

/// Models different kinds of buttons.
#[derive(Copy, Clone, RustcDecodable, RustcEncodable, PartialEq, Eq, Debug)]
pub enum Button {
    /// A keyboard button.
    Keyboard(Key),
    /// A mouse button.
    Mouse(MouseButton),
}

/// Models different kinds of motion.
#[derive(Copy, Clone, RustcDecodable, RustcEncodable, PartialEq, Debug)]
pub enum Motion {
    /// x and y in window coordinates.
    MouseCursor(f64, f64),
    /// x and y in relative coordinates.
    MouseRelative(f64, f64),
    /// x and y in scroll ticks.
    MouseScroll(f64, f64),
}

/// Models input events.
#[derive(Clone, RustcDecodable, RustcEncodable, PartialEq, Debug)]
pub enum Input {
    /// Pressed a button.
    Press(Button),
    /// Released a button.
    Release(Button),
    /// Moved mouse cursor.
    Move(Motion),
    /// Text (usually from keyboard).
    Text(String),
    /// Window got resized.
    Resize(u32, u32),
    /// Window gained or lost focus.
    Focus(bool),
}
<|endoftext|>