<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("value", ...)
    pub fn value<'b>(&'b mut self, data: &'b[u8]) {
        unsafe {ffi::setstring(self.o, "value\0".as_bytes(), data); }
    }

    pub fn get_value<'b>(&'b self) -> Option<&'b[u8]> {
        unsafe {
            let mut sz = 0;
            let valptr = ffi::sp_getstring(self.o, "value\0".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);
        }
    }

}

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> {
    pub fn get_value<'b>(&'b self) -> Option<&'b[u8]> {
        unsafe {
            let mut sz = 0;
            let valptr = ffi::sp_getstring(self.o, "value\0".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);
        }
    }
}

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 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);
        }
    }
}

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) };
    }
}

pub struct Cursor {
    obj: ffi::Voidptr,
}

pub struct CursorObject<'a> {
    obj: ffi::Voidptr,
    cur: &'a Cursor
}

impl<'a> CursorObject<'a> {
    pub fn get_key<'b>(&'b mut self) -> Option<&'b[u8]> {
        unsafe {
            let mut sz = 0;
            let keyptr = ffi::sp_getstring(self.obj, "key\0".as_ptr(), &mut sz);

            if keyptr.is_null() {
                return None;
            }

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

    pub fn get_value<'b>(&'b mut self) -> Option<&'b[u8]> {
        unsafe {
            let mut sz = 0;
            let valptr = ffi::sp_getstring(self.obj, "value\0".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);
        }
    }
}

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

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

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

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}
    }

    pub fn iter_all(&mut self) -> Cursor {
        unsafe {
            let obj = ffi::sp_object(self.db);
            assert!(!obj.is_null());
            ffi::setstring(obj, "order\0".as_bytes(), ">=".as_bytes());
            let cursor = ffi::sp_cursor(self.db, obj);
            assert!(!cursor.is_null());
            Cursor {obj: cursor}
        }
    }

    /*
    // XXX: Cannot distinguish between key not found and no value.
    pub fn get_value(&self, key: &[u8]) -> Option<Vec<u8>> {
        match self.get(key) {
            None => None,
            Some(mut valobj) => {
                match valobj.get_value() {
                    Some(val) => Some(val.to_vec()),
                    None => None
                }
            }
        }
    }
    */
}

impl SetGetOps for Db {
    fn backend(&self) -> ffi::Voidptr { self.db }
}
<commit_msg>Remove commented out code<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 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("value", ...)
    pub fn value<'b>(&'b mut self, data: &'b[u8]) {
        unsafe {ffi::setstring(self.o, "value\0".as_bytes(), data); }
    }

    pub fn get_value<'b>(&'b self) -> Option<&'b[u8]> {
        unsafe {
            let mut sz = 0;
            let valptr = ffi::sp_getstring(self.o, "value\0".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);
        }
    }

}

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> {
    pub fn get_value<'b>(&'b self) -> Option<&'b[u8]> {
        unsafe {
            let mut sz = 0;
            let valptr = ffi::sp_getstring(self.o, "value\0".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);
        }
    }
}

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 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);
        }
    }
}

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) };
    }
}

pub struct Cursor {
    obj: ffi::Voidptr,
}

pub struct CursorObject<'a> {
    obj: ffi::Voidptr,
    cur: &'a Cursor
}

impl<'a> CursorObject<'a> {
    pub fn get_key<'b>(&'b mut self) -> Option<&'b[u8]> {
        unsafe {
            let mut sz = 0;
            let keyptr = ffi::sp_getstring(self.obj, "key\0".as_ptr(), &mut sz);

            if keyptr.is_null() {
                return None;
            }

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

    pub fn get_value<'b>(&'b mut self) -> Option<&'b[u8]> {
        unsafe {
            let mut sz = 0;
            let valptr = ffi::sp_getstring(self.obj, "value\0".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);
        }
    }
}

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

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

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

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}
    }

    pub fn iter_all(&mut self) -> Cursor {
        unsafe {
            let obj = ffi::sp_object(self.db);
            assert!(!obj.is_null());
            ffi::setstring(obj, "order\0".as_bytes(), ">=".as_bytes());
            let cursor = ffi::sp_cursor(self.db, obj);
            assert!(!cursor.is_null());
            Cursor {obj: cursor}
        }
    }
}

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


<commit_before>//!
//! # Conrod
//!
//! An easy-to-use, immediate-mode, 2D GUI library featuring a range of useful widgets.
//!

#![deny(missing_copy_implementations)]
#![warn(missing_docs)]

#[macro_use] extern crate bitflags;
extern crate clock_ticks;
extern crate elmesque;
extern crate graphics;
extern crate num;
#[macro_use] extern crate piston;
extern crate rand;
extern crate rustc_serialize;
extern crate vecmath;

pub use canvas::split::Split;

pub use widget::button::Button;
pub use widget::custom::Custom as CustomWidget;
pub use widget::custom::State as CustomWidgetState;
pub use widget::drop_down_list::DropDownList;
pub use widget::envelope_editor::EnvelopeEditor;
pub use widget::envelope_editor::EnvelopePoint;
pub use widget::label::Label;
pub use widget::number_dialer::NumberDialer;
pub use widget::slider::Slider;
pub use widget::text_box::TextBox;
pub use widget::toggle::Toggle;
pub use widget::matrix::Matrix as WidgetMatrix;
pub use widget::xy_pad::XYPad;
pub use widget::Update as WidgetUpdate;

pub use background::Background;
pub use canvas::{Canvas, CanvasId};
pub use elmesque::color;
pub use elmesque::color::{Color, Colorable};
pub use frame::{Framing, Frameable};
pub use label::{FontSize, Labelable};
pub use mouse::Mouse;
pub use mouse::ButtonState as MouseButtonState;
pub use position::{align_left_of, align_right_of, align_bottom_of, align_top_of};
pub use position::{Corner, Depth, Direction, Dimensions, HorizontalAlign, Place, Point, Position,
                   Positionable, Sizeable, VerticalAlign};
pub use theme::Theme;
pub use ui::{Ui, UiId};

#[macro_use]
mod macros;

mod background;
mod canvas;
mod frame;
mod label;
pub mod mouse;
mod position;
mod theme;
mod ui;
pub mod utils;
mod widget;

<commit_msg>Expose CharacterCache<commit_after>//!
//! # Conrod
//!
//! An easy-to-use, immediate-mode, 2D GUI library featuring a range of useful widgets.
//!

#![deny(missing_copy_implementations)]
#![warn(missing_docs)]

#[macro_use] extern crate bitflags;
extern crate clock_ticks;
extern crate elmesque;
extern crate graphics;
extern crate num;
#[macro_use] extern crate piston;
extern crate rand;
extern crate rustc_serialize;
extern crate vecmath;

pub use canvas::split::Split;

pub use widget::button::Button;
pub use widget::custom::Custom as CustomWidget;
pub use widget::custom::State as CustomWidgetState;
pub use widget::drop_down_list::DropDownList;
pub use widget::envelope_editor::EnvelopeEditor;
pub use widget::envelope_editor::EnvelopePoint;
pub use widget::label::Label;
pub use widget::number_dialer::NumberDialer;
pub use widget::slider::Slider;
pub use widget::text_box::TextBox;
pub use widget::toggle::Toggle;
pub use widget::matrix::Matrix as WidgetMatrix;
pub use widget::xy_pad::XYPad;
pub use widget::Update as WidgetUpdate;

pub use background::Background;
pub use canvas::{Canvas, CanvasId};
pub use elmesque::color;
pub use elmesque::color::{Color, Colorable};
pub use frame::{Framing, Frameable};
pub use graphics::character::CharacterCache;
pub use label::{FontSize, Labelable};
pub use mouse::Mouse;
pub use mouse::ButtonState as MouseButtonState;
pub use position::{align_left_of, align_right_of, align_bottom_of, align_top_of};
pub use position::{Corner, Depth, Direction, Dimensions, HorizontalAlign, Place, Point, Position,
                   Positionable, Sizeable, VerticalAlign};
pub use theme::Theme;
pub use ui::{Ui, UiId};

#[macro_use]
mod macros;

mod background;
mod canvas;
mod frame;
mod label;
pub mod mouse;
mod position;
mod theme;
mod ui;
pub mod utils;
mod widget;

<|endoftext|>


<commit_before>#![allow(unstable)]
#![unstable]

extern crate iron;
extern crate "rustc-serialize" as serialize;
extern crate handlebars;
extern crate modifier;
extern crate glob;

pub use self::middleware::Template;
pub use self::middleware::HandlebarsEngine;

mod middleware;
<commit_msg>(doc) docsup<commit_after>#![allow(unstable)]
#![unstable]

//! # Handlebars for Iron
//!
//! This library combines [Handlebars templating library](https://github.com/sunng87/handlebars-rust) and [Iron web framework](http://ironframework.io) together. It gives you a `HandlebarsEngine` as Iron `AfterMiddleware`, so you can render your data with specified handlebars template.
//!
//! ## Setup
//!
//! Given the template root directory (prefix) and template file extension (suffix), you can create `HandlebarsEngine` with `Handlebars::new("/prefix/path", ".hbs")` function. HandlebarsEngine will scan the directory and its sub-directories (with Unix glob **/*), and register these templates with `path/name` as name.
//!
//! ## Usage
//!
//! From any of your handler, you can set template name and data into our `Template` struct. Remember you need to make your data `ToJson`-able, which is required by handlebars-rust.
//!
//! We have implemented Modifier for `Template` on `Response`, so you can just use `response.set` to put set template into response and let it processed by our middleware.
//!

extern crate iron;
extern crate "rustc-serialize" as serialize;
extern crate handlebars;
extern crate modifier;
extern crate glob;

pub use self::middleware::Template;
pub use self::middleware::HandlebarsEngine;

mod middleware;
<|endoftext|>


<commit_before>#![allow(dead_code)]
#![allow(unused_variables)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]

extern crate libc;

use std::ffi::CString;
mod postgres;

use postgres::{
    LogicalDecodingContext,
    OutputPluginOptions,
    ReorderBufferTXN,
    Relation,
    ReorderBufferChange,
    TupleDesc,
    HeapTuple,
    Struct_HeapTupleData,
    OUTPUT_PLUGIN_TEXTUAL_OUTPUT,
    REORDER_BUFFER_CHANGE_INSERT,
    REORDER_BUFFER_CHANGE_UPDATE,
    REORDER_BUFFER_CHANGE_DELETE,
};

pub struct WrappedPG {
    pub num_attributes:i32,
}

extern {
  fn OutputPluginPrepareWrite(ctx: &LogicalDecodingContext, last_write: bool);
  fn OutputPluginWrite(ctx: &LogicalDecodingContext, last_write: bool);
  fn appendStringInfoString(str: *mut postgres::Struct_StringInfoData, s: *const i8);
}

#[no_mangle]
pub extern fn pg_decode_startup(ctx: &LogicalDecodingContext, opt: &mut OutputPluginOptions, is_init: bool) {
	opt.output_type = OUTPUT_PLUGIN_TEXTUAL_OUTPUT;
}

#[no_mangle]
pub extern fn pg_decode_change(ctx:      &LogicalDecodingContext,
                               txn:      &ReorderBufferTXN,
                               relation: Relation,
                               change:   &mut ReorderBufferChange) {

    let action_string = match change.action {
        REORDER_BUFFER_CHANGE_INSERT => { "Insert " },
        REORDER_BUFFER_CHANGE_UPDATE => { "Update " },
        REORDER_BUFFER_CHANGE_DELETE => { "Delete " },
        _                            => { "Other " },
    };

    let tuple_string = match change.action {
        REORDER_BUFFER_CHANGE_INSERT => {
            pg_tuple_to_rspgod_tuple(
                unsafe { (*relation).rd_att },
                unsafe { (*(*change.data.tp()).newtuple).tuple }
            ).num_attributes.to_string()
        },
        REORDER_BUFFER_CHANGE_UPDATE => { "Update".to_string() },
        REORDER_BUFFER_CHANGE_DELETE => { "Delete".to_string() },
        _                            => { "No Data".to_string() },
    };

    let c_action_string = CString::new(action_string).unwrap();
    let c_tuple_string  = CString::new(&tuple_string[..]).unwrap();

    unsafe {
	    OutputPluginPrepareWrite(ctx, true);
        appendStringInfoString(ctx.out, c_action_string.as_ptr());
        appendStringInfoString(ctx.out, c_tuple_string.as_ptr());
	    OutputPluginWrite(ctx, true);
    }
}

// type TupleDesc = *mut Struct_tupleDesc
//   which is: struct Struct_tupleDesc {
//                      natts: ::libc::c_int,
//                      attrs: *mut Form_pg_attribute,
//                      tdtypeid: Oid,
pub fn pg_tuple_to_rspgod_tuple(description:TupleDesc, tuple:Struct_HeapTupleData) -> WrappedPG {
    let num_attributes = unsafe { (*description).natts };
    WrappedPG { num_attributes: num_attributes }
}
    // tuple_to_avro_row (from bottledwater)
    //   this works by modifying a pointer to the (avro_value_t *output_value)
    //   or returning (at the end, or via the `check` macro) an error int
    // -----------------------------------------------------
    // int err = 0, field = 0;
    // check(err, avro_value_reset(output_val));
    // for (int i = 0; i < tupdesc->natts; i++) {
    //     avro_value_t field_val;
    //     bool isnull;
    //     Datum datum;
    //     Form_pg_attribute attr = tupdesc->attrs[i];
    //     if (attr->attisdropped) continue; /* skip dropped columns */
    //     check(err, avro_value_get_by_index(output_val, field, &field_val, NULL));
    //     datum = heap_getattr(tuple, i + 1, tupdesc, &isnull);
    //     if (isnull) {
    //         check(err, avro_value_set_branch(&field_val, 0, NULL));
    //     } else {
    //         check(err, update_avro_with_datum(&field_val, attr->atttypid, datum));
    //     }
    //     field++;
    // }
    // return err;

    // /* ----------------
    //  *		heap_getattr
    //  *
    //  *		Extract an attribute of a heap tuple and return it as a Datum.
    //  *		This works for either system or user attributes.  The given attnum
    //  *		is properly range-checked.
    //  *
    //  *		If the field in question has a NULL value, we return a zero Datum
    //  *		and set *isnull == true.  Otherwise, we set *isnull == false.
    //  *
    //  *		<tup> is the pointer to the heap tuple.  <attnum> is the attribute
    //  *		number of the column (field) caller wants.  <tupleDesc> is a
    //  *		pointer to the structure describing the row and all its fields.
    //  * ----------------
    //  */
    // #define heap_getattr(tup, attnum, tupleDesc, isnull) \
    // 	( \
    // 		((attnum) > 0) ? \
    // 		( \
    // 			((attnum) > (int) HeapTupleHeaderGetNatts((tup)->t_data)) ? \
    // 			( \
    // 				(*(isnull) = true), \
    // 				(Datum)NULL \
    // 			) \
    // 			: \
    // 				fastgetattr((tup), (attnum), (tupleDesc), (isnull)) \
    // 		) \
    // 		: \
    // 			heap_getsysattr((tup), (attnum), (tupleDesc), (isnull)) \
    // 	)
//
    // /* ----------------
    //  *		fastgetattr
    //  *
    //  *		Fetch a user attribute's value as a Datum (might be either a
    //  *		value, or a pointer into the data area of the tuple).
    //  *
    //  *		This must not be used when a system attribute might be requested.
    //  *		Furthermore, the passed attnum MUST be valid.  Use heap_getattr()
    //  *		instead, if in doubt.
    //  *
    //  *		This gets called many times, so we macro the cacheable and NULL
    //  *		lookups, and call nocachegetattr() for the rest.
    //  * ----------------
    //  */
    //
    // #if !defined(DISABLE_COMPLEX_MACRO)
    //
    // #define fastgetattr(tup, attnum, tupleDesc, isnull)					\
    // (																	\
    // 	AssertMacro((attnum) > 0),										\
    // 	(*(isnull) = false),											\
    // 	HeapTupleNoNulls(tup) ?											\
    // 	(																\
    // 		(tupleDesc)->attrs[(attnum)-1]->attcacheoff >= 0 ?			\
    // 		(															\
    // 			fetchatt((tupleDesc)->attrs[(attnum)-1],				\
    // 				(char *) (tup)->t_data + (tup)->t_data->t_hoff +	\
    // 					(tupleDesc)->attrs[(attnum)-1]->attcacheoff)	\
    // 		)															\
    // 		:															\
    // 			nocachegetattr((tup), (attnum), (tupleDesc))			\
    // 	)																\
    // 	:																\
    // 	(																\
    // 		att_isnull((attnum)-1, (tup)->t_data->t_bits) ?				\
    // 		(															\
    // 			(*(isnull) = true),										\
    // 			(Datum)NULL												\
    // 		)															\
    // 		:															\
    // 		(															\
    // 			nocachegetattr((tup), (attnum), (tupleDesc))			\
    // 		)															\
    // 	)																\
    // )
    // #else							/* defined(DISABLE_COMPLEX_MACRO) */
    //
    // extern Datum fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc,
    // 			bool *isnull);
    // #endif   /* defined(DISABLE_COMPLEX_MACRO) */

#[no_mangle]
pub extern fn pg_decode_commit_txn(ctx: &LogicalDecodingContext, txn: &ReorderBufferTXN, commit_lsn: u64) {
}

#[no_mangle]
pub extern fn pg_decode_begin_txn(ctx: &LogicalDecodingContext, txn: &ReorderBufferTXN) {
}

#[no_mangle]
pub extern fn pg_decode_shutdown(ctx: &LogicalDecodingContext) {
}

<commit_msg>Starts pulling together attribute data<commit_after>#![allow(dead_code)]
#![allow(unused_variables)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]

extern crate libc;

use std::ffi::CString;
mod postgres;

use postgres::{
    LogicalDecodingContext,
    OutputPluginOptions,
    ReorderBufferTXN,
    Relation,
    ReorderBufferChange,
    TupleDesc,
    HeapTuple,
    Struct_HeapTupleData,
    OUTPUT_PLUGIN_TEXTUAL_OUTPUT,
    REORDER_BUFFER_CHANGE_INSERT,
    REORDER_BUFFER_CHANGE_UPDATE,
    REORDER_BUFFER_CHANGE_DELETE,
};

pub struct WrappedPG {
    pub num_attributes: i32,
    pub fields:         Vec<Field>,
}

pub struct Field {
    pub name:  String,
    pub value: String,
}

extern {
  fn OutputPluginPrepareWrite(ctx: &LogicalDecodingContext, last_write: bool);
  fn OutputPluginWrite(ctx: &LogicalDecodingContext, last_write: bool);
  fn appendStringInfoString(str: *mut postgres::Struct_StringInfoData, s: *const i8);
}

#[no_mangle]
pub extern fn pg_decode_startup(ctx: &LogicalDecodingContext, opt: &mut OutputPluginOptions, is_init: bool) {
	opt.output_type = OUTPUT_PLUGIN_TEXTUAL_OUTPUT;
}

#[no_mangle]
pub extern fn pg_decode_change(ctx:      &LogicalDecodingContext,
                               txn:      &ReorderBufferTXN,
                               relation: Relation,
                               change:   &mut ReorderBufferChange) {

    let action_string = match change.action {
        REORDER_BUFFER_CHANGE_INSERT => { "Insert " },
        REORDER_BUFFER_CHANGE_UPDATE => { "Update " },
        REORDER_BUFFER_CHANGE_DELETE => { "Delete " },
        _                            => { "Other " },
    };

    let tuple_string = match change.action {
        REORDER_BUFFER_CHANGE_INSERT => {
            pg_tuple_to_rspgod_tuple(
                unsafe { (*relation).rd_att },
                unsafe { (*(*change.data.tp()).newtuple).tuple }
            ).num_attributes.to_string()
        },
        REORDER_BUFFER_CHANGE_UPDATE => { "Update".to_string() },
        REORDER_BUFFER_CHANGE_DELETE => { "Delete".to_string() },
        _                            => { "No Data".to_string() },
    };

    let c_action_string = CString::new(action_string).unwrap();
    let c_tuple_string  = CString::new(&tuple_string[..]).unwrap();

    unsafe {
	    OutputPluginPrepareWrite(ctx, true);
        appendStringInfoString(ctx.out, c_action_string.as_ptr());
        appendStringInfoString(ctx.out, c_tuple_string.as_ptr());
	    OutputPluginWrite(ctx, true);
    }
}

// type TupleDesc = *mut Struct_tupleDesc
//   which is: struct Struct_tupleDesc {
//                      natts: ::libc::c_int,
//                      attrs: *mut Form_pg_attribute,
//                      tdtypeid: Oid,
pub fn pg_tuple_to_rspgod_tuple(description:TupleDesc, tuple:Struct_HeapTupleData) -> WrappedPG {
    let num_attributes = unsafe { (*description).natts };
    let mut fields     = vec![];

    for n in 0..num_attributes {
        let attnum = unsafe { 5 };
        let thing = format!("{}", attnum);
        fields.push(Field { name: thing.clone(), value: thing.clone() });
    }

    WrappedPG {
        num_attributes: num_attributes,
        fields:         fields,
    }
}
    // tuple_to_avro_row (from bottledwater)
    //   this works by modifying a pointer to the (avro_value_t *output_value)
    //   or returning (at the end, or via the `check` macro) an error int
    // -----------------------------------------------------
    // int err = 0, field = 0;
    // check(err, avro_value_reset(output_val));
    // for (int i = 0; i < tupdesc->natts; i++) {
    //     avro_value_t field_val;
    //     bool isnull;
    //     Datum datum;
    //     Form_pg_attribute attr = tupdesc->attrs[i];
    //     if (attr->attisdropped) continue; /* skip dropped columns */
    //     check(err, avro_value_get_by_index(output_val, field, &field_val, NULL));
    //     datum = heap_getattr(tuple, i + 1, tupdesc, &isnull);
    //     if (isnull) {
    //         check(err, avro_value_set_branch(&field_val, 0, NULL));
    //     } else {
    //         check(err, update_avro_with_datum(&field_val, attr->atttypid, datum));
    //     }
    //     field++;
    // }
    // return err;

    // /* ----------------
    //  *		heap_getattr
    //  *
    //  *		Extract an attribute of a heap tuple and return it as a Datum.
    //  *		This works for either system or user attributes.  The given attnum
    //  *		is properly range-checked.
    //  *
    //  *		If the field in question has a NULL value, we return a zero Datum
    //  *		and set *isnull == true.  Otherwise, we set *isnull == false.
    //  *
    //  *		<tup> is the pointer to the heap tuple.  <attnum> is the attribute
    //  *		number of the column (field) caller wants.  <tupleDesc> is a
    //  *		pointer to the structure describing the row and all its fields.
    //  * ----------------
    //  */
    // #define heap_getattr(tup, attnum, tupleDesc, isnull) \
    // 	( \
    // 		((attnum) > 0) ? \
    // 		( \
    // 			((attnum) > (int) HeapTupleHeaderGetNatts((tup)->t_data)) ? \
    // 			( \
    // 				(*(isnull) = true), \
    // 				(Datum)NULL \
    // 			) \
    // 			: \
    // 				fastgetattr((tup), (attnum), (tupleDesc), (isnull)) \
    // 		) \
    // 		: \
    // 			heap_getsysattr((tup), (attnum), (tupleDesc), (isnull)) \
    // 	)
//
    // /* ----------------
    //  *		fastgetattr
    //  *
    //  *		Fetch a user attribute's value as a Datum (might be either a
    //  *		value, or a pointer into the data area of the tuple).
    //  *
    //  *		This must not be used when a system attribute might be requested.
    //  *		Furthermore, the passed attnum MUST be valid.  Use heap_getattr()
    //  *		instead, if in doubt.
    //  *
    //  *		This gets called many times, so we macro the cacheable and NULL
    //  *		lookups, and call nocachegetattr() for the rest.
    //  * ----------------
    //  */
    //
    // #if !defined(DISABLE_COMPLEX_MACRO)
    //
    // #define fastgetattr(tup, attnum, tupleDesc, isnull)					\
    // (																	\
    // 	AssertMacro((attnum) > 0),										\
    // 	(*(isnull) = false),											\
    // 	HeapTupleNoNulls(tup) ?											\
    // 	(																\
    // 		(tupleDesc)->attrs[(attnum)-1]->attcacheoff >= 0 ?			\
    // 		(															\
    // 			fetchatt((tupleDesc)->attrs[(attnum)-1],				\
    // 				(char *) (tup)->t_data + (tup)->t_data->t_hoff +	\
    // 					(tupleDesc)->attrs[(attnum)-1]->attcacheoff)	\
    // 		)															\
    // 		:															\
    // 			nocachegetattr((tup), (attnum), (tupleDesc))			\
    // 	)																\
    // 	:																\
    // 	(																\
    // 		att_isnull((attnum)-1, (tup)->t_data->t_bits) ?				\
    // 		(															\
    // 			(*(isnull) = true),										\
    // 			(Datum)NULL												\
    // 		)															\
    // 		:															\
    // 		(															\
    // 			nocachegetattr((tup), (attnum), (tupleDesc))			\
    // 		)															\
    // 	)																\
    // )
    // #else							/* defined(DISABLE_COMPLEX_MACRO) */
    //
    // extern Datum fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc,
    // 			bool *isnull);
    // #endif   /* defined(DISABLE_COMPLEX_MACRO) */

#[no_mangle]
pub extern fn pg_decode_commit_txn(ctx: &LogicalDecodingContext, txn: &ReorderBufferTXN, commit_lsn: u64) {
}

#[no_mangle]
pub extern fn pg_decode_begin_txn(ctx: &LogicalDecodingContext, txn: &ReorderBufferTXN) {
}

#[no_mangle]
pub extern fn pg_decode_shutdown(ctx: &LogicalDecodingContext) {
}

<|endoftext|>


<commit_before>/*!
Compile-time dimensional analysis for various unit systems using Rust's type system.

Its goal is to provide zero cost unit safety while requiring minimal effort from the programmer.

For a short introduction and some examples, check out the [readme on
GitHub](https://github.com/paholg/dimensioned).
*/

#![doc(html_logo_url = "https://raw.githubusercontent.com/paholg/dimensioned/master/favicon.png",
       html_favicon_url = "https://raw.githubusercontent.com/paholg/dimensioned/master/favicon.png",
       html_root_url = "http://paholg.com/dimensioned")]

#![no_std]

#![warn(missing_docs)]

#![cfg_attr(feature = "oibit", feature(optin_builtin_traits))]
#![cfg_attr(feature = "spec", feature(specialization))]

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]

#![allow(unknown_lints)]
#![deny(clippy)]
#![allow(type_complexity, float_cmp, useless_attribute, doc_markdown)]

// Macro debugging
// #![feature(trace_macros)]
// trace_macros!(true);

pub extern crate typenum;

// Copied from typenum so that users don't have to import typenum for the make_units macro to work.
// Only change is the paths.
/// Construct a type-level array of type-level integers
///
/// # Example
/// ```rust
/// #[macro_use]
/// extern crate dimensioned as dim;
/// #[macro_use]
/// extern crate generic_array;
///
/// use dim::typenum::consts::*;
/// type TArr = tarr![P3, P2, N5, N8, P2];
///
/// fn main() {
///     use dim::array::ToGA;
///     let x = TArr::to_ga();
///     let y = arr![isize; 3, 2, -5, -8, 2];
///
///     assert_eq!(x, y);
/// }
/// ```
#[macro_export]
macro_rules! tarr {
    () => ( $crate::typenum::ATerm );
    ($n:ty) => ( $crate::typenum::TArr<$n, $crate::typenum::ATerm> );
    ($n:ty,) => ( $crate::typenum::TArr<$n, $crate::typenum::ATerm> );
    ($n:ty, $($tail:ty),+) => ( $crate::typenum::TArr<$n, tarr![$($tail),+]> );
    ($n:ty, $($tail:ty),+,) => ( $crate::typenum::TArr<$n, tarr![$($tail),+]> );
}

// Get a warning without this. If it's fixed, remove `useless_attribute` from clippy allow list
#[allow(unused_imports)]
#[macro_use]
pub extern crate generic_array;

#[macro_use] mod make_units;
mod fmt;

include!(concat!(env!("OUT_DIR"), "/unit_systems.rs"));
pub mod traits;
pub mod dimensions;
pub mod conversion;
pub mod array;
pub mod f32prefixes;
pub mod f64prefixes;

pub use traits::*;
pub use unit_systems::{si, ucum, cgs, mks, fps};

// Used for the make_units macro
#[doc(hidden)]
pub mod dimcore {
    pub use core::{marker, fmt, ops, mem, f32, f64};
}
<commit_msg>add to lib doc<commit_after>/*!
Compile-time dimensional analysis for various unit systems using Rust's type system.

Its goal is to provide zero cost unit safety while requiring minimal effort from the programmer.

For a short introduction and some examples, check out the [readme on
GitHub](https://github.com/paholg/dimensioned).

# Use

The recommended way to import this crate is with the rename

```rust
extern crate dimensioned as dim;
```

and then either import the module for the unit system you will be using,

```rust
# extern crate dimensioned as dim;
# fn main() {
use dim::si;
let x = 3.0 * si::M;
# }
```

or import the constants and/or types that you care about,

```rust
# extern crate dimensioned as dim;
# fn main() {
use dim::si::{Meter, M, S};
let x: Meter<f64> = 3.0 * M;
let t = 2.0 * S;
# }
```

For clarity, all the examples contained herein will import unit system modules.

# How it works

When a unit system is created, say the SI system, a struct with two parameters is made; in this
case `SI<V, U>`. The first parameter, `V`, is for the value type -- it can be anything, and is the
value to which we are giving units. The second parameter, `U`, is where the magic happens. It
represents the units, and is a type-level array of type-level numbers. Now, these guys have some
pretty ugly type signatures, so I will express the array as the macro which maps to it, `tarr![]`,
and the type numbers as their aliases; `N1` for -1, `Z0` for 0, `P1` for 1, etc.

The SI system has seven base units, so that's how many elements the type array needs to have. The
order is the order in which the base units were defined, and the values of the type numbers are the
power to which each unit is raised. For example, the first three SI units, in order, are `Meter`,
`Kilogram`, `Second`, so the following aliases exist:

```ignore
type Meter<V>    = SI<V, tarr![P1, Z0, Z0, Z0, Z0, Z0, Z0]>;
type Kilogram<V> = SI<V, tarr![Z0, P1, Z0, Z0, Z0, Z0, Z0]>;
type Second<V>   = SI<V, tarr![Z0, Z0, P1, Z0, Z0, Z0, Z0]>;
type Newton<V>   = SI<V, tarr![Z1, Z1, N2, Z0, Z0, Z0, Z0]>;
...
```

In addition to creating the unit system struct, `SI`, the type aliases, and constants for each,
various traits are implemented for the unit system. These include arithmetic operations, which work
as follows.

If you try to add a `Meter<f64>` to a `Second<f64>`, then you will get a compiler error because
they have different types and so addition is not defined. Multiplication, on the other hand, is
defined, and results in a normal multiplication of the value types, and the unit powers added.

So, multiplying `Meter<f64>` by `Second<f64>` gives `SI<f64, tarr![P1, Z0, P1, Z0, Z0, Z0,
Z0]>`.

## Example

```rust
extern crate dimensioned as dim;

use dim::si;

fn main() {
    let x = 3.0 * si::M;
    let t = 2.0 * si::S;
    assert_eq!("6 m*s", &format!("{}", x*t));
}
```

That's basically it. All of the dimensional safety comes from whether things typecheck, and from
performing type-level arithmetic, thanks to the [typenum](http://paholg.com/typenum/)
crate. Pretty much everything else is for ergonomics.

*/

#![doc(html_logo_url = "https://raw.githubusercontent.com/paholg/dimensioned/master/favicon.png",
       html_favicon_url = "https://raw.githubusercontent.com/paholg/dimensioned/master/favicon.png",
       html_root_url = "http://paholg.com/dimensioned")]

#![no_std]

#![warn(missing_docs)]

#![cfg_attr(feature = "oibit", feature(optin_builtin_traits))]
#![cfg_attr(feature = "spec", feature(specialization))]

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]

#![allow(unknown_lints)]
#![deny(clippy)]
#![allow(type_complexity, float_cmp, useless_attribute, doc_markdown)]

// Macro debugging
// #![feature(trace_macros)]
// trace_macros!(true);

pub extern crate typenum;

// Copied from typenum so that users don't have to import typenum for the make_units macro to work.
// Only change is the paths.
/// Construct a type-level array of type-level integers
///
/// # Example
/// ```rust
/// #[macro_use]
/// extern crate dimensioned as dim;
/// #[macro_use]
/// extern crate generic_array;
///
/// use dim::typenum::consts::*;
/// type TArr = tarr![P3, P2, N5, N8, P2];
///
/// fn main() {
///     use dim::array::ToGA;
///     let x = TArr::to_ga();
///     let y = arr![isize; 3, 2, -5, -8, 2];
///
///     assert_eq!(x, y);
/// }
/// ```
#[macro_export]
macro_rules! tarr {
    () => ( $crate::typenum::ATerm );
    ($n:ty) => ( $crate::typenum::TArr<$n, $crate::typenum::ATerm> );
    ($n:ty,) => ( $crate::typenum::TArr<$n, $crate::typenum::ATerm> );
    ($n:ty, $($tail:ty),+) => ( $crate::typenum::TArr<$n, tarr![$($tail),+]> );
    ($n:ty, $($tail:ty),+,) => ( $crate::typenum::TArr<$n, tarr![$($tail),+]> );
}

// Get a warning without this. If it's fixed, remove `useless_attribute` from clippy allow list
#[allow(unused_imports)]
#[macro_use]
pub extern crate generic_array;

#[macro_use] mod make_units;
mod fmt;

include!(concat!(env!("OUT_DIR"), "/unit_systems.rs"));
pub mod traits;
pub mod dimensions;
pub mod conversion;
pub mod array;
pub mod f32prefixes;
pub mod f64prefixes;

pub use traits::*;
pub use unit_systems::{si, ucum, cgs, mks, fps};

// Used for the make_units macro
#[doc(hidden)]
pub mod dimcore {
    pub use core::{marker, fmt, ops, mem, f32, f64};
}
<|endoftext|>


<commit_before>/*!
Simple persistent generic HashMap/Key-value store, using file locking to limit
writing between threads.

This is in a beta state at the moment.

Basic usage:

```
extern crate typedb;

use typedb::{ KV, Value };

fn main() {
    let mut test_store = KV::<String, Value>::new("./db.cab").unwrap();

    let _ = test_store.insert("key".to_string(), Value::String("value".to_string()));
    println!("{:?}", test_store.get("key".to_string()));
    let _ = test_store.remove("key".to_string());
}
```

Usage with user defined Key and Value types:

```
#[macro_use]
extern crate typedb;
#[macro_use]
extern crate serde_derive;

use typedb::KV;

key!(MyKey:
    String(String),
    Int(i32),
);

value!(MyValue:
    String(String),
    Int(i32),
);

fn main() {
    let mut test_store = KV::<MyKey, MyValue>::new("./db.cab").unwrap();

    let _ = test_store.insert(MyKey::Int(1i32), MyValue::String("value".to_string()));
    println!("{:?}", test_store.get(MyKey::Int(1i32)));
    let _ = test_store.remove(MyKey::Int(1i32));
}
```

*/

#![deny(missing_docs)]

extern crate bincode;
#[macro_use]
extern crate log;
extern crate persy;
extern crate serde;
#[macro_use]
extern crate serde_derive;

/// Macros for simplifying custom key and value types definition
pub mod macros;

use std::collections::HashMap;
use std::hash::Hash;

use bincode::{deserialize, serialize};
use serde::ser::Serialize;
use serde::de::Deserialize;

use persy::{Config, PRes, Persy, PersyError};

/// A default value type to use with KV
#[derive(Clone, Serialize, Deserialize, PartialEq, Debug)]
pub enum Value {
    /// Cab default Value type for strings
    String(String),
    /// Cab default Value type for intergers
    Int(i32),
    /// Cab default Value type for floats
    Float(f32),
    /// Cab default Value type for a sub map
    Map(HashMap<String, Value>),
    /// Cab default Value type for list
    List(Vec<Value>),
}

/// Type alias for results from KV
type KVResult = PRes<bool>;

/// Type alias for PersyError
type KVError = PersyError;

/// The type that represents the key-value store
pub struct KV<K, V> {
    cab: HashMap<K, V>,
    persy: Persy,
}

impl<K, V> KV<K, V>
where
    K: Clone + Serialize + for<'kde> Deserialize<'kde> + Eq + Hash,
    V: Clone + Serialize + for<'vde> Deserialize<'vde>,
{
    /// Creates a new instance of the KV store
    pub fn new(p: &'static str) -> Result<KV<K, V>, PersyError> {
        // create the KV instance
        Persy::create(p)?;
        let persy = Persy::open(p, Config::new())?;

        let mut store = KV {
            cab: HashMap::new(),
            persy: persy,
        };

        match store.load_from_persist() {
            Ok(f) => trace!("{}", f),
            Err(e) => {
                return Err(e);
            }
        };

        Ok(store)
    }

    /// Inserta a key, value pair into the key-value store
    pub fn insert(&mut self, key: K, value: V) -> KVResult {
        // make sure mem version up to date
        self.load_from_persist()?;
        // insert into the HashMap
        self.cab.insert(key, value);
        // persist
        self.write_to_persist()
    }

    /// Get the value from a key
    pub fn get(&mut self, key: K) -> Result<Option<V>, KVError> {
        // make sure mem version up to date
        self.load_from_persist()?;
        // get the value from the cab
        match self.cab.get(&key) {
            Some(v) => Ok(Some((*v).clone())),
            None => Ok(None),
        }
    }

    /// Removes a key and associated value from the key-value Store
    pub fn remove(&mut self, key: K) -> KVResult {
        // make sure mem version up to date
        self.load_from_persist()?;
        // remove from the HashMap
        self.cab.remove(&key);
        // persist
        self.write_to_persist()
    }

    /// get all the keys contained in the KV Store
    pub fn keys(&mut self) -> Result<Vec<K>, KVError> {
        // make sure mem version up to date
        self.load_from_persist()?;
        // create a vec from the cabs keys
        Ok(self.cab.keys().map(|k| k.clone()).collect())
    }

    /// Writes the key-value Store to file
    fn write_to_persist(&mut self) -> KVResult {
        // attempt to write to the cab
        let mut tx = self.persy.begin()?;
        self.persy.create_segment(&mut tx, "tdb")?;

        // serialize the cab as a u8 vec
        let byte_vec: Vec<u8> = match serialize(&mut self.cab) {
            Ok(bv) => bv,
            Err(e) => {
                error!("serialize: {}", e);
                return Err(PersyError::Err("Couldn't encode".to_string()));
            }
        };

        self.persy.insert_record(&mut tx, "tdb", &byte_vec)?;

        let prepared = self.persy.prepare_commit(tx)?;
        self.persy.commit(prepared)?;

        Ok(true)
    }

    /// Loads key-value store from file
    fn load_from_persist(&mut self) -> KVResult {
        for rec in self.persy.scan_records("tdb")? {
            let byte_vec = rec.content;
            // deserialize u8 vec back into HashMap
            match deserialize(byte_vec.as_slice()) {
                Ok(f) => {
                    // assign read HashMap back to self
                    self.cab = f;
                }
                Err(e) => {
                    error!("{}", e);
                    continue;
                }
            };
        }

        Ok(true)
    }
}
<commit_msg>Check for segment existing before loading<commit_after>/*!
Simple persistent generic HashMap/Key-value store, using file locking to limit
writing between threads.

This is in a beta state at the moment.

Basic usage:

```
extern crate typedb;

use typedb::{ KV, Value };

fn main() {
    let mut test_store = KV::<String, Value>::new("./db.cab").unwrap();

    let _ = test_store.insert("key".to_string(), Value::String("value".to_string()));
    println!("{:?}", test_store.get("key".to_string()));
    let _ = test_store.remove("key".to_string());
}
```

Usage with user defined Key and Value types:

```
#[macro_use]
extern crate typedb;
#[macro_use]
extern crate serde_derive;

use typedb::KV;

key!(MyKey:
    String(String),
    Int(i32),
);

value!(MyValue:
    String(String),
    Int(i32),
);

fn main() {
    let mut test_store = KV::<MyKey, MyValue>::new("./db.cab").unwrap();

    let _ = test_store.insert(MyKey::Int(1i32), MyValue::String("value".to_string()));
    println!("{:?}", test_store.get(MyKey::Int(1i32)));
    let _ = test_store.remove(MyKey::Int(1i32));
}
```

*/

#![deny(missing_docs)]

extern crate bincode;
#[macro_use]
extern crate log;
extern crate persy;
extern crate serde;
#[macro_use]
extern crate serde_derive;

/// Macros for simplifying custom key and value types definition
pub mod macros;

use std::collections::HashMap;
use std::hash::Hash;

use bincode::{deserialize, serialize};
use serde::ser::Serialize;
use serde::de::Deserialize;

use persy::{Config, PRes, Persy, PersyError};

/// A default value type to use with KV
#[derive(Clone, Serialize, Deserialize, PartialEq, Debug)]
pub enum Value {
    /// Cab default Value type for strings
    String(String),
    /// Cab default Value type for intergers
    Int(i32),
    /// Cab default Value type for floats
    Float(f32),
    /// Cab default Value type for a sub map
    Map(HashMap<String, Value>),
    /// Cab default Value type for list
    List(Vec<Value>),
}

/// Type alias for results from KV
type KVResult = PRes<bool>;

/// Type alias for PersyError
type KVError = PersyError;

/// The type that represents the key-value store
pub struct KV<K, V> {
    cab: HashMap<K, V>,
    persy: Persy,
}

impl<K, V> KV<K, V>
where
    K: Clone + Serialize + for<'kde> Deserialize<'kde> + Eq + Hash,
    V: Clone + Serialize + for<'vde> Deserialize<'vde>,
{
    /// Creates a new instance of the KV store
    pub fn new(p: &'static str) -> Result<KV<K, V>, PersyError> {
        // create the KV instance
        Persy::create(p)?;
        let persy = Persy::open(p, Config::new())?;

        let mut store = KV {
            cab: HashMap::new(),
            persy: persy,
        };

        match store.load_from_persist() {
            Ok(f) => trace!("{}", f),
            Err(e) => {
                return Err(e);
            }
        };

        Ok(store)
    }

    /// Inserta a key, value pair into the key-value store
    pub fn insert(&mut self, key: K, value: V) -> KVResult {
        // make sure mem version up to date
        self.load_from_persist()?;
        // insert into the HashMap
        self.cab.insert(key, value);
        // persist
        self.write_to_persist()
    }

    /// Get the value from a key
    pub fn get(&mut self, key: K) -> Result<Option<V>, KVError> {
        // make sure mem version up to date
        self.load_from_persist()?;
        // get the value from the cab
        match self.cab.get(&key) {
            Some(v) => Ok(Some((*v).clone())),
            None => Ok(None),
        }
    }

    /// Removes a key and associated value from the key-value Store
    pub fn remove(&mut self, key: K) -> KVResult {
        // make sure mem version up to date
        self.load_from_persist()?;
        // remove from the HashMap
        self.cab.remove(&key);
        // persist
        self.write_to_persist()
    }

    /// get all the keys contained in the KV Store
    pub fn keys(&mut self) -> Result<Vec<K>, KVError> {
        // make sure mem version up to date
        self.load_from_persist()?;
        // create a vec from the cabs keys
        Ok(self.cab.keys().map(|k| k.clone()).collect())
    }

    /// Writes the key-value Store to file
    fn write_to_persist(&mut self) -> KVResult {
        // attempt to write to the cab
        let mut tx = self.persy.begin()?;
        self.persy.create_segment(&mut tx, "tdb")?;

        // serialize the cab as a u8 vec
        let byte_vec: Vec<u8> = match serialize(&mut self.cab) {
            Ok(bv) => bv,
            Err(e) => {
                error!("serialize: {}", e);
                return Err(PersyError::Err("Couldn't encode".to_string()));
            }
        };

        self.persy.insert_record(&mut tx, "tdb", &byte_vec)?;

        let prepared = self.persy.prepare_commit(tx)?;
        self.persy.commit(prepared)?;

        Ok(true)
    }

    /// Loads key-value store from file
    fn load_from_persist(&mut self) -> KVResult {
        if self.persy.exists_segment("tdb")? {
            for rec in self.persy.scan_records("tdb")? {
                let byte_vec = rec.content;
                // deserialize u8 vec back into HashMap
                match deserialize(byte_vec.as_slice()) {
                    Ok(f) => {
                        // assign read HashMap back to self
                        self.cab = f;
                    }
                    Err(e) => {
                        error!("{}", e);
                        continue;
                    }
                };
            }
        }

        Ok(true)
    }
}
<|endoftext|>


