1use std::cell::RefCell;
2use std::fmt::{self, Write};
3use std::str;
4
5use time::{self, Duration};
6
7pub struct Now(());
8
9pub fn now() -> Now {
12 Now(())
13}
14
15struct LastRenderedNow {
32 bytes: [u8; 128],
33 amt: usize,
34 next_update: time::Timespec,
35}
36
37thread_local!(static LAST: RefCell<LastRenderedNow> = RefCell::new(LastRenderedNow {
38 bytes: [0; 128],
39 amt: 0,
40 next_update: time::Timespec::new(0, 0),
41}));
42
43impl fmt::Display for Now {
44 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
45 LAST.with(|cache| {
46 let mut cache = cache.borrow_mut();
47 let now = time::get_time();
48 if now > cache.next_update {
49 cache.update(now);
50 }
51 f.write_str(cache.buffer())
52 })
53 }
54}
55
56impl LastRenderedNow {
57 fn buffer(&self) -> &str {
58 str::from_utf8(&self.bytes[..self.amt]).unwrap()
59 }
60
61 fn update(&mut self, now: time::Timespec) {
62 self.amt = 0;
63 write!(LocalBuffer(self), "{}", time::at(now).rfc822()).unwrap();
64 self.next_update = now + Duration::seconds(1);
65 self.next_update.nsec = 0;
66 }
67}
68
69struct LocalBuffer<'a>(&'a mut LastRenderedNow);
70
71impl<'a> fmt::Write for LocalBuffer<'a> {
72 fn write_str(&mut self, s: &str) -> fmt::Result {
73 let start = self.0.amt;
74 let end = start + s.len();
75 self.0.bytes[start..end].copy_from_slice(s.as_bytes());
76 self.0.amt += s.len();
77 Ok(())
78 }
79}