<commit_before>//! OpenCC binding for Rust
//!
//! You should install [OpenCC 1.0.x](https://github.com/BYVoid/OpenCC) library first.
//!
//! Supported configurations:
//!
//! * `s2t.json` Simplified Chinese to Traditional Chinese
//! * `t2s.json` Traditional Chinese to Simplified Chinese
//! * `s2tw.json` Simplified Chinese to Traditional Chinese (Taiwan Standard)
//! * `tw2s.json` Traditional Chinese (Taiwan Standard) to Simplified Chinese
//! * `s2hk.json` Simplified Chinese to Traditional Chinese (Hong Kong Standard)
//! * `hk2s.json` Traditional Chinese (Hong Kong Standard) to Simplified Chinese
//! * `s2twp.json` Simplified Chinese to Traditional Chinese (Taiwan Standard) with Taiwanese idiom
//! * `tw2sp.json` Traditional Chinese (Taiwan Standard) to Simplified Chinese with Mainland Chinese idiom
//! * `t2tw.json` Traditional Chinese (OpenCC Standard) to Taiwan Standard
//! * `t2hk.json` Traditional Chinese (OpenCC Standard) to Hong Kong Standard
//!
//! # Examples
//! ```
//! extern crate opencc;
//!
//! use opencc::OpenCC;
//!
//! fn main() {
//!     let cc = OpenCC::new("t2s.json");
//!     println!("{}", cc.convert("乾坤一擲"));
//!     println!("{}", cc.convert("開放中文轉換"));
//! }
//! ```
extern crate libc;
use libc::{size_t, c_void, c_char};

use std::ptr;
use std::ffi::{CStr, CString};

#[link(name = "opencc")]
extern {
    fn opencc_open(config: *const c_char) -> *mut c_void;
    fn opencc_close(opencc: *mut c_void);
    fn opencc_convert_utf8(opencc: *mut c_void, text: *const c_char, length: size_t) -> *mut c_char;
    fn opencc_convert_utf8_free(text: *mut c_char);
    fn opencc_error() -> *const c_char;
}

pub struct OpenCC {
    /// Configuration file
    pub config: String,
    libopencc: *mut c_void,
}

impl OpenCC {
    /// Constructs a new `OpenCC`
    ///
    /// # Examples
    /// ```
    /// let cc = opencc::OpenCC::new("t2s.json");
    /// ```
    pub fn new(config: &str) -> OpenCC {
        let c_config = CString::new(config).unwrap();
        unsafe {
            OpenCC {
                config: config.to_string(),
                libopencc: opencc_open(c_config.as_ptr()),
            }
        }
    }

    /// Convert a text
    ///
    /// # Examples
    /// ```
    /// let cc = opencc::OpenCC::new("t2s.json");
    /// cc.convert("乾坤一擲");
    /// cc.convert("開放中文轉換");
    /// ```
    pub fn convert(&self, text: &str) -> String {
        unsafe {
            let c_text = CString::new(text).unwrap();
            let c_ptr = opencc_convert_utf8(self.libopencc, c_text.as_ptr(), text.len() as size_t);
            let c_str = CStr::from_ptr(c_ptr);
            let str_buf = c_str.to_str().unwrap().to_owned();
            opencc_convert_utf8_free(c_ptr);
            str_buf
        }
    }

    /// Close the underlying libopencc.
    /// Will be called automatically when the variable gets out of scope.
    fn close(&mut self) {
        if !self.libopencc.is_null() {
            unsafe {
                opencc_close(self.libopencc);
            }
            self.libopencc = ptr::null_mut();
        }
    }

    /// Returns the last error message
    ///
    /// # Safety
    ///
    /// Note that this function is the only one which is NOT thread-safe.
    pub fn last_error(&mut self) -> Option<String> {
        unsafe {
            let error_ptr = opencc_error();
            if error_ptr.is_null() {
                None
            } else {
                let c_str = CStr::from_ptr(error_ptr);
                let str_buf = c_str.to_str().unwrap().to_owned();
                Some(str_buf)
            }
        }
    }
}

impl Drop for OpenCC {
    /// Close the underlying libopencc when it been droped
    fn drop(&mut self) {
        self.close();
    }
}

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

    #[test]
    fn test_simple_convert() {
        let cc = OpenCC::new("t2s.json");
        assert_eq!("乾坤一掷", &cc.convert("乾坤一擲"));
        assert_eq!("开放中文转换", &cc.convert("開放中文轉換"));
    }

    #[test]
    fn test_opencc_last_error() {
        let mut cc = OpenCC::new("t2s.json");
        println!("{}", cc.last_error().unwrap());
    }
}
<commit_msg>Impl Send & Sync for OpenCC<commit_after>//! OpenCC binding for Rust
//!
//! You should install [OpenCC 1.0.x](https://github.com/BYVoid/OpenCC) library first.
//!
//! Supported configurations:
//!
//! * `s2t.json` Simplified Chinese to Traditional Chinese
//! * `t2s.json` Traditional Chinese to Simplified Chinese
//! * `s2tw.json` Simplified Chinese to Traditional Chinese (Taiwan Standard)
//! * `tw2s.json` Traditional Chinese (Taiwan Standard) to Simplified Chinese
//! * `s2hk.json` Simplified Chinese to Traditional Chinese (Hong Kong Standard)
//! * `hk2s.json` Traditional Chinese (Hong Kong Standard) to Simplified Chinese
//! * `s2twp.json` Simplified Chinese to Traditional Chinese (Taiwan Standard) with Taiwanese idiom
//! * `tw2sp.json` Traditional Chinese (Taiwan Standard) to Simplified Chinese with Mainland Chinese idiom
//! * `t2tw.json` Traditional Chinese (OpenCC Standard) to Taiwan Standard
//! * `t2hk.json` Traditional Chinese (OpenCC Standard) to Hong Kong Standard
//!
//! # Examples
//! ```
//! extern crate opencc;
//!
//! use opencc::OpenCC;
//!
//! fn main() {
//!     let cc = OpenCC::new("t2s.json");
//!     println!("{}", cc.convert("乾坤一擲"));
//!     println!("{}", cc.convert("開放中文轉換"));
//! }
//! ```
extern crate libc;
use libc::{size_t, c_void, c_char};

use std::ptr;
use std::ffi::{CStr, CString};

#[link(name = "opencc")]
extern {
    fn opencc_open(config: *const c_char) -> *mut c_void;
    fn opencc_close(opencc: *mut c_void);
    fn opencc_convert_utf8(opencc: *mut c_void, text: *const c_char, length: size_t) -> *mut c_char;
    fn opencc_convert_utf8_free(text: *mut c_char);
    fn opencc_error() -> *const c_char;
}

pub struct OpenCC {
    /// Configuration file
    pub config: String,
    libopencc: *mut c_void,
}

impl OpenCC {
    /// Constructs a new `OpenCC`
    ///
    /// # Examples
    /// ```
    /// let cc = opencc::OpenCC::new("t2s.json");
    /// ```
    pub fn new(config: &str) -> OpenCC {
        let c_config = CString::new(config).unwrap();
        unsafe {
            OpenCC {
                config: config.to_string(),
                libopencc: opencc_open(c_config.as_ptr()),
            }
        }
    }

    /// Convert a text
    ///
    /// # Examples
    /// ```
    /// let cc = opencc::OpenCC::new("t2s.json");
    /// cc.convert("乾坤一擲");
    /// cc.convert("開放中文轉換");
    /// ```
    pub fn convert(&self, text: &str) -> String {
        unsafe {
            let c_text = CString::new(text).unwrap();
            let c_ptr = opencc_convert_utf8(self.libopencc, c_text.as_ptr(), text.len() as size_t);
            let c_str = CStr::from_ptr(c_ptr);
            let str_buf = c_str.to_str().unwrap().to_owned();
            opencc_convert_utf8_free(c_ptr);
            str_buf
        }
    }

    /// Close the underlying libopencc.
    /// Will be called automatically when the variable gets out of scope.
    fn close(&mut self) {
        if !self.libopencc.is_null() {
            unsafe {
                opencc_close(self.libopencc);
            }
            self.libopencc = ptr::null_mut();
        }
    }

    /// Returns the last error message
    ///
    /// # Safety
    ///
    /// Note that this function is the only one which is NOT thread-safe.
    pub fn last_error(&mut self) -> Option<String> {
        unsafe {
            let error_ptr = opencc_error();
            if error_ptr.is_null() {
                None
            } else {
                let c_str = CStr::from_ptr(error_ptr);
                let str_buf = c_str.to_str().unwrap().to_owned();
                Some(str_buf)
            }
        }
    }
}

impl Drop for OpenCC {
    /// Close the underlying libopencc when it been droped
    fn drop(&mut self) {
        self.close();
    }
}

unsafe impl Send for OpenCC {}
unsafe impl Sync for OpenCC {}

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

    #[test]
    fn test_simple_convert() {
        let cc = OpenCC::new("t2s.json");
        assert_eq!("乾坤一掷", &cc.convert("乾坤一擲"));
        assert_eq!("开放中文转换", &cc.convert("開放中文轉換"));
    }

    #[test]
    fn test_opencc_last_error() {
        let mut cc = OpenCC::new("t2s.json");
        println!("{}", cc.last_error().unwrap());
    }
}
<|endoftext|>


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

extern crate chrono;
extern crate env_logger;
extern crate futures;
extern crate openssl;
extern crate trust_dns_client;
extern crate trust_dns_compatibility;

use std::env;
use std::fs::File;
use std::io::Read;
#[cfg(not(feature = "none"))]
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use std::str::FromStr;

#[cfg(not(feature = "none"))]
use chrono::Duration;
use openssl::rsa::Rsa;

#[cfg(not(feature = "none"))]
use trust_dns_client::client::Client;
use trust_dns_client::client::{ClientConnection, SyncClient};
#[cfg(not(feature = "none"))]
use trust_dns_client::op::ResponseCode;
use trust_dns_client::rr::dnssec::{Algorithm, KeyPair, Signer};
use trust_dns_client::rr::rdata::key::{KeyUsage, KEY};
use trust_dns_client::rr::Name;
#[cfg(not(feature = "none"))]
use trust_dns_client::rr::{DNSClass, RData, Record, RecordType};
#[cfg(not(feature = "none"))]
use trust_dns_client::udp::UdpClientConnection;
#[cfg(not(feature = "none"))]
use trust_dns_compatibility::named_process;

#[cfg(not(feature = "none"))]
#[test]
#[allow(unused)]
fn test_get() {
    let (process, port) = named_process();
    let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), port);
    let conn = UdpClientConnection::new(socket).unwrap();
    let client = SyncClient::new(conn);

    let name = Name::from_str("www.example.com.").unwrap();
    let result = client
        .query(&name, DNSClass::IN, RecordType::A)
        .expect("query failed");
    assert_eq!(result.response_code(), ResponseCode::NoError);
    assert_eq!(result.answers().len(), 1);
    assert_eq!(result.answers()[0].rr_type(), RecordType::A);

    let rdata = result.answers()[0].rdata();
    if let RData::A(address) = rdata {
        assert_eq!(address, &Ipv4Addr::new(127, 0, 0, 1));
    } else {
        panic!("RData::A wasn't here");
    }
}

#[allow(unused)]
fn create_sig0_ready_client<CC>(conn: CC) -> SyncClient<CC>
where
    CC: ClientConnection,
{
    let server_path =
        env::var("TDNS_WORKSPACE_ROOT").unwrap_or_else(|_| "../../crates/server".to_owned());
    let pem_path = format!(
        "{}/../../tests/compatibility-tests/tests/conf/Kupdate.example.com.+008+56935.pem",
        server_path
    );
    println!("loading pem from: {}", pem_path);
    let mut pem = File::open(pem_path).expect("could not find pem file");

    let mut pem_buf = Vec::<u8>::new();
    pem.read_to_end(&mut pem_buf).expect("failed to read pem");
    let rsa = Rsa::private_key_from_pem(&pem_buf).expect("something wrong with key from pem");
    let key = KeyPair::from_rsa(rsa).unwrap();
    let sig0key = KEY::new(
        Default::default(),
        KeyUsage::Entity,
        Default::default(),
        Default::default(),
        Algorithm::RSASHA256,
        key.to_public_bytes().unwrap(),
    );

    let signer = Signer::sig0(sig0key, key, Name::from_str("update.example.com").unwrap());

    assert_eq!(signer.calculate_key_tag().unwrap(), 56935_u16);

    SyncClient::with_signer(conn, signer)
}

#[cfg(not(feature = "none"))]
#[test]
#[allow(unused)]
fn test_create() {
    let (process, port) = named_process();
    let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), port);
    let conn = UdpClientConnection::new(socket).unwrap();

    let client = create_sig0_ready_client(conn);
    let origin = Name::from_str("example.com.").unwrap();

    // create a record
    let mut record = Record::with(
        Name::from_str("new.example.com.").unwrap(),
        RecordType::A,
        Duration::minutes(5).num_seconds() as u32,
    );
    record.set_rdata(RData::A(Ipv4Addr::new(100, 10, 100, 10)));

    let result = client
        .create(record.clone(), origin.clone())
        .expect("create failed");
    assert_eq!(result.response_code(), ResponseCode::NoError);
    let result = client
        .query(record.name(), record.dns_class(), record.rr_type())
        .expect("query failed");
    assert_eq!(result.response_code(), ResponseCode::NoError);
    assert_eq!(result.answers().len(), 1);
    assert_eq!(result.answers()[0], record);

    // trying to create again should error
    // TODO: it would be cool to make this
    let result = client
        .create(record.clone(), origin.clone())
        .expect("create failed");
    assert_eq!(result.response_code(), ResponseCode::YXRRSet);

    // will fail if already set and not the same value.
    let mut record = record;
    record.set_rdata(RData::A(Ipv4Addr::new(101, 11, 101, 11)));

    let result = client.create(record, origin).expect("create failed");
    assert_eq!(result.response_code(), ResponseCode::YXRRSet);
}

// #[test]
// fn test_update() {
//     // named_process();
// }

// #[test]
// fn test_delete() {
//     // named_process();
// }
<commit_msg>cleanup paths for coverage script run<commit_after>// Copyright 2015-2017 Benjamin Fry <benjaminfry@me.com>
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

extern crate chrono;
extern crate env_logger;
extern crate futures;
extern crate openssl;
extern crate trust_dns_client;
extern crate trust_dns_compatibility;

use std::env;
use std::fs::File;
use std::io::Read;
#[cfg(not(feature = "none"))]
use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use std::str::FromStr;

#[cfg(not(feature = "none"))]
use chrono::Duration;
use openssl::rsa::Rsa;

#[cfg(not(feature = "none"))]
use trust_dns_client::client::Client;
use trust_dns_client::client::{ClientConnection, SyncClient};
#[cfg(not(feature = "none"))]
use trust_dns_client::op::ResponseCode;
use trust_dns_client::rr::dnssec::{Algorithm, KeyPair, Signer};
use trust_dns_client::rr::rdata::key::{KeyUsage, KEY};
use trust_dns_client::rr::Name;
#[cfg(not(feature = "none"))]
use trust_dns_client::rr::{DNSClass, RData, Record, RecordType};
#[cfg(not(feature = "none"))]
use trust_dns_client::udp::UdpClientConnection;
#[cfg(not(feature = "none"))]
use trust_dns_compatibility::named_process;

#[cfg(not(feature = "none"))]
#[test]
#[allow(unused)]
fn test_get() {
    let (process, port) = named_process();
    let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), port);
    let conn = UdpClientConnection::new(socket).unwrap();
    let client = SyncClient::new(conn);

    let name = Name::from_str("www.example.com.").unwrap();
    let result = client
        .query(&name, DNSClass::IN, RecordType::A)
        .expect("query failed");
    assert_eq!(result.response_code(), ResponseCode::NoError);
    assert_eq!(result.answers().len(), 1);
    assert_eq!(result.answers()[0].rr_type(), RecordType::A);

    let rdata = result.answers()[0].rdata();
    if let RData::A(address) = rdata {
        assert_eq!(address, &Ipv4Addr::new(127, 0, 0, 1));
    } else {
        panic!("RData::A wasn't here");
    }
}

#[allow(unused)]
fn create_sig0_ready_client<CC>(conn: CC) -> SyncClient<CC>
where
    CC: ClientConnection,
{
    let server_path = env::var("TDNS_WORKSPACE_ROOT").unwrap_or_else(|_| "../..".to_owned());
    let pem_path = format!(
        "{}/tests/compatibility-tests/tests/conf/Kupdate.example.com.+008+56935.pem",
        server_path
    );
    println!("loading pem from: {}", pem_path);
    let mut pem = File::open(pem_path).expect("could not find pem file");

    let mut pem_buf = Vec::<u8>::new();
    pem.read_to_end(&mut pem_buf).expect("failed to read pem");
    let rsa = Rsa::private_key_from_pem(&pem_buf).expect("something wrong with key from pem");
    let key = KeyPair::from_rsa(rsa).unwrap();
    let sig0key = KEY::new(
        Default::default(),
        KeyUsage::Entity,
        Default::default(),
        Default::default(),
        Algorithm::RSASHA256,
        key.to_public_bytes().unwrap(),
    );

    let signer = Signer::sig0(sig0key, key, Name::from_str("update.example.com").unwrap());

    assert_eq!(signer.calculate_key_tag().unwrap(), 56935_u16);

    SyncClient::with_signer(conn, signer)
}

#[cfg(not(feature = "none"))]
#[test]
#[allow(unused)]
fn test_create() {
    let (process, port) = named_process();
    let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), port);
    let conn = UdpClientConnection::new(socket).unwrap();

    let client = create_sig0_ready_client(conn);
    let origin = Name::from_str("example.com.").unwrap();

    // create a record
    let mut record = Record::with(
        Name::from_str("new.example.com.").unwrap(),
        RecordType::A,
        Duration::minutes(5).num_seconds() as u32,
    );
    record.set_rdata(RData::A(Ipv4Addr::new(100, 10, 100, 10)));

    let result = client
        .create(record.clone(), origin.clone())
        .expect("create failed");
    assert_eq!(result.response_code(), ResponseCode::NoError);
    let result = client
        .query(record.name(), record.dns_class(), record.rr_type())
        .expect("query failed");
    assert_eq!(result.response_code(), ResponseCode::NoError);
    assert_eq!(result.answers().len(), 1);
    assert_eq!(result.answers()[0], record);

    // trying to create again should error
    // TODO: it would be cool to make this
    let result = client
        .create(record.clone(), origin.clone())
        .expect("create failed");
    assert_eq!(result.response_code(), ResponseCode::YXRRSet);

    // will fail if already set and not the same value.
    let mut record = record;
    record.set_rdata(RData::A(Ipv4Addr::new(101, 11, 101, 11)));

    let result = client.create(record, origin).expect("create failed");
    assert_eq!(result.response_code(), ResponseCode::YXRRSet);
}

// #[test]
// fn test_update() {
//     // named_process();
// }

// #[test]
// fn test_delete() {
//     // named_process();
// }
<|endoftext|>


<commit_before>#![deny(missing_docs)]

//! The official Piston window back-end for the Piston game engine

extern crate piston;
extern crate gfx;
extern crate gfx_device_gl;
extern crate gfx_graphics;
extern crate graphics;

use std::cell::RefCell;
use std::rc::Rc;
use std::any::Any;

use piston::{ event, window };
use gfx::traits::*;
use gfx_graphics::{ Gfx2d, GfxGraphics };
use graphics::Context;

/// Actual gfx::Stream implementation carried by the window.
pub type GfxStream = gfx::OwnedStream<
    gfx_device_gl::Resources, gfx_device_gl::CommandBuffer, gfx_device_gl::Output
>;

/// Contains everything required for controlling window, graphics, event loop.
pub struct PistonWindow<W: window::Window, T = ()> {
    /// The window.
    pub window: Rc<RefCell<W>>,
    /// GFX stream.
    pub stream: Rc<RefCell<GfxStream>>,
    /// GFX device.
    pub device: Rc<RefCell<gfx_device_gl::Device>>,
    /// Gfx2d.
    pub g2d: Rc<RefCell<Gfx2d<gfx_device_gl::Resources>>>,
    /// The event loop.
    pub events: Rc<RefCell<event::WindowEvents<W, event::Event<W::Event>>>>,
    /// The event.
    pub event: Option<event::Event<W::Event>>,
    /// Application structure.
    pub app: Rc<RefCell<T>>,
}

impl<W, T> Clone for PistonWindow<W, T>
    where W: window::Window, W::Event: Clone
{
    fn clone(&self) -> Self {
        PistonWindow {
            window: self.window.clone(),
            stream: self.stream.clone(),
            device: self.device.clone(),
            g2d: self.g2d.clone(),
            events: self.events.clone(),
            event: self.event.clone(),
            app: self.app.clone(),
        }
    }
}

impl<W, T> PistonWindow<W, T>
    where W: window::Window, W::Event: event::GenericEvent
{
    /// Creates a new piston object.
    pub fn new(window: Rc<RefCell<W>>, app: Rc<RefCell<T>>) -> Self
        where W: window::OpenGLWindow
    {
        use piston::event::Events;
        use piston::window::{ OpenGLWindow, Window };

        let mut device = gfx_device_gl::Device::new(|s| window.borrow_mut().get_proc_address(s));
        let mut factory = device.spawn_factory();

        let draw_size = window.borrow().draw_size();
        let output = factory.make_fake_output(draw_size.width as u16, draw_size.height as u16);

        let g2d = Gfx2d::new(&mut device, &mut factory);

        let stream = factory.create_stream(output);

        PistonWindow {
            window: window.clone(),
            stream: Rc::new(RefCell::new(stream)),
            device: Rc::new(RefCell::new(device)),
            g2d: Rc::new(RefCell::new(g2d)),
            events: Rc::new(RefCell::new(window.events())),
            event: None,
            app: app,
        }
    }

    /// Changes application structure.
    pub fn app<U>(self, app: Rc<RefCell<U>>) -> PistonWindow<W, U> {
        PistonWindow {
            window: self.window,
            stream: self.stream,
            device: self.device,
            g2d: self.g2d,
            events: self.events,
            event: self.event,
            app: app,
        }
    }

    /// Renders 2D graphics.
    pub fn draw_2d<F>(&self, f: F) where
        F: FnMut(Context, &mut GfxGraphics<
            gfx_device_gl::Resources, gfx_device_gl::CommandBuffer,
            gfx_device_gl::Output>)
    {
        use piston::event::RenderEvent;

        if let Some(ref e) = self.event {
            if let Some(args) = e.render_args() {
                let mut stream = self.stream.borrow_mut();
                {
                    let (renderer, output) = stream.access();
                    self.g2d.borrow_mut().draw(renderer, output, args.viewport(), f);
                }
                stream.flush(&mut *self.device.borrow_mut());
            }
        }
    }

    /// Renders 3D graphics.
    pub fn draw_3d<F>(&self, mut f: F) where
        F: FnMut(&mut GfxStream)
    {
        use piston::event::RenderEvent;

        if let Some(ref e) = self.event {
            if let Some(_) = e.render_args() {
                let mut stream = self.stream.borrow_mut();
                f(&mut *stream);
                stream.flush(&mut *self.device.borrow_mut())
            }
        }
    }
}

impl<W, T> Iterator for PistonWindow<W, T>
    where W: window::Window, W::Event: event::GenericEvent
{
    type Item = PistonWindow<W, T>;

    fn next(&mut self) -> Option<PistonWindow<W, T>> {
        use piston::event::*;

        if let Some(e) = self.events.borrow_mut().next() {
            if let Some(_) = e.after_render_args() {
                // After swapping buffers.
                self.device.borrow_mut().cleanup();
            }

            if let Some(_) = e.resize_args() {
                let mut stream = self.stream.borrow_mut();
                let draw_size = self.window.borrow().draw_size();
                stream.out.width = draw_size.width as u16;
                stream.out.height = draw_size.height as u16;
            }

            Some(PistonWindow {
                window: self.window.clone(),
                stream: self.stream.clone(),
                device: self.device.clone(),
                g2d: self.g2d.clone(),
                events: self.events.clone(),
                event: Some(e),
                app: self.app.clone(),
            })
        } else { None }
    }
}

impl<W, T> event::GenericEvent for PistonWindow<W, T>
    where W: window::Window, W::Event: event::GenericEvent
{
    fn event_id(&self) -> event::EventId {
        match self.event {
            Some(ref e) => e.event_id(),
            None => event::EventId("")
        }
    }

    fn with_args<'a, F, U>(&'a self, f: F) -> U
       where F: FnMut(&Any) -> U
    {
        self.event.as_ref().unwrap().with_args(f)
    }

    fn from_args(event_id: event::EventId, any: &Any, old_event: &Self) -> Option<Self> {
        if let Some(ref e) = old_event.event {
            match event::GenericEvent::from_args(event_id, any, e) {
                Some(e) => {
                    Some(PistonWindow {
                        window: old_event.window.clone(),
                        stream: old_event.stream.clone(),
                        device: old_event.device.clone(),
                        g2d: old_event.g2d.clone(),
                        events: old_event.events.clone(),
                        event: Some(e),
                        app: old_event.app.clone(),
                    })
                }
                None => None
            }
        } else { None }
    }
}

impl<W, T> window::Window for PistonWindow<W, T>
    where W: window::Window
{
    type Event = <W as window::Window>::Event;

    fn should_close(&self) -> bool { self.window.borrow().should_close() }
    fn size(&self) -> window::Size { self.window.borrow().size() }
    fn draw_size(&self) -> window::Size { self.window.borrow().draw_size() }
    fn swap_buffers(&mut self) { self.window.borrow_mut().swap_buffers() }
    fn poll_event(&mut self) -> Option<Self::Event> {
        window::Window::poll_event(&mut *self.window.borrow_mut())
    }
}

impl<W, T> window::AdvancedWindow for PistonWindow<W, T>
    where W: window::AdvancedWindow
{
    fn get_title(&self) -> String { self.window.borrow().get_title() }
    fn set_title(&mut self, title: String) {
        self.window.borrow_mut().set_title(title)
    }
    fn get_exit_on_esc(&self) -> bool { self.window.borrow().get_exit_on_esc() }
    fn set_exit_on_esc(&mut self, value: bool) {
        self.window.borrow_mut().set_exit_on_esc(value)
    }
    fn set_capture_cursor(&mut self, value: bool) {
        self.window.borrow_mut().set_capture_cursor(value)
    }
}

/// Creates a new empty application.
pub fn empty_app() -> Rc<RefCell<()>> { Rc::new(RefCell::new(())) }
<commit_msg>Update to latest gfx_graphics<commit_after>#![deny(missing_docs)]

//! The official Piston window back-end for the Piston game engine

extern crate piston;
extern crate gfx;
extern crate gfx_device_gl;
extern crate gfx_graphics;
extern crate graphics;

use std::cell::RefCell;
use std::rc::Rc;
use std::any::Any;

use piston::{ event, window };
use gfx::traits::*;
use gfx_graphics::{ Gfx2d, GfxGraphics };
use graphics::Context;

/// Actual gfx::Stream implementation carried by the window.
pub type GfxStream = gfx::OwnedStream<
    gfx_device_gl::Resources, gfx_device_gl::CommandBuffer, gfx_device_gl::Output
>;

/// Contains everything required for controlling window, graphics, event loop.
pub struct PistonWindow<W: window::Window, T = ()> {
    /// The window.
    pub window: Rc<RefCell<W>>,
    /// GFX stream.
    pub stream: Rc<RefCell<GfxStream>>,
    /// GFX device.
    pub device: Rc<RefCell<gfx_device_gl::Device>>,
    /// Gfx2d.
    pub g2d: Rc<RefCell<Gfx2d<gfx_device_gl::Resources>>>,
    /// The event loop.
    pub events: Rc<RefCell<event::WindowEvents<W, event::Event<W::Event>>>>,
    /// The event.
    pub event: Option<event::Event<W::Event>>,
    /// Application structure.
    pub app: Rc<RefCell<T>>,
}

impl<W, T> Clone for PistonWindow<W, T>
    where W: window::Window, W::Event: Clone
{
    fn clone(&self) -> Self {
        PistonWindow {
            window: self.window.clone(),
            stream: self.stream.clone(),
            device: self.device.clone(),
            g2d: self.g2d.clone(),
            events: self.events.clone(),
            event: self.event.clone(),
            app: self.app.clone(),
        }
    }
}

impl<W, T> PistonWindow<W, T>
    where W: window::Window, W::Event: event::GenericEvent
{
    /// Creates a new piston object.
    pub fn new(window: Rc<RefCell<W>>, app: Rc<RefCell<T>>) -> Self
        where W: window::OpenGLWindow
    {
        use piston::event::Events;
        use piston::window::{ OpenGLWindow, Window };

        let device = gfx_device_gl::Device::new(|s| window.borrow_mut().get_proc_address(s));
        let mut factory = device.spawn_factory();

        let draw_size = window.borrow().draw_size();
        let output = factory.make_fake_output(draw_size.width as u16, draw_size.height as u16);

        let g2d = Gfx2d::new(&mut factory);

        let stream = factory.create_stream(output);

        PistonWindow {
            window: window.clone(),
            stream: Rc::new(RefCell::new(stream)),
            device: Rc::new(RefCell::new(device)),
            g2d: Rc::new(RefCell::new(g2d)),
            events: Rc::new(RefCell::new(window.events())),
            event: None,
            app: app,
        }
    }

    /// Changes application structure.
    pub fn app<U>(self, app: Rc<RefCell<U>>) -> PistonWindow<W, U> {
        PistonWindow {
            window: self.window,
            stream: self.stream,
            device: self.device,
            g2d: self.g2d,
            events: self.events,
            event: self.event,
            app: app,
        }
    }

    /// Renders 2D graphics.
    pub fn draw_2d<F>(&self, f: F) where
        F: FnMut(Context, &mut GfxGraphics<
            gfx_device_gl::Resources, gfx_device_gl::CommandBuffer,
            gfx_device_gl::Output>)
    {
        use piston::event::RenderEvent;

        if let Some(ref e) = self.event {
            if let Some(args) = e.render_args() {
                let mut stream = self.stream.borrow_mut();
                {
                    let (renderer, output) = stream.access();
                    self.g2d.borrow_mut().draw(renderer, output, args.viewport(), f);
                }
                stream.flush(&mut *self.device.borrow_mut());
            }
        }
    }

    /// Renders 3D graphics.
    pub fn draw_3d<F>(&self, mut f: F) where
        F: FnMut(&mut GfxStream)
    {
        use piston::event::RenderEvent;

        if let Some(ref e) = self.event {
            if let Some(_) = e.render_args() {
                let mut stream = self.stream.borrow_mut();
                f(&mut *stream);
                stream.flush(&mut *self.device.borrow_mut())
            }
        }
    }
}

impl<W, T> Iterator for PistonWindow<W, T>
    where W: window::Window, W::Event: event::GenericEvent
{
    type Item = PistonWindow<W, T>;

    fn next(&mut self) -> Option<PistonWindow<W, T>> {
        use piston::event::*;

        if let Some(e) = self.events.borrow_mut().next() {
            if let Some(_) = e.after_render_args() {
                // After swapping buffers.
                self.device.borrow_mut().cleanup();
            }

            if let Some(_) = e.resize_args() {
                let mut stream = self.stream.borrow_mut();
                let draw_size = self.window.borrow().draw_size();
                stream.out.width = draw_size.width as u16;
                stream.out.height = draw_size.height as u16;
            }

            Some(PistonWindow {
                window: self.window.clone(),
                stream: self.stream.clone(),
                device: self.device.clone(),
                g2d: self.g2d.clone(),
                events: self.events.clone(),
                event: Some(e),
                app: self.app.clone(),
            })
        } else { None }
    }
}

impl<W, T> event::GenericEvent for PistonWindow<W, T>
    where W: window::Window, W::Event: event::GenericEvent
{
    fn event_id(&self) -> event::EventId {
        match self.event {
            Some(ref e) => e.event_id(),
            None => event::EventId("")
        }
    }

    fn with_args<'a, F, U>(&'a self, f: F) -> U
       where F: FnMut(&Any) -> U
    {
        self.event.as_ref().unwrap().with_args(f)
    }

    fn from_args(event_id: event::EventId, any: &Any, old_event: &Self) -> Option<Self> {
        if let Some(ref e) = old_event.event {
            match event::GenericEvent::from_args(event_id, any, e) {
                Some(e) => {
                    Some(PistonWindow {
                        window: old_event.window.clone(),
                        stream: old_event.stream.clone(),
                        device: old_event.device.clone(),
                        g2d: old_event.g2d.clone(),
                        events: old_event.events.clone(),
                        event: Some(e),
                        app: old_event.app.clone(),
                    })
                }
                None => None
            }
        } else { None }
    }
}

impl<W, T> window::Window for PistonWindow<W, T>
    where W: window::Window
{
    type Event = <W as window::Window>::Event;

    fn should_close(&self) -> bool { self.window.borrow().should_close() }
    fn size(&self) -> window::Size { self.window.borrow().size() }
    fn draw_size(&self) -> window::Size { self.window.borrow().draw_size() }
    fn swap_buffers(&mut self) { self.window.borrow_mut().swap_buffers() }
    fn poll_event(&mut self) -> Option<Self::Event> {
        window::Window::poll_event(&mut *self.window.borrow_mut())
    }
}

impl<W, T> window::AdvancedWindow for PistonWindow<W, T>
    where W: window::AdvancedWindow
{
    fn get_title(&self) -> String { self.window.borrow().get_title() }
    fn set_title(&mut self, title: String) {
        self.window.borrow_mut().set_title(title)
    }
    fn get_exit_on_esc(&self) -> bool { self.window.borrow().get_exit_on_esc() }
    fn set_exit_on_esc(&mut self, value: bool) {
        self.window.borrow_mut().set_exit_on_esc(value)
    }
    fn set_capture_cursor(&mut self, value: bool) {
        self.window.borrow_mut().set_capture_cursor(value)
    }
}

/// Creates a new empty application.
pub fn empty_app() -> Rc<RefCell<()>> { Rc::new(RefCell::new(())) }
<|endoftext|>


<commit_before>#![deny(missing_docs)]

//! Meta parsing and encoding for data oriented design

extern crate read_token;
extern crate range;

pub use whitespace::Whitespace;
pub use parse_error_handler::{ ParseErrorHandler, ParseStdErr };
pub use parse_error::ParseError;
pub use ty::Type;
pub use token::Token;
pub use select::Select;
pub use parameter::Parameter;
pub use optional::Optional;
pub use until_any_or_whitespace::UntilAnyOrWhitespace;
pub use text::Text;
pub use number::Number;
pub use rule::Rule;
pub use meta_reader::MetaReader;
pub use tokenizer::Tokenizer;

use std::rc::Rc;

mod parse_error;
mod parse_error_handler;
mod ty;
mod token;
mod whitespace;
mod select;
mod parameter;
mod optional;
mod until_any_or_whitespace;
mod text;
mod number;
mod rule;
mod meta_reader;
mod tokenizer;

/// Represents a data structure to read into.
pub struct Struct<'a> {
    /// The fields of a struct.
    pub fields: &'a mut [Data<'a>],
}

/// Allocated data for reading.
/// This also tells the meta parser which properties are required
/// and which properties that are optional.
pub enum Data<'a> {
    /// Has a f64 property.
    F64(&'a str, &'a mut f64),
    /// Has a bool property.
    Bool(&'a str, &'a mut bool),
    /// Has a string property.
    String(&'a str, &'a mut String),
    /// Has a sub node.
    Node(&'a str),
    /// Has an optional f64 property.
    MaybeF64(&'a str, &'a mut Option<f64>),
    /// Has an optional bool property.
    MaybeBool(&'a str, &'a mut Option<bool>),
    /// Has an optional string property.
    MaybeString(&'a str, &'a mut Option<String>),
    /// Has an optional sub node.
    MaybeNode(&'a str),
}

/// Represents meta data.
pub enum MetaData {
    /// Starts node.
    StartNode(Rc<String>),
    /// Ends node.
    EndNode,
    /// Sets bool property.
    Bool(Rc<String>, bool),
    /// Sets f64 property.
    F64(Rc<String>, f64),
    /// Sets string property.
    String(Rc<String>, String),
}

/// Implemented by meta writers.
pub trait MetaWriter {
    /// Starts encoding a node.
    fn start_node(&mut self, name: &str);
    /// Ends encoding a node.
    fn end_node(&mut self, name: &str);
    /// Get bool property.
    fn get_as_bool(&mut self, name: &str) -> Option<bool>;
    /// Get str property.
    fn get_as_str<F, U>(&mut self, name: &str, f: F) -> Option<U>
        where F: FnOnce(&str) -> U;
    /// Get f64 property.
    fn get_as_f64(&mut self, name: &str) -> Option<f64>;
}

#[inline(always)]
fn update<'a>(range: range::Range, chars: &mut &'a [char], offset: &mut usize) {
    let next_offset = range.next_offset();
    *chars = &chars[next_offset - *offset..];
    *offset = next_offset;
}

/// Used by meta readers to handle or forward a state.
/// This makes it easier to write generic meta readers wrapping a sub reader.
pub enum CommandState<T, U> {
    /// Handle state.
    Handle(T),
    /// Forward command to sub meta reader.
    Forward(U),
}
<commit_msg>Removed unused stuff<commit_after>#![deny(missing_docs)]

//! Meta parsing and encoding for data oriented design

extern crate read_token;
extern crate range;

pub use whitespace::Whitespace;
pub use parse_error_handler::{ ParseErrorHandler, ParseStdErr };
pub use parse_error::ParseError;
pub use ty::Type;
pub use token::Token;
pub use select::Select;
pub use parameter::Parameter;
pub use optional::Optional;
pub use until_any_or_whitespace::UntilAnyOrWhitespace;
pub use text::Text;
pub use number::Number;
pub use rule::Rule;
pub use meta_reader::MetaReader;
pub use tokenizer::Tokenizer;

use std::rc::Rc;

mod parse_error;
mod parse_error_handler;
mod ty;
mod token;
mod whitespace;
mod select;
mod parameter;
mod optional;
mod until_any_or_whitespace;
mod text;
mod number;
mod rule;
mod meta_reader;
mod tokenizer;

/// Represents meta data.
pub enum MetaData {
    /// Starts node.
    StartNode(Rc<String>),
    /// Ends node.
    EndNode,
    /// Sets bool property.
    Bool(Rc<String>, bool),
    /// Sets f64 property.
    F64(Rc<String>, f64),
    /// Sets string property.
    String(Rc<String>, String),
}

#[inline(always)]
fn update<'a>(range: range::Range, chars: &mut &'a [char], offset: &mut usize) {
    let next_offset = range.next_offset();
    *chars = &chars[next_offset - *offset..];
    *offset = next_offset;
}
<|endoftext|>


<commit_before>#![crate_type = "lib"]
#![warn(missing_docs)]

//! Synchronization primitives based on spinning

#![no_std]

#[cfg(test)]
#[macro_use]
extern crate std;

pub use mutex::*;
pub use rw_lock::*;
pub use once::*;

mod mutex;
mod rw_lock;
mod once;

/// Spin synchronisation primitives, but compatible with `lock_api`.
#[cfg(feature = "lock_api1")]
pub mod lock_api {
    /// `lock_api`-compatible version of [`crate::Mutex`].
    pub type Mutex<T> = lock_api::Mutex<crate::Mutex<()>, T>;

    /// `lock_api`-compatible version of [`crate::RwLock`].
    pub type RwLock<T> = lock_api::RwLock<crate::RwLock<()>, T>;
}
<commit_msg>Added lock definitions<commit_after>#![crate_type = "lib"]
#![warn(missing_docs)]

//! Synchronization primitives based on spinning

#![no_std]

#[cfg(test)]
#[macro_use]
extern crate std;

pub use mutex::*;
pub use rw_lock::*;
pub use once::*;

mod mutex;
mod rw_lock;
mod once;

/// Spin synchronisation primitives, but compatible with `lock_api`.
#[cfg(feature = "lock_api1")]
pub mod lock_api {
    /// `lock_api`-compatible version of [`crate::Mutex`].
    pub type Mutex<T> = lock_api::Mutex<crate::Mutex<()>, T>;

    /// `lock_api`-compatible version of [`crate::MutexGuard`].
    pub type MutexGuard<'a, T> = lock_api::MutexGuard<'a, crate::Mutex<()>, T>;

    /// `lock_api`-compatible version of [`crate::RwLock`].
    pub type RwLock<T> = lock_api::RwLock<crate::RwLock<()>, T>;

    /// `lock_api`-compatible version of [`crate::RwLockWriteGuard`].
    pub type RwLockWriteGuard<'a, T> = lock_api::RwLockWriteGuard<'a, crate::RwLock<()>, T>;

    /// `lock_api`-compatible version of [`crate::RwLockReadGuard`].
    pub type RwLockReadGuard<'a, T> = lock_api::RwLockReadGuard<'a, crate::RwLock<()>, T>;
}
<|endoftext|>


<commit_before>use std::io;
use std::io::prelude::*;
use std::io::{Error, ErrorKind};

pub trait Endec {
    type T;

    fn encoded_len(value: &Self::T) -> usize;

    fn encode(value: &Self::T, dst: &mut Write) -> io::Result<usize>;
    fn decode(src: &mut Read) -> io::Result<Self::T>;
}

pub trait Packet {
    type T;

    fn encode(&self, dst: &mut Write) -> io::Result<usize>;
    fn decode(src: &mut Read) -> io::Result<Self::T>;
}

impl Endec for u16 {
    type T = u16;

    fn encoded_len(value: &Self::T) -> usize {
        2
    }

    fn encode(value: &Self::T, dst: &mut Write) -> io::Result<usize> {
        let mut buf = [0u8; 2];
        buf[0] = (value >> 8 & 0xffu8 as u16) as u8;
        buf[1] = (value & 0xffu8 as u16) as u8;

        assert_eq!(dst.write(&buf).is_ok(), true);
        Ok(2)
    }

    fn decode(src: &mut Read) -> io::Result<Self::T> {
        let mut buf = [0u8; 2];
        assert_eq!(src.read(&mut buf).is_ok(), true);
        Ok(((buf[0] as u16) << 8 ) | (buf[1] as u16))
    }
}

macro_rules! packets {
    ($($id:expr => $name:ident { $($fname:ident: $fty:ty),* })+) => {
        #[derive(Debug)]
        enum Protocol {
            $(
                $name { $($fname:$fty),* }
             ),+
        }

        impl Endec for Protocol {
            type T = Protocol ;

            fn encoded_len(value: &Self::T) -> usize {
                let mut len: usize = 0;

                match value { $(
                    &Protocol::$name { $($fname),* } => {$(
                        //TODO: try! is not the best thing here
                        len += <$fty as Endec>::encoded_len(&$fname);
                    )*}
                )+}

                len
            }

            fn encode(value: &Self::T, dst: &mut Write) -> io::Result<usize> {
                let mut len: usize = 0;

                match value { $(
                    &Protocol::$name { $($fname),* } => {$(
                        //TODO: try! is not the best thing here
                        len += try!(<$fty as Endec>::encode(&$fname, dst));
                    )*}
                )+}

                Ok(len)
            }

            fn decode(src: &mut Read) -> io::Result<Self::T> {
                let id = 0;

                match id {
                    $(
                        $id => Ok(Protocol::$name {
                                    $(
                                        $fname:try!(<$fty as Endec>::decode(src))
                                    ),*
                                }),
                    )+
                        _ => Err(Error::new(ErrorKind::Other, "oh no!"))
                }
            }
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::io;
    use std::io::prelude::*;
    use std::io::{Error, ErrorKind};

    packets! {
        0 => Message { a: u16, b: u16 }
        1 => Msg { b: u16 }
    }

    #[test]
    fn test_main() {
        let x:Protocol = Protocol::Message { a: 10, b: 15 };
        let mut buf:Vec<u8> = Vec::new();
        Protocol::encode(&x, &mut buf);
        println!("{:?}", buf);
        assert!(Protocol::encoded_len(&x) == 4);
    }

}
<commit_msg>macros kinda work with one 'full' protocol, but not more yet<commit_after>use std::io;
use std::io::prelude::*;
use std::io::{Error, ErrorKind};

pub trait Endec {
    type T;

    fn encoded_len(value: &Self::T) -> usize;

    fn encode(value: &Self::T, dst: &mut Write) -> io::Result<usize>;
    fn decode(src: &mut Read) -> io::Result<Self::T>;
}

impl Endec for u16 {
    type T = u16;

    fn encoded_len(value: &Self::T) -> usize {
        2
    }

    fn encode(value: &Self::T, dst: &mut Write) -> io::Result<usize> {
        let mut buf = [0u8; 2];
        buf[0] = (value >> 8 & 0xffu8 as u16) as u8;
        buf[1] = (value & 0xffu8 as u16) as u8;

        assert_eq!(dst.write(&buf).is_ok(), true);
        Ok(2)
    }

    fn decode(src: &mut Read) -> io::Result<Self::T> {
        let mut buf = [0u8; 2];
        assert_eq!(src.read(&mut buf).is_ok(), true);
        Ok(((buf[0] as u16) << 8 ) | (buf[1] as u16))
    }
}

macro_rules! packets {
    ($($id:expr => $name:ident { $($fname:ident: $fty:ty),* })+) => {
        #[derive(Debug)]
        enum Protocol {
            $(
                $name { $($fname:$fty),* }
             ),+
        }

        impl Endec for Protocol {
            type T = Protocol ;

            fn encoded_len(value: &Self::T) -> usize {
                let mut len: usize = 0;

                match value { $(
                    &Protocol::$name { $($fname),* } => {$(
                        //TODO: try! is not the best thing here
                        len += <$fty as Endec>::encoded_len(&$fname);
                    )*}
                )+}

                len
            }

            fn encode(value: &Self::T, dst: &mut Write) -> io::Result<usize> {
                let mut len: usize = 0;

                match value { $(
                    &Protocol::$name { $($fname),* } => {$(
                        //TODO: try! is not the best thing here
                        len += try!(<$fty as Endec>::encode(&$fname, dst));
                    )*}
                )+}

                Ok(len)
            }

            fn decode(src: &mut Read) -> io::Result<Self::T> {
                let id = 0;

                match id {
                    $(
                        $id => Ok(Protocol::$name {
                                    $(
                                        $fname:try!(<$fty as Endec>::decode(src))
                                    ),*
                                }),
                    )+
                        _ => Err(Error::new(ErrorKind::Other, "oh no!"))
                }
            }
        }
    }
}

macro_rules! protocol {
    ($proto_name:ident : $header_func:expr => {
        $($id:expr => $name:ident { $($fname:ident: $fty:ty),* })+}) => {
            packets!($($id => $name { $($fname:$fty),* })+);
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::io;
    use std::io::prelude::*;
    use std::io::{Error, ErrorKind};

    protocol! {
        dummy : |x, y| -> [u8] { [0u8,2] } => {
            0 => Message { a: u16, b: u16 }
            1 => Msg { b: u16 }
        }
        //other : |x, y| -> [u8] { [0u8, 2] } => {
            //0 => Message { a: u16, b: u16 }
            //1 => Msg { b: u16 }
        //}
    }

    #[test]
    fn test_main() {

        let x:Protocol = Protocol::Message { a: 10, b: 15 };
        let mut buf:Vec<u8> = Vec::new();
        Protocol::encode(&x, &mut buf);
        println!("{:?}", buf);
        assert!(Protocol::encoded_len(&x) == 4);
    }

}
<|endoftext|>


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

#![doc(html_root_url = "https://docs.rs/itoa/0.4.2")]

#![cfg_attr(not(feature = "std"), no_std)]

#![cfg_attr(feature = "i128", feature(i128_type, i128))]

#![cfg_attr(feature = "cargo-clippy", allow(cast_lossless, unreadable_literal))]

#[cfg(feature = "i128")]
mod udiv128;

#[cfg(feature = "std")]
use std::{fmt, io, mem, ptr, slice, str};

#[cfg(not(feature = "std"))]
use core::{fmt, mem, ptr, slice, str};

/// Write integer to an `io::Write`.
#[cfg(feature = "std")]
#[inline]
pub fn write<W: io::Write, V: Integer>(mut wr: W, value: V) -> io::Result<usize> {
    let mut buf = Buffer::new();
    let s = buf.format(value);
    try!(wr.write_all(s.as_bytes()));
    Ok(s.len())
}

/// Write integer to an `fmt::Write`.
#[inline]
pub fn fmt<W: fmt::Write, V: Integer>(mut wr: W, value: V) -> fmt::Result {
    let mut buf = Buffer::new();
    wr.write_str(buf.format(value))
}

/// A safe API for formatting integers to text.
#[derive(Copy, Clone)]
pub struct Buffer {
    bytes: [u8; I128_MAX_LEN],
}

impl Default for Buffer {
    fn default() -> Buffer {
        Buffer::new()
    }
}

impl Buffer {
    /// This is a cheap operation; you don't need to worry about reusing buffers
    /// for efficiency.
    pub fn new() -> Buffer {
        Buffer { bytes: unsafe { mem::uninitialized() } }
    }

    /// Print an integer into this buffer and return a reference to its string representation
    /// within the buffer
    pub fn format<I: Integer>(&mut self, i: I) -> &str {
        i.write(self)
    }
}

// Seal to prevent downstream implementations of the Integer trait.
mod private {
    pub trait Sealed {}
}

/// An integer that can be formatted by `itoa::write` and `itoa::fmt`.
///
/// This trait is sealed and cannot be implemented for types outside of itoa.
pub trait Integer: private::Sealed {
    // Not public API.
    #[doc(hidden)]
    fn write<'a>(self, buf: &'a mut Buffer) -> &'a str;
}

trait IntegerPrivate<B> {
    fn write_to(self, buf: &mut B) -> &[u8];
}

const DEC_DIGITS_LUT: &'static[u8] =
    b"0001020304050607080910111213141516171819\
      2021222324252627282930313233343536373839\
      4041424344454647484950515253545556575859\
      6061626364656667686970717273747576777879\
      8081828384858687888990919293949596979899";

// Adaptation of the original implementation at
// https://github.com/rust-lang/rust/blob/b8214dc6c6fc20d0a660fb5700dca9ebf51ebe89/src/libcore/fmt/num.rs#L188-L266
macro_rules! impl_IntegerCommon {
    ($max_len:expr, $t:ident) => {
        impl Integer for $t {
            #[inline]
            fn write<'a>(self, buf: &'a mut Buffer) -> &'a str {
                unsafe {
                    debug_assert!($max_len <= I128_MAX_LEN);
                    let buf = mem::transmute::<&mut [u8; I128_MAX_LEN], &mut [u8; $max_len]>(
                        &mut buf.bytes
                    );
                    let bytes = self.write_to(buf);
                    str::from_utf8_unchecked(bytes)
                }
            }
        }

        impl private::Sealed for $t {}
    };
}

macro_rules! impl_Integer {
    ($($max_len:expr => $t:ident),* as $conv_fn:ident) => {$(
        impl_IntegerCommon!($max_len, $t);

        impl IntegerPrivate<[u8; $max_len]> for $t {
            #[allow(unused_comparisons)]
            #[inline]
            fn write_to(self, buf: &mut [u8; $max_len]) -> &[u8] {
                let is_nonnegative = self >= 0;
                let mut n = if is_nonnegative {
                    self as $conv_fn
                } else {
                    // convert the negative num to positive by summing 1 to it's 2 complement
                    (!(self as $conv_fn)).wrapping_add(1)
                };
                let mut curr = buf.len() as isize;
                let buf_ptr = buf.as_mut_ptr();
                let lut_ptr = DEC_DIGITS_LUT.as_ptr();

                unsafe {
                    // need at least 16 bits for the 4-characters-at-a-time to work.
                    if mem::size_of::<$t>() >= 2 {
                        // eagerly decode 4 characters at a time
                        while n >= 10000 {
                            let rem = (n % 10000) as isize;
                            n /= 10000;

                            let d1 = (rem / 100) << 1;
                            let d2 = (rem % 100) << 1;
                            curr -= 4;
                            ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                            ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(curr + 2), 2);
                        }
                    }

                    // if we reach here numbers are <= 9999, so at most 4 chars long
                    let mut n = n as isize; // possibly reduce 64bit math

                    // decode 2 more chars, if > 2 chars
                    if n >= 100 {
                        let d1 = (n % 100) << 1;
                        n /= 100;
                        curr -= 2;
                        ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                    }

                    // decode last 1 or 2 chars
                    if n < 10 {
                        curr -= 1;
                        *buf_ptr.offset(curr) = (n as u8) + b'0';
                    } else {
                        let d1 = n << 1;
                        curr -= 2;
                        ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                    }

                    if !is_nonnegative {
                        curr -= 1;
                        *buf_ptr.offset(curr) = b'-';
                    }
                }

                let len = buf.len() - curr as usize;
                unsafe { slice::from_raw_parts(buf_ptr.offset(curr), len) }
            }
        }
    )*};
}

const I8_MAX_LEN: usize = 4;
const U8_MAX_LEN: usize = 3;
const I16_MAX_LEN: usize = 6;
const U16_MAX_LEN: usize = 5;
const I32_MAX_LEN: usize = 11;
const U32_MAX_LEN: usize = 10;
const I64_MAX_LEN: usize = 20;
const U64_MAX_LEN: usize = 20;

impl_Integer!(
    I8_MAX_LEN => i8,
    U8_MAX_LEN => u8,
    I16_MAX_LEN => i16,
    U16_MAX_LEN => u16,
    I32_MAX_LEN => i32,
    U32_MAX_LEN => u32
    as u32);

impl_Integer!(I64_MAX_LEN => i64, U64_MAX_LEN => u64 as u64);

#[cfg(target_pointer_width = "16")]
impl_Integer!(I16_MAX_LEN => isize, U16_MAX_LEN => usize as u16);

#[cfg(target_pointer_width = "32")]
impl_Integer!(I32_MAX_LEN => isize, U32_MAX_LEN => usize as u32);

#[cfg(target_pointer_width = "64")]
impl_Integer!(I64_MAX_LEN => isize, U64_MAX_LEN => usize as u64);

#[cfg(all(feature = "i128"))]
macro_rules! impl_Integer128 {
    ($($max_len:expr => $t:ident),*) => {$(
        impl_IntegerCommon!($max_len, $t);

        impl IntegerPrivate<[u8; $max_len]> for $t {
            #[allow(unused_comparisons)]
            #[inline]
            fn write_to(self, buf: &mut [u8; $max_len]) -> &[u8] {
                let is_nonnegative = self >= 0;
                let n = if is_nonnegative {
                    self as u128
                } else {
                    // convert the negative num to positive by summing 1 to it's 2 complement
                    (!(self as u128)).wrapping_add(1)
                };
                let mut curr = buf.len() as isize;
                let buf_ptr = buf.as_mut_ptr();

                unsafe {
                    // Divide by 10^19 which is the highest power less than 2^64.
                    let (n, rem) = udiv128::udivmod_1e19(n);
                    let buf1 = buf_ptr.offset(curr - U64_MAX_LEN as isize) as *mut [u8; U64_MAX_LEN];
                    curr -= rem.write_to(&mut *buf1).len() as isize;

                    if n != 0 {
                        // Memset the base10 leading zeros of rem.
                        let target = buf.len() as isize - 19;
                        ptr::write_bytes(buf_ptr.offset(target), b'0', (curr - target) as usize);
                        curr = target;

                        // Divide by 10^19 again.
                        let (n, rem) = udiv128::udivmod_1e19(n);
                        let buf2 = buf_ptr.offset(curr - U64_MAX_LEN as isize) as *mut [u8; U64_MAX_LEN];
                        curr -= rem.write_to(&mut *buf2).len() as isize;

                        if n != 0 {
                            // Memset the leading zeros.
                            let target = buf.len() as isize - 38;
                            ptr::write_bytes(buf_ptr.offset(target), b'0', (curr - target) as usize);
                            curr = target;

                            // There is at most one digit left
                            // because u128::max / 10^19 / 10^19 is 3.
                            curr -= 1;
                            *buf_ptr.offset(curr) = (n as u8) + b'0';
                        }
                    }

                    if !is_nonnegative {
                        curr -= 1;
                        *buf_ptr.offset(curr) = b'-';
                    }

                    let len = buf.len() - curr as usize;
                    slice::from_raw_parts(buf_ptr.offset(curr), len)
                }
            }
        }
    )*};
}

#[cfg(all(feature = "i128"))]
const U128_MAX_LEN: usize = 39;
const I128_MAX_LEN: usize = 40;

#[cfg(all(feature = "i128"))]
impl_Integer128!(I128_MAX_LEN => i128, U128_MAX_LEN => u128);
<commit_msg>Inline the buffer construction functions<commit_after>// Copyright 2016 Itoa Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![doc(html_root_url = "https://docs.rs/itoa/0.4.2")]

#![cfg_attr(not(feature = "std"), no_std)]

#![cfg_attr(feature = "i128", feature(i128_type, i128))]

#![cfg_attr(feature = "cargo-clippy", allow(cast_lossless, unreadable_literal))]

#[cfg(feature = "i128")]
mod udiv128;

#[cfg(feature = "std")]
use std::{fmt, io, mem, ptr, slice, str};

#[cfg(not(feature = "std"))]
use core::{fmt, mem, ptr, slice, str};

/// Write integer to an `io::Write`.
#[cfg(feature = "std")]
#[inline]
pub fn write<W: io::Write, V: Integer>(mut wr: W, value: V) -> io::Result<usize> {
    let mut buf = Buffer::new();
    let s = buf.format(value);
    try!(wr.write_all(s.as_bytes()));
    Ok(s.len())
}

/// Write integer to an `fmt::Write`.
#[inline]
pub fn fmt<W: fmt::Write, V: Integer>(mut wr: W, value: V) -> fmt::Result {
    let mut buf = Buffer::new();
    wr.write_str(buf.format(value))
}

/// A safe API for formatting integers to text.
#[derive(Copy, Clone)]
pub struct Buffer {
    bytes: [u8; I128_MAX_LEN],
}

impl Default for Buffer {
    #[inline]
    fn default() -> Buffer {
        Buffer::new()
    }
}

impl Buffer {
    /// This is a cheap operation; you don't need to worry about reusing buffers
    /// for efficiency.
    #[inline]
    pub fn new() -> Buffer {
        Buffer { bytes: unsafe { mem::uninitialized() } }
    }

    /// Print an integer into this buffer and return a reference to its string representation
    /// within the buffer
    pub fn format<I: Integer>(&mut self, i: I) -> &str {
        i.write(self)
    }
}

// Seal to prevent downstream implementations of the Integer trait.
mod private {
    pub trait Sealed {}
}

/// An integer that can be formatted by `itoa::write` and `itoa::fmt`.
///
/// This trait is sealed and cannot be implemented for types outside of itoa.
pub trait Integer: private::Sealed {
    // Not public API.
    #[doc(hidden)]
    fn write<'a>(self, buf: &'a mut Buffer) -> &'a str;
}

trait IntegerPrivate<B> {
    fn write_to(self, buf: &mut B) -> &[u8];
}

const DEC_DIGITS_LUT: &'static[u8] =
    b"0001020304050607080910111213141516171819\
      2021222324252627282930313233343536373839\
      4041424344454647484950515253545556575859\
      6061626364656667686970717273747576777879\
      8081828384858687888990919293949596979899";

// Adaptation of the original implementation at
// https://github.com/rust-lang/rust/blob/b8214dc6c6fc20d0a660fb5700dca9ebf51ebe89/src/libcore/fmt/num.rs#L188-L266
macro_rules! impl_IntegerCommon {
    ($max_len:expr, $t:ident) => {
        impl Integer for $t {
            #[inline]
            fn write<'a>(self, buf: &'a mut Buffer) -> &'a str {
                unsafe {
                    debug_assert!($max_len <= I128_MAX_LEN);
                    let buf = mem::transmute::<&mut [u8; I128_MAX_LEN], &mut [u8; $max_len]>(
                        &mut buf.bytes
                    );
                    let bytes = self.write_to(buf);
                    str::from_utf8_unchecked(bytes)
                }
            }
        }

        impl private::Sealed for $t {}
    };
}

macro_rules! impl_Integer {
    ($($max_len:expr => $t:ident),* as $conv_fn:ident) => {$(
        impl_IntegerCommon!($max_len, $t);

        impl IntegerPrivate<[u8; $max_len]> for $t {
            #[allow(unused_comparisons)]
            #[inline]
            fn write_to(self, buf: &mut [u8; $max_len]) -> &[u8] {
                let is_nonnegative = self >= 0;
                let mut n = if is_nonnegative {
                    self as $conv_fn
                } else {
                    // convert the negative num to positive by summing 1 to it's 2 complement
                    (!(self as $conv_fn)).wrapping_add(1)
                };
                let mut curr = buf.len() as isize;
                let buf_ptr = buf.as_mut_ptr();
                let lut_ptr = DEC_DIGITS_LUT.as_ptr();

                unsafe {
                    // need at least 16 bits for the 4-characters-at-a-time to work.
                    if mem::size_of::<$t>() >= 2 {
                        // eagerly decode 4 characters at a time
                        while n >= 10000 {
                            let rem = (n % 10000) as isize;
                            n /= 10000;

                            let d1 = (rem / 100) << 1;
                            let d2 = (rem % 100) << 1;
                            curr -= 4;
                            ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                            ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(curr + 2), 2);
                        }
                    }

                    // if we reach here numbers are <= 9999, so at most 4 chars long
                    let mut n = n as isize; // possibly reduce 64bit math

                    // decode 2 more chars, if > 2 chars
                    if n >= 100 {
                        let d1 = (n % 100) << 1;
                        n /= 100;
                        curr -= 2;
                        ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                    }

                    // decode last 1 or 2 chars
                    if n < 10 {
                        curr -= 1;
                        *buf_ptr.offset(curr) = (n as u8) + b'0';
                    } else {
                        let d1 = n << 1;
                        curr -= 2;
                        ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
                    }

                    if !is_nonnegative {
                        curr -= 1;
                        *buf_ptr.offset(curr) = b'-';
                    }
                }

                let len = buf.len() - curr as usize;
                unsafe { slice::from_raw_parts(buf_ptr.offset(curr), len) }
            }
        }
    )*};
}

const I8_MAX_LEN: usize = 4;
const U8_MAX_LEN: usize = 3;
const I16_MAX_LEN: usize = 6;
const U16_MAX_LEN: usize = 5;
const I32_MAX_LEN: usize = 11;
const U32_MAX_LEN: usize = 10;
const I64_MAX_LEN: usize = 20;
const U64_MAX_LEN: usize = 20;

impl_Integer!(
    I8_MAX_LEN => i8,
    U8_MAX_LEN => u8,
    I16_MAX_LEN => i16,
    U16_MAX_LEN => u16,
    I32_MAX_LEN => i32,
    U32_MAX_LEN => u32
    as u32);

impl_Integer!(I64_MAX_LEN => i64, U64_MAX_LEN => u64 as u64);

#[cfg(target_pointer_width = "16")]
impl_Integer!(I16_MAX_LEN => isize, U16_MAX_LEN => usize as u16);

#[cfg(target_pointer_width = "32")]
impl_Integer!(I32_MAX_LEN => isize, U32_MAX_LEN => usize as u32);

#[cfg(target_pointer_width = "64")]
impl_Integer!(I64_MAX_LEN => isize, U64_MAX_LEN => usize as u64);