<commit_before>//! Async WebSocket usage.
//!
//! This library is an implementation of WebSocket handshakes and streams. It
//! is based on the crate which implements all required WebSocket protocol
//! logic. So this crate basically just brings tokio support / tokio integration
//! to it.
//!
//! Each WebSocket stream implements the required `Stream` and `Sink` traits,
//! so the socket is just a stream of messages coming in and going out.

#![deny(missing_docs, unused_must_use, unused_mut, unused_imports, unused_import_braces)]

pub use tungstenite;

mod compat;
#[cfg(feature = "connect")]
mod connect;
mod handshake;
#[cfg(feature = "stream")]
mod stream;
#[cfg(any(feature = "native-tls", feature = "__rustls-tls", feature = "connect"))]
mod tls;

use std::io::{Read, Write};

use compat::{cvt, AllowStd, ContextWaker};
use futures_util::{
    sink::{Sink, SinkExt},
    stream::Stream,
};
use log::*;
use std::{
    pin::Pin,
    task::{Context, Poll},
};
use tokio::io::{AsyncRead, AsyncWrite};

use tungstenite::{
    client::IntoClientRequest,
    error::Error as WsError,
    handshake::{
        client::{ClientHandshake, Response},
        server::{Callback, NoCallback},
        HandshakeError,
    },
    protocol::{Message, Role, WebSocket, WebSocketConfig},
};

#[cfg(any(feature = "native-tls", feature = "__rustls-tls", feature = "connect"))]
pub use tls::Connector;
#[cfg(any(feature = "native-tls", feature = "__rustls-tls"))]
pub use tls::{client_async_tls, client_async_tls_with_config};

#[cfg(feature = "connect")]
pub use connect::{connect_async, connect_async_with_config};

#[cfg(all(any(feature = "native-tls", feature = "__rustls-tls"), feature = "connect"))]
pub use connect::connect_async_tls_with_config;

#[cfg(feature = "stream")]
pub use stream::MaybeTlsStream;

use tungstenite::protocol::CloseFrame;

/// Creates a WebSocket handshake from a request and a stream.
/// For convenience, the user may call this with a url string, a URL,
/// or a `Request`. Calling with `Request` allows the user to add
/// a WebSocket protocol or other custom headers.
///
/// Internally, this custom creates a handshake representation and returns
/// a future representing the resolution of the WebSocket handshake. The
/// returned future will resolve to either `WebSocketStream<S>` or `Error`
/// depending on whether the handshake is successful.
///
/// This is typically used for clients who have already established, for
/// example, a TCP connection to the remote server.
pub async fn client_async<'a, R, S>(
    request: R,
    stream: S,
) -> Result<(WebSocketStream<S>, Response), WsError>
where
    R: IntoClientRequest + Unpin,
    S: AsyncRead + AsyncWrite + Unpin,
{
    client_async_with_config(request, stream, None).await
}

/// The same as `client_async()` but the one can specify a websocket configuration.
/// Please refer to `client_async()` for more details.
pub async fn client_async_with_config<'a, R, S>(
    request: R,
    stream: S,
    config: Option<WebSocketConfig>,
) -> Result<(WebSocketStream<S>, Response), WsError>
where
    R: IntoClientRequest + Unpin,
    S: AsyncRead + AsyncWrite + Unpin,
{
    let f = handshake::client_handshake(stream, move |allow_std| {
        let request = request.into_client_request()?;
        let cli_handshake = ClientHandshake::start(allow_std, request, config)?;
        cli_handshake.handshake()
    });
    f.await.map_err(|e| match e {
        HandshakeError::Failure(e) => e,
        e => WsError::Io(std::io::Error::new(std::io::ErrorKind::Other, e.to_string())),
    })
}

/// Accepts a new WebSocket connection with the provided stream.
///
/// This function will internally call `server::accept` to create a
/// handshake representation and returns a future representing the
/// resolution of the WebSocket handshake. The returned future will resolve
/// to either `WebSocketStream<S>` or `Error` depending if it's successful
/// or not.
///
/// This is typically used after a socket has been accepted from a
/// `TcpListener`. That socket is then passed to this function to perform
/// the server half of the accepting a client's websocket connection.
pub async fn accept_async<S>(stream: S) -> Result<WebSocketStream<S>, WsError>
where
    S: AsyncRead + AsyncWrite + Unpin,
{
    accept_hdr_async(stream, NoCallback).await
}

/// The same as `accept_async()` but the one can specify a websocket configuration.
/// Please refer to `accept_async()` for more details.
pub async fn accept_async_with_config<S>(
    stream: S,
    config: Option<WebSocketConfig>,
) -> Result<WebSocketStream<S>, WsError>
where
    S: AsyncRead + AsyncWrite + Unpin,
{
    accept_hdr_async_with_config(stream, NoCallback, config).await
}

/// Accepts a new WebSocket connection with the provided stream.
///
/// This function does the same as `accept_async()` but accepts an extra callback
/// for header processing. The callback receives headers of the incoming
/// requests and is able to add extra headers to the reply.
pub async fn accept_hdr_async<S, C>(stream: S, callback: C) -> Result<WebSocketStream<S>, WsError>
where
    S: AsyncRead + AsyncWrite + Unpin,
    C: Callback + Unpin,
{
    accept_hdr_async_with_config(stream, callback, None).await
}

/// The same as `accept_hdr_async()` but the one can specify a websocket configuration.
/// Please refer to `accept_hdr_async()` for more details.
pub async fn accept_hdr_async_with_config<S, C>(
    stream: S,
    callback: C,
    config: Option<WebSocketConfig>,
) -> Result<WebSocketStream<S>, WsError>
where
    S: AsyncRead + AsyncWrite + Unpin,
    C: Callback + Unpin,
{
    let f = handshake::server_handshake(stream, move |allow_std| {
        tungstenite::accept_hdr_with_config(allow_std, callback, config)
    });
    f.await.map_err(|e| match e {
        HandshakeError::Failure(e) => e,
        e => WsError::Io(std::io::Error::new(std::io::ErrorKind::Other, e.to_string())),
    })
}

/// A wrapper around an underlying raw stream which implements the WebSocket
/// protocol.
///
/// A `WebSocketStream<S>` represents a handshake that has been completed
/// successfully and both the server and the client are ready for receiving
/// and sending data. Message from a `WebSocketStream<S>` are accessible
/// through the respective `Stream` and `Sink`. Check more information about
/// them in `futures-rs` crate documentation or have a look on the examples
/// and unit tests for this crate.
#[derive(Debug)]
pub struct WebSocketStream<S> {
    inner: WebSocket<AllowStd<S>>,
    closing: bool,
}

impl<S> WebSocketStream<S> {
    /// Convert a raw socket into a WebSocketStream without performing a
    /// handshake.
    pub async fn from_raw_socket(stream: S, role: Role, config: Option<WebSocketConfig>) -> Self
    where
        S: AsyncRead + AsyncWrite + Unpin,
    {
        handshake::without_handshake(stream, move |allow_std| {
            WebSocket::from_raw_socket(allow_std, role, config)
        })
        .await
    }

    /// Convert a raw socket into a WebSocketStream without performing a
    /// handshake.
    pub async fn from_partially_read(
        stream: S,
        part: Vec<u8>,
        role: Role,
        config: Option<WebSocketConfig>,
    ) -> Self
    where
        S: AsyncRead + AsyncWrite + Unpin,
    {
        handshake::without_handshake(stream, move |allow_std| {
            WebSocket::from_partially_read(allow_std, part, role, config)
        })
        .await
    }

    pub(crate) fn new(ws: WebSocket<AllowStd<S>>) -> Self {
        WebSocketStream { inner: ws, closing: false }
    }

    fn with_context<F, R>(&mut self, ctx: Option<(ContextWaker, &mut Context<'_>)>, f: F) -> R
    where
        S: Unpin,
        F: FnOnce(&mut WebSocket<AllowStd<S>>) -> R,
        AllowStd<S>: Read + Write,
    {
        trace!("{}:{} WebSocketStream.with_context", file!(), line!());
        if let Some((kind, ctx)) = ctx {
            self.inner.get_mut().set_waker(kind, ctx.waker());
        }
        f(&mut self.inner)
    }

    /// Returns a shared reference to the inner stream.
    pub fn get_ref(&self) -> &S
    where
        S: AsyncRead + AsyncWrite + Unpin,
    {
        self.inner.get_ref().get_ref()
    }

    /// Returns a mutable reference to the inner stream.
    pub fn get_mut(&mut self) -> &mut S
    where
        S: AsyncRead + AsyncWrite + Unpin,
    {
        self.inner.get_mut().get_mut()
    }

    /// Returns a reference to the configuration of the tungstenite stream.
    pub fn get_config(&self) -> &WebSocketConfig {
        self.inner.get_config()
    }

    /// Close the underlying web socket
    pub async fn close(&mut self, msg: Option<CloseFrame<'_>>) -> Result<(), WsError>
    where
        S: AsyncRead + AsyncWrite + Unpin,
    {
        let msg = msg.map(|msg| msg.into_owned());
        self.send(Message::Close(msg)).await
    }
}

impl<T> Stream for WebSocketStream<T>
where
    T: AsyncRead + AsyncWrite + Unpin,
{
    type Item = Result<Message, WsError>;

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        trace!("{}:{} Stream.poll_next", file!(), line!());
        match futures_util::ready!(self.with_context(Some((ContextWaker::Read, cx)), |s| {
            trace!("{}:{} Stream.with_context poll_next -> read_message()", file!(), line!());
            cvt(s.read_message())
        })) {
            Ok(v) => Poll::Ready(Some(Ok(v))),
            Err(WsError::AlreadyClosed) | Err(WsError::ConnectionClosed) => Poll::Ready(None),
            Err(e) => Poll::Ready(Some(Err(e))),
        }
    }
}

impl<T> Sink<Message> for WebSocketStream<T>
where
    T: AsyncRead + AsyncWrite + Unpin,
{
    type Error = WsError;

    fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
        (*self).with_context(Some((ContextWaker::Write, cx)), |s| cvt(s.write_pending()))
    }

    fn start_send(mut self: Pin<&mut Self>, item: Message) -> Result<(), Self::Error> {
        match (*self).with_context(None, |s| s.write_message(item)) {
            Ok(()) => Ok(()),
            Err(::tungstenite::Error::Io(err)) if err.kind() == std::io::ErrorKind::WouldBlock => {
                // the message was accepted and queued
                // isn't an error.
                Ok(())
            }
            Err(e) => {
                debug!("websocket start_send error: {}", e);
                Err(e)
            }
        }
    }

    fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
        (*self).with_context(Some((ContextWaker::Write, cx)), |s| cvt(s.write_pending()))
    }

    fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
        if self.closing {
            // After queing it, we call `write_pending` to drive the close handshake to completion.
            match (*self).with_context(Some((ContextWaker::Write, cx)), |s| s.write_pending()) {
                Ok(()) => Poll::Ready(Ok(())),
                Err(::tungstenite::Error::ConnectionClosed) => Poll::Ready(Ok(())),
                Err(::tungstenite::Error::Io(err))
                    if err.kind() == std::io::ErrorKind::WouldBlock =>
                {
                    trace!("WouldBlock");
                    Poll::Pending
                }
                Err(err) => Poll::Ready(Err(err)),
            }
        } else {
            match (*self).with_context(Some((ContextWaker::Write, cx)), |s| s.close(None)) {
                Ok(()) => Poll::Ready(Ok(())),
                Err(::tungstenite::Error::ConnectionClosed) => Poll::Ready(Ok(())),
                Err(::tungstenite::Error::Io(err))
                    if err.kind() == std::io::ErrorKind::WouldBlock =>
                {
                    trace!("WouldBlock");
                    self.closing = true;
                    Poll::Pending
                }
                Err(err) => {
                    debug!("websocket close error: {}", err);
                    Poll::Ready(Err(err))
                }
            }
        }
    }
}

/// Get a domain from an URL.
#[cfg(any(feature = "connect", feature = "native-tls", feature = "__rustls-tls"))]
#[inline]
fn domain(request: &tungstenite::handshake::client::Request) -> Result<String, WsError> {
    match request.uri().host() {
        Some(d) => Ok(d.to_string()),
        None => Err(WsError::Url(tungstenite::error::UrlError::NoHostName)),
    }
}

#[cfg(test)]
mod tests {
    #[cfg(feature = "connect")]
    use crate::stream::MaybeTlsStream;
    use crate::{compat::AllowStd, WebSocketStream};
    use std::io::{Read, Write};
    #[cfg(feature = "connect")]
    use tokio::io::{AsyncReadExt, AsyncWriteExt};

    fn is_read<T: Read>() {}
    fn is_write<T: Write>() {}
    #[cfg(feature = "connect")]
    fn is_async_read<T: AsyncReadExt>() {}
    #[cfg(feature = "connect")]
    fn is_async_write<T: AsyncWriteExt>() {}
    fn is_unpin<T: Unpin>() {}

    #[test]
    fn web_socket_stream_has_traits() {
        is_read::<AllowStd<tokio::net::TcpStream>>();
        is_write::<AllowStd<tokio::net::TcpStream>>();

        #[cfg(feature = "connect")]
        is_async_read::<MaybeTlsStream<tokio::net::TcpStream>>();
        #[cfg(feature = "connect")]
        is_async_write::<MaybeTlsStream<tokio::net::TcpStream>>();

        is_unpin::<WebSocketStream<tokio::net::TcpStream>>();
        #[cfg(feature = "connect")]
        is_unpin::<WebSocketStream<MaybeTlsStream<tokio::net::TcpStream>>>();
    }
}
<commit_msg>Fix typo in comment<commit_after>//! Async WebSocket usage.
//!
//! This library is an implementation of WebSocket handshakes and streams. It
//! is based on the crate which implements all required WebSocket protocol
//! logic. So this crate basically just brings tokio support / tokio integration
//! to it.
//!
//! Each WebSocket stream implements the required `Stream` and `Sink` traits,
//! so the socket is just a stream of messages coming in and going out.

#![deny(missing_docs, unused_must_use, unused_mut, unused_imports, unused_import_braces)]

pub use tungstenite;

mod compat;
#[cfg(feature = "connect")]
mod connect;
mod handshake;
#[cfg(feature = "stream")]
mod stream;
#[cfg(any(feature = "native-tls", feature = "__rustls-tls", feature = "connect"))]
mod tls;

use std::io::{Read, Write};

use compat::{cvt, AllowStd, ContextWaker};
use futures_util::{
    sink::{Sink, SinkExt},
    stream::Stream,
};
use log::*;
use std::{
    pin::Pin,
    task::{Context, Poll},
};
use tokio::io::{AsyncRead, AsyncWrite};

use tungstenite::{
    client::IntoClientRequest,
    error::Error as WsError,
    handshake::{
        client::{ClientHandshake, Response},
        server::{Callback, NoCallback},
        HandshakeError,
    },
    protocol::{Message, Role, WebSocket, WebSocketConfig},
};

#[cfg(any(feature = "native-tls", feature = "__rustls-tls", feature = "connect"))]
pub use tls::Connector;
#[cfg(any(feature = "native-tls", feature = "__rustls-tls"))]
pub use tls::{client_async_tls, client_async_tls_with_config};

#[cfg(feature = "connect")]
pub use connect::{connect_async, connect_async_with_config};

#[cfg(all(any(feature = "native-tls", feature = "__rustls-tls"), feature = "connect"))]
pub use connect::connect_async_tls_with_config;

#[cfg(feature = "stream")]
pub use stream::MaybeTlsStream;

use tungstenite::protocol::CloseFrame;

/// Creates a WebSocket handshake from a request and a stream.
/// For convenience, the user may call this with a url string, a URL,
/// or a `Request`. Calling with `Request` allows the user to add
/// a WebSocket protocol or other custom headers.
///
/// Internally, this custom creates a handshake representation and returns
/// a future representing the resolution of the WebSocket handshake. The
/// returned future will resolve to either `WebSocketStream<S>` or `Error`
/// depending on whether the handshake is successful.
///
/// This is typically used for clients who have already established, for
/// example, a TCP connection to the remote server.
pub async fn client_async<'a, R, S>(
    request: R,
    stream: S,
) -> Result<(WebSocketStream<S>, Response), WsError>
where
    R: IntoClientRequest + Unpin,
    S: AsyncRead + AsyncWrite + Unpin,
{
    client_async_with_config(request, stream, None).await
}

/// The same as `client_async()` but the one can specify a websocket configuration.
/// Please refer to `client_async()` for more details.
pub async fn client_async_with_config<'a, R, S>(
    request: R,
    stream: S,
    config: Option<WebSocketConfig>,
) -> Result<(WebSocketStream<S>, Response), WsError>
where
    R: IntoClientRequest + Unpin,
    S: AsyncRead + AsyncWrite + Unpin,
{
    let f = handshake::client_handshake(stream, move |allow_std| {
        let request = request.into_client_request()?;
        let cli_handshake = ClientHandshake::start(allow_std, request, config)?;
        cli_handshake.handshake()
    });
    f.await.map_err(|e| match e {
        HandshakeError::Failure(e) => e,
        e => WsError::Io(std::io::Error::new(std::io::ErrorKind::Other, e.to_string())),
    })
}

/// Accepts a new WebSocket connection with the provided stream.
///
/// This function will internally call `server::accept` to create a
/// handshake representation and returns a future representing the
/// resolution of the WebSocket handshake. The returned future will resolve
/// to either `WebSocketStream<S>` or `Error` depending if it's successful
/// or not.
///
/// This is typically used after a socket has been accepted from a
/// `TcpListener`. That socket is then passed to this function to perform
/// the server half of the accepting a client's websocket connection.
pub async fn accept_async<S>(stream: S) -> Result<WebSocketStream<S>, WsError>
where
    S: AsyncRead + AsyncWrite + Unpin,
{
    accept_hdr_async(stream, NoCallback).await
}

/// The same as `accept_async()` but the one can specify a websocket configuration.
/// Please refer to `accept_async()` for more details.
pub async fn accept_async_with_config<S>(
    stream: S,
    config: Option<WebSocketConfig>,
) -> Result<WebSocketStream<S>, WsError>
where
    S: AsyncRead + AsyncWrite + Unpin,
{
    accept_hdr_async_with_config(stream, NoCallback, config).await
}

/// Accepts a new WebSocket connection with the provided stream.
///
/// This function does the same as `accept_async()` but accepts an extra callback
/// for header processing. The callback receives headers of the incoming
/// requests and is able to add extra headers to the reply.
pub async fn accept_hdr_async<S, C>(stream: S, callback: C) -> Result<WebSocketStream<S>, WsError>
where
    S: AsyncRead + AsyncWrite + Unpin,
    C: Callback + Unpin,
{
    accept_hdr_async_with_config(stream, callback, None).await
}

/// The same as `accept_hdr_async()` but the one can specify a websocket configuration.
/// Please refer to `accept_hdr_async()` for more details.
pub async fn accept_hdr_async_with_config<S, C>(
    stream: S,
    callback: C,
    config: Option<WebSocketConfig>,
) -> Result<WebSocketStream<S>, WsError>
where
    S: AsyncRead + AsyncWrite + Unpin,
    C: Callback + Unpin,
{
    let f = handshake::server_handshake(stream, move |allow_std| {
        tungstenite::accept_hdr_with_config(allow_std, callback, config)
    });
    f.await.map_err(|e| match e {
        HandshakeError::Failure(e) => e,
        e => WsError::Io(std::io::Error::new(std::io::ErrorKind::Other, e.to_string())),
    })
}

/// A wrapper around an underlying raw stream which implements the WebSocket
/// protocol.
///
/// A `WebSocketStream<S>` represents a handshake that has been completed
/// successfully and both the server and the client are ready for receiving
/// and sending data. Message from a `WebSocketStream<S>` are accessible
/// through the respective `Stream` and `Sink`. Check more information about
/// them in `futures-rs` crate documentation or have a look on the examples
/// and unit tests for this crate.
#[derive(Debug)]
pub struct WebSocketStream<S> {
    inner: WebSocket<AllowStd<S>>,
    closing: bool,
}

impl<S> WebSocketStream<S> {
    /// Convert a raw socket into a WebSocketStream without performing a
    /// handshake.
    pub async fn from_raw_socket(stream: S, role: Role, config: Option<WebSocketConfig>) -> Self
    where
        S: AsyncRead + AsyncWrite + Unpin,
    {
        handshake::without_handshake(stream, move |allow_std| {
            WebSocket::from_raw_socket(allow_std, role, config)
        })
        .await
    }

    /// Convert a raw socket into a WebSocketStream without performing a
    /// handshake.
    pub async fn from_partially_read(
        stream: S,
        part: Vec<u8>,
        role: Role,
        config: Option<WebSocketConfig>,
    ) -> Self
    where
        S: AsyncRead + AsyncWrite + Unpin,
    {
        handshake::without_handshake(stream, move |allow_std| {
            WebSocket::from_partially_read(allow_std, part, role, config)
        })
        .await
    }

    pub(crate) fn new(ws: WebSocket<AllowStd<S>>) -> Self {
        WebSocketStream { inner: ws, closing: false }
    }

    fn with_context<F, R>(&mut self, ctx: Option<(ContextWaker, &mut Context<'_>)>, f: F) -> R
    where
        S: Unpin,
        F: FnOnce(&mut WebSocket<AllowStd<S>>) -> R,
        AllowStd<S>: Read + Write,
    {
        trace!("{}:{} WebSocketStream.with_context", file!(), line!());
        if let Some((kind, ctx)) = ctx {
            self.inner.get_mut().set_waker(kind, ctx.waker());
        }
        f(&mut self.inner)
    }

    /// Returns a shared reference to the inner stream.
    pub fn get_ref(&self) -> &S
    where
        S: AsyncRead + AsyncWrite + Unpin,
    {
        self.inner.get_ref().get_ref()
    }

    /// Returns a mutable reference to the inner stream.
    pub fn get_mut(&mut self) -> &mut S
    where
        S: AsyncRead + AsyncWrite + Unpin,
    {
        self.inner.get_mut().get_mut()
    }

    /// Returns a reference to the configuration of the tungstenite stream.
    pub fn get_config(&self) -> &WebSocketConfig {
        self.inner.get_config()
    }

    /// Close the underlying web socket
    pub async fn close(&mut self, msg: Option<CloseFrame<'_>>) -> Result<(), WsError>
    where
        S: AsyncRead + AsyncWrite + Unpin,
    {
        let msg = msg.map(|msg| msg.into_owned());
        self.send(Message::Close(msg)).await
    }
}

impl<T> Stream for WebSocketStream<T>
where
    T: AsyncRead + AsyncWrite + Unpin,
{
    type Item = Result<Message, WsError>;

    fn poll_next(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
        trace!("{}:{} Stream.poll_next", file!(), line!());
        match futures_util::ready!(self.with_context(Some((ContextWaker::Read, cx)), |s| {
            trace!("{}:{} Stream.with_context poll_next -> read_message()", file!(), line!());
            cvt(s.read_message())
        })) {
            Ok(v) => Poll::Ready(Some(Ok(v))),
            Err(WsError::AlreadyClosed) | Err(WsError::ConnectionClosed) => Poll::Ready(None),
            Err(e) => Poll::Ready(Some(Err(e))),
        }
    }
}

impl<T> Sink<Message> for WebSocketStream<T>
where
    T: AsyncRead + AsyncWrite + Unpin,
{
    type Error = WsError;

    fn poll_ready(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
        (*self).with_context(Some((ContextWaker::Write, cx)), |s| cvt(s.write_pending()))
    }

    fn start_send(mut self: Pin<&mut Self>, item: Message) -> Result<(), Self::Error> {
        match (*self).with_context(None, |s| s.write_message(item)) {
            Ok(()) => Ok(()),
            Err(::tungstenite::Error::Io(err)) if err.kind() == std::io::ErrorKind::WouldBlock => {
                // the message was accepted and queued
                // isn't an error.
                Ok(())
            }
            Err(e) => {
                debug!("websocket start_send error: {}", e);
                Err(e)
            }
        }
    }

    fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
        (*self).with_context(Some((ContextWaker::Write, cx)), |s| cvt(s.write_pending()))
    }

    fn poll_close(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
        if self.closing {
            // After queueing it, we call `write_pending` to drive the close handshake to completion.
            match (*self).with_context(Some((ContextWaker::Write, cx)), |s| s.write_pending()) {
                Ok(()) => Poll::Ready(Ok(())),
                Err(::tungstenite::Error::ConnectionClosed) => Poll::Ready(Ok(())),
                Err(::tungstenite::Error::Io(err))
                    if err.kind() == std::io::ErrorKind::WouldBlock =>
                {
                    trace!("WouldBlock");
                    Poll::Pending
                }
                Err(err) => Poll::Ready(Err(err)),
            }
        } else {
            match (*self).with_context(Some((ContextWaker::Write, cx)), |s| s.close(None)) {
                Ok(()) => Poll::Ready(Ok(())),
                Err(::tungstenite::Error::ConnectionClosed) => Poll::Ready(Ok(())),
                Err(::tungstenite::Error::Io(err))
                    if err.kind() == std::io::ErrorKind::WouldBlock =>
                {
                    trace!("WouldBlock");
                    self.closing = true;
                    Poll::Pending
                }
                Err(err) => {
                    debug!("websocket close error: {}", err);
                    Poll::Ready(Err(err))
                }
            }
        }
    }
}

/// Get a domain from an URL.
#[cfg(any(feature = "connect", feature = "native-tls", feature = "__rustls-tls"))]
#[inline]
fn domain(request: &tungstenite::handshake::client::Request) -> Result<String, WsError> {
    match request.uri().host() {
        Some(d) => Ok(d.to_string()),
        None => Err(WsError::Url(tungstenite::error::UrlError::NoHostName)),
    }
}

#[cfg(test)]
mod tests {
    #[cfg(feature = "connect")]
    use crate::stream::MaybeTlsStream;
    use crate::{compat::AllowStd, WebSocketStream};
    use std::io::{Read, Write};
    #[cfg(feature = "connect")]
    use tokio::io::{AsyncReadExt, AsyncWriteExt};

    fn is_read<T: Read>() {}
    fn is_write<T: Write>() {}
    #[cfg(feature = "connect")]
    fn is_async_read<T: AsyncReadExt>() {}
    #[cfg(feature = "connect")]
    fn is_async_write<T: AsyncWriteExt>() {}
    fn is_unpin<T: Unpin>() {}

    #[test]
    fn web_socket_stream_has_traits() {
        is_read::<AllowStd<tokio::net::TcpStream>>();
        is_write::<AllowStd<tokio::net::TcpStream>>();

        #[cfg(feature = "connect")]
        is_async_read::<MaybeTlsStream<tokio::net::TcpStream>>();
        #[cfg(feature = "connect")]
        is_async_write::<MaybeTlsStream<tokio::net::TcpStream>>();

        is_unpin::<WebSocketStream<tokio::net::TcpStream>>();
        #[cfg(feature = "connect")]
        is_unpin::<WebSocketStream<MaybeTlsStream<tokio::net::TcpStream>>>();
    }
}
<|endoftext|>


<commit_before>pub fn run() {
    iterate();
}

// Iterators in rust are lazy, i.e. they no effect until we call methods on them.
fn iterate() {
    let v1:Vec<i32> = vec![1,2,3];
    let v1_iter = v1.iter();
    for val in v1_iter {
        println!("Got {}", val);
    }
}

// Iterators have to implement the Iterator trait defined in the standard library.
/*
trait Iterator {
    type Item;
    // self is borrowed mutably becausing calling 'next' on an iterator changes the iterator's
    // state.
    fn next(&mut self) -> Option<Self::Item>;
    // methods with default implementation...
}
*/

#[test]
fn iterator_demo() {
    let v1:Vec<i32> = vec![1,2,3];
    // This was not required in the for loop because for takes ownership of the iterator and
    // mutates it behind the scenes.
    let mut v1_iter = v1.iter();
    // iter() returns iterator over immutable references. into_iter() creates an iterator that
    // takes ownership of the v1 and returns owned values. iter_mut() iterates over mutable
    // references.
    assert_eq!(v1_iter.next(), Some(&1));
    assert_eq!(v1_iter.next(), Some(&2));
    assert_eq!(v1_iter.next(), Some(&3));
    assert_eq!(v1_iter.next(), None);
}

#[test]
// Consuming adaptors.
fn iterator_sum() {
    let v1 = vec![1, 2, 3];
    let v1_iter = v1.iter();
    // The sum method on an iterator is a "consuming adaptor", because it takes ownership of the
    // adaptor itself.
    let total: i32 = v1_iter.sum();
    // We are not allowed to use v1_iter after this.
    assert_eq!(total, 6);
}

// Iterator adaptors. allow us to change iterators into different kind of iterators. We can chain
// multiple calls to iterator adaptors. Because all iterators are lazy, however, we have to call one
// of the consuming adaptor methods in order to get results from calls to iterator adaptors.
#[test]
fn map_sum() {
    let v1 = vec![1,2,3];
    // doesn't really do anything and produces a compiler warning.
    v1.iter().map(|x| x + 1);
    // consuming values: Collect consumes an iterator into a collection specified by the type of
    // LHS.
    let v2: Vec<i32> = v1.iter().map(|x| x + 1).collect();
    assert_eq!(v2, vec![2,3,4]);
}

// Custom iterator which counts from 1 to 5.
struct Counter {
    count: u32,
}

impl Counter {
    fn new() -> Counter {
        Counter { count: 0 }
    }
}

impl Iterator for Counter {
    type Item = u32;

    fn next(&mut self) -> Option<Self::Item> {
        self.count +=1 ;
        if self.count < 6 {
            Some(self.count)
        } else {
            None
        }
    }
}

#[test]
fn calling_next_directly() {
    let mut counter = Counter::new();
    assert_eq!(counter.next(), Some(1));
    assert_eq!(counter.next(), Some(2));
    assert_eq!(counter.next(), Some(3));
    assert_eq!(counter.next(), Some(4));
    assert_eq!(counter.next(), Some(5));
    assert_eq!(counter.next(), None);
}

// Now that we have an iterator for Counter, we can use other iterator methods, such as skip() or
// zip on it.
#[test]
fn using_other_iterator_trait_methods() {
    let sum: u32 = Counter::new().zip(Counter::new().skip(1))
                                 .map(|(a, b)| a * b)
                                 .filter(|x| x % 3 == 0)
                                 .sum();
    assert_eq!(18, sum);
}

#[derive(PartialEq, Debug)]
struct Shoe {
    size: i32,
    style: String,
}

fn shoes_in_my_size(shoes: Vec<Shoe>, shoe_size: i32) -> Vec<Shoe> {
    shoes.into_iter()
        .filter(|s| s.size == shoe_size)
        .collect()
}

#[test]
fn filters_by_size() {
    let shoes = vec![
        Shoe { size: 10, style: String::from("sneaker") },
        Shoe { size: 13, style: String::from("sandal") },
        Shoe { size: 10, style: String::from("boot") },
    ];

    let in_my_size = shoes_in_my_size(shoes, 10);

    assert_eq!(
        in_my_size,
        vec![
            Shoe { size: 10, style: String::from("sneaker") },
            Shoe { size: 10, style: String::from("boot") },
        ]
    );
}
<commit_msg>Remove duplicated code<commit_after>pub fn run() {
    iterate();
}

// Iterators in rust are lazy, i.e. they no effect until we call methods on them.
fn iterate() {
    let v1:Vec<i32> = vec![1,2,3];
    let v1_iter = v1.iter();
    for val in v1_iter {
        println!("Got {}", val);
    }
}

// Iterators have to implement the Iterator trait defined in the standard library.
/*
trait Iterator {
    type Item;
    // self is borrowed mutably becausing calling 'next' on an iterator changes the iterator's
    // state.
    fn next(&mut self) -> Option<Self::Item>;
    // methods with default implementation...
}
*/

#[test]
fn iterator_demo() {
    let v1:Vec<i32> = vec![1,2,3];
    // This was not required in the for loop because for takes ownership of the iterator and
    // mutates it behind the scenes.
    let mut v1_iter = v1.iter();
    // iter() returns iterator over immutable references. into_iter() creates an iterator that
    // takes ownership of the v1 and returns owned values. iter_mut() iterates over mutable
    // references.
    assert_eq!(v1_iter.next(), Some(&1));
    assert_eq!(v1_iter.next(), Some(&2));
    assert_eq!(v1_iter.next(), Some(&3));
    assert_eq!(v1_iter.next(), None);
}

#[test]
// Consuming adaptors.
fn iterator_sum() {
    let v1 = vec![1, 2, 3];
    let v1_iter = v1.iter();
    // The sum method on an iterator is a "consuming adaptor", because it takes ownership of the
    // adaptor itself.
    let total: i32 = v1_iter.sum();
    // We are not allowed to use v1_iter after this.
    assert_eq!(total, 6);
}

// Iterator adaptors. allow us to change iterators into different kind of iterators. We can chain
// multiple calls to iterator adaptors. Because all iterators are lazy, however, we have to call one
// of the consuming adaptor methods in order to get results from calls to iterator adaptors.
#[test]
fn map_sum() {
    let v1 = vec![1,2,3];
    // doesn't really do anything and produces a compiler warning.
    v1.iter().map(|x| x + 1);
    // consuming values: Collect consumes an iterator into a collection specified by the type of
    // LHS.
    let v2: Vec<i32> = v1.iter().map(|x| x + 1).collect();
    assert_eq!(v2, vec![2,3,4]);
}

// Custom iterator which counts from 1 to 5.
struct Counter {
    count: u32,
}

impl Counter {
    fn new() -> Counter {
        Counter { count: 0 }
    }
}

impl Iterator for Counter {
    type Item = u32;

    fn next(&mut self) -> Option<Self::Item> {
        self.count +=1 ;
        if self.count < 6 {
            Some(self.count)
        } else {
            None
        }
    }
}

#[test]
fn calling_next_directly() {
    let mut counter = Counter::new();
    assert_eq!(counter.next(), Some(1));
    assert_eq!(counter.next(), Some(2));
    assert_eq!(counter.next(), Some(3));
    assert_eq!(counter.next(), Some(4));
    assert_eq!(counter.next(), Some(5));
    assert_eq!(counter.next(), None);
}

// Now that we have an iterator for Counter, we can use other iterator methods, such as skip() or
// zip on it.
#[test]
fn using_other_iterator_trait_methods() {
    let sum: u32 = Counter::new().zip(Counter::new().skip(1))
                                 .map(|(a, b)| a * b)
                                 .filter(|x| x % 3 == 0)
                                 .sum();
    assert_eq!(18, sum);
}
<|endoftext|>


<commit_before>#![allow(dead_code)]

use std::cell::RefCell;

thread_local!(static EVENT_LOOP: Option<RefCell<EventLoop>> = None);

fn with_current_event_loop<F, R>(f: F) -> R
    where F: FnOnce(&RefCell<EventLoop>) -> R {
        EVENT_LOOP.with(|maybe_event_loop| {
            match maybe_event_loop {
                &None => panic!("current thread has no event loop"),
                &Some(ref event_loop) => f(event_loop),
            }
        })
    }

pub type Error = Box<::std::error::Error>;
pub type Result<T> = ::std::result::Result<T, Error>;

pub struct Promise<T> {
    phantom_data : ::std::marker::PhantomData<T>,
    pub node : Box<PromiseNode>,
}

impl <T> Promise <T> {
    pub fn then<F, G, R>(self, _func: F, _error_handler: G) -> Promise<R>
        where F: FnOnce(T) -> Result<R> {
            unimplemented!()
        }

    pub fn wait(self) -> Result<T> {
        unimplemented!()
    }
}

pub trait Event {
    fn fire(&mut self);
}

pub trait PromiseNode {
    /// Arms the given event when ready.
    fn on_ready(&mut self, event : Box<Event>);

    fn set_self_pointer(&mut self) {}
    fn get(&self);
}

/// A PromiseNode that transforms the result of another PromiseNode through an application-provided
/// function (implements `then()`).
pub struct TransformPromiseNode {
    dependency: Box<PromiseNode>,
}

/// A promise that has already been resolved to an immediate value or error.
pub struct ImmediatePromiseNode<T> {
    result: Result<T>,
}

impl <T> PromiseNode for ImmediatePromiseNode<T> {

    /// Arms the event then the promise is ready.
    fn on_ready(&mut self, event: Box<Event>) {
        with_current_event_loop(|event_loop| {
            event_loop.borrow_mut().arm_breadth_first(event);
        });
    }
    fn get(&self) {

    }
}

trait ErrorHandler {
    fn task_failed(error: Error);
}

struct TaskSetImpl {
    error_handler: Box<ErrorHandler>,
}

/// A Deque with an insertion point in the middle.
struct InsertDeque<T> {
    front: ::std::collections::VecDeque<T>,
    back: ::std::collections::VecDeque<T>,
}

/// A queue of events being executed in a loop.
pub struct EventLoop {
    daemons: TaskSetImpl,
    running: bool,
    last_runnable_state: bool,
    events: ::std::collections::VecDeque<Box<Event>>,
    depth_first_events: ::std::collections::VecDeque<Box<Event>>,
}

impl EventLoop {

    fn arm_depth_first(&mut self, event: Box<Event>) {
        self.depth_first_events.push_front(event);
    }

    fn arm_breadth_first(&mut self, event: Box<Event>) {
        self.events.push_back(event);
    }

    /// Run the even loop for `max_turn_count` turns or until there is nothing left to be done,
    /// whichever comes first. This never calls the `EventPort`'s `sleep()` or `poll()`. It will
    /// call the `EventPort`'s `set_runnable(false)` if the queue becomes empty.
    pub fn run(&mut self, max_turn_count : u32) {
        self.running = true;

        for _ in 0..max_turn_count {
            if !self.turn() {
                break;
            }
        }
    }

    fn turn(&mut self) -> bool {
        assert!(self.depth_first_events.is_empty());
        match self.events.pop_front() {
            None => return false,
            Some(mut event) => {
                // event->firing = true ?
                event.fire();
            }
        }
        while !self.depth_first_events.is_empty() {
            self.events.push_front(self.depth_first_events.pop_back().unwrap());
        }
        return true;
    }
}
<commit_msg>don't worry about code bloat for now<commit_after>#![allow(dead_code)]

use std::cell::RefCell;

thread_local!(static EVENT_LOOP: Option<RefCell<EventLoop>> = None);

fn with_current_event_loop<F, R>(f: F) -> R
    where F: FnOnce(&RefCell<EventLoop>) -> R {
        EVENT_LOOP.with(|maybe_event_loop| {
            match maybe_event_loop {
                &None => panic!("current thread has no event loop"),
                &Some(ref event_loop) => f(event_loop),
            }
        })
    }

pub type Error = Box<::std::error::Error>;
pub type Result<T> = ::std::result::Result<T, Error>;

pub struct Promise<T> {
    pub node : Box<PromiseNode<T>>,
}

impl <T> Promise <T> {
    pub fn then<F, G, R>(self, _func: F, _error_handler: G) -> Promise<R>
        where F: FnOnce(T) -> Result<R> {
            unimplemented!()
        }

    pub fn wait(self) -> Result<T> {
        unimplemented!()
    }
}

pub trait Event {
    fn fire(&mut self);
}

pub trait PromiseNode<T> {
    /// Arms the given event when the promised value is ready.
    fn on_ready(&mut self, event : Box<Event>);

    fn set_self_pointer(&mut self) {}
    fn get(self) -> Result<T>;
}

/// A PromiseNode that transforms the result of another PromiseNode through an application-provided
/// function (implements `then()`).
pub struct TransformPromiseNode<T, DepT, Func, ErrorFunc>
where Func: FnOnce(DepT) -> Result<T>, ErrorFunc: FnOnce(Error) -> Result<T> {
    dependency: Box<PromiseNode<DepT>>,
    func: Func,
    error_handler: ErrorFunc,
}

impl <T, DepT, Func, ErrorFunc> PromiseNode<T> for TransformPromiseNode<T, DepT, Func, ErrorFunc>
where Func: FnOnce(DepT) -> Result<T>, ErrorFunc: FnOnce(Error) -> Result<T> {
    fn on_ready(&mut self, event: Box<Event>) {
        self.dependency.on_ready(event);
    }
    fn get(self) -> Result<T> {
//        let dep_result = self.dependency.get();
        unimplemented!()
//        self.result
    }
}

/// A promise that has already been resolved to an immediate value or error.
pub struct ImmediatePromiseNode<T> {
    result: Result<T>,
}

impl <T> PromiseNode<T> for ImmediatePromiseNode<T> {

    fn on_ready(&mut self, event: Box<Event>) {
        with_current_event_loop(|event_loop| {
            event_loop.borrow_mut().arm_breadth_first(event);
        });
    }
    fn get(self) -> Result<T> {
        self.result
    }
}

trait ErrorHandler {
    fn task_failed(error: Error);
}

struct TaskSetImpl {
    error_handler: Box<ErrorHandler>,
}

/// A Deque with an insertion point in the middle.
struct InsertDeque<T> {
    front: ::std::collections::VecDeque<T>,
    back: ::std::collections::VecDeque<T>,
}

/// A queue of events being executed in a loop.
pub struct EventLoop {
    daemons: TaskSetImpl,
    running: bool,
    last_runnable_state: bool,
    events: ::std::collections::VecDeque<Box<Event>>,
    depth_first_events: ::std::collections::VecDeque<Box<Event>>,
}

impl EventLoop {

    fn arm_depth_first(&mut self, event: Box<Event>) {
        self.depth_first_events.push_front(event);
    }

    fn arm_breadth_first(&mut self, event: Box<Event>) {
        self.events.push_back(event);
    }

    /// Run the even loop for `max_turn_count` turns or until there is nothing left to be done,
    /// whichever comes first. This never calls the `EventPort`'s `sleep()` or `poll()`. It will
    /// call the `EventPort`'s `set_runnable(false)` if the queue becomes empty.
    pub fn run(&mut self, max_turn_count : u32) {
        self.running = true;

        for _ in 0..max_turn_count {
            if !self.turn() {
                break;
            }
        }
    }

    fn turn(&mut self) -> bool {
        assert!(self.depth_first_events.is_empty());
        match self.events.pop_front() {
            None => return false,
            Some(mut event) => {
                // event->firing = true ?
                event.fire();
            }
        }
        while !self.depth_first_events.is_empty() {
            self.events.push_front(self.depth_first_events.pop_back().unwrap());
        }
        return true;
    }
}
<|endoftext|>


<commit_before>//! Additive and multiplicative identities

#![allow(unstable)]
#![deny(missing_docs, warnings)]

/// Multiplicative identity
pub trait One {
    /// Returns one
    fn one() -> Self;
}

/// Additive identity
pub trait Zero {
    /// Returns zero
    fn zero() -> Self;
}

macro_rules! float {
    ($($ty:ty),+) => {$(
        impl One for $ty { fn one() -> $ty { 1. } }
        impl Zero for $ty { fn zero() -> $ty { 0. } })+
    }
}

float!(f32, f64);

macro_rules! int {
    ($($ty:ty),+) => {$(
        impl One for $ty { fn one() -> $ty { 1 } }
        impl Zero for $ty { fn zero() -> $ty { 0 } })+
    }
}

int!(i8, i16, i32, i64, isize, u8, u16, u32, u64, usize);
<commit_msg>refactor: fix warnings<commit_after>//! Additive and multiplicative identities

#![deny(missing_docs)]
#![deny(warnings)]

/// Multiplicative identity
pub trait One {
    /// Returns one
    fn one() -> Self;
}

/// Additive identity
pub trait Zero {
    /// Returns zero
    fn zero() -> Self;
}

macro_rules! float {
    ($($ty:ty),+) => {$(
        impl One for $ty { fn one() -> $ty { 1. } }
        impl Zero for $ty { fn zero() -> $ty { 0. } })+
    }
}

float!(f32, f64);

macro_rules! int {
    ($($ty:ty),+) => {$(
        impl One for $ty { fn one() -> $ty { 1 } }
        impl Zero for $ty { fn zero() -> $ty { 0 } })+
    }
}

int!(i8, i16, i32, i64, isize, u8, u16, u32, u64, usize);
<|endoftext|>