<commit_before>extern crate libc;
extern crate "mpfr-sys" as mpfr_sys;

use std::mem;
use std::ptr;
use std::borrow::ToOwned;
use std::str;
use std::ffi;
use std::ops::Add;

use libc::c_double;

use mpfr_sys::*;

pub use update_big_float::UpdateBigFloat;
pub use from_big_float::FromBigFloat;
pub use to_big_float::ToBigFloat;
pub use builder::{BigFloatBuilder, BigFloatBuilderWithPrec};
pub use rounding_mode::{RoundingMode, global_rounding_mode};

mod util;
mod update_big_float;
mod from_big_float;
mod to_big_float;
mod builder;
mod rounding_mode;

pub mod format;

pub mod traits {
    pub use UpdateBigFloat;
    pub use FromBigFloat;
    pub use ToBigFloat;
}

#[derive(Copy)]
pub enum Sign {
    Negative,
    Positive
}

pub struct BigFloat {
    value: __mpfr_struct
}

impl Drop for BigFloat {
    fn drop(&mut self) {
        unsafe { mpfr_clear(&mut self.value) }
    }
}

impl Clone for BigFloat {
    fn clone(&self) -> BigFloat {
        BigFloat::new().with_prec(self.prec()).from(self)
    }
}

macro_rules! generate_predicates {
    ($t:ty, $($(#[$attr:meta])* fn $method:ident -> $mpfr:ident),+) => (
        impl $t {
        $(
            $(#[$attr])*
            pub fn $method(&self) -> bool {
                unsafe {
                    $mpfr(&self.value) != 0
                }
            }
        )+
        }
    )
}

impl BigFloat {
    #[inline]
    pub fn set_default_prec(precision: uint) {
        unsafe { mpfr_set_default_prec(precision as mpfr_prec_t); }
    }

    #[inline]
    pub fn get_default_prec() -> uint {
        unsafe { mpfr_get_default_prec() as uint }
    }

    #[inline]
    pub fn new() -> BigFloatBuilder { BigFloatBuilder }

    pub fn fresh() -> BigFloat {
        BigFloat {
            value: unsafe {
                let mut value = mem::uninitialized();
                mpfr_init(&mut value);
                value
            }
        }
    }

    pub fn fresh_with_prec(precision: uint) -> BigFloat {
        BigFloat {
            value: unsafe {
                let mut value = mem::uninitialized();
                mpfr_init2(&mut value, precision as mpfr_prec_t);
                value
            }
        }
    }

    #[inline]
    pub fn set_to<T: UpdateBigFloat>(&mut self, value: T) {
        value.update_big_float(self);
    }

    #[inline]
    pub fn get<T: FromBigFloat>(&self) -> T::Target {
        FromBigFloat::from_big_float(self, None::<T>)
    }

    #[inline]
    pub fn set_to_nan(&mut self) {
        unsafe {
            mpfr_set_nan(&mut self.value);
        }
    }

    #[inline]
    pub fn set_to_inf(&mut self, sign: Sign) {
        unsafe {
            mpfr_set_inf(&mut self.value, match sign {
                Sign::Negative => -1,
                Sign::Positive =>  1
            });
        }
    }

    #[inline]
    pub fn set_to_zero(&mut self, sign: Sign) {
        unsafe {
            mpfr_set_inf(&mut self.value, match sign {
                Sign::Negative => -1,
                Sign::Positive =>  1
            });
        }
    }

    #[inline]
    pub fn swap(&mut self, other: &mut BigFloat) {
        unsafe {
             mpfr_swap(&mut self.value, &mut other.value);
        }
    }

    pub fn prec(&self) -> uint {
        unsafe {
            mpfr_get_prec(&self.value) as uint
        }
    }

    pub fn set_prec_clear(&mut self, precision: uint) {
        unsafe {
            mpfr_set_prec(&mut self.value, precision as mpfr_prec_t);
        }
    }

    pub fn set_prec_round(&mut self, precision: uint) {
        unsafe {
            mpfr_prec_round(&mut self.value,
                            precision as mpfr_prec_t,
                            global_rounding_mode::get().to_rnd_t());
        }
    }

    pub fn to_string_in_base(&self, base: uint) -> (String, u64) {
        unsafe {
            let mut exp: mpfr_exp_t = 0;
            // We're going to ask MPFR to allocate the string itself, so the maximum
            // possible precision is used
            let s = mpfr_get_str(
                ptr::null_mut(),
                &mut exp, base as libc::c_int,
                0, &self.value,
                global_rounding_mode::get().to_rnd_t()
            );

            if s.is_null() {
                panic!("Couldn't convert big float to a string");
            }

            let r = str::from_utf8(ffi::c_str_to_bytes(&(s as *const _))).unwrap().to_owned();

            mpfr_free_str(s);

            (r, exp as u64)
        }
    }
}

generate_predicates! { BigFloat,
    #[doc="Checks that this number is NaN."]
    fn is_nan     -> mpfr_nan_p,
    #[doc="Checks that this number is an infinity (positive or negative)."]
    fn is_inf     -> mpfr_inf_p,
    #[doc="Checks that this number is an ordinary number (neither NaN nor an infinity)."]
    fn is_number  -> mpfr_number_p,
    #[doc="Checks that this number is zero."]
    fn is_zero    -> mpfr_zero_p,
    #[doc="Checks that this number is a regular number (neither NaN, nor an infinity nor zero)."]
    fn is_regular -> mpfr_regular_p
}

// Implementation of arithmetic operations for BigFloat.
// Basically, all operations are implemented both for BigFloat and &BigFloat as RHS and LHS
// (4 variants total: value + value, value + reference, reference + value, reference + reference).
//
// If one of the operands is a value, then it is used to hold the result. If both of the
// operands are values, LHS gets a priority. If both of the operands are references,
// the LHS is cloned and used to hold the result.
//
// The order is important if participating values have different precisions.
//
// If one of the operands is of primitive type, then either the BigFloat operand will
// be reused for the result or it will be cloned.

// x + &y
impl<'a> Add<&'a BigFloat> for BigFloat {
    type Output = BigFloat;

    fn add(mut self, rhs: &'a BigFloat) -> BigFloat {
        unsafe {
            mpfr_add(
                &mut self.value,
                &self.value, &rhs.value,
                global_rounding_mode::get().to_rnd_t()
            );
        }
        self
    }
}

// x + y
impl Add<BigFloat> for BigFloat {
    type Output = BigFloat;

    #[inline]
    fn add(self, rhs: BigFloat) -> BigFloat {
        self + &rhs
    }
}

// &x + y
impl<'r> Add<BigFloat> for &'r BigFloat {
    type Output = BigFloat;

    #[inline]
    fn add(self, rhs: BigFloat) -> BigFloat {
        rhs + self
    }
}

// &x + &y
impl<'a, 'r> Add<&'a BigFloat> for &'r BigFloat {
    type Output = BigFloat;

    #[inline]
    fn add(self, rhs: &'a BigFloat) -> BigFloat {
        let c = self.clone();
        c + rhs
    }
}

// x + f
impl Add<f64> for BigFloat {
    type Output = BigFloat;

    fn add(mut self, rhs: f64) -> BigFloat {
        unsafe {
            mpfr_add_d(
                &mut self.value,
                &self.value, rhs as c_double,
                global_rounding_mode::get().to_rnd_t()
            );
        }
        self
    }
}

// &x + f
impl<'r> Add<f64> for &'r BigFloat {
    type Output = BigFloat;

    #[inline]
    fn add(self, rhs: f64) -> BigFloat {
        let r = self.clone();
        r + rhs
    }
}

/*
// f + x
impl Add<BigFloat> for f64 {
    type Output = BigFloat;

    #[inline]
    fn add(self, rhs: BigFloat) -> BigFloat {
        rhs + self
    }
}

// f + &x
impl<'r> Add<&'r BigFloat> for f64 {
    type Output = BigFloat;

    #[inline]
    fn add(self, rhs: &'r BigFloat) -> BigFloat {
        rhs + self
    }
}
*/
<commit_msg>Started using macros for operations<commit_after>extern crate libc;
extern crate "mpfr-sys" as mpfr_sys;

use std::mem;
use std::ptr;
use std::borrow::ToOwned;
use std::str;
use std::ffi;
use std::ops::{Add, Mul};

use libc::c_double;

use mpfr_sys::*;

pub use update_big_float::UpdateBigFloat;
pub use from_big_float::FromBigFloat;
pub use to_big_float::ToBigFloat;
pub use builder::{BigFloatBuilder, BigFloatBuilderWithPrec};
pub use rounding_mode::{RoundingMode, global_rounding_mode};

mod util;
mod update_big_float;
mod from_big_float;
mod to_big_float;
mod builder;
mod rounding_mode;

pub mod format;

pub mod traits {
    pub use UpdateBigFloat;
    pub use FromBigFloat;
    pub use ToBigFloat;
}

#[derive(Copy)]
pub enum Sign {
    Negative,
    Positive
}

pub struct BigFloat {
    value: __mpfr_struct
}

impl Drop for BigFloat {
    fn drop(&mut self) {
        unsafe { mpfr_clear(&mut self.value) }
    }
}

impl Clone for BigFloat {
    fn clone(&self) -> BigFloat {
        BigFloat::new().with_prec(self.prec()).from(self)
    }
}

macro_rules! generate_predicates {
    ($t:ty, $($(#[$attr:meta])* fn $method:ident -> $mpfr:ident),+) => (
        impl $t {
        $(
            $(#[$attr])*
            pub fn $method(&self) -> bool {
                unsafe {
                    $mpfr(&self.value) != 0
                }
            }
        )+
        }
    )
}

impl BigFloat {
    #[inline]
    pub fn set_default_prec(precision: uint) {
        unsafe { mpfr_set_default_prec(precision as mpfr_prec_t); }
    }

    #[inline]
    pub fn get_default_prec() -> uint {
        unsafe { mpfr_get_default_prec() as uint }
    }

    #[inline]
    pub fn new() -> BigFloatBuilder { BigFloatBuilder }

    pub fn fresh() -> BigFloat {
        BigFloat {
            value: unsafe {
                let mut value = mem::uninitialized();
                mpfr_init(&mut value);
                value
            }
        }
    }

    pub fn fresh_with_prec(precision: uint) -> BigFloat {
        BigFloat {
            value: unsafe {
                let mut value = mem::uninitialized();
                mpfr_init2(&mut value, precision as mpfr_prec_t);
                value
            }
        }
    }

    #[inline]
    pub fn set_to<T: UpdateBigFloat>(&mut self, value: T) {
        value.update_big_float(self);
    }

    #[inline]
    pub fn get<T: FromBigFloat>(&self) -> T::Target {
        FromBigFloat::from_big_float(self, None::<T>)
    }

    #[inline]
    pub fn set_to_nan(&mut self) {
        unsafe {
            mpfr_set_nan(&mut self.value);
        }
    }

    #[inline]
    pub fn set_to_inf(&mut self, sign: Sign) {
        unsafe {
            mpfr_set_inf(&mut self.value, match sign {
                Sign::Negative => -1,
                Sign::Positive =>  1
            });
        }
    }

    #[inline]
    pub fn set_to_zero(&mut self, sign: Sign) {
        unsafe {
            mpfr_set_inf(&mut self.value, match sign {
                Sign::Negative => -1,
                Sign::Positive =>  1
            });
        }
    }

    #[inline]
    pub fn swap(&mut self, other: &mut BigFloat) {
        unsafe {
             mpfr_swap(&mut self.value, &mut other.value);
        }
    }

    pub fn prec(&self) -> uint {
        unsafe {
            mpfr_get_prec(&self.value) as uint
        }
    }

    pub fn set_prec_clear(&mut self, precision: uint) {
        unsafe {
            mpfr_set_prec(&mut self.value, precision as mpfr_prec_t);
        }
    }

    pub fn set_prec_round(&mut self, precision: uint) {
        unsafe {
            mpfr_prec_round(&mut self.value,
                            precision as mpfr_prec_t,
                            global_rounding_mode::get().to_rnd_t());
        }
    }

    pub fn to_string_in_base(&self, base: uint) -> (String, u64) {
        unsafe {
            let mut exp: mpfr_exp_t = 0;
            // We're going to ask MPFR to allocate the string itself, so the maximum
            // possible precision is used
            let s = mpfr_get_str(
                ptr::null_mut(),
                &mut exp, base as libc::c_int,
                0, &self.value,
                global_rounding_mode::get().to_rnd_t()
            );

            if s.is_null() {
                panic!("Couldn't convert big float to a string");
            }

            let r = str::from_utf8(ffi::c_str_to_bytes(&(s as *const _))).unwrap().to_owned();

            mpfr_free_str(s);

            (r, exp as u64)
        }
    }
}

generate_predicates! { BigFloat,
    #[doc="Checks that this number is NaN."]
    fn is_nan     -> mpfr_nan_p,
    #[doc="Checks that this number is an infinity (positive or negative)."]
    fn is_inf     -> mpfr_inf_p,
    #[doc="Checks that this number is an ordinary number (neither NaN nor an infinity)."]
    fn is_number  -> mpfr_number_p,
    #[doc="Checks that this number is zero."]
    fn is_zero    -> mpfr_zero_p,
    #[doc="Checks that this number is a regular number (neither NaN, nor an infinity nor zero)."]
    fn is_regular -> mpfr_regular_p
}

// Implementation of arithmetic operations for BigFloat.
// Basically, all operations are implemented both for BigFloat and &BigFloat as RHS and LHS
// (4 variants total: value + value, value + reference, reference + value, reference + reference).
//
// If one of the operands is a value, then it is used to hold the result. If both of the
// operands are values, LHS gets a priority. If both of the operands are references,
// the LHS is cloned and used to hold the result.
//
// The order is important if participating values have different precisions.
//
// If one of the operands is of primitive type, then either the BigFloat operand will
// be reused for the result or it will be cloned.

macro_rules! impl_commutative_op_val_ref {
    ($tr:ident, $meth:ident, $mpfr:ident) => {
        impl<'a> $tr<&'a BigFloat> for BigFloat {
            type Output = BigFloat;

            fn $meth(mut self, rhs: &'a BigFloat) -> BigFloat {
                unsafe {
                    $mpfr(
                        &mut self.value,
                        &self.value, &rhs.value,
                        global_rounding_mode::get().to_rnd_t()
                    );
                }
                self
            }
        }
    }
}

macro_rules! impl_commutative_op_val_val {
    ($tr:ident, $meth:ident) => {
        impl $tr<BigFloat> for BigFloat {
            type Output = BigFloat;

            #[inline]
            fn $meth(self, rhs: BigFloat) -> BigFloat {
                self.$meth(&rhs)
            }
        }
    }
}

macro_rules! impl_commutative_op_ref_val {
    ($tr:ident, $meth:ident) => {
        impl<'r> $tr<BigFloat> for &'r BigFloat {
            type Output = BigFloat;

            #[inline]
            fn $meth(self, rhs: BigFloat) -> BigFloat {
                rhs.$meth(self)
            }
        }
    }
}

macro_rules! impl_commutative_op_ref_ref {
    ($tr:ident, $meth:ident) => {
        impl<'a, 'r> $tr<&'a BigFloat> for &'r BigFloat {
            type Output = BigFloat;

            #[inline]
            fn $meth(self, rhs: &'a BigFloat) -> BigFloat {
                let c = self.clone();
                c.$meth(rhs)
            }
        }
    }
}

macro_rules! impl_commutative_op {
    ($tr:ident, $meth:ident, $mpfr:ident) => {
        impl_commutative_op_val_ref! { $tr, $meth, $mpfr }
        impl_commutative_op_val_val! { $tr, $meth }
        impl_commutative_op_ref_val! { $tr, $meth }
        impl_commutative_op_ref_ref! { $tr, $meth }
    }
}

// Addition

impl_commutative_op! { Add, add, mpfr_add }

// x + f
impl Add<f64> for BigFloat {
    type Output = BigFloat;

    fn add(mut self, rhs: f64) -> BigFloat {
        unsafe {
            mpfr_add_d(
                &mut self.value,
                &self.value, rhs as c_double,
                global_rounding_mode::get().to_rnd_t()
            );
        }
        self
    }
}

// &x + f
impl<'r> Add<f64> for &'r BigFloat {
    type Output = BigFloat;

    #[inline]
    fn add(self, rhs: f64) -> BigFloat {
        let r = self.clone();
        r + rhs
    }
}

/*
// f + x
impl Add<BigFloat> for f64 {
    type Output = BigFloat;

    #[inline]
    fn add(self, rhs: BigFloat) -> BigFloat {
        rhs + self
    }
}

// f + &x
impl<'r> Add<&'r BigFloat> for f64 {
    type Output = BigFloat;

    #[inline]
    fn add(self, rhs: &'r BigFloat) -> BigFloat {
        rhs + self
    }
}
*/

// Multiplication

impl_commutative_op! { Mul, mul, mpfr_mul }
<|endoftext|>


<commit_before>pub mod rocksdb {
    extern crate libc;

    mod ffi {
        extern crate libc;

        pub enum Db {}
        pub enum Options {}

        #[link(name = "rocksdb")]
        extern "C" {
            pub fn rocksdb_options_create() -> *mut Options;
            pub fn rocksdb_options_destroy(ptr: *mut Options);

            pub fn rocksdb_options_increase_parallelism(
                opt: *mut Options, total_threads: libc::c_int);
            pub fn rocksdb_options_optimize_for_point_lookup(
                opt: *mut Options, block_cache_size_mb: libc::uint64_t);
            pub fn rocksdb_options_optimize_level_style_compaction(
                opt: *mut Options, memtable_memory_budget: libc::uint64_t);
            pub fn rocksdb_options_optimize_universal_style_compaction(
                opt: *mut Options, memtable_memory_budget: libc::uint64_t);
            // pub fn rocksdb_options_set_compaction_filter(
            //     opt: *mut Options,
            //     rocksdb_compactionfilter_t*);
            // pub fn rocksdb_options_set_compaction_filter_factory(
            //     opt: *mut Options, rocksdb_compactionfilterfactory_t*);
            // pub fn rocksdb_options_set_compaction_filter_factory_v2(
            //     opt: *mut Options,
            //     rocksdb_compactionfilterfactoryv2_t*);
            // pub fn rocksdb_options_set_comparator(
            //     opt: *mut Options,
            //     rocksdb_comparator_t*);
            // pub fn rocksdb_options_set_merge_operator(
            //     opt: *mut Options,
            //     rocksdb_mergeoperator_t*);
            pub fn rocksdb_options_set_compression_per_level(
                opt: *mut Options,
                level_values: *const libc::c_int,
                num_levels: libc::size_t);
            pub fn rocksdb_options_set_create_if_missing(
                opt: *mut Options, flag: libc::uint8_t);
            pub fn rocksdb_options_set_create_missing_column_families(
                opt: *mut Options, flag: libc::uint8_t);
            pub fn rocksdb_options_set_error_if_exists(
                opt: *mut Options, flag: libc::uint8_t);
            pub fn rocksdb_options_set_paranoid_checks(
                opt: *mut Options, flag: libc::uint8_t);

            pub fn rocksdb_open(
                options: *const Options,
                name: *const libc::c_char,
                errptr: *mut *mut libc::c_char)
                -> *mut Db;
            pub fn rocksdb_close(db: *mut Db);
        }
    }

    pub struct Options {
        ptr: *mut ffi::Options,
    }

    impl Options {

        pub fn new() -> Options {
            Options {
                ptr: unsafe { ffi::rocksdb_options_create() }
            }
        }

        pub fn increase_parallelism(&mut self, total_threads: int) {
            unsafe {
                ffi::rocksdb_options_increase_parallelism(
                    self.ptr, total_threads as libc::c_int)
            }
        }

        pub fn optimize_for_point_lookup(&mut self, block_cache_size_mb: u64) {
            unsafe {
                ffi::rocksdb_options_optimize_for_point_lookup(
                    self.ptr, block_cache_size_mb as libc::uint64_t);
            }
        }

        pub fn optimize_level_style_compaction(&mut self, memtable_memory_budget: u64) {
            unsafe {
                ffi::rocksdb_options_optimize_level_style_compaction(
                    self.ptr, memtable_memory_budget as libc::uint64_t);
            }
        }

        pub fn optimize_universal_style_compaction(&mut self, memtable_memory_budget: u64) {
            unsafe {
                ffi::rocksdb_options_optimize_universal_style_compaction(
                    self.ptr, memtable_memory_budget as libc::uint64_t);
            }
        }

        pub fn set_compression_per_level(&mut self, levels: &[int]) {
            unsafe {
                let len = levels.len() as libc::size_t;
                let ptr = levels.as_ptr();

                ffi::rocksdb_options_set_compression_per_level(
                    self.ptr, ptr as *const libc::c_int, len);
            }
        }

        pub fn set_create_if_missing(&mut self, flag: bool) {
            unsafe {
                ffi::rocksdb_options_set_create_if_missing(
                    self.ptr, flag as libc::uint8_t);
            }
        }

        pub fn set_create_missing_column_families(&mut self, flag: bool) {
            unsafe {
                ffi::rocksdb_options_set_create_missing_column_families(
                    self.ptr, flag as libc::uint8_t);
            }
        }

        pub fn set_error_if_exists(&mut self, flag: bool) {
            unsafe {
                ffi::rocksdb_options_set_error_if_exists(
                    self.ptr, flag as libc::uint8_t);
            }
        }

        pub fn set_paranoid_checks(&mut self, flag: bool) {
            unsafe {
                ffi::rocksdb_options_set_paranoid_checks(
                    self.ptr, flag as libc::uint8_t);
            }
        }
    }

    impl Drop for Options {
        fn drop(&mut self) {
            unsafe { ffi::rocksdb_options_destroy(self.ptr); }
        }
    }

    pub struct Db {
        ptr: *mut ffi::Db,
    }

    impl Db {
        pub fn new(opts: &Options, name: &str) -> Result<Db, String> {
            use std::ptr;
            use std::c_str::CString;

            unsafe {
                let mut errstr : *mut libc::c_char = ptr::null_mut::<libc::c_char>();
                let c_str = name.as_ptr();
                let ptr = ffi::rocksdb_open(opts.ptr as *const ffi::Options,
                                            c_str as *const libc::c_char,
                                            &mut errstr);

                if ptr.is_null() {
                    let cstring = CString::new(errstr as *const libc::c_char, true);
                    Err(String::from_str(
                        cstring
                            .as_str()
                            .expect("Bad UTF-8 in rocksdb_open error message")))
                } else {
                    if !errstr.is_null() { libc::free(errstr as *mut libc::c_void) }
                    Ok(Db { ptr: ptr })
                }
            }
        }
    }

    impl Drop for Db {
        fn drop(&mut self) {
            unsafe { ffi::rocksdb_close(self.ptr); }
        }
    }
}

#[test]
fn test_options() {
    let mut opts = rocksdb::Options::new();
    opts.increase_parallelism(2);
    opts.optimize_for_point_lookup(16);
    opts.optimize_level_style_compaction(16);
    opts.optimize_universal_style_compaction(16);
    opts.set_compression_per_level([1,2,3,4,5]);
    opts.set_create_if_missing(true);
    opts.set_create_missing_column_families(true);
    opts.set_error_if_exists(true);
    opts.set_paranoid_checks(true);
}

#[test]
fn test_db() {
    use std::io;

    let mut opts = rocksdb::Options::new();
    let tmpdir = io::TempDir::new("rocksdb_create_db").unwrap();
    let dbpath = tmpdir.path().join("db");
    let tmppath = dbpath.as_str().unwrap();

    opts.set_create_if_missing(true);
    let mut db = rocksdb::Db::new(&opts, tmppath).unwrap();
}

<commit_msg>Added basic read and write functions. Tried adding snapshot, but there are lifetime problems I don't yet understand.<commit_after>pub mod rocksdb {
    extern crate libc;

    mod ffi {
        extern crate libc;

        pub enum Db {}
        pub enum Options {}
        pub enum WriteOptions {}
        pub enum ReadOptions {}
        // pub enum Snapshot {}

        #[link(name = "rocksdb")]
        extern "C" {
            pub fn rocksdb_options_create() -> *mut Options;
            pub fn rocksdb_options_destroy(ptr: *mut Options);

            pub fn rocksdb_options_increase_parallelism(
                opt: *mut Options, total_threads: libc::c_int);
            pub fn rocksdb_options_optimize_for_point_lookup(
                opt: *mut Options, block_cache_size_mb: libc::uint64_t);
            pub fn rocksdb_options_optimize_level_style_compaction(
                opt: *mut Options, memtable_memory_budget: libc::uint64_t);
            pub fn rocksdb_options_optimize_universal_style_compaction(
                opt: *mut Options, memtable_memory_budget: libc::uint64_t);
            // pub fn rocksdb_options_set_compaction_filter(
            //     opt: *mut Options,
            //     rocksdb_compactionfilter_t*);
            // pub fn rocksdb_options_set_compaction_filter_factory(
            //     opt: *mut Options, rocksdb_compactionfilterfactory_t*);
            // pub fn rocksdb_options_set_compaction_filter_factory_v2(
            //     opt: *mut Options,
            //     rocksdb_compactionfilterfactoryv2_t*);
            // pub fn rocksdb_options_set_comparator(
            //     opt: *mut Options,
            //     rocksdb_comparator_t*);
            // pub fn rocksdb_options_set_merge_operator(
            //     opt: *mut Options,
            //     rocksdb_mergeoperator_t*);
            pub fn rocksdb_options_set_compression_per_level(
                opt: *mut Options,
                level_values: *const libc::c_int,
                num_levels: libc::size_t);
            pub fn rocksdb_options_set_create_if_missing(
                opt: *mut Options, flag: libc::uint8_t);
            pub fn rocksdb_options_set_create_missing_column_families(
                opt: *mut Options, flag: libc::uint8_t);
            pub fn rocksdb_options_set_error_if_exists(
                opt: *mut Options, flag: libc::uint8_t);
            pub fn rocksdb_options_set_paranoid_checks(
                opt: *mut Options, flag: libc::uint8_t);

            pub fn rocksdb_writeoptions_create() -> *mut WriteOptions;
            pub fn rocksdb_writeoptions_destroy(
                opts: *mut WriteOptions);
            pub fn rocksdb_writeoptions_set_sync(
                opts: *mut WriteOptions, flag: libc::uint8_t);
            pub fn rocksdb_writeoptions_disable_WAL(
                opts: *mut WriteOptions, flag: libc::c_int);

            pub fn rocksdb_readoptions_create() -> *mut ReadOptions;
            pub fn rocksdb_readoptions_destroy(
                opts: *mut ReadOptions);
            pub fn rocksdb_readoptions_set_verify_checksums(
                opts: *mut ReadOptions, flag: libc::uint8_t);
            pub fn rocksdb_readoptions_set_fill_cache(
                opts: *mut ReadOptions, flag: libc::uint8_t);
            // pub fn rocksdb_readoptions_set_snapshot(
            //     opts: *mut ReadOptions, snapshot: *const Snapshot);
            // pub fn rocksdb_readoptions_set_iterate_upper_bound(
            //     opts: *mut ReadOptions, key: *const libc::c_char,
            //     key_len: libc::size_t);
            pub fn rocksdb_readoptions_set_read_tier(
                opts: *mut ReadOptions, tier: libc::c_int);
            pub fn rocksdb_readoptions_set_tailing(
                opts: *mut ReadOptions, flag: libc::uint8_t);

            pub fn rocksdb_open(
                options: *const Options,
                name: *const libc::c_char,
                errptr: *mut *mut libc::c_char)
                -> *mut Db;
            pub fn rocksdb_close(db: *mut Db);
            // pub fn rocksdb_create_snapshot(db: *mut Db) -> *const Snapshot;
            pub fn rocksdb_get(
                db: *mut Db, read_opts: *const ReadOptions,
                key: *const libc::c_char, keylen: libc::size_t,
                vallen: *mut libc::size_t,
                errptr: *mut *mut libc::c_char)
                -> *mut libc::c_char;
            pub fn rocksdb_put(
                db: *mut Db, write_opts: *const WriteOptions,
                key: *const libc::c_char, keylen: libc::size_t,
                val: *const libc::c_char, vallen: libc::size_t,
                errptr: *mut *mut libc::c_char);

            // pub fn rocksdb_release_snapshot(
            //     db: *mut Db, snapshot: *const Snapshot);
        }
    }

    pub struct Options {
        ptr: *mut ffi::Options,
    }

    pub struct ReadOptions {
        ptr: *mut ffi::ReadOptions,
    }

    pub struct WriteOptions {
        ptr: *mut ffi::WriteOptions,
    }

    pub struct Db {
        ptr: *mut ffi::Db,
    }

    // pub struct Snapshot<'a> {
    //     db: &'a Db,
    //     ptr: *const ffi::Snapshot,
    // }

    impl Options {

        pub fn new() -> Options {
            Options {
                ptr: unsafe { ffi::rocksdb_options_create() }
            }
        }

        pub fn increase_parallelism(&mut self, total_threads: int) {
            unsafe {
                ffi::rocksdb_options_increase_parallelism(
                    self.ptr, total_threads as libc::c_int)
            }
        }

        pub fn optimize_for_point_lookup(&mut self, block_cache_size_mb: u64) {
            unsafe {
                ffi::rocksdb_options_optimize_for_point_lookup(
                    self.ptr, block_cache_size_mb as libc::uint64_t);
            }
        }

        pub fn optimize_level_style_compaction(&mut self, memtable_memory_budget: u64) {
            unsafe {
                ffi::rocksdb_options_optimize_level_style_compaction(
                    self.ptr, memtable_memory_budget as libc::uint64_t);
            }
        }

        pub fn optimize_universal_style_compaction(&mut self, memtable_memory_budget: u64) {
            unsafe {
                ffi::rocksdb_options_optimize_universal_style_compaction(
                    self.ptr, memtable_memory_budget as libc::uint64_t);
            }
        }

        pub fn set_compression_per_level(&mut self, levels: &[int]) {
            unsafe {
                let len = levels.len() as libc::size_t;
                let ptr = levels.as_ptr();

                ffi::rocksdb_options_set_compression_per_level(
                    self.ptr, ptr as *const libc::c_int, len);
            }
        }

        pub fn set_create_if_missing(&mut self, flag: bool) {
            unsafe {
                ffi::rocksdb_options_set_create_if_missing(
                    self.ptr, flag as libc::uint8_t);
            }
        }

        pub fn set_create_missing_column_families(&mut self, flag: bool) {
            unsafe {
                ffi::rocksdb_options_set_create_missing_column_families(
                    self.ptr, flag as libc::uint8_t);
            }
        }

        pub fn set_error_if_exists(&mut self, flag: bool) {
            unsafe {
                ffi::rocksdb_options_set_error_if_exists(
                    self.ptr, flag as libc::uint8_t);
            }
        }

        pub fn set_paranoid_checks(&mut self, flag: bool) {
            unsafe {
                ffi::rocksdb_options_set_paranoid_checks(
                    self.ptr, flag as libc::uint8_t);
            }
        }
    }

    impl Drop for Options {
        fn drop(&mut self) {
            unsafe { ffi::rocksdb_options_destroy(self.ptr); }
        }
    }

    impl WriteOptions {
        pub fn new() -> WriteOptions {
            WriteOptions {
                ptr: unsafe { ffi::rocksdb_writeoptions_create() }
            }
        }

        pub fn set_sync(&mut self, flag: bool) {
            unsafe { ffi::rocksdb_writeoptions_set_sync(self.ptr, flag as libc::uint8_t); }
        }

        pub fn disable_wal(&mut self, flag: bool) {
            unsafe { ffi::rocksdb_writeoptions_disable_WAL(self.ptr, flag as libc::c_int); }
        }
    }

    impl Drop for WriteOptions {
        fn drop(&mut self) {
            unsafe { ffi::rocksdb_writeoptions_destroy(self.ptr); }
        }
    }

    impl ReadOptions {
        pub fn new() -> ReadOptions {
            ReadOptions {
                ptr: unsafe { ffi::rocksdb_readoptions_create() }
            }
        }

        pub fn set_verify_checksums(&mut self, flag: bool) {
            unsafe { ffi::rocksdb_readoptions_set_verify_checksums(self.ptr, flag as libc::uint8_t); }
        }

        pub fn set_fill_cache(&mut self, flag: bool) {
            unsafe { ffi::rocksdb_readoptions_set_fill_cache(self.ptr, flag as libc::uint8_t); }
        }

        // pub fn set_snapshot(&mut self, snapshot: &Snapshot) {
        //     unsafe { ffi::rocksdb_readoptions_set_snapshot(self.ptr, snapshot.ptr); }
        // }

        // NOTE: this is totally broken - it assigns a pointer from the stack, and
        // the lifetime / ownership is not specified.
        //
        // pub fn set_iterate_upper_bound(&mut self, key: &str) {
        //     unsafe { ffi::rocksdb_readoptions_(self.ptr, flag as libc::uint8_t); }
        // }

        pub fn set_read_tier(&mut self, tier: int) {
            unsafe { ffi::rocksdb_readoptions_set_read_tier(self.ptr, tier as libc::c_int); }
        }

        pub fn set_tailing(&mut self, flag: bool) {
            unsafe { ffi::rocksdb_readoptions_set_tailing(self.ptr, flag as libc::uint8_t); }
        }
    }

    impl Drop for ReadOptions {
        fn drop(&mut self) {
            unsafe { ffi::rocksdb_readoptions_destroy(self.ptr); }
        }
    }

    impl Db {
        pub fn new(opts: &Options, name: &str) -> Result<Db, String> {
            use std::ptr;
            use std::c_str::CString;

            unsafe {
                let mut errstr : *mut libc::c_char = ptr::null_mut::<libc::c_char>();
                let c_str = name.as_ptr();
                let ptr = ffi::rocksdb_open(opts.ptr as *const ffi::Options,
                                            c_str as *const libc::c_char,
                                            &mut errstr);

                if ptr.is_null() {
                    let cstring = CString::new(errstr as *const libc::c_char, true);
                    Err(String::from_str(
                        cstring
                            .as_str()
                            .expect("Bad UTF-8 in rocksdb_open error message")))
                } else {
                    if !errstr.is_null() { libc::free(errstr as *mut libc::c_void) }
                    Ok(Db { ptr: ptr })
                }
            }
        }

        // pub fn snapshot(&mut self) -> Snapshot {
        //     Snapshot {
        //         db: self,
        //         ptr: unsafe { ffi::rocksdb_create_snapshot(self.ptr) }
        //     }
        // }

        pub fn get(&mut self, read_opts: &ReadOptions, key: &[u8]) -> Result<Option<Vec<u8>>, String> {
            use std::ptr;
            use std::c_str::CString;

            unsafe {
                let mut errstr : *mut libc::c_char = ptr::null_mut::<libc::c_char>();
                let key_ptr = key.as_ptr();
                let mut vallen : libc::size_t = 0;
                let ptr = ffi::rocksdb_get(self.ptr,
                                           read_opts.ptr as *const ffi::ReadOptions,
                                           key_ptr as *const libc::c_char,
                                           key.len() as libc::size_t,
                                           &mut vallen,
                                           &mut errstr);

                if errstr.is_null() {
                    Ok(if ptr.is_null() {
                        None

                    } else {
                        use std::vec::raw;
                        let arr = raw::from_buf(ptr as *const u8, vallen as uint);
                        libc::free(ptr as *mut libc::c_void);
                        Some(arr)
                    })

                } else {
                    let cstring = CString::new(errstr as *const libc::c_char, true);
                    Err(String::from_str(
                        cstring
                            .as_str()
                            .expect("Bad UTF-8 in rocksdb_get error message")))
                }
            }
        }

        pub fn put(&mut self, write_opts: &WriteOptions, key: &[u8], val: &[u8])
                   -> Result<(), String> {
            use std::ptr;
            use std::c_str::CString;

            unsafe {
                let mut errstr : *mut libc::c_char = ptr::null_mut::<libc::c_char>();
                let key_ptr = key.as_ptr();
                let val_ptr = val.as_ptr();
                ffi::rocksdb_put(
                    self.ptr, write_opts.ptr as *const ffi::WriteOptions,
                    key_ptr as *const libc::c_char, key.len() as libc::size_t,
                    val_ptr as *const libc::c_char, val.len() as libc::size_t,
                    &mut errstr);

                if errstr.is_null() {
                    Ok(())

                } else {
                    let cstring = CString::new(errstr as *const libc::c_char, true);
                    Err(String::from_str(
                        cstring
                            .as_str()
                            .expect("Bad UTF-8 in rocksdb_put error message")))
                }
            }
        }
    }

    impl Drop for Db {
        fn drop(&mut self) {
            unsafe { ffi::rocksdb_close(self.ptr); }
        }
    }

    /*
/home/matt/Programming/rust/rocksdb/src/lib.rs:295:5: 299:6 error: cannot implement a destructor on a structure with type parameters [E0141]
/home/matt/Programming/rust/rocksdb/src/lib.rs:295     impl<'a> Drop for Snapshot<'a> {
/home/matt/Programming/rust/rocksdb/src/lib.rs:296         fn drop(&mut self) {
/home/matt/Programming/rust/rocksdb/src/lib.rs:297             unsafe { ffi::rocksdb_release_snapshot(self.db.ptr, self.ptr); }
/home/matt/Programming/rust/rocksdb/src/lib.rs:298         }
/home/matt/Programming/rust/rocksdb/src/lib.rs:299     }
/home/matt/Programming/rust/rocksdb/src/lib.rs:295:5: 299:6 note: use "#[unsafe_destructor]" on the implementation to force the compiler to allow this
/home/matt/Programming/rust/rocksdb/src/lib.rs:295     impl<'a> Drop for Snapshot<'a> {
/home/matt/Programming/rust/rocksdb/src/lib.rs:296         fn drop(&mut self) {
/home/matt/Programming/rust/rocksdb/src/lib.rs:297             unsafe { ffi::rocksdb_release_snapshot(self.db.ptr, self.ptr); }
/home/matt/Programming/rust/rocksdb/src/lib.rs:298         }
/home/matt/Programming/rust/rocksdb/src/lib.rs:299     }

     */
    // impl<'a> Drop for Snapshot<'a> {
    //     fn drop(&mut self) {
    //         unsafe { ffi::rocksdb_release_snapshot(self.db.ptr, self.ptr); }
    //     }
    // }
}

#[test]
fn test_options() {
    let mut opts = rocksdb::Options::new();
    opts.increase_parallelism(2);
    opts.optimize_for_point_lookup(16);
    opts.optimize_level_style_compaction(16);
    opts.optimize_universal_style_compaction(16);
    opts.set_compression_per_level([1,2,3,4,5]);
    opts.set_create_if_missing(true);
    opts.set_create_missing_column_families(true);
    opts.set_error_if_exists(true);
    opts.set_paranoid_checks(true);
}

#[test]
fn test_db() {
    use std::io;

    let mut opts = rocksdb::Options::new();
    let tmpdir = io::TempDir::new("rocksdb_create_db").unwrap();
    let dbpath = tmpdir.path().join("db");
    let tmppath = dbpath.as_str().unwrap();

    let write_opts = rocksdb::WriteOptions::new();
    let read_opts = rocksdb::ReadOptions::new();

    opts.set_create_if_missing(true);
    let mut db = rocksdb::Db::new(&opts, tmppath).unwrap();

    let key = [104u8, 101u8, 108u8, 108u8, 111u8];
    let val = [119u8, 111u8, 114u8, 108u8, 100u8];
    let first_value = db.get(&read_opts, key).unwrap();
    assert!(first_value.is_none());
    db.put(&write_opts, key, val).unwrap();
    let second_value = db.get(&read_opts, key).unwrap();
    assert!(second_value.is_some());
    assert!(second_value.unwrap().as_slice() == val);
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use futures::stream::Stream;

struct Entity {
    identifier: u64
}

enum Object<'a> {
    Entity(Entity),
    Literal(Literal<'a>)
}

enum Literal<'a> {
    LangLiteral(LangLiteral<'a>),
    StringLiteral(&'a str),
    BooleanLiteral(bool),
    LongLiteral(i64),
    DoubleLiteral(f64),
}

struct LangLiteral<'a> {
    value: &'a str,
    lang_tag: &'a str,
}

struct Predicate<'a> {
    predicate: &'a str,
}

enum Range<'a> {
    LangLiteralRange(LangLiteral<'a>, LangLiteral<'a>),
    StringLiteralRange(&'a str, &'a str),
    LongLiteralRange(i64, i64),
    DoubleLiteralRange(f64, f64),
}

struct Statement<'a> {
    subject: Entity,
    predicate: Predicate<'a>,
    object: Object<'a>,
    context: Entity,
}

pub const A: Predicate = Predicate { predicate: "_a" };
pub const DEFAULT: Entity = Entity { identifier: 0 };

struct CollectionName<'a> {
    name: &'a str
}

trait LigatureStore {
    fn read_tx() -> dyn ReadTx;
    fn write_tx() -> dyn WriteTx;
//     fn <T>compute(fun: suspend (ReadTx) -> T): T {
// val readTx = this.readTx()
// try {
// return fn(readTx)
// } finally {
// if (readTx.is_open()) {
// readTx.cancel()
// }
// }
//}

// fn write(fn: suspend (WriteTx) -> Unit) {
// val writeTx = this.writeTx()
// try {
// return fn(writeTx)
// } finally {
// if (writeTx.is_open()) {
// writeTx.commit()
// }
// }
// }

    /**
     * Close connection with the Store.
     */
    fn close();

    fn is_open() -> bool;
}

trait ReadTx {
    /**
     * Returns a Stream of all existing collections.
     */
    fn collections() -> dyn Stream<Item = CollectionName>;

    /**
     * Returns a Stream of all existing collections that start with the given prefix.
     */
    fn collections_prefix(prefix: CollectionName) -> dyn Stream<Item = CollectionName>;

    /**
     * Returns a Stream of all existing collections that are within the given range.
     * `from` is inclusive and `to` is exclusive.
     */
    fn collections_range(from: CollectionName, to: CollectionName) -> dyn Stream<Item = CollectionName>;

    /**
     * Accepts nothing but returns a Stream of all Statements in the Collection.
     */
    fn all_statements(collection: CollectionName) -> dyn Stream<Item = Statement>;

    /**
     * Is passed a pattern and returns a seq with all matching Statements.
     */
    fn match_statements(collection: CollectionName, subject: Option<Entity>, predicate: Option<Predicate>, object: Option<Object>, context: Option<Entity>) -> dyn Stream<Item = Statement>;

    /**
     * Is passed a pattern and returns a seq with all matching Statements.
     */
    fn match_statements_range(collection: CollectionName, subject: Option<Entity>, predicate: Option<Predicate>, range: Option<Range>, context: Option<Entity>) -> dyn Stream<Item = Statement>;

    /**
     * Cancels this transaction.
     */
    fn cancel();

    fn is_open() -> bool;
}

trait WriteTx {
    /**
     * Creates a collection with the given name or does nothing if the collection already exists.
     * Only useful for creating an empty collection.
     */
    fn create_collection(collection: CollectionName);

    /**
     * Deletes the collection of the name given and does nothing if the collection doesn't exist.
     */
    fn delete_collection(collection: CollectionName);

    /**
     * Returns a new, unique to this collection identifier in the form _:NUMBER
     */
    fn new_entity(collection: CollectionName) -> Entity;
    fn add_statement(collection: CollectionName, statement: Statement);
    fn remove_statement(collection: CollectionName, statement: Statement);

    /**
     * Commits this transaction.
     */
    fn commit();

    /**
     * Cancels this transaction.
     */
    fn cancel();

    fn is_open() -> bool;
}

/**
 * Accepts a String representing an identifier and returns true or false depending on if it is valid.
 */
fn valid_predicate(identifier: &str) -> bool {
    return "[a-zA-Z_][^\\s\\(\\)\\[\\]\\{\\}'\"`<>\\\\]*".toRegex().matches(identifier)
}

/**
 * Accepts a String representing a lang tag and returns true or false depending on if it is valid.
 */
fn valid_lang_tag(lang_tag: &str) -> bool {
    return "[a-zA-Z]+(-[a-zA-Z0-9]+)*".toRegex().matches(langTag)
}

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

    #[test]
    fn valid_identifier_tests() {
        assert_eq!(valid_predicate(""), false);
        assert_eq!(valid_predicate("http://localhost/people/7"), true);
        assert_eq!(valid_predicate("http://localhost(/people/7"), false);
        assert_eq!(valid_predicate("http://localhost /people/7"), false);
        assert_eq!(valid_predicate("hello"), true);
        assert_eq!(valid_predicate("_:"), true);
        assert_eq!(valid_predicate("_:valid"), true);
        assert_eq!(valid_predicate("_:1"), true);
        assert_eq!(valid_predicate("_:1344"), true);
    }

    #[test]
    fn valid_lang_tag_tests() {
        assert_eq!(valid_lang_tag(""), false);
        assert_eq!(valid_lang_tag("en"), true);
        assert_eq!(valid_lang_tag("en-"), false);
        assert_eq!(valid_lang_tag("en-fr"), true);
        assert_eq!(valid_lang_tag("en-fr-"), false);
        assert_eq!(valid_lang_tag("en-fr-sp"), true);
        assert_eq!(valid_lang_tag("ennnenefnk-dkfjkjfl-dfakjelfkjalkf-fakjeflkajlkfj"), true);
        assert_eq!(valid_lang_tag("en-fr-ef "), false);
    }
}
<commit_msg>last commit before typescript rewrite, closes #100<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use futures::stream::Stream;

pub struct Entity {
    identifier: u64
}

pub enum Object<'a> {
    Entity(Entity),
    Literal(Literal<'a>)
}

pub enum Literal<'a> {
    LangLiteral(LangLiteral<'a>),
    StringLiteral(&'a str),
    BooleanLiteral(bool),
    LongLiteral(i64),
    DoubleLiteral(f64),
}

pub struct LangLiteral<'a> {
    value: &'a str,
    lang_tag: &'a str,
}

pub struct Predicate<'a> {
    predicate: &'a str,
}

pub enum Range<'a> {
    LangLiteralRange(LangLiteral<'a>, LangLiteral<'a>),
    StringLiteralRange(&'a str, &'a str),
    LongLiteralRange(i64, i64),
    DoubleLiteralRange(f64, f64),
}

pub struct Statement<'a> {
    subject: Entity,
    predicate: Predicate<'a>,
    object: Object<'a>,
    context: Entity,
}

pub const A: Predicate = Predicate { predicate: "_a" };
pub const DEFAULT: Entity = Entity { identifier: 0 };

pub struct CollectionName<'a> {
    name: &'a str
}

pub trait LigatureStore<R, W> where R: ReadTxTrait, W: WriteTxTrait {
    fn read_tx() -> ReadTx<R>;
    fn write_tx() -> WriteTx<W>;
//     fn <T>compute(fun: suspend (ReadTx) -> T): T {
// val readTx = this.readTx()
// try {
// return fn(readTx)
// } finally {
// if (readTx.is_open()) {
// readTx.cancel()
// }
// }
//}

// fn write(fn: suspend (WriteTx) -> Unit) {
// val writeTx = this.writeTx()
// try {
// return fn(writeTx)
// } finally {
// if (writeTx.is_open()) {
// writeTx.commit()
// }
// }
// }

    /**
     * Close connection with the Store.
     */
    fn close();