#[cfg(all(feature = "i128"))]
macro_rules! impl_Integer128 {
    ($($max_len:expr => $t:ident),*) => {$(
        impl_IntegerCommon!($max_len, $t);

        impl IntegerPrivate<[u8; $max_len]> for $t {
            #[allow(unused_comparisons)]
            #[inline]
            fn write_to(self, buf: &mut [u8; $max_len]) -> &[u8] {
                let is_nonnegative = self >= 0;
                let n = if is_nonnegative {
                    self as u128
                } else {
                    // convert the negative num to positive by summing 1 to it's 2 complement
                    (!(self as u128)).wrapping_add(1)
                };
                let mut curr = buf.len() as isize;
                let buf_ptr = buf.as_mut_ptr();

                unsafe {
                    // Divide by 10^19 which is the highest power less than 2^64.
                    let (n, rem) = udiv128::udivmod_1e19(n);
                    let buf1 = buf_ptr.offset(curr - U64_MAX_LEN as isize) as *mut [u8; U64_MAX_LEN];
                    curr -= rem.write_to(&mut *buf1).len() as isize;

                    if n != 0 {
                        // Memset the base10 leading zeros of rem.
                        let target = buf.len() as isize - 19;
                        ptr::write_bytes(buf_ptr.offset(target), b'0', (curr - target) as usize);
                        curr = target;

                        // Divide by 10^19 again.
                        let (n, rem) = udiv128::udivmod_1e19(n);
                        let buf2 = buf_ptr.offset(curr - U64_MAX_LEN as isize) as *mut [u8; U64_MAX_LEN];
                        curr -= rem.write_to(&mut *buf2).len() as isize;

                        if n != 0 {
                            // Memset the leading zeros.
                            let target = buf.len() as isize - 38;
                            ptr::write_bytes(buf_ptr.offset(target), b'0', (curr - target) as usize);
                            curr = target;

                            // There is at most one digit left
                            // because u128::max / 10^19 / 10^19 is 3.
                            curr -= 1;
                            *buf_ptr.offset(curr) = (n as u8) + b'0';
                        }
                    }

                    if !is_nonnegative {
                        curr -= 1;
                        *buf_ptr.offset(curr) = b'-';
                    }

                    let len = buf.len() - curr as usize;
                    slice::from_raw_parts(buf_ptr.offset(curr), len)
                }
            }
        }
    )*};
}

#[cfg(all(feature = "i128"))]
const U128_MAX_LEN: usize = 39;
const I128_MAX_LEN: usize = 40;

#[cfg(all(feature = "i128"))]
impl_Integer128!(I128_MAX_LEN => i128, U128_MAX_LEN => u128);
<|endoftext|>


<commit_before>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// 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.

//! An implementation of the [Cap'n Proto remote procedure call](https://capnproto.org/rpc.html)
//! protocol. Includes all [Level 1](https://capnproto.org/rpc.html#protocol-features) features.
//!
//! # Example
//!
//! ```capnp
//! # Cap'n Proto schema
//! interface Foo {
//!     identity @0 (x: UInt32) -> (y: UInt32);
//! }
//! ```
//!
//! ```ignore
//! // Rust server defining an implementation of Foo.
//! struct FooImpl;
//! impl foo::Server for FooImpl {
//!     fn identity(&mut self,
//!                 params: foo::IdentityParams,
//!                 mut results: foo::IdentityResults)
//!                 -> Promise<(), ::capnp::Error>
//!     {
//!         let x = pry!(params.get()).get_x();
//!         results.get().set_x(x);
//!         Promise::ok(())
//!     }
//! }
//! ```
//!
//! ```ignore
//! // Rust client calling a remote implementation of Foo.
//! let mut request = foo_client.identity_request();
//! request.get().set_x(123);
//! let promise = request.send().promise.map(|response| {
//!     println!("results = {}", try!(response.get()).get_y());
//!     Ok(())
//! });
//! ```
//!
//! For a more complete example, see https://github.com/dwrensha/capnp-rpc-rust/tree/master/examples/calculator

extern crate capnp;
#[macro_use] extern crate gj;
extern crate gjio;
extern crate capnp_gj;

use gj::Promise;
use capnp::Error;
use capnp::private::capability::{ClientHook, ServerHook};
use std::cell::RefCell;
use std::rc::Rc;

/// Code generated from [rpc.capnp]
/// (https://github.com/sandstorm-io/capnproto/blob/master/c%2B%2B/src/capnp/rpc.capnp).
pub mod rpc_capnp {
  include!(concat!(env!("OUT_DIR"), "/rpc_capnp.rs"));
}

/// Code generated from [rpc-twoparty.capnp]
/// (https://github.com/sandstorm-io/capnproto/blob/master/c%2B%2B/src/capnp/rpc-twoparty.capnp).
pub mod rpc_twoparty_capnp {
  include!(concat!(env!("OUT_DIR"), "/rpc_twoparty_capnp.rs"));
}

mod broken;
mod local;
mod queued;
mod rpc;
pub mod twoparty;

pub trait OutgoingMessage {
    fn get_body<'a>(&'a mut self) -> ::capnp::Result<::capnp::any_pointer::Builder<'a>>;
    fn get_body_as_reader<'a>(&'a self) -> ::capnp::Result<::capnp::any_pointer::Reader<'a>>;

    /// Sends the message. Returns a promise for the message that resolves once the send has completed.
    /// Dropping the returned promise does *not* cancel the send.
    fn send(self: Box<Self>)
            -> Promise<::capnp::message::Builder<::capnp::message::HeapAllocator>, ::capnp::Error>;

    fn take(self: Box<Self>) -> ::capnp::message::Builder<::capnp::message::HeapAllocator>;
}

pub trait IncomingMessage {
    fn get_body<'a>(&'a self) -> ::capnp::Result<::capnp::any_pointer::Reader<'a>>;
}

pub trait Connection<VatId> {
    fn get_peer_vat_id(&self) -> VatId;
    fn new_outgoing_message(&mut self, first_segment_word_size: u32) -> Box<OutgoingMessage>;

    /// Waits for a message to be received and returns it.  If the read stream cleanly terminates,
    /// returns None. If any other problem occurs, returns an Error.
    fn receive_incoming_message(&mut self) -> Promise<Option<Box<IncomingMessage>>, Error>;

    // Waits until all outgoing messages have been sent, then shuts down the outgoing stream. The
    // returned promise resolves after shutdown is complete.
    fn shutdown(&mut self) -> Promise<(), Error>;
}

pub trait VatNetwork<VatId> {
    /// Returns None if `hostId` refers to the local vat.
    fn connect(&mut self, hostId: VatId) -> Option<Box<Connection<VatId>>>;

    /// Waits for the next incoming connection and return it.
    fn accept(&mut self) -> ::gj::Promise<Box<Connection<VatId>>, ::capnp::Error>;
}

struct SystemTaskReaper;
impl ::gj::TaskReaper<(), Error> for SystemTaskReaper {
    fn task_failed(&mut self, error: Error) {
        println!("ERROR: {}", error);
    }
}

/// A portal to objects available on the network.
///
/// The RPC implemententation sits on top of an implementation of `VatNetwork`, which
/// determines how to form connections between vats. The RPC implementation determines
/// how to use such connections to manage object references and make method calls.
///
/// At the moment, this is all rather more general than it needs to be, because the only
/// implementation of `VatNetwork` is `twoparty::VatNetwork`. However, eventually we
/// will need to have more sophistocated `VatNetwork` implementations, in order to support
/// [level 3](https://capnproto.org/rpc.html#protocol-features) features.
pub struct RpcSystem<VatId> where VatId: 'static {
    network: Box<::VatNetwork<VatId>>,

    bootstrap_cap: Box<ClientHook>,

    // XXX To handle three or more party networks, this should be a map from connection pointers
    // to connection states.
    connection_state: Rc<RefCell<Option<Rc<rpc::ConnectionState<VatId>>>>>,

    tasks: Rc<RefCell<::gj::TaskSet<(), Error>>>,
}

impl <VatId> RpcSystem <VatId> {
    /// Constructs a new `RpcSystem` with the given network and bootstrap capability.
    pub fn new(network: Box<::VatNetwork<VatId>>,
               bootstrap: Option<::capnp::capability::Client>) -> RpcSystem<VatId> {
        let bootstrap_cap = match bootstrap {
            Some(cap) => cap.hook,
            None => broken::new_cap(Error::failed("no bootstrap capabiity".to_string())),
        };
        let mut result = RpcSystem {
            network: network,
            bootstrap_cap: bootstrap_cap,
            connection_state: Rc::new(RefCell::new(None)),
            tasks: Rc::new(RefCell::new(::gj::TaskSet::new(Box::new(SystemTaskReaper)))),
        };
        let accept_loop = result.accept_loop();
        result.tasks.borrow_mut().add(accept_loop);
        result
    }

    /// Connects to the given vat and returns its bootstrap interface.
    pub fn bootstrap<T>(&mut self, vat_id: VatId) -> T
        where T: ::capnp::capability::FromClientHook
    {
        let connection = match self.network.connect(vat_id) {
            Some(connection) => connection,
            None => {
                return T::new(self.bootstrap_cap.clone());
            }
        };
        let connection_state =
            RpcSystem::get_connection_state(self.connection_state.clone(),
                                            self.bootstrap_cap.clone(),
                                            connection, self.tasks.clone());

        let hook = rpc::ConnectionState::bootstrap(connection_state.clone());
        T::new(hook)
    }

    fn accept_loop(&mut self) -> Promise<(), Error> {
        let connection_state_ref = self.connection_state.clone();
        let tasks_ref = Rc::downgrade(&self.tasks);
        let bootstrap_cap = self.bootstrap_cap.clone();
        self.network.accept().map(move |connection| {
            RpcSystem::get_connection_state(connection_state_ref,
                                            bootstrap_cap,
                                            connection,
                                            tasks_ref.upgrade().expect("dangling reference to task set"));
            Ok(())
        })
    }

    fn get_connection_state(connection_state_ref: Rc<RefCell<Option<Rc<rpc::ConnectionState<VatId>>>>>,
                            bootstrap_cap: Box<ClientHook>,
                            connection: Box<::Connection<VatId>>,
                            tasks: Rc<RefCell<::gj::TaskSet<(), Error>>>)
                            -> Rc<rpc::ConnectionState<VatId>>
    {

        // TODO this needs to be updated once we allow more general VatNetworks.
        let result = match &*connection_state_ref.borrow() {
            &Some(ref connection_state) => {
                // return early.
                return connection_state.clone()
            }
            &None => {
                let (on_disconnect_promise, on_disconnect_fulfiller) = Promise::and_fulfiller();
                let connection_state_ref1 = connection_state_ref.clone();
                tasks.borrow_mut().add(on_disconnect_promise.then(move |shutdown_promise| {
                    *connection_state_ref1.borrow_mut() = None;
                    shutdown_promise
                }));
                rpc::ConnectionState::new(bootstrap_cap, connection, on_disconnect_fulfiller)
            }
        };
        *connection_state_ref.borrow_mut() = Some(result.clone());
        result
    }
}

