|
| 1 | +use log::kv::value::Error as ValueError; |
1 | 2 | use slog::{Record, Serializer}; |
2 | 3 |
|
3 | | -pub(crate) struct Visitor { |
4 | | - kvs: Vec<(String, String)>, |
| 4 | +struct Visitor<'s> { |
| 5 | + serializer: &'s mut dyn Serializer, |
5 | 6 | } |
6 | 7 |
|
7 | | -impl Visitor { |
8 | | - pub fn new() -> Self { |
9 | | - Self { kvs: vec![] } |
| 8 | +impl<'s> Visitor<'s> { |
| 9 | + pub fn new(serializer: &'s mut dyn Serializer) -> Self { |
| 10 | + Self { serializer } |
10 | 11 | } |
11 | 12 | } |
12 | 13 |
|
13 | | -impl<'kvs, 'a> log::kv::Visitor<'kvs> for Visitor { |
| 14 | +pub(crate) struct SourceKV<'kvs>(pub &'kvs dyn log::kv::source::Source); |
| 15 | + |
| 16 | +struct KeyVisit<'s> { |
| 17 | + serializer: &'s mut dyn Serializer, |
| 18 | + key: &'s str, |
| 19 | +} |
| 20 | + |
| 21 | +impl<'kvs> log::kv::Visitor<'kvs> for Visitor<'kvs> { |
14 | 22 | fn visit_pair( |
15 | 23 | &mut self, |
16 | 24 | key: log::kv::Key<'kvs>, |
17 | 25 | val: log::kv::Value<'kvs>, |
18 | 26 | ) -> Result<(), log::kv::Error> { |
19 | | - let key = key.to_string(); |
20 | | - if let Some(val) = val.to_borrowed_str() { |
21 | | - let val = val.to_string(); |
22 | | - self.kvs.push((key, val)); |
| 27 | + val.visit(KeyVisit { |
| 28 | + serializer: self.serializer, |
| 29 | + key: key.as_str(), |
| 30 | + }) |
| 31 | + } |
| 32 | +} |
| 33 | + |
| 34 | +macro_rules! visit_to_emit { |
| 35 | + ($t:ty : $vname:ident -> $ename:ident) => { |
| 36 | + fn $vname(&mut self, value: $t) -> Result<(), ValueError> { |
| 37 | + self.serializer |
| 38 | + .$ename(self.key.to_string().into(), value) |
| 39 | + .map_err(to_value_err) |
23 | 40 | } |
24 | | - Ok(()) |
| 41 | + }; |
| 42 | +} |
| 43 | + |
| 44 | +impl<'s> log::kv::value::Visit<'s> for KeyVisit<'s> { |
| 45 | + fn visit_any(&mut self, value: log::kv::Value<'_>) -> Result<(), ValueError> { |
| 46 | + let key = self.key.to_string().into(); |
| 47 | + self.serializer |
| 48 | + .emit_arguments(key, &format_args!("{}", value)) |
| 49 | + .map_err(to_value_err) |
25 | 50 | } |
| 51 | + |
| 52 | + visit_to_emit!(u64: visit_u64 -> emit_u64); |
| 53 | + visit_to_emit!(i64: visit_i64 -> emit_i64); |
| 54 | + visit_to_emit!(u128: visit_u128 -> emit_u128); |
| 55 | + visit_to_emit!(i128: visit_i128 -> emit_i128); |
| 56 | + visit_to_emit!(f64: visit_f64 -> emit_f64); |
| 57 | + visit_to_emit!(bool: visit_bool -> emit_bool); |
| 58 | + visit_to_emit!(&str: visit_str -> emit_str); |
| 59 | + visit_to_emit!(char: visit_char -> emit_char); |
| 60 | + visit_to_emit!(&(dyn std::error::Error + 'static): visit_error -> emit_error); |
26 | 61 | } |
27 | 62 |
|
28 | | -impl slog::KV for Visitor { |
| 63 | +impl slog::KV for SourceKV<'_> { |
29 | 64 | fn serialize(&self, _record: &Record, serializer: &mut dyn Serializer) -> slog::Result { |
30 | | - for (key, val) in &self.kvs { |
31 | | - serializer.emit_str(key.to_owned().into(), val.as_str())?; |
32 | | - } |
33 | | - Ok(()) |
| 65 | + // Unfortunately, there isn't a way for use to pass the original error through. |
| 66 | + self.0 |
| 67 | + .visit(&mut Visitor::new(serializer)) |
| 68 | + .map_err(|_| slog::Error::Other) |
34 | 69 | } |
35 | 70 | } |
| 71 | + |
| 72 | +fn to_value_err(err: slog::Error) -> ValueError { |
| 73 | + use slog::Error::*; |
| 74 | + |
| 75 | + match err { |
| 76 | + Io(e) => e.into(), |
| 77 | + Fmt(e) => e.into(), |
| 78 | + Other => ValueError::boxed(err), |
| 79 | + } |
| 80 | +} |
| 81 | + |
| 82 | +// TODO: support going the other way |
0 commit comments