Skip to content

Instantly share code, notes, and snippets.

@lilith
Created August 30, 2016 21:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lilith/044ae7d10733751ad4c8b583e7bad5c1 to your computer and use it in GitHub Desktop.
Save lilith/044ae7d10733751ad4c8b583e7bad5c1 to your computer and use it in GitHub Desktop.
#![feature(alloc)]
#![feature(oom)]
pub mod ffi;
pub mod boring;
pub mod parsing;
#[macro_use]
extern crate json;
extern crate libc;
extern crate alloc;
use std::ptr;
use std::cell::RefCell;
struct ContextPtr {
ptr: Option<*mut ::ffi::Context>
}
pub struct Context{
p: RefCell<ContextPtr>
}
struct JobPtr{
ptr: Option<*mut ::ffi::Job>
}
pub struct Job{
p: RefCell<JobPtr>
}
#[derive(Debug, PartialEq)]
pub enum FlowError {
ContextInvalid,
Oom,
ErrNotImpl
}
pub type Result<T> = std::result::Result<T, FlowError>;
impl ContextPtr {
fn destroy(&mut self){
unsafe {
self.ptr = match self.ptr{
Some(ptr) => {
::ffi::flow_context_destroy(ptr);
None
}
_ => None
}
}
}
}
impl Drop for Context {
fn drop(&mut self) {
(*self.p.borrow_mut()).destroy();
}
}
impl Context {
pub fn create() -> Context {
unsafe {
let ptr = ::ffi::flow_context_create();
if ptr.is_null() {
panic!("OOM");
} else {
Context {
p: RefCell::new(ContextPtr { ptr: Some(ptr) }),
}
}
}
}
fn get_error_copy(&self) -> Option<FlowError> {
unsafe {
match (*self.p.borrow()).ptr {
Some(ptr) if ::ffi::flow_context_has_error(ptr) => Some(FlowError::ErrNotImpl),
None => Some(FlowError::ContextInvalid),
Some(_) => None
}
}
}
pub fn destroy(&mut self) -> Result<()> {
let ref mut b = *self.p.borrow_mut();
match b.ptr {
None => Ok(()),
Some(ptr) => unsafe {
if !::ffi::flow_context_begin_terminate(ptr) {
//Already borrowed; will panic!
//This kind of bug is only exposed at runtime, now.
//Code reuse will require two copies of every function
//One against the ContextPtr, to be reused
//One exposed publicly against the Context, which performs the borrowing
//Same scenario will occur with other types.
let copy = self.get_error_copy().unwrap();
b.destroy();
Err(copy)
} else {
b.destroy();
Ok(())
}
}
}
}
pub fn create_job(&mut self) -> Result<Job> {
let ref b = *self.p.borrow_mut();
match b.ptr {
None => Err(FlowError::ContextInvalid),
Some(ptr) => unsafe {
let p = ::ffi::flow_job_create(ptr);
if p.is_null() {
Err(FlowError::Oom)
} else {
Ok(Job { p: RefCell::new(JobPtr { ptr: Some(p) }) })
}
}
}
}
}
#[test]
fn it_works() {
let mut c = Context::create();
let j = c.create_job().unwrap();
let j2 = c.create_job().unwrap();
assert_eq!(c.destroy(), Ok(()));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment