#![warn(missing_debug_implementations)]
#[macro_use]
extern crate error_chain;
#[macro_use]
extern crate lazy_static;
pub mod error;
use std::ffi::CString;
use std::fmt;
use std::fs::File;
use std::os::raw::c_char;
use std::path::Path;
use error::{Error, ErrorKind};
use std::sync::Mutex;
lazy_static! {
#[derive(Debug)]
pub static ref PROFILER: Mutex<Profiler> = Mutex::new(Profiler {
state: ProfilerState::NotActive,
});
}
#[allow(non_snake_case)]
extern "C" {
fn ProfilerStart(fname: *const c_char) -> i32;
fn ProfilerStop();
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum ProfilerState {
Active,
NotActive,
}
impl fmt::Display for ProfilerState {
fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match *self {
ProfilerState::Active => write!(f, "Active"),
ProfilerState::NotActive => write!(f, "NotActive"),
}
}
}
#[derive(Debug)]
pub struct Profiler {
state: ProfilerState,
}
impl Profiler {
pub fn state(&self) -> ProfilerState {
self.state
}
pub fn start<T: Into<Vec<u8>>>(&mut self, fname: T) -> Result<(), Error> {
if self.state == ProfilerState::NotActive {
let c_fname = try!(CString::new(fname));
try!(check_file_path(c_fname.clone().into_string().unwrap()));
unsafe {
let res = ProfilerStart(c_fname.as_ptr());
if res == 0 {
Err(ErrorKind::InternalError.into())
} else {
self.state = ProfilerState::Active;
Ok(())
}
}
} else {
Err(ErrorKind::InvalidState(self.state).into())
}
}
pub fn stop(&mut self) -> Result<(), Error> {
if self.state == ProfilerState::Active {
unsafe {
ProfilerStop();
}
self.state = ProfilerState::NotActive;
Ok(())
} else {
Err(ErrorKind::InvalidState(self.state).into())
}
}
}
fn check_file_path<P: AsRef<Path>>(path: P) -> Result<(), Error> {
let write_res = File::create(path);
match write_res {
Ok(_) => Ok(()),
Err(e) => Err(e.into()),
}
}