<commit_before>use ffi::{AsRawFd, RawFd, Signal, close, SystemError, OPERATION_CANCELED, sock_error};
use core::{IoContext, AsIoContext, ThreadIoContext, TimerQueue, Perform, Expiry, Intr, UnsafeRef};

use std::mem;
use std::ptr;
use std::time::Duration;
use std::sync::Mutex;
use std::collections::{HashSet, VecDeque};
use libc::{self, EV_ADD, EV_ERROR, EV_DELETE, EV_ENABLE, EV_DISPATCH, EV_CLEAR, EVFILT_READ,
           EVFILT_WRITE, EVFILT_SIGNAL, SIG_SETMASK, sigaddset, sigprocmask, sigset_t, sigemptyset};

fn ev_set(kev: &Kevent, ident: i32, filter: i16, flags: u16) -> libc::kevent {
    libc::kevent {
        ident: ident as usize,
        filter: filter,
        flags: flags,
        fflags: 0,
        data: 0,
        udata: kev as *const _ as *mut _,
    }
}

fn dispatch_socket(kev: &libc::kevent, this: &mut ThreadIoContext) {
    let udata = unsafe { &mut *(kev.udata as *const Kevent as *mut Kevent) };
    match kev.filter {
        _ if (kev.flags & EV_ERROR) != 0 => {
            let err = sock_error(udata);
            udata.cancel_ops(this.as_ctx(), err)
        }
        EVFILT_READ => {
            if let Some(op) = udata.input.queue.pop_front() {
                udata.input.blocked = true;
                this.push(op, SystemError::default());
            }
        }
        EVFILT_WRITE => {
            if let Some(op) = udata.output.queue.pop_front() {
                udata.output.blocked = true;
                this.push(op, SystemError::default());
            }
        }
        EVFILT_SIGNAL => {
            if let Some(op) = udata.input.queue.pop_front() {
                this.push(op, SystemError::from_signal(kev.ident as i32));
            }
        }
        _ => unreachable!(),
    }
}

fn dispatch_intr(kev: &libc::kevent, _: &mut ThreadIoContext) {
    match kev.filter {
        EVFILT_READ => unsafe {
            let mut buf: [u8; 8] = mem::uninitialized();
            libc::read(kev.ident as RawFd, buf.as_mut_ptr() as *mut _, buf.len());
        },
        _ => unreachable!(""),
    }
}

#[derive(Default)]
struct Ops {
    queue: VecDeque<Box<Perform>>,
    blocked: bool,
    canceled: bool,
}

pub struct Kevent {
    fd: RawFd,
    input: Ops,
    output: Ops,
    dispatch: fn(&libc::kevent, &mut ThreadIoContext),
}

impl Kevent {
    pub fn socket(fd: RawFd) -> Self {
        Kevent {
            fd: fd,
            input: Default::default(),
            output: Default::default(),
            dispatch: dispatch_socket,
        }
    }

    pub fn signal() -> Self {
        Kevent {
            fd: -1,
            input: Ops {
                queue: Default::default(),
                blocked: true, // Always blocked
                canceled: false,
            },
            output: Default::default(),
            dispatch: dispatch_socket,
        }
    }

    pub fn intr(fd: RawFd) -> Self {
        Kevent {
            fd: fd,
            input: Default::default(),
            output: Default::default(),
            dispatch: dispatch_intr,
        }
    }
}

unsafe impl Send for Kevent {}

impl AsRawFd for Kevent {
    fn as_raw_fd(&self) -> RawFd {
        self.fd
    }
}

impl PartialEq for Kevent {
    fn eq(&self, other: &Kevent) -> bool {
        (self as *const Self) == (other as *const Self)
    }
}

impl Eq for Kevent {}

type KeventRef = UnsafeRef<Kevent>;

pub struct KqueueReactor {
    kq: RawFd,
    mutex: Mutex<HashSet<KeventRef>>,
    intr: Intr,
    sigmask: Mutex<sigset_t>,
}

impl KqueueReactor {
    pub fn new() -> Result<Self, SystemError> {
        match unsafe { libc::kqueue() } {
            -1 => Err(SystemError::last_error()),
            kq => {
                let kq = KqueueReactor {
                    kq: kq,
                    mutex: Default::default(),
                    intr: Intr::new()?,
                    sigmask: unsafe {
                        let mut sigmask = mem::uninitialized();
                        sigemptyset(&mut sigmask);
                        Mutex::new(sigmask)
                    },
                };
                Ok(kq)
            }
        }
    }

    pub fn init(&self) {
        self.intr.startup(self);
    }

    pub fn kevent(&self, kev: &[libc::kevent]) {
        unsafe {
            libc::kevent(
                self.kq,
                kev.as_ptr(),
                kev.len() as i32,
                ptr::null_mut(),
                0,
                ptr::null(),
            )
        };
    }

    pub fn poll(&self, block: bool, tq: &TimerQueue, this: &mut ThreadIoContext) {
        let tv = if block {
            let timeout = tq.wait_duration(Duration::new(10, 0));
            libc::timespec {
                tv_sec: timeout.as_secs() as _,
                tv_nsec: timeout.subsec_nanos() as _,
            }
        } else {
            libc::timespec {
                tv_sec: 0,
                tv_nsec: 0,
            }
        };

        let mut kev: [libc::kevent; 128] = unsafe { mem::uninitialized() };
        let n = unsafe {
            libc::kevent(
                self.kq,
                ptr::null(),
                0,
                kev.as_mut_ptr(),
                kev.len() as _,
                &tv,
            )
        };

        tq.get_ready_timers(this);
        if n > 0 {
            let _kq = self.mutex.lock().unwrap();
            for ev in &kev[..(n as usize)] {
                let kev = unsafe { &*(ev.udata as *const Kevent) };
                (kev.dispatch)(ev, this);
            }
        }
    }

    pub fn register_socket(&self, kev: &Kevent) {
        self.kevent(
            &[
                ev_set(
                    kev,
                    kev.fd,
                    EVFILT_READ,
                    EV_ADD | EV_CLEAR | EV_ENABLE | EV_DISPATCH,
                ),
                ev_set(
                    kev,
                    kev.fd,
                    EVFILT_WRITE,
                    EV_ADD | EV_CLEAR | EV_ENABLE | EV_DISPATCH,
                ),
            ],
        );
        let mut kq = self.mutex.lock().unwrap();
        kq.insert(KeventRef::new(kev));
    }

    pub fn deregister_socket(&self, kev: &Kevent) {
        self.kevent(
            &[
                ev_set(kev, kev.fd, EVFILT_READ, EV_DELETE),
                ev_set(kev, kev.fd, EVFILT_WRITE, EV_DELETE),
            ],
        );
        let mut kq = self.mutex.lock().unwrap();
        kq.remove(&KeventRef::new(kev));
    }

    pub fn register_signal(&self, kev: &Kevent) {
        let mut kq = self.mutex.lock().unwrap();
        kq.insert(KeventRef::new(kev));
    }

    pub fn deregister_signal(&self, kev: &Kevent) {
        let mut kq = self.mutex.lock().unwrap();
        kq.remove(&KeventRef::new(kev));
    }

    pub fn register_intr(&self, kev: &Kevent) {
        self.kevent(&[ev_set(kev, kev.fd, EVFILT_READ, EV_ADD | EV_CLEAR)]);
    }

    pub fn deregister_intr(&self, kev: &Kevent) {
        self.kevent(&[ev_set(kev, kev.fd, EVFILT_READ, EV_DELETE | EV_CLEAR)]);
    }

    pub fn interrupt(&self) {
        self.intr.interrupt()
    }

    pub fn reset_timeout(&self, _: Expiry) {
        self.intr.interrupt()
    }

    pub fn add_read_op(
        &self,
        kev: &Kevent,
        this: &mut ThreadIoContext,
        op: Box<Perform>,
        err: SystemError,
    ) {
        let ops = &mut KeventRef::new(kev).input;
        let _kq = self.mutex.lock().unwrap();
        if err == SystemError::default() {
            if ops.queue.is_empty() && !ops.blocked {
                ops.blocked = true;
                this.push(op, SystemError::default());
            } else {
                ops.queue.push_back(op);
            }
        } else if ops.canceled {
            ops.queue.push_front(op);
            for op in ops.queue.drain(..) {
                this.push(op, OPERATION_CANCELED);
            }
            this.as_ctx().as_reactor().kevent(
                &[
                    ev_set(
                        kev,
                        kev.fd,
                        EVFILT_READ,
                        EV_ENABLE,
                    ),
                ],
            );
        } else {
            ops.blocked = false;
            ops.queue.push_front(op);
            this.as_ctx().as_reactor().kevent(
                &[
                    ev_set(
                        kev,
                        kev.fd,
                        EVFILT_READ,
                        EV_ENABLE,
                    ),
                ],
            );
        }
    }

    pub fn add_write_op(
        &self,
        kev: &Kevent,
        this: &mut ThreadIoContext,
        op: Box<Perform>,
        err: SystemError,
    ) {
        let ops = &mut KeventRef::new(kev).output;
        let _kq = self.mutex.lock().unwrap();
        if err == SystemError::default() {
            if ops.queue.is_empty() && !ops.blocked {
                ops.blocked = true;
                this.push(op, SystemError::default());
            } else {
                ops.queue.push_back(op);
            }
        } else if ops.canceled {
            ops.queue.push_front(op);
            for op in ops.queue.drain(..) {
                this.push(op, OPERATION_CANCELED);
            }
            this.as_ctx().as_reactor().kevent(
                &[
                    ev_set(
                        kev,
                        kev.fd,
                        EVFILT_WRITE,
                        EV_ENABLE,
                    ),
                ],
            );
        } else {
            ops.blocked = false;
            ops.queue.push_front(op);
            this.as_ctx().as_reactor().kevent(
                &[
                    ev_set(
                        kev,
                        kev.fd,
                        EVFILT_WRITE,
                        EV_ENABLE,
                    ),
                ],
            );
        }
    }

    pub fn next_read_op(&self, kev: &Kevent, this: &mut ThreadIoContext) {
        let ops = &mut KeventRef::new(kev).input;
        let _kq = self.mutex.lock().unwrap();
        if ops.canceled {
            ops.canceled = false;
            for op in ops.queue.drain(..) {
                this.push(op, OPERATION_CANCELED);
            }
        } else {
            if let Some(op) = ops.queue.pop_front() {
                this.push(op, SystemError::default());
            } else {
                ops.blocked = false;
                this.as_ctx().as_reactor().kevent(
                    &[
                        ev_set(
                            kev,
                            kev.fd,
                            EVFILT_READ,
                            EV_ENABLE,
                        ),
                    ],
                );
            }
        }
    }

    pub fn next_write_op(&self, kev: &Kevent, this: &mut ThreadIoContext) {
        let ops = &mut KeventRef::new(kev).output;
        let _kq = self.mutex.lock().unwrap();
        if ops.canceled {
            ops.canceled = false;
            for op in ops.queue.drain(..) {
                this.push(op, OPERATION_CANCELED);
            }
        } else {
            if let Some(op) = ops.queue.pop_front() {
                this.push(op, SystemError::default());
            } else {
                ops.blocked = false;
                this.as_ctx().as_reactor().kevent(
                    &[
                        ev_set(
                            kev,
                            kev.as_raw_fd(),
                            EVFILT_READ,
                            EV_ENABLE,
                        ),
                    ],
                );
            }
        }
    }

    pub fn cancel_ops(&self, kev: &Kevent, ctx: &IoContext, err: SystemError) {
        let _kq = self.mutex.lock().unwrap();
        for ops in &mut [
            &mut KeventRef::new(kev).input,
            &mut KeventRef::new(kev).output,
        ]
        {
            if !ops.canceled {
                ops.canceled = true;
                if !ops.blocked {
                    for op in ops.queue.drain(..) {
                        ctx.do_post((op, err))
                    }
                }
            }
        }
    }

    pub fn add_signal(&self, kev: &Kevent, sig: Signal) {
        unsafe {
            let mut sigmask = self.sigmask.lock().unwrap();
            sigaddset(&mut *sigmask, sig as i32);
            sigprocmask(SIG_SETMASK, &mut *sigmask, ptr::null_mut());
        }
        self.kevent(
            &[ev_set(kev, sig as i32, EVFILT_SIGNAL, EV_ADD | EV_ENABLE)],
        );
    }

    pub fn del_signal(&self, kev: &Kevent, sig: Signal) {
        self.kevent(&[ev_set(kev, sig as i32, EVFILT_SIGNAL, EV_DELETE)]);
    }
}

impl Drop for KqueueReactor {
    fn drop(&mut self) {
        self.intr.cleanup(self);
        close(self.kq);
    }
}
<commit_msg>fix cancel_ops() of kqueue<commit_after>use ffi::{AsRawFd, RawFd, Signal, close, SystemError, OPERATION_CANCELED, sock_error};
use core::{IoContext, AsIoContext, ThreadIoContext, TimerQueue, Perform, Expiry, Intr, UnsafeRef};

use std::mem;
use std::ptr;
use std::time::Duration;
use std::sync::Mutex;
use std::collections::{HashSet, VecDeque};
use libc::{self, EV_ADD, EV_ERROR, EV_DELETE, EV_ENABLE, EV_DISPATCH, EV_CLEAR, EVFILT_READ,
           EVFILT_WRITE, EVFILT_SIGNAL, SIG_SETMASK, sigaddset, sigprocmask, sigset_t, sigemptyset};

fn ev_set(kev: &Kevent, ident: i32, filter: i16, flags: u16) -> libc::kevent {
    libc::kevent {
        ident: ident as usize,
        filter: filter,
        flags: flags,
        fflags: 0,
        data: 0,
        udata: kev as *const _ as *mut _,
    }
}

fn dispatch_socket(kev: &libc::kevent, this: &mut ThreadIoContext) {
    let udata = unsafe { &mut *(kev.udata as *const Kevent as *mut Kevent) };
    match kev.filter {
        _ if (kev.flags & EV_ERROR) != 0 => {
            let err = sock_error(udata);
            this.as_ctx().clone().as_reactor().cancel_ops_nolock(udata, this.as_ctx(), err)
        }
        EVFILT_READ => {
            if let Some(op) = udata.input.queue.pop_front() {
                udata.input.blocked = true;
                this.push(op, SystemError::default());
            }
        }
        EVFILT_WRITE => {
            if let Some(op) = udata.output.queue.pop_front() {
                udata.output.blocked = true;
                this.push(op, SystemError::default());
            }
        }
        EVFILT_SIGNAL => {
            if let Some(op) = udata.input.queue.pop_front() {
                this.push(op, SystemError::from_signal(kev.ident as i32));
            }
        }
        _ => unreachable!(),
    }
}

fn dispatch_intr(kev: &libc::kevent, _: &mut ThreadIoContext) {
    match kev.filter {
        EVFILT_READ => unsafe {
            let mut buf: [u8; 8] = mem::uninitialized();
            libc::read(kev.ident as RawFd, buf.as_mut_ptr() as *mut _, buf.len());
        },
        _ => unreachable!(""),
    }
}

#[derive(Default)]
struct Ops {
    queue: VecDeque<Box<Perform>>,
    blocked: bool,
    canceled: bool,
}

pub struct Kevent {
    fd: RawFd,
    input: Ops,
    output: Ops,
    dispatch: fn(&libc::kevent, &mut ThreadIoContext),
}

impl Kevent {
    pub fn socket(fd: RawFd) -> Self {
        Kevent {
            fd: fd,
            input: Default::default(),
            output: Default::default(),
            dispatch: dispatch_socket,
        }
    }

    pub fn signal() -> Self {
        Kevent {
            fd: -1,
            input: Ops {
                queue: Default::default(),
                blocked: true, // Always blocked
                canceled: false,
            },
            output: Default::default(),
            dispatch: dispatch_socket,
        }
    }

    pub fn intr(fd: RawFd) -> Self {
        Kevent {
            fd: fd,
            input: Default::default(),
            output: Default::default(),
            dispatch: dispatch_intr,
        }
    }
}

unsafe impl Send for Kevent {}

impl AsRawFd for Kevent {
    fn as_raw_fd(&self) -> RawFd {
        self.fd
    }
}

impl PartialEq for Kevent {
    fn eq(&self, other: &Kevent) -> bool {
        (self as *const Self) == (other as *const Self)
    }
}

impl Eq for Kevent {}

type KeventRef = UnsafeRef<Kevent>;

pub struct KqueueReactor {
    kq: RawFd,
    mutex: Mutex<HashSet<KeventRef>>,
    intr: Intr,
    sigmask: Mutex<sigset_t>,
}

impl KqueueReactor {
    pub fn new() -> Result<Self, SystemError> {
        match unsafe { libc::kqueue() } {
            -1 => Err(SystemError::last_error()),
            kq => {
                let kq = KqueueReactor {
                    kq: kq,
                    mutex: Default::default(),
                    intr: Intr::new()?,
                    sigmask: unsafe {
                        let mut sigmask = mem::uninitialized();
                        sigemptyset(&mut sigmask);
                        Mutex::new(sigmask)
                    },
                };
                Ok(kq)
            }
        }
    }

    pub fn init(&self) {
        self.intr.startup(self);
    }

    pub fn kevent(&self, kev: &[libc::kevent]) {
        unsafe {
            libc::kevent(
                self.kq,
                kev.as_ptr(),
                kev.len() as i32,
                ptr::null_mut(),
                0,
                ptr::null(),
            )
        };
    }

    pub fn poll(&self, block: bool, tq: &TimerQueue, this: &mut ThreadIoContext) {
        let tv = if block {
            let timeout = tq.wait_duration(Duration::new(10, 0));
            libc::timespec {
                tv_sec: timeout.as_secs() as _,
                tv_nsec: timeout.subsec_nanos() as _,
            }
        } else {
            libc::timespec {
                tv_sec: 0,
                tv_nsec: 0,
            }
        };

        let mut kev: [libc::kevent; 128] = unsafe { mem::uninitialized() };
        let n = unsafe {
            libc::kevent(
                self.kq,
                ptr::null(),
                0,
                kev.as_mut_ptr(),
                kev.len() as _,
                &tv,
            )
        };

        tq.get_ready_timers(this);
        if n > 0 {
            let _kq = self.mutex.lock().unwrap();
            for ev in &kev[..(n as usize)] {
                let kev = unsafe { &*(ev.udata as *const Kevent) };
                (kev.dispatch)(ev, this);
            }
        }
    }

    pub fn register_socket(&self, kev: &Kevent) {
        self.kevent(
            &[
                ev_set(
                    kev,
                    kev.fd,
                    EVFILT_READ,
                    EV_ADD | EV_CLEAR | EV_ENABLE | EV_DISPATCH,
                ),
                ev_set(
                    kev,
                    kev.fd,
                    EVFILT_WRITE,
                    EV_ADD | EV_CLEAR | EV_ENABLE | EV_DISPATCH,
                ),
            ],
        );
        let mut kq = self.mutex.lock().unwrap();
        kq.insert(KeventRef::new(kev));
    }

    pub fn deregister_socket(&self, kev: &Kevent) {
        self.kevent(
            &[
                ev_set(kev, kev.fd, EVFILT_READ, EV_DELETE),
                ev_set(kev, kev.fd, EVFILT_WRITE, EV_DELETE),
            ],
        );
        let mut kq = self.mutex.lock().unwrap();
        kq.remove(&KeventRef::new(kev));
    }

