Skip to content

Instantly share code, notes, and snippets.

@umurgdk
Last active May 9, 2017 17:19
Show Gist options
  • Select an option

  • Save umurgdk/799c69a15564414891ea5de940955b33 to your computer and use it in GitHub Desktop.

Select an option

Save umurgdk/799c69a15564414891ea5de940955b33 to your computer and use it in GitHub Desktop.
extern crate rusqlite;
extern crate app_dirs;
extern crate libc;
use rusqlite::{Connection, Statement};
use app_dirs::*;
use std::fs::{File};
use std::io::prelude::*;
use std::sync::mpsc::channel;
use std::sync::mpsc::{Sender, Receiver};
use std::mem::transmute;
use libc::{c_void, size_t};
const APP_INFO : AppInfo = AppInfo{ name: "fil", author: "Umur Gedik" };
enum Command {
Quit,
Timeout(u32, extern fn(* const c_void), * const c_void),
GetImage(extern fn(*mut u8, size_t, *const c_void), *const c_void)
}
pub struct FilContext {
sender: Sender<Command>,
receiver: Receiver<Command>,
dispatcher: extern fn(*const fn())
}
#[no_mangle]
pub extern "C" fn fil_init(dispatcher: extern fn(*const fn())) -> *mut FilContext {
let (sender, receiver) : (Sender<Command>, Receiver<Command>) = channel();
Box::into_raw(Box::new(FilContext { sender, receiver, dispatcher }))
}
fn dispatch<F>(ctx: &FilContext, closure: F)
where F: FnMut(),
F: 'static
{
let cb: Box<Box<FnMut()>> = Box::new(Box::new(closure));
unsafe {
(ctx.dispatcher)(Box::into_raw(cb) as *mut _);
}
}
fn get_image() -> Vec<u8> {
let db_path = get_app_dir(AppDataType::UserCache, &APP_INFO, "cache.db").unwrap();
let conn: Connection = Connection::open(db_path).unwrap();
let mut stmt: Statement = conn.prepare("select data from images").unwrap();
let mut image_iter = stmt.query_map(&[], |row| {
let data: Vec<u8> = row.get("data");
return data;
}).unwrap();
image_iter.next().unwrap().unwrap()
}
#[no_mangle]
pub extern "C" fn fil_storage_loop(ctx: &FilContext) {
for cmd in &ctx.receiver {
match cmd {
Command::Quit => {
println!("libfil storage_loop is quitting...");
break;
},
Command::Timeout(ms, cb, closure) => {
std::thread::sleep_ms(ms);
dispatch(&ctx, move| | cb(closure));
},
Command::GetImage(cb, user_data) => {
println!("Getting image...");
let mut buffer = get_image().into_boxed_slice();
dispatch(&ctx, move || {
cb(buffer.as_mut_ptr(), buffer.len() as size_t, user_data);
});
}
}
}
}
#[no_mangle]
pub extern "C" fn fil_invoke_fun(cb: *mut c_void) {
let mut closure: Box<Box<FnMut()>> = unsafe { Box::from_raw(cb as *mut Box<FnMut()>) };
closure();
}
#[no_mangle]
pub extern "C" fn fil_storage_timeout(ctx: &FilContext, time: u32, cb: extern fn(*const c_void), closure: *const c_void) {
ctx.sender.send(Command::Timeout(time, cb, closure)).unwrap();
}
#[no_mangle]
pub extern "C" fn fil_get_image(ctx: &FilContext, cb: extern fn(*mut u8, size_t, *const c_void), user_data: *const c_void) {
ctx.sender.send(Command::GetImage(cb, user_data)).unwrap();
}
#[no_mangle]
pub extern "C" fn fil_storage_stop(ctx: &FilContext) {
ctx.sender.send(Command::Quit).unwrap();
}
#[no_mangle]
pub extern "C" fn fil_terminate(ctx: *mut FilContext) {
unsafe {
Box::from_raw(ctx);
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment