1#![warn(missing_docs)]
7
8#[macro_use]
9extern crate slog;
10extern crate slog_extra;
11extern crate thread_local;
12
13use slog::{Drain, DrainExt};
14
15use std::cell::RefCell;
16
17use std::sync::Mutex;
18use std::io;
19use slog::Record;
20
21use slog_extra::Async;
22use slog::OwnedKeyValueList;
23
24include!("format.rs");
25
26thread_local! {
27 static TL_BUF: RefCell<Vec<u8>> = RefCell::new(Vec::with_capacity(128))
28}
29
30pub struct Streamer<W: io::Write, F: Format> {
35 io: Mutex<W>,
36 format: F,
37}
38
39impl<W: io::Write, F: Format> Streamer<W, F> {
40 pub fn new(io: W, format: F) -> Self {
42 Streamer {
43 io: Mutex::new(io),
44 format: format,
45 }
46 }
47}
48
49impl<W: 'static + io::Write + Send, F: Format + Send> Drain for Streamer<W, F> {
50 type Error = io::Error;
51
52 fn log(&self, info: &Record, logger_values: &OwnedKeyValueList) -> io::Result<()> {
53
54 TL_BUF.with(|buf| {
55 let mut buf = buf.borrow_mut();
56 let res = {
57 || {
58 try!(self.format.format(&mut *buf, info, logger_values));
59 {
60 let mut io = try!(self.io
61 .lock()
62 .map_err(|_| io::Error::new(io::ErrorKind::Other, "lock error")));
63 try!(io.write_all(&buf));
64 }
65 Ok(())
66 }
67 }();
68 buf.clear();
69 res
70 })
71 }
72}
73
74pub fn stream<W: io::Write + Send, F: Format>(io: W, format: F) -> Streamer<W, F> {
78 Streamer::new(io, format)
79}
80
81pub fn async_stream<W: io::Write + Send + 'static, F: Format + Send + 'static>(io: W,
85 format: F)
86 -> Async {
87 Async::new(Streamer::new(io, format).fuse())
88}