extern crate parking_lot;
use self::parking_lot::Mutex;
use std::fs::{File, OpenOptions, create_dir_all};
use std::path::Path;
use std::fmt;
use std::io;
use std::io::Write;
use handlers::Handler;
pub enum FileHandlerError {
IoError(io::Error),
}
impl From<io::Error> for FileHandlerError {
fn from(e: io::Error) -> Self {
FileHandlerError::IoError(e)
}
}
impl fmt::Debug for FileHandlerError {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
FileHandlerError::IoError(ref err) => write!(f, "{}", err),
}
}
}
struct Context {
file: File,
}
impl Context {
fn new(path: &Path) -> Result<Self, FileHandlerError> {
if let Some(dir) = path.parent() {
create_dir_all(dir)?;
}
Ok(Context {
file: OpenOptions::new().append(true).create(true).open(path)?,
})
}
fn emit(&mut self, msg: &[u8]) {
let _ = self.file.write_all(msg);
}
}
pub fn handler(path: &Path) -> Result<Handler, FileHandlerError> {
let ctx = Context::new(path)?;
let ctx = Mutex::new(ctx);
Ok(Box::new(move |record| {
let mut ctx = ctx.lock();
ctx.emit(record.formatted().as_bytes());
}))
}
#[cfg(test)]
mod tests {
extern crate tempdir;
use self::tempdir::TempDir;
#[test]
fn test_file() {
let dir = TempDir::new("wp-f").unwrap();
let path = dir.path().join("logs").join("test.log");
let mut ctx = super::Context::new(&path).unwrap();
assert!(path.exists());
assert_eq!(path.metadata().unwrap().len(), 0);
ctx.emit("x".as_bytes());
assert_eq!(path.metadata().unwrap().len(), 1);
ctx.emit("x".as_bytes());
assert_eq!(path.metadata().unwrap().len(), 2);
}
}