    fn is_open() -> bool;
}

pub struct ReadTx<T> where T: ReadTxTrait {
    pub read_tx: T,
}

pub struct WriteTx<T> where T: WriteTxTrait {
    pub write_tx: T,
}

pub trait ReadTxTrait {
    /**
     * Returns a Stream of all existing collections.
     */
    fn collections<'a>() -> dyn Stream<Item = CollectionName<'a>>;

    /**
     * Returns a Stream of all existing collections that start with the given prefix.
     */
    fn collections_prefix<'a>(prefix: CollectionName) -> dyn Stream<Item = CollectionName<'a>>;

    /**
     * Returns a Stream of all existing collections that are within the given range.
     * `from` is inclusive and `to` is exclusive.
     */
    fn collections_range<'a>(from: CollectionName, to: CollectionName) -> dyn Stream<Item = CollectionName<'a>>;

    /**
     * Accepts nothing but returns a Stream of all Statements in the Collection.
     */
    fn all_statements<'a>(collection: CollectionName) -> dyn Stream<Item = Statement<'a>>;

    /**
     * Is passed a pattern and returns a seq with all matching Statements.
     */
    fn match_statements<'a>(collection: CollectionName, subject: Option<Entity>, predicate: Option<Predicate>, object: Option<Object>, context: Option<Entity>) -> dyn Stream<Item = Statement<'a>>;