/// Hook that allows local implementations of interfaces to be passed to the RPC system
/// so that they can be called remotely.
///
/// To use this, you need to do the following dance:
///
/// ```ignore
/// let client = foo:ToClient::new(FooImpl).from_server::<::capnp_rpc::Server>());
/// ```
pub struct Server;

impl ServerHook for Server {
    fn new_client(server: Box<::capnp::capability::Server>) -> ::capnp::capability::Client {
        ::capnp::capability::Client::new(Box::new(local::Client::new(server)))
    }
}

/// Converts a promise for a client into a client that queues up any calls that arrive
/// before the promise resolves.
// TODO: figure out a better way to allow construction of promise clients.
pub fn new_promise_client<T>(client_promise: Promise<::capnp::capability::Client, Error>) -> T
    where T: ::capnp::capability::FromClientHook
{
    T::new(Box::new(queued::Client::new(client_promise.map(|c| Ok(c.hook)))))
}
<commit_msg>fix documentation typo<commit_after>// Copyright (c) 2013-2015 Sandstorm Development Group, Inc. and contributors
// Licensed under the MIT License:
//
// 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.

//! An implementation of the [Cap'n Proto remote procedure call](https://capnproto.org/rpc.html)
//! protocol. Includes all [Level 1](https://capnproto.org/rpc.html#protocol-features) features.
//!
//! # Example
//!
//! ```capnp
//! # Cap'n Proto schema
//! interface Foo {
//!     identity @0 (x: UInt32) -> (y: UInt32);
//! }
//! ```
//!
//! ```ignore
//! // Rust server defining an implementation of Foo.
//! struct FooImpl;
//! impl foo::Server for FooImpl {
//!     fn identity(&mut self,
//!                 params: foo::IdentityParams,
//!                 mut results: foo::IdentityResults)
//!                 -> Promise<(), ::capnp::Error>
//!     {
//!         let x = pry!(params.get()).get_x();
//!         results.get().set_y(x);
//!         Promise::ok(())
//!     }
//! }
//! ```
//!
//! ```ignore
//! // Rust client calling a remote implementation of Foo.
//! let mut request = foo_client.identity_request();
//! request.get().set_x(123);
//! let promise = request.send().promise.map(|response| {
//!     println!("results = {}", try!(response.get()).get_y());
//!     Ok(())
//! });
//! ```
//!
//! For a more complete example, see https://github.com/dwrensha/capnp-rpc-rust/tree/master/examples/calculator

extern crate capnp;
#[macro_use] extern crate gj;
extern crate gjio;
extern crate capnp_gj;

use gj::Promise;
use capnp::Error;
use capnp::private::capability::{ClientHook, ServerHook};
use std::cell::RefCell;
use std::rc::Rc;

/// Code generated from [rpc.capnp]
/// (https://github.com/sandstorm-io/capnproto/blob/master/c%2B%2B/src/capnp/rpc.capnp).
pub mod rpc_capnp {
  include!(concat!(env!("OUT_DIR"), "/rpc_capnp.rs"));
}

/// Code generated from [rpc-twoparty.capnp]
/// (https://github.com/sandstorm-io/capnproto/blob/master/c%2B%2B/src/capnp/rpc-twoparty.capnp).
pub mod rpc_twoparty_capnp {
  include!(concat!(env!("OUT_DIR"), "/rpc_twoparty_capnp.rs"));
}

mod broken;
mod local;
mod queued;
mod rpc;
pub mod twoparty;

pub trait OutgoingMessage {
    fn get_body<'a>(&'a mut self) -> ::capnp::Result<::capnp::any_pointer::Builder<'a>>;
    fn get_body_as_reader<'a>(&'a self) -> ::capnp::Result<::capnp::any_pointer::Reader<'a>>;

    /// Sends the message. Returns a promise for the message that resolves once the send has completed.
    /// Dropping the returned promise does *not* cancel the send.
    fn send(self: Box<Self>)
            -> Promise<::capnp::message::Builder<::capnp::message::HeapAllocator>, ::capnp::Error>;

    fn take(self: Box<Self>) -> ::capnp::message::Builder<::capnp::message::HeapAllocator>;
}

pub trait IncomingMessage {
    fn get_body<'a>(&'a self) -> ::capnp::Result<::capnp::any_pointer::Reader<'a>>;
}

pub trait Connection<VatId> {
    fn get_peer_vat_id(&self) -> VatId;
    fn new_outgoing_message(&mut self, first_segment_word_size: u32) -> Box<OutgoingMessage>;

    /// Waits for a message to be received and returns it.  If the read stream cleanly terminates,
    /// returns None. If any other problem occurs, returns an Error.
    fn receive_incoming_message(&mut self) -> Promise<Option<Box<IncomingMessage>>, Error>;

    // Waits until all outgoing messages have been sent, then shuts down the outgoing stream. The
    // returned promise resolves after shutdown is complete.
    fn shutdown(&mut self) -> Promise<(), Error>;
}

pub trait VatNetwork<VatId> {
    /// Returns None if `hostId` refers to the local vat.
    fn connect(&mut self, hostId: VatId) -> Option<Box<Connection<VatId>>>;

    /// Waits for the next incoming connection and return it.
    fn accept(&mut self) -> ::gj::Promise<Box<Connection<VatId>>, ::capnp::Error>;
}

struct SystemTaskReaper;
impl ::gj::TaskReaper<(), Error> for SystemTaskReaper {
    fn task_failed(&mut self, error: Error) {
        println!("ERROR: {}", error);
    }
}

/// A portal to objects available on the network.
///
/// The RPC implemententation sits on top of an implementation of `VatNetwork`, which
/// determines how to form connections between vats. The RPC implementation determines
/// how to use such connections to manage object references and make method calls.
///
/// At the moment, this is all rather more general than it needs to be, because the only
/// implementation of `VatNetwork` is `twoparty::VatNetwork`. However, eventually we
/// will need to have more sophistocated `VatNetwork` implementations, in order to support
/// [level 3](https://capnproto.org/rpc.html#protocol-features) features.
pub struct RpcSystem<VatId> where VatId: 'static {
    network: Box<::VatNetwork<VatId>>,

    bootstrap_cap: Box<ClientHook>,

    // XXX To handle three or more party networks, this should be a map from connection pointers
    // to connection states.
    connection_state: Rc<RefCell<Option<Rc<rpc::ConnectionState<VatId>>>>>,

    tasks: Rc<RefCell<::gj::TaskSet<(), Error>>>,
}

impl <VatId> RpcSystem <VatId> {
    /// Constructs a new `RpcSystem` with the given network and bootstrap capability.
    pub fn new(network: Box<::VatNetwork<VatId>>,
               bootstrap: Option<::capnp::capability::Client>) -> RpcSystem<VatId> {
        let bootstrap_cap = match bootstrap {
            Some(cap) => cap.hook,
            None => broken::new_cap(Error::failed("no bootstrap capabiity".to_string())),
        };
        let mut result = RpcSystem {
            network: network,
            bootstrap_cap: bootstrap_cap,
            connection_state: Rc::new(RefCell::new(None)),
            tasks: Rc::new(RefCell::new(::gj::TaskSet::new(Box::new(SystemTaskReaper)))),
        };
        let accept_loop = result.accept_loop();
        result.tasks.borrow_mut().add(accept_loop);
        result
    }

    /// Connects to the given vat and returns its bootstrap interface.
    pub fn bootstrap<T>(&mut self, vat_id: VatId) -> T
        where T: ::capnp::capability::FromClientHook
    {
        let connection = match self.network.connect(vat_id) {
            Some(connection) => connection,
            None => {
                return T::new(self.bootstrap_cap.clone());
            }
        };
        let connection_state =
            RpcSystem::get_connection_state(self.connection_state.clone(),
                                            self.bootstrap_cap.clone(),
                                            connection, self.tasks.clone());

        let hook = rpc::ConnectionState::bootstrap(connection_state.clone());
        T::new(hook)
    }

    fn accept_loop(&mut self) -> Promise<(), Error> {
        let connection_state_ref = self.connection_state.clone();
        let tasks_ref = Rc::downgrade(&self.tasks);
        let bootstrap_cap = self.bootstrap_cap.clone();
        self.network.accept().map(move |connection| {
            RpcSystem::get_connection_state(connection_state_ref,
                                            bootstrap_cap,
                                            connection,
                                            tasks_ref.upgrade().expect("dangling reference to task set"));
            Ok(())
        })
    }

    fn get_connection_state(connection_state_ref: Rc<RefCell<Option<Rc<rpc::ConnectionState<VatId>>>>>,
                            bootstrap_cap: Box<ClientHook>,
                            connection: Box<::Connection<VatId>>,
                            tasks: Rc<RefCell<::gj::TaskSet<(), Error>>>)
                            -> Rc<rpc::ConnectionState<VatId>>
    {

        // TODO this needs to be updated once we allow more general VatNetworks.
        let result = match &*connection_state_ref.borrow() {
            &Some(ref connection_state) => {
                // return early.
                return connection_state.clone()
            }
            &None => {
                let (on_disconnect_promise, on_disconnect_fulfiller) = Promise::and_fulfiller();
                let connection_state_ref1 = connection_state_ref.clone();
                tasks.borrow_mut().add(on_disconnect_promise.then(move |shutdown_promise| {
                    *connection_state_ref1.borrow_mut() = None;
                    shutdown_promise
                }));
                rpc::ConnectionState::new(bootstrap_cap, connection, on_disconnect_fulfiller)
            }
        };
        *connection_state_ref.borrow_mut() = Some(result.clone());
        result
    }
}

/// Hook that allows local implementations of interfaces to be passed to the RPC system
/// so that they can be called remotely.
///
/// To use this, you need to do the following dance:
///
/// ```ignore
/// let client = foo:ToClient::new(FooImpl).from_server::<::capnp_rpc::Server>());
/// ```
pub struct Server;

impl ServerHook for Server {
    fn new_client(server: Box<::capnp::capability::Server>) -> ::capnp::capability::Client {
        ::capnp::capability::Client::new(Box::new(local::Client::new(server)))
    }
}

/// Converts a promise for a client into a client that queues up any calls that arrive
/// before the promise resolves.
// TODO: figure out a better way to allow construction of promise clients.
pub fn new_promise_client<T>(client_promise: Promise<::capnp::capability::Client, Error>) -> T
    where T: ::capnp::capability::FromClientHook
{
    T::new(Box::new(queued::Client::new(client_promise.map(|c| Ok(c.hook)))))
}
<|endoftext|>