Last active
May 9, 2017 17:19
-
-
Save umurgdk/799c69a15564414891ea5de940955b33 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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