    /**
     * Is passed a pattern and returns a seq with all matching Statements.
     */
    fn match_statements_range<'a>(collection: CollectionName, subject: Option<Entity>, predicate: Option<Predicate>, range: Option<Range>, context: Option<Entity>) -> dyn Stream<Item = Statement<'a>>;

    /**
     * Cancels this transaction.
     */
    fn cancel();

    fn is_open() -> bool;
}

pub trait WriteTxTrait {
    /**
     * Creates a collection with the given name or does nothing if the collection already exists.
     * Only useful for creating an empty collection.
     */
    fn create_collection(collection: CollectionName);

    /**
     * Deletes the collection of the name given and does nothing if the collection doesn't exist.
     */
    fn delete_collection(collection: CollectionName);

    /**
     * Returns a new, unique to this collection identifier in the form _:NUMBER
     */
    fn new_entity(collection: CollectionName) -> Entity;
    fn add_statement(collection: CollectionName, statement: Statement);
    fn remove_statement(collection: CollectionName, statement: Statement);

    /**
     * Commits this transaction.
     */
    fn commit();

    /**
     * Cancels this transaction.
     */
    fn cancel();

    fn is_open() -> bool;
}

// /**
//  * Accepts a String representing an identifier and returns true or false depending on if it is valid.
//  */
// fn valid_predicate(identifier: &str) -> bool {
//     return "[a-zA-Z_][^\\s\\(\\)\\[\\]\\{\\}'\"`<>\\\\]*".toRegex().matches(identifier)
// }

// /**
//  * Accepts a String representing a lang tag and returns true or false depending on if it is valid.
//  */
// fn valid_lang_tag(lang_tag: &str) -> bool {
//     return "[a-zA-Z]+(-[a-zA-Z0-9]+)*".toRegex().matches(lang_tag)
// }

// #[cfg(test)]
// mod tests {
//     use super::*;
//
//     #[test]
//     fn valid_identifier_tests() {
//         assert_eq!(valid_predicate(""), false);
//         assert_eq!(valid_predicate("http://localhost/people/7"), true);
//         assert_eq!(valid_predicate("http://localhost(/people/7"), false);
//         assert_eq!(valid_predicate("http://localhost /people/7"), false);
//         assert_eq!(valid_predicate("hello"), true);
//         assert_eq!(valid_predicate("_:"), true);
//         assert_eq!(valid_predicate("_:valid"), true);
//         assert_eq!(valid_predicate("_:1"), true);
//         assert_eq!(valid_predicate("_:1344"), true);
//     }
//
//     #[test]
//     fn valid_lang_tag_tests() {
//         assert_eq!(valid_lang_tag(""), false);
//         assert_eq!(valid_lang_tag("en"), true);
//         assert_eq!(valid_lang_tag("en-"), false);
//         assert_eq!(valid_lang_tag("en-fr"), true);
//         assert_eq!(valid_lang_tag("en-fr-"), false);
//         assert_eq!(valid_lang_tag("en-fr-sp"), true);
//         assert_eq!(valid_lang_tag("ennnenefnk-dkfjkjfl-dfakjelfkjalkf-fakjeflkajlkfj"), true);
//         assert_eq!(valid_lang_tag("en-fr-ef "), false);
//     }
// }
<|endoftext|>


<commit_before>//! As of Rust 1.30, the language supports user-defined function-like procedural
//! macros. However these can only be invoked in item position, not in
//! statements or expressions.
//!
//! This crate implements an alternative type of procedural macro that can be
//! invoked in statement or expression position.
//!
//! # Defining procedural macros
//!
//! Two crates are required to define a procedural macro.
//!
//! ## The implementation crate
//!
//! This crate must contain nothing but procedural macros. Private helper
//! functions and private modules are fine but nothing can be public.
//!
//! [> example of an implementation crate][demo-hack-impl]
//!
//! Just like you would use a #\[proc_macro\] attribute to define a natively
//! supported procedural macro, use proc-macro-hack's #\[proc_macro_hack\]
//! attribute to define a procedural macro that works in expression position.
//! The function signature is the same as for ordinary function-like procedural
//! macros.
//!
//! ```rust
//! extern crate proc_macro;
//! extern crate proc_macro_hack;
//! extern crate quote;
//! extern crate syn;
//!
//! use proc_macro::TokenStream;
//! use proc_macro_hack::proc_macro_hack;
//! use quote::quote;
//! use syn::{parse_macro_input, Expr};
//!
//! /// Add one to an expression.
//! # const IGNORE: &str = stringify! {
//! #[proc_macro_hack]
//! # };
//! pub fn add_one(input: TokenStream) -> TokenStream {
//!     let expr = parse_macro_input!(input as Expr);
//!     TokenStream::from(quote! {
//!         1 + (#expr)
//!     })
//! }
//! #
//! # fn main() {}
//! ```
//!
//! ## The declaration crate
//!
//! This crate is allowed to contain other public things if you need, for
//! example traits or functions or ordinary macros.
//!
//! [> example of a declaration crate][demo-hack]
//!
//! Within the declaration crate there needs to be a re-export of your
//! procedural macro from the implementation crate. The re-export also carries a
//! \#\[proc_macro_hack\] attribute.
//!
//! ```rust
//! extern crate demo_hack_impl;
//! extern crate proc_macro_hack;
//!
//! use proc_macro_hack::proc_macro_hack;
//!
//! /// Add one to an expression.
//! #[proc_macro_hack]
//! pub use demo_hack_impl::add_one;
//! #
//! # fn main() {}
//! ```
//!
//! Both crates depend on `proc-macro-hack`:
//!
//! ```toml
//! [dependencies]
//! proc-macro-hack = "0.5"
//! ```
//!
//! Additionally, your implementation crate (but not your declaration crate) is
//! a proc macro crate:
//!
//! ```toml
//! [lib]
//! proc-macro = true
//! ```
//!
//! # Using procedural macros
//!
//! Users of your crate depend on your declaration crate (not your
//! implementation crate), then use your procedural macros as usual.
//!
//! [> example of a downstream crate][example]
//!
//! ```rust
//! extern crate demo_hack;
//! use demo_hack::add_one;
//!
//! fn main() {
//!     let two = 2;
//!     let nine = add_one!(two) + add_one!(2 + 3);
//!     println!("nine = {}", nine);
//! }
//! ```
//!
//! [demo-hack-impl]: https://github.com/dtolnay/proc-macro-hack/tree/master/demo-hack-impl
//! [demo-hack]: https://github.com/dtolnay/proc-macro-hack/tree/master/demo-hack
//! [example]: https://github.com/dtolnay/proc-macro-hack/tree/master/example

#![recursion_limit = "256"]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
#![cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))]

extern crate proc_macro;
extern crate proc_macro2;
extern crate quote;
extern crate syn;

use std::fmt::Write;

use proc_macro2::{Span, TokenStream, TokenTree};
use quote::{quote, ToTokens};
use syn::parse::{Parse, ParseStream, Result};
use syn::{braced, bracketed, parenthesized, parse_macro_input, token, Ident, Token};

type Visibility = Option<Token![pub]>;

mod keyword {
    syn::custom_keyword!(export);
}

enum Input {
    Export(Export),
    Define(Define),
}

// pub use demo_hack_impl::{m1, m2 as qrst};
struct Export {
    attrs: TokenStream,
    vis: Visibility,
    from: Ident,
    macros: Vec<Macro>,
}

// pub fn m1(input: TokenStream) -> TokenStream { ... }
struct Define {
    attrs: TokenStream,
    name: Ident,
    body: TokenStream,
}

struct Macro {
    name: Ident,
    export_as: Ident,
}

impl Parse for Input {
    fn parse(input: ParseStream) -> Result<Self> {
        let ahead = input.fork();
        parse_attributes(&ahead)?;
        ahead.parse::<Visibility>()?;

        if ahead.peek(Token![use]) {
            input.parse().map(Input::Export)
        } else if ahead.peek(Token![fn]) {
            input.parse().map(Input::Define)
        } else {
            Err(input.error("unexpected input to #[proc_macro_hack]"))
        }
    }
}

impl Parse for Export {
    fn parse(input: ParseStream) -> Result<Self> {
        let attrs = input.call(parse_attributes)?;
        let vis: Visibility = input.parse()?;
        input.parse::<Token![use]>()?;
        let from: Ident = input.parse()?;
        input.parse::<Token![::]>()?;

        let mut macros = Vec::new();
        if input.peek(token::Brace) {
            let content;
            braced!(content in input);
            loop {
                macros.push(content.parse()?);
                if content.is_empty() {
                    break;
                }
                content.parse::<Token![,]>()?;
                if content.is_empty() {
                    break;
                }
            }
        } else {
            macros.push(input.parse()?);
        }

        input.parse::<Token![;]>()?;
        Ok(Export { attrs, vis, from, macros })
    }
}

impl Parse for Define {
    fn parse(input: ParseStream) -> Result<Self> {
        let attrs = input.call(parse_attributes)?;
        let vis: Visibility = input.parse()?;
        if vis.is_none() {
            return Err(input.error("functions tagged with `#[proc_macro_hack]` must be `pub`"));
        }

        input.parse::<Token![fn]>()?;
        let name: Ident = input.parse()?;
        let body: TokenStream = input.parse()?;
        Ok(Define { attrs, name, body })
    }
}

impl Parse for Macro {
    fn parse(input: ParseStream) -> Result<Self> {
        let name: Ident = input.parse()?;
        let renamed: Option<Token![as]> = input.parse()?;
        let export_as = if renamed.is_some() {
            input.parse()?
        } else {
            name.clone()
        };
        Ok(Macro { name, export_as })
    }
}

fn parse_attributes(input: ParseStream) -> Result<TokenStream> {
    let mut attrs = TokenStream::new();
    while input.peek(Token![#]) {
        let pound: Token![#] = input.parse()?;
        pound.to_tokens(&mut attrs);
        let content;
        let bracket_token = bracketed!(content in input);
        let content: TokenStream = content.parse()?;
        bracket_token.surround(&mut attrs, |tokens| content.to_tokens(tokens));
    }
    Ok(attrs)
}

#[proc_macro_attribute]
pub fn proc_macro_hack(
    _args: proc_macro::TokenStream,
    input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
    proc_macro::TokenStream::from(match parse_macro_input!(input) {
        Input::Export(export) => expand_export(export),
        Input::Define(define) => expand_define(define),
    })
}

struct EnumHack {
    token_stream: TokenStream,
}

impl Parse for EnumHack {
    fn parse(input: ParseStream) -> Result<Self> {
        input.parse::<Token![enum]>()?;
        input.parse::<Ident>()?;

        let braces;
        braced!(braces in input);
        braces.parse::<Ident>()?;
        braces.parse::<Token![=]>()?;

        let parens;
        parenthesized!(parens in braces);
        parens.parse::<Ident>()?;
        parens.parse::<Token![!]>()?;

        let inner;
        braced!(inner in parens);
        let token_stream: TokenStream = inner.parse()?;

        parens.parse::<Token![,]>()?;
        parens.parse::<TokenTree>()?;
        braces.parse::<Token![.]>()?;
        braces.parse::<TokenTree>()?;
        braces.parse::<Token![,]>()?;

        Ok(EnumHack { token_stream })
    }
}

#[doc(hidden)]
#[proc_macro_derive(ProcMacroHack)]
pub fn enum_hack(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let inner = parse_macro_input!(input as EnumHack);
    proc_macro::TokenStream::from(inner.token_stream)
}

fn expand_export(export: Export) -> TokenStream {
    let dummy = dummy_name_for_export(&export);

    let attrs = export.attrs;
    let vis = export.vis;
    let macro_export = match vis {
        Some(_) => quote!(#[macro_export]),
        None => quote!(),
    };
    let crate_prefix = match vis {
        Some(_) => quote!($crate::),
        None => quote!(),
    };

    let from = export.from;
    let rules = export
        .macros
        .into_iter()
        .map(|Macro { name, export_as }| {
            let actual_name = actual_proc_macro_name(&name);

            quote! {
                #[doc(hidden)]
                #vis use #from::#actual_name;

                #attrs
                #macro_export
                macro_rules! #export_as {
                    ($($proc_macro:tt)*) => {{
                        #[derive(#crate_prefix #actual_name)]
                        enum ProcMacroHack {
                            Value = (stringify! { $($proc_macro)* }, 0).1,
                        }
                        proc_macro_call!()
                    }};
                }
            }
        })
        .collect();

    wrap_in_enum_hack(dummy, rules)
}

fn expand_define(define: Define) -> TokenStream {
    let attrs = define.attrs;
    let name = define.name;
    let dummy = actual_proc_macro_name(&name);
    let body = define.body;

    quote! {
        mod #dummy {
            extern crate proc_macro;
            pub use self::proc_macro::*;
        }

        #attrs
        #[proc_macro_derive(#dummy)]
        pub fn #dummy(input: #dummy::TokenStream) -> #dummy::TokenStream {
            use std::iter::FromIterator;

            let mut iter = input.into_iter();
            iter.next().unwrap(); // `enum`
            iter.next().unwrap(); // `ProcMacroHack`

            let mut braces = match iter.next().unwrap() {
                #dummy::TokenTree::Group(group) => group.stream().into_iter(),
                _ => unimplemented!(),
            };
            braces.next().unwrap(); // `Value`
            braces.next().unwrap(); // `=`

            let mut parens = match braces.next().unwrap() {
                #dummy::TokenTree::Group(group) => group.stream().into_iter(),
                _ => unimplemented!(),
            };
            parens.next().unwrap(); // `stringify`
            parens.next().unwrap(); // `!`

            let inner = match parens.next().unwrap() {
                #dummy::TokenTree::Group(group) => group.stream(),
                _ => unimplemented!(),
            };

            let output: #dummy::TokenStream = #name(inner);

            // macro_rules! proc_macro_call {
            //     () => { #output }
            // }
            #dummy::TokenStream::from_iter(vec![
                #dummy::TokenTree::Ident(
                    #dummy::Ident::new("macro_rules", #dummy::Span::call_site()),
                ),
                #dummy::TokenTree::Punct(
                    #dummy::Punct::new('!', #dummy::Spacing::Alone),
                ),
                #dummy::TokenTree::Ident(
                    #dummy::Ident::new("proc_macro_call", #dummy::Span::call_site()),
                ),
                #dummy::TokenTree::Group(
                    #dummy::Group::new(#dummy::Delimiter::Brace, #dummy::TokenStream::from_iter(vec![
                        #dummy::TokenTree::Group(
                            #dummy::Group::new(#dummy::Delimiter::Parenthesis, #dummy::TokenStream::new()),
                        ),
                        #dummy::TokenTree::Punct(
                            #dummy::Punct::new('=', #dummy::Spacing::Joint),
                        ),
                        #dummy::TokenTree::Punct(
                            #dummy::Punct::new('>', #dummy::Spacing::Alone),
                        ),
                        #dummy::TokenTree::Group(
                            #dummy::Group::new(#dummy::Delimiter::Brace, output),
                        ),
                    ])),
                ),
            ])
        }

        fn #name #body
    }
}

fn actual_proc_macro_name(conceptual: &Ident) -> Ident {
    let actual_name = format!("proc_macro_hack_{}", conceptual);
    Ident::new(&actual_name, Span::call_site())
}

fn dummy_name_for_export(export: &Export) -> String {
    let mut dummy = String::new();
    write!(dummy, "_{}{}", export.from.to_string().len(), export.from);
    for m in &export.macros {
        write!(dummy, "_{}{}", m.name.to_string().len(), m.name);
    }
    dummy
}

fn wrap_in_enum_hack(dummy: String, inner: TokenStream) -> TokenStream {
    let dummy = Ident::new(&dummy, Span::call_site());
    quote! {
        #[derive(proc_macro_hack::ProcMacroHack)]
        enum #dummy {
            Value = (stringify! { #inner }, 0).1,
        }
    }
}
<commit_msg>Remove unused custom keyword<commit_after>//! As of Rust 1.30, the language supports user-defined function-like procedural
//! macros. However these can only be invoked in item position, not in
//! statements or expressions.
//!
//! This crate implements an alternative type of procedural macro that can be
//! invoked in statement or expression position.
//!
//! # Defining procedural macros
//!
//! Two crates are required to define a procedural macro.
//!
//! ## The implementation crate
//!
//! This crate must contain nothing but procedural macros. Private helper
//! functions and private modules are fine but nothing can be public.
//!
//! [> example of an implementation crate][demo-hack-impl]
//!
//! Just like you would use a #\[proc_macro\] attribute to define a natively
//! supported procedural macro, use proc-macro-hack's #\[proc_macro_hack\]
//! attribute to define a procedural macro that works in expression position.
//! The function signature is the same as for ordinary function-like procedural
//! macros.
//!
//! ```rust
//! extern crate proc_macro;
//! extern crate proc_macro_hack;
//! extern crate quote;
//! extern crate syn;
//!
//! use proc_macro::TokenStream;
//! use proc_macro_hack::proc_macro_hack;
//! use quote::quote;
//! use syn::{parse_macro_input, Expr};
//!
//! /// Add one to an expression.
//! # const IGNORE: &str = stringify! {
//! #[proc_macro_hack]
//! # };
//! pub fn add_one(input: TokenStream) -> TokenStream {
//!     let expr = parse_macro_input!(input as Expr);
//!     TokenStream::from(quote! {
//!         1 + (#expr)
//!     })
//! }
//! #
//! # fn main() {}
//! ```
//!
//! ## The declaration crate
//!
//! This crate is allowed to contain other public things if you need, for
//! example traits or functions or ordinary macros.
//!
//! [> example of a declaration crate][demo-hack]
//!
//! Within the declaration crate there needs to be a re-export of your
//! procedural macro from the implementation crate. The re-export also carries a
//! \#\[proc_macro_hack\] attribute.
//!
//! ```rust
//! extern crate demo_hack_impl;
//! extern crate proc_macro_hack;
//!
//! use proc_macro_hack::proc_macro_hack;
//!
//! /// Add one to an expression.
//! #[proc_macro_hack]
//! pub use demo_hack_impl::add_one;
//! #
//! # fn main() {}
//! ```
//!
//! Both crates depend on `proc-macro-hack`:
//!
//! ```toml
//! [dependencies]
//! proc-macro-hack = "0.5"
//! ```
//!
//! Additionally, your implementation crate (but not your declaration crate) is
//! a proc macro crate:
//!
//! ```toml
//! [lib]
//! proc-macro = true
//! ```
//!
//! # Using procedural macros
//!
//! Users of your crate depend on your declaration crate (not your
//! implementation crate), then use your procedural macros as usual.
//!
//! [> example of a downstream crate][example]
//!
//! ```rust
//! extern crate demo_hack;
//! use demo_hack::add_one;
//!
//! fn main() {
//!     let two = 2;
//!     let nine = add_one!(two) + add_one!(2 + 3);
//!     println!("nine = {}", nine);
//! }
//! ```
//!
//! [demo-hack-impl]: https://github.com/dtolnay/proc-macro-hack/tree/master/demo-hack-impl
//! [demo-hack]: https://github.com/dtolnay/proc-macro-hack/tree/master/demo-hack
//! [example]: https://github.com/dtolnay/proc-macro-hack/tree/master/example

#![recursion_limit = "256"]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
#![cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))]

extern crate proc_macro;
extern crate proc_macro2;
extern crate quote;
extern crate syn;

use std::fmt::Write;

use proc_macro2::{Span, TokenStream, TokenTree};
use quote::{quote, ToTokens};
use syn::parse::{Parse, ParseStream, Result};
use syn::{braced, bracketed, parenthesized, parse_macro_input, token, Ident, Token};

type Visibility = Option<Token![pub]>;

enum Input {
    Export(Export),
    Define(Define),
}

// pub use demo_hack_impl::{m1, m2 as qrst};
struct Export {
    attrs: TokenStream,
    vis: Visibility,
    from: Ident,
    macros: Vec<Macro>,
}

// pub fn m1(input: TokenStream) -> TokenStream { ... }
struct Define {
    attrs: TokenStream,
    name: Ident,
    body: TokenStream,
}

struct Macro {
    name: Ident,
    export_as: Ident,
}

impl Parse for Input {
    fn parse(input: ParseStream) -> Result<Self> {
        let ahead = input.fork();
        parse_attributes(&ahead)?;
        ahead.parse::<Visibility>()?;

        if ahead.peek(Token![use]) {
            input.parse().map(Input::Export)
        } else if ahead.peek(Token![fn]) {
            input.parse().map(Input::Define)
        } else {
            Err(input.error("unexpected input to #[proc_macro_hack]"))
        }
    }
}

impl Parse for Export {
    fn parse(input: ParseStream) -> Result<Self> {
        let attrs = input.call(parse_attributes)?;
        let vis: Visibility = input.parse()?;
        input.parse::<Token![use]>()?;
        let from: Ident = input.parse()?;
        input.parse::<Token![::]>()?;

        let mut macros = Vec::new();
        if input.peek(token::Brace) {
            let content;
            braced!(content in input);
            loop {
                macros.push(content.parse()?);
                if content.is_empty() {
                    break;
                }
                content.parse::<Token![,]>()?;
                if content.is_empty() {
                    break;
                }
            }
        } else {
            macros.push(input.parse()?);
        }

        input.parse::<Token![;]>()?;
        Ok(Export { attrs, vis, from, macros })
    }
}

impl Parse for Define {
    fn parse(input: ParseStream) -> Result<Self> {
        let attrs = input.call(parse_attributes)?;
        let vis: Visibility = input.parse()?;
        if vis.is_none() {
            return Err(input.error("functions tagged with `#[proc_macro_hack]` must be `pub`"));
        }

        input.parse::<Token![fn]>()?;
        let name: Ident = input.parse()?;
        let body: TokenStream = input.parse()?;
        Ok(Define { attrs, name, body })
    }
}

impl Parse for Macro {
    fn parse(input: ParseStream) -> Result<Self> {
        let name: Ident = input.parse()?;
        let renamed: Option<Token![as]> = input.parse()?;
        let export_as = if renamed.is_some() {
            input.parse()?
        } else {
            name.clone()
        };
        Ok(Macro { name, export_as })
    }
}

fn parse_attributes(input: ParseStream) -> Result<TokenStream> {
    let mut attrs = TokenStream::new();
    while input.peek(Token![#]) {
        let pound: Token![#] = input.parse()?;
        pound.to_tokens(&mut attrs);
        let content;
        let bracket_token = bracketed!(content in input);
        let content: TokenStream = content.parse()?;
        bracket_token.surround(&mut attrs, |tokens| content.to_tokens(tokens));
    }
    Ok(attrs)
}

#[proc_macro_attribute]
pub fn proc_macro_hack(
    _args: proc_macro::TokenStream,
    input: proc_macro::TokenStream,
) -> proc_macro::TokenStream {
    proc_macro::TokenStream::from(match parse_macro_input!(input) {
        Input::Export(export) => expand_export(export),
        Input::Define(define) => expand_define(define),
    })
}

struct EnumHack {
    token_stream: TokenStream,
}

impl Parse for EnumHack {
    fn parse(input: ParseStream) -> Result<Self> {
        input.parse::<Token![enum]>()?;
        input.parse::<Ident>()?;

        let braces;
        braced!(braces in input);
        braces.parse::<Ident>()?;
        braces.parse::<Token![=]>()?;

        let parens;
        parenthesized!(parens in braces);
        parens.parse::<Ident>()?;
        parens.parse::<Token![!]>()?;

        let inner;
        braced!(inner in parens);
        let token_stream: TokenStream = inner.parse()?;

        parens.parse::<Token![,]>()?;
        parens.parse::<TokenTree>()?;
        braces.parse::<Token![.]>()?;
        braces.parse::<TokenTree>()?;
        braces.parse::<Token![,]>()?;

        Ok(EnumHack { token_stream })
    }
}

#[doc(hidden)]
#[proc_macro_derive(ProcMacroHack)]
pub fn enum_hack(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
    let inner = parse_macro_input!(input as EnumHack);
    proc_macro::TokenStream::from(inner.token_stream)
}

fn expand_export(export: Export) -> TokenStream {
    let dummy = dummy_name_for_export(&export);

    let attrs = export.attrs;
    let vis = export.vis;
    let macro_export = match vis {
        Some(_) => quote!(#[macro_export]),
        None => quote!(),
    };
    let crate_prefix = match vis {
        Some(_) => quote!($crate::),
        None => quote!(),
    };

    let from = export.from;
    let rules = export
        .macros
        .into_iter()
        .map(|Macro { name, export_as }| {
            let actual_name = actual_proc_macro_name(&name);

            quote! {
                #[doc(hidden)]
                #vis use #from::#actual_name;

                #attrs
                #macro_export
                macro_rules! #export_as {
                    ($($proc_macro:tt)*) => {{
                        #[derive(#crate_prefix #actual_name)]
                        enum ProcMacroHack {
                            Value = (stringify! { $($proc_macro)* }, 0).1,
                        }
                        proc_macro_call!()
                    }};
                }
            }
        })
        .collect();

    wrap_in_enum_hack(dummy, rules)
}

fn expand_define(define: Define) -> TokenStream {
    let attrs = define.attrs;
    let name = define.name;
    let dummy = actual_proc_macro_name(&name);
    let body = define.body;

    quote! {
        mod #dummy {
            extern crate proc_macro;
            pub use self::proc_macro::*;
        }

        #attrs
        #[proc_macro_derive(#dummy)]
        pub fn #dummy(input: #dummy::TokenStream) -> #dummy::TokenStream {
            use std::iter::FromIterator;

            let mut iter = input.into_iter();
            iter.next().unwrap(); // `enum`
            iter.next().unwrap(); // `ProcMacroHack`

            let mut braces = match iter.next().unwrap() {
                #dummy::TokenTree::Group(group) => group.stream().into_iter(),
                _ => unimplemented!(),
            };
            braces.next().unwrap(); // `Value`
            braces.next().unwrap(); // `=`

            let mut parens = match braces.next().unwrap() {
                #dummy::TokenTree::Group(group) => group.stream().into_iter(),
                _ => unimplemented!(),
            };
            parens.next().unwrap(); // `stringify`
            parens.next().unwrap(); // `!`

            let inner = match parens.next().unwrap() {
                #dummy::TokenTree::Group(group) => group.stream(),
                _ => unimplemented!(),
            };

            let output: #dummy::TokenStream = #name(inner);

            // macro_rules! proc_macro_call {
            //     () => { #output }
            // }
            #dummy::TokenStream::from_iter(vec![
                #dummy::TokenTree::Ident(
                    #dummy::Ident::new("macro_rules", #dummy::Span::call_site()),
                ),
                #dummy::TokenTree::Punct(
                    #dummy::Punct::new('!', #dummy::Spacing::Alone),
                ),
                #dummy::TokenTree::Ident(
                    #dummy::Ident::new("proc_macro_call", #dummy::Span::call_site()),
                ),
                #dummy::TokenTree::Group(
                    #dummy::Group::new(#dummy::Delimiter::Brace, #dummy::TokenStream::from_iter(vec![
                        #dummy::TokenTree::Group(
                            #dummy::Group::new(#dummy::Delimiter::Parenthesis, #dummy::TokenStream::new()),
                        ),
                        #dummy::TokenTree::Punct(
                            #dummy::Punct::new('=', #dummy::Spacing::Joint),
                        ),
                        #dummy::TokenTree::Punct(
                            #dummy::Punct::new('>', #dummy::Spacing::Alone),
                        ),
                        #dummy::TokenTree::Group(
                            #dummy::Group::new(#dummy::Delimiter::Brace, output),
                        ),
                    ])),
                ),
            ])
        }

        fn #name #body
    }
}

fn actual_proc_macro_name(conceptual: &Ident) -> Ident {
    let actual_name = format!("proc_macro_hack_{}", conceptual);
    Ident::new(&actual_name, Span::call_site())
}

fn dummy_name_for_export(export: &Export) -> String {
    let mut dummy = String::new();
    write!(dummy, "_{}{}", export.from.to_string().len(), export.from);
    for m in &export.macros {
        write!(dummy, "_{}{}", m.name.to_string().len(), m.name);
    }
    dummy
}

fn wrap_in_enum_hack(dummy: String, inner: TokenStream) -> TokenStream {
    let dummy = Ident::new(&dummy, Span::call_site());
    quote! {
        #[derive(proc_macro_hack::ProcMacroHack)]
        enum #dummy {
            Value = (stringify! { #inner }, 0).1,
        }
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate wlroots;

use std::cell::{Cell, RefCell};
use std::rc::Rc;
use wlroots::compositor::Compositor;
use wlroots::cursor::{Cursor, XCursor, XCursorTheme};
use wlroots::device::Device;
use wlroots::key_event::KeyEvent;
use wlroots::manager::{InputManagerHandler, OutputManagerHandler};
use wlroots::output::{Output, OutputLayout};
use wlroots::pointer;
use wlroots::wlroots_sys::gl;
use wlroots::wlroots_sys::wlr_button_state::{WLR_BUTTON_PRESSED, WLR_BUTTON_RELEASED};
use wlroots::xkbcommon::xkb::keysyms::KEY_Escape;

struct OutputHandler {
    color: Rc<Cell<[f32; 4]>>,
    cursor: Rc<RefCell<Cursor>>
}

struct InputHandler {
    color: Rc<Cell<[f32; 4]>>,
    default_color: [f32; 4],
    cursor: Rc<RefCell<Cursor>>
}

impl OutputManagerHandler for OutputHandler {
    fn output_added(&mut self, mut output: Output) {
        let mut cursor = self.cursor.borrow_mut();
        {
            let xcursor = cursor.xcursor().expect("XCursor was not set!");
            let image = &xcursor.images()[0];
            // TODO use output config if present instead of auto
            let mut layout = cursor
                .output_layout()
                .as_ref()
                .expect("Could not get output layout");
            layout.borrow_mut().add_auto(&mut output);
            if output.set_cursor(image).is_err() {
                wlr_log!(L_DEBUG, "Failed to set hardware cursor");
                return;
            }
        }
        let (x, y) = cursor.coords();
        // https://en.wikipedia.org/wiki/Mouse_warping
        cursor.warp(None, x, y);
    }

    fn output_frame(&mut self, output: Output) {
        output.make_current();
        unsafe {
            gl::ClearColor(self.color.get()[0], self.color.get()[1], self.color.get()[2], 1.0);
            gl::Clear(gl::COLOR_BUFFER_BIT);
        }
        output.swap_buffers();
    }
}

impl InputManagerHandler for InputHandler {
    fn button(&mut self, event: pointer::ButtonEvent) {
        if event.state() == WLR_BUTTON_RELEASED {
            self.color.set(self.default_color.clone())
        } else {
            let mut red: [f32; 4] = [0.25, 0.25, 0.25, 1.0];
            red[event.button() as usize % 3] = 1.0;
            self.color.set(red);
        }
    }
}

fn managers(mut cursor: Cursor) -> (OutputHandler, InputHandler) {
    let mut layout = Rc::new(RefCell::new(OutputLayout::new()));
    // TODO Ensure this can be safe...
    // e.g what's stopping me from simply dropping layout now that I gave it to
    // cursor?
    cursor.attach_output_layout(layout);
    let cursor = Rc::new(RefCell::new(cursor));
    let color = Rc::new(Cell::new([0.25, 0.25, 0.25, 1.0]));
    (OutputHandler {
         color: color.clone(),
         cursor: cursor.clone()
     },
     InputHandler {
         color: color.clone(),
         default_color: color.get(),
         cursor: cursor.clone()
     })
}

fn main() {
    let mut cursor = Cursor::new().expect("Could not create cursor");
    let xcursor_theme = XCursorTheme::load_theme(None, 16).expect("Could not load theme");
    let mut xcursor = xcursor_theme
        .get_cursor("left_ptr".into())
        .expect("Could not load cursor from theme");
    cursor.set_xcursor(Some(xcursor));

    let (mut output_manager, input_manager) = managers(cursor);
    let compositor = Compositor::new(Box::new(input_manager), Box::new(output_manager));
    compositor.run();
}
<commit_msg>Warning prune and clean up of pointer example<commit_after>#[macro_use]
extern crate wlroots;

use std::cell::{Cell, RefCell};
use std::rc::Rc;
use wlroots::compositor::Compositor;
use wlroots::cursor::{Cursor, XCursorTheme};
use wlroots::manager::{InputManagerHandler, OutputManagerHandler};
use wlroots::output::{Output, OutputLayout};
use wlroots::pointer;
use wlroots::wlroots_sys::gl;
use wlroots::wlroots_sys::wlr_button_state::{WLR_BUTTON_RELEASED};

struct OutputHandler {
    color: Rc<Cell<[f32; 4]>>,
    cursor: Cursor
}

struct InputHandler {
    color: Rc<Cell<[f32; 4]>>,
    default_color: [f32; 4]
}

impl OutputManagerHandler for OutputHandler {
    fn output_added(&mut self, mut output: Output) {
        let cursor = &mut self.cursor;
        {
            let xcursor = cursor.xcursor().expect("XCursor was not set!");
            let image = &xcursor.images()[0];
            // TODO use output config if present instead of auto
            let layout = cursor
                .output_layout()
                .as_ref()
                .expect("Could not get output layout");
            layout.borrow_mut().add_auto(&mut output);
            if output.set_cursor(image).is_err() {
                wlr_log!(L_DEBUG, "Failed to set hardware cursor");
                return;
            }
        }
        let (x, y) = cursor.coords();
        // https://en.wikipedia.org/wiki/Mouse_warping
        cursor.warp(None, x, y);
    }

    fn output_frame(&mut self, output: Output) {
        output.make_current();
        unsafe {
            gl::ClearColor(self.color.get()[0], self.color.get()[1], self.color.get()[2], 1.0);
            gl::Clear(gl::COLOR_BUFFER_BIT);
        }
        output.swap_buffers();
    }
}

impl InputManagerHandler for InputHandler {
    fn button(&mut self, event: pointer::ButtonEvent) {
        if event.state() == WLR_BUTTON_RELEASED {
            self.color.set(self.default_color.clone())
        } else {
            let mut red: [f32; 4] = [0.25, 0.25, 0.25, 1.0];
            red[event.button() as usize % 3] = 1.0;
            self.color.set(red);
        }
    }
}

fn managers(mut cursor: Cursor) -> (OutputHandler, InputHandler) {
    let layout = Rc::new(RefCell::new(OutputLayout::new()));
    // TODO Ensure this can be safe...
    // e.g what's stopping me from simply dropping layout now that I gave it to
    // cursor?
    cursor.attach_output_layout(layout);
    let cursor = cursor;
    let color = Rc::new(Cell::new([0.25, 0.25, 0.25, 1.0]));
    (OutputHandler {
         color: color.clone(),
         cursor: cursor
     },
     InputHandler {
         color: color.clone(),
         default_color: color.get(),
     })
}

fn main() {
    let mut cursor = Cursor::new().expect("Could not create cursor");
    let xcursor_theme = XCursorTheme::load_theme(None, 16).expect("Could not load theme");
    let xcursor = xcursor_theme
        .get_cursor("left_ptr".into())
        .expect("Could not load cursor from theme");
    cursor.set_xcursor(Some(xcursor));

    let (output_manager, input_manager) = managers(cursor);
    let compositor = Compositor::new(Box::new(input_manager), Box::new(output_manager));
    compositor.run();
}
<|endoftext|>


<commit_before>pub fn ralf() {
    println!("ralf");
}
<commit_msg>Window and stuff<commit_after>extern crate sdl2;

use sdl2::pixels::Color;
use std::thread;

pub fn ralf() {
    println!("ralf");
    let sdl_context = sdl2::init().unwrap();
    let timer = sdl_context.timer().unwrap();
    let mut event_pump = sdl_context.event_pump().unwrap();
    let video = sdl_context.video().unwrap();

    let window = video.window("Ruffel", 800, 600)
        .position_centered().opengl()
        .build().unwrap();

    let mut renderer = window.renderer()
        .accelerated()
        .build().unwrap();

    let done = false;
    while !done {
        renderer.set_draw_color(Color::RGB(0, 0, 0));
        renderer.clear();
        renderer.present();

        thread::sleep_ms(1/60);
        for event in event_pump.poll_iter() {
        }
    }
    println!("finish");
}
<|endoftext|>


<commit_before>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

//! [Apache Parquet](http://parquet.apache.org) is a columnar storage format that
//! provides efficient data compression and encoding schemes to improve performance of
//! handling complex nested data structures. Parquet implements record-shredding and
//! assembly algorithm described in the Dremel paper.
//!
//! Crate provides API to access file schema and metadata from a Parquet file, extract
//! row groups or column chunks from a file, and read records/values.
//!
//! # Usage
//!
//! This crate is [on crates.io](https://crates.io/crates/parquet) and can be used by
//! adding `parquet` to the list of dependencies in `Cargo.toml`.
//!
//! ```toml
//! [dependencies]
//! parquet = "0.1"
//! ```
//!
//! and this to the project's crate root:
//!
//! ```rust
//! extern crate parquet;
//! ```
//!
//! # Example
//!
//! Below is the example of reading a Parquet file, listing Parquet metadata including
//! column chunk metadata, using record API and accessing row group readers.
//!
//! ```rust
//! use std::fs::File;
//! use std::path::Path;
//! use parquet::file::reader::{FileReader, SerializedFileReader};
//!
//! // Creating a file reader
//! let path = Path::new("data/alltypes_plain.parquet");
//! let file = File::open(&path).expect("File should exist");
//! let reader = SerializedFileReader::new(file).expect("Valid Parquet file");
//!
//! // Listing Parquet metadata
//! let parquet_metadata = reader.metadata();
//! let file_metadata = parquet_metadata.file_metadata();
//! for i in 0..parquet_metadata.num_row_groups() {
//!   // Accessing row group metadata
//!   let row_group_metadata = parquet_metadata.row_group(i);
//!   // Accessing column chunk metadata
//!   for j in 0..row_group_metadata.num_columns() {
//!     let column_chunk_metadata = row_group_metadata.column(j);
//!   }
//! }
//!
//! // Reading data using record API
//! let mut iter = reader.get_row_iter(None).expect("Should be okay");
//! while let Some(record) = iter.next() {
//!   // do something with the record...
//!   println!("{}", record);
//! }
//!
//! // Accessing row group readers in a file
//! for i in 0..reader.num_row_groups() {
//!   let row_group_reader = reader.get_row_group(i).expect("Should be okay");
//! }
//! ```
//!
//! # Metadata
//!
//! Module [`metadata`](`file::metadata`) contains Parquet metadata structs, including
//! file metadata, that has information about file schema, version, and number of rows,
//! row group metadata with a set of column chunks that contain column type and encodings,
//! number of values and compressed/uncompressed size in bytes.
//!
//! # Schema and type
//!
//! Parquet schema can be extracted from [`FileMetaData`](`file::metadata::FileMetaData`)
//! and is represented by Parquet type.
//!
//! Parquet type is described by [`Type`](`schema::types::Type`), including top level
//! message type or schema. Refer to the [`schema`] module for the detailed information
//! on Type API, printing and parsing of message types.
//!
//! # File and row group API
//!
//! Module [`file`] contains all definitions to explore Parquet files metadata and data.
//! File reader [`FileReader`](`file::reader::FileReader`) is a starting point for
//! working with Parquet files - it provides set of methods to get file metadata, row
//! group readers [`RowGroupReader`](`file::reader::RowGroupReader`) to get access to
//! column readers and record iterator.
//!
//! # Read API
//!
//! Crate offers several methods to read data from a Parquet file:
//! - Low level column reader API (see [`column`] module)
//! - Arrow API (_TODO_)
//! - High level record API (see [`record`] module)
//!

#![feature(type_ascription)]
#![feature(rustc_private)]
#![feature(specialization)]
#![feature(cfg_target_feature)]
#![feature(match_default_bindings)]

#![allow(dead_code)]
#![allow(non_camel_case_types)]

#[macro_use]
extern crate quick_error;
extern crate byteorder;
extern crate thrift;
extern crate arena;
extern crate snap;
extern crate brotli;
extern crate flate2;
extern crate rand;
extern crate x86intrin;
extern crate parquet_format;
extern crate chrono;

#[macro_use]
pub mod errors;
pub mod basic;
pub mod data_type;

// Exported for external use, such as benchmarks
pub use util::memory;
pub use encodings::encoding;
pub use encodings::decoding;

#[macro_use]
mod util;
mod encodings;
pub mod compression;
pub mod column;
pub mod record;
pub mod schema;
pub mod file;
<commit_msg>Remove features flags that are stablized (#97)<commit_after>// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

//! [Apache Parquet](http://parquet.apache.org) is a columnar storage format that
//! provides efficient data compression and encoding schemes to improve performance of
//! handling complex nested data structures. Parquet implements record-shredding and
//! assembly algorithm described in the Dremel paper.
//!
//! Crate provides API to access file schema and metadata from a Parquet file, extract
//! row groups or column chunks from a file, and read records/values.
//!
//! # Usage
//!
//! This crate is [on crates.io](https://crates.io/crates/parquet) and can be used by
//! adding `parquet` to the list of dependencies in `Cargo.toml`.
//!
//! ```toml
//! [dependencies]
//! parquet = "0.1"
//! ```
//!
//! and this to the project's crate root:
//!
//! ```rust
//! extern crate parquet;
//! ```
//!
//! # Example
//!
//! Below is the example of reading a Parquet file, listing Parquet metadata including
//! column chunk metadata, using record API and accessing row group readers.
//!
//! ```rust
//! use std::fs::File;
//! use std::path::Path;
//! use parquet::file::reader::{FileReader, SerializedFileReader};
//!
//! // Creating a file reader
//! let path = Path::new("data/alltypes_plain.parquet");
//! let file = File::open(&path).expect("File should exist");
//! let reader = SerializedFileReader::new(file).expect("Valid Parquet file");
//!
//! // Listing Parquet metadata
//! let parquet_metadata = reader.metadata();
//! let file_metadata = parquet_metadata.file_metadata();
//! for i in 0..parquet_metadata.num_row_groups() {
//!   // Accessing row group metadata
//!   let row_group_metadata = parquet_metadata.row_group(i);
//!   // Accessing column chunk metadata
//!   for j in 0..row_group_metadata.num_columns() {
//!     let column_chunk_metadata = row_group_metadata.column(j);
//!   }
//! }
//!
//! // Reading data using record API
//! let mut iter = reader.get_row_iter(None).expect("Should be okay");
//! while let Some(record) = iter.next() {
//!   // do something with the record...
//!   println!("{}", record);
//! }
//!
//! // Accessing row group readers in a file
//! for i in 0..reader.num_row_groups() {
//!   let row_group_reader = reader.get_row_group(i).expect("Should be okay");
//! }
//! ```
//!
//! # Metadata
//!
//! Module [`metadata`](`file::metadata`) contains Parquet metadata structs, including
//! file metadata, that has information about file schema, version, and number of rows,
//! row group metadata with a set of column chunks that contain column type and encodings,
//! number of values and compressed/uncompressed size in bytes.
//!
//! # Schema and type
//!
//! Parquet schema can be extracted from [`FileMetaData`](`file::metadata::FileMetaData`)
//! and is represented by Parquet type.
//!
//! Parquet type is described by [`Type`](`schema::types::Type`), including top level
//! message type or schema. Refer to the [`schema`] module for the detailed information
//! on Type API, printing and parsing of message types.
//!
//! # File and row group API
//!
//! Module [`file`] contains all definitions to explore Parquet files metadata and data.
//! File reader [`FileReader`](`file::reader::FileReader`) is a starting point for
//! working with Parquet files - it provides set of methods to get file metadata, row
//! group readers [`RowGroupReader`](`file::reader::RowGroupReader`) to get access to
//! column readers and record iterator.
//!
//! # Read API
//!
//! Crate offers several methods to read data from a Parquet file:
//! - Low level column reader API (see [`column`] module)
//! - Arrow API (_TODO_)
//! - High level record API (see [`record`] module)
//!

#![feature(type_ascription)]
#![feature(rustc_private)]
#![feature(specialization)]

#![allow(dead_code)]
#![allow(non_camel_case_types)]

#[macro_use]
extern crate quick_error;
extern crate byteorder;
extern crate thrift;
extern crate arena;
extern crate snap;
extern crate brotli;
extern crate flate2;
extern crate rand;
extern crate x86intrin;
extern crate parquet_format;
extern crate chrono;

#[macro_use]
pub mod errors;
pub mod basic;
pub mod data_type;

// Exported for external use, such as benchmarks
pub use util::memory;
pub use encodings::encoding;
pub use encodings::decoding;

#[macro_use]
mod util;
mod encodings;
pub mod compression;
pub mod column;
pub mod record;
pub mod schema;
pub mod file;
<|endoftext|>