#![cfg_attr(not(feature = "std"), feature(alloc))]
#![cfg_attr(not(feature = "std"), feature(collections))]
#![warn(missing_docs)]
#![no_std]
#[cfg(not(feature = "std"))]
extern crate alloc;
#[cfg(not(feature = "std"))]
extern crate collections;
#[macro_use]
#[cfg(feature = "std")]
extern crate std;
mod key;
pub use self::key::Key;
#[cfg(not(feature = "std"))]
use alloc::arc::Arc;
#[cfg(not(feature = "std"))]
use alloc::boxed::Box;
#[cfg(not(feature = "std"))]
use alloc::rc::Rc;
#[cfg(not(feature = "std"))]
use collections::string::String;
#[cfg(feature = "nested-values")]
extern crate erased_serde;
use core::{convert, fmt, result};
use core::str::FromStr;
#[cfg(feature = "std")]
use std::boxed::Box;
#[cfg(feature = "std")]
use std::panic::{RefUnwindSafe, UnwindSafe};
#[cfg(feature = "std")]
use std::rc::Rc;
#[cfg(feature = "std")]
use std::string::String;
#[cfg(feature = "std")]
use std::sync::Arc;
#[macro_export]
macro_rules! o(
($($args:tt)*) => {
$crate::OwnedKV(kv!($($args)*))
};
);
#[macro_export]
macro_rules! slog_o(
($($args:tt)*) => {
$crate::OwnedKV(slog_kv!($($args)*))
};
);
#[macro_export]
macro_rules! b(
($($args:tt)*) => {
$crate::BorrowedKV(&kv!($($args)*))
};
);
#[macro_export]
macro_rules! slog_b(
($($args:tt)*) => {
$crate::BorrowedKV(&slog_kv!($($args)*))
};
);
#[macro_export]
macro_rules! kv(
(@ $args_ready:expr; $k:expr => %$v:expr) => {
kv!(@ ($crate::SingleKV::from(($k, format_args!("{}", $v))), $args_ready); )
};
(@ $args_ready:expr; $k:expr => %$v:expr, $($args:tt)* ) => {
kv!(@ ($crate::SingleKV::from(($k, format_args!("{}", $v))), $args_ready); $($args)* )
};
(@ $args_ready:expr; $k:expr => ?$v:expr) => {
kv!(@ ($crate::SingleKV::from(($k, format_args!("{:?}", $v))), $args_ready); )
};
(@ $args_ready:expr; $k:expr => ?$v:expr, $($args:tt)* ) => {
kv!(@ ($crate::SingleKV::from(($k, format_args!("{:?}", $v))), $args_ready); $($args)* )
};
(@ $args_ready:expr; $k:expr => $v:expr) => {
kv!(@ ($crate::SingleKV::from(($k, $v)), $args_ready); )
};
(@ $args_ready:expr; $k:expr => $v:expr, $($args:tt)* ) => {
kv!(@ ($crate::SingleKV::from(($k, $v)), $args_ready); $($args)* )
};
(@ $args_ready:expr; $kv:expr) => {
kv!(@ ($kv, $args_ready); )
};
(@ $args_ready:expr; $kv:expr, $($args:tt)* ) => {
kv!(@ ($kv, $args_ready); $($args)* )
};
(@ $args_ready:expr; ) => {
$args_ready
};
(@ $args_ready:expr;, ) => {
$args_ready
};
($($args:tt)*) => {
kv!(@ (); $($args)*)
};
);
#[macro_export]
macro_rules! slog_kv(
(@ $args_ready:expr; $k:expr => %$v:expr) => {
slog_kv!(@ ($crate::SingleKV::from(($k, format_args!("{}", $v))), $args_ready); )
};
(@ $args_ready:expr; $k:expr => %$v:expr, $($args:tt)* ) => {
slog_kv!(@ ($crate::SingleKV::from(($k, format_args!("{}", $v))), $args_ready); $($args)* )
};
(@ $args_ready:expr; $k:expr => ?$v:expr) => {
kv!(@ ($crate::SingleKV::from(($k, format_args!("{:?}", $v))), $args_ready); )
};
(@ $args_ready:expr; $k:expr => ?$v:expr, $($args:tt)* ) => {
kv!(@ ($crate::SingleKV::from(($k, format_args!("{:?}", $v))), $args_ready); $($args)* )
};
(@ $args_ready:expr; $k:expr => $v:expr) => {
slog_kv!(@ ($crate::SingleKV::from(($k, $v)), $args_ready); )
};
(@ $args_ready:expr; $k:expr => $v:expr, $($args:tt)* ) => {
slog_kv!(@ ($crate::SingleKV::from(($k, $v)), $args_ready); $($args)* )
};
(@ $args_ready:expr; $slog_kv:expr) => {
slog_kv!(@ ($slog_kv, $args_ready); )
};
(@ $args_ready:expr; $slog_kv:expr, $($args:tt)* ) => {
slog_kv!(@ ($slog_kv, $args_ready); $($args)* )
};
(@ $args_ready:expr; ) => {
$args_ready
};
(@ $args_ready:expr;, ) => {
$args_ready
};
($($args:tt)*) => {
slog_kv!(@ (); $($args)*)
};
);
#[macro_export]
macro_rules! record_static(
($lvl:expr, $tag:expr,) => { record_static!($lvl, $tag) };
($lvl:expr, $tag:expr) => {{
static LOC : $crate::RecordLocation = $crate::RecordLocation {
file: file!(),
line: line!(),
column: column!(),
function: "",
module: module_path!(),
};
$crate::RecordStatic {
location : &LOC,
level: $lvl,
tag : $tag,
}
}};
);
#[macro_export]
macro_rules! slog_record_static(
($lvl:expr, $tag:expr,) => { slog_record_static!($lvl, $tag) };
($lvl:expr, $tag:expr) => {{
static LOC : $crate::RecordLocation = $crate::RecordLocation {
file: file!(),
line: line!(),
column: column!(),
function: "",
module: module_path!(),
};
$crate::RecordStatic {
location : &LOC,
level: $lvl,
tag: $tag,
}
}};
);
#[macro_export]
macro_rules! record(
($lvl:expr, $tag:expr, $args:expr, $b:expr,) => {
record!($lvl, $tag, $args, $b)
};
($lvl:expr, $tag:expr, $args:expr, $b:expr) => {{
#[allow(dead_code)]
static RS : $crate::RecordStatic<'static> = record_static!($lvl, $tag);
$crate::Record::new(&RS, $args, $b)
}};
);
#[macro_export]
macro_rules! slog_record(
($lvl:expr, $tag:expr, $args:expr, $b:expr,) => {
slog_record!($lvl, $tag, $args, $b)
};
($lvl:expr, $tag:expr, $args:expr, $b:expr) => {{
static RS : $crate::RecordStatic<'static> = slog_record_static!($lvl,
$tag);
$crate::Record::new(&RS, $args, $b)
}};
);
#[macro_export]
macro_rules! log(
(2 @ { $($fmt:tt)* }, { $($kv:tt)* }, $l:expr, $lvl:expr, $tag:expr, $msg_fmt:expr) => {
$l.log(&record!($lvl, $tag, &format_args!($msg_fmt, $($fmt)*), b!($($kv)*)))
};
(2 @ { $($fmt:tt)* }, { $($kv:tt)* }, $l:expr, $lvl:expr, $tag:expr, $msg_fmt:expr,) => {
log!(2 @ { $($fmt)* }, { $($kv)* }, $l, $lvl, $tag, $msg_fmt)
};
(2 @ { $($fmt:tt)* }, { $($kv:tt)* }, $l:expr, $lvl:expr, $tag:expr, $msg_fmt:expr;) => {
log!(2 @ { $($fmt)* }, { $($kv)* }, $l, $lvl, $tag, $msg_fmt)
};
(2 @ { $($fmt:tt)* }, { $($kv:tt)* }, $l:expr, $lvl:expr, $tag:expr, $msg_fmt:expr, $($args:tt)*) => {
log!(2 @ { $($fmt)* }, { $($kv)* $($args)*}, $l, $lvl, $tag, $msg_fmt)
};
(1 @ { $($fmt:tt)* }, { $($kv:tt)* }, $l:expr, $lvl:expr, $tag:expr, $msg_fmt:expr, $k:ident = $v:expr) => {
log!(2 @ { $($fmt)* $k = $v }, { $($kv)* stringify!($k) => $v, }, $l, $lvl, $tag, $msg_fmt)
};
(1 @ { $($fmt:tt)* }, { $($kv:tt)* }, $l:expr, $lvl:expr, $tag:expr, $msg_fmt:expr, $k:ident = $v:expr;) => {
log!(2 @ { $($fmt)* $k = $v }, { $($kv)* stringify!($k) => $v, }, $l, $lvl, $tag, $msg_fmt)
};
(1 @ { $($fmt:tt)* }, { $($kv:tt)* }, $l:expr, $lvl:expr, $tag:expr, $msg_fmt:expr, $k:ident = $v:expr,) => {
log!(2 @ { $($fmt)* $k = $v }, { $($kv)* stringify!($k) => $v, }, $l, $lvl, $tag, $msg_fmt)
};
(1 @ { $($fmt:tt)* }, { $($kv:tt)* }, $l:expr, $lvl:expr, $tag:expr, $msg_fmt:expr, $k:ident = $v:expr; $($args:tt)*) => {
log!(2 @ { $($fmt)* $k = $v }, { $($kv)* stringify!($k) => $v, }, $l, $lvl, $tag, $msg_fmt, $($args)*)
};
(1 @ { $($fmt:tt)* }, { $($kv:tt)* }, $l:expr, $lvl:expr, $tag:expr, $msg_fmt:expr, $k:ident = $v:expr, $($args:tt)*) => {
log!(1 @ { $($fmt)* $k = $v, }, { $($kv)* stringify!($k) => $v, }, $l, $lvl, $tag, $msg_fmt, $($args)*)
};
(1 @ { $($fmt:tt)* }, { $($kv:tt)* }, $l:expr, $lvl:expr, $tag:expr, $msg_fmt:expr,) => {
log!(2 @ { $($fmt)* }, { $($kv)* }, $l, $lvl, $tag, $msg_fmt)
};
(1 @ { $($fmt:tt)* }, { $($kv:tt)* }, $l:expr, $lvl:expr, $tag:expr, $msg_fmt:expr) => {
log!(2 @ { $($fmt)* }, { $($kv)* }, $l, $lvl, $tag, $msg_fmt)
};
(1 @ { $($fmt:tt)* }, { $($kv:tt)* }, $l:expr, $lvl:expr, $tag:expr, $msg_fmt:expr, ; $($args:tt)*) => {
log!(1 @ { $($fmt)* }, { $($kv)* }, $l, $lvl, $tag, $msg_fmt; $($args)*)
};
(1 @ { $($fmt:tt)* }, { $($kv:tt)* }, $l:expr, $lvl:expr, $tag:expr, $msg_fmt:expr; $($args:tt)*) => {
log!(2 @ { $($fmt)* }, { $($kv)* }, $l, $lvl, $tag, $msg_fmt, $($args)*)
};
(1 @ { $($fmt:tt)* }, { $($kv:tt)* }, $l:expr, $lvl:expr, $tag:expr, $msg_fmt:expr, $f:tt $($args:tt)*) => {
log!(1 @ { $($fmt)* $f }, { $($kv)* }, $l, $lvl, $tag, $msg_fmt, $($args)*)
};
($l:expr, $lvl:expr, $tag:expr, $($args:tt)*) => {
if $lvl.as_usize() <= $crate::__slog_static_max_level().as_usize() {
log!(1 @ { }, { }, $l, $lvl, $tag, $($args)*)
}
};
);
#[macro_export]
macro_rules! slog_log(
(2 @ { $($fmt:tt)* }, { $($kv:tt)* }, $l:expr, $lvl:expr, $tag:expr, $msg_fmt:expr) => {
$l.log(&slog_record!($lvl, $tag, &format_args!($msg_fmt, $($fmt)*), slog_b!($($kv)*)))
};
(2 @ { $($fmt:tt)* }, { $($kv:tt)* }, $l:expr, $lvl:expr, $tag:expr, $msg_fmt:expr,) => {
slog_log!(2 @ { $($fmt)* }, { $($kv)* }, $l, $lvl, $tag, $msg_fmt)
};
(2 @ { $($fmt:tt)* }, { $($kv:tt)* }, $l:expr, $lvl:expr, $tag:expr, $msg_fmt:expr;) => {
slog_log!(2 @ { $($fmt)* }, { $($kv)* }, $l, $lvl, $tag, $msg_fmt)
};
(2 @ { $($fmt:tt)* }, { $($kv:tt)* }, $l:expr, $lvl:expr, $tag:expr, $msg_fmt:expr, $($args:tt)*) => {
slog_log!(2 @ { $($fmt)* }, { $($kv)* $($args)*}, $l, $lvl, $tag, $msg_fmt)
};
(1 @ { $($fmt:tt)* }, { $($kv:tt)* }, $l:expr, $lvl:expr, $tag:expr, $msg_fmt:expr, $k:ident = $v:expr) => {
slog_log!(2 @ { $($fmt)* $k = $v }, { $($kv)* stringify!($k) => $v, }, $l, $lvl, $tag, $msg_fmt)
};
(1 @ { $($fmt:tt)* }, { $($kv:tt)* }, $l:expr, $lvl:expr, $tag:expr, $msg_fmt:expr, $k:ident = $v:expr;) => {
slog_log!(2 @ { $($fmt)* $k = $v }, { $($kv)* stringify!($k) => $v, }, $l, $lvl, $tag, $msg_fmt)
};
(1 @ { $($fmt:tt)* }, { $($kv:tt)* }, $l:expr, $lvl:expr, $tag:expr, $msg_fmt:expr, $k:ident = $v:expr,) => {
slog_log!(2 @ { $($fmt)* $k = $v }, { $($kv)* stringify!($k) => $v, }, $l, $lvl, $tag, $msg_fmt)
};
(1 @ { $($fmt:tt)* }, { $($kv:tt)* }, $l:expr, $lvl:expr, $tag:expr, $msg_fmt:expr, $k:ident = $v:expr; $($args:tt)*) => {
slog_log!(2 @ { $($fmt)* $k = $v }, { $($kv)* stringify!($k) => $v, }, $l, $lvl, $tag, $msg_fmt, $($args)*)
};
(1 @ { $($fmt:tt)* }, { $($kv:tt)* }, $l:expr, $lvl:expr, $tag:expr, $msg_fmt:expr, $k:ident = $v:expr, $($args:tt)*) => {
slog_log!(1 @ { $($fmt)* $k = $v, }, { $($kv)* stringify!($k) => $v, }, $l, $lvl, $tag, $msg_fmt, $($args)*)
};
(1 @ { $($fmt:tt)* }, { $($kv:tt)* }, $l:expr, $lvl:expr, $tag:expr, $msg_fmt:expr,) => {
slog_log!(2 @ { $($fmt)* }, { $($kv)* }, $l, $lvl, $tag, $msg_fmt)
};
(1 @ { $($fmt:tt)* }, { $($kv:tt)* }, $l:expr, $lvl:expr, $tag:expr, $msg_fmt:expr) => {
slog_log!(2 @ { $($fmt)* }, { $($kv)* }, $l, $lvl, $tag, $msg_fmt)
};
(1 @ { $($fmt:tt)* }, { $($kv:tt)* }, $l:expr, $lvl:expr, $tag:expr, $msg_fmt:expr, ; $($args:tt)*) => {
slog_log!(1 @ { $($fmt)* }, { $($kv)* }, $l, $lvl, $tag, $msg_fmt; $($args)*)
};
(1 @ { $($fmt:tt)* }, { $($kv:tt)* }, $l:expr, $lvl:expr, $tag:expr, $msg_fmt:expr; $($args:tt)*) => {
slog_log!(2 @ { $($fmt)* }, { $($kv)* }, $l, $lvl, $tag, $msg_fmt, $($args)*)
};
(1 @ { $($fmt:tt)* }, { $($kv:tt)* }, $l:expr, $lvl:expr, $tag:expr, $msg_fmt:expr, $f:tt $($args:tt)*) => {
slog_log!(1 @ { $($fmt)* $f }, { $($kv)* }, $l, $lvl, $tag, $msg_fmt, $($args)*)
};
($l:expr, $lvl:expr, $tag:expr, $($args:tt)*) => {
if $lvl.as_usize() <= $crate::__slog_static_max_level().as_usize() {
slog_log!(1 @ { }, { }, $l, $lvl, $tag, $($args)*)
}
};
);
#[macro_export]
macro_rules! crit(
($l:expr, #$tag:expr, $($args:tt)+) => {
log!($l, $crate::Level::Critical, $tag, $($args)+)
};
($l:expr, $($args:tt)+) => {
log!($l, $crate::Level::Critical, "", $($args)+)
};
);
#[macro_export]
macro_rules! slog_crit(
($l:expr, #$tag:expr, $($args:tt)+) => {
slog_log!($l, $crate::Level::Critical, $tag, $($args)+)
};
($l:expr, $($args:tt)+) => {
slog_log!($l, $crate::Level::Critical, "", $($args)+)
};
);
#[macro_export]
macro_rules! error(
($l:expr, #$tag:expr, $($args:tt)+) => {
log!($l, $crate::Level::Error, $tag, $($args)+)
};
($l:expr, $($args:tt)+) => {
log!($l, $crate::Level::Error, "", $($args)+)
};
);
#[macro_export]
macro_rules! slog_error(
($l:expr, #$tag:expr, $($args:tt)+) => {
slog_log!($l, $crate::Level::Error, $tag, $($args)+)
};
($l:expr, $($args:tt)+) => {
slog_log!($l, $crate::Level::Error, "", $($args)+)
};
);
#[macro_export]
macro_rules! warn(
($l:expr, #$tag:expr, $($args:tt)+) => {
log!($l, $crate::Level::Warning, $tag, $($args)+)
};
($l:expr, $($args:tt)+) => {
log!($l, $crate::Level::Warning, "", $($args)+)
};
);
#[macro_export]
macro_rules! slog_warn(
($l:expr, #$tag:expr, $($args:tt)+) => {
slog_log!($l, $crate::Level::Warning, $tag, $($args)+)
};
($l:expr, $($args:tt)+) => {
slog_log!($l, $crate::Level::Warning, "", $($args)+)
};
);
#[macro_export]
macro_rules! info(
($l:expr, #$tag:expr, $($args:tt)*) => {
log!($l, $crate::Level::Info, $tag, $($args)*)
};
($l:expr, $($args:tt)*) => {
log!($l, $crate::Level::Info, "", $($args)*)
};
);
#[macro_export]
macro_rules! slog_info(
($l:expr, #$tag:expr, $($args:tt)+) => {
slog_log!($l, $crate::Level::Info, $tag, $($args)+)
};
($l:expr, $($args:tt)+) => {
slog_log!($l, $crate::Level::Info, "", $($args)+)
};
);
#[macro_export]
macro_rules! debug(
($l:expr, #$tag:expr, $($args:tt)+) => {
log!($l, $crate::Level::Debug, $tag, $($args)+)
};
($l:expr, $($args:tt)+) => {
log!($l, $crate::Level::Debug, "", $($args)+)
};
);
#[macro_export]
macro_rules! slog_debug(
($l:expr, #$tag:expr, $($args:tt)+) => {
slog_log!($l, $crate::Level::Debug, $tag, $($args)+)
};
($l:expr, $($args:tt)+) => {
slog_log!($l, $crate::Level::Debug, "", $($args)+)
};
);
#[macro_export]
macro_rules! trace(
($l:expr, #$tag:expr, $($args:tt)+) => {
log!($l, $crate::Level::Trace, $tag, $($args)+)
};
($l:expr, $($args:tt)+) => {
log!($l, $crate::Level::Trace, "", $($args)+)
};
);
#[macro_export]
macro_rules! slog_trace(
($l:expr, #$tag:expr, $($args:tt)+) => {
slog_log!($l, $crate::Level::Trace, $tag, $($args)+)
};
($l:expr, $($args:tt)+) => {
slog_log!($l, $crate::Level::Trace, "", $($args)+)
};
($($args:tt)+) => {
slog_log!($crate::Level::Trace, $($args)+)
};
);
#[derive(Clone)]
pub struct Logger<D = Arc<SendSyncRefUnwindSafeDrain<Ok = (), Err = Never>>>
where
D: SendSyncUnwindSafeDrain<Ok = (), Err = Never>,
{
drain: D,
list: OwnedKVList,
}
impl<D> Logger<D>
where
D: SendSyncUnwindSafeDrain<Ok = (), Err = Never>,
{
pub fn root<T>(drain: D, values: OwnedKV<T>) -> Logger
where
D: 'static + SendSyncRefUnwindSafeDrain<Err = Never, Ok = ()>,
T: SendSyncRefUnwindSafeKV + 'static,
{
Logger {
drain: Arc::new(drain)
as Arc<SendSyncRefUnwindSafeDrain<Ok = (), Err = Never>>,
list: OwnedKVList::root(values),
}
}
pub fn root_typed<T>(drain: D, values: OwnedKV<T>) -> Logger<D>
where
D: 'static + SendSyncUnwindSafeDrain<Err = Never, Ok = ()> + Sized,
T: SendSyncRefUnwindSafeKV + 'static,
{
Logger {
drain: drain,
list: OwnedKVList::root(values),
}
}
#[cfg_attr(feature = "cargo-clippy", allow(wrong_self_convention))]
pub fn new<T>(&self, values: OwnedKV<T>) -> Logger<D>
where
T: SendSyncRefUnwindSafeKV + 'static,
D: Clone,
{
Logger {
drain: self.drain.clone(),
list: OwnedKVList::new(values, self.list.node.clone()),
}
}
#[inline]
pub fn log(&self, record: &Record) {
let _ = self.drain.log(record, &self.list);
}
pub fn list(&self) -> &OwnedKVList {
&self.list
}
pub fn into_erased(
self,
) -> Logger<Arc<SendSyncRefUnwindSafeDrain<Ok = (), Err = Never>>>
where
D: SendRefUnwindSafeDrain + 'static,
{
Logger {
drain: Arc::new(self.drain)
as Arc<SendSyncRefUnwindSafeDrain<Ok = (), Err = Never>>,
list: self.list,
}
}
pub fn to_erased(
&self,
) -> Logger<Arc<SendSyncRefUnwindSafeDrain<Ok = (), Err = Never>>>
where
D: SendRefUnwindSafeDrain + 'static + Clone,
{
self.clone().into_erased()
}
}
impl<D> fmt::Debug for Logger<D>
where
D: SendSyncUnwindSafeDrain<Ok = (), Err = Never>,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, "Logger{:?}", self.list));
Ok(())
}
}
impl<D> Drain for Logger<D>
where
D: SendSyncUnwindSafeDrain<Ok = (), Err = Never>,
{
type Ok = ();
type Err = Never;
fn log(
&self,
record: &Record,
values: &OwnedKVList,
) -> result::Result<Self::Ok, Self::Err> {
let chained = OwnedKVList {
node: Arc::new(MultiListNode {
next_node: values.node.clone(),
node: self.list.node.clone(),
}),
};
self.drain.log(record, &chained)
}
#[inline]
fn is_enabled(&self, level: Level) -> bool {
self.drain.is_enabled(level)
}
}
pub trait Drain {
type Ok;
type Err;
fn log(
&self,
record: &Record,
values: &OwnedKVList,
) -> result::Result<Self::Ok, Self::Err>;
#[inline]
fn is_enabled(&self, level: Level) -> bool {
level.as_usize() <= ::__slog_static_max_level().as_usize()
}
#[inline]
fn is_critical_enabled(&self) -> bool {
self.is_enabled(Level::Critical)
}
#[inline]
fn is_error_enabled(&self) -> bool {
self.is_enabled(Level::Error)
}
#[inline]
fn is_warning_enabled(&self) -> bool {
self.is_enabled(Level::Warning)
}
#[inline]
fn is_info_enabled(&self) -> bool {
self.is_enabled(Level::Info)
}
#[inline]
fn is_debug_enabled(&self) -> bool {
self.is_enabled(Level::Debug)
}
#[inline]
fn is_trace_enabled(&self) -> bool {
self.is_enabled(Level::Trace)
}
fn map<F, R>(self, f: F) -> R
where
Self: Sized,
F: FnOnce(Self) -> R,
{
f(self)
}
fn filter<F>(self, f: F) -> Filter<Self, F>
where
Self: Sized,
F: FilterFn,
{
Filter::new(self, f)
}
fn filter_level(self, level: Level) -> LevelFilter<Self>
where
Self: Sized,
{
LevelFilter(self, level)
}
fn map_err<F, E>(self, f: F) -> MapError<Self, E>
where
Self: Sized,
F: MapErrFn<Self::Err, E>,
{
MapError::new(self, f)
}
fn ignore_res(self) -> IgnoreResult<Self>
where
Self: Sized,
{
IgnoreResult::new(self)
}
fn fuse(self) -> Fuse<Self>
where
Self::Err: fmt::Debug,
Self: Sized,
{
self.map(Fuse)
}
}
impl<'a, D: Drain + 'a> Drain for &'a D {
type Ok = D::Ok;
type Err = D::Err;
#[inline]
fn log(
&self,
record: &Record,
values: &OwnedKVList,
) -> result::Result<Self::Ok, Self::Err> {
(**self).log(record, values)
}
#[inline]
fn is_enabled(&self, level: Level) -> bool {
(**self).is_enabled(level)
}
}
impl<'a, D: Drain + 'a> Drain for &'a mut D {
type Ok = D::Ok;
type Err = D::Err;
#[inline]
fn log(
&self,
record: &Record,
values: &OwnedKVList,
) -> result::Result<Self::Ok, Self::Err> {
(**self).log(record, values)
}
#[inline]
fn is_enabled(&self, level: Level) -> bool {
(**self).is_enabled(level)
}
}
#[cfg(feature = "std")]
pub trait SendSyncUnwindSafe: Send + Sync + UnwindSafe {}
#[cfg(feature = "std")]
impl<T> SendSyncUnwindSafe for T
where
T: Send + Sync + UnwindSafe + ?Sized,
{
}
#[cfg(feature = "std")]
pub trait SendSyncUnwindSafeDrain: Drain + Send + Sync + UnwindSafe {}
#[cfg(feature = "std")]
impl<T> SendSyncUnwindSafeDrain for T
where
T: Drain + Send + Sync + UnwindSafe + ?Sized,
{
}
#[cfg(feature = "std")]
pub trait SendSyncRefUnwindSafeDrain: Drain + Send + Sync + RefUnwindSafe {}
#[cfg(feature = "std")]
impl<T> SendSyncRefUnwindSafeDrain for T
where
T: Drain + Send + Sync + RefUnwindSafe + ?Sized,
{
}
#[cfg(feature = "std")]
pub trait MapErrFn<EI, EO>
: 'static + Sync + Send + UnwindSafe + RefUnwindSafe + Fn(EI) -> EO {
}
#[cfg(feature = "std")]
impl<T, EI, EO> MapErrFn<EI, EO> for T
where
T: 'static
+ Sync
+ Send
+ ?Sized
+ UnwindSafe
+ RefUnwindSafe
+ Fn(EI) -> EO,
{
}
#[cfg(feature = "std")]
pub trait FilterFn
: 'static + Sync + Send + UnwindSafe + RefUnwindSafe + Fn(&Record) -> bool {
}
#[cfg(feature = "std")]
impl<T> FilterFn for T
where
T: 'static
+ Sync
+ Send
+ ?Sized
+ UnwindSafe
+ RefUnwindSafe
+ Fn(&Record) -> bool,
{
}
#[cfg(not(feature = "std"))]
pub trait SendSyncUnwindSafeDrain: Drain + Send + Sync {}
#[cfg(not(feature = "std"))]
impl<T> SendSyncUnwindSafeDrain for T
where
T: Drain + Send + Sync + ?Sized,
{
}
#[cfg(not(feature = "std"))]
pub trait SendSyncRefUnwindSafeDrain: Drain + Send + Sync {}
#[cfg(not(feature = "std"))]
impl<T> SendSyncRefUnwindSafeDrain for T
where
T: Drain + Send + Sync + ?Sized,
{
}
#[cfg(feature = "std")]
pub trait SendRefUnwindSafeDrain: Drain + Send + RefUnwindSafe {}
#[cfg(feature = "std")]
impl<T> SendRefUnwindSafeDrain for T
where
T: Drain + Send + RefUnwindSafe + ?Sized,
{
}
#[cfg(not(feature = "std"))]
pub trait SendRefUnwindSafeDrain: Drain + Send {}
#[cfg(not(feature = "std"))]
impl<T> SendRefUnwindSafeDrain for T
where
T: Drain + Send + ?Sized,
{
}
#[cfg(not(feature = "std"))]
pub trait MapErrFn<EI, EO>: 'static + Sync + Send + Fn(EI) -> EO {}
#[cfg(not(feature = "std"))]
impl<T, EI, EO> MapErrFn<EI, EO> for T
where
T: 'static + Sync + Send + ?Sized + Fn(EI) -> EO,
{
}
#[cfg(not(feature = "std"))]
pub trait FilterFn: 'static + Sync + Send + Fn(&Record) -> bool {}
#[cfg(not(feature = "std"))]
impl<T> FilterFn for T
where
T: 'static + Sync + Send + ?Sized + Fn(&Record) -> bool,
{
}
impl<D: Drain + ?Sized> Drain for Box<D> {
type Ok = D::Ok;
type Err = D::Err;
fn log(
&self,
record: &Record,
o: &OwnedKVList,
) -> result::Result<Self::Ok, D::Err> {
(**self).log(record, o)
}
#[inline]
fn is_enabled(&self, level: Level) -> bool {
(**self).is_enabled(level)
}
}
impl<D: Drain + ?Sized> Drain for Arc<D> {
type Ok = D::Ok;
type Err = D::Err;
fn log(
&self,
record: &Record,
o: &OwnedKVList,
) -> result::Result<Self::Ok, D::Err> {
(**self).log(record, o)
}
#[inline]
fn is_enabled(&self, level: Level) -> bool {
(**self).is_enabled(level)
}
}
#[derive(Debug, Copy, Clone)]
pub struct Discard;
impl Drain for Discard {
type Ok = ();
type Err = Never;
fn log(&self, _: &Record, _: &OwnedKVList) -> result::Result<(), Never> {
Ok(())
}
#[inline]
fn is_enabled(&self, _1: Level) -> bool {
false
}
}
#[derive(Debug, Clone)]
pub struct Filter<D: Drain, F>(pub D, pub F)
where
F: Fn(&Record) -> bool + 'static + Send + Sync;
impl<D: Drain, F> Filter<D, F>
where
F: FilterFn,
{
pub fn new(drain: D, cond: F) -> Self {
Filter(drain, cond)
}
}
impl<D: Drain, F> Drain for Filter<D, F>
where
F: FilterFn,
{
type Ok = Option<D::Ok>;
type Err = D::Err;
fn log(
&self,
record: &Record,
logger_values: &OwnedKVList,
) -> result::Result<Self::Ok, Self::Err> {
if (self.1)(record) {
Ok(Some(self.0.log(record, logger_values)?))
} else {
Ok(None)
}
}
#[inline]
fn is_enabled(&self, level: Level) -> bool {
self.0.is_enabled(level)
}
}
#[derive(Debug, Clone)]
pub struct LevelFilter<D: Drain>(pub D, pub Level);
impl<D: Drain> LevelFilter<D> {
pub fn new(drain: D, level: Level) -> Self {
LevelFilter(drain, level)
}
}
impl<D: Drain> Drain for LevelFilter<D> {
type Ok = Option<D::Ok>;
type Err = D::Err;
fn log(
&self,
record: &Record,
logger_values: &OwnedKVList,
) -> result::Result<Self::Ok, Self::Err> {
if record.level().is_at_least(self.1) {
Ok(Some(self.0.log(record, logger_values)?))
} else {
Ok(None)
}
}
#[inline]
fn is_enabled(&self, level: Level) -> bool {
level.is_at_least(self.1) && self.0.is_enabled(level)
}
}
pub struct MapError<D: Drain, E> {
drain: D,
map_fn: Box<MapErrFn<D::Err, E, Output = E>>,
}
impl<D: Drain, E> MapError<D, E> {
pub fn new<F>(drain: D, map_fn: F) -> Self
where
F: MapErrFn<<D as Drain>::Err, E>,
{
MapError {
drain: drain,
map_fn: Box::new(map_fn),
}
}
}
impl<D: Drain, E> Drain for MapError<D, E> {
type Ok = D::Ok;
type Err = E;
fn log(
&self,
record: &Record,
logger_values: &OwnedKVList,
) -> result::Result<Self::Ok, Self::Err> {
self.drain
.log(record, logger_values)
.map_err(|e| (self.map_fn)(e))
}
#[inline]
fn is_enabled(&self, level: Level) -> bool {
self.drain.is_enabled(level)
}
}
#[derive(Debug, Clone)]
pub struct Duplicate<D1: Drain, D2: Drain>(pub D1, pub D2);
impl<D1: Drain, D2: Drain> Duplicate<D1, D2> {
pub fn new(drain1: D1, drain2: D2) -> Self {
Duplicate(drain1, drain2)
}
}
impl<D1: Drain, D2: Drain> Drain for Duplicate<D1, D2> {
type Ok = (D1::Ok, D2::Ok);
type Err = (
result::Result<D1::Ok, D1::Err>,
result::Result<D2::Ok, D2::Err>,
);
fn log(
&self,
record: &Record,
logger_values: &OwnedKVList,
) -> result::Result<Self::Ok, Self::Err> {
let res1 = self.0.log(record, logger_values);
let res2 = self.1.log(record, logger_values);
match (res1, res2) {
(Ok(o1), Ok(o2)) => Ok((o1, o2)),
(r1, r2) => Err((r1, r2)),
}
}
#[inline]
fn is_enabled(&self, level: Level) -> bool {
self.0.is_enabled(level) || self.1.is_enabled(level)
}
}
#[derive(Debug, Clone)]
pub struct Fuse<D: Drain>(pub D)
where
D::Err: fmt::Debug;
impl<D: Drain> Fuse<D>
where
D::Err: fmt::Debug,
{
pub fn new(drain: D) -> Self {
Fuse(drain)
}
}
impl<D: Drain> Drain for Fuse<D>
where
D::Err: fmt::Debug,
{
type Ok = ();
type Err = Never;
fn log(
&self,
record: &Record,
logger_values: &OwnedKVList,
) -> result::Result<Self::Ok, Never> {
let _ = self.0
.log(record, logger_values)
.unwrap_or_else(|e| panic!("slog::Fuse Drain: {:?}", e));
Ok(())
}
#[inline]
fn is_enabled(&self, level: Level) -> bool {
self.0.is_enabled(level)
}
}
#[derive(Clone)]
pub struct IgnoreResult<D: Drain> {
drain: D,
}
impl<D: Drain> IgnoreResult<D> {
pub fn new(drain: D) -> Self {
IgnoreResult { drain: drain }
}
}
impl<D: Drain> Drain for IgnoreResult<D> {
type Ok = ();
type Err = Never;
fn log(
&self,
record: &Record,
logger_values: &OwnedKVList,
) -> result::Result<(), Never> {
let _ = self.drain.log(record, logger_values);
Ok(())
}
#[inline]
fn is_enabled(&self, level: Level) -> bool {
self.drain.is_enabled(level)
}
}
#[cfg(feature = "std")]
#[derive(Clone)]
pub enum MutexDrainError<D: Drain> {
Mutex,
Drain(D::Err),
}
#[cfg(feature = "std")]
impl<D> fmt::Debug for MutexDrainError<D>
where
D: Drain,
D::Err: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
match *self {
MutexDrainError::Mutex => write!(f, "MutexDrainError::Mutex"),
MutexDrainError::Drain(ref e) => e.fmt(f),
}
}
}
#[cfg(feature = "std")]
impl<D> std::error::Error for MutexDrainError<D>
where
D: Drain,
D::Err: fmt::Debug + fmt::Display + std::error::Error,
{
fn description(&self) -> &str {
match *self {
MutexDrainError::Mutex => "Mutex acquire failed",
MutexDrainError::Drain(ref e) => e.description(),
}
}
fn cause(&self) -> Option<&std::error::Error> {
match *self {
MutexDrainError::Mutex => None,
MutexDrainError::Drain(ref e) => Some(e),
}
}
}
#[cfg(feature = "std")]
impl<'a, D: Drain> From<std::sync::PoisonError<std::sync::MutexGuard<'a, D>>>
for MutexDrainError<D> {
fn from(
_: std::sync::PoisonError<std::sync::MutexGuard<'a, D>>,
) -> MutexDrainError<D> {
MutexDrainError::Mutex
}
}
#[cfg(feature = "std")]
impl<D: Drain> fmt::Display for MutexDrainError<D>
where
D::Err: fmt::Display,
{
fn fmt(&self, f: &mut fmt::Formatter) -> result::Result<(), fmt::Error> {
match *self {
MutexDrainError::Mutex => write!(f, "MutexError"),
MutexDrainError::Drain(ref e) => write!(f, "{}", e),
}
}
}
#[cfg(feature = "std")]
impl<D: Drain> Drain for std::sync::Mutex<D> {
type Ok = D::Ok;
type Err = MutexDrainError<D>;
fn log(
&self,
record: &Record,
logger_values: &OwnedKVList,
) -> result::Result<Self::Ok, Self::Err> {
let d = self.lock()?;
d.log(record, logger_values).map_err(MutexDrainError::Drain)
}
#[inline]
fn is_enabled(&self, level: Level) -> bool {
self.lock().ok().map_or(true, |lock| lock.is_enabled(level))
}
}
pub static LOG_LEVEL_NAMES: [&'static str; 7] =
["OFF", "CRITICAL", "ERROR", "WARN", "INFO", "DEBUG", "TRACE"];
pub static LOG_LEVEL_SHORT_NAMES: [&'static str; 7] =
["OFF", "CRIT", "ERRO", "WARN", "INFO", "DEBG", "TRCE"];
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub enum Level {
Critical,
Error,
Warning,
Info,
Debug,
Trace,
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd)]
pub enum FilterLevel {
Off,
Critical,
Error,
Warning,
Info,
Debug,
Trace,
}
impl Level {
pub fn as_short_str(&self) -> &'static str {
LOG_LEVEL_SHORT_NAMES[self.as_usize()]
}
pub fn as_str(&self) -> &'static str {
LOG_LEVEL_NAMES[self.as_usize()]
}
#[inline]
pub fn as_usize(&self) -> usize {
match *self {
Level::Critical => 1,
Level::Error => 2,
Level::Warning => 3,
Level::Info => 4,
Level::Debug => 5,
Level::Trace => 6,
}
}
#[inline]
pub fn from_usize(u: usize) -> Option<Level> {
match u {
1 => Some(Level::Critical),
2 => Some(Level::Error),
3 => Some(Level::Warning),
4 => Some(Level::Info),
5 => Some(Level::Debug),
6 => Some(Level::Trace),
_ => None,
}
}
}
impl FilterLevel {
#[inline]
pub fn as_usize(&self) -> usize {
match *self {
FilterLevel::Off => 0,
FilterLevel::Critical => 1,
FilterLevel::Error => 2,
FilterLevel::Warning => 3,
FilterLevel::Info => 4,
FilterLevel::Debug => 5,
FilterLevel::Trace => 6,
}
}
#[inline]
pub fn from_usize(u: usize) -> Option<FilterLevel> {
match u {
0 => Some(FilterLevel::Off),
1 => Some(FilterLevel::Critical),
2 => Some(FilterLevel::Error),
3 => Some(FilterLevel::Warning),
4 => Some(FilterLevel::Info),
5 => Some(FilterLevel::Debug),
6 => Some(FilterLevel::Trace),
_ => None,
}
}
#[inline]
pub fn max() -> Self {
FilterLevel::Trace
}
#[inline]
pub fn min() -> Self {
FilterLevel::Off
}
}
#[cfg_attr(rustfmt, rustfmt_skip)]
static ASCII_LOWERCASE_MAP: [u8; 256] =
[0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, b' ', b'!', b'"', b'#',
b'$', b'%', b'&', b'\'', b'(', b')', b'*', b'+', b',', b'-', b'.', b'/',
b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'9', b':', b';',
b'<', b'=', b'>', b'?', b'@', b'a', b'b', b'c', b'd', b'e', b'f', b'g',
b'h', b'i', b'j', b'k', b'l', b'm', b'n', b'o', b'p', b'q', b'r', b's',
b't', b'u', b'v', b'w', b'x', b'y', b'z', b'[', b'\\', b']', b'^', b'_',
b'`', b'a', b'b', b'c', b'd', b'e', b'f', b'g', b'h', b'i', b'j', b'k',
b'l', b'm', b'n', b'o', b'p', b'q', b'r', b's', b't', b'u', b'v', b'w',
b'x', b'y', b'z', b'{', b'|', b'}', b'~', 0x7f, 0x80, 0x81, 0x82, 0x83,
0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b,
0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3,
0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb,
0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xe0, 0xe1, 0xe2, 0xe3,
0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb,
0xfc, 0xfd, 0xfe, 0xff];
impl FromStr for Level {
type Err = ();
fn from_str(level: &str) -> core::result::Result<Level, ()> {
LOG_LEVEL_NAMES
.iter()
.position(|&name| {
name.as_bytes().iter().zip(level.as_bytes().iter()).all(
|(a, b)| {
ASCII_LOWERCASE_MAP[*a as usize]
== ASCII_LOWERCASE_MAP[*b as usize]
},
)
})
.map(|p| Level::from_usize(p).unwrap())
.ok_or(())
}
}
impl FromStr for FilterLevel {
type Err = ();
fn from_str(level: &str) -> core::result::Result<FilterLevel, ()> {
LOG_LEVEL_NAMES
.iter()
.position(|&name| {
name.as_bytes().iter().zip(level.as_bytes().iter()).all(
|(a, b)| {
ASCII_LOWERCASE_MAP[*a as usize]
== ASCII_LOWERCASE_MAP[*b as usize]
},
)
})
.map(|p| FilterLevel::from_usize(p).unwrap())
.ok_or(())
}
}
impl fmt::Display for Level {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.as_short_str())
}
}
impl Level {
#[inline]
pub fn is_at_least(&self, level: Self) -> bool {
self.as_usize() <= level.as_usize()
}
}
#[test]
fn level_at_least() {
assert!(Level::Debug.is_at_least(Level::Debug));
assert!(Level::Debug.is_at_least(Level::Trace));
assert!(!Level::Debug.is_at_least(Level::Info));
}
#[test]
fn filterlevel_sanity() {
assert!(Level::Critical.as_usize() > FilterLevel::Off.as_usize());
assert!(Level::Critical.as_usize() == FilterLevel::Critical.as_usize());
assert!(Level::Trace.as_usize() == FilterLevel::Trace.as_usize());
}
#[test]
fn level_from_str() {
assert_eq!("info".parse::<FilterLevel>().unwrap(), FilterLevel::Info);
}
#[doc(hidden)]
#[derive(Clone, Copy)]
pub struct RecordLocation {
pub file: &'static str,
pub line: u32,
pub column: u32,
pub function: &'static str,
pub module: &'static str,
}
pub struct RecordStatic<'a> {
#[doc(hidden)]
pub location: &'a RecordLocation,
#[doc(hidden)]
pub tag: &'a str,
#[doc(hidden)]
pub level: Level,
}
pub struct Record<'a> {
rstatic: &'a RecordStatic<'a>,
msg: &'a fmt::Arguments<'a>,
kv: BorrowedKV<'a>,
}
impl<'a> Record<'a> {
#[inline]
pub fn new(
s: &'a RecordStatic<'a>,
msg: &'a fmt::Arguments<'a>,
kv: BorrowedKV<'a>,
) -> Self {
Record {
rstatic: s,
msg: msg,
kv: kv,
}
}
pub fn msg(&self) -> &fmt::Arguments {
self.msg
}
pub fn level(&self) -> Level {
self.rstatic.level
}
pub fn line(&self) -> u32 {
self.rstatic.location.line
}
pub fn location(&self) -> &RecordLocation {
self.rstatic.location
}
pub fn column(&self) -> u32 {
self.rstatic.location.column
}
pub fn file(&self) -> &'static str {
self.rstatic.location.file
}
pub fn tag(&self) -> &str {
self.rstatic.tag
}
pub fn module(&self) -> &'static str {
self.rstatic.location.module
}
pub fn function(&self) -> &'static str {
self.rstatic.location.function
}
pub fn kv(&self) -> BorrowedKV {
BorrowedKV(self.kv.0)
}
}
macro_rules! impl_default_as_fmt{
($t:ty, $f:ident) => {
fn $f(&mut self, key : Key, val : $t)
-> Result {
self.emit_arguments(key, &format_args!("{}", val))
}
};
}
#[cfg(feature = "nested-values")]
struct SerializerForward<'a, T: 'a + ?Sized>(&'a mut T);
#[cfg(feature = "nested-values")]
impl<'a, T: Serializer + 'a + ?Sized> Serializer for SerializerForward<'a, T> {
fn emit_arguments(&mut self, key: Key, val: &fmt::Arguments) -> Result {
self.0.emit_arguments(key, val)
}
#[cfg(feature = "nested-values")]
fn emit_serde(&mut self, _key: Key, _value: &SerdeValue) -> Result {
panic!();
}
}
pub trait Serializer {
impl_default_as_fmt!(usize, emit_usize);
impl_default_as_fmt!(isize, emit_isize);
impl_default_as_fmt!(bool, emit_bool);
impl_default_as_fmt!(char, emit_char);
impl_default_as_fmt!(u8, emit_u8);
impl_default_as_fmt!(i8, emit_i8);
impl_default_as_fmt!(u16, emit_u16);
impl_default_as_fmt!(i16, emit_i16);
impl_default_as_fmt!(u32, emit_u32);
impl_default_as_fmt!(i32, emit_i32);
impl_default_as_fmt!(f32, emit_f32);
impl_default_as_fmt!(u64, emit_u64);
impl_default_as_fmt!(i64, emit_i64);
impl_default_as_fmt!(f64, emit_f64);
impl_default_as_fmt!(&str, emit_str);
fn emit_unit(&mut self, key: Key) -> Result {
self.emit_arguments(key, &format_args!("()"))
}
fn emit_none(&mut self, key: Key) -> Result {
self.emit_arguments(key, &format_args!(""))
}
fn emit_arguments(&mut self, key: Key, val: &fmt::Arguments) -> Result;
#[cfg(feature = "nested-values")]
fn emit_serde(&mut self, key: Key, value: &SerdeValue) -> Result {
value.serialize_fallback(key, &mut SerializerForward(self))
}
}
struct AsFmtSerializer<F>(pub F)
where
F: for<'a> FnMut(Key, fmt::Arguments<'a>) -> Result;
impl<F> Serializer for AsFmtSerializer<F>
where
F: for<'a> FnMut(Key, fmt::Arguments<'a>) -> Result,
{
fn emit_arguments(&mut self, key: Key, val: &fmt::Arguments) -> Result {
(self.0)(key, *val)
}
}
#[cfg(feature = "nested-values")]
pub trait SerdeValue: erased_serde::Serialize + Value {
fn serialize_fallback(
&self,
_key: Key,
_serializer: &mut Serializer,
) -> Result<()> {
Err(Error::Other)
}
fn as_serde(&self) -> &erased_serde::Serialize;
fn to_sendable(&self) -> Box<SerdeValue + Send + 'static>;
}
pub trait Value {
fn serialize(
&self,
record: &Record,
key: Key,
serializer: &mut Serializer,
) -> Result;
}
impl<'a, V> Value for &'a V
where
V: Value + ?Sized,
{
fn serialize(
&self,
record: &Record,
key: Key,
serializer: &mut Serializer,
) -> Result {
(*self).serialize(record, key, serializer)
}
}
macro_rules! impl_value_for{
($t:ty, $f:ident) => {
impl Value for $t {
fn serialize(&self,
_record : &Record,
key : Key,
serializer : &mut Serializer
) -> Result {
serializer.$f(key, *self)
}
}
};
}
impl_value_for!(usize, emit_usize);
impl_value_for!(isize, emit_isize);
impl_value_for!(bool, emit_bool);
impl_value_for!(char, emit_char);
impl_value_for!(u8, emit_u8);
impl_value_for!(i8, emit_i8);
impl_value_for!(u16, emit_u16);
impl_value_for!(i16, emit_i16);
impl_value_for!(u32, emit_u32);
impl_value_for!(i32, emit_i32);
impl_value_for!(f32, emit_f32);
impl_value_for!(u64, emit_u64);
impl_value_for!(i64, emit_i64);
impl_value_for!(f64, emit_f64);
impl Value for () {
fn serialize(
&self,
_record: &Record,
key: Key,
serializer: &mut Serializer,
) -> Result {
serializer.emit_unit(key)
}
}
impl Value for str {
fn serialize(
&self,
_record: &Record,
key: Key,
serializer: &mut Serializer,
) -> Result {
serializer.emit_str(key, self)
}
}
impl<'a> Value for fmt::Arguments<'a> {
fn serialize(
&self,
_record: &Record,
key: Key,
serializer: &mut Serializer,
) -> Result {
serializer.emit_arguments(key, self)
}
}
impl Value for String {
fn serialize(
&self,
_record: &Record,
key: Key,
serializer: &mut Serializer,
) -> Result {
serializer.emit_str(key, self.as_str())
}
}
impl<T: Value> Value for Option<T> {
fn serialize(
&self,
record: &Record,
key: Key,
serializer: &mut Serializer,
) -> Result {
match *self {
Some(ref s) => s.serialize(record, key, serializer),
None => serializer.emit_none(key),
}
}
}
impl<T> Value for Box<T>
where
T: Value + ?Sized,
{
fn serialize(
&self,
record: &Record,
key: Key,
serializer: &mut Serializer,
) -> Result {
(**self).serialize(record, key, serializer)
}
}
impl<T> Value for Arc<T>
where
T: Value + ?Sized,
{
fn serialize(
&self,
record: &Record,
key: Key,
serializer: &mut Serializer,
) -> Result {
(**self).serialize(record, key, serializer)
}
}
impl<T> Value for Rc<T>
where
T: Value,
{
fn serialize(
&self,
record: &Record,
key: Key,
serializer: &mut Serializer,
) -> Result {
(**self).serialize(record, key, serializer)
}
}
impl<T> Value for core::num::Wrapping<T>
where
T: Value,
{
fn serialize(
&self,
record: &Record,
key: Key,
serializer: &mut Serializer,
) -> Result {
self.0.serialize(record, key, serializer)
}
}
impl<'a> Value for std::path::Display<'a> {
fn serialize(
&self,
_record: &Record,
key: Key,
serializer: &mut Serializer,
) -> Result {
serializer.emit_arguments(key, &format_args!("{}", *self))
}
}
pub struct FnValue<V: Value, F>(pub F)
where
F: for<'c, 'd> Fn(&'c Record<'d>) -> V;
impl<'a, V: 'a + Value, F> Value for FnValue<V, F>
where
F: 'a + for<'c, 'd> Fn(&'c Record<'d>) -> V,
{
fn serialize(
&self,
record: &Record,
key: Key,
serializer: &mut Serializer,
) -> Result {
(self.0)(record).serialize(record, key, serializer)
}
}
#[deprecated(note = "Renamed to `PushFnValueSerializer`")]
pub type PushFnSerializer<'a> = PushFnValueSerializer<'a>;
pub struct PushFnValueSerializer<'a> {
record: &'a Record<'a>,
key: Key,
serializer: &'a mut Serializer,
done: bool,
}
impl<'a> PushFnValueSerializer<'a> {
#[deprecated(note = "Renamed to `emit`")]
pub fn serialize<'b, S: 'b + Value>(self, s: S) -> Result {
self.emit(s)
}
pub fn emit<'b, S: 'b + Value>(mut self, s: S) -> Result {
self.done = true;
s.serialize(self.record, self.key.clone(), self.serializer)
}
}
impl<'a> Drop for PushFnValueSerializer<'a> {
fn drop(&mut self) {
if !self.done {
let _ = self.serializer.emit_unit(self.key.clone());
}
}
}
pub struct PushFnValue<F>(pub F)
where
F: 'static
+ for<'c, 'd> Fn(&'c Record<'d>, PushFnValueSerializer<'c>) -> Result;
impl<F> Value for PushFnValue<F>
where
F: 'static
+ for<'c, 'd> Fn(&'c Record<'d>, PushFnValueSerializer<'c>) -> Result,
{
fn serialize(
&self,
record: &Record,
key: Key,
serializer: &mut Serializer,
) -> Result {
let ser = PushFnValueSerializer {
record: record,
key: key,
serializer: serializer,
done: false,
};
(self.0)(record, ser)
}
}
pub trait KV {
fn serialize(&self, record: &Record, serializer: &mut Serializer)
-> Result;
}
impl<'a, T> KV for &'a T
where
T: KV,
{
fn serialize(
&self,
record: &Record,
serializer: &mut Serializer,
) -> Result {
(**self).serialize(record, serializer)
}
}
#[cfg(feature = "std")]
pub trait SendSyncRefUnwindSafeKV: KV + Send + Sync + RefUnwindSafe {}
#[cfg(feature = "std")]
impl<T> SendSyncRefUnwindSafeKV for T
where
T: KV + Send + Sync + RefUnwindSafe + ?Sized,
{
}
#[cfg(not(feature = "std"))]
pub trait SendSyncRefUnwindSafeKV: KV + Send + Sync {}
#[cfg(not(feature = "std"))]
impl<T> SendSyncRefUnwindSafeKV for T
where
T: KV + Send + Sync + ?Sized,
{
}
pub struct SingleKV<V>(pub Key, pub V)
where
V: Value;
#[cfg(feature = "dynamic-keys")]
impl<V: Value> From<(String, V)> for SingleKV<V> {
fn from(x: (String, V)) -> SingleKV<V> {
SingleKV(Key::from(x.0), x.1)
}
}
#[cfg(feature = "dynamic-keys")]
impl<V: Value> From<(&'static str, V)> for SingleKV<V> {
fn from(x: (&'static str, V)) -> SingleKV<V> {
SingleKV(Key::from(x.0), x.1)
}
}
#[cfg(not(feature = "dynamic-keys"))]
impl<V: Value> From<(&'static str, V)> for SingleKV<V> {
fn from(x: (&'static str, V)) -> SingleKV<V> {
SingleKV(x.0, x.1)
}
}
impl<V> KV for SingleKV<V>
where
V: Value,
{
fn serialize(
&self,
record: &Record,
serializer: &mut Serializer,
) -> Result {
self.1.serialize(record, self.0.clone(), serializer)
}
}
impl KV for () {
fn serialize(
&self,
_record: &Record,
_serializer: &mut Serializer,
) -> Result {
Ok(())
}
}
impl<T: KV, R: KV> KV for (T, R) {
fn serialize(
&self,
record: &Record,
serializer: &mut Serializer,
) -> Result {
try!(self.0.serialize(record, serializer));
self.1.serialize(record, serializer)
}
}
impl<T> KV for Box<T>
where
T: KV + ?Sized,
{
fn serialize(
&self,
record: &Record,
serializer: &mut Serializer,
) -> Result {
(**self).serialize(record, serializer)
}
}
impl<T> KV for Arc<T>
where
T: KV + ?Sized,
{
fn serialize(
&self,
record: &Record,
serializer: &mut Serializer,
) -> Result {
(**self).serialize(record, serializer)
}
}
impl<T> KV for OwnedKV<T>
where
T: SendSyncRefUnwindSafeKV + ?Sized,
{
fn serialize(
&self,
record: &Record,
serializer: &mut Serializer,
) -> Result {
self.0.serialize(record, serializer)
}
}
impl<'a> KV for BorrowedKV<'a> {
fn serialize(
&self,
record: &Record,
serializer: &mut Serializer,
) -> Result {
self.0.serialize(record, serializer)
}
}
pub struct OwnedKV<T>(
#[doc(hidden)]
pub T,
)
where
T: SendSyncRefUnwindSafeKV + ?Sized;
pub struct BorrowedKV<'a>(
#[doc(hidden)]
pub &'a KV,
);
struct OwnedKVListNode<T>
where
T: SendSyncRefUnwindSafeKV + 'static,
{
next_node: Arc<SendSyncRefUnwindSafeKV + 'static>,
kv: T,
}
struct MultiListNode {
next_node: Arc<SendSyncRefUnwindSafeKV + 'static>,
node: Arc<SendSyncRefUnwindSafeKV + 'static>,
}
#[derive(Clone)]
pub struct OwnedKVList {
node: Arc<SendSyncRefUnwindSafeKV + 'static>,
}
impl<T> KV for OwnedKVListNode<T>
where
T: SendSyncRefUnwindSafeKV + 'static,
{
fn serialize(
&self,
record: &Record,
serializer: &mut Serializer,
) -> Result {
try!(self.kv.serialize(record, serializer));
try!(self.next_node.serialize(record, serializer));
Ok(())
}
}
impl KV for MultiListNode {
fn serialize(
&self,
record: &Record,
serializer: &mut Serializer,
) -> Result {
try!(self.next_node.serialize(record, serializer));
try!(self.node.serialize(record, serializer));
Ok(())
}
}
impl KV for OwnedKVList {
fn serialize(
&self,
record: &Record,
serializer: &mut Serializer,
) -> Result {
try!(self.node.serialize(record, serializer));
Ok(())
}
}
impl fmt::Debug for OwnedKVList {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, "("));
let mut i = 0;
{
let mut as_str_ser = AsFmtSerializer(|key, _val| {
if i != 0 {
try!(write!(f, ", "));
}
try!(write!(f, "{}", key));
i += 1;
Ok(())
});
let record_static = record_static!(Level::Trace, "");
try!(
self.node
.serialize(
&Record::new(
&record_static,
&format_args!(""),
BorrowedKV(&STATIC_TERMINATOR_UNIT)
),
&mut as_str_ser
)
.map_err(|_| fmt::Error)
);
}
try!(write!(f, ")"));
Ok(())
}
}
impl OwnedKVList {
fn root<T>(values: OwnedKV<T>) -> Self
where
T: SendSyncRefUnwindSafeKV + 'static,
{
OwnedKVList {
node: Arc::new(OwnedKVListNode {
next_node: Arc::new(()),
kv: values.0,
}),
}
}
fn new<T>(
values: OwnedKV<T>,
next_node: Arc<SendSyncRefUnwindSafeKV + 'static>,
) -> Self
where
T: SendSyncRefUnwindSafeKV + 'static,
{
OwnedKVList {
node: Arc::new(OwnedKVListNode {
next_node: next_node,
kv: values.0,
}),
}
}
}
impl<T> convert::From<OwnedKV<T>> for OwnedKVList
where
T: SendSyncRefUnwindSafeKV + 'static,
{
fn from(from: OwnedKV<T>) -> Self {
OwnedKVList::root(from)
}
}
#[derive(Debug)]
#[cfg(feature = "std")]
pub enum Error {
Io(std::io::Error),
Fmt(std::fmt::Error),
Other,
}
#[derive(Debug)]
#[cfg(not(feature = "std"))]
pub enum Error {
Fmt(core::fmt::Error),
Other,
}
pub type Result<T = ()> = result::Result<T, Error>;
#[cfg(feature = "std")]
impl From<std::io::Error> for Error {
fn from(err: std::io::Error) -> Error {
Error::Io(err)
}
}
impl From<core::fmt::Error> for Error {
fn from(_: core::fmt::Error) -> Error {
Error::Other
}
}
#[cfg(feature = "std")]
impl From<Error> for std::io::Error {
fn from(e: Error) -> std::io::Error {
match e {
Error::Io(e) => e,
Error::Fmt(_) => std::io::Error::new(
std::io::ErrorKind::Other,
"formatting error",
),
Error::Other => {
std::io::Error::new(std::io::ErrorKind::Other, "other error")
}
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for Error {
fn description(&self) -> &str {
match *self {
Error::Io(ref e) => e.description(),
Error::Fmt(_) => "formatting error",
Error::Other => "serialization error",
}
}
fn cause(&self) -> Option<&std::error::Error> {
match *self {
Error::Io(ref e) => Some(e),
Error::Fmt(ref e) => Some(e),
Error::Other => None,
}
}
}
#[cfg(feature = "std")]
impl core::fmt::Display for Error {
fn fmt(&self, fmt: &mut core::fmt::Formatter) -> std::fmt::Result {
match *self {
Error::Io(ref e) => e.fmt(fmt),
Error::Fmt(ref e) => e.fmt(fmt),
Error::Other => fmt.write_str("Other serialization error"),
}
}
}
#[doc(hidden)]
pub type Never = private::NeverStruct;
mod private {
#[doc(hidden)]
#[derive(Debug)]
pub struct NeverStruct(());
}
#[doc(hidden)]
pub static STATIC_TERMINATOR_UNIT: () = ();
#[allow(unknown_lints)]
#[allow(inline_always)]
#[inline(always)]
#[doc(hidden)]
pub fn __slog_static_max_level() -> FilterLevel {
if !cfg!(debug_assertions) {
if cfg!(feature = "release_max_level_off") {
return FilterLevel::Off;
} else if cfg!(feature = "release_max_level_error") {
return FilterLevel::Error;
} else if cfg!(feature = "release_max_level_warn") {
return FilterLevel::Warning;
} else if cfg!(feature = "release_max_level_info") {
return FilterLevel::Info;
} else if cfg!(feature = "release_max_level_debug") {
return FilterLevel::Debug;
} else if cfg!(feature = "release_max_level_trace") {
return FilterLevel::Trace;
}
}
if cfg!(feature = "max_level_off") {
FilterLevel::Off
} else if cfg!(feature = "max_level_error") {
FilterLevel::Error
} else if cfg!(feature = "max_level_warn") {
FilterLevel::Warning
} else if cfg!(feature = "max_level_info") {
FilterLevel::Info
} else if cfg!(feature = "max_level_debug") {
FilterLevel::Debug
} else if cfg!(feature = "max_level_trace") {
FilterLevel::Trace
} else {
if !cfg!(debug_assertions) {
FilterLevel::Info
} else {
FilterLevel::Debug
}
}
}
#[deprecated(note = "Renamed to `Value`")]
pub type Serialize = Value;
#[deprecated(note = "Renamed to `PushFnValue`")]
pub type PushLazy<T> = PushFnValue<T>;
#[deprecated(note = "Renamed to `PushFnValueSerializer`")]
pub type ValueSerializer<'a> = PushFnValueSerializer<'a>;
#[deprecated(note = "Renamed to `OwnedKVList`")]
pub type OwnedKeyValueList = OwnedKVList;
#[deprecated(note = "Content of ser module moved to main namespace")]
pub mod ser {
#[allow(deprecated)]
pub use super::{OwnedKeyValueList, PushLazy, Serialize, Serializer,
ValueSerializer};
}
#[cfg(test)]
mod tests;