    pub fn register_signal(&self, kev: &Kevent) {
        let mut kq = self.mutex.lock().unwrap();
        kq.insert(KeventRef::new(kev));
    }

    pub fn deregister_signal(&self, kev: &Kevent) {
        let mut kq = self.mutex.lock().unwrap();
        kq.remove(&KeventRef::new(kev));
    }

    pub fn register_intr(&self, kev: &Kevent) {
        self.kevent(&[ev_set(kev, kev.fd, EVFILT_READ, EV_ADD | EV_CLEAR)]);
    }

    pub fn deregister_intr(&self, kev: &Kevent) {
        self.kevent(&[ev_set(kev, kev.fd, EVFILT_READ, EV_DELETE | EV_CLEAR)]);
    }

    pub fn interrupt(&self) {
        self.intr.interrupt()
    }

    pub fn reset_timeout(&self, _: Expiry) {
        self.intr.interrupt()
    }

    pub fn add_read_op(
        &self,
        kev: &Kevent,
        this: &mut ThreadIoContext,
        op: Box<Perform>,
        err: SystemError,
    ) {
        let ops = &mut KeventRef::new(kev).input;
        let _kq = self.mutex.lock().unwrap();
        if err == SystemError::default() {
            if ops.queue.is_empty() && !ops.blocked {
                ops.blocked = true;
                this.push(op, SystemError::default());
            } else {
                ops.queue.push_back(op);
            }
        } else if ops.canceled {
            ops.queue.push_front(op);
            for op in ops.queue.drain(..) {
                this.push(op, OPERATION_CANCELED);
            }
            this.as_ctx().as_reactor().kevent(
                &[
                    ev_set(
                        kev,
                        kev.fd,
                        EVFILT_READ,
                        EV_ENABLE,
                    ),
                ],
            );
        } else {
            ops.blocked = false;
            ops.queue.push_front(op);
            this.as_ctx().as_reactor().kevent(
                &[
                    ev_set(
                        kev,
                        kev.fd,
                        EVFILT_READ,
                        EV_ENABLE,
                    ),
                ],
            );
        }
    }

    pub fn add_write_op(
        &self,
        kev: &Kevent,
        this: &mut ThreadIoContext,
        op: Box<Perform>,
        err: SystemError,
    ) {
        let ops = &mut KeventRef::new(kev).output;
        let _kq = self.mutex.lock().unwrap();
        if err == SystemError::default() {
            if ops.queue.is_empty() && !ops.blocked {
                ops.blocked = true;
                this.push(op, SystemError::default());
            } else {
                ops.queue.push_back(op);
            }
        } else if ops.canceled {
            ops.queue.push_front(op);
            for op in ops.queue.drain(..) {
                this.push(op, OPERATION_CANCELED);
            }
            this.as_ctx().as_reactor().kevent(
                &[
                    ev_set(
                        kev,
                        kev.fd,
                        EVFILT_WRITE,
                        EV_ENABLE,
                    ),
                ],
            );
        } else {
            ops.blocked = false;
            ops.queue.push_front(op);
            this.as_ctx().as_reactor().kevent(
                &[
                    ev_set(
                        kev,
                        kev.fd,
                        EVFILT_WRITE,
                        EV_ENABLE,
                    ),
                ],
            );
        }
    }

    pub fn next_read_op(&self, kev: &Kevent, this: &mut ThreadIoContext) {
        let ops = &mut KeventRef::new(kev).input;
        let _kq = self.mutex.lock().unwrap();
        if ops.canceled {
            ops.canceled = false;
            for op in ops.queue.drain(..) {
                this.push(op, OPERATION_CANCELED);
            }
        } else {
            if let Some(op) = ops.queue.pop_front() {
                this.push(op, SystemError::default());
            } else {
                ops.blocked = false;
                this.as_ctx().as_reactor().kevent(
                    &[
                        ev_set(
                            kev,
                            kev.fd,
                            EVFILT_READ,
                            EV_ENABLE,
                        ),
                    ],
                );
            }
        }
    }

    pub fn next_write_op(&self, kev: &Kevent, this: &mut ThreadIoContext) {
        let ops = &mut KeventRef::new(kev).output;
        let _kq = self.mutex.lock().unwrap();
        if ops.canceled {
            ops.canceled = false;
            for op in ops.queue.drain(..) {
                this.push(op, OPERATION_CANCELED);
            }
        } else {
            if let Some(op) = ops.queue.pop_front() {
                this.push(op, SystemError::default());
            } else {
                ops.blocked = false;
                this.as_ctx().as_reactor().kevent(
                    &[
                        ev_set(
                            kev,
                            kev.as_raw_fd(),
                            EVFILT_READ,
                            EV_ENABLE,
                        ),
                    ],
                );
            }
        }
    }

    pub fn cancel_ops(&self, kev: &Kevent, ctx: &IoContext, err: SystemError) {
        let _kq = self.mutex.lock().unwrap();
        self.cancel_ops_nolock(kev, ctx, err)
    }

    pub fn cancel_ops_nolock(&self, kev: &Kevent, ctx: &IoContext, err: SystemError) {
        for ops in &mut [
            &mut KeventRef::new(kev).input,
            &mut KeventRef::new(kev).output,
        ]
        {
            if !ops.canceled {
                ops.canceled = true;
                if !ops.blocked {
                    for op in ops.queue.drain(..) {
                        ctx.do_post((op, err))
                    }
                }
            }
        }
    }

    pub fn add_signal(&self, kev: &Kevent, sig: Signal) {
        unsafe {
            let mut sigmask = self.sigmask.lock().unwrap();
            sigaddset(&mut *sigmask, sig as i32);
            sigprocmask(SIG_SETMASK, &mut *sigmask, ptr::null_mut());
        }
        self.kevent(
            &[ev_set(kev, sig as i32, EVFILT_SIGNAL, EV_ADD | EV_ENABLE)],
        );
    }

    pub fn del_signal(&self, kev: &Kevent, sig: Signal) {
        self.kevent(&[ev_set(kev, sig as i32, EVFILT_SIGNAL, EV_DELETE)]);
    }
}

impl Drop for KqueueReactor {
    fn drop(&mut self) {
        self.intr.cleanup(self);
        close(self.kq);
    }
}
<|endoftext|>


<commit_before>/// Macro to print the current stats of ArrayFire's memory manager.
///
/// `mem_info!` print 4 values:
///
///  Name                    | Description
/// -------------------------|-------------------------
///  Allocated Bytes         | Total number of bytes allocated by the memory manager
///  Allocated Buffers       | Total number of buffers allocated
///  Locked (In Use) Bytes   | Number of bytes that are in use by active arrays
///  Locked (In Use) Buffers | Number of buffers that are in use by active arrays
///
///  The `Allocated Bytes` is always a multiple of the memory step size. The
///  default step size is 1024 bytes. This means when a buffer is to be
///  allocated, the size is always rounded up to a multiple of the step size.
///  You can use [get_mem_step_size](./fn.get_mem_step_size.html) to check the
///  current step size and [set_mem_step_size](./fn.set_mem_step_size.html) to
///  set a custom resolution size.
///
///  The `Allocated Buffers` is the number of buffers that use up the allocated
///  bytes. This includes buffers currently in scope, as well as buffers marked
///  as free, ie, from arrays gone out of scope. The free buffers are available
///  for use by new arrays that might be created.
///
///  The `Locked Bytes` is the number of bytes in use that cannot be
///  reallocated at the moment. The difference of Allocated Bytes and Locked
///  Bytes is the total bytes available for reallocation.
///
///  The `Locked Buffers` is the number of buffer in use that cannot be
///  reallocated at the moment. The difference of Allocated Buffers and Locked
///  Buffers is the number of buffers available for reallocation.
///
/// # Parameters
///
/// - `msg` is the message that is printed to screen before printing stats
///
/// # Examples
///
/// ```rust
/// use arrayfire::{Dim4, device_mem_info, print, randu, mem_info};
///
/// let dims = Dim4::new(&[5, 5, 1, 1]);
/// let a = randu::<f32>(dims);
/// print(&a);
/// mem_info!("Hello!");
/// ```
///
/// Sample Output:
///
/// ```text
/// AF Memory: Here
/// Allocated [ Bytes | Buffers ] = [ 4096 | 4 ]
/// In Use    [ Bytes | Buffers ] = [ 2048 | 2 ]
/// ```
#[macro_export]
macro_rules! mem_info {
    [$msg: expr] => {
        {
            let (abytes, abuffs, lbytes, lbuffs) = $crate::device_mem_info();
            println!("AF Memory: {:?}", $msg);
            println!("Allocated [Bytes | Buffers] = [ {} | {} ]", abytes, abuffs);
            println!("In Use    [Bytes | Buffers] = [ {} | {} ]", lbytes, lbuffs);
        }
    };
}

/// Join multiple Arrays along a given dimension
///
/// All the Arrays provided to this macro should be of type `&Array`
///
/// # Examples
///
/// ```rust
/// use arrayfire::{Dim4, join_many, print, randu};
///
/// let a = &randu::<f32>(Dim4::new(&[5, 3, 1, 1]));
/// let b = &randu::<f32>(Dim4::new(&[5, 3, 1, 1]));
/// let c = &randu::<f32>(Dim4::new(&[5, 3, 1, 1]));
/// let d = join_many![2; a, b, c];
/// print(&d);
/// ```
///
/// # Panics
///
/// This macro just calls [join_many](./fn.join_many.html) function after collecting all
/// the input arrays into a vector.
// Using macro to implement join many wrapper
#[macro_export]
macro_rules! join_many {
    [$dim: expr; $($x:expr),+] => {
        {
            let mut temp_vec = Vec::new();
            $(
                temp_vec.push($x);
             )*
            $crate::join_many($dim, temp_vec)
        }
    };
}

/// Print given message before printing out the Array to standard output
///
/// # Examples
///
/// ```rust
/// use arrayfire::{Dim4, print_gen, randu, af_print};
/// let dims = Dim4::new(&[3, 1, 1, 1]);
/// let a = randu::<f32>(dims);
/// af_print!("Create a 5-by-3 matrix of random floats on the GPU", a);
/// ```
///
#[macro_export]
macro_rules! af_print {
    [$msg: expr, $x: expr] => {
        {
            $crate::print_gen(String::from($msg), &$x, Some(4));
        }
    };
}

/// Evaluate arbitrary number of arrays
#[macro_export]
macro_rules! eval {
    [$($x:expr),+] => {
        {
            let mut temp_vec = Vec::new();
            $(
                temp_vec.push($x);
             )*
            eval_multiple(temp_vec)
        }
    };
}

/// Create a dim4 object from provided dimensions
///
/// The user can pass 1 or more sizes and the left over values will default to 1.
#[macro_export]
macro_rules! dim4 {
    ($dim0:literal) => {
        $crate::Dim4::new(&[$dim0, 1, 1, 1])
    };
    ($dim0:literal, $dim1:literal) => {
        $crate::Dim4::new(&[$dim0, $dim1, 1, 1])
    };
    ($dim0:literal, $dim1:literal, $dim2:literal) => {
        $crate::Dim4::new(&[$dim0, $dim1, $dim2, 1])
    };
    ($dim0:literal, $dim1:literal, $dim2:literal, $dim3:literal) => {
        $crate::Dim4::new(&[$dim0, $dim1, $dim2, $dim3])
    };
}

/// Create a sequence object
///
/// If type is not provided, then the Seq will default to i32 type
#[macro_export]
macro_rules! seq {
    () => {
        $crate::Seq::<i32>::default()
    };
    ($sty:ty; $start:literal : $end:literal : $step:literal) => {
        $crate::Seq::<$sty>::new($start, $end, $step)
    };
    ($start:literal : $end:literal : $step:literal) => {
        $crate::Seq::<i32>::new($start, $end, $step)
    };
}

/// Indexing into an existing Array
///
/// This macro call with return an Array that has a view of another Array. The Array returned due to
/// the indexing operation will follow copy-on-write semantics. The Array identifier taken by this
/// macro is passed to the relevant internal functions as a borrowed reference. Thus, this identifier
/// will be still available for futher use after the macro call.
///
/// The following types of inputs are matched by this macro.
///
/// - A simple Array identifier.
/// - An Array with slicing info for indexing.
/// - An Array with slicing info and other arrays used for indexing.
#[macro_export]
macro_rules! view {
    (@af_max_dims) => {
        4
    };
    ( $array_ident:ident ) => {
        $array_ident.clone()
    };
    ( $array_ident:ident [ $($start:literal : $end:literal : $step:literal),+ ] ) => {
        {
            let AF_MAX_DIMS: usize = view!(@af_max_dims);
            let mut seq_vec = Vec::<$crate::Seq<i32>>::with_capacity(AF_MAX_DIMS);
            $(
                seq_vec.push($crate::seq!($start:$end:$step));
             )*
             for span_place_holder in seq_vec.len()..AF_MAX_DIMS {
                 seq_vec.push($crate::seq!());
             }
            $crate::index(&$array_ident, &seq_vec)
        }
    };
    (@set_indexer $idim:expr, $idxr:ident, $lterm:expr) => {
        {
            $idxr.set_index(&$lterm, $idim, None);
        }
    };
    (@set_indexer $idim:expr, $idxr:ident, $hterm:expr, $($tterm:expr),*) => {
        {
            $idxr.set_index(&$hterm, $idim, None);
            view!(@set_indexer $idim + 1, $idxr, $($tterm),*);
        }
    };
    ($array_ident:ident [ $($_e:expr),+ ]) => {
        {
            let AF_MAX_DIMS: u32 = view!(@af_max_dims);
            let span = $crate::seq!();
            let mut idxrs = $crate::Indexer::default();

            view!(@set_indexer 0, idxrs, $($_e),*);

            let mut dimIx = idxrs.len() as u32;
            while dimIx < AF_MAX_DIMS {
                idxrs.set_index(&span, dimIx, None);
                dimIx += 1;
            }
            $crate::index_gen(&$array_ident, idxrs)
        }
    };
}
<commit_msg>Expand scope of dim4 & seq macros args to accept all expressions<commit_after>/// Macro to print the current stats of ArrayFire's memory manager.
///
/// `mem_info!` print 4 values:
///
///  Name                    | Description
/// -------------------------|-------------------------
///  Allocated Bytes         | Total number of bytes allocated by the memory manager
///  Allocated Buffers       | Total number of buffers allocated
///  Locked (In Use) Bytes   | Number of bytes that are in use by active arrays
///  Locked (In Use) Buffers | Number of buffers that are in use by active arrays
///
///  The `Allocated Bytes` is always a multiple of the memory step size. The
///  default step size is 1024 bytes. This means when a buffer is to be
///  allocated, the size is always rounded up to a multiple of the step size.
///  You can use [get_mem_step_size](./fn.get_mem_step_size.html) to check the
///  current step size and [set_mem_step_size](./fn.set_mem_step_size.html) to
///  set a custom resolution size.
///
///  The `Allocated Buffers` is the number of buffers that use up the allocated
///  bytes. This includes buffers currently in scope, as well as buffers marked
///  as free, ie, from arrays gone out of scope. The free buffers are available
///  for use by new arrays that might be created.
///
///  The `Locked Bytes` is the number of bytes in use that cannot be
///  reallocated at the moment. The difference of Allocated Bytes and Locked
///  Bytes is the total bytes available for reallocation.
///
///  The `Locked Buffers` is the number of buffer in use that cannot be
///  reallocated at the moment. The difference of Allocated Buffers and Locked
///  Buffers is the number of buffers available for reallocation.
///
/// # Parameters
///
/// - `msg` is the message that is printed to screen before printing stats
///
/// # Examples
///
/// ```rust
/// use arrayfire::{Dim4, device_mem_info, print, randu, mem_info};
///
/// let dims = Dim4::new(&[5, 5, 1, 1]);
/// let a = randu::<f32>(dims);
/// print(&a);
/// mem_info!("Hello!");
/// ```
///
/// Sample Output:
///
/// ```text
/// AF Memory: Here
/// Allocated [ Bytes | Buffers ] = [ 4096 | 4 ]
/// In Use    [ Bytes | Buffers ] = [ 2048 | 2 ]
/// ```
#[macro_export]
macro_rules! mem_info {
    [$msg: expr] => {
        {
            let (abytes, abuffs, lbytes, lbuffs) = $crate::device_mem_info();
            println!("AF Memory: {:?}", $msg);
            println!("Allocated [Bytes | Buffers] = [ {} | {} ]", abytes, abuffs);
            println!("In Use    [Bytes | Buffers] = [ {} | {} ]", lbytes, lbuffs);
        }
    };
}

/// Join multiple Arrays along a given dimension
///
/// All the Arrays provided to this macro should be of type `&Array`
///
/// # Examples
///
/// ```rust
/// use arrayfire::{Dim4, join_many, print, randu};
///
/// let a = &randu::<f32>(Dim4::new(&[5, 3, 1, 1]));
/// let b = &randu::<f32>(Dim4::new(&[5, 3, 1, 1]));
/// let c = &randu::<f32>(Dim4::new(&[5, 3, 1, 1]));
/// let d = join_many![2; a, b, c];
/// print(&d);
/// ```
///
/// # Panics
///
/// This macro just calls [join_many](./fn.join_many.html) function after collecting all
/// the input arrays into a vector.
// Using macro to implement join many wrapper
#[macro_export]
macro_rules! join_many {
    [$dim: expr; $($x:expr),+] => {
        {
            let mut temp_vec = Vec::new();
            $(
                temp_vec.push($x);
             )*
            $crate::join_many($dim, temp_vec)
        }
    };
}

/// Print given message before printing out the Array to standard output
///
/// # Examples
///
/// ```rust
/// use arrayfire::{Dim4, print_gen, randu, af_print};
/// let dims = Dim4::new(&[3, 1, 1, 1]);
/// let a = randu::<f32>(dims);
/// af_print!("Create a 5-by-3 matrix of random floats on the GPU", a);
/// ```
///
#[macro_export]
macro_rules! af_print {
    [$msg: expr, $x: expr] => {
        {
            $crate::print_gen(String::from($msg), &$x, Some(4));
        }
    };
}

/// Evaluate arbitrary number of arrays
#[macro_export]
macro_rules! eval {
    [$($x:expr),+] => {
        {
            let mut temp_vec = Vec::new();
            $(
                temp_vec.push($x);
             )*
            eval_multiple(temp_vec)
        }
    };
}

/// Create a dim4 object from provided dimensions
///
/// The user can pass 1 or more sizes and the left over values will default to 1.
#[macro_export]
macro_rules! dim4 {
    ($dim0:expr) => {
        $crate::Dim4::new(&[$dim0, 1, 1, 1])
    };
    ($dim0:expr, $dim1:expr) => {
        $crate::Dim4::new(&[$dim0, $dim1, 1, 1])
    };
    ($dim0:expr, $dim1:expr, $dim2:expr) => {
        $crate::Dim4::new(&[$dim0, $dim1, $dim2, 1])
    };
    ($dim0:expr, $dim1:expr, $dim2:expr, $dim3:expr) => {
        $crate::Dim4::new(&[$dim0, $dim1, $dim2, $dim3])
    };
}

/// Create a sequence object
///
/// If type is not provided, then the Seq will default to i32 type
#[macro_export]
macro_rules! seq {
    () => {
        $crate::Seq::<i32>::default()
    };
    ($sty:ty; $start:literal : $end:literal : $step:literal) => {
        $crate::Seq::<$sty>::new($start, $end, $step)
    };
    ($start:literal : $end:literal : $step:literal) => {
        $crate::Seq::<i32>::new($start, $end, $step)
    };
    ($sty:ty; $start:expr , $end:expr , $step:expr) => {
        $crate::Seq::<$sty>::new($start, $end, $step)
    };
    ($start:expr , $end:expr , $step:expr) => {
        $crate::Seq::<i32>::new($start, $end, $step)
    };
}

/// Indexing into an existing Array
///
/// This macro call with return an Array that has a view of another Array. The Array returned due to
/// the indexing operation will follow copy-on-write semantics. The Array identifier taken by this
/// macro is passed to the relevant internal functions as a borrowed reference. Thus, this identifier
/// will be still available for futher use after the macro call.
///
/// The following types of inputs are matched by this macro.
///
/// - A simple Array identifier.
/// - An Array with slicing info for indexing.
/// - An Array with slicing info and other arrays used for indexing.
#[macro_export]
macro_rules! view {
    (@af_max_dims) => {
        4
    };
    ( $array_ident:ident ) => {
        $array_ident.clone()
    };
    ( $array_ident:ident [ $($start:literal : $end:literal : $step:literal),+ ] ) => {
        {
            let AF_MAX_DIMS: usize = view!(@af_max_dims);
            let mut seq_vec = Vec::<$crate::Seq<i32>>::with_capacity(AF_MAX_DIMS);
            $(
                seq_vec.push($crate::seq!($start:$end:$step));
             )*
             for span_place_holder in seq_vec.len()..AF_MAX_DIMS {
                 seq_vec.push($crate::seq!());
             }
            $crate::index(&$array_ident, &seq_vec)
        }
    };
    (@set_indexer $idim:expr, $idxr:ident, $lterm:expr) => {
        {
            $idxr.set_index(&$lterm, $idim, None);
        }
    };
    (@set_indexer $idim:expr, $idxr:ident, $hterm:expr, $($tterm:expr),*) => {
        {
            $idxr.set_index(&$hterm, $idim, None);
            view!(@set_indexer $idim + 1, $idxr, $($tterm),*);
        }
    };
    ($array_ident:ident [ $($_e:expr),+ ]) => {
        {
            let AF_MAX_DIMS: u32 = view!(@af_max_dims);
            let span = $crate::seq!();
            let mut idxrs = $crate::Indexer::default();

            view!(@set_indexer 0, idxrs, $($_e),*);

            let mut dimIx = idxrs.len() as u32;
            while dimIx < AF_MAX_DIMS {
                idxrs.set_index(&span, dimIx, None);
                dimIx += 1;
            }
            $crate::index_gen(&$array_ident, idxrs)
        }
    };
}
<|endoftext|>


<commit_before>// NOTE: Object is a term for an entity or a prop.

use time;
use opengl_graphics::*;
use graphics::*;
use core::{Vec2};

/// A trait for positioned objects
pub trait Position {
  /// Get the x coordinate
  fn get_pos(&self) -> Vec2<i64>;
  /// Set the Vec coordinate
  fn set_pos(&mut self, new_pos: Vec2<i64>);
}

// TODO: This should probably just be a Vec2, especially since you're doing
//       things like Dir::to_vec, and you want to allow two different
//       directions at once.
/// The direction of a given object
#[derive(Clone, Copy)]
pub enum Dir {
  Left,
  Right,
  Up,
  Down,
}

pub struct Movement {
  dir1: Option<Dir>,
  dir2: Option<Dir>,
  state: i64, // This should change every half second
}

impl Movement {
  fn to_vec(&self) -> Vec2<i64> {
    unimplemented!()
  }
}

impl Dir {
  fn to_vec(self) -> Vec2<i64> {
    Vec2(
      match self {
        Dir::Left => 1,
        Dir::Right => -1,
        _ => 0,
      },

      match self {
        Dir::Up => 1,
        Dir::Down => -1,
      _ => 0,
      }
    )
  }
  /// Get the dir in the opposite direction
  fn invert(self) -> Dir {
    match self {
      Dir::Left => Dir::Right,
      Dir::Right => Dir::Left,
      Dir::Up => Dir::Down,
      Dir::Down => Dir::Up,
    }
  }
}

// TODO: Implement two directions at once. (See comment above.)

/// A movable object
pub trait Move: Position {
  /// Get the direction
  fn get_movement(&self) -> Movement;
  /// Set the direction
  fn set_movement(&mut self, new_dir: Movement);
  /// Is the object moving?
  fn is_moving(&self) -> bool;
  /// Can the object move? Or is it blocked?
  fn can_move(&self) -> bool;
  /// Move the object
  fn move_obj(&mut self, mov: Vec2<i64>) {
    let coord = self.get_pos();
    self.set_pos(coord + mov);
  }
  /// Get new coordinate
  fn get_new_pos(&self) -> Vec2<i64> {
    let mov = self.get_movement();
    self.get_pos() + mov.to_vec()
  }
  /// Move object in direction.
  fn move_obj_dir(&mut self) {
    let new_coord = self.get_new_pos();
    self.set_pos(new_coord)
  }
  /// Get the timestamp of the last move
  fn get_last_move(&self) -> f64;
  /// Set the timestamp of the last move
  fn set_last_move(&mut self, new: &f64);
  /// Get the speed of the object
  fn get_speed(&self) -> f64;
  /// Moves regularly
  fn move_reg(&mut self) {
    let now = &time::precise_time_s();
    if self.is_moving() && self.can_move()
       && self.get_last_move() - now > 1.0 / self.get_speed() {
      self.set_last_move(now);
      self.move_obj_dir();
    }
  }
  /// Get transitition point, which is in the interval [0,1]
  fn get_trans_state(&self) -> f64;
  /// Get animation frame
  fn get_animation_frame(&self) -> i16;
}

/// Trait for sprited objects
pub trait Sprite: Move {
  /// Get current sprite
  fn get_sprite(&self) -> &Texture;
  /// Get width, not neccesarily the width of the sprite, but rather the space
  /// the given object occupies. Given in fields.
  fn get_width(&self) -> i16;
  /// Get height, see note above
  fn get_height(&self) -> i16;
  /// Get the opacity of the object
  fn get_opacity(&self) -> f64;
  //
  fn draw(&self, c: &Context, gl: &mut GlGraphics);
}

// TODO: Add event trait, for objects you can click on etc.
<commit_msg>Annoying git...<commit_after>// NOTE: Object is a term for an entity or a prop.

use time;
use opengl_graphics::*;
use graphics::*;
use core::{Vec2};

/// A trait for positioned objects
pub trait Position {
  /// Get the x coordinate
  fn get_pos(&self) -> Vec2<i64>;
  /// Set the Vec coordinate
  fn set_pos(&mut self, new_pos: Vec2<i64>);
}

// TODO: This should probably just be a Vec2, especially since you're doing
//       things like Dir::to_vec, and you want to allow two different
//       directions at once.
/// The direction of a given object
#[derive(Clone, Copy)]
pub enum Dir {
  N,
  S,
  E,
  W,
  NE,
  NW,
  SE,
  SW,
}

impl Dir {
  fn to_vec(self) -> Vec2<i64> {
    match self {
      Dir::N => Vec2(0, 1),
      Dir::S => Vec2(0, -1),
      Dir::E => Vec2(1, 0),
      Dir::W => Vec2(-1, 0),
      Dir::NE => Vec2(1, 1),
      Dir::NW => Vec2(1, -1),
      Dir::SE => Vec2(-1, 1),
      Dir::SW => Vec2(-1, -1),
    }
  }
  /// Calculate the "locked" direction (i.e. the direction locked to the grid)
  fn to_locked(self) -> Dir {
    let mov = time::precise_time_s().round() as i64 % 2;
    match (self, mov) {
      (Dir::NE, 0) | (Dir::NW, 0) => Dir::N,
      (Dir::SE, 0) | (Dir::SW, 0) => Dir::S,
      (Dir::NE, 1) | (Dir::SE, 1) => Dir::E,
      (Dir::NW, 1) | (Dir::SW, 1) => Dir::W,
      _ => self,
    }
  }
}

// TODO: Dir or direction? For consistency, I temporary chose the short naming. Should we shift to
//       long names? What's the rust standarts?
// TODO: Implement two directions at once. (See comment above.)

/// A movable object
pub trait Move: Position {
  /// Get the direction
  fn get_dir(&self) -> Dir;
  /// Set the direction
  fn set_dir(&mut self, new_dir: Dir);
  /// Is the object moving?
  fn is_moving(&self) -> bool;
  /// Can the object move? Or is it blocked?
  fn can_move(&self) -> bool;
  /// Move the object
  fn move_obj(&mut self, mov: Vec2<i64>) {
    let coord = self.get_pos();
    self.set_pos(coord + mov);
  }
  /// Get new coordinate
  fn get_new_pos(&self) -> Vec2<i64> {
    // TODO: This is only temporary. Should diagonal moves be allowed or not?
    let mov = self.get_dir();
    self.get_pos() + mov.to_vec()
  }
  /// Move object in direction.
  fn move_obj_dir(&mut self) {
    let new_coord = self.get_new_pos();
    self.set_pos(new_coord)
  }
  /// Get the timestamp of the last move
  fn get_last_move(&self) -> f64;
  /// Set the timestamp of the last move
  fn set_last_move(&mut self, new: &f64);
  /// Get the speed of the object
  fn get_speed(&self) -> f64;
  /// Moves regularly
  fn move_reg(&mut self) {
    let now = &time::precise_time_s();
    if self.is_moving() && self.can_move()
       && self.get_last_move() - now > 1.0 / self.get_speed() {
      self.set_last_move(now);
      self.move_obj_dir();
    }
  }
  /// Get transitition point, which is in the interval [0,1]
  fn get_trans_state(&self) -> f64;
  /// Get animation frame
  fn get_animation_frame(&self) -> i16;
}

/// Trait for sprited objects
pub trait Sprite: Move {
  /// Get current sprite
  fn get_sprite(&self) -> &Texture;
  /// Get width, not neccesarily the width of the sprite, but rather the space
  /// the given object occupies. Given in fields.
  fn get_width(&self) -> i16;
  /// Get height, see note above
  fn get_height(&self) -> i16;
  /// Get the opacity of the object
  fn get_opacity(&self) -> f64;
  //
  fn draw(&self, c: &Context, gl: &mut GlGraphics);
}

// TODO: Add event trait, for objects you can click on etc.
<|endoftext|>


<commit_before>extern crate libc;

use self::libc::c_char;
use api::CxsStatus;
use utils::cstring::CStringUtils;
use utils::{pool, wallet};
use utils::error;
use std::ptr;
use settings;
use connection::{build_connection, connect, to_string, get_state, release};

#[no_mangle]
pub extern fn cxs_init (config_path:*const c_char) -> u32 {

    ::utils::logger::LoggerUtils::init();

    settings::set_defaults();

    if !config_path.is_null() {
        check_useful_c_str!(config_path,error::UNKNOWN_ERROR.code_num);

        match settings::process_config_file(&config_path) {
            Err(_) => {
                error!("Invalid configuration specified");
                return error::INVALID_CONFIGURATION.code_num;
            },
            Ok(_) => info!("Successfully parsed config: {}",config_path),
        };
    }

    let config_name = match settings::get_config_value(settings::CONFIG_POOL_CONFIG_NAME) {
        Err(x) => return x,
        Ok(v) => v,
    };

    let pool_name = match settings::get_config_value(settings::CONFIG_POOL_NAME) {
        Err(x) => return x,
        Ok(v) => v,
    };

    let wallet_name = match settings::get_config_value(settings::CONFIG_WALLET_NAME) {
        Err(x) => return x,
        Ok(v) => v,
    };

    let wallet_type = match settings::get_config_value(settings::CONFIG_WALLET_TYPE) {
        Err(x) => return x,
        Ok(v) => v,
    };

    let agency_pairwise_did = match settings::get_config_value(settings::CONFIG_AGENCY_PAIRWISE_DID) {
        Err(x) => return x,
        Ok(v) => v,
    };

    let agency_ver_key = match settings::get_config_value(settings::CONFIG_AGENCY_PAIRWISE_VERKEY) {
        Err(x) => return x,
        Ok(v) => v,
    };

    let agent_ver_key = match settings::get_config_value(settings::CONFIG_AGENT_PAIRWISE_VERKEY) {
        Err(x) => return x,
        Ok(v) => v,
    };

    let enterprise_did_agency = match settings::get_config_value(settings::CONFIG_ENTERPRISE_DID_AGENCY) {
        Err(x) => return x,
        Ok(v) => v,
    };

    let enterprise_did_agent = match settings::get_config_value(settings::CONFIG_ENTERPRISE_DID_AGENT) {
        Err(x) => return x,
        Ok(v) => v,
    };

    let enterprise_name = match settings::get_config_value(settings::CONFIG_ENTERPRISE_NAME) {
        Err(x) => return x,
        Ok(v) => v,
    };

    let logo_url = match settings::get_config_value(settings::CONFIG_LOGO_URL) {
        Err(x) => return x,
        Ok(v) => v,
    };

    match pool::create_pool_config(&pool_name, &config_name) {
        0 => 0,
        x => return x,
    };

    match wallet::create_wallet(&pool_name, &wallet_name, &wallet_type) {
        0 => 0,
        x => return x,
    };

    return error::SUCCESS.code_num
}

/**
 * Schema object
 */

#[allow(unused_variables, unused_mut)]
pub extern fn cxs_schema_create(schema_data: *const c_char, schema_handle: *mut u32) -> u32 { error::SUCCESS.code_num }
#[allow(unused_variables, unused_mut)]
pub extern fn cxs_schema_commit(schema_handle: u32) -> u32 { error::SUCCESS.code_num }
#[allow(unused_variables)]
pub extern fn cxs_schema_get_data(schema_handle: u32, data: *mut c_char) -> u32 { error::SUCCESS.code_num }
#[allow(unused_variables, unused_mut)]
pub extern fn cxs_schema_get_sequence_no(schema_handle: u32, sequence_no: *mut u32) -> u32 { error::SUCCESS.code_num }

/**
 * claimdef object
 */

#[allow(unused_variables, unused_mut)]
pub extern fn cxs_claimdef_create(schema_handle: u32, claimdef_handle: *mut u32) -> u32 { error::SUCCESS.code_num }
#[allow(unused_variables, unused_mut)]
pub extern fn cxs_claimdef_commit(claimdef_handle: u32) -> u32 { error::SUCCESS.code_num }
#[allow(unused_variables, unused_mut)]
pub extern fn cxs_claimdef_get_sequence_no(claimdef_handle: u32, sequence_no: *mut u32) -> u32 { error::SUCCESS.code_num }
#[allow(unused_variables, unused_mut)]
pub extern fn cxs_claimdef_get(claimdef_handle: u32, data: *mut c_char) -> u32 { error::SUCCESS.code_num }

/**
 * connection object
 */

#[no_mangle]
pub extern fn cxs_connection_create(recipient_info: *const c_char, connection_handle: *mut u32) -> u32 {
    check_useful_c_str!(recipient_info, error::UNKNOWN_ERROR.code_num);

    if connection_handle.is_null() {return error::UNKNOWN_ERROR.code_num}

    let handle = build_connection(recipient_info.to_owned());

    unsafe { *connection_handle = handle }

    error::SUCCESS.code_num
}

#[no_mangle]
pub extern fn cxs_connection_connect(connection_handle: u32) -> u32 {
    connect(connection_handle)
}

#[no_mangle]
pub extern fn cxs_connection_get_data(connection_handle: u32) -> *mut c_char {
    let json_string = to_string(connection_handle);

    if json_string.is_empty() {
        return ptr::null_mut()
    }
    else {
        let msg = CStringUtils::string_to_cstring(json_string);

        msg.into_raw()
    }
}

#[no_mangle]
pub extern fn cxs_connection_get_state(connection_handle: u32, status: *mut u32) -> u32 {

    if status.is_null() {return error::UNKNOWN_ERROR.code_num}

    let state = get_state(connection_handle);

    unsafe { *status = state }

    error::SUCCESS.code_num
}

#[no_mangle]
pub extern fn cxs_connection_release(connection_handle: u32) -> u32 {
    release(connection_handle)
}

#[no_mangle]
#[allow(unused_variables, unused_mut)]
pub extern fn cxs_connection_list_state(status_array: *mut CxsStatus) -> u32 { error::SUCCESS.code_num }

/**
 * claim object
 */

#[allow(unused_variables, unused_mut)]
pub extern fn cxs_claim_create(claimdef_handle: u32, claim_data: *const c_char, claim_handle: *mut u32) -> u32 { error::SUCCESS.code_num }
#[allow(unused_variables)]
pub extern fn cxs_claim_set_connection(claim_handle: u32, connection_handle: u32) -> u32 { error::SUCCESS.code_num }
#[allow(unused_variables, unused_mut)]
pub extern fn cxs_claim_send_offer(claim_handle: u32) -> u32 { error::SUCCESS.code_num }
#[allow(unused_variables, unused_mut)]
pub extern fn cxs_claim_get_claim_request(claim_handle: u32, claim_request: *mut c_char) -> u32 { error::SUCCESS.code_num }
#[allow(unused_variables, unused_mut)]
pub extern fn cxs_claim_send(claim_handle: u32) -> u32 { error::SUCCESS.code_num }
#[allow(unused_variables)]
pub extern fn cxs_claim_terminate(claim_handle: u32, termination_type: u32, msg: *const c_char) -> u32 { error::SUCCESS.code_num }
#[allow(unused_variables, unused_mut)]
pub extern fn cxs_claim_list_state(status_array: *mut CxsStatus) -> u32 { error::SUCCESS.code_num }
#[allow(unused_variables, unused_mut)]
pub extern fn cxs_claim_get_state(claim_handle: u32, status: *mut c_char) -> u32 { error::SUCCESS.code_num }

/**
 * proof object
 */

#[allow(unused_variables, unused_mut)]
pub extern fn cxs_proof_create(proof_request_data: *mut c_char, proof_handle: *mut u32) -> u32 { error::SUCCESS.code_num }
#[allow(unused_variables)]
pub extern fn cxs_proof_set_connection(proof_handle: u32, connection_handle: u32) -> u32 { error::SUCCESS.code_num }
#[allow(unused_variables, unused_mut)]
pub extern fn cxs_proof_send_request(proof_handle: u32) -> u32 { error::SUCCESS.code_num }
#[allow(unused_variables, unused_mut)]
pub extern fn cxs_proof_get_proof_offer(proof_handle: u32, response_data: *mut c_char) -> u32 { error::SUCCESS.code_num }
#[allow(unused_variables)]
pub extern fn cxs_proof_validate_response(proof_handle: u32, response_data: *const c_char) -> u32 { error::SUCCESS.code_num }
#[allow(unused_variables, unused_mut)]
pub extern fn cxs_proof_list_state(status_array: *mut CxsStatus) -> u32 { error::SUCCESS.code_num }
#[allow(unused_variables, unused_mut)]
pub extern fn cxs_proof_get_state(proof_handle: u32, status: *mut c_char) -> u32 { error::SUCCESS.code_num }

