<commit_before>use libc::{c_double, c_int, c_long, c_ulong, c_void,c_char};
use std::mem::uninitialized;
use std::cmp;
use std::cmp::Ordering::{self, Greater, Less, Equal};
use std::ops::{Div, Mul, Add, Sub, Neg};
use std::ffi::CString;
use std::string::String;
use super::mpz::mp_bitcnt_t;
use super::mpz::{Mpz, mpz_srcptr};
use super::mpq::{Mpq, mpq_srcptr};

type mp_exp_t = c_long;

#[repr(C)]
pub struct mpf_struct {
    _mp_prec: c_int,
    _mp_size: c_int,
    _mp_exp: mp_exp_t,
    _mp_d: *mut c_void
}

pub type mpf_srcptr = *const mpf_struct;
pub type mpf_ptr = *mut mpf_struct;

#[link(name = "gmp")]
extern "C" {
    fn __gmpf_init2(x: mpf_ptr, prec: mp_bitcnt_t);
    fn __gmpf_init_set(rop: mpf_ptr, op: mpf_srcptr);
    fn __gmpf_clear(x: mpf_ptr);
    fn __gmpf_get_prec(op: mpf_srcptr) -> mp_bitcnt_t;
    fn __gmpf_set_prec(rop: mpf_ptr, prec: mp_bitcnt_t);
    fn __gmpf_set(rop: mpf_ptr, op: mpf_srcptr);
    fn __gmpf_set_z(rop: mpf_ptr, op: mpz_srcptr);
    fn __gmpf_set_q(rop: mpf_ptr, op: mpq_srcptr);

    fn __gmpf_set_str(rop: mpf_ptr, str: *const c_char, base: c_int);
    fn __gmpf_set_si(rop: mpf_ptr, op: c_long);
    fn __gmpf_get_str(str: *const c_char, expptr: *const mp_exp_t, base: i32, n_digits: i32, op: mpf_ptr) -> *mut c_char;

    fn __gmpf_cmp(op1: mpf_srcptr, op2: mpf_srcptr) -> c_int;
    fn __gmpf_cmp_d(op1: mpf_srcptr, op2: c_double) -> c_int;
    fn __gmpf_cmp_ui(op1: mpf_srcptr, op2: c_ulong) -> c_int;
    fn __gmpf_cmp_si(op1: mpf_srcptr, op2: c_long) -> c_int;
    fn __gmpf_reldiff(rop: mpf_ptr, op1: mpf_srcptr, op2: mpf_srcptr);
    fn __gmpf_add(rop: mpf_ptr, op1: mpf_srcptr, op2: mpf_srcptr);
    fn __gmpf_sub(rop: mpf_ptr, op1: mpf_srcptr, op2: mpf_srcptr);
    fn __gmpf_mul(rop: mpf_ptr, op1: mpf_srcptr, op2: mpf_srcptr);
    fn __gmpf_div(rop: mpf_ptr, op1: mpf_srcptr, op2: mpf_srcptr);
    fn __gmpf_neg(rop: mpf_ptr, op: mpf_srcptr);
    fn __gmpf_abs(rop: mpf_ptr, op: mpf_srcptr);
    fn __gmpf_ceil(rop: mpf_ptr, op: mpf_srcptr);
    fn __gmpf_floor(rop: mpf_ptr, op: mpf_srcptr);
    fn __gmpf_trunc(rop: mpf_ptr, op: mpf_srcptr);
    fn __gmpf_sqrt(rop: mpf_ptr, op: mpf_srcptr);
}

pub struct Mpf {
    mpf: mpf_struct,
}

unsafe impl Send for Mpf { }

impl Drop for Mpf {
    fn drop(&mut self) { unsafe { __gmpf_clear(&mut self.mpf) } }
}

impl Mpf {
    pub unsafe fn inner(&self) -> mpf_srcptr {
        &self.mpf
    }

    pub unsafe fn inner_mut(&mut self) -> mpf_ptr {
        &mut self.mpf
    }

    pub fn zero() -> Mpf { Mpf::new(32) }

    pub fn new(precision: usize) -> Mpf {
        unsafe {
            let mut mpf = uninitialized();
            __gmpf_init2(&mut mpf, precision as c_ulong);
            Mpf { mpf: mpf }
        }
    }

    pub fn set(&mut self, other: &Mpf) {
        unsafe { __gmpf_set(&mut self.mpf, &other.mpf) }
    }

    pub fn set_z(&mut self, other: &Mpz) {
        unsafe { __gmpf_set_z(&mut self.mpf, other.inner()) }
    }

    pub fn set_q(&mut self, other: &Mpq) {
        unsafe { __gmpf_set_q(&mut self.mpf, other.inner()) }
    }

    pub fn get_prec(&self) -> usize {
        unsafe { __gmpf_get_prec(&self.mpf) as usize }
    }

    pub fn set_prec(&mut self, precision: usize) {
        unsafe { __gmpf_set_prec(&mut self.mpf, precision as c_ulong) }
    }

    pub fn set_from_str(&mut self, string: &str, base: i32){
        let c_str = CString::new(string).unwrap();
        unsafe {
            __gmpf_set_str(&mut self.mpf, c_str.as_ptr(), base as c_int);
        }
    }

    pub fn set_from_si(&mut self, int: i64){
        unsafe{
            __gmpf_set_si(&mut self.mpf,int as c_long);
        }
    }

    pub fn get_str(&mut self, n_digits: i32, base: i32, exp: &mut c_long) -> String{
        let c_str = CString::new("").unwrap();
        let out;
        unsafe{
            out = CString::from_raw(__gmpf_get_str(c_str.into_raw(), exp, base, n_digits, &mut self.mpf));
        }
        out.to_str().unwrap().to_string()
    }

    pub fn abs(&self) -> Mpf {
        unsafe {
            let mut res = Mpf::new(self.get_prec());
            __gmpf_abs(&mut res.mpf, &self.mpf);
            res
        }
    }

    pub fn ceil(&self) -> Mpf {
        unsafe {
            let mut res = Mpf::new(self.get_prec());
            __gmpf_ceil(&mut res.mpf, &self.mpf);
            res
        }
    }

    pub fn floor(&self) -> Mpf {
        unsafe {
            let mut res = Mpf::new(self.get_prec());
            __gmpf_floor(&mut res.mpf, &self.mpf);
            res
        }
    }

    pub fn trunc(&self) -> Mpf {
        unsafe {
            let mut res = Mpf::new(self.get_prec());
            __gmpf_trunc(&mut res.mpf, &self.mpf);
            res
        }
    }

    pub fn reldiff(&self, other: &Mpf) -> Mpf {
        unsafe {
            let mut res = Mpf::new(cmp::max(self.get_prec(), other.get_prec()));
            __gmpf_reldiff(&mut res.mpf, &self.mpf, &other.mpf);
            res
        }
    }

    pub fn sqrt(self) -> Mpf {
        let mut retval:Mpf;
        unsafe {
            retval = Mpf::new(__gmpf_get_prec(&self.mpf) as usize);
            retval.set_from_si(0);
            if __gmpf_cmp_si(&self.mpf, 0) > 0 {
                __gmpf_sqrt(&mut retval.mpf, &self.mpf);
            } else {
                panic!("Square root of negative/zero");
            }
        }
        retval
    }
}

impl Clone for Mpf {
    fn clone(&self) -> Mpf {
        unsafe {
            let mut mpf = uninitialized();
            __gmpf_init_set(&mut mpf, &self.mpf);
            Mpf { mpf: mpf }
        }
    }
}

impl Eq for Mpf { }
impl PartialEq for Mpf {
    fn eq(&self, other: &Mpf) -> bool {
        unsafe { __gmpf_cmp(&self.mpf, &other.mpf) == 0 }
    }
}

impl Ord for Mpf {
    fn cmp(&self, other: &Mpf) -> Ordering {
        let cmp = unsafe { __gmpf_cmp(&self.mpf, &other.mpf) };
        if cmp == 0 {
            Equal
        } else if cmp > 0 {
            Greater
        } else {
            Less
        }
    }
}

impl PartialOrd for Mpf {
    fn partial_cmp(&self, other: &Mpf) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl<'a, 'b> Add<&'a Mpf> for &'b Mpf {
    type Output = Mpf;
    fn add(self, other: &Mpf) -> Mpf {
        unsafe {
            let mut res = Mpf::new(cmp::max(self.get_prec(), other.get_prec()));
            __gmpf_add(&mut res.mpf, &self.mpf, &other.mpf);
            res
        }
    }
}

impl<'a> Add<&'a Mpf> for Mpf {
    type Output = Mpf;
    #[inline]
    fn add(mut self, other: &Mpf) -> Mpf {
        unsafe {
            __gmpf_add(&mut self.mpf, &self.mpf, &other.mpf);
            self
        }
    }
}

impl<'a, 'b> Sub<&'a Mpf> for &'b Mpf {
    type Output = Mpf;
    fn sub(self, other: &Mpf) -> Mpf {
        unsafe {
            let mut res = Mpf::new(cmp::max(self.get_prec(), other.get_prec()));
            __gmpf_sub(&mut res.mpf, &self.mpf, &other.mpf);
            res
        }
    }
}

impl<'a> Sub<&'a Mpf> for Mpf {
    type Output = Mpf;
    #[inline]
    fn sub(mut self, other: &Mpf) -> Mpf {
        unsafe {
            __gmpf_sub(&mut self.mpf, &self.mpf, &other.mpf);
            self
        }
    }
}

impl<'a, 'b> Mul<&'a Mpf> for &'b Mpf {
    type Output = Mpf;
    fn mul(self, other: &Mpf) -> Mpf {
        unsafe {
            let mut res = Mpf::new(cmp::max(self.get_prec(), other.get_prec()));
            __gmpf_mul(&mut res.mpf, &self.mpf, &other.mpf);
            res
        }
    }
}

impl<'a> Mul<&'a Mpf> for Mpf {
    type Output = Mpf;
    #[inline]
    fn mul(mut self, other: &Mpf) -> Mpf {
        unsafe {
            __gmpf_mul(&mut self.mpf, &self.mpf, &other.mpf);
            self
        }
    }
}

impl<'a, 'b> Div<&'a Mpf> for &'b Mpf {
    type Output = Mpf;
    fn div(self, other: &Mpf) -> Mpf {
        unsafe {
            if __gmpf_cmp_ui(&self.mpf, 0) == 0 {
                panic!("divide by zero")
            }

            let mut res = Mpf::new(cmp::max(self.get_prec(), other.get_prec()));
            __gmpf_div(&mut res.mpf, &self.mpf, &other.mpf);
            res
        }
    }
}

impl<'a> Div<&'a Mpf> for Mpf {
    type Output = Mpf;
    #[inline]
    fn div(mut self, other: &Mpf) -> Mpf {
        unsafe {
            if __gmpf_cmp_ui(&self.mpf, 0) == 0 {
                panic!("divide by zero")
            }

            __gmpf_div(&mut self.mpf, &self.mpf, &other.mpf);
            self
        }
    }
}

impl<'b> Neg for &'b Mpf {
    type Output = Mpf;
    fn neg(self) -> Mpf {
        unsafe {
            let mut res = Mpf::new(self.get_prec());
            __gmpf_neg(&mut res.mpf, &self.mpf);
            res
        }
    }
}

impl Neg for Mpf {
    type Output = Mpf;
    #[inline]
    fn neg(mut self) -> Mpf {
        unsafe {
            __gmpf_neg(&mut self.mpf, &self.mpf);
            self
        }
    }
}

gen_overloads!(Mpf);
<commit_msg>Mpf: Panic on x / 0, not 0 / x<commit_after>use libc::{c_double, c_int, c_long, c_ulong, c_void,c_char};
use std::mem::uninitialized;
use std::cmp;
use std::cmp::Ordering::{self, Greater, Less, Equal};
use std::ops::{Div, Mul, Add, Sub, Neg};
use std::ffi::CString;
use std::string::String;
use super::mpz::mp_bitcnt_t;
use super::mpz::{Mpz, mpz_srcptr};
use super::mpq::{Mpq, mpq_srcptr};

type mp_exp_t = c_long;

#[repr(C)]
pub struct mpf_struct {
    _mp_prec: c_int,
    _mp_size: c_int,
    _mp_exp: mp_exp_t,
    _mp_d: *mut c_void
}

pub type mpf_srcptr = *const mpf_struct;
pub type mpf_ptr = *mut mpf_struct;

#[link(name = "gmp")]
extern "C" {
    fn __gmpf_init2(x: mpf_ptr, prec: mp_bitcnt_t);
    fn __gmpf_init_set(rop: mpf_ptr, op: mpf_srcptr);
    fn __gmpf_clear(x: mpf_ptr);
    fn __gmpf_get_prec(op: mpf_srcptr) -> mp_bitcnt_t;
    fn __gmpf_set_prec(rop: mpf_ptr, prec: mp_bitcnt_t);
    fn __gmpf_set(rop: mpf_ptr, op: mpf_srcptr);
    fn __gmpf_set_z(rop: mpf_ptr, op: mpz_srcptr);
    fn __gmpf_set_q(rop: mpf_ptr, op: mpq_srcptr);

    fn __gmpf_set_str(rop: mpf_ptr, str: *const c_char, base: c_int);
    fn __gmpf_set_si(rop: mpf_ptr, op: c_long);
    fn __gmpf_get_str(str: *const c_char, expptr: *const mp_exp_t, base: i32, n_digits: i32, op: mpf_ptr) -> *mut c_char;

    fn __gmpf_cmp(op1: mpf_srcptr, op2: mpf_srcptr) -> c_int;
    fn __gmpf_cmp_d(op1: mpf_srcptr, op2: c_double) -> c_int;
    fn __gmpf_cmp_ui(op1: mpf_srcptr, op2: c_ulong) -> c_int;
    fn __gmpf_cmp_si(op1: mpf_srcptr, op2: c_long) -> c_int;
    fn __gmpf_reldiff(rop: mpf_ptr, op1: mpf_srcptr, op2: mpf_srcptr);
    fn __gmpf_add(rop: mpf_ptr, op1: mpf_srcptr, op2: mpf_srcptr);
    fn __gmpf_sub(rop: mpf_ptr, op1: mpf_srcptr, op2: mpf_srcptr);
    fn __gmpf_mul(rop: mpf_ptr, op1: mpf_srcptr, op2: mpf_srcptr);
    fn __gmpf_div(rop: mpf_ptr, op1: mpf_srcptr, op2: mpf_srcptr);
    fn __gmpf_neg(rop: mpf_ptr, op: mpf_srcptr);
    fn __gmpf_abs(rop: mpf_ptr, op: mpf_srcptr);
    fn __gmpf_ceil(rop: mpf_ptr, op: mpf_srcptr);
    fn __gmpf_floor(rop: mpf_ptr, op: mpf_srcptr);
    fn __gmpf_trunc(rop: mpf_ptr, op: mpf_srcptr);
    fn __gmpf_sqrt(rop: mpf_ptr, op: mpf_srcptr);
}

pub struct Mpf {
    mpf: mpf_struct,
}

unsafe impl Send for Mpf { }

impl Drop for Mpf {
    fn drop(&mut self) { unsafe { __gmpf_clear(&mut self.mpf) } }
}

impl Mpf {
    pub unsafe fn inner(&self) -> mpf_srcptr {
        &self.mpf
    }

    pub unsafe fn inner_mut(&mut self) -> mpf_ptr {
        &mut self.mpf
    }

    pub fn zero() -> Mpf { Mpf::new(32) }

    pub fn new(precision: usize) -> Mpf {
        unsafe {
            let mut mpf = uninitialized();
            __gmpf_init2(&mut mpf, precision as c_ulong);
            Mpf { mpf: mpf }
        }
    }

    pub fn set(&mut self, other: &Mpf) {
        unsafe { __gmpf_set(&mut self.mpf, &other.mpf) }
    }

    pub fn set_z(&mut self, other: &Mpz) {
        unsafe { __gmpf_set_z(&mut self.mpf, other.inner()) }
    }

    pub fn set_q(&mut self, other: &Mpq) {
        unsafe { __gmpf_set_q(&mut self.mpf, other.inner()) }
    }

    pub fn get_prec(&self) -> usize {
        unsafe { __gmpf_get_prec(&self.mpf) as usize }
    }

    pub fn set_prec(&mut self, precision: usize) {
        unsafe { __gmpf_set_prec(&mut self.mpf, precision as c_ulong) }
    }

    pub fn set_from_str(&mut self, string: &str, base: i32){
        let c_str = CString::new(string).unwrap();
        unsafe {
            __gmpf_set_str(&mut self.mpf, c_str.as_ptr(), base as c_int);
        }
    }

    pub fn set_from_si(&mut self, int: i64){
        unsafe{
            __gmpf_set_si(&mut self.mpf,int as c_long);
        }
    }

    pub fn get_str(&mut self, n_digits: i32, base: i32, exp: &mut c_long) -> String{
        let c_str = CString::new("").unwrap();
        let out;
        unsafe{
            out = CString::from_raw(__gmpf_get_str(c_str.into_raw(), exp, base, n_digits, &mut self.mpf));
        }
        out.to_str().unwrap().to_string()
    }

    pub fn abs(&self) -> Mpf {
        unsafe {
            let mut res = Mpf::new(self.get_prec());
            __gmpf_abs(&mut res.mpf, &self.mpf);
            res
        }
    }

    pub fn ceil(&self) -> Mpf {
        unsafe {
            let mut res = Mpf::new(self.get_prec());
            __gmpf_ceil(&mut res.mpf, &self.mpf);
            res
        }
    }

    pub fn floor(&self) -> Mpf {
        unsafe {
            let mut res = Mpf::new(self.get_prec());
            __gmpf_floor(&mut res.mpf, &self.mpf);
            res
        }
    }

    pub fn trunc(&self) -> Mpf {
        unsafe {
            let mut res = Mpf::new(self.get_prec());
            __gmpf_trunc(&mut res.mpf, &self.mpf);
            res
        }
    }

    pub fn reldiff(&self, other: &Mpf) -> Mpf {
        unsafe {
            let mut res = Mpf::new(cmp::max(self.get_prec(), other.get_prec()));
            __gmpf_reldiff(&mut res.mpf, &self.mpf, &other.mpf);
            res
        }
    }

    pub fn sqrt(self) -> Mpf {
        let mut retval:Mpf;
        unsafe {
            retval = Mpf::new(__gmpf_get_prec(&self.mpf) as usize);
            retval.set_from_si(0);
            if __gmpf_cmp_si(&self.mpf, 0) > 0 {
                __gmpf_sqrt(&mut retval.mpf, &self.mpf);
            } else {
                panic!("Square root of negative/zero");
            }
        }
        retval
    }
}

impl Clone for Mpf {
    fn clone(&self) -> Mpf {
        unsafe {
            let mut mpf = uninitialized();
            __gmpf_init_set(&mut mpf, &self.mpf);
            Mpf { mpf: mpf }
        }
    }
}

impl Eq for Mpf { }
impl PartialEq for Mpf {
    fn eq(&self, other: &Mpf) -> bool {
        unsafe { __gmpf_cmp(&self.mpf, &other.mpf) == 0 }
    }
}

impl Ord for Mpf {
    fn cmp(&self, other: &Mpf) -> Ordering {
        let cmp = unsafe { __gmpf_cmp(&self.mpf, &other.mpf) };
        if cmp == 0 {
            Equal
        } else if cmp > 0 {
            Greater
        } else {
            Less
        }
    }
}

impl PartialOrd for Mpf {
    fn partial_cmp(&self, other: &Mpf) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl<'a, 'b> Add<&'a Mpf> for &'b Mpf {
    type Output = Mpf;
    fn add(self, other: &Mpf) -> Mpf {
        unsafe {
            let mut res = Mpf::new(cmp::max(self.get_prec(), other.get_prec()));
            __gmpf_add(&mut res.mpf, &self.mpf, &other.mpf);
            res
        }
    }
}

impl<'a> Add<&'a Mpf> for Mpf {
    type Output = Mpf;
    #[inline]
    fn add(mut self, other: &Mpf) -> Mpf {
        unsafe {
            __gmpf_add(&mut self.mpf, &self.mpf, &other.mpf);
            self
        }
    }
}

impl<'a, 'b> Sub<&'a Mpf> for &'b Mpf {
    type Output = Mpf;
    fn sub(self, other: &Mpf) -> Mpf {
        unsafe {
            let mut res = Mpf::new(cmp::max(self.get_prec(), other.get_prec()));
            __gmpf_sub(&mut res.mpf, &self.mpf, &other.mpf);
            res
        }
    }
}

impl<'a> Sub<&'a Mpf> for Mpf {
    type Output = Mpf;
    #[inline]
    fn sub(mut self, other: &Mpf) -> Mpf {
        unsafe {
            __gmpf_sub(&mut self.mpf, &self.mpf, &other.mpf);
            self
        }
    }
}

impl<'a, 'b> Mul<&'a Mpf> for &'b Mpf {
    type Output = Mpf;
    fn mul(self, other: &Mpf) -> Mpf {
        unsafe {
            let mut res = Mpf::new(cmp::max(self.get_prec(), other.get_prec()));
            __gmpf_mul(&mut res.mpf, &self.mpf, &other.mpf);
            res
        }
    }
}

impl<'a> Mul<&'a Mpf> for Mpf {
    type Output = Mpf;
    #[inline]
    fn mul(mut self, other: &Mpf) -> Mpf {
        unsafe {
            __gmpf_mul(&mut self.mpf, &self.mpf, &other.mpf);
            self
        }
    }
}

impl<'a, 'b> Div<&'a Mpf> for &'b Mpf {
    type Output = Mpf;
    fn div(self, other: &Mpf) -> Mpf {
        unsafe {
            if __gmpf_cmp_ui(&other.mpf, 0) == 0 {
                panic!("divide by zero")
            }

            let mut res = Mpf::new(cmp::max(self.get_prec(), other.get_prec()));
            __gmpf_div(&mut res.mpf, &self.mpf, &other.mpf);
            res
        }
    }
}

impl<'a> Div<&'a Mpf> for Mpf {
    type Output = Mpf;
    #[inline]
    fn div(mut self, other: &Mpf) -> Mpf {
        unsafe {
            if __gmpf_cmp_ui(&other.mpf, 0) == 0 {
                panic!("divide by zero")
            }

            __gmpf_div(&mut self.mpf, &self.mpf, &other.mpf);
            self
        }
    }
}

impl<'b> Neg for &'b Mpf {
    type Output = Mpf;
    fn neg(self) -> Mpf {
        unsafe {
            let mut res = Mpf::new(self.get_prec());
            __gmpf_neg(&mut res.mpf, &self.mpf);
            res
        }
    }
}

impl Neg for Mpf {
    type Output = Mpf;
    #[inline]
    fn neg(mut self) -> Mpf {
        unsafe {
            __gmpf_neg(&mut self.mpf, &self.mpf);
            self
        }
    }
}

gen_overloads!(Mpf);
<|endoftext|>


<commit_before>
<commit_msg>chore(net): remove empty net file<commit_after><|endoftext|>


<commit_before>use openvpn_parser::{parse_openvpn_tcp,Payload};
use tls::TlsParser;

use rparser::{RParser,R_STATUS_OK,R_STATUS_FAIL};

pub struct OpenVPNTCPParser<'a> {
    _name: Option<&'a[u8]>,
    defrag_buf: Vec<u8>,

    tls_parser: TlsParser<'a>,
}

impl<'a> OpenVPNTCPParser<'a> {
    pub fn new(name: &'a[u8]) -> OpenVPNTCPParser<'a> {
        OpenVPNTCPParser{
            _name: Some(name),
            defrag_buf: Vec::new(),
            tls_parser: TlsParser::new(b"OpenVPN/TLS"),
        }
    }
}

impl<'a> RParser for OpenVPNTCPParser<'a> {
    fn parse(&mut self, i: &[u8], direction: u8) -> u32 {
        let mut cur_i = i;
        loop {
            match parse_openvpn_tcp(cur_i) {
                Ok((rem,r)) => {
                    debug!("parse_openvpn_tcp: {:?}", r);
                    if let Payload::Control(ref ctrl) = r.msg {
                        // XXX check number, and if packets needs to be reordered
                        self.defrag_buf.extend_from_slice(ctrl.payload);
                    }
                    if rem.len() == 0 { break; }
                    debug!("Remaining bytes: {}", rem.len());
                    cur_i = rem;
                },
                e => {
                    warn!("parse_openvpn_tcp failed: {:?}", e);
                    // warn!("input buffer:\n{}",i.to_hex(16));
                    return R_STATUS_FAIL;
                },
            }
        }
        if self.defrag_buf.len() > 0 {
            // inscpect TLS message
            // debug!("TLS message:\n{}", self.defrag_buf.to_hex(16));
            self.tls_parser.parse_tcp_level(&self.defrag_buf, direction);
            self.defrag_buf.clear();
        }
        R_STATUS_OK
    }
}

pub fn openvpn_tcp_probe(i: &[u8]) -> bool {
    if i.len() <= 20 { return false; }
    // XXX
    parse_openvpn_tcp(i).is_ok()
}

<commit_msg>Restrict OpenVPN TCP probing to make less false positives<commit_after>use openvpn_parser::{parse_openvpn_tcp,Payload,P_CONTROL_V1,P_ACK_V1};
use tls::TlsParser;

use rparser::{RParser,R_STATUS_OK,R_STATUS_FAIL};

pub struct OpenVPNTCPParser<'a> {
    _name: Option<&'a[u8]>,
    defrag_buf: Vec<u8>,

    tls_parser: TlsParser<'a>,
}

impl<'a> OpenVPNTCPParser<'a> {
    pub fn new(name: &'a[u8]) -> OpenVPNTCPParser<'a> {
        OpenVPNTCPParser{
            _name: Some(name),
            defrag_buf: Vec::new(),
            tls_parser: TlsParser::new(b"OpenVPN/TLS"),
        }
    }
}

impl<'a> RParser for OpenVPNTCPParser<'a> {
    fn parse(&mut self, i: &[u8], direction: u8) -> u32 {
        let mut cur_i = i;
        loop {
            match parse_openvpn_tcp(cur_i) {
                Ok((rem,r)) => {
                    debug!("parse_openvpn_tcp: {:?}", r);
                    if let Payload::Control(ref ctrl) = r.msg {
                        // XXX check number, and if packets needs to be reordered
                        self.defrag_buf.extend_from_slice(ctrl.payload);
                    }
                    if rem.len() == 0 { break; }
                    debug!("Remaining bytes: {}", rem.len());
                    cur_i = rem;
                },
                e => {
                    warn!("parse_openvpn_tcp failed: {:?}", e);
                    // warn!("input buffer:\n{}",i.to_hex(16));
                    return R_STATUS_FAIL;
                },
            }
        }
        if self.defrag_buf.len() > 0 {
            // inscpect TLS message
            // debug!("TLS message:\n{}", self.defrag_buf.to_hex(16));
            self.tls_parser.parse_tcp_level(&self.defrag_buf, direction);
            self.defrag_buf.clear();
        }
        R_STATUS_OK
    }
}

pub fn openvpn_tcp_probe(i: &[u8]) -> bool {
    if i.len() <= 20 { return false; }
    // XXX
    match parse_openvpn_tcp(i) {
        Ok((rem,pkt)) => {
            match pkt.hdr.opcode {
                P_CONTROL_V1 => {
                    if rem.len() > 3 && &rem[0..1] == &[0x16, 0x03] { true }
                    else { false }
                },
                P_ACK_V1 => {
                    if rem.is_empty() { true } else { false }
                },
                _ => false,
            }
        },
        _ => false,
    }
}

<|endoftext|>


<commit_before>use libc;
use glib::translate::*;
use pango::{self, ContextExt, LayoutExt};
use pango_sys;

use drawing_ctx::{self, RsvgDrawingCtx};
use state::{self, UnicodeBidi};

// FIXME: should the pango crate provide this like PANGO_GRAVITY_IS_VERTICAL() / PANGO_GRAVITY_IS_IMPROPER()?
fn gravity_is_vertical(gravity: pango::Gravity) -> bool {
    match gravity {
        pango::Gravity::East | pango::Gravity::West => true,
        _ => false
    }
}

fn to_pango_units(v: f64) -> i32 {
    (v * f64::from(pango::SCALE)) as i32
}

fn create_pango_layout(draw_ctx: *const RsvgDrawingCtx, text: &str) -> pango::Layout {
    let state = drawing_ctx::get_current_state(draw_ctx);
    let pango_context = drawing_ctx::get_pango_context(draw_ctx);

    if let Some(lang) = state::get_language(state) {
        let pango_lang = pango::Language::from_string(&lang);
        pango_context.set_language(&pango_lang);
    }

    let unicode_bidi = state::get_unicode_bidi(state);
    match unicode_bidi {
        UnicodeBidi::Override | UnicodeBidi::Embed => {
            pango_context.set_base_dir(state::get_text_dir(state));
        },

        _ => ()
    }

    let gravity = state::get_text_gravity(state);
    if gravity_is_vertical(gravity) {
        pango_context.set_base_gravity(gravity);
    }

    let mut font_desc = pango_context.get_font_description().unwrap();

    if let Some(font_family) = state::get_font_family(state) {
        font_desc.set_family(&font_family);
    }

    font_desc.set_style(state::get_font_style(state));
    font_desc.set_variant(state::get_font_variant(state));
    font_desc.set_weight(state::get_font_weight(state));
    font_desc.set_stretch(state::get_font_stretch(state));

    let (_, dpi_y) = drawing_ctx::get_dpi(draw_ctx);
    font_desc.set_size(to_pango_units(drawing_ctx::get_normalized_font_size(draw_ctx) / dpi_y * 72.0));

    let layout = pango::Layout::new(&pango_context);
    layout.set_font_description(&font_desc);

    let attr_list = pango::AttrList::new();

    attr_list.insert(
        pango::Attribute::new_letter_spacing(
            to_pango_units(state::get_letter_spacing(state).normalize(draw_ctx))
        ).unwrap());

    if let Some(font_decor) = state::get_font_decor(state) {
        if font_decor.underline {
            attr_list.insert(pango::Attribute::new_underline(pango::Underline::Single)
                             .unwrap());
        }

        if font_decor.strike {
            attr_list.insert(pango::Attribute::new_strikethrough(true)
                             .unwrap());
        }
    }

    layout.set_attributes(&attr_list);

    layout.set_alignment(
        match state::get_text_dir(state) {
            pango::Direction::Ltr => pango::Alignment::Left,
            _                     => pango::Alignment::Right,
        }
    );

    layout.set_text(text);

    layout
}

#[no_mangle]
pub extern fn rsvg_text_create_layout(draw_ctx: *const RsvgDrawingCtx,
                                      text: *const libc::c_char) -> *const pango_sys::PangoLayout {
    assert!(!text.is_null());
    let s = unsafe { String::from_glib_none(text) };
    let layout = create_pango_layout(draw_ctx, &s);

    layout.to_glib_full()
}
<commit_msg>rsvg_text_create_layout(): Don't copy the incoming string<commit_after>use libc;
use glib::translate::*;
use pango::{self, ContextExt, LayoutExt};
use pango_sys;

use drawing_ctx::{self, RsvgDrawingCtx};
use state::{self, UnicodeBidi};
use util::utf8_cstr;

// FIXME: should the pango crate provide this like PANGO_GRAVITY_IS_VERTICAL() / PANGO_GRAVITY_IS_IMPROPER()?
fn gravity_is_vertical(gravity: pango::Gravity) -> bool {
    match gravity {
        pango::Gravity::East | pango::Gravity::West => true,
        _ => false
    }
}

fn to_pango_units(v: f64) -> i32 {
    (v * f64::from(pango::SCALE)) as i32
}

fn create_pango_layout(draw_ctx: *const RsvgDrawingCtx, text: &str) -> pango::Layout {
    let state = drawing_ctx::get_current_state(draw_ctx);
    let pango_context = drawing_ctx::get_pango_context(draw_ctx);

    if let Some(lang) = state::get_language(state) {
        let pango_lang = pango::Language::from_string(&lang);
        pango_context.set_language(&pango_lang);
    }

    let unicode_bidi = state::get_unicode_bidi(state);
    match unicode_bidi {
        UnicodeBidi::Override | UnicodeBidi::Embed => {
            pango_context.set_base_dir(state::get_text_dir(state));
        },

        _ => ()
    }

    let gravity = state::get_text_gravity(state);
    if gravity_is_vertical(gravity) {
        pango_context.set_base_gravity(gravity);
    }

    let mut font_desc = pango_context.get_font_description().unwrap();

    if let Some(font_family) = state::get_font_family(state) {
        font_desc.set_family(&font_family);
    }

    font_desc.set_style(state::get_font_style(state));
    font_desc.set_variant(state::get_font_variant(state));
    font_desc.set_weight(state::get_font_weight(state));
    font_desc.set_stretch(state::get_font_stretch(state));

    let (_, dpi_y) = drawing_ctx::get_dpi(draw_ctx);
    font_desc.set_size(to_pango_units(drawing_ctx::get_normalized_font_size(draw_ctx) / dpi_y * 72.0));

    let layout = pango::Layout::new(&pango_context);
    layout.set_font_description(&font_desc);

    let attr_list = pango::AttrList::new();

    attr_list.insert(
        pango::Attribute::new_letter_spacing(
            to_pango_units(state::get_letter_spacing(state).normalize(draw_ctx))
        ).unwrap());

    if let Some(font_decor) = state::get_font_decor(state) {
        if font_decor.underline {
            attr_list.insert(pango::Attribute::new_underline(pango::Underline::Single)
                             .unwrap());
        }

        if font_decor.strike {
            attr_list.insert(pango::Attribute::new_strikethrough(true)
                             .unwrap());
        }
    }

    layout.set_attributes(&attr_list);

    layout.set_alignment(
        match state::get_text_dir(state) {
            pango::Direction::Ltr => pango::Alignment::Left,
            _                     => pango::Alignment::Right,
        }
    );

    layout.set_text(text);

    layout
}

#[no_mangle]
pub extern fn rsvg_text_create_layout(draw_ctx: *const RsvgDrawingCtx,
                                      text: *const libc::c_char) -> *const pango_sys::PangoLayout {
    assert!(!text.is_null());
    let s = unsafe { utf8_cstr(text) };
    let layout = create_pango_layout(draw_ctx, s);

    layout.to_glib_full()
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::ops::{Sub, Div};
use itertools::Itertools;
use error::*;
use eval::Env;
use types::{Expr, List, Vector, Function, Lambda};
use util::*;

pub fn env<'a>() -> Env<'a> {
    let table: Vec<(&str, Lambda)> = vec![
        ("not", not),
        ("or", or),
        ("and", and),
        ("print", print),
        ("+", add),
        ("-", sub),
        ("*", mul),
        ("/", div),
        ("=", equal),
        ("<", less),
        ("<=", less_eq),
        (">", greater),
        (">=", greater_eq),
        ("first", first),
        ("rest", rest),
        ("cons", cons),
        ("exit", exit),
    ];

    let builtins = table
        .into_iter()
        .map(|(symbol, f)| {
            (
                String::from(symbol),
                Expr::from(Function::builtin(symbol, f)),
            )
        })
        .collect::<HashMap<_, _>>();

    Env::new(builtins, None)
}

fn numeric_op<F, G>(name: &str, args: &[Expr], fn_int: F, fn_flt: G) -> Result<Expr>
where
    F: Fn(&[i64]) -> Result<i64>,
    G: Fn(&[f64]) -> Result<f64>,
{
    // Check all arguments are numeric
    if args.iter().all(Expr::is_num) {
        if args.iter().any(Expr::is_flt) {
            // If any are float, promote to float
            let floats = args.iter()
                .map(|x| match x {
                    &Expr::Int(y) => y as f64,
                    &Expr::Flt(y) => y,
                    _ => unreachable!(),
                })
                .collect::<Vec<_>>();
            fn_flt(&floats).map(Expr::from)
        } else {
            // Otherwise perform integer operation
            let ints = args.iter()
                .map(|x| match x {
                    &Expr::Int(y) => y,
                    _ => unreachable!(),
                })
                .collect::<Vec<_>>();
            fn_int(&ints).map(Expr::from)
        }
    } else {
        Err(format!("#[{}] expected numeric", name).into())
    }
}

pub fn add(args: &[Expr], _env: &Env) -> Result<Expr> {
    numeric_op("+", args,
        |ints| Ok(ints.iter().sum::<i64>()),
        |floats| Ok(floats.iter().sum::<f64>())
    )
}

pub fn sub(args: &[Expr], _env: &Env) -> Result<Expr> {
    ensure_min_args("-", args, 1)?;

    // Check all arguments are numeric
    if !args.iter().all(Expr::is_num) {
        return Err("#[-] expected numeric".into());
    }

    // If one argument, negate and return
    if args.len() == 1 {
        return match args[0] {
            Expr::Int(x) => Ok(Expr::from(-x)),
            Expr::Flt(x) => Ok(Expr::from(-x)),
            _ => Err("invalid type".into())
        }
    }

    numeric_op("-", args,
        |ints| Ok(ints[1..].iter().fold(ints[0], Sub::sub)),
        |floats| Ok(floats[1..].iter().fold(floats[0], Sub::sub))
    )
}

pub fn mul(args: &[Expr], _env: &Env) -> Result<Expr> {
    numeric_op("*", args,
        |ints| Ok(ints.iter().product::<i64>()),
        |floats| Ok(floats.iter().product::<f64>())
    )
}

pub fn div(args: &[Expr], _env: &Env) -> Result<Expr> {
    ensure_min_args("[/]", args, 1)?;

    // Check all arguments are numeric
    if !args.iter().all(Expr::is_num) {
        return Err("#[-] expected numeric".into());
    }

    // If one argument, invert and return
    if args.len() == 1 {
        return match args[0] {
            Expr::Int(x) => Ok(Expr::from((x as f64).recip())),
            Expr::Flt(x) => Ok(Expr::from(x.recip())),
            _ => Err("invalid type".into())
        }
    }

    let int_div = |ints: &[i64]| {
        ints[1..].iter()
            .map(|&x| if x == 0i64 { Err("division by zero".into()) } else { Ok(x) })
            .fold_results(ints[0], Div::div)
    };

    numeric_op("/", args,
        int_div,
        |floats| Ok(floats[1..].iter().fold(floats[0], Div::div))
    )
}

pub fn equal(args: &[Expr], _env: &Env) -> Result<Expr> {
    ensure_args("[=]", args, 2)?;
    Ok(Expr::from(args[0] == args[1]))
}

pub fn less(args: &[Expr], _env: &Env) -> Result<Expr> {
    ensure_args("[<]", args, 2)?;
    match (&args[0], &args[1]) {
        (&Expr::Int(ref a), &Expr::Int(ref b)) => Ok(Expr::from(a < b)),
        (&Expr::Flt(ref a), &Expr::Flt(ref b)) => Ok(Expr::from(a < b)),
        (&Expr::Str(ref a), &Expr::Str(ref b)) => Ok(Expr::from(a < b)),
        _ => Err(
            format!("comparison undefined for: {}, {}", args[0], args[1]).into(),
        ),
    }
}

pub fn less_eq(args: &[Expr], _env: &Env) -> Result<Expr> {
    ensure_args("[<=]", args, 2)?;
    match (&args[0], &args[1]) {
        (&Expr::Int(ref a), &Expr::Int(ref b)) => Ok(Expr::from(a <= b)),
        (&Expr::Flt(ref a), &Expr::Flt(ref b)) => Ok(Expr::from(a <= b)),
        (&Expr::Str(ref a), &Expr::Str(ref b)) => Ok(Expr::from(a <= b)),
        _ => Err(
            format!("comparison undefined for: {}, {}", args[0], args[1]).into(),
        ),
    }
}

pub fn greater(args: &[Expr], _env: &Env) -> Result<Expr> {
    ensure_args("[>]", args, 2)?;
    match (&args[0], &args[1]) {
        (&Expr::Int(ref a), &Expr::Int(ref b)) => Ok(Expr::from(a > b)),
        (&Expr::Flt(ref a), &Expr::Flt(ref b)) => Ok(Expr::from(a > b)),
        (&Expr::Str(ref a), &Expr::Str(ref b)) => Ok(Expr::from(a > b)),
        _ => Err(
            format!("comparison undefined for: {}, {}", args[0], args[1]).into(),
        ),
    }
}

pub fn greater_eq(args: &[Expr], _env: &Env) -> Result<Expr> {
    ensure_args("[>=]", args, 2)?;
    match (&args[0], &args[1]) {
        (&Expr::Int(ref a), &Expr::Int(ref b)) => Ok(Expr::from(a >= b)),
        (&Expr::Flt(ref a), &Expr::Flt(ref b)) => Ok(Expr::from(a >= b)),
        (&Expr::Str(ref a), &Expr::Str(ref b)) => Ok(Expr::from(a >= b)),
        _ => Err(
            format!("comparison undefined for: {}, {}", args[0], args[1]).into(),
        ),
    }
}

pub fn not(args: &[Expr], _env: &Env) -> Result<Expr> {
    ensure_args("[not]", args, 1)?;
    Ok(Expr::from(!args[0].truthiness()))
}

// TODO: convert to special form
pub fn and(args: &[Expr], _env: &Env) -> Result<Expr> {
    args
        .into_iter()
        .map(|a| a.boolean())
        .collect::<Option<Vec<_>>>()
        .ok_or("#[and] expected boolean argument".into())
        .map(|bools| bools.iter().all(|b| *b))
        .map(Expr::from)
}

// TODO: convert to special form
pub fn or(args: &[Expr], _env: &Env) -> Result<Expr> {
    args
        .into_iter()
        .map(|a| a.boolean())
        .collect::<Option<Vec<_>>>()
        .ok_or("#[or] expected boolean argument".into())
        .map(|bools| bools.iter().any(|b| *b))
        .map(Expr::from)
}

pub fn print(args: &[Expr], _env: &Env) -> Result<Expr> {
    ensure_args("#[print]", args, 1)?;
    println!("{}", args[0]);
    Ok(Expr::Nil)
}

pub fn first(args: &[Expr], _env: &Env) -> Result<Expr> {
    ensure_args("#[first]", args, 1)?;

    match &args[0] {
        &Expr::List(ref l) => Ok(l.0.first().cloned().unwrap_or(Expr::Nil)),
        &Expr::Vector(ref q) => Ok(q.0.first().cloned().unwrap_or(Expr::Nil)),
        _ => Err("#[first] expected list".into()),
    }
}

pub fn rest(args: &[Expr], _env: &Env) -> Result<Expr> {
    match &args[0] {
        &Expr::List(ref l) => {
            Ok(
                l.0
                    .split_first()
                    .map(|(_, rest)| Expr::List(List(rest.to_vec())))
                    .unwrap_or(Expr::Nil),
            )
        }
        &Expr::Vector(ref v) => {
            Ok(
                v.0
                    .split_first()
                    .map(|(_, rest)| Expr::Vector(Vector(rest.to_vec())))
                    .unwrap_or(Expr::Nil),
            )
        }
        _ => Err("#[rest] expected list".into()),
    }
}

// (cons item seq)
pub fn cons(args: &[Expr], _env: &Env) -> Result<Expr> {
    ensure_args("cons]", args, 2)?;

    match &args[2] {
        &Expr::List(ref l) => {
            let mut new = l.clone();
            new.0.insert(0, args[1].clone());
            Ok(Expr::List(new))
        }
        &Expr::Vector(ref v) => {
            let mut new = v.clone();
            new.0.push(args[1].clone());
            Ok(Expr::Vector(new))
        }
        _ => Err("#[cons] expected list".into()),
    }
}

// (exit)
pub fn exit(_args: &[Expr], _env: &Env) -> Result<Expr> {
    Err(ErrorKind::Exit(0).into())
}
<commit_msg>Implement list fn<commit_after>use std::collections::HashMap;
use std::ops::{Sub, Div};
use itertools::Itertools;
use error::*;
use eval::Env;
use types::{Expr, List, Vector, Function, Lambda};
use util::*;

pub fn env<'a>() -> Env<'a> {
    let table: Vec<(&str, Lambda)> = vec![
        ("not", not),
        ("or", or),
        ("and", and),
        ("print", print),
        ("+", add),
        ("-", sub),
        ("*", mul),
        ("/", div),
        ("=", equal),
        ("<", less),
        ("<=", less_eq),
        (">", greater),
        (">=", greater_eq),
        ("first", first),
        ("rest", rest),
        ("cons", cons),
        ("list", list),
        ("exit", exit),
    ];

    let builtins = table
        .into_iter()
        .map(|(symbol, f)| {
            (
                String::from(symbol),
                Expr::from(Function::builtin(symbol, f)),
            )
        })
        .collect::<HashMap<_, _>>();

    Env::new(builtins, None)
}

fn numeric_op<F, G>(name: &str, args: &[Expr], fn_int: F, fn_flt: G) -> Result<Expr>
where
    F: Fn(&[i64]) -> Result<i64>,
    G: Fn(&[f64]) -> Result<f64>,
{
    // Check all arguments are numeric
    if args.iter().all(Expr::is_num) {
        if args.iter().any(Expr::is_flt) {
            // If any are float, promote to float
            let floats = args.iter()
                .map(|x| match x {
                    &Expr::Int(y) => y as f64,
                    &Expr::Flt(y) => y,
                    _ => unreachable!(),
                })
                .collect::<Vec<_>>();
            fn_flt(&floats).map(Expr::from)
        } else {
            // Otherwise perform integer operation
            let ints = args.iter()
                .map(|x| match x {
                    &Expr::Int(y) => y,
                    _ => unreachable!(),
                })
                .collect::<Vec<_>>();
            fn_int(&ints).map(Expr::from)
        }
    } else {
        Err(format!("#[{}] expected numeric", name).into())
    }
}

pub fn add(args: &[Expr], _env: &Env) -> Result<Expr> {
    numeric_op("+", args,
        |ints| Ok(ints.iter().sum::<i64>()),
        |floats| Ok(floats.iter().sum::<f64>())
    )
}

pub fn sub(args: &[Expr], _env: &Env) -> Result<Expr> {
    ensure_min_args("-", args, 1)?;

    // Check all arguments are numeric
    if !args.iter().all(Expr::is_num) {
        return Err("#[-] expected numeric".into());
    }

    // If one argument, negate and return
    if args.len() == 1 {
        return match args[0] {
            Expr::Int(x) => Ok(Expr::from(-x)),
            Expr::Flt(x) => Ok(Expr::from(-x)),
            _ => Err("invalid type".into())
        }
    }

    numeric_op("-", args,
        |ints| Ok(ints[1..].iter().fold(ints[0], Sub::sub)),
        |floats| Ok(floats[1..].iter().fold(floats[0], Sub::sub))
    )
}

pub fn mul(args: &[Expr], _env: &Env) -> Result<Expr> {
    numeric_op("*", args,
        |ints| Ok(ints.iter().product::<i64>()),
        |floats| Ok(floats.iter().product::<f64>())
    )
}

pub fn div(args: &[Expr], _env: &Env) -> Result<Expr> {
    ensure_min_args("[/]", args, 1)?;

    // Check all arguments are numeric
    if !args.iter().all(Expr::is_num) {
        return Err("#[-] expected numeric".into());
    }

    // If one argument, invert and return
    if args.len() == 1 {
        return match args[0] {
            Expr::Int(x) => Ok(Expr::from((x as f64).recip())),
            Expr::Flt(x) => Ok(Expr::from(x.recip())),
            _ => Err("invalid type".into())
        }
    }

    let int_div = |ints: &[i64]| {
        ints[1..].iter()
            .map(|&x| if x == 0i64 { Err("division by zero".into()) } else { Ok(x) })
            .fold_results(ints[0], Div::div)
    };

    numeric_op("/", args,
        int_div,
        |floats| Ok(floats[1..].iter().fold(floats[0], Div::div))
    )
}

pub fn equal(args: &[Expr], _env: &Env) -> Result<Expr> {
    ensure_args("[=]", args, 2)?;
    Ok(Expr::from(args[0] == args[1]))
}

pub fn less(args: &[Expr], _env: &Env) -> Result<Expr> {
    ensure_args("[<]", args, 2)?;
    match (&args[0], &args[1]) {
        (&Expr::Int(ref a), &Expr::Int(ref b)) => Ok(Expr::from(a < b)),
        (&Expr::Flt(ref a), &Expr::Flt(ref b)) => Ok(Expr::from(a < b)),
        (&Expr::Str(ref a), &Expr::Str(ref b)) => Ok(Expr::from(a < b)),
        _ => Err(
            format!("comparison undefined for: {}, {}", args[0], args[1]).into(),
        ),
    }
}

pub fn less_eq(args: &[Expr], _env: &Env) -> Result<Expr> {
    ensure_args("[<=]", args, 2)?;
    match (&args[0], &args[1]) {
        (&Expr::Int(ref a), &Expr::Int(ref b)) => Ok(Expr::from(a <= b)),
        (&Expr::Flt(ref a), &Expr::Flt(ref b)) => Ok(Expr::from(a <= b)),
        (&Expr::Str(ref a), &Expr::Str(ref b)) => Ok(Expr::from(a <= b)),
        _ => Err(
            format!("comparison undefined for: {}, {}", args[0], args[1]).into(),
        ),
    }
}

pub fn greater(args: &[Expr], _env: &Env) -> Result<Expr> {
    ensure_args("[>]", args, 2)?;
    match (&args[0], &args[1]) {
        (&Expr::Int(ref a), &Expr::Int(ref b)) => Ok(Expr::from(a > b)),
        (&Expr::Flt(ref a), &Expr::Flt(ref b)) => Ok(Expr::from(a > b)),
        (&Expr::Str(ref a), &Expr::Str(ref b)) => Ok(Expr::from(a > b)),
        _ => Err(
            format!("comparison undefined for: {}, {}", args[0], args[1]).into(),
        ),
    }
}

pub fn greater_eq(args: &[Expr], _env: &Env) -> Result<Expr> {
    ensure_args("[>=]", args, 2)?;
    match (&args[0], &args[1]) {
        (&Expr::Int(ref a), &Expr::Int(ref b)) => Ok(Expr::from(a >= b)),
        (&Expr::Flt(ref a), &Expr::Flt(ref b)) => Ok(Expr::from(a >= b)),
        (&Expr::Str(ref a), &Expr::Str(ref b)) => Ok(Expr::from(a >= b)),
        _ => Err(
            format!("comparison undefined for: {}, {}", args[0], args[1]).into(),
        ),
    }
}

pub fn not(args: &[Expr], _env: &Env) -> Result<Expr> {
    ensure_args("[not]", args, 1)?;
    Ok(Expr::from(!args[0].truthiness()))
}

// TODO: convert to special form
pub fn and(args: &[Expr], _env: &Env) -> Result<Expr> {
    args
        .into_iter()
        .map(|a| a.boolean())
        .collect::<Option<Vec<_>>>()
        .ok_or("#[and] expected boolean argument".into())
        .map(|bools| bools.iter().all(|b| *b))
        .map(Expr::from)
}

// TODO: convert to special form
pub fn or(args: &[Expr], _env: &Env) -> Result<Expr> {
    args
        .into_iter()
        .map(|a| a.boolean())
        .collect::<Option<Vec<_>>>()
        .ok_or("#[or] expected boolean argument".into())
        .map(|bools| bools.iter().any(|b| *b))
        .map(Expr::from)
}

pub fn print(args: &[Expr], _env: &Env) -> Result<Expr> {
    ensure_args("#[print]", args, 1)?;
    println!("{}", args[0]);
    Ok(Expr::Nil)
}

pub fn first(args: &[Expr], _env: &Env) -> Result<Expr> {
    ensure_args("#[first]", args, 1)?;

    match &args[0] {
        &Expr::List(ref l) => Ok(l.0.first().cloned().unwrap_or(Expr::Nil)),
        &Expr::Vector(ref q) => Ok(q.0.first().cloned().unwrap_or(Expr::Nil)),
        _ => Err("#[first] expected list".into()),
    }
}

pub fn rest(args: &[Expr], _env: &Env) -> Result<Expr> {
    match &args[0] {
        &Expr::List(ref l) => {
            Ok(
                l.0
                    .split_first()
                    .map(|(_, rest)| Expr::List(List(rest.to_vec())))
                    .unwrap_or(Expr::Nil),
            )
        }
        &Expr::Vector(ref v) => {
            Ok(
                v.0
                    .split_first()
                    .map(|(_, rest)| Expr::Vector(Vector(rest.to_vec())))
                    .unwrap_or(Expr::Nil),
            )
        }
        _ => Err("#[rest] expected list".into()),
    }
}

// (cons item seq)
pub fn cons(args: &[Expr], _env: &Env) -> Result<Expr> {
    ensure_args("cons]", args, 2)?;

    match &args[2] {
        &Expr::List(ref l) => {
            let mut new = l.clone();
            new.0.insert(0, args[1].clone());
            Ok(Expr::List(new))
        }
        &Expr::Vector(ref v) => {
            let mut new = v.clone();
            new.0.push(args[1].clone());
            Ok(Expr::Vector(new))
        }
        _ => Err("#[cons] expected list".into()),
    }
}

pub fn list(args: &[Expr], _env: &Env) -> Result<Expr> {
    Ok(Expr::List(List(args.to_vec())))
}

// (exit)
pub fn exit(_args: &[Expr], _env: &Env) -> Result<Expr> {
    Err(ErrorKind::Exit(0).into())
}
<|endoftext|>


<commit_before>use std::fs;
use std::fs::File;
use std::sync::mpsc;
use std::thread;
use regex::Regex;

const STATS: Vec<String> = vec![
    String::from("cpu.shares"),
    String::from("cpu.cfs_period_us"),
    String::from("cpu.rt_period_us"),
    String::from("cpu.rt_runtime_us"),
    String::from("cpuacct.usage"),
    String::from("cpuacct.usage_percpu"),
    String::from("memory.failcnt"),
    String::from("memory.limit_in_bytes"),
    String::from("memory.max_usage_in_bytes"),
    String::from("memory.move_charge_at_immigrate"),
    String::from("memory.pressure_level"),
    String::from("memory.swappiness"),
    String::from("memory.usage_in_bytes"),
    String::from("blkio.io_merged"),
    String::from("blkio.io_queued"),
    String::from("blkio.io_service_bytes"),
    String::from("blkio.io_service_time"),
    String::from("blkio.io_wait_time"),
    String::from("blkio.io_time"),
    String::from("net_cls.classid"),
    String::from("net_prio.ifpriomap"),
    String::from("net_prio.prioidx"),
];

trait CGroup_Reader {
    fn read(&self, stat: String) -> String;
}

fn which_cgroup(pid: u32) -> Box<Fn(String) -> String> {
    use std::fs;
    use std::fs::File;
    let path = format!("/proc/{}/cgroup", pid);
    let mut cgroup_f = File::open(path).unwrap();
    let mut buffer = String::new();
    cgroup_f.read_to_string(&mut buffer);
    Box::new(move |resource| {
        let mut r_cnt = 0;
        let mut begin = -1;
        let mut end = -1;
        let mut colon_cnt = 0;
        for (c, i) in buffer {
            if c == ':' {
                colon_cnt += 1;
            } else if begin > 0 && end < 0 && c == '\n'{
                end = i;
            } else if colon_cnt == 1 {
                if resource[r_cnt] == c {
                    r_cnt += 1;
                } else if r_cnt > 0 && r_cnt + 1 < resource.capacity() {
                    continue;
                }
            } else {
                if begin < 0 {
                    begin = i + 1;
                }
            }
        }
        buffer[begin..end]
    })
}

fn read_cgroup(resource: String, name: String, stat: String) -> String {
    let path = format!("/sys/fs/cgroup/{}/{}/{}", resource, name, stat);
    let mut stat_f = try!(fs::File::open(path));
    let mut buffer = String::new();
    try!(stat_f.read_to_string(&mut buffer));
    return buffer;
}

struct CPU_Reader {
    name: String,
    pid: u32,
}

impl CGroup_Reader for CPU_Reader {
    fn read(&self, stat: String) -> String {
        return read_cgroup("cpu,cpuacct", self.name, stat);
    }
}

struct Mem_Reader {
    name: String,
    pid: u32,
}

impl CGroup_Reader for Mem_Reader {
    fn read(&self, stat: String) -> String {
        return read_cgroup("memory", self.name, stat);
    }
}

struct BLKIO_Reader {
    name: String,
    pid: u32,
}

impl CGroup_Reader for BLKIO_Reader {
    fn read(&self, stat: String) -> String {
        return read_cgroup("blkio", self.name, stat);
    }
}

struct Net_Reader {
    name: String,
    pid: u32,
}

impl CGroup_Reader for Net_Reader {
    fn read(&self, stat: String) -> String {
        return read_cgroup("net_cls,net_prio", self.name, stat);
    }
}

pub struct Reader {
    cpu: CPU_Reader,
    mem: Mem_Reader,
    blkio: BLKIO_Reader,
    net: Net_Reader,
}

pub type CGroup_Stat = (String, String);

impl Reader {
    fn read_res(&self, res: String, tx: mpsc::Sender<String>) {
        let ctx = self;
        thread::spawn(|| {
            let shares;
            let cpu_re = Regex::new(r"^cpu(.*)").unwrap();
            let mem_re = Regex::new(r"^mem(.*)").unwrap();
            let blkio_re = Regex::new(r"^mem(.*)").unwrap();
            let net_re = Regex::new(r"^net(.*)").unwrap();
            if cpu_re.is_match(res) {
                shares = ctx.cpu.read(res);
            } else if mem_re.is_match(res) {
                shares = ctx.mem.read(res);
            } else if blkio_re.is_match(res) {
                shares = ctx.blkio.read(res);
            } else {
                shares = ctx.net.read(res);
            }
            tx.send(shares).unwrap();
        })
    }
    fn read(&self) -> Vec<CGroup_Stat> {
        let stats = Vec::<CGroup_Stat>::new();
        let (tx, rx): (mpsc::Sender<String>, mpsc::Receiver<String>) = mpsc::channel();
        for stat in STATS {
            self.read_res(stat, tx);
        }
        for _ in STATS {
            stats.push(rx.recv().unwrap());
        }
        return stats;
    }
}

pub fn new(pid: u32) -> Reader {
    let name = which_cgroup(pid);
    return Reader{
        cpu: CPU_Reader{
            name: name("cpu"),
            pid: pid,
        },
        mem: Mem_Reader{
            name: name("memory"),
            pid: pid,
        },
        blkio: BLKIO_Reader{
            name: name("blkio"),
            pid: pid,
        },
        net: Net_Reader{
            name: name("net_cls"),
            pid: pid,
        },
    };
}
<commit_msg>WIP fix string related compiling issues<commit_after>use std::fs;
use std::fs::File;
use std::io::Read;
use std::sync::mpsc;
use std::thread;
use regex::Regex;

const STATS: Vec<String> = vec![
    String::from("cpu.shares"),
    String::from("cpu.cfs_period_us"),
    String::from("cpu.rt_period_us"),
    String::from("cpu.rt_runtime_us"),
    String::from("cpuacct.usage"),
    String::from("cpuacct.usage_percpu"),
    String::from("memory.failcnt"),
    String::from("memory.limit_in_bytes"),
    String::from("memory.max_usage_in_bytes"),
    String::from("memory.move_charge_at_immigrate"),
    String::from("memory.pressure_level"),
    String::from("memory.swappiness"),
    String::from("memory.usage_in_bytes"),
    String::from("blkio.io_merged"),
    String::from("blkio.io_queued"),
    String::from("blkio.io_service_bytes"),
    String::from("blkio.io_service_time"),
    String::from("blkio.io_wait_time"),
    String::from("blkio.io_time"),
    String::from("net_cls.classid"),
    String::from("net_prio.ifpriomap"),
    String::from("net_prio.prioidx"),
];

trait CGroup_Reader {
    fn read(&self, stat: &str) -> String;
}

fn which_cgroup(pid: u32) -> Box<Fn(String) -> String> {
    use std::fs;
    use std::fs::File;
    let path = format!("/proc/{}/cgroup", pid);
    let mut cgroup_f = File::open(path).unwrap();
    let mut buffer = String::new();
    cgroup_f.read_to_string(&mut buffer);
    Box::new(move |resource| {
        let mut r_cnt = 0;
        let mut begin = -1;
        let mut end = -1;
        let mut colon_cnt = 0;
        for (i, c) in buffer.chars().enumerate() {
            if c == ':' {
                colon_cnt += 1;
            } else if begin > 0 && end < 0 && c == '\n'{
                end = i;
            } else if colon_cnt == 1 {
                let res = resource.chars();
                if res.nth(r_cnt).unwrap() == c {
                    r_cnt += 1;
                } else if r_cnt > 0 && r_cnt + 1 < resource.capacity() {
                    continue;
                }
            } else {
                if begin < 0 {
                    begin = i + 1;
                }
            }
        }
        buffer[begin..end].to_string()
    })
}

fn read_cgroup(resource: String, name: String, stat: &str) -> String {
    let path = format!("/sys/fs/cgroup/{}/{}/{}", resource, name, stat);
    let mut stat_f = fs::File::open(path).unwrap();
    let mut buffer = String::new();
    stat_f.read_to_string(&mut buffer);
    buffer
}

struct CPU_Reader {
    name: String,
    pid: u32,
}

impl CGroup_Reader for CPU_Reader {
    fn read(&self, stat: &str) -> String {
        read_cgroup(String::from("cpu,cpuacct"), self.name, stat);
    }
}

struct Mem_Reader {
    name: String,
    pid: u32,
}

impl CGroup_Reader for Mem_Reader {
    fn read(&self, stat: &str) -> String {
        return read_cgroup(String::from("memory"), self.name, stat);
    }
}

struct BLKIO_Reader {
    name: String,
    pid: u32,
}

impl CGroup_Reader for BLKIO_Reader {
    fn read(&self, stat: &str) -> String {
        return read_cgroup(String::from("blkio"), self.name, stat);
    }
}

struct Net_Reader {
    name: String,
    pid: u32,
}

impl CGroup_Reader for Net_Reader {
    fn read(&self, stat: &str) -> String {
        return read_cgroup(String::from("net_cls,net_prio"), self.name, stat);
    }
}

pub struct Reader {
    cpu: CPU_Reader,
    mem: Mem_Reader,
    blkio: BLKIO_Reader,
    net: Net_Reader,
}

pub type CGroup_Stat = (String, String);

impl Reader {
    fn read_res(&self, res: &str, tx: mpsc::Sender<String>) {
        let ctx = self;
        thread::spawn(|| {
            let shares;
            let cpu_re = Regex::new(r"^cpu(.*)").unwrap();
            let mem_re = Regex::new(r"^mem(.*)").unwrap();
            let blkio_re = Regex::new(r"^mem(.*)").unwrap();
            let net_re = Regex::new(r"^net(.*)").unwrap();
            if cpu_re.is_match(res) {
                shares = ctx.cpu.read(res);
            } else if mem_re.is_match(res) {
                shares = ctx.mem.read(res);
            } else if blkio_re.is_match(res) {
                shares = ctx.blkio.read(res);
            } else {
                shares = ctx.net.read(res);
            }
            tx.send(shares).unwrap();
        })
    }
    fn read(&self) -> Vec<CGroup_Stat> {
        let stats = Vec::<CGroup_Stat>::new();
        let (tx, rx): (mpsc::Sender<String>, mpsc::Receiver<String>) = mpsc::channel();
        for stat in STATS {
            self.read_res(stat.as_str(), tx);
        }
        for _ in STATS {
            stats.push(rx.recv().unwrap());
        }
        return stats;
    }
}

pub fn new(pid: u32) -> Reader {
    let name = which_cgroup(pid);
    return Reader{
        cpu: CPU_Reader{
            name: name("cpu"),
            pid: pid,
        },
        mem: Mem_Reader{
            name: name("memory"),
            pid: pid,
        },
        blkio: BLKIO_Reader{
            name: name("blkio"),
            pid: pid,
        },
        net: Net_Reader{
            name: name("net_cls"),
            pid: pid,
        },
    };
}
<|endoftext|>


<commit_before>#![crate_name = "oxcable"]

pub mod adsr;
pub mod components;
pub mod delay;
pub mod dynamics;
pub mod filters;
pub mod init;
pub mod instruments;
pub mod io;
pub mod mixers;
pub mod oscillator;
pub mod reverb;
pub mod types;
pub mod utils;
<commit_msg>Silence stability warnings for now<commit_after>#![crate_name = "oxcable"]

#![feature(collections)]
#![feature(core)]
#![feature(io)]
#![feature(path)]
#![feature(test)]

pub mod adsr;
pub mod components;
pub mod delay;
pub mod dynamics;
pub mod filters;
pub mod init;
pub mod instruments;
pub mod io;
pub mod mixers;
pub mod oscillator;
pub mod reverb;
pub mod types;
pub mod utils;
<|endoftext|>


<commit_before>use std::{ u32 };

use store::Store;
use store::Store::{ Array, Bitmap };

#[deriving(PartialEq)]
pub struct Container {
    key: u16,
    len: u16,
    store: Store,
}

impl Container {
    pub fn new(key: u16) -> Container {
        Container {
            key: key,
            len: 0,
            store: Array(Vec::new()),
        }
    }
}

impl Container {
    #[inline]
    pub fn key(&self) -> u16 { self.key }

    #[inline]
    pub fn len(&self) -> u16 { self.len }

    #[inline]
    pub fn insert(&mut self, index: u16) -> bool {
        if self.store.insert(index) {
            self.len += 1;
            if self.len == 4097 {
                self.store = self.store.to_bitmap();
            }
            true
        } else {
            false
        }
    }

    #[inline]
    pub fn remove(&mut self, index: u16) -> bool {
        if self.store.remove(index) {
            self.len -= 1;
            if self.len == 4096 {
                self.store = self.store.to_array();
            }
            true
        } else {
            false
        }
    }

    #[inline]
    pub fn contains(&self, index: u16) -> bool {
        self.store.contains(index)
    }

    #[inline]
    pub fn iter<'a>(&'a self) -> Box<Iterator<u16> + 'a> {
        match self.store {
            Array(ref vec) => box vec.iter().map(|x| *x),
            _ => panic!("↓ causes the compiler to do something stupid"),
            // Bitmap(ref bits) => box BitmapIter::new(bits),
        }
    }

    #[inline]
    pub fn is_disjoint(&self, other: &Self) -> bool {
        self.store.is_disjoint(&other.store)
    }

    #[inline]
    pub fn is_subset(&self, other: &Self) -> bool {
        if self.len > other.len {
            false
        } else {
            self.store.is_subset(&other.store)
        }
    }

    #[inline]
    pub fn union_with(&mut self, other: &Self) {
        self.store.union_with(&other.store);
        self.len = self.store.len();
    }

    #[inline]
    pub fn min(&self) -> u16 {
        self.store.min()
    }

    #[inline]
    pub fn max(&self) -> u16 {
        self.store.max()
    }
}

struct BitmapIter<'a> {
    key: uint,
    bit: uint,
    bits: &'a [u32; 2048],
}

impl<'a> BitmapIter<'a> {
    fn new(bits: &'a [u32; 2048]) -> BitmapIter<'a> {
        BitmapIter {
            key: 0,
            bit: 0,
            bits: bits,
        }
    }
}

impl<'a> Iterator<u16> for BitmapIter<'a> {
    fn next(&mut self) -> Option<u16> {
        loop {
            if self.key == 2049 {
                break;
            }
            self.bit += 1;
            if self.bit == u32::BITS {
                self.bit = 0;
                self.key += 1;
            }
            if self.key == 2048 {
                break;
            }
            if (self.bits[self.key] & (1 << self.bit)) != 0 {
                break;
            }
        }
        if self.key == 2049 {
            None
        } else {
            Some((self.key * u32::BITS + self.bit) as u16)
        }
    }
}
<commit_msg>Revert to failing implementation<commit_after>use std::{ u32 };

use store::Store;
use store::Store::{ Array, Bitmap };

#[deriving(PartialEq)]
pub struct Container {
    key: u16,
    len: u16,
    store: Store,
}

impl Container {
    pub fn new(key: u16) -> Container {
        Container {
            key: key,
            len: 0,
            store: Array(Vec::new()),
        }
    }
}

impl Container {
    #[inline]
    pub fn key(&self) -> u16 { self.key }