#[cfg(test)]
mod tests {

    use super::*;
    use api::CxsStateType;
    use std::path::Path;
    use std::ffi::CString;
    use std::error::Error;
    use std::io::prelude::*;
    use std::fs;

    #[test]
    fn test_init_with_file() {
        let config_path = "/tmp/test_init.json";
        let path = Path::new(config_path);

        let mut file = match fs::File::create(&path) {
            Err(why) => panic!("couldn't create sample config file: {}", why.description()),
            Ok(file) => file,
        };

        let content = "{ \"pool_name\" : \"my_pool\", \"config_name\":\"my_config\", \"wallet_name\":\"my_wallet\"}";
        match file.write_all(content.as_bytes()) {
            Err(why) => panic!("couldn't write to sample config file: {}", why.description()),
            Ok(_) => println!("sample config ready"),
        }

        let result = cxs_init(CString::new(config_path).unwrap().into_raw());
        assert_eq!(result,0);
        // Leave file around or other concurrent tests will fail
        //fs::remove_file(config_path).unwrap();
    }

    #[test]
    fn test_init_bad_path() {
        let empty_str = CString::new("").unwrap().into_raw();
        assert_eq!(error::UNKNOWN_ERROR.code_num,cxs_init(empty_str));
    }

    #[test]
    fn test_init_no_config_path() {
        let result = cxs_init(ptr::null());
        assert_eq!(result,0);
    }

    #[test]
    fn test_cxs_connection_create() {
        let mut handle: u32 = 0;
        let rc = cxs_connection_create(CString::new("test_create").unwrap().into_raw(), &mut handle);
        assert_eq!(rc, error::SUCCESS.code_num);
        assert!(handle > 0);
    }

    #[test]
    fn test_cxs_connection_create_fails() {
        let rc = cxs_connection_create(CString::new("test_create_fails").unwrap().into_raw(), ptr::null_mut());
        assert_eq!(rc, error::UNKNOWN_ERROR.code_num);

        let rc = cxs_connection_create(ptr::null(),ptr::null_mut());
        assert_eq!(rc, error::UNKNOWN_ERROR.code_num);
    }

    #[test]
    fn test_cxs_connection_connect() {
        let mut handle: u32 = 0;
        let rc = cxs_connection_create(CString::new("test_connect").unwrap().into_raw(), &mut handle);
        assert_eq!(rc, error::SUCCESS.code_num);
        assert!(handle > 0);

        let rc = cxs_connection_connect(handle);
        assert_eq!(rc, error::SUCCESS.code_num);
    }

    #[test]
    fn test_cxs_connection_connect_fails() {
        let rc = cxs_connection_connect(0);
        assert_eq!(rc, error::INVALID_CONNECTION_HANDLE.code_num);
    }

    #[test]
    fn test_cxs_connection_get_state() {
        let mut handle: u32 = 0;
        let rc = cxs_connection_create(CString::new("test_get_state").unwrap().into_raw(), &mut handle);
        assert_eq!(rc, error::SUCCESS.code_num);
        assert!(handle > 0);

        let mut state: u32 = 0;
        let rc = cxs_connection_get_state(handle, &mut state);
        assert_eq!(rc, error::SUCCESS.code_num);
        assert_eq!(state,CxsStateType::CxsStateInitialized as u32);
    }

    #[test]
    fn test_cxs_connection_get_state_fails() {
        let mut handle: u32 = 0;
        let rc = cxs_connection_create(CString::new("test_get_state_fails").unwrap().into_raw(), &mut handle);
        assert_eq!(rc, error::SUCCESS.code_num);
        assert!(handle > 0);

        let rc = cxs_connection_get_state(handle, ptr::null_mut());
        assert_eq!(rc, error::UNKNOWN_ERROR.code_num);

        let rc = cxs_connection_get_state(0, ptr::null_mut());
        assert_eq!(rc, error::UNKNOWN_ERROR.code_num);
    }

    #[test]
    #[allow(unused_assignments)]
    fn test_cxs_connection_get_data() {
        let mut handle: u32 = 0;
        let rc = cxs_connection_create(CString::new("test_get_data").unwrap().into_raw(), &mut handle);
        assert_eq!(rc, error::SUCCESS.code_num);
        assert!(handle > 0);

        let data = cxs_connection_get_data(handle);
        let mut final_string = String::new();

        unsafe {
            let c_string = CString::from_raw(data);
            final_string = c_string.into_string().unwrap();
        }

        assert!(final_string.len() > 0);
    }

    #[test]
    fn test_cxs_connection_get_data_fails() {
        let data = cxs_connection_get_data(0);

        assert_eq!(data, ptr::null_mut());
    }

    #[test]
    fn test_cxs_connection_release() {
        let mut handle: u32 = 0;
        let rc = cxs_connection_create(CString::new("test_release").unwrap().into_raw(), &mut handle);
        assert_eq!(rc, error::SUCCESS.code_num);
        assert!(handle > 0);

        let rc = cxs_connection_release(handle);
        assert_eq!(rc, error::SUCCESS.code_num);
        let rc = cxs_connection_connect(handle);
        assert_eq!(rc, error::INVALID_CONNECTION_HANDLE.code_num);
    }
}
<commit_msg>added aget_pariwse_did getter to cxs_init<commit_after>extern crate libc;

use self::libc::c_char;
use api::CxsStatus;
use utils::cstring::CStringUtils;
use utils::{pool, wallet};
use utils::error;
use std::ptr;
use settings;
use connection::{build_connection, connect, to_string, get_state, release};

#[no_mangle]
pub extern fn cxs_init (config_path:*const c_char) -> u32 {

    ::utils::logger::LoggerUtils::init();

    settings::set_defaults();

    if !config_path.is_null() {
        check_useful_c_str!(config_path,error::UNKNOWN_ERROR.code_num);

        match settings::process_config_file(&config_path) {
            Err(_) => {
                error!("Invalid configuration specified");
                return error::INVALID_CONFIGURATION.code_num;
            },
            Ok(_) => info!("Successfully parsed config: {}",config_path),
        };
    }

    let config_name = match settings::get_config_value(settings::CONFIG_POOL_CONFIG_NAME) {
        Err(x) => return x,
        Ok(v) => v,
    };

    let pool_name = match settings::get_config_value(settings::CONFIG_POOL_NAME) {
        Err(x) => return x,
        Ok(v) => v,
    };

    let wallet_name = match settings::get_config_value(settings::CONFIG_WALLET_NAME) {
        Err(x) => return x,
        Ok(v) => v,
    };

    let wallet_type = match settings::get_config_value(settings::CONFIG_WALLET_TYPE) {
        Err(x) => return x,
        Ok(v) => v,
    };

    let agency_pairwise_did = match settings::get_config_value(settings::CONFIG_AGENCY_PAIRWISE_DID) {
        Err(x) => return x,
        Ok(v) => v,
    };

    let agent_pairwise_did = match settings::get_config_value(settings::CONFIG_AGENT_PAIRWISE_DID) {
        Err(x) => return x,
        Ok(v) => v,
    };

    let agency_ver_key = match settings::get_config_value(settings::CONFIG_AGENCY_PAIRWISE_VERKEY) {
        Err(x) => return x,
        Ok(v) => v,
    };

    let agent_ver_key = match settings::get_config_value(settings::CONFIG_AGENT_PAIRWISE_VERKEY) {
        Err(x) => return x,
        Ok(v) => v,
    };

    let enterprise_did_agency = match settings::get_config_value(settings::CONFIG_ENTERPRISE_DID_AGENCY) {
        Err(x) => return x,
        Ok(v) => v,
    };

    let enterprise_did_agent = match settings::get_config_value(settings::CONFIG_ENTERPRISE_DID_AGENT) {
        Err(x) => return x,
        Ok(v) => v,
    };

    let enterprise_name = match settings::get_config_value(settings::CONFIG_ENTERPRISE_NAME) {
        Err(x) => return x,
        Ok(v) => v,
    };

    let logo_url = match settings::get_config_value(settings::CONFIG_LOGO_URL) {
        Err(x) => return x,
        Ok(v) => v,
    };

    match pool::create_pool_config(&pool_name, &config_name) {
        0 => 0,
        x => return x,
    };

    match wallet::create_wallet(&pool_name, &wallet_name, &wallet_type) {
        0 => 0,
        x => return x,
    };

    return error::SUCCESS.code_num
}

/**
 * Schema object
 */

#[allow(unused_variables, unused_mut)]
pub extern fn cxs_schema_create(schema_data: *const c_char, schema_handle: *mut u32) -> u32 { error::SUCCESS.code_num }
#[allow(unused_variables, unused_mut)]
pub extern fn cxs_schema_commit(schema_handle: u32) -> u32 { error::SUCCESS.code_num }
#[allow(unused_variables)]
pub extern fn cxs_schema_get_data(schema_handle: u32, data: *mut c_char) -> u32 { error::SUCCESS.code_num }
#[allow(unused_variables, unused_mut)]
pub extern fn cxs_schema_get_sequence_no(schema_handle: u32, sequence_no: *mut u32) -> u32 { error::SUCCESS.code_num }

/**
 * claimdef object
 */

#[allow(unused_variables, unused_mut)]
pub extern fn cxs_claimdef_create(schema_handle: u32, claimdef_handle: *mut u32) -> u32 { error::SUCCESS.code_num }
#[allow(unused_variables, unused_mut)]
pub extern fn cxs_claimdef_commit(claimdef_handle: u32) -> u32 { error::SUCCESS.code_num }
#[allow(unused_variables, unused_mut)]
pub extern fn cxs_claimdef_get_sequence_no(claimdef_handle: u32, sequence_no: *mut u32) -> u32 { error::SUCCESS.code_num }
#[allow(unused_variables, unused_mut)]
pub extern fn cxs_claimdef_get(claimdef_handle: u32, data: *mut c_char) -> u32 { error::SUCCESS.code_num }

/**
 * connection object
 */

#[no_mangle]
pub extern fn cxs_connection_create(recipient_info: *const c_char, connection_handle: *mut u32) -> u32 {
    check_useful_c_str!(recipient_info, error::UNKNOWN_ERROR.code_num);

    if connection_handle.is_null() {return error::UNKNOWN_ERROR.code_num}

    let handle = build_connection(recipient_info.to_owned());

    unsafe { *connection_handle = handle }

    error::SUCCESS.code_num
}

#[no_mangle]
pub extern fn cxs_connection_connect(connection_handle: u32) -> u32 {
    connect(connection_handle)
}

#[no_mangle]
pub extern fn cxs_connection_get_data(connection_handle: u32) -> *mut c_char {
    let json_string = to_string(connection_handle);

    if json_string.is_empty() {
        return ptr::null_mut()
    }
    else {
        let msg = CStringUtils::string_to_cstring(json_string);

        msg.into_raw()
    }
}

#[no_mangle]
pub extern fn cxs_connection_get_state(connection_handle: u32, status: *mut u32) -> u32 {

    if status.is_null() {return error::UNKNOWN_ERROR.code_num}

    let state = get_state(connection_handle);

    unsafe { *status = state }

    error::SUCCESS.code_num
}

#[no_mangle]
pub extern fn cxs_connection_release(connection_handle: u32) -> u32 {
    release(connection_handle)
}

#[no_mangle]
#[allow(unused_variables, unused_mut)]
pub extern fn cxs_connection_list_state(status_array: *mut CxsStatus) -> u32 { error::SUCCESS.code_num }

/**
 * claim object
 */

#[allow(unused_variables, unused_mut)]
pub extern fn cxs_claim_create(claimdef_handle: u32, claim_data: *const c_char, claim_handle: *mut u32) -> u32 { error::SUCCESS.code_num }
#[allow(unused_variables)]
pub extern fn cxs_claim_set_connection(claim_handle: u32, connection_handle: u32) -> u32 { error::SUCCESS.code_num }
#[allow(unused_variables, unused_mut)]
pub extern fn cxs_claim_send_offer(claim_handle: u32) -> u32 { error::SUCCESS.code_num }
#[allow(unused_variables, unused_mut)]
pub extern fn cxs_claim_get_claim_request(claim_handle: u32, claim_request: *mut c_char) -> u32 { error::SUCCESS.code_num }
#[allow(unused_variables, unused_mut)]
pub extern fn cxs_claim_send(claim_handle: u32) -> u32 { error::SUCCESS.code_num }
#[allow(unused_variables)]
pub extern fn cxs_claim_terminate(claim_handle: u32, termination_type: u32, msg: *const c_char) -> u32 { error::SUCCESS.code_num }
#[allow(unused_variables, unused_mut)]
pub extern fn cxs_claim_list_state(status_array: *mut CxsStatus) -> u32 { error::SUCCESS.code_num }
#[allow(unused_variables, unused_mut)]
pub extern fn cxs_claim_get_state(claim_handle: u32, status: *mut c_char) -> u32 { error::SUCCESS.code_num }

/**
 * proof object
 */

#[allow(unused_variables, unused_mut)]
pub extern fn cxs_proof_create(proof_request_data: *mut c_char, proof_handle: *mut u32) -> u32 { error::SUCCESS.code_num }
#[allow(unused_variables)]
pub extern fn cxs_proof_set_connection(proof_handle: u32, connection_handle: u32) -> u32 { error::SUCCESS.code_num }
#[allow(unused_variables, unused_mut)]
pub extern fn cxs_proof_send_request(proof_handle: u32) -> u32 { error::SUCCESS.code_num }
#[allow(unused_variables, unused_mut)]
pub extern fn cxs_proof_get_proof_offer(proof_handle: u32, response_data: *mut c_char) -> u32 { error::SUCCESS.code_num }
#[allow(unused_variables)]
pub extern fn cxs_proof_validate_response(proof_handle: u32, response_data: *const c_char) -> u32 { error::SUCCESS.code_num }
#[allow(unused_variables, unused_mut)]
pub extern fn cxs_proof_list_state(status_array: *mut CxsStatus) -> u32 { error::SUCCESS.code_num }
#[allow(unused_variables, unused_mut)]
pub extern fn cxs_proof_get_state(proof_handle: u32, status: *mut c_char) -> u32 { error::SUCCESS.code_num }

#[cfg(test)]
mod tests {

    use super::*;
    use api::CxsStateType;
    use std::path::Path;
    use std::ffi::CString;
    use std::error::Error;
    use std::io::prelude::*;
    use std::fs;

    #[test]
    fn test_init_with_file() {
        let config_path = "/tmp/test_init.json";
        let path = Path::new(config_path);

        let mut file = match fs::File::create(&path) {
            Err(why) => panic!("couldn't create sample config file: {}", why.description()),
            Ok(file) => file,
        };

        let content = "{ \"pool_name\" : \"my_pool\", \"config_name\":\"my_config\", \"wallet_name\":\"my_wallet\"}";
        match file.write_all(content.as_bytes()) {
            Err(why) => panic!("couldn't write to sample config file: {}", why.description()),
            Ok(_) => println!("sample config ready"),
        }

        let result = cxs_init(CString::new(config_path).unwrap().into_raw());
        assert_eq!(result,0);
        // Leave file around or other concurrent tests will fail
        //fs::remove_file(config_path).unwrap();
    }

    #[test]
    fn test_init_bad_path() {
        let empty_str = CString::new("").unwrap().into_raw();
        assert_eq!(error::UNKNOWN_ERROR.code_num,cxs_init(empty_str));
    }

    #[test]
    fn test_init_no_config_path() {
        let result = cxs_init(ptr::null());
        assert_eq!(result,0);
    }

    #[test]
    fn test_cxs_connection_create() {
        let mut handle: u32 = 0;
        let rc = cxs_connection_create(CString::new("test_create").unwrap().into_raw(), &mut handle);
        assert_eq!(rc, error::SUCCESS.code_num);
        assert!(handle > 0);
    }

    #[test]
    fn test_cxs_connection_create_fails() {
        let rc = cxs_connection_create(CString::new("test_create_fails").unwrap().into_raw(), ptr::null_mut());
        assert_eq!(rc, error::UNKNOWN_ERROR.code_num);

        let rc = cxs_connection_create(ptr::null(),ptr::null_mut());
        assert_eq!(rc, error::UNKNOWN_ERROR.code_num);
    }

    #[test]
    fn test_cxs_connection_connect() {
        let mut handle: u32 = 0;
        let rc = cxs_connection_create(CString::new("test_connect").unwrap().into_raw(), &mut handle);
        assert_eq!(rc, error::SUCCESS.code_num);
        assert!(handle > 0);

        let rc = cxs_connection_connect(handle);
        assert_eq!(rc, error::SUCCESS.code_num);
    }

    #[test]
    fn test_cxs_connection_connect_fails() {
        let rc = cxs_connection_connect(0);
        assert_eq!(rc, error::INVALID_CONNECTION_HANDLE.code_num);
    }

    #[test]
    fn test_cxs_connection_get_state() {
        let mut handle: u32 = 0;
        let rc = cxs_connection_create(CString::new("test_get_state").unwrap().into_raw(), &mut handle);
        assert_eq!(rc, error::SUCCESS.code_num);
        assert!(handle > 0);

        let mut state: u32 = 0;
        let rc = cxs_connection_get_state(handle, &mut state);
        assert_eq!(rc, error::SUCCESS.code_num);
        assert_eq!(state,CxsStateType::CxsStateInitialized as u32);
    }

    #[test]
    fn test_cxs_connection_get_state_fails() {
        let mut handle: u32 = 0;
        let rc = cxs_connection_create(CString::new("test_get_state_fails").unwrap().into_raw(), &mut handle);
        assert_eq!(rc, error::SUCCESS.code_num);
        assert!(handle > 0);

        let rc = cxs_connection_get_state(handle, ptr::null_mut());
        assert_eq!(rc, error::UNKNOWN_ERROR.code_num);

        let rc = cxs_connection_get_state(0, ptr::null_mut());
        assert_eq!(rc, error::UNKNOWN_ERROR.code_num);
    }

    #[test]
    #[allow(unused_assignments)]
    fn test_cxs_connection_get_data() {
        let mut handle: u32 = 0;
        let rc = cxs_connection_create(CString::new("test_get_data").unwrap().into_raw(), &mut handle);
        assert_eq!(rc, error::SUCCESS.code_num);
        assert!(handle > 0);

        let data = cxs_connection_get_data(handle);
        let mut final_string = String::new();

        unsafe {
            let c_string = CString::from_raw(data);
            final_string = c_string.into_string().unwrap();
        }

        assert!(final_string.len() > 0);
    }

    #[test]
    fn test_cxs_connection_get_data_fails() {
        let data = cxs_connection_get_data(0);

        assert_eq!(data, ptr::null_mut());
    }

    #[test]
    fn test_cxs_connection_release() {
        let mut handle: u32 = 0;
        let rc = cxs_connection_create(CString::new("test_release").unwrap().into_raw(), &mut handle);
        assert_eq!(rc, error::SUCCESS.code_num);
        assert!(handle > 0);

        let rc = cxs_connection_release(handle);
        assert_eq!(rc, error::SUCCESS.code_num);
        let rc = cxs_connection_connect(handle);
        assert_eq!(rc, error::INVALID_CONNECTION_HANDLE.code_num);
    }
}
<|endoftext|>