    #[inline]
    pub fn len(&self) -> u16 { self.len }

    #[inline]
    pub fn insert(&mut self, index: u16) -> bool {
        if self.store.insert(index) {
            self.len += 1;
            if self.len == 4097 {
                self.store = self.store.to_bitmap();
            }
            true
        } else {
            false
        }
    }

    #[inline]
    pub fn remove(&mut self, index: u16) -> bool {
        if self.store.remove(index) {
            self.len -= 1;
            if self.len == 4096 {
                self.store = self.store.to_array();
            }
            true
        } else {
            false
        }
    }

    #[inline]
    pub fn contains(&self, index: u16) -> bool {
        self.store.contains(index)
    }

    #[inline]
    pub fn iter<'a>(&'a self) -> Box<Iterator<u16> + 'a> {
        match self.store {
            Array(ref vec) => box vec.iter().map(|x| *x),
            Bitmap(ref bits) => box BitmapIter::new(bits),
        }
    }

    #[inline]
    pub fn is_disjoint(&self, other: &Self) -> bool {
        self.store.is_disjoint(&other.store)
    }

    #[inline]
    pub fn is_subset(&self, other: &Self) -> bool {
        if self.len > other.len {
            false
        } else {
            self.store.is_subset(&other.store)
        }
    }

    #[inline]
    pub fn union_with(&mut self, other: &Self) {
        self.store.union_with(&other.store);
        self.len = self.store.len();
    }

    #[inline]
    pub fn min(&self) -> u16 {
        self.store.min()
    }

    #[inline]
    pub fn max(&self) -> u16 {
        self.store.max()
    }
}

struct BitmapIter<'a> {
    key: uint,
    bit: uint,
    bits: &'a [u32; 2048],
}

impl<'a> BitmapIter<'a> {
    fn new(bits: &'a [u32; 2048]) -> BitmapIter<'a> {
        BitmapIter {
            key: 0,
            bit: 0,
            bits: bits,
        }
    }
}

impl<'a> Iterator<u16> for BitmapIter<'a> {
    fn next(&mut self) -> Option<u16> {
        loop {
            if self.key == 2049 {
                break;
            }
            self.bit += 1;
            if self.bit == u32::BITS {
                self.bit = 0;
                self.key += 1;
            }
            if self.key == 2048 {
                break;
            }
            if (self.bits[self.key] & (1 << self.bit)) != 0 {
                break;
            }
        }
        if self.key == 2049 {
            None
        } else {
            Some((self.key * u32::BITS + self.bit) as u16)
        }
    }
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::path::{Path, PathBuf};
use std::io::{SeekFrom, Seek};
use std::io::{Write, Read};

use super::{Page, PAGE_SIZE, PageError};

// on disk storage will have to be broken into segments.
// a segment will be a fixed number of pages
#[derive(Debug)]
pub struct Segment {
    fp: File,
    meta: File,
    pub pages: usize,
    row_offsets: Vec<usize>, // index is the page index of the segment value is the first id
    start_page: u64, // offset.  page 0 in first segment is 0.

}
#[derive(Debug)]
pub enum SegmentError {
    FlushFailure,
    PageNotFound,
    UnknownError,
}

// TODO fix this up a bit
impl From<PageError> for SegmentError {
    fn from(err: PageError) -> SegmentError {
        match err {
            PageError::Full =>
                SegmentError::PageNotFound,
            PageError::NotFound =>
                SegmentError::PageNotFound,
        }
    }
}

type SegmentResult<T> = Result<T, SegmentError>;

impl Segment {

    pub fn new(location: &Path, num: u64, start_page: u64) -> SegmentResult<Segment> {
        let name = format!("segment-{}.data", num);
        let seg_path = location.join(name);

        let name = format!("segment-{}.meta", num);
        let meta_path = location.join(name);

        info!("Creating segment at: {:?}", seg_path);

        let fp = File::create(seg_path).expect("Could not created segment");
        let meta = File::create(meta_path).expect("Could not created segment metadata");

        Ok(Segment{fp: fp, pages: 0, meta: meta,
                   row_offsets: Vec::new(),
                   start_page: start_page})
    }

    pub fn write(&mut self, data: &Page) -> SegmentResult<()> {
        // append a page to the current segment
        // job of the Disk storage to flush when ready
        // seek to the end of the segment
        self.fp.seek(SeekFrom::End(0));
        self.fp.write(&data.to_bytes()).expect("Write failed");
        self.fp.flush();
        self.pages += 1;
        Ok(())
    }

    fn read_page(&mut self, page: u64) -> SegmentResult<Page> {
        let p = page - self.start_page;
        let offset = p * PAGE_SIZE as u64;
        self.fp.seek(SeekFrom::Start(offset));

        let mut data : Vec<u8> = Vec::new();
        self.fp.read(&mut data);

        let page = Page::from_bytes(data)?;
        Ok(page)

    }
}

#[cfg(test)]
mod segment_tests {
    use tempdir::TempDir;
    use super::Segment;
    use super::Page;

    #[test]
    fn test_normal_segment_usage() {
        let dir = TempDir::new("total_recall_segments").expect("Couldn't make a temp dir");
        let mut segment = Segment::new(dir.path(), 0, 0).expect("Could not create segment");

        let mut page = Page::new();
        let data: [u8; 1024] = [1; 1024];
        page.write(&data);
        segment.write(&page);

        dir.into_path();

        segment.read_page(0).expect("Page should be OK");

    }
}<commit_msg>comments are cool<commit_after>use std::fs::File;
use std::path::{Path, PathBuf};
use std::io::{SeekFrom, Seek};
use std::io::{Write, Read};

use super::{Page, PAGE_SIZE, PageError};

/// Segments are a bunch of of Pages organized into files
/// A segment might be a few hundred (or thousand pages)
/// Currently each segment has 2 files, a data file and metadata

// on disk storage will have to be broken into segments.
// a segment will be a fixed number of pages
#[derive(Debug)]
pub struct Segment {
    fp: File,
    meta: File,
    pub pages: usize,
    row_offsets: Vec<usize>, // index is the page index of the segment value is the first id
    start_page: u64, // offset.  page 0 in first segment is 0.

}
#[derive(Debug)]
pub enum SegmentError {
    FlushFailure,
    PageNotFound,
    UnknownError,
}

// TODO fix this up a bit
impl From<PageError> for SegmentError {
    fn from(err: PageError) -> SegmentError {
        match err {
            PageError::Full =>
                SegmentError::PageNotFound,
            PageError::NotFound =>
                SegmentError::PageNotFound,
        }
    }
}

type SegmentResult<T> = Result<T, SegmentError>;

impl Segment {

    pub fn new(location: &Path, num: u64, start_page: u64) -> SegmentResult<Segment> {
        let name = format!("segment-{}.data", num);
        let seg_path = location.join(name);

        let name = format!("segment-{}.meta", num);
        let meta_path = location.join(name);

        info!("Creating segment at: {:?}", seg_path);

        let fp = File::create(seg_path).expect("Could not created segment");
        let meta = File::create(meta_path).expect("Could not created segment metadata");

        Ok(Segment{fp: fp, pages: 0, meta: meta,
                   row_offsets: Vec::new(),
                   start_page: start_page})
    }

    pub fn write(&mut self, data: &Page) -> SegmentResult<()> {
        // append a page to the current segment
        // job of the Disk storage to flush when ready
        // seek to the end of the segment
        self.fp.seek(SeekFrom::End(0));
        self.fp.write(&data.to_bytes()).expect("Write failed");
        self.fp.flush();
        self.pages += 1;
        Ok(())
    }

    fn read_page(&mut self, page: u64) -> SegmentResult<Page> {
        let p = page - self.start_page;
        let offset = p * PAGE_SIZE as u64;
        self.fp.seek(SeekFrom::Start(offset));

        let mut data : Vec<u8> = Vec::new();
        self.fp.read(&mut data);

        let page = Page::from_bytes(data)?;
        Ok(page)

    }
}

#[cfg(test)]
mod segment_tests {
    use tempdir::TempDir;
    use super::Segment;
    use super::Page;

    #[test]
    fn test_normal_segment_usage() {
        let dir = TempDir::new("total_recall_segments").expect("Couldn't make a temp dir");
        let mut segment = Segment::new(dir.path(), 0, 0).expect("Could not create segment");

        let mut page = Page::new();
        let data: [u8; 1024] = [1; 1024];
        page.write(&data);
        segment.write(&page);

        dir.into_path();

        segment.read_page(0).expect("Page should be OK");

    }
}<|endoftext|>


<commit_before>use fallible_iterator::FallibleIterator;
use fallible_streaming_iterator::FallibleStreamingIterator;
use std::{convert, result};

use super::{Error, Result, Statement};
use crate::types::{FromSql, FromSqlError, ValueRef};

/// An handle for the resulting rows of a query.
pub struct Rows<'stmt> {
    pub(crate) stmt: Option<&'stmt Statement<'stmt>>,
    row: Option<Row<'stmt>>,
}

impl<'stmt> Rows<'stmt> {
    fn reset(&mut self) {
        if let Some(stmt) = self.stmt.take() {
            stmt.reset();
        }
    }

    /// Attempt to get the next row from the query. Returns `Ok(Some(Row))` if
    /// there is another row, `Err(...)` if there was an error
    /// getting the next row, and `Ok(None)` if all rows have been retrieved.
    ///
    /// ## Note
    ///
    /// This interface is not compatible with Rust's `Iterator` trait, because
    /// the lifetime of the returned row is tied to the lifetime of `self`.
    /// This is a fallible "streaming iterator". For a more natural interface,
    /// consider using `query_map` or `query_and_then` instead, which
    /// return types that implement `Iterator`.
    #[allow(clippy::should_implement_trait)] // cannot implement Iterator
    pub fn next(&mut self) -> Result<Option<&Row<'stmt>>> {
        self.advance()?;
        Ok((*self).get())
    }

    pub fn map<F, B>(self, f: F) -> Map<'stmt, F>
    where
        F: FnMut(&Row<'_>) -> Result<B>,
    {
        Map { rows: self, f }
    }
}

impl<'stmt> Rows<'stmt> {
    pub(crate) fn new(stmt: &'stmt Statement<'stmt>) -> Rows<'stmt> {
        Rows {
            stmt: Some(stmt),
            row: None,
        }
    }

    pub(crate) fn get_expected_row(&mut self) -> Result<&Row<'stmt>> {
        match self.next()? {
            Some(row) => Ok(row),
            None => Err(Error::QueryReturnedNoRows),
        }
    }
}

impl Drop for Rows<'_> {
    fn drop(&mut self) {
        self.reset();
    }
}

pub struct Map<'stmt, F> {
    rows: Rows<'stmt>,
    f: F,
}

impl<F, B> FallibleIterator for Map<'_, F>
where
    F: FnMut(&Row<'_>) -> Result<B>,
{
    type Error = Error;
    type Item = B;

    fn next(&mut self) -> Result<Option<B>> {
        match self.rows.next()? {
            Some(v) => Ok(Some((self.f)(v)?)),
            None => Ok(None),
        }
    }
}

/// An iterator over the mapped resulting rows of a query.
pub struct MappedRows<'stmt, F> {
    rows: Rows<'stmt>,
    map: F,
}

impl<'stmt, T, F> MappedRows<'stmt, F>
where
    F: FnMut(&Row<'_>) -> Result<T>,
{
    pub(crate) fn new(rows: Rows<'stmt>, f: F) -> MappedRows<'stmt, F> {
        MappedRows { rows, map: f }
    }
}

impl<T, F> Iterator for MappedRows<'_, F>
where
    F: FnMut(&Row<'_>) -> Result<T>,
{
    type Item = Result<T>;

    fn next(&mut self) -> Option<Result<T>> {
        let map = &mut self.map;
        self.rows
            .next()
            .transpose()
            .map(|row_result| row_result.and_then(|row| (map)(&row)))
    }
}

/// An iterator over the mapped resulting rows of a query, with an Error type
/// unifying with Error.
pub struct AndThenRows<'stmt, F> {
    rows: Rows<'stmt>,
    map: F,
}

impl<'stmt, T, E, F> AndThenRows<'stmt, F>
where
    F: FnMut(&Row<'_>) -> result::Result<T, E>,
{
    pub(crate) fn new(rows: Rows<'stmt>, f: F) -> AndThenRows<'stmt, F> {
        AndThenRows { rows, map: f }
    }
}

impl<T, E, F> Iterator for AndThenRows<'_, F>
where
    E: convert::From<Error>,
    F: FnMut(&Row<'_>) -> result::Result<T, E>,
{
    type Item = result::Result<T, E>;

    fn next(&mut self) -> Option<Self::Item> {
        let map = &mut self.map;
        self.rows
            .next()
            .transpose()
            .map(|row_result| row_result.map_err(E::from).and_then(|row| (map)(&row)))
    }
}

impl<'stmt> FallibleStreamingIterator for Rows<'stmt> {
    type Error = Error;
    type Item = Row<'stmt>;

    fn advance(&mut self) -> Result<()> {
        match self.stmt {
            Some(ref stmt) => match stmt.step() {
                Ok(true) => {
                    self.row = Some(Row { stmt });
                    Ok(())
                }
                Ok(false) => {
                    self.reset();
                    self.row = None;
                    Ok(())
                }
                Err(e) => {
                    self.reset();
                    self.row = None;
                    Err(e)
                }
            },
            None => {
                self.row = None;
                Ok(())
            }
        }
    }

    fn get(&self) -> Option<&Row<'stmt>> {
        self.row.as_ref()
    }
}

/// A single result row of a query.
pub struct Row<'stmt> {
    pub(crate) stmt: &'stmt Statement<'stmt>,
}

impl<'stmt> Row<'stmt> {
    /// Get the value of a particular column of the result row.
    ///
    /// ## Failure
    ///
    /// Panics if calling `row.get(idx)` would return an error,
    /// including:
    ///
    /// * If the underlying SQLite column type is not a valid type as a source
    ///   for `T`
    /// * If the underlying SQLite integral value is outside the range
    ///   representable by `T`
    /// * If `idx` is outside the range of columns in the returned query
    pub fn get_unwrap<I: RowIndex, T: FromSql>(&self, idx: I) -> T {
        self.get(idx).unwrap()
    }

    /// Get the value of a particular column of the result row.
    ///
    /// ## Failure
    ///
    /// Returns an `Error::InvalidColumnType` if the underlying SQLite column
    /// type is not a valid type as a source for `T`.
    ///
    /// Returns an `Error::InvalidColumnIndex` if `idx` is outside the valid
    /// column range for this row.
    ///
    /// Returns an `Error::InvalidColumnName` if `idx` is not a valid column
    /// name for this row.
    ///
    /// If the result type is i128 (which requires the `i128_blob` feature to be
    /// enabled), and the underlying SQLite column is a blob whose size is not
    /// 16 bytes, `Error::InvalidColumnType` will also be returned.
    pub fn get<I: RowIndex, T: FromSql>(&self, idx: I) -> Result<T> {
        let idx = idx.idx(self.stmt)?;
        let value = self.stmt.value_ref(idx);
        FromSql::column_result(value).map_err(|err| match err {
            FromSqlError::InvalidType => Error::InvalidColumnType(
                idx,
                self.stmt.column_name_unwrap(idx).into(),
                value.data_type(),
            ),
            FromSqlError::OutOfRange(i) => Error::IntegralValueOutOfRange(idx, i),
            FromSqlError::Other(err) => {
                Error::FromSqlConversionFailure(idx as usize, value.data_type(), err)
            }
            #[cfg(feature = "i128_blob")]
            FromSqlError::InvalidI128Size(_) => Error::InvalidColumnType(
                idx,
                self.stmt.column_name_unwrap(idx).into(),
                value.data_type(),
            ),
            #[cfg(feature = "uuid")]
            FromSqlError::InvalidUuidSize(_) => Error::InvalidColumnType(
                idx,
                self.stmt.column_name_unwrap(idx).into(),
                value.data_type(),
            ),
        })
    }

    /// Get the value of a particular column of the result row as a `ValueRef`,
    /// allowing data to be read out of a row without copying.
    ///
    /// This `ValueRef` is valid only as long as this Row, which is enforced by
    /// it's lifetime. This means that while this method is completely safe,
    /// it can be somewhat difficult to use, and most callers will be better
    /// served by `get` or `get`.
    ///
    /// ## Failure
    ///
    /// Returns an `Error::InvalidColumnIndex` if `idx` is outside the valid
    /// column range for this row.
    ///
    /// Returns an `Error::InvalidColumnName` if `idx` is not a valid column
    /// name for this row.
    pub fn get_raw_checked<I: RowIndex>(&self, idx: I) -> Result<ValueRef<'_>> {
        let idx = idx.idx(self.stmt)?;
        // Narrowing from `ValueRef<'stmt>` (which `self.stmt.value_ref(idx)`
        // returns) to `ValueRef<'a>` is needed because it's only valid until
        // the next call to sqlite3_step.
        let val_ref = self.stmt.value_ref(idx);
        Ok(val_ref)
    }

    /// Get the value of a particular column of the result row as a `ValueRef`,
    /// allowing data to be read out of a row without copying.
    ///
    /// This `ValueRef` is valid only as long as this Row, which is enforced by
    /// it's lifetime. This means that while this method is completely safe,
    /// it can be difficult to use, and most callers will be better served by
    /// `get` or `get`.
    ///
    /// ## Failure
    ///
    /// Panics if calling `row.get_raw_checked(idx)` would return an error,
    /// including:
    ///
    /// * If `idx` is outside the range of columns in the returned query.
    /// * If `idx` is not a valid column name for this row.
    pub fn get_raw<I: RowIndex>(&self, idx: I) -> ValueRef<'_> {
        self.get_raw_checked(idx).unwrap()
    }
}

/// A trait implemented by types that can index into columns of a row.
pub trait RowIndex {
    /// Returns the index of the appropriate column, or `None` if no such
    /// column exists.
    fn idx(&self, stmt: &Statement<'_>) -> Result<usize>;
}

impl RowIndex for usize {
    #[inline]
    fn idx(&self, stmt: &Statement<'_>) -> Result<usize> {
        if *self >= stmt.column_count() {
            Err(Error::InvalidColumnIndex(*self))
        } else {
            Ok(*self)
        }
    }
}

impl RowIndex for &'_ str {
    #[inline]
    fn idx(&self, stmt: &Statement<'_>) -> Result<usize> {
        stmt.column_index(*self)
    }
}
<commit_msg>Add `Rows::{mapped,and_then}` to get an Iterator out of a Rows i… (#676)<commit_after>use fallible_iterator::FallibleIterator;
use fallible_streaming_iterator::FallibleStreamingIterator;
use std::{convert, result};

use super::{Error, Result, Statement};
use crate::types::{FromSql, FromSqlError, ValueRef};

/// An handle for the resulting rows of a query.
pub struct Rows<'stmt> {
    pub(crate) stmt: Option<&'stmt Statement<'stmt>>,
    row: Option<Row<'stmt>>,
}

impl<'stmt> Rows<'stmt> {
    fn reset(&mut self) {
        if let Some(stmt) = self.stmt.take() {
            stmt.reset();
        }
    }

    /// Attempt to get the next row from the query. Returns `Ok(Some(Row))` if
    /// there is another row, `Err(...)` if there was an error
    /// getting the next row, and `Ok(None)` if all rows have been retrieved.
    ///
    /// ## Note
    ///
    /// This interface is not compatible with Rust's `Iterator` trait, because
    /// the lifetime of the returned row is tied to the lifetime of `self`.
    /// This is a fallible "streaming iterator". For a more natural interface,
    /// consider using `query_map` or `query_and_then` instead, which
    /// return types that implement `Iterator`.
    #[allow(clippy::should_implement_trait)] // cannot implement Iterator
    pub fn next(&mut self) -> Result<Option<&Row<'stmt>>> {
        self.advance()?;
        Ok((*self).get())
    }

    pub fn map<F, B>(self, f: F) -> Map<'stmt, F>
    where
        F: FnMut(&Row<'_>) -> Result<B>,
    {
        Map { rows: self, f }
    }

    /// Map over this `Rows`, converting it to a [`MappedRows`], which
    /// implements `Iterator`.
    pub fn mapped<F, B>(self, f: F) -> MappedRows<'stmt, F>
    where
        F: FnMut(&Row<'_>) -> Result<B>,
    {
        MappedRows { rows: self, map: f }
    }

    /// Map over this `Rows` with a fallible function, converting it to a
    /// [`AndThenRows`], which implements `Iterator` (instead of
    /// `FallibleStreamingIterator`).
    pub fn and_then<F, T, E>(self, f: F) -> AndThenRows<'stmt, F>
    where
        F: FnMut(&Row<'_>) -> result::Result<T, E>,
    {
        AndThenRows { rows: self, map: f }
    }
}

impl<'stmt> Rows<'stmt> {
    pub(crate) fn new(stmt: &'stmt Statement<'stmt>) -> Rows<'stmt> {
        Rows {
            stmt: Some(stmt),
            row: None,
        }
    }

    pub(crate) fn get_expected_row(&mut self) -> Result<&Row<'stmt>> {
        match self.next()? {
            Some(row) => Ok(row),
            None => Err(Error::QueryReturnedNoRows),
        }
    }
}

impl Drop for Rows<'_> {
    fn drop(&mut self) {
        self.reset();
    }
}

pub struct Map<'stmt, F> {
    rows: Rows<'stmt>,
    f: F,
}

impl<F, B> FallibleIterator for Map<'_, F>
where
    F: FnMut(&Row<'_>) -> Result<B>,
{
    type Error = Error;
    type Item = B;

    fn next(&mut self) -> Result<Option<B>> {
        match self.rows.next()? {
            Some(v) => Ok(Some((self.f)(v)?)),
            None => Ok(None),
        }
    }
}

/// An iterator over the mapped resulting rows of a query.
pub struct MappedRows<'stmt, F> {
    rows: Rows<'stmt>,
    map: F,
}

impl<'stmt, T, F> MappedRows<'stmt, F>
where
    F: FnMut(&Row<'_>) -> Result<T>,
{
    pub(crate) fn new(rows: Rows<'stmt>, f: F) -> MappedRows<'stmt, F> {
        MappedRows { rows, map: f }
    }
}

impl<T, F> Iterator for MappedRows<'_, F>
where
    F: FnMut(&Row<'_>) -> Result<T>,
{
    type Item = Result<T>;

    fn next(&mut self) -> Option<Result<T>> {
        let map = &mut self.map;
        self.rows
            .next()
            .transpose()
            .map(|row_result| row_result.and_then(|row| (map)(&row)))
    }
}

/// An iterator over the mapped resulting rows of a query, with an Error type
/// unifying with Error.
pub struct AndThenRows<'stmt, F> {
    rows: Rows<'stmt>,
    map: F,
}

impl<'stmt, T, E, F> AndThenRows<'stmt, F>
where
    F: FnMut(&Row<'_>) -> result::Result<T, E>,
{
    pub(crate) fn new(rows: Rows<'stmt>, f: F) -> AndThenRows<'stmt, F> {
        AndThenRows { rows, map: f }
    }
}

impl<T, E, F> Iterator for AndThenRows<'_, F>
where
    E: convert::From<Error>,
    F: FnMut(&Row<'_>) -> result::Result<T, E>,
{
    type Item = result::Result<T, E>;

    fn next(&mut self) -> Option<Self::Item> {
        let map = &mut self.map;
        self.rows
            .next()
            .transpose()
            .map(|row_result| row_result.map_err(E::from).and_then(|row| (map)(&row)))
    }
}

impl<'stmt> FallibleStreamingIterator for Rows<'stmt> {
    type Error = Error;
    type Item = Row<'stmt>;

    fn advance(&mut self) -> Result<()> {
        match self.stmt {
            Some(ref stmt) => match stmt.step() {
                Ok(true) => {
                    self.row = Some(Row { stmt });
                    Ok(())
                }
                Ok(false) => {
                    self.reset();
                    self.row = None;
                    Ok(())
                }
                Err(e) => {
                    self.reset();
                    self.row = None;
                    Err(e)
                }
            },
            None => {
                self.row = None;
                Ok(())
            }
        }
    }

    fn get(&self) -> Option<&Row<'stmt>> {
        self.row.as_ref()
    }
}

/// A single result row of a query.
pub struct Row<'stmt> {
    pub(crate) stmt: &'stmt Statement<'stmt>,
}

impl<'stmt> Row<'stmt> {
    /// Get the value of a particular column of the result row.
    ///
    /// ## Failure
    ///
    /// Panics if calling `row.get(idx)` would return an error,
    /// including:
    ///
    /// * If the underlying SQLite column type is not a valid type as a source
    ///   for `T`
    /// * If the underlying SQLite integral value is outside the range
    ///   representable by `T`
    /// * If `idx` is outside the range of columns in the returned query
    pub fn get_unwrap<I: RowIndex, T: FromSql>(&self, idx: I) -> T {
        self.get(idx).unwrap()
    }

    /// Get the value of a particular column of the result row.
    ///
    /// ## Failure
    ///
    /// Returns an `Error::InvalidColumnType` if the underlying SQLite column
    /// type is not a valid type as a source for `T`.
    ///
    /// Returns an `Error::InvalidColumnIndex` if `idx` is outside the valid
    /// column range for this row.
    ///
    /// Returns an `Error::InvalidColumnName` if `idx` is not a valid column
    /// name for this row.
    ///
    /// If the result type is i128 (which requires the `i128_blob` feature to be
    /// enabled), and the underlying SQLite column is a blob whose size is not
    /// 16 bytes, `Error::InvalidColumnType` will also be returned.
    pub fn get<I: RowIndex, T: FromSql>(&self, idx: I) -> Result<T> {
        let idx = idx.idx(self.stmt)?;
        let value = self.stmt.value_ref(idx);
        FromSql::column_result(value).map_err(|err| match err {
            FromSqlError::InvalidType => Error::InvalidColumnType(
                idx,
                self.stmt.column_name_unwrap(idx).into(),
                value.data_type(),
            ),
            FromSqlError::OutOfRange(i) => Error::IntegralValueOutOfRange(idx, i),
            FromSqlError::Other(err) => {
                Error::FromSqlConversionFailure(idx as usize, value.data_type(), err)
            }
            #[cfg(feature = "i128_blob")]
            FromSqlError::InvalidI128Size(_) => Error::InvalidColumnType(
                idx,
                self.stmt.column_name_unwrap(idx).into(),
                value.data_type(),
            ),
            #[cfg(feature = "uuid")]
            FromSqlError::InvalidUuidSize(_) => Error::InvalidColumnType(
                idx,
                self.stmt.column_name_unwrap(idx).into(),
                value.data_type(),
            ),
        })
    }

    /// Get the value of a particular column of the result row as a `ValueRef`,
    /// allowing data to be read out of a row without copying.
    ///
    /// This `ValueRef` is valid only as long as this Row, which is enforced by
    /// it's lifetime. This means that while this method is completely safe,
    /// it can be somewhat difficult to use, and most callers will be better
    /// served by `get` or `get`.
    ///
    /// ## Failure
    ///
    /// Returns an `Error::InvalidColumnIndex` if `idx` is outside the valid
    /// column range for this row.
    ///
    /// Returns an `Error::InvalidColumnName` if `idx` is not a valid column
    /// name for this row.
    pub fn get_raw_checked<I: RowIndex>(&self, idx: I) -> Result<ValueRef<'_>> {
        let idx = idx.idx(self.stmt)?;
        // Narrowing from `ValueRef<'stmt>` (which `self.stmt.value_ref(idx)`
        // returns) to `ValueRef<'a>` is needed because it's only valid until
        // the next call to sqlite3_step.
        let val_ref = self.stmt.value_ref(idx);
        Ok(val_ref)
    }

    /// Get the value of a particular column of the result row as a `ValueRef`,
    /// allowing data to be read out of a row without copying.
    ///
    /// This `ValueRef` is valid only as long as this Row, which is enforced by
    /// it's lifetime. This means that while this method is completely safe,
    /// it can be difficult to use, and most callers will be better served by
    /// `get` or `get`.
    ///
    /// ## Failure
    ///
    /// Panics if calling `row.get_raw_checked(idx)` would return an error,
    /// including:
    ///
    /// * If `idx` is outside the range of columns in the returned query.
    /// * If `idx` is not a valid column name for this row.
    pub fn get_raw<I: RowIndex>(&self, idx: I) -> ValueRef<'_> {
        self.get_raw_checked(idx).unwrap()
    }
}

/// A trait implemented by types that can index into columns of a row.
pub trait RowIndex {
    /// Returns the index of the appropriate column, or `None` if no such
    /// column exists.
    fn idx(&self, stmt: &Statement<'_>) -> Result<usize>;
}

impl RowIndex for usize {
    #[inline]
    fn idx(&self, stmt: &Statement<'_>) -> Result<usize> {
        if *self >= stmt.column_count() {
            Err(Error::InvalidColumnIndex(*self))
        } else {
            Ok(*self)
        }
    }
}

impl RowIndex for &'_ str {
    #[inline]
    fn idx(&self, stmt: &Statement<'_>) -> Result<usize> {
        stmt.column_index(*self)
    }
}
<|endoftext|>