From 067efb50cd476d77d48d2054be98124e64e0d5a9 Mon Sep 17 00:00:00 2001 From: Dion Dokter Date: Mon, 27 Jul 2020 09:16:45 +0200 Subject: [PATCH 001/280] Added deserialization from index. --- src/serde.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/serde.rs b/src/serde.rs index efc9f14a4..1fde882d7 100644 --- a/src/serde.rs +++ b/src/serde.rs @@ -60,6 +60,17 @@ impl<'de> Deserialize<'de> for Level { self.visit_str(variant) } + + fn visit_u64(self, v: u64) -> Result + where + E: Error, + { + let variant: &str = LOG_LEVEL_NAMES[1..] + .get(v as usize) + .ok_or_else(|| Error::invalid_value(Unexpected::Unsigned(v), &self))?; + + self.visit_str(variant) + } } impl<'de> DeserializeSeed<'de> for LevelIdentifier { @@ -144,6 +155,17 @@ impl<'de> Deserialize<'de> for LevelFilter { self.visit_str(variant) } + + fn visit_u64(self, v: u64) -> Result + where + E: Error, + { + let variant: &str = LOG_LEVEL_NAMES + .get(v as usize) + .ok_or_else(|| Error::invalid_value(Unexpected::Unsigned(v), &self))?; + + self.visit_str(variant) + } } impl<'de> DeserializeSeed<'de> for LevelFilterIdentifier { From 2d66fe4ce37d4d529ccb41f2bc1ff5d50dba2673 Mon Sep 17 00:00:00 2001 From: Dion Dokter Date: Mon, 27 Jul 2020 09:41:04 +0200 Subject: [PATCH 002/280] Made the variants deserialize as u32 because that's the type that is given when serializing. Added tests --- src/serde.rs | 61 ++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 55 insertions(+), 6 deletions(-) diff --git a/src/serde.rs b/src/serde.rs index 1fde882d7..3cccb277b 100644 --- a/src/serde.rs +++ b/src/serde.rs @@ -61,13 +61,13 @@ impl<'de> Deserialize<'de> for Level { self.visit_str(variant) } - fn visit_u64(self, v: u64) -> Result + fn visit_u32(self, v: u32) -> Result where E: Error, { - let variant: &str = LOG_LEVEL_NAMES[1..] + let variant = LOG_LEVEL_NAMES[1..] .get(v as usize) - .ok_or_else(|| Error::invalid_value(Unexpected::Unsigned(v), &self))?; + .ok_or_else(|| Error::invalid_value(Unexpected::Unsigned(v as u64), &self))?; self.visit_str(variant) } @@ -156,13 +156,13 @@ impl<'de> Deserialize<'de> for LevelFilter { self.visit_str(variant) } - fn visit_u64(self, v: u64) -> Result + fn visit_u32(self, v: u32) -> Result where E: Error, { - let variant: &str = LOG_LEVEL_NAMES + let variant = LOG_LEVEL_NAMES .get(v as usize) - .ok_or_else(|| Error::invalid_value(Unexpected::Unsigned(v), &self))?; + .ok_or_else(|| Error::invalid_value(Unexpected::Unsigned(v as u64), &self))?; self.visit_str(variant) } @@ -225,6 +225,14 @@ mod tests { ] } + fn level_variant_tokens(variant: u32) -> [Token; 3] { + [ + Token::Enum { name: "Level" }, + Token::U32(variant), + Token::Unit, + ] + } + fn level_filter_token(variant: &'static str) -> Token { Token::UnitVariant { name: "LevelFilter", @@ -242,6 +250,16 @@ mod tests { ] } + fn level_filter_variant_tokens(variant: u32) -> [Token; 3] { + [ + Token::Enum { + name: "LevelFilter", + }, + Token::U32(variant), + Token::Unit, + ] + } + #[test] fn test_level_ser_de() { let cases = [ @@ -287,6 +305,21 @@ mod tests { } } + #[test] + fn test_level_de_variant_index() { + let cases = [ + (Level::Error, level_variant_tokens(0)), + (Level::Warn, level_variant_tokens(1)), + (Level::Info, level_variant_tokens(2)), + (Level::Debug, level_variant_tokens(3)), + (Level::Trace, level_variant_tokens(4)), + ]; + + for &(value, tokens) in &cases { + assert_de_tokens(&value, &tokens); + } + } + #[test] fn test_level_de_error() { let msg = "unknown variant `errorx`, expected one of \ @@ -342,6 +375,22 @@ mod tests { } } + #[test] + fn test_level_filter_de_variant_index() { + let cases = [ + (LevelFilter::Off, level_filter_variant_tokens(0)), + (LevelFilter::Error, level_filter_variant_tokens(1)), + (LevelFilter::Warn, level_filter_variant_tokens(2)), + (LevelFilter::Info, level_filter_variant_tokens(3)), + (LevelFilter::Debug, level_filter_variant_tokens(4)), + (LevelFilter::Trace, level_filter_variant_tokens(5)), + ]; + + for &(value, tokens) in &cases { + assert_de_tokens(&value, &tokens); + } + } + #[test] fn test_level_filter_de_error() { let msg = "unknown variant `errorx`, expected one of \ From caaa559a235ccde65ef10a0559fc85753270b188 Mon Sep 17 00:00:00 2001 From: Dion Dokter Date: Tue, 28 Jul 2020 08:17:18 +0200 Subject: [PATCH 003/280] Back to u64 --- src/serde.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/serde.rs b/src/serde.rs index 3cccb277b..50128330f 100644 --- a/src/serde.rs +++ b/src/serde.rs @@ -61,13 +61,13 @@ impl<'de> Deserialize<'de> for Level { self.visit_str(variant) } - fn visit_u32(self, v: u32) -> Result + fn visit_u64(self, v: u64) -> Result where E: Error, { let variant = LOG_LEVEL_NAMES[1..] .get(v as usize) - .ok_or_else(|| Error::invalid_value(Unexpected::Unsigned(v as u64), &self))?; + .ok_or_else(|| Error::invalid_value(Unexpected::Unsigned(v), &self))?; self.visit_str(variant) } @@ -156,13 +156,13 @@ impl<'de> Deserialize<'de> for LevelFilter { self.visit_str(variant) } - fn visit_u32(self, v: u32) -> Result + fn visit_u64(self, v: u64) -> Result where E: Error, { let variant = LOG_LEVEL_NAMES .get(v as usize) - .ok_or_else(|| Error::invalid_value(Unexpected::Unsigned(v as u64), &self))?; + .ok_or_else(|| Error::invalid_value(Unexpected::Unsigned(v), &self))?; self.visit_str(variant) } From 803a23b15ed86be5097e99a2d806e3774757d72e Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Mon, 3 Aug 2020 18:05:15 +1000 Subject: [PATCH 004/280] Rework structured value casting (#396) Also adds a const-fn based mechanism for pulling concrete values out of generic ones --- benches/value.rs | 30 +++ build.rs | 61 +++++- src/kv/value/fill.rs | 6 +- src/kv/value/impls.rs | 56 ++--- .../value/internal/{cast.rs => cast/mod.rs} | 94 ++------- src/kv/value/internal/cast/primitive.rs | 195 ++++++++++++++++++ src/kv/value/internal/fmt.rs | 82 +++++++- src/kv/value/internal/mod.rs | 131 +++++++----- src/kv/value/internal/sval.rs | 78 +++++-- src/kv/value/mod.rs | 124 +++++++++++ 10 files changed, 667 insertions(+), 190 deletions(-) create mode 100644 benches/value.rs rename src/kv/value/internal/{cast.rs => cast/mod.rs} (83%) create mode 100644 src/kv/value/internal/cast/primitive.rs diff --git a/benches/value.rs b/benches/value.rs new file mode 100644 index 000000000..4e6960e80 --- /dev/null +++ b/benches/value.rs @@ -0,0 +1,30 @@ +#![cfg(feature = "kv_unstable")] +#![feature(test)] + +extern crate log; +extern crate test; + +use log::kv::Value; + +#[bench] +fn u8_to_value(b: &mut test::Bencher) { + b.iter(|| Value::from(1u8)) +} + +#[bench] +fn u8_to_value_debug(b: &mut test::Bencher) { + b.iter(|| Value::from_debug(&1u8)) +} + +#[bench] +fn str_to_value_debug(b: &mut test::Bencher) { + b.iter(|| Value::from_debug(&"a string")) +} + +#[bench] +fn custom_to_value_debug(b: &mut test::Bencher) { + #[derive(Debug)] + struct A; + + b.iter(|| Value::from_debug(&A)) +} diff --git a/build.rs b/build.rs index 6717bf0f7..40d16129b 100644 --- a/build.rs +++ b/build.rs @@ -2,13 +2,72 @@ //! atomics and sets `cfg` flags accordingly. use std::env; +use std::process::Command; +use std::str::{self, FromStr}; + +#[cfg(feature = "kv_unstable")] +#[path = "src/kv/value/internal/cast/primitive.rs"] +mod primitive; fn main() { - let target = env::var("TARGET").unwrap(); + let minor = match rustc_minor_version() { + Some(minor) => minor, + None => return, + }; + + let target = match rustc_target() { + Some(target) => target, + None => return, + }; + // If the target isn't thumbv6 then we can use atomic CAS if !target.starts_with("thumbv6") { println!("cargo:rustc-cfg=atomic_cas"); } + // If the Rust version is at least 1.46.0 then we can use type ids at compile time + if minor >= 47 { + println!("cargo:rustc-cfg=const_type_id"); + } + + // Generate sorted type id lookup + #[cfg(feature = "kv_unstable")] + primitive::generate(); + + println!("cargo:rustc-cfg=srcbuild"); println!("cargo:rerun-if-changed=build.rs"); } + +fn rustc_target() -> Option { + env::var("TARGET").ok() +} + +// From the `serde` build script +fn rustc_minor_version() -> Option { + let rustc = match env::var_os("RUSTC") { + Some(rustc) => rustc, + None => return None, + }; + + let output = match Command::new(rustc).arg("--version").output() { + Ok(output) => output, + Err(_) => return None, + }; + + let version = match str::from_utf8(&output.stdout) { + Ok(version) => version, + Err(_) => return None, + }; + + let mut pieces = version.split('.'); + if pieces.next() != Some("rustc 1") { + return None; + } + + let next = match pieces.next() { + Some(next) => next, + None => return None, + }; + + u32::from_str(next).ok() +} diff --git a/src/kv/value/fill.rs b/src/kv/value/fill.rs index d14a64258..f34ba31d5 100644 --- a/src/kv/value/fill.rs +++ b/src/kv/value/fill.rs @@ -2,17 +2,17 @@ use std::fmt; -use super::internal::{Erased, Inner, Visitor}; +use super::internal::{Inner, Visitor}; use super::{Error, Value}; impl<'v> Value<'v> { /// Get a value from a fillable slot. pub fn from_fill(value: &'v T) -> Self where - T: Fill + 'static, + T: Fill, { Value { - inner: Inner::Fill(unsafe { Erased::new_unchecked::(value) }), + inner: Inner::Fill(value), } } } diff --git a/src/kv/value/impls.rs b/src/kv/value/impls.rs index a6169f101..506128bf2 100644 --- a/src/kv/value/impls.rs +++ b/src/kv/value/impls.rs @@ -7,24 +7,6 @@ use std::fmt; use super::{Primitive, ToValue, Value}; -macro_rules! impl_into_owned { - ($($into_ty:ty => $convert:ident,)*) => { - $( - impl ToValue for $into_ty { - fn to_value(&self) -> Value { - Value::from(*self) - } - } - - impl<'v> From<$into_ty> for Value<'v> { - fn from(value: $into_ty) -> Self { - Value::from_primitive(value as $convert) - } - } - )* - }; -} - impl<'v> ToValue for &'v str { fn to_value(&self) -> Value { Value::from(*self) @@ -67,25 +49,25 @@ where } } -impl_into_owned! [ - usize => u64, - u8 => u64, - u16 => u64, - u32 => u64, - u64 => u64, - - isize => i64, - i8 => i64, - i16 => i64, - i32 => i64, - i64 => i64, - - f32 => f64, - f64 => f64, - - char => char, - bool => bool, -]; +macro_rules! impl_to_value_primitive { + ($($into_ty:ty,)*) => { + $( + impl ToValue for $into_ty { + fn to_value(&self) -> Value { + Value::from(*self) + } + } + + impl<'v> From<$into_ty> for Value<'v> { + fn from(value: $into_ty) -> Self { + Value::from_primitive(value) + } + } + )* + }; +} + +impl_to_value_primitive![usize, u8, u16, u32, u64, isize, i8, i16, i32, i64, f32, f64, char, bool,]; #[cfg(feature = "std")] mod std_support { diff --git a/src/kv/value/internal/cast.rs b/src/kv/value/internal/cast/mod.rs similarity index 83% rename from src/kv/value/internal/cast.rs rename to src/kv/value/internal/cast/mod.rs index d2aa86e63..ec6a22379 100644 --- a/src/kv/value/internal/cast.rs +++ b/src/kv/value/internal/cast/mod.rs @@ -4,12 +4,23 @@ //! but may end up executing arbitrary caller code if the value is complex. //! They will also attempt to downcast erased types into a primitive where possible. -use std::any::TypeId; use std::fmt; -use super::{Erased, Inner, Primitive, Visitor}; +use super::{Inner, Primitive, Visitor}; use crate::kv::value::{Error, Value}; +mod primitive; + +/// Attempt to capture a primitive from some generic value. +/// +/// If the value is a primitive type, then cast it here, avoiding needing to erase its value +/// This makes `Value`s produced by `Value::from_*` more useful +pub(super) fn try_from_primitive<'v, T: 'static>(value: &'v T) -> Option> { + primitive::from_any(value).map(|primitive| Value { + inner: Inner::Primitive(primitive), + }) +} + impl<'v> Value<'v> { /// Try get a `usize` from this value. /// @@ -203,8 +214,9 @@ impl<'v> Inner<'v> { Ok(()) } - fn borrowed_str(&mut self, v: &'v str) -> Result<(), Error> { - self.0 = Cast::Primitive(Primitive::Str(v)); + #[cfg(feature = "std")] + fn str(&mut self, s: &str) -> Result<(), Error> { + self.0 = Cast::String(s.to_owned()); Ok(()) } @@ -213,9 +225,8 @@ impl<'v> Inner<'v> { Ok(()) } - #[cfg(feature = "std")] - fn str(&mut self, v: &str) -> Result<(), Error> { - self.0 = Cast::String(v.into()); + fn borrowed_str(&mut self, v: &'v str) -> Result<(), Error> { + self.0 = Cast::Primitive(Primitive::Str(v)); Ok(()) } @@ -231,24 +242,14 @@ impl<'v> Inner<'v> { } } - // Try downcast an erased value first - // It also lets us avoid the Visitor infrastructure for simple primitives - let primitive = match self { - Inner::Primitive(value) => Some(value), - Inner::Fill(value) => value.downcast_primitive(), - Inner::Debug(value) => value.downcast_primitive(), - Inner::Display(value) => value.downcast_primitive(), - - #[cfg(feature = "sval")] - Inner::Sval(value) => value.downcast_primitive(), - }; - - primitive.map(Cast::Primitive).unwrap_or_else(|| { + if let Inner::Primitive(value) = self { + Cast::Primitive(value) + } else { // If the erased value isn't a primitive then we visit it let mut cast = CastVisitor(Cast::Primitive(Primitive::None)); let _ = self.visit(&mut cast); cast.0 - }) + } } } @@ -321,57 +322,6 @@ impl<'v> Primitive<'v> { } } -impl<'v, T: ?Sized + 'static> Erased<'v, T> { - // NOTE: This function is a perfect candidate for memoization - // The outcome could be stored in a `Cell` - fn downcast_primitive(self) -> Option> { - macro_rules! type_ids { - ($($value:ident : $ty:ty => $cast:expr,)*) => {{ - struct TypeIds; - - impl TypeIds { - fn downcast_primitive<'v, T: ?Sized>(&self, value: Erased<'v, T>) -> Option> { - $( - if TypeId::of::<$ty>() == value.type_id { - let $value = unsafe { value.downcast_unchecked::<$ty>() }; - return Some(Primitive::from($cast)); - } - )* - - None - } - } - - TypeIds - }}; - } - - let type_ids = type_ids![ - value: usize => *value as u64, - value: u8 => *value as u64, - value: u16 => *value as u64, - value: u32 => *value as u64, - value: u64 => *value, - - value: isize => *value as i64, - value: i8 => *value as i64, - value: i16 => *value as i64, - value: i32 => *value as i64, - value: i64 => *value, - - value: f32 => *value as f64, - value: f64 => *value, - - value: char => *value, - value: bool => *value, - - value: &str => *value, - ]; - - type_ids.downcast_primitive(self) - } -} - #[cfg(feature = "std")] mod std_support { use super::*; diff --git a/src/kv/value/internal/cast/primitive.rs b/src/kv/value/internal/cast/primitive.rs new file mode 100644 index 000000000..991a70046 --- /dev/null +++ b/src/kv/value/internal/cast/primitive.rs @@ -0,0 +1,195 @@ +/* +This module generates code to try efficiently convert some arbitrary `T: 'static` into +a `Primitive`. It's used by both the `build.rs` script and by the source itself. There +are currently two implementations here: + +- When the compiler version is less than `1.46.0` we check type ids at runtime. This +means generating a pre-sorted list of type ids at compile time using the `build.rs` +and matching them at runtime. +- When the compiler version is at least `1.46.0` we use const evaluation to check type ids +at compile time. There's no generated code from `build.rs` involved. + +In the future when `min_specialization` is stabilized we could use it instead and avoid needing +the `'static` bound altogether. +*/ + +// Use consts to match a type with a conversion fn +#[cfg(all(srcbuild, const_type_id))] +pub(super) fn from_any<'v, T: ?Sized + 'static>( + value: &'v T, +) -> Option> { + use std::any::TypeId; + + use crate::kv::value::internal::Primitive; + + macro_rules! to_primitive { + ($($ty:ty : ($const_ident:ident, $option_ident:ident),)*) => { + trait ToPrimitive + where + Self: 'static, + { + const CALL: fn(&Self) -> Option = { + $( + const $const_ident: TypeId = TypeId::of::<$ty>(); + const $option_ident: TypeId = TypeId::of::>(); + );* + + match TypeId::of::() { + $( + $const_ident => |v| Some(Primitive::from(unsafe { *(v as *const Self as *const $ty) })), + $option_ident => |v| Some({ + let v = unsafe { *(v as *const Self as *const Option<$ty>) }; + match v { + Some(v) => Primitive::from(v), + None => Primitive::None, + } + }), + )* + + _ => |_| None, + } + }; + + fn to_primitive(&self) -> Option { + (Self::CALL)(self) + } + } + + impl ToPrimitive for T {} + } + } + + // NOTE: The types here *must* match the ones used below when `const_type_id` is not available + to_primitive![ + usize: (USIZE, OPTION_USIZE), + u8: (U8, OPTION_U8), + u16: (U16, OPTION_U16), + u32: (U32, OPTION_U32), + u64: (U64, OPTION_U64), + + isize: (ISIZE, OPTION_ISIZE), + i8: (I8, OPTION_I8), + i16: (I16, OPTION_I16), + i32: (I32, OPTION_I32), + i64: (I64, OPTION_I64), + + f32: (F32, OPTION_F32), + f64: (F64, OPTION_F64), + + char: (CHAR, OPTION_CHAR), + bool: (BOOL, OPTION_BOOL), + &'static str: (STR, OPTION_STR), + ]; + + value.to_primitive() +} + +#[cfg(all(not(src_build), const_type_id))] +#[allow(dead_code)] +pub fn generate() {} + +// Use a build-time generated set of type ids to match a type with a conversion fn +#[cfg(all(srcbuild, not(const_type_id)))] +pub(super) fn from_any<'v>( + value: &'v (dyn std::any::Any + 'static), +) -> Option> { + // The set of type ids that map to primitives are generated at build-time + // by the contents of `sorted_type_ids.expr`. These type ids are pre-sorted + // so that they can be searched efficiently. See the `sorted_type_ids.expr.rs` + // file for the set of types that appear in this list + let type_ids = include!(concat!(env!("OUT_DIR"), "/into_primitive.rs")); + + if let Ok(i) = type_ids.binary_search_by_key(&value.type_id(), |&(k, _)| k) { + Some((type_ids[i].1)(value)) + } else { + None + } +} + +// When the `src_build` config is not set then we're in the build script +#[cfg(all(not(srcbuild), not(const_type_id)))] +#[allow(dead_code)] +pub fn generate() { + use std::path::Path; + use std::{env, fs}; + + macro_rules! type_ids { + ($($ty:ty,)*) => { + [ + $( + ( + std::any::TypeId::of::<$ty>(), + stringify!( + ( + std::any::TypeId::of::<$ty>(), + (|value| unsafe { + debug_assert_eq!(value.type_id(), std::any::TypeId::of::<$ty>()); + + // SAFETY: We verify the value is $ty before casting + let value = *(value as *const dyn std::any::Any as *const $ty); + crate::kv::value::internal::Primitive::from(value) + }) as for<'a> fn(&'a (dyn std::any::Any + 'static)) -> crate::kv::value::internal::Primitive<'a> + ) + ) + ), + )* + $( + ( + std::any::TypeId::of::>(), + stringify!( + ( + std::any::TypeId::of::>(), + (|value| unsafe { + debug_assert_eq!(value.type_id(), std::any::TypeId::of::>()); + + // SAFETY: We verify the value is Option<$ty> before casting + let value = *(value as *const dyn std::any::Any as *const Option<$ty>); + if let Some(value) = value { + crate::kv::value::internal::Primitive::from(value) + } else { + crate::kv::value::internal::Primitive::None + } + }) as for<'a> fn(&'a (dyn std::any::Any + 'static)) -> crate::kv::value::internal::Primitive<'a> + ) + ) + ), + )* + ] + }; + } + + // NOTE: The types here *must* match the ones used above when `const_type_id` is available + let mut type_ids = type_ids![ + usize, + u8, + u16, + u32, + u64, + isize, + i8, + i16, + i32, + i64, + f32, + f64, + char, + bool, + &'static str, + ]; + + type_ids.sort_by_key(|&(k, _)| k); + + let mut ordered_type_ids_expr = String::new(); + + ordered_type_ids_expr.push('['); + + for (_, v) in &type_ids { + ordered_type_ids_expr.push_str(v); + ordered_type_ids_expr.push(','); + } + + ordered_type_ids_expr.push(']'); + + let path = Path::new(&env::var_os("OUT_DIR").unwrap()).join("into_primitive.rs"); + fs::write(path, ordered_type_ids_expr).unwrap(); +} diff --git a/src/kv/value/internal/fmt.rs b/src/kv/value/internal/fmt.rs index eabd4dd15..bde703c20 100644 --- a/src/kv/value/internal/fmt.rs +++ b/src/kv/value/internal/fmt.rs @@ -5,28 +5,54 @@ use std::fmt; -use super::{Erased, Inner, Visitor}; +use super::{cast, Inner, Visitor}; use crate::kv; -use crate::kv::value::{Error, Slot}; +use crate::kv::value::{Error, Slot, ToValue}; impl<'v> kv::Value<'v> { /// Get a value from a debuggable type. - pub fn from_debug(value: &'v T) -> Self + /// + /// This method will attempt to capture the given value as a well-known primitive + /// before resorting to using its `Debug` implementation. + pub fn capture_debug(value: &'v T) -> Self where T: fmt::Debug + 'static, + { + cast::try_from_primitive(value).unwrap_or(kv::Value { + inner: Inner::Debug(value), + }) + } + + /// Get a value from a debuggable type. + pub fn from_debug(value: &'v T) -> Self + where + T: fmt::Debug, { kv::Value { - inner: Inner::Debug(unsafe { Erased::new_unchecked::(value) }), + inner: Inner::Debug(value), } } /// Get a value from a displayable type. - pub fn from_display(value: &'v T) -> Self + /// + /// This method will attempt to capture the given value as a well-known primitive + /// before resorting to using its `Display` implementation. + pub fn capture_display(value: &'v T) -> Self where T: fmt::Display + 'static, + { + cast::try_from_primitive(value).unwrap_or(kv::Value { + inner: Inner::Display(value), + }) + } + + /// Get a value from a displayable type. + pub fn from_display(value: &'v T) -> Self + where + T: fmt::Display, { kv::Value { - inner: Inner::Display(unsafe { Erased::new_unchecked::(value) }), + inner: Inner::Display(value), } } } @@ -201,24 +227,64 @@ impl<'v> fmt::Display for kv::Value<'v> { } } +impl<'v> ToValue for dyn fmt::Debug + 'v { + fn to_value(&self) -> kv::Value { + kv::Value::from(self) + } +} + +impl<'v> ToValue for dyn fmt::Display + 'v { + fn to_value(&self) -> kv::Value { + kv::Value::from(self) + } +} + +impl<'v> From<&'v (dyn fmt::Debug)> for kv::Value<'v> { + fn from(value: &'v (dyn fmt::Debug)) -> kv::Value<'v> { + kv::Value { + inner: Inner::Debug(value), + } + } +} + +impl<'v> From<&'v (dyn fmt::Display)> for kv::Value<'v> { + fn from(value: &'v (dyn fmt::Display)) -> kv::Value<'v> { + kv::Value { + inner: Inner::Display(value), + } + } +} + #[cfg(test)] mod tests { use super::*; + use kv::value::test::Token; use crate::kv::value::ToValue; + #[test] + fn fmt_capture() { + assert_eq!(kv::Value::capture_debug(&1u16).to_token(), Token::U64(1)); + assert_eq!(kv::Value::capture_display(&1u16).to_token(), Token::U64(1)); + + assert_eq!( + kv::Value::capture_debug(&Some(1u16)).to_token(), + Token::U64(1) + ); + } + #[test] fn fmt_cast() { assert_eq!( 42u32, - kv::Value::from_debug(&42u64) + kv::Value::capture_debug(&42u64) .to_u32() .expect("invalid value") ); assert_eq!( "a string", - kv::Value::from_display(&"a string") + kv::Value::capture_display(&"a string") .to_borrowed_str() .expect("invalid value") ); diff --git a/src/kv/value/internal/mod.rs b/src/kv/value/internal/mod.rs index 429f0db98..4acbe683c 100644 --- a/src/kv/value/internal/mod.rs +++ b/src/kv/value/internal/mod.rs @@ -3,8 +3,6 @@ //! This implementation isn't intended to be public. It may need to change //! for optimizations or to support new external serialization frameworks. -use std::any::TypeId; - use super::{Error, Fill, Slot}; pub(super) mod cast; @@ -18,27 +16,29 @@ pub(super) enum Inner<'v> { /// A simple primitive value that can be copied without allocating. Primitive(Primitive<'v>), /// A value that can be filled. - Fill(Erased<'v, dyn Fill + 'static>), + Fill(&'v (dyn Fill)), /// A debuggable value. - Debug(Erased<'v, dyn fmt::Debug + 'static>), + Debug(&'v (dyn fmt::Debug)), /// A displayable value. - Display(Erased<'v, dyn fmt::Display + 'static>), + Display(&'v (dyn fmt::Display)), #[cfg(feature = "kv_unstable_sval")] /// A structured value from `sval`. - Sval(Erased<'v, dyn sval::Value + 'static>), + Sval(&'v (dyn sval::Value)), } impl<'v> Inner<'v> { pub(super) fn visit(self, visitor: &mut dyn Visitor<'v>) -> Result<(), Error> { match self { Inner::Primitive(value) => value.visit(visitor), - Inner::Fill(value) => value.get().fill(&mut Slot::new(visitor)), - Inner::Debug(value) => visitor.debug(value.get()), - Inner::Display(value) => visitor.display(value.get()), + + Inner::Debug(value) => visitor.debug(value), + Inner::Display(value) => visitor.display(value), + + Inner::Fill(value) => value.fill(&mut Slot::new(visitor)), #[cfg(feature = "kv_unstable_sval")] - Inner::Sval(value) => visitor.sval(value.get()), + Inner::Sval(value) => visitor.sval(value), } } } @@ -97,85 +97,114 @@ impl<'v> Primitive<'v> { } } +impl<'v> From for Primitive<'v> { + #[inline] + fn from(v: u8) -> Self { + Primitive::Unsigned(v as u64) + } +} + +impl<'v> From for Primitive<'v> { + #[inline] + fn from(v: u16) -> Self { + Primitive::Unsigned(v as u64) + } +} + +impl<'v> From for Primitive<'v> { + #[inline] + fn from(v: u32) -> Self { + Primitive::Unsigned(v as u64) + } +} + impl<'v> From for Primitive<'v> { + #[inline] fn from(v: u64) -> Self { Primitive::Unsigned(v) } } +impl<'v> From for Primitive<'v> { + #[inline] + fn from(v: usize) -> Self { + Primitive::Unsigned(v as u64) + } +} + +impl<'v> From for Primitive<'v> { + #[inline] + fn from(v: i8) -> Self { + Primitive::Signed(v as i64) + } +} + +impl<'v> From for Primitive<'v> { + #[inline] + fn from(v: i16) -> Self { + Primitive::Signed(v as i64) + } +} + +impl<'v> From for Primitive<'v> { + #[inline] + fn from(v: i32) -> Self { + Primitive::Signed(v as i64) + } +} + impl<'v> From for Primitive<'v> { + #[inline] fn from(v: i64) -> Self { Primitive::Signed(v) } } +impl<'v> From for Primitive<'v> { + #[inline] + fn from(v: isize) -> Self { + Primitive::Signed(v as i64) + } +} + +impl<'v> From for Primitive<'v> { + #[inline] + fn from(v: f32) -> Self { + Primitive::Float(v as f64) + } +} + impl<'v> From for Primitive<'v> { + #[inline] fn from(v: f64) -> Self { Primitive::Float(v) } } impl<'v> From for Primitive<'v> { + #[inline] fn from(v: bool) -> Self { Primitive::Bool(v) } } impl<'v> From for Primitive<'v> { + #[inline] fn from(v: char) -> Self { Primitive::Char(v) } } impl<'v> From<&'v str> for Primitive<'v> { + #[inline] fn from(v: &'v str) -> Self { Primitive::Str(v) } } impl<'v> From> for Primitive<'v> { + #[inline] fn from(v: fmt::Arguments<'v>) -> Self { Primitive::Fmt(v) } } - -/// A downcastable dynamic type. -pub(super) struct Erased<'v, T: ?Sized> { - type_id: TypeId, - inner: &'v T, -} - -impl<'v, T: ?Sized> Clone for Erased<'v, T> { - fn clone(&self) -> Self { - Erased { - type_id: self.type_id, - inner: self.inner, - } - } -} - -impl<'v, T: ?Sized> Copy for Erased<'v, T> {} - -impl<'v, T: ?Sized> Erased<'v, T> { - // SAFETY: `U: Unsize` and the underlying value `T` must not change - // We could add a safe variant of this method with the `Unsize` trait - pub(super) unsafe fn new_unchecked(inner: &'v T) -> Self - where - U: 'static, - T: 'static, - { - Erased { - type_id: TypeId::of::(), - inner, - } - } - - pub(super) fn get(self) -> &'v T { - self.inner - } - - // SAFETY: The underlying type of `T` is `U` - pub(super) unsafe fn downcast_unchecked(self) -> &'v U { - &*(self.inner as *const T as *const U) - } -} diff --git a/src/kv/value/internal/sval.rs b/src/kv/value/internal/sval.rs index 0d76f4e1f..252efd152 100644 --- a/src/kv/value/internal/sval.rs +++ b/src/kv/value/internal/sval.rs @@ -7,19 +7,32 @@ extern crate sval; use std::fmt; -use super::cast::Cast; -use super::{Erased, Inner, Primitive, Visitor}; +use super::cast::{self, Cast}; +use super::{Inner, Primitive, Visitor}; use crate::kv; -use crate::kv::value::{Error, Slot}; +use crate::kv::value::{Error, Slot, ToValue}; impl<'v> kv::Value<'v> { /// Get a value from a structured type. - pub fn from_sval(value: &'v T) -> Self + /// + /// This method will attempt to capture the given value as a well-known primitive + /// before resorting to using its `Value` implementation. + pub fn capture_sval(value: &'v T) -> Self where T: sval::Value + 'static, + { + cast::try_from_primitive(value).unwrap_or(kv::Value { + inner: Inner::Sval(value), + }) + } + + /// Get a value from a structured type. + pub fn from_sval(value: &'v T) -> Self + where + T: sval::Value, { kv::Value { - inner: Inner::Sval(unsafe { Erased::new_unchecked::(value) }), + inner: Inner::Sval(value), } } } @@ -90,6 +103,20 @@ impl<'v> sval::Value for kv::Value<'v> { } } +impl<'v> ToValue for dyn sval::Value + 'v { + fn to_value(&self) -> kv::Value { + kv::Value::from(self) + } +} + +impl<'v> From<&'v (dyn sval::Value)> for kv::Value<'v> { + fn from(value: &'v (dyn sval::Value)) -> kv::Value<'v> { + kv::Value { + inner: Inner::Sval(value), + } + } +} + pub(in kv::value) use self::sval::Value; pub(super) fn fmt(f: &mut fmt::Formatter, v: &dyn sval::Value) -> Result<(), Error> { @@ -155,30 +182,22 @@ mod tests { use kv::value::test::Token; #[test] - fn test_from_sval() { - assert_eq!(kv::Value::from_sval(&42u64).to_token(), Token::Sval); - } - - #[test] - fn test_sval_structured() { - let value = kv::Value::from(42u64); - let expected = vec![sval::test::Token::Unsigned(42)]; - - assert_eq!(sval::test::tokens(value), expected); + fn sval_capture() { + assert_eq!(kv::Value::capture_sval(&42u64).to_token(), Token::U64(42)); } #[test] fn sval_cast() { assert_eq!( 42u32, - kv::Value::from_sval(&42u64) + kv::Value::capture_sval(&42u64) .to_u32() .expect("invalid value") ); assert_eq!( "a string", - kv::Value::from_sval(&"a string") + kv::Value::capture_sval(&"a string") .to_borrowed_str() .expect("invalid value") ); @@ -186,12 +205,20 @@ mod tests { #[cfg(feature = "std")] assert_eq!( "a string", - kv::Value::from_sval(&"a string") + kv::Value::capture_sval(&"a string") .to_str() .expect("invalid value") ); } + #[test] + fn sval_structured() { + let value = kv::Value::from(42u64); + let expected = vec![sval::test::Token::Unsigned(42)]; + + assert_eq!(sval::test::tokens(value), expected); + } + #[test] fn sval_debug() { struct TestSval; @@ -207,4 +234,19 @@ mod tests { format!("{:04?}", kv::Value::from_sval(&TestSval)), ); } + + #[cfg(feature = "std")] + mod std_support { + use super::*; + + #[test] + fn sval_cast() { + assert_eq!( + "a string", + kv::Value::capture_sval(&"a string".to_owned()) + .to_str() + .expect("invalid value") + ); + } + } } diff --git a/src/kv/value/mod.rs b/src/kv/value/mod.rs index 422adb0b5..8d8282624 100644 --- a/src/kv/value/mod.rs +++ b/src/kv/value/mod.rs @@ -34,11 +34,135 @@ impl<'v> ToValue for Value<'v> { } /// A value in a structured key-value pair. +/// +/// # Capturing values +/// +/// There are a few ways to capture a value: +/// +/// - Using the `Value::capture_*` methods. +/// - Using the `Value::from_*` methods. +/// - Using the `ToValue` trait. +/// - Using the standard `From` trait. +/// - Using the `Fill` API. +/// +/// ## Using the `Value::capture_*` methods +/// +/// `Value` offers a few constructor methods that capture values of different kinds. +/// These methods require a `T: 'static` to support downcasting. +/// +/// ``` +/// use log::kv::Value; +/// +/// let value = Value::capture_debug(&42i32); +/// +/// assert_eq!(Some(42), value.to_i32()); +/// ``` +/// +/// ## Using the `Value::from_*` methods +/// +/// `Value` offers a few constructor methods that capture values of different kinds. +/// These methods don't require `T: 'static`, but can't support downcasting. +/// +/// ``` +/// use log::kv::Value; +/// +/// let value = Value::from_debug(&42i32); +/// +/// assert_eq!(None, value.to_i32()); +/// ``` +/// +/// ## Using the `ToValue` trait +/// +/// The `ToValue` trait can be used to capture values generically. +/// It's the bound used by `Source`. +/// +/// ``` +/// # use log::kv::ToValue; +/// let value = 42i32.to_value(); +/// +/// assert_eq!(Some(42), value.to_i32()); +/// ``` +/// +/// ``` +/// # use std::fmt::Debug; +/// use log::kv::ToValue; +/// +/// let value = (&42i32 as &dyn Debug).to_value(); +/// +/// assert_eq!(None, value.to_i32()); +/// ``` +/// +/// ## Using the standard `From` trait +/// +/// Standard types that implement `ToValue` also implement `From`. +/// +/// ``` +/// use log::kv::Value; +/// +/// let value = Value::from(42i32); +/// +/// assert_eq!(Some(42), value.to_i32()); +/// ``` +/// +/// ``` +/// # use std::fmt::Debug; +/// use log::kv::Value; +/// +/// let value = Value::from(&42i32 as &dyn Debug); +/// +/// assert_eq!(None, value.to_i32()); +/// ``` +/// +/// ## Using the `Fill` API +/// +/// The `Fill` trait is a way to bridge APIs that may not be directly +/// compatible with other constructor methods. +/// +/// ``` +/// use log::kv::value::{Value, Slot, Fill, Error}; +/// +/// struct FillSigned; +/// +/// impl Fill for FillSigned { +/// fn fill(&self, slot: &mut Slot) -> Result<(), Error> { +/// slot.fill_any(42i32) +/// } +/// } +/// +/// let value = Value::from_fill(&FillSigned); +/// +/// assert_eq!(Some(42), value.to_i32()); +/// ``` +/// +/// ``` +/// # use std::fmt::Debug; +/// use log::kv::value::{Value, Slot, Fill, Error}; +/// +/// struct FillDebug; +/// +/// impl Fill for FillDebug { +/// fn fill(&self, slot: &mut Slot) -> Result<(), Error> { +/// slot.fill_debug(&42i32 as &dyn Debug) +/// } +/// } +/// +/// let value = Value::from_fill(&FillDebug); +/// +/// assert_eq!(None, value.to_i32()); +/// ``` pub struct Value<'v> { inner: Inner<'v>, } impl<'v> Value<'v> { + /// Get a value from a type implementing `ToValue`. + pub fn from_any(value: &'v T) -> Self + where + T: ToValue, + { + value.to_value() + } + /// Get a value from an internal primitive. fn from_primitive(value: T) -> Self where From 469a4418699ddb5a1e21f9afa9a4316a32bb6fe9 Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Tue, 4 Aug 2020 11:35:58 +1000 Subject: [PATCH 005/280] Require Source methods be implemented in test (#406) require Source methods be implemented in test This just makes sure we don't forget to forward Source methods on types that wrap other sources --- src/kv/source.rs | 94 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 67 insertions(+), 27 deletions(-) diff --git a/src/kv/source.rs b/src/kv/source.rs index a882068f9..86b016033 100644 --- a/src/kv/source.rs +++ b/src/kv/source.rs @@ -30,28 +30,14 @@ pub trait Source { /// /// A source that can provide a more efficient implementation of this method /// should override it. + #[cfg(not(test))] fn get<'v>(&'v self, key: Key) -> Option> { - struct Get<'k, 'v> { - key: Key<'k>, - found: Option>, - } - - impl<'k, 'kvs> Visitor<'kvs> for Get<'k, 'kvs> { - fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> { - if self.key == key { - self.found = Some(value); - } - - Ok(()) - } - } - - let mut get = Get { key, found: None }; - - let _ = self.visit(&mut get); - get.found + get_default(self, key) } + #[cfg(test)] + fn get<'v>(&'v self, key: Key) -> Option>; + /// Count the number of key-value pairs that can be visited. /// /// # Implementation notes @@ -61,21 +47,53 @@ pub trait Source { /// /// A subsequent call to `visit` should yield the same number of key-value pairs /// to the visitor, unless that visitor fails part way through. + #[cfg(not(test))] fn count(&self) -> usize { - struct Count(usize); + count_default(self) + } - impl<'kvs> Visitor<'kvs> for Count { - fn visit_pair(&mut self, _: Key<'kvs>, _: Value<'kvs>) -> Result<(), Error> { - self.0 += 1; + #[cfg(test)] + fn count(&self) -> usize; +} - Ok(()) +/// The default implemention of `Source::get` +pub(crate) fn get_default<'v>(source: &'v (impl Source + ?Sized), key: Key) -> Option> { + struct Get<'k, 'v> { + key: Key<'k>, + found: Option>, + } + + impl<'k, 'kvs> Visitor<'kvs> for Get<'k, 'kvs> { + fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> { + if self.key == key { + self.found = Some(value); } + + Ok(()) } + } + + let mut get = Get { key, found: None }; + + let _ = source.visit(&mut get); + get.found +} + +/// The default implementation of `Source::count`. +pub(crate) fn count_default(source: impl Source) -> usize { + struct Count(usize); + + impl<'kvs> Visitor<'kvs> for Count { + fn visit_pair(&mut self, _: Key<'kvs>, _: Value<'kvs>) -> Result<(), Error> { + self.0 += 1; - let mut count = Count(0); - let _ = self.visit(&mut count); - count.0 + Ok(()) + } } + + let mut count = Count(0); + let _ = source.visit(&mut count); + count.0 } impl<'a, T> Source for &'a T @@ -129,6 +147,16 @@ where Ok(()) } + fn get<'v>(&'v self, key: Key) -> Option> { + for source in self { + if let Some(found) = source.get(key.clone()) { + return Some(found); + } + } + + None + } + fn count(&self) -> usize { self.len() } @@ -146,6 +174,10 @@ where Ok(()) } + fn get<'v>(&'v self, key: Key) -> Option> { + self.as_ref().and_then(|s| s.get(key)) + } + fn count(&self) -> usize { self.as_ref().map(Source::count).unwrap_or(0) } @@ -366,6 +398,14 @@ mod tests { fn visit<'kvs>(&'kvs self, visitor: &mut dyn Visitor<'kvs>) -> Result<(), Error> { visitor.visit_pair(self.key.to_key(), self.value.to_value()) } + + fn get<'v>(&'v self, key: Key) -> Option> { + get_default(self, key) + } + + fn count(&self) -> usize { + count_default(self) + } } assert_eq!(1, Source::count(&("a", 1))); From 85dad3f61e90cee0b4301242363d65b4b4b7f332 Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Sun, 23 Aug 2020 19:01:39 +0200 Subject: [PATCH 006/280] Add Level::as_str Returns the string representation of the `Level`. --- src/lib.rs | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 0dca5e3cc..cc022d43f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -479,7 +479,7 @@ impl FromStr for Level { impl fmt::Display for Level { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.pad(LOG_LEVEL_NAMES[*self as usize]) + fmt.pad(self.as_str()) } } @@ -506,6 +506,13 @@ impl Level { pub fn to_level_filter(&self) -> LevelFilter { LevelFilter::from_usize(*self as usize).unwrap() } + + /// Returns the string representation of the `Level`. + /// + /// This returns the same string as the `fmt::Display` implementation. + pub fn as_str(&self) -> &'static str { + LOG_LEVEL_NAMES[*self as usize] + } } /// An enum representing the available verbosity level filters of the logger. @@ -1496,6 +1503,20 @@ mod tests { } } + #[test] + fn test_level_as_str() { + let tests = &[ + (Level::Error, "ERROR"), + (Level::Warn, "WARN"), + (Level::Info, "INFO"), + (Level::Debug, "DEBUG"), + (Level::Trace, "TRACE"), + ]; + for (input, expected) in tests { + assert_eq!(*expected, input.as_str()); + } + } + #[test] fn test_level_show() { assert_eq!("INFO", Level::Info.to_string()); From 186efede865cec4be2c16c9394ba91ba13ee601c Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Mon, 24 Aug 2020 11:20:25 +0200 Subject: [PATCH 007/280] Add LevelFilter::as_str --- src/lib.rs | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index cc022d43f..cf6f09052 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -639,7 +639,7 @@ impl FromStr for LevelFilter { impl fmt::Display for LevelFilter { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.pad(LOG_LEVEL_NAMES[*self as usize]) + fmt.pad(self.as_str()) } } @@ -668,6 +668,13 @@ impl LevelFilter { pub fn to_level(&self) -> Option { Level::from_usize(*self as usize) } + + /// Returns the string representation of the `LevelFilter`. + /// + /// This returns the same string as the `fmt::Display` implementation. + pub fn as_str(&self) -> &'static str { + LOG_LEVEL_NAMES[*self as usize] + } } #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] @@ -1556,6 +1563,21 @@ mod tests { assert_eq!(LevelFilter::Trace, Level::Trace.to_level_filter()); } + #[test] + fn test_level_filter_as_str() { + let tests = &[ + (LevelFilter::Off, "OFF"), + (LevelFilter::Error, "ERROR"), + (LevelFilter::Warn, "WARN"), + (LevelFilter::Info, "INFO"), + (LevelFilter::Debug, "DEBUG"), + (LevelFilter::Trace, "TRACE"), + ]; + for (input, expected) in tests { + assert_eq!(*expected, input.as_str()); + } + } + #[test] #[cfg(feature = "std")] fn test_error_trait() { From 85b8a11565c77522b2c7334b6979c2a95b4b8344 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Fri, 11 Sep 2020 11:37:43 -0700 Subject: [PATCH 008/280] build.rs: Update the list of non CAS targets Based on the implementation in the headless crate (https://github.com/japaric/heapless/blob/master/build.rs#L26) let's not enable CAS for three more targets. Signed-off-by: Alistair Francis --- build.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/build.rs b/build.rs index 40d16129b..a8dcc9660 100644 --- a/build.rs +++ b/build.rs @@ -20,10 +20,16 @@ fn main() { None => return, }; - // If the target isn't thumbv6 then we can use atomic CAS - if !target.starts_with("thumbv6") { - println!("cargo:rustc-cfg=atomic_cas"); - } + match &target[..] { + "thumbv6m-none-eabi" + | "msp430-none-elf" + | "riscv32i-unknown-none-elf" + | "riscv32imc-unknown-none-elf" => {} + + _ => { + println!("cargo:rustc-cfg=atomic_cas"); + } + }; // If the Rust version is at least 1.46.0 then we can use type ids at compile time if minor >= 47 { From 351ee33633497ad35a11eddd7a5afa242b9096fc Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Fri, 11 Sep 2020 11:35:14 -0700 Subject: [PATCH 009/280] lib: Implement AtomicUsize for platforms without atomics Some platforms don't provide a AtomicUsize. Instead of just failing to build with this error: 291 | use std::sync::atomic::{AtomicUsize, Ordering}; | ^^^^^^^^^^^ no `AtomicUsize` in `sync::atomic` let's instead add a fake AtomicUsize. As the platform doesn't have atomics we can't implement an Atomic version of AtomicUsize, so this version is not atomic. Any platform without atomics is unlikely to have multiple cores, so this shouldn't be a problem. This is somewhat based on: https://github.com/japaric/heapless/commit/940d2e9d7f7ff57f9922b012fcad54cd46b673ae Signed-off-by: Alistair Francis --- build.rs | 8 ++++++++ src/lib.rs | 41 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/build.rs b/build.rs index a8dcc9660..17f48183a 100644 --- a/build.rs +++ b/build.rs @@ -31,6 +31,14 @@ fn main() { } }; + match &target[..] { + "msp430-none-elf" | "riscv32i-unknown-none-elf" | "riscv32imc-unknown-none-elf" => {} + + _ => { + println!("cargo:rustc-cfg=has_atomics"); + } + }; + // If the Rust version is at least 1.46.0 then we can use type ids at compile time if minor >= 47 { println!("cargo:rustc-cfg=const_type_id"); diff --git a/src/lib.rs b/src/lib.rs index cf6f09052..a3f6c7a26 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -288,7 +288,6 @@ use std::error; use std::fmt; use std::mem; use std::str::FromStr; -use std::sync::atomic::{AtomicUsize, Ordering}; #[macro_use] mod macros; @@ -297,6 +296,46 @@ mod serde; #[cfg(feature = "kv_unstable")] pub mod kv; +#[cfg(has_atomics)] +use std::sync::atomic::{AtomicUsize, Ordering}; + +#[cfg(not(has_atomics))] +use std::cell::Cell; +#[cfg(not(has_atomics))] +use std::sync::atomic::Ordering; + +#[cfg(not(has_atomics))] +struct AtomicUsize { + v: Cell, +} + +#[cfg(not(has_atomics))] +impl AtomicUsize { + const fn new(v: usize) -> AtomicUsize { + AtomicUsize { v: Cell::new(v) } + } + + fn load(&self, _order: Ordering) -> usize { + self.v.get() + } + + fn store(&self, val: usize, _order: Ordering) { + self.v.set(val) + } + + #[cfg(atomic_cas)] + fn compare_and_swap(&self, current: usize, new: usize, _order: Ordering) -> usize { + let prev = self.v.get(); + if current == prev { + self.v.set(new); + } + prev + } +} + +#[cfg(not(has_atomics))] +unsafe impl Sync for AtomicUsize {} + // The LOGGER static holds a pointer to the global logger. It is protected by // the STATE static which determines whether LOGGER has been initialized yet. static mut LOGGER: &dyn Log = &NopLogger; From b5e9d0182a91a9c61885b51463cfe9ce629f6fa6 Mon Sep 17 00:00:00 2001 From: Lionel Faber Date: Mon, 21 Sep 2020 17:19:58 +0530 Subject: [PATCH 010/280] Implement Log for boxed data types that already implement the Log trait --- src/lib.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index cf6f09052..36a530799 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1167,6 +1167,23 @@ impl Log for NopLogger { fn flush(&self) {} } +#[cfg(feature = "std")] +impl Log for std::boxed::Box +where + T: ?Sized + Log, +{ + fn enabled(&self, metadata: &Metadata) -> bool { + self.as_ref().enabled(metadata) + } + + fn log(&self, record: &Record) { + self.as_ref().log(record) + } + fn flush(&self) { + self.as_ref().flush() + } +} + /// Sets the global maximum log level. /// /// Generally, this should only be called by the active logging implementation. From 18ab92ffe66edf030f2fc493cabbe24b58501ec1 Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Mon, 21 Sep 2020 12:02:55 -0700 Subject: [PATCH 011/280] workflows/main.yml: Add an embedded riscv32imc test case Signed-off-by: Alistair Francis --- .github/workflows/main.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d96b24c1d..5810a23e8 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -79,5 +79,6 @@ jobs: run: | rustup update stable --no-self-update rustup default stable - - run: rustup target add thumbv6m-none-eabi + - run: rustup target add thumbv6m-none-eabi riscv32imc-unknown-none-elf - run: cargo build --verbose --target=thumbv6m-none-eabi + - run: cargo build --verbose --target=riscv32imc-unknown-none-elf From 5334a7ecee620b3ab1e3142fb8e361673eb11b5d Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Tue, 22 Sep 2020 12:06:47 -0700 Subject: [PATCH 012/280] build.rs: Convert to functions Signed-off-by: Alistair Francis --- build.rs | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/build.rs b/build.rs index 17f48183a..e73c83158 100644 --- a/build.rs +++ b/build.rs @@ -20,24 +20,13 @@ fn main() { None => return, }; - match &target[..] { - "thumbv6m-none-eabi" - | "msp430-none-elf" - | "riscv32i-unknown-none-elf" - | "riscv32imc-unknown-none-elf" => {} - - _ => { - println!("cargo:rustc-cfg=atomic_cas"); - } - }; - - match &target[..] { - "msp430-none-elf" | "riscv32i-unknown-none-elf" | "riscv32imc-unknown-none-elf" => {} + if target_has_atomic_cas(&target) { + println!("cargo:rustc-cfg=atomic_cas"); + } - _ => { - println!("cargo:rustc-cfg=has_atomics"); - } - }; + if target_has_atomics(&target) { + println!("cargo:rustc-cfg=has_atomics"); + } // If the Rust version is at least 1.46.0 then we can use type ids at compile time if minor >= 47 { @@ -52,6 +41,23 @@ fn main() { println!("cargo:rerun-if-changed=build.rs"); } +fn target_has_atomic_cas(target: &str) -> bool { + match &target[..] { + "thumbv6m-none-eabi" + | "msp430-none-elf" + | "riscv32i-unknown-none-elf" + | "riscv32imc-unknown-none-elf" => false, + _ => true, + } +} + +fn target_has_atomics(target: &str) -> bool { + match &target[..] { + "msp430-none-elf" | "riscv32i-unknown-none-elf" | "riscv32imc-unknown-none-elf" => false, + _ => true, + } +} + fn rustc_target() -> Option { env::var("TARGET").ok() } From 3ae52e2729bdb4f9649628132ebcf9dc34e28fed Mon Sep 17 00:00:00 2001 From: Alistair Francis Date: Tue, 22 Sep 2020 12:07:01 -0700 Subject: [PATCH 013/280] lib.rs: Add rationale comments Signed-off-by: Alistair Francis --- src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index a3f6c7a26..987160f51 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -333,6 +333,8 @@ impl AtomicUsize { } } +// Any platform without atomics is unlikely to have multiple cores, so +// writing via Cell will not be a race condition. #[cfg(not(has_atomics))] unsafe impl Sync for AtomicUsize {} From 14335ec8890f957ade7dc82fcac4f3cbbfec3ece Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Wed, 14 Oct 2020 10:05:02 -0700 Subject: [PATCH 014/280] Remove broken const_type_id feature The `const_type_id` feature was planned to stabilize in Rust 1.47, but this was reverted in: https://github.com/rust-lang/rust/pull/77083 This causes errors when building `log` with the `kv_unstable` feature on Rust 1.47 or later. This patch removes the use of this no-longer-stable feature in those Rust versions. --- build.rs | 43 +------------- src/kv/value/internal/cast/primitive.rs | 79 +------------------------ 2 files changed, 3 insertions(+), 119 deletions(-) diff --git a/build.rs b/build.rs index e73c83158..bb2462d06 100644 --- a/build.rs +++ b/build.rs @@ -2,19 +2,13 @@ //! atomics and sets `cfg` flags accordingly. use std::env; -use std::process::Command; -use std::str::{self, FromStr}; +use std::str; #[cfg(feature = "kv_unstable")] #[path = "src/kv/value/internal/cast/primitive.rs"] mod primitive; fn main() { - let minor = match rustc_minor_version() { - Some(minor) => minor, - None => return, - }; - let target = match rustc_target() { Some(target) => target, None => return, @@ -28,11 +22,6 @@ fn main() { println!("cargo:rustc-cfg=has_atomics"); } - // If the Rust version is at least 1.46.0 then we can use type ids at compile time - if minor >= 47 { - println!("cargo:rustc-cfg=const_type_id"); - } - // Generate sorted type id lookup #[cfg(feature = "kv_unstable")] primitive::generate(); @@ -61,33 +50,3 @@ fn target_has_atomics(target: &str) -> bool { fn rustc_target() -> Option { env::var("TARGET").ok() } - -// From the `serde` build script -fn rustc_minor_version() -> Option { - let rustc = match env::var_os("RUSTC") { - Some(rustc) => rustc, - None => return None, - }; - - let output = match Command::new(rustc).arg("--version").output() { - Ok(output) => output, - Err(_) => return None, - }; - - let version = match str::from_utf8(&output.stdout) { - Ok(version) => version, - Err(_) => return None, - }; - - let mut pieces = version.split('.'); - if pieces.next() != Some("rustc 1") { - return None; - } - - let next = match pieces.next() { - Some(next) => next, - None => return None, - }; - - u32::from_str(next).ok() -} diff --git a/src/kv/value/internal/cast/primitive.rs b/src/kv/value/internal/cast/primitive.rs index 991a70046..c306e66f6 100644 --- a/src/kv/value/internal/cast/primitive.rs +++ b/src/kv/value/internal/cast/primitive.rs @@ -13,83 +13,8 @@ In the future when `min_specialization` is stabilized we could use it instead an the `'static` bound altogether. */ -// Use consts to match a type with a conversion fn -#[cfg(all(srcbuild, const_type_id))] -pub(super) fn from_any<'v, T: ?Sized + 'static>( - value: &'v T, -) -> Option> { - use std::any::TypeId; - - use crate::kv::value::internal::Primitive; - - macro_rules! to_primitive { - ($($ty:ty : ($const_ident:ident, $option_ident:ident),)*) => { - trait ToPrimitive - where - Self: 'static, - { - const CALL: fn(&Self) -> Option = { - $( - const $const_ident: TypeId = TypeId::of::<$ty>(); - const $option_ident: TypeId = TypeId::of::>(); - );* - - match TypeId::of::() { - $( - $const_ident => |v| Some(Primitive::from(unsafe { *(v as *const Self as *const $ty) })), - $option_ident => |v| Some({ - let v = unsafe { *(v as *const Self as *const Option<$ty>) }; - match v { - Some(v) => Primitive::from(v), - None => Primitive::None, - } - }), - )* - - _ => |_| None, - } - }; - - fn to_primitive(&self) -> Option { - (Self::CALL)(self) - } - } - - impl ToPrimitive for T {} - } - } - - // NOTE: The types here *must* match the ones used below when `const_type_id` is not available - to_primitive![ - usize: (USIZE, OPTION_USIZE), - u8: (U8, OPTION_U8), - u16: (U16, OPTION_U16), - u32: (U32, OPTION_U32), - u64: (U64, OPTION_U64), - - isize: (ISIZE, OPTION_ISIZE), - i8: (I8, OPTION_I8), - i16: (I16, OPTION_I16), - i32: (I32, OPTION_I32), - i64: (I64, OPTION_I64), - - f32: (F32, OPTION_F32), - f64: (F64, OPTION_F64), - - char: (CHAR, OPTION_CHAR), - bool: (BOOL, OPTION_BOOL), - &'static str: (STR, OPTION_STR), - ]; - - value.to_primitive() -} - -#[cfg(all(not(src_build), const_type_id))] -#[allow(dead_code)] -pub fn generate() {} - // Use a build-time generated set of type ids to match a type with a conversion fn -#[cfg(all(srcbuild, not(const_type_id)))] +#[cfg(srcbuild)] pub(super) fn from_any<'v>( value: &'v (dyn std::any::Any + 'static), ) -> Option> { @@ -107,7 +32,7 @@ pub(super) fn from_any<'v>( } // When the `src_build` config is not set then we're in the build script -#[cfg(all(not(srcbuild), not(const_type_id)))] +#[cfg(not(srcbuild))] #[allow(dead_code)] pub fn generate() { use std::path::Path; From dec098261819771ae1f22cd85f306ec71f23fd85 Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Thu, 15 Oct 2020 17:51:20 +1000 Subject: [PATCH 015/280] remove dependency on reverted const type id --- build.rs | 40 ---------------------------------------- 1 file changed, 40 deletions(-) diff --git a/build.rs b/build.rs index e73c83158..8a194371c 100644 --- a/build.rs +++ b/build.rs @@ -10,11 +10,6 @@ use std::str::{self, FromStr}; mod primitive; fn main() { - let minor = match rustc_minor_version() { - Some(minor) => minor, - None => return, - }; - let target = match rustc_target() { Some(target) => target, None => return, @@ -28,11 +23,6 @@ fn main() { println!("cargo:rustc-cfg=has_atomics"); } - // If the Rust version is at least 1.46.0 then we can use type ids at compile time - if minor >= 47 { - println!("cargo:rustc-cfg=const_type_id"); - } - // Generate sorted type id lookup #[cfg(feature = "kv_unstable")] primitive::generate(); @@ -61,33 +51,3 @@ fn target_has_atomics(target: &str) -> bool { fn rustc_target() -> Option { env::var("TARGET").ok() } - -// From the `serde` build script -fn rustc_minor_version() -> Option { - let rustc = match env::var_os("RUSTC") { - Some(rustc) => rustc, - None => return None, - }; - - let output = match Command::new(rustc).arg("--version").output() { - Ok(output) => output, - Err(_) => return None, - }; - - let version = match str::from_utf8(&output.stdout) { - Ok(version) => version, - Err(_) => return None, - }; - - let mut pieces = version.split('.'); - if pieces.next() != Some("rustc 1") { - return None; - } - - let next = match pieces.next() { - Some(next) => next, - None => return None, - }; - - u32::from_str(next).ok() -} From b6438b9b1191179e407552cf834df67f9dcd6466 Mon Sep 17 00:00:00 2001 From: Matt Brubeck Date: Mon, 12 Oct 2020 11:04:06 -0700 Subject: [PATCH 016/280] Update to cfg-if 1.0 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 4021fb041..69fe79d25 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,7 +49,7 @@ kv_unstable = [] kv_unstable_sval = ["kv_unstable", "sval/fmt"] [dependencies] -cfg-if = "0.1.2" +cfg-if = "1.0" serde = { version = "1.0", optional = true, default-features = false } sval = { version = "0.5.2", optional = true, default-features = false } From ed7a622a3f016822888412249d20642d57c0849e Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Mon, 9 Nov 2020 15:59:04 -0500 Subject: [PATCH 017/280] Remove some trailing semicolons from macro definitions This will allow these macros to continue to be used in expression position if https://github.com/rust-lang/rust/issues/33953 is fixed. --- src/macros.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index ae6080d9b..7b87501f4 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -71,10 +71,10 @@ macro_rules! log { #[macro_export(local_inner_macros)] macro_rules! error { (target: $target:expr, $($arg:tt)+) => ( - log!(target: $target, $crate::Level::Error, $($arg)+); + log!(target: $target, $crate::Level::Error, $($arg)+) ); ($($arg:tt)+) => ( - log!($crate::Level::Error, $($arg)+); + log!($crate::Level::Error, $($arg)+) ) } @@ -95,10 +95,10 @@ macro_rules! error { #[macro_export(local_inner_macros)] macro_rules! warn { (target: $target:expr, $($arg:tt)+) => ( - log!(target: $target, $crate::Level::Warn, $($arg)+); + log!(target: $target, $crate::Level::Warn, $($arg)+) ); ($($arg:tt)+) => ( - log!($crate::Level::Warn, $($arg)+); + log!($crate::Level::Warn, $($arg)+) ) } @@ -121,10 +121,10 @@ macro_rules! warn { #[macro_export(local_inner_macros)] macro_rules! info { (target: $target:expr, $($arg:tt)+) => ( - log!(target: $target, $crate::Level::Info, $($arg)+); + log!(target: $target, $crate::Level::Info, $($arg)+) ); ($($arg:tt)+) => ( - log!($crate::Level::Info, $($arg)+); + log!($crate::Level::Info, $($arg)+) ) } @@ -146,10 +146,10 @@ macro_rules! info { #[macro_export(local_inner_macros)] macro_rules! debug { (target: $target:expr, $($arg:tt)+) => ( - log!(target: $target, $crate::Level::Debug, $($arg)+); + log!(target: $target, $crate::Level::Debug, $($arg)+) ); ($($arg:tt)+) => ( - log!($crate::Level::Debug, $($arg)+); + log!($crate::Level::Debug, $($arg)+) ) } @@ -173,10 +173,10 @@ macro_rules! debug { #[macro_export(local_inner_macros)] macro_rules! trace { (target: $target:expr, $($arg:tt)+) => ( - log!(target: $target, $crate::Level::Trace, $($arg)+); + log!(target: $target, $crate::Level::Trace, $($arg)+) ); ($($arg:tt)+) => ( - log!($crate::Level::Trace, $($arg)+); + log!($crate::Level::Trace, $($arg)+) ) } From 84b78e27fa27a66ba25e26957faca547bb3e0089 Mon Sep 17 00:00:00 2001 From: Ashley Mannix <=> Date: Sat, 3 Oct 2020 17:06:45 +1000 Subject: [PATCH 018/280] replace value impl with value-bag --- Cargo.toml | 10 +- build.rs | 9 - src/kv/source.rs | 4 +- src/kv/value.rs | 575 ++++++++++++++++++++++++ src/kv/value/fill.rs | 164 ------- src/kv/value/impls.rs | 141 ------ src/kv/value/internal/cast/mod.rs | 425 ------------------ src/kv/value/internal/cast/primitive.rs | 120 ----- src/kv/value/internal/fmt.rs | 315 ------------- src/kv/value/internal/mod.rs | 210 --------- src/kv/value/internal/sval.rs | 252 ----------- src/kv/value/mod.rs | 180 -------- src/kv/value/test.rs | 81 ---- 13 files changed, 583 insertions(+), 1903 deletions(-) create mode 100644 src/kv/value.rs delete mode 100644 src/kv/value/fill.rs delete mode 100644 src/kv/value/impls.rs delete mode 100644 src/kv/value/internal/cast/mod.rs delete mode 100644 src/kv/value/internal/cast/primitive.rs delete mode 100644 src/kv/value/internal/fmt.rs delete mode 100644 src/kv/value/internal/mod.rs delete mode 100644 src/kv/value/internal/sval.rs delete mode 100644 src/kv/value/mod.rs delete mode 100644 src/kv/value/test.rs diff --git a/Cargo.toml b/Cargo.toml index 69fe79d25..a90852bc0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -45,14 +45,16 @@ std = [] # requires the latest stable # this will have a tighter MSRV before stabilization -kv_unstable = [] -kv_unstable_sval = ["kv_unstable", "sval/fmt"] +kv_unstable = ["value-bag"] +kv_unstable_sval = ["kv_unstable", "value-bag/sval", "sval"] +kv_unstable_std = ["std", "kv_unstable", "value-bag/std"] [dependencies] cfg-if = "1.0" serde = { version = "1.0", optional = true, default-features = false } -sval = { version = "0.5.2", optional = true, default-features = false } +sval = { version = "1.0.0-alpha.4", optional = true, default-features = false } +value-bag = { version = "1.0.0-alpha.5", optional = true, default-features = false } [dev-dependencies] serde_test = "1.0" -sval = { version = "0.5.2", features = ["test"] } +value-bag = { version = "1.0.0-alpha.5", features = ["test"] } diff --git a/build.rs b/build.rs index bb2462d06..2b17e0be9 100644 --- a/build.rs +++ b/build.rs @@ -4,10 +4,6 @@ use std::env; use std::str; -#[cfg(feature = "kv_unstable")] -#[path = "src/kv/value/internal/cast/primitive.rs"] -mod primitive; - fn main() { let target = match rustc_target() { Some(target) => target, @@ -22,11 +18,6 @@ fn main() { println!("cargo:rustc-cfg=has_atomics"); } - // Generate sorted type id lookup - #[cfg(feature = "kv_unstable")] - primitive::generate(); - - println!("cargo:rustc-cfg=srcbuild"); println!("cargo:rerun-if-changed=build.rs"); } diff --git a/src/kv/source.rs b/src/kv/source.rs index 86b016033..cb5efc066 100644 --- a/src/kv/source.rs +++ b/src/kv/source.rs @@ -323,7 +323,7 @@ mod std_support { #[cfg(test)] mod tests { use super::*; - use kv::value::test::Token; + use kv::value::tests::Token; use std::collections::{BTreeMap, HashMap}; #[test] @@ -375,7 +375,7 @@ mod std_support { #[cfg(test)] mod tests { use super::*; - use kv::value::test::Token; + use kv::value::tests::Token; #[test] fn source_is_object_safe() { diff --git a/src/kv/value.rs b/src/kv/value.rs new file mode 100644 index 000000000..c30787ff7 --- /dev/null +++ b/src/kv/value.rs @@ -0,0 +1,575 @@ +//! Structured values. + +use std::fmt; + +extern crate value_bag; + +#[cfg(feature = "kv_unstable_sval")] +extern crate sval; + +use self::value_bag::ValueBag; + +pub use kv::Error; + +/// A type that can be converted into a [`Value`](struct.Value.html). +pub trait ToValue { + /// Perform the conversion. + fn to_value(&self) -> Value; +} + +impl<'a, T> ToValue for &'a T +where + T: ToValue + ?Sized, +{ + fn to_value(&self) -> Value { + (**self).to_value() + } +} + +impl<'v> ToValue for Value<'v> { + fn to_value(&self) -> Value { + Value { + inner: self.inner.clone(), + } + } +} + +/// A value in a structured key-value pair. +/// +/// # Capturing values +/// +/// There are a few ways to capture a value: +/// +/// - Using the `Value::capture_*` methods. +/// - Using the `Value::from_*` methods. +/// - Using the `ToValue` trait. +/// - Using the standard `From` trait. +/// +/// ## Using the `Value::capture_*` methods +/// +/// `Value` offers a few constructor methods that capture values of different kinds. +/// These methods require a `T: 'static` to support downcasting. +/// +/// ``` +/// use log::kv::Value; +/// +/// let value = Value::capture_debug(&42i32); +/// +/// assert_eq!(Some(42), value.to_i32()); +/// ``` +/// +/// ## Using the `Value::from_*` methods +/// +/// `Value` offers a few constructor methods that capture values of different kinds. +/// These methods don't require `T: 'static`, but can't support downcasting. +/// +/// ``` +/// use log::kv::Value; +/// +/// let value = Value::from_debug(&42i32); +/// +/// assert_eq!(None, value.to_i32()); +/// ``` +/// +/// ## Using the `ToValue` trait +/// +/// The `ToValue` trait can be used to capture values generically. +/// It's the bound used by `Source`. +/// +/// ``` +/// # use log::kv::ToValue; +/// let value = 42i32.to_value(); +/// +/// assert_eq!(Some(42), value.to_i32()); +/// ``` +/// +/// ``` +/// # use std::fmt::Debug; +/// use log::kv::ToValue; +/// +/// let value = (&42i32 as &dyn Debug).to_value(); +/// +/// assert_eq!(None, value.to_i32()); +/// ``` +/// +/// ## Using the standard `From` trait +/// +/// Standard types that implement `ToValue` also implement `From`. +/// +/// ``` +/// use log::kv::Value; +/// +/// let value = Value::from(42i32); +/// +/// assert_eq!(Some(42), value.to_i32()); +/// ``` +pub struct Value<'v> { + inner: ValueBag<'v>, +} + +impl<'v> Value<'v> { + /// Get a value from a type implementing `ToValue`. + pub fn from_any(value: &'v T) -> Self + where + T: ToValue, + { + value.to_value() + } + + /// Get a value from a type implementing `std::fmt::Debug`. + pub fn capture_debug(value: &'v T) -> Self + where + T: fmt::Debug + 'static, + { + Value { + inner: ValueBag::capture_debug(value), + } + } + + /// Get a value from a type implementing `std::fmt::Display`. + pub fn capture_display(value: &'v T) -> Self + where + T: fmt::Display + 'static, + { + Value { + inner: ValueBag::capture_display(value), + } + } + + /// Get a value from a type implementing `sval::value::Value`. + #[cfg(feature = "kv_unstable_sval")] + pub fn capture_sval(value: &'v T) -> Self + where + T: self::sval::value::Value + 'static, + { + Value { + inner: ValueBag::capture_sval1(value), + } + } + + /// Get a value from a type implementing `std::fmt::Debug`. + pub fn from_debug(value: &'v T) -> Self + where + T: fmt::Debug, + { + Value { + inner: ValueBag::from_debug(value), + } + } + + /// Get a value from a dynamic `std::fmt::Debug`. + pub fn from_dyn_debug(value: &'v dyn fmt::Debug) -> Self { + Value { + inner: ValueBag::from_dyn_debug(value), + } + } + + /// Get a value from a type implementing `std::fmt::Display`. + pub fn from_display(value: &'v T) -> Self + where + T: fmt::Display, + { + Value { + inner: ValueBag::from_display(value), + } + } + + /// Get a value from a dynamic `std::fmt::Display`. + pub fn from_dyn_display(value: &'v dyn fmt::Display) -> Self { + Value { + inner: ValueBag::from_dyn_display(value), + } + } + + /// Get a value from a type implementing `sval::value::Value`. + #[cfg(feature = "kv_unstable_sval")] + pub fn from_sval(value: &'v T) -> Self + where + T: self::sval::value::Value, + { + Value { + inner: ValueBag::from_sval1(value), + } + } + + /// Get a value from a type implementing `sval::value::Value`. + #[cfg(feature = "kv_unstable_sval")] + pub fn from_dyn_sval(value: &'v dyn self::sval::value::Value) -> Self { + Value { + inner: ValueBag::from_dyn_sval1(value), + } + } + + /// Get a value from an internal primitive. + fn from_value_bag(value: T) -> Self + where + T: Into>, + { + Value { + inner: value.into(), + } + } +} + +impl<'v> fmt::Debug for Value<'v> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Debug::fmt(&self.inner, f) + } +} + +impl<'v> fmt::Display for Value<'v> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&self.inner, f) + } +} + +impl ToValue for dyn fmt::Debug { + fn to_value(&self) -> Value { + Value::from_dyn_debug(self) + } +} + +impl ToValue for dyn fmt::Display { + fn to_value(&self) -> Value { + Value::from_dyn_display(self) + } +} + +#[cfg(feature = "kv_unstable_sval")] +impl<'v> self::sval::value::Value for Value<'v> { + fn stream(&self, stream: &mut self::sval::value::Stream) -> self::sval::value::Result { + self::sval::value::Value::stream(&self.inner, stream) + } +} + +#[cfg(feature = "kv_unstable_sval")] +impl ToValue for dyn self::sval::value::Value { + fn to_value(&self) -> Value { + Value::from_dyn_sval(self) + } +} + +impl<'v> ToValue for &'v str { + fn to_value(&self) -> Value { + Value::from(*self) + } +} + +impl<'v> From<&'v str> for Value<'v> { + fn from(value: &'v str) -> Self { + Value::from_value_bag(value) + } +} + +impl ToValue for () { + fn to_value(&self) -> Value { + Value::from_value_bag(()) + } +} + +impl ToValue for Option +where + T: ToValue, +{ + fn to_value(&self) -> Value { + match *self { + Some(ref value) => value.to_value(), + None => Value::from_value_bag(()), + } + } +} + +macro_rules! impl_to_value_primitive { + ($($into_ty:ty,)*) => { + $( + impl ToValue for $into_ty { + fn to_value(&self) -> Value { + Value::from(*self) + } + } + + impl<'v> From<$into_ty> for Value<'v> { + fn from(value: $into_ty) -> Self { + Value::from_value_bag(value) + } + } + )* + }; +} + +macro_rules! impl_value_to_primitive { + ($(#[doc = $doc:tt] $into_name:ident -> $into_ty:ty,)*) => { + impl<'v> Value<'v> { + $( + #[doc = $doc] + pub fn $into_name(&self) -> Option<$into_ty> { + self.inner.$into_name() + } + )* + } + } +} + +impl_to_value_primitive![usize, u8, u16, u32, u64, isize, i8, i16, i32, i64, f32, f64, char, bool,]; + +impl_value_to_primitive![ + #[doc = "Try convert this value into a `usize`."] + to_usize -> usize, + #[doc = "Try convert this value into a `u8`."] + to_u8 -> u8, + #[doc = "Try convert this value into a `u16`."] + to_u16 -> u16, + #[doc = "Try convert this value into a `u32`."] + to_u32 -> u32, + #[doc = "Try convert this value into a `u64`."] + to_u64 -> u64, + #[doc = "Try convert this value into a `isize`."] + to_isize -> isize, + #[doc = "Try convert this value into a `i8`."] + to_i8 -> i8, + #[doc = "Try convert this value into a `i16`."] + to_i16 -> i16, + #[doc = "Try convert this value into a `i32`."] + to_i32 -> i32, + #[doc = "Try convert this value into a `i64`."] + to_i64 -> i64, + #[doc = "Try convert this value into a `f32`."] + to_f32 -> f32, + #[doc = "Try convert this value into a `f64`."] + to_f64 -> f64, + #[doc = "Try convert this value into a `char`."] + to_char -> char, + #[doc = "Try convert this value into a `bool`."] + to_bool -> bool, +]; + +impl<'v> Value<'v> { + /// Try convert this value into a borrowed string. + pub fn to_borrowed_str(&self) -> Option<&str> { + self.inner.to_borrowed_str() + } +} + +#[cfg(feature = "std")] +mod std_support { + use super::*; + + use std::borrow::Cow; + + impl ToValue for Box + where + T: ToValue + ?Sized, + { + fn to_value(&self) -> Value { + (**self).to_value() + } + } + + impl ToValue for String { + fn to_value(&self) -> Value { + Value::from(&**self) + } + } + + impl<'v> ToValue for Cow<'v, str> { + fn to_value(&self) -> Value { + Value::from(&**self) + } + } + + impl<'v> Value<'v> { + /// Try convert this value into a string. + pub fn to_str(&self) -> Option> { + self.inner.to_str() + } + } +} + +#[cfg(test)] +pub(crate) mod tests { + use super::*; + + pub(crate) use super::value_bag::test::Token; + + impl<'v> Value<'v> { + pub(crate) fn to_token(&self) -> Token { + self.inner.to_token() + } + } + + fn unsigned() -> impl Iterator> { + vec![ + Value::from(8u8), + Value::from(16u16), + Value::from(32u32), + Value::from(64u64), + Value::from(1usize), + ] + .into_iter() + } + + fn signed() -> impl Iterator> { + vec![ + Value::from(-8i8), + Value::from(-16i16), + Value::from(-32i32), + Value::from(-64i64), + Value::from(-1isize), + ] + .into_iter() + } + + fn float() -> impl Iterator> { + vec![Value::from(32.32f32), Value::from(64.64f64)].into_iter() + } + + fn bool() -> impl Iterator> { + vec![Value::from(true), Value::from(false)].into_iter() + } + + fn str() -> impl Iterator> { + vec![Value::from("a string"), Value::from("a loong string")].into_iter() + } + + fn char() -> impl Iterator> { + vec![Value::from('a'), Value::from('â›°')].into_iter() + } + + #[test] + fn test_capture_fmt() { + assert_eq!(Some(42u64), Value::capture_display(&42).to_u64()); + assert_eq!(Some(42u64), Value::capture_debug(&42).to_u64()); + + assert!(Value::from_display(&42).to_u64().is_none()); + assert!(Value::from_debug(&42).to_u64().is_none()); + } + + #[cfg(feature = "kv_unstable_sval")] + #[test] + fn test_capture_sval() { + assert_eq!(Some(42u64), Value::capture_sval(&42).to_u64()); + + assert_eq!(Some(42u64), Value::from_sval(&42).to_u64()); + } + + #[test] + fn test_to_value_display() { + assert_eq!(42u64.to_value().to_string(), "42"); + assert_eq!(42i64.to_value().to_string(), "42"); + assert_eq!(42.01f64.to_value().to_string(), "42.01"); + assert_eq!(true.to_value().to_string(), "true"); + assert_eq!('a'.to_value().to_string(), "a"); + assert_eq!("a loong string".to_value().to_string(), "a loong string"); + assert_eq!(Some(true).to_value().to_string(), "true"); + assert_eq!(().to_value().to_string(), "None"); + assert_eq!(Option::None::.to_value().to_string(), "None"); + } + + #[test] + fn test_to_value_structured() { + assert_eq!(42u64.to_value().to_token(), Token::U64(42)); + assert_eq!(42i64.to_value().to_token(), Token::I64(42)); + assert_eq!(42.01f64.to_value().to_token(), Token::F64(42.01)); + assert_eq!(true.to_value().to_token(), Token::Bool(true)); + assert_eq!('a'.to_value().to_token(), Token::Char('a')); + assert_eq!( + "a loong string".to_value().to_token(), + Token::Str("a loong string".into()) + ); + assert_eq!(Some(true).to_value().to_token(), Token::Bool(true)); + assert_eq!(().to_value().to_token(), Token::None); + assert_eq!(Option::None::.to_value().to_token(), Token::None); + } + + #[test] + fn test_to_number() { + for v in unsigned().chain(signed()).chain(float()) { + assert!(v.to_u8().is_some()); + assert!(v.to_u16().is_some()); + assert!(v.to_u32().is_some()); + assert!(v.to_u64().is_some()); + assert!(v.to_usize().is_some()); + + assert!(v.to_i8().is_some()); + assert!(v.to_i16().is_some()); + assert!(v.to_i32().is_some()); + assert!(v.to_i64().is_some()); + assert!(v.to_isize().is_some()); + + assert!(v.to_f32().is_some()); + assert!(v.to_f64().is_some()); + } + + for v in bool().chain(str()).chain(char()) { + assert!(v.to_u8().is_none()); + assert!(v.to_u16().is_none()); + assert!(v.to_u32().is_none()); + assert!(v.to_u64().is_none()); + + assert!(v.to_i8().is_none()); + assert!(v.to_i16().is_none()); + assert!(v.to_i32().is_none()); + assert!(v.to_i64().is_none()); + + assert!(v.to_f32().is_none()); + assert!(v.to_f64().is_none()); + } + } + + #[test] + fn test_to_str() { + for v in str() { + assert!(v.to_borrowed_str().is_some()); + + #[cfg(feature = "std")] + assert!(v.to_str().is_some()); + } + + let short_lived = String::from("short lived"); + let v = Value::from(&*short_lived); + + assert!(v.to_borrowed_str().is_some()); + + #[cfg(feature = "std")] + assert!(v.to_str().is_some()); + + for v in unsigned().chain(signed()).chain(float()).chain(bool()) { + assert!(v.to_borrowed_str().is_none()); + + #[cfg(feature = "std")] + assert!(v.to_str().is_none()); + } + } + + #[test] + fn test_to_bool() { + for v in bool() { + assert!(v.to_bool().is_some()); + } + + for v in unsigned() + .chain(signed()) + .chain(float()) + .chain(str()) + .chain(char()) + { + assert!(v.to_bool().is_none()); + } + } + + #[test] + fn test_to_char() { + for v in char() { + assert!(v.to_char().is_some()); + } + + for v in unsigned() + .chain(signed()) + .chain(float()) + .chain(str()) + .chain(bool()) + { + assert!(v.to_char().is_none()); + } + } +} diff --git a/src/kv/value/fill.rs b/src/kv/value/fill.rs deleted file mode 100644 index f34ba31d5..000000000 --- a/src/kv/value/fill.rs +++ /dev/null @@ -1,164 +0,0 @@ -//! Lazy value initialization. - -use std::fmt; - -use super::internal::{Inner, Visitor}; -use super::{Error, Value}; - -impl<'v> Value<'v> { - /// Get a value from a fillable slot. - pub fn from_fill(value: &'v T) -> Self - where - T: Fill, - { - Value { - inner: Inner::Fill(value), - } - } -} - -/// A type that requires extra work to convert into a [`Value`](struct.Value.html). -/// -/// This trait is a more advanced initialization API than [`ToValue`](trait.ToValue.html). -/// It's intended for erased values coming from other logging frameworks that may need -/// to perform extra work to determine the concrete type to use. -pub trait Fill { - /// Fill a value. - fn fill(&self, slot: &mut Slot) -> Result<(), Error>; -} - -impl<'a, T> Fill for &'a T -where - T: Fill + ?Sized, -{ - fn fill(&self, slot: &mut Slot) -> Result<(), Error> { - (**self).fill(slot) - } -} - -/// A value slot to fill using the [`Fill`](trait.Fill.html) trait. -pub struct Slot<'s, 'f> { - filled: bool, - visitor: &'s mut dyn Visitor<'f>, -} - -impl<'s, 'f> fmt::Debug for Slot<'s, 'f> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("Slot").finish() - } -} - -impl<'s, 'f> Slot<'s, 'f> { - pub(super) fn new(visitor: &'s mut dyn Visitor<'f>) -> Self { - Slot { - visitor, - filled: false, - } - } - - pub(super) fn fill(&mut self, f: F) -> Result<(), Error> - where - F: FnOnce(&mut dyn Visitor<'f>) -> Result<(), Error>, - { - assert!(!self.filled, "the slot has already been filled"); - self.filled = true; - - f(self.visitor) - } - - /// Fill the slot with a value. - /// - /// The given value doesn't need to satisfy any particular lifetime constraints. - /// - /// # Panics - /// - /// Calling more than a single `fill` method on this slot will panic. - pub fn fill_any(&mut self, value: T) -> Result<(), Error> - where - T: Into>, - { - self.fill(|visitor| value.into().inner.visit(visitor)) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn fill_value_borrowed() { - struct TestFill; - - impl Fill for TestFill { - fn fill(&self, slot: &mut Slot) -> Result<(), Error> { - let dbg: &dyn fmt::Debug = &1; - - slot.fill_debug(&dbg) - } - } - - assert_eq!("1", Value::from_fill(&TestFill).to_string()); - } - - #[test] - fn fill_value_owned() { - struct TestFill; - - impl Fill for TestFill { - fn fill(&self, slot: &mut Slot) -> Result<(), Error> { - slot.fill_any("a string") - } - } - } - - #[test] - #[should_panic] - fn fill_multiple_times_panics() { - struct BadFill; - - impl Fill for BadFill { - fn fill(&self, slot: &mut Slot) -> Result<(), Error> { - slot.fill_any(42)?; - slot.fill_any(6789)?; - - Ok(()) - } - } - - let _ = Value::from_fill(&BadFill).to_string(); - } - - #[test] - fn fill_cast() { - struct TestFill; - - impl Fill for TestFill { - fn fill(&self, slot: &mut Slot) -> Result<(), Error> { - slot.fill_any("a string") - } - } - - assert_eq!( - "a string", - Value::from_fill(&TestFill) - .to_borrowed_str() - .expect("invalid value") - ); - } - - #[test] - fn fill_debug() { - struct TestFill; - - impl Fill for TestFill { - fn fill(&self, slot: &mut Slot) -> Result<(), Error> { - slot.fill_any(42u64) - } - } - - assert_eq!( - format!("{:04?}", 42u64), - format!("{:04?}", Value::from_fill(&TestFill)), - ) - } -} diff --git a/src/kv/value/impls.rs b/src/kv/value/impls.rs deleted file mode 100644 index 506128bf2..000000000 --- a/src/kv/value/impls.rs +++ /dev/null @@ -1,141 +0,0 @@ -//! Converting standard types into `Value`s. -//! -//! This module provides `ToValue` implementations for commonly -//! logged types from the standard library. - -use std::fmt; - -use super::{Primitive, ToValue, Value}; - -impl<'v> ToValue for &'v str { - fn to_value(&self) -> Value { - Value::from(*self) - } -} - -impl<'v> From<&'v str> for Value<'v> { - fn from(value: &'v str) -> Self { - Value::from_primitive(value) - } -} - -impl<'v> ToValue for fmt::Arguments<'v> { - fn to_value(&self) -> Value { - Value::from(*self) - } -} - -impl<'v> From> for Value<'v> { - fn from(value: fmt::Arguments<'v>) -> Self { - Value::from_primitive(value) - } -} - -impl ToValue for () { - fn to_value(&self) -> Value { - Value::from_primitive(Primitive::None) - } -} - -impl ToValue for Option -where - T: ToValue, -{ - fn to_value(&self) -> Value { - match *self { - Some(ref value) => value.to_value(), - None => Value::from_primitive(Primitive::None), - } - } -} - -macro_rules! impl_to_value_primitive { - ($($into_ty:ty,)*) => { - $( - impl ToValue for $into_ty { - fn to_value(&self) -> Value { - Value::from(*self) - } - } - - impl<'v> From<$into_ty> for Value<'v> { - fn from(value: $into_ty) -> Self { - Value::from_primitive(value) - } - } - )* - }; -} - -impl_to_value_primitive![usize, u8, u16, u32, u64, isize, i8, i16, i32, i64, f32, f64, char, bool,]; - -#[cfg(feature = "std")] -mod std_support { - use super::*; - - use std::borrow::Cow; - - impl ToValue for Box - where - T: ToValue + ?Sized, - { - fn to_value(&self) -> Value { - (**self).to_value() - } - } - - impl ToValue for String { - fn to_value(&self) -> Value { - Value::from_primitive(Primitive::Str(&*self)) - } - } - - impl<'v> ToValue for Cow<'v, str> { - fn to_value(&self) -> Value { - Value::from_primitive(Primitive::Str(&*self)) - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use kv::value::test::Token; - - #[test] - fn test_to_value_display() { - assert_eq!(42u64.to_value().to_string(), "42"); - assert_eq!(42i64.to_value().to_string(), "42"); - assert_eq!(42.01f64.to_value().to_string(), "42.01"); - assert_eq!(true.to_value().to_string(), "true"); - assert_eq!('a'.to_value().to_string(), "a"); - assert_eq!( - format_args!("a {}", "value").to_value().to_string(), - "a value" - ); - assert_eq!("a loong string".to_value().to_string(), "a loong string"); - assert_eq!(Some(true).to_value().to_string(), "true"); - assert_eq!(().to_value().to_string(), "None"); - assert_eq!(Option::None::.to_value().to_string(), "None"); - } - - #[test] - fn test_to_value_structured() { - assert_eq!(42u64.to_value().to_token(), Token::U64(42)); - assert_eq!(42i64.to_value().to_token(), Token::I64(42)); - assert_eq!(42.01f64.to_value().to_token(), Token::F64(42.01)); - assert_eq!(true.to_value().to_token(), Token::Bool(true)); - assert_eq!('a'.to_value().to_token(), Token::Char('a')); - assert_eq!( - format_args!("a {}", "value").to_value().to_token(), - Token::Str("a value".into()) - ); - assert_eq!( - "a loong string".to_value().to_token(), - Token::Str("a loong string".into()) - ); - assert_eq!(Some(true).to_value().to_token(), Token::Bool(true)); - assert_eq!(().to_value().to_token(), Token::None); - assert_eq!(Option::None::.to_value().to_token(), Token::None); - } -} diff --git a/src/kv/value/internal/cast/mod.rs b/src/kv/value/internal/cast/mod.rs deleted file mode 100644 index ec6a22379..000000000 --- a/src/kv/value/internal/cast/mod.rs +++ /dev/null @@ -1,425 +0,0 @@ -//! Coerce a `Value` into some concrete types. -//! -//! These operations are cheap when the captured value is a simple primitive, -//! but may end up executing arbitrary caller code if the value is complex. -//! They will also attempt to downcast erased types into a primitive where possible. - -use std::fmt; - -use super::{Inner, Primitive, Visitor}; -use crate::kv::value::{Error, Value}; - -mod primitive; - -/// Attempt to capture a primitive from some generic value. -/// -/// If the value is a primitive type, then cast it here, avoiding needing to erase its value -/// This makes `Value`s produced by `Value::from_*` more useful -pub(super) fn try_from_primitive<'v, T: 'static>(value: &'v T) -> Option> { - primitive::from_any(value).map(|primitive| Value { - inner: Inner::Primitive(primitive), - }) -} - -impl<'v> Value<'v> { - /// Try get a `usize` from this value. - /// - /// This method is cheap for primitive types, but may call arbitrary - /// serialization implementations for complex ones. - pub fn to_usize(&self) -> Option { - self.inner - .cast() - .into_primitive() - .into_u64() - .map(|v| v as usize) - } - - /// Try get a `u8` from this value. - /// - /// This method is cheap for primitive types, but may call arbitrary - /// serialization implementations for complex ones. - pub fn to_u8(&self) -> Option { - self.inner - .cast() - .into_primitive() - .into_u64() - .map(|v| v as u8) - } - - /// Try get a `u16` from this value. - /// - /// This method is cheap for primitive types, but may call arbitrary - /// serialization implementations for complex ones. - pub fn to_u16(&self) -> Option { - self.inner - .cast() - .into_primitive() - .into_u64() - .map(|v| v as u16) - } - - /// Try get a `u32` from this value. - /// - /// This method is cheap for primitive types, but may call arbitrary - /// serialization implementations for complex ones. - pub fn to_u32(&self) -> Option { - self.inner - .cast() - .into_primitive() - .into_u64() - .map(|v| v as u32) - } - - /// Try get a `u64` from this value. - /// - /// This method is cheap for primitive types, but may call arbitrary - /// serialization implementations for complex ones. - pub fn to_u64(&self) -> Option { - self.inner.cast().into_primitive().into_u64() - } - - /// Try get a `isize` from this value. - /// - /// This method is cheap for primitive types, but may call arbitrary - /// serialization implementations for complex ones. - pub fn to_isize(&self) -> Option { - self.inner - .cast() - .into_primitive() - .into_i64() - .map(|v| v as isize) - } - - /// Try get a `i8` from this value. - /// - /// This method is cheap for primitive types, but may call arbitrary - /// serialization implementations for complex ones. - pub fn to_i8(&self) -> Option { - self.inner - .cast() - .into_primitive() - .into_i64() - .map(|v| v as i8) - } - - /// Try get a `i16` from this value. - /// - /// This method is cheap for primitive types, but may call arbitrary - /// serialization implementations for complex ones. - pub fn to_i16(&self) -> Option { - self.inner - .cast() - .into_primitive() - .into_i64() - .map(|v| v as i16) - } - - /// Try get a `i32` from this value. - /// - /// This method is cheap for primitive types, but may call arbitrary - /// serialization implementations for complex ones. - pub fn to_i32(&self) -> Option { - self.inner - .cast() - .into_primitive() - .into_i64() - .map(|v| v as i32) - } - - /// Try get a `i64` from this value. - /// - /// This method is cheap for primitive types, but may call arbitrary - /// serialization implementations for complex ones. - pub fn to_i64(&self) -> Option { - self.inner.cast().into_primitive().into_i64() - } - - /// Try get a `f32` from this value. - /// - /// This method is cheap for primitive types, but may call arbitrary - /// serialization implementations for complex ones. - pub fn to_f32(&self) -> Option { - self.inner - .cast() - .into_primitive() - .into_f64() - .map(|v| v as f32) - } - - /// Try get a `f64` from this value. - /// - /// This method is cheap for primitive types, but may call arbitrary - /// serialization implementations for complex ones. - pub fn to_f64(&self) -> Option { - self.inner.cast().into_primitive().into_f64() - } - - /// Try get a `bool` from this value. - /// - /// This method is cheap for primitive types, but may call arbitrary - /// serialization implementations for complex ones. - pub fn to_bool(&self) -> Option { - self.inner.cast().into_primitive().into_bool() - } - - /// Try get a `char` from this value. - /// - /// This method is cheap for primitive types, but may call arbitrary - /// serialization implementations for complex ones. - pub fn to_char(&self) -> Option { - self.inner.cast().into_primitive().into_char() - } - - /// Try get a `str` from this value. - /// - /// This method is cheap for primitive types. It won't allocate an owned - /// `String` if the value is a complex type. - pub fn to_borrowed_str(&self) -> Option<&str> { - self.inner.cast().into_primitive().into_borrowed_str() - } -} - -impl<'v> Inner<'v> { - /// Cast the inner value to another type. - fn cast(self) -> Cast<'v> { - struct CastVisitor<'v>(Cast<'v>); - - impl<'v> Visitor<'v> for CastVisitor<'v> { - fn debug(&mut self, _: &dyn fmt::Debug) -> Result<(), Error> { - Ok(()) - } - - fn u64(&mut self, v: u64) -> Result<(), Error> { - self.0 = Cast::Primitive(Primitive::Unsigned(v)); - Ok(()) - } - - fn i64(&mut self, v: i64) -> Result<(), Error> { - self.0 = Cast::Primitive(Primitive::Signed(v)); - Ok(()) - } - - fn f64(&mut self, v: f64) -> Result<(), Error> { - self.0 = Cast::Primitive(Primitive::Float(v)); - Ok(()) - } - - fn bool(&mut self, v: bool) -> Result<(), Error> { - self.0 = Cast::Primitive(Primitive::Bool(v)); - Ok(()) - } - - fn char(&mut self, v: char) -> Result<(), Error> { - self.0 = Cast::Primitive(Primitive::Char(v)); - Ok(()) - } - - #[cfg(feature = "std")] - fn str(&mut self, s: &str) -> Result<(), Error> { - self.0 = Cast::String(s.to_owned()); - Ok(()) - } - - #[cfg(not(feature = "std"))] - fn str(&mut self, _: &str) -> Result<(), Error> { - Ok(()) - } - - fn borrowed_str(&mut self, v: &'v str) -> Result<(), Error> { - self.0 = Cast::Primitive(Primitive::Str(v)); - Ok(()) - } - - fn none(&mut self) -> Result<(), Error> { - self.0 = Cast::Primitive(Primitive::None); - Ok(()) - } - - #[cfg(feature = "kv_unstable_sval")] - fn sval(&mut self, v: &dyn super::sval::Value) -> Result<(), Error> { - self.0 = super::sval::cast(v); - Ok(()) - } - } - - if let Inner::Primitive(value) = self { - Cast::Primitive(value) - } else { - // If the erased value isn't a primitive then we visit it - let mut cast = CastVisitor(Cast::Primitive(Primitive::None)); - let _ = self.visit(&mut cast); - cast.0 - } - } -} - -pub(super) enum Cast<'v> { - Primitive(Primitive<'v>), - #[cfg(feature = "std")] - String(String), -} - -impl<'v> Cast<'v> { - fn into_primitive(self) -> Primitive<'v> { - match self { - Cast::Primitive(value) => value, - #[cfg(feature = "std")] - _ => Primitive::None, - } - } -} - -impl<'v> Primitive<'v> { - fn into_borrowed_str(self) -> Option<&'v str> { - if let Primitive::Str(value) = self { - Some(value) - } else { - None - } - } - - fn into_u64(self) -> Option { - match self { - Primitive::Unsigned(value) => Some(value), - Primitive::Signed(value) => Some(value as u64), - Primitive::Float(value) => Some(value as u64), - _ => None, - } - } - - fn into_i64(self) -> Option { - match self { - Primitive::Signed(value) => Some(value), - Primitive::Unsigned(value) => Some(value as i64), - Primitive::Float(value) => Some(value as i64), - _ => None, - } - } - - fn into_f64(self) -> Option { - match self { - Primitive::Float(value) => Some(value), - Primitive::Unsigned(value) => Some(value as f64), - Primitive::Signed(value) => Some(value as f64), - _ => None, - } - } - - fn into_char(self) -> Option { - if let Primitive::Char(value) = self { - Some(value) - } else { - None - } - } - - fn into_bool(self) -> Option { - if let Primitive::Bool(value) = self { - Some(value) - } else { - None - } - } -} - -#[cfg(feature = "std")] -mod std_support { - use super::*; - - use std::borrow::Cow; - - impl<'v> Value<'v> { - /// Try get a `usize` from this value. - /// - /// This method is cheap for primitive types, but may call arbitrary - /// serialization implementations for complex ones. If the serialization - /// implementation produces a short lived string it will be allocated. - pub fn to_str(&self) -> Option> { - self.inner.cast().into_str() - } - } - - impl<'v> Cast<'v> { - pub(super) fn into_str(self) -> Option> { - match self { - Cast::Primitive(Primitive::Str(value)) => Some(value.into()), - Cast::String(value) => Some(value.into()), - _ => None, - } - } - } - - #[cfg(test)] - mod tests { - use crate::kv::ToValue; - - #[test] - fn primitive_cast() { - assert_eq!( - "a string", - "a string" - .to_owned() - .to_value() - .to_borrowed_str() - .expect("invalid value") - ); - assert_eq!( - "a string", - &*"a string".to_value().to_str().expect("invalid value") - ); - assert_eq!( - "a string", - &*"a string" - .to_owned() - .to_value() - .to_str() - .expect("invalid value") - ); - } - } -} - -#[cfg(test)] -mod tests { - use crate::kv::ToValue; - - #[test] - fn primitive_cast() { - assert_eq!( - "a string", - "a string" - .to_value() - .to_borrowed_str() - .expect("invalid value") - ); - assert_eq!( - "a string", - Some("a string") - .to_value() - .to_borrowed_str() - .expect("invalid value") - ); - - assert_eq!(1u8, 1u64.to_value().to_u8().expect("invalid value")); - assert_eq!(1u16, 1u64.to_value().to_u16().expect("invalid value")); - assert_eq!(1u32, 1u64.to_value().to_u32().expect("invalid value")); - assert_eq!(1u64, 1u64.to_value().to_u64().expect("invalid value")); - assert_eq!(1usize, 1u64.to_value().to_usize().expect("invalid value")); - - assert_eq!(-1i8, -1i64.to_value().to_i8().expect("invalid value")); - assert_eq!(-1i16, -1i64.to_value().to_i16().expect("invalid value")); - assert_eq!(-1i32, -1i64.to_value().to_i32().expect("invalid value")); - assert_eq!(-1i64, -1i64.to_value().to_i64().expect("invalid value")); - assert_eq!(-1isize, -1i64.to_value().to_isize().expect("invalid value")); - - assert!(1f32.to_value().to_f32().is_some(), "invalid value"); - assert!(1f64.to_value().to_f64().is_some(), "invalid value"); - - assert_eq!(1u32, 1i64.to_value().to_u32().expect("invalid value")); - assert_eq!(1i32, 1u64.to_value().to_i32().expect("invalid value")); - assert!(1f32.to_value().to_i32().is_some(), "invalid value"); - - assert_eq!('a', 'a'.to_value().to_char().expect("invalid value")); - assert_eq!(true, true.to_value().to_bool().expect("invalid value")); - } -} diff --git a/src/kv/value/internal/cast/primitive.rs b/src/kv/value/internal/cast/primitive.rs deleted file mode 100644 index c306e66f6..000000000 --- a/src/kv/value/internal/cast/primitive.rs +++ /dev/null @@ -1,120 +0,0 @@ -/* -This module generates code to try efficiently convert some arbitrary `T: 'static` into -a `Primitive`. It's used by both the `build.rs` script and by the source itself. There -are currently two implementations here: - -- When the compiler version is less than `1.46.0` we check type ids at runtime. This -means generating a pre-sorted list of type ids at compile time using the `build.rs` -and matching them at runtime. -- When the compiler version is at least `1.46.0` we use const evaluation to check type ids -at compile time. There's no generated code from `build.rs` involved. - -In the future when `min_specialization` is stabilized we could use it instead and avoid needing -the `'static` bound altogether. -*/ - -// Use a build-time generated set of type ids to match a type with a conversion fn -#[cfg(srcbuild)] -pub(super) fn from_any<'v>( - value: &'v (dyn std::any::Any + 'static), -) -> Option> { - // The set of type ids that map to primitives are generated at build-time - // by the contents of `sorted_type_ids.expr`. These type ids are pre-sorted - // so that they can be searched efficiently. See the `sorted_type_ids.expr.rs` - // file for the set of types that appear in this list - let type_ids = include!(concat!(env!("OUT_DIR"), "/into_primitive.rs")); - - if let Ok(i) = type_ids.binary_search_by_key(&value.type_id(), |&(k, _)| k) { - Some((type_ids[i].1)(value)) - } else { - None - } -} - -// When the `src_build` config is not set then we're in the build script -#[cfg(not(srcbuild))] -#[allow(dead_code)] -pub fn generate() { - use std::path::Path; - use std::{env, fs}; - - macro_rules! type_ids { - ($($ty:ty,)*) => { - [ - $( - ( - std::any::TypeId::of::<$ty>(), - stringify!( - ( - std::any::TypeId::of::<$ty>(), - (|value| unsafe { - debug_assert_eq!(value.type_id(), std::any::TypeId::of::<$ty>()); - - // SAFETY: We verify the value is $ty before casting - let value = *(value as *const dyn std::any::Any as *const $ty); - crate::kv::value::internal::Primitive::from(value) - }) as for<'a> fn(&'a (dyn std::any::Any + 'static)) -> crate::kv::value::internal::Primitive<'a> - ) - ) - ), - )* - $( - ( - std::any::TypeId::of::>(), - stringify!( - ( - std::any::TypeId::of::>(), - (|value| unsafe { - debug_assert_eq!(value.type_id(), std::any::TypeId::of::>()); - - // SAFETY: We verify the value is Option<$ty> before casting - let value = *(value as *const dyn std::any::Any as *const Option<$ty>); - if let Some(value) = value { - crate::kv::value::internal::Primitive::from(value) - } else { - crate::kv::value::internal::Primitive::None - } - }) as for<'a> fn(&'a (dyn std::any::Any + 'static)) -> crate::kv::value::internal::Primitive<'a> - ) - ) - ), - )* - ] - }; - } - - // NOTE: The types here *must* match the ones used above when `const_type_id` is available - let mut type_ids = type_ids![ - usize, - u8, - u16, - u32, - u64, - isize, - i8, - i16, - i32, - i64, - f32, - f64, - char, - bool, - &'static str, - ]; - - type_ids.sort_by_key(|&(k, _)| k); - - let mut ordered_type_ids_expr = String::new(); - - ordered_type_ids_expr.push('['); - - for (_, v) in &type_ids { - ordered_type_ids_expr.push_str(v); - ordered_type_ids_expr.push(','); - } - - ordered_type_ids_expr.push(']'); - - let path = Path::new(&env::var_os("OUT_DIR").unwrap()).join("into_primitive.rs"); - fs::write(path, ordered_type_ids_expr).unwrap(); -} diff --git a/src/kv/value/internal/fmt.rs b/src/kv/value/internal/fmt.rs deleted file mode 100644 index bde703c20..000000000 --- a/src/kv/value/internal/fmt.rs +++ /dev/null @@ -1,315 +0,0 @@ -//! Integration between `Value` and `std::fmt`. -//! -//! This module allows any `Value` to implement the `fmt::Debug` and `fmt::Display` traits, -//! and for any `fmt::Debug` or `fmt::Display` to be captured as a `Value`. - -use std::fmt; - -use super::{cast, Inner, Visitor}; -use crate::kv; -use crate::kv::value::{Error, Slot, ToValue}; - -impl<'v> kv::Value<'v> { - /// Get a value from a debuggable type. - /// - /// This method will attempt to capture the given value as a well-known primitive - /// before resorting to using its `Debug` implementation. - pub fn capture_debug(value: &'v T) -> Self - where - T: fmt::Debug + 'static, - { - cast::try_from_primitive(value).unwrap_or(kv::Value { - inner: Inner::Debug(value), - }) - } - - /// Get a value from a debuggable type. - pub fn from_debug(value: &'v T) -> Self - where - T: fmt::Debug, - { - kv::Value { - inner: Inner::Debug(value), - } - } - - /// Get a value from a displayable type. - /// - /// This method will attempt to capture the given value as a well-known primitive - /// before resorting to using its `Display` implementation. - pub fn capture_display(value: &'v T) -> Self - where - T: fmt::Display + 'static, - { - cast::try_from_primitive(value).unwrap_or(kv::Value { - inner: Inner::Display(value), - }) - } - - /// Get a value from a displayable type. - pub fn from_display(value: &'v T) -> Self - where - T: fmt::Display, - { - kv::Value { - inner: Inner::Display(value), - } - } -} - -impl<'s, 'f> Slot<'s, 'f> { - /// Fill the slot with a debuggable value. - /// - /// The given value doesn't need to satisfy any particular lifetime constraints. - /// - /// # Panics - /// - /// Calling more than a single `fill` method on this slot will panic. - pub fn fill_debug(&mut self, value: T) -> Result<(), Error> - where - T: fmt::Debug, - { - self.fill(|visitor| visitor.debug(&value)) - } - - /// Fill the slot with a displayable value. - /// - /// The given value doesn't need to satisfy any particular lifetime constraints. - /// - /// # Panics - /// - /// Calling more than a single `fill` method on this slot will panic. - pub fn fill_display(&mut self, value: T) -> Result<(), Error> - where - T: fmt::Display, - { - self.fill(|visitor| visitor.display(&value)) - } -} - -pub(in kv::value) use self::fmt::{Arguments, Debug, Display}; - -impl<'v> fmt::Debug for kv::Value<'v> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - struct DebugVisitor<'a, 'b: 'a>(&'a mut fmt::Formatter<'b>); - - impl<'a, 'b: 'a, 'v> Visitor<'v> for DebugVisitor<'a, 'b> { - fn debug(&mut self, v: &dyn fmt::Debug) -> Result<(), Error> { - fmt::Debug::fmt(v, self.0)?; - - Ok(()) - } - - fn display(&mut self, v: &dyn fmt::Display) -> Result<(), Error> { - fmt::Display::fmt(v, self.0)?; - - Ok(()) - } - - fn u64(&mut self, v: u64) -> Result<(), Error> { - fmt::Debug::fmt(&v, self.0)?; - - Ok(()) - } - - fn i64(&mut self, v: i64) -> Result<(), Error> { - fmt::Debug::fmt(&v, self.0)?; - - Ok(()) - } - - fn f64(&mut self, v: f64) -> Result<(), Error> { - fmt::Debug::fmt(&v, self.0)?; - - Ok(()) - } - - fn bool(&mut self, v: bool) -> Result<(), Error> { - fmt::Debug::fmt(&v, self.0)?; - - Ok(()) - } - - fn char(&mut self, v: char) -> Result<(), Error> { - fmt::Debug::fmt(&v, self.0)?; - - Ok(()) - } - - fn str(&mut self, v: &str) -> Result<(), Error> { - fmt::Debug::fmt(&v, self.0)?; - - Ok(()) - } - - fn none(&mut self) -> Result<(), Error> { - self.debug(&format_args!("None")) - } - - #[cfg(feature = "kv_unstable_sval")] - fn sval(&mut self, v: &dyn super::sval::Value) -> Result<(), Error> { - super::sval::fmt(self.0, v) - } - } - - self.visit(&mut DebugVisitor(f)).map_err(|_| fmt::Error)?; - - Ok(()) - } -} - -impl<'v> fmt::Display for kv::Value<'v> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - struct DisplayVisitor<'a, 'b: 'a>(&'a mut fmt::Formatter<'b>); - - impl<'a, 'b: 'a, 'v> Visitor<'v> for DisplayVisitor<'a, 'b> { - fn debug(&mut self, v: &dyn fmt::Debug) -> Result<(), Error> { - fmt::Debug::fmt(v, self.0)?; - - Ok(()) - } - - fn display(&mut self, v: &dyn fmt::Display) -> Result<(), Error> { - fmt::Display::fmt(v, self.0)?; - - Ok(()) - } - - fn u64(&mut self, v: u64) -> Result<(), Error> { - fmt::Display::fmt(&v, self.0)?; - - Ok(()) - } - - fn i64(&mut self, v: i64) -> Result<(), Error> { - fmt::Display::fmt(&v, self.0)?; - - Ok(()) - } - - fn f64(&mut self, v: f64) -> Result<(), Error> { - fmt::Display::fmt(&v, self.0)?; - - Ok(()) - } - - fn bool(&mut self, v: bool) -> Result<(), Error> { - fmt::Display::fmt(&v, self.0)?; - - Ok(()) - } - - fn char(&mut self, v: char) -> Result<(), Error> { - fmt::Display::fmt(&v, self.0)?; - - Ok(()) - } - - fn str(&mut self, v: &str) -> Result<(), Error> { - fmt::Display::fmt(&v, self.0)?; - - Ok(()) - } - - fn none(&mut self) -> Result<(), Error> { - self.debug(&format_args!("None")) - } - - #[cfg(feature = "kv_unstable_sval")] - fn sval(&mut self, v: &dyn super::sval::Value) -> Result<(), Error> { - super::sval::fmt(self.0, v) - } - } - - self.visit(&mut DisplayVisitor(f)).map_err(|_| fmt::Error)?; - - Ok(()) - } -} - -impl<'v> ToValue for dyn fmt::Debug + 'v { - fn to_value(&self) -> kv::Value { - kv::Value::from(self) - } -} - -impl<'v> ToValue for dyn fmt::Display + 'v { - fn to_value(&self) -> kv::Value { - kv::Value::from(self) - } -} - -impl<'v> From<&'v (dyn fmt::Debug)> for kv::Value<'v> { - fn from(value: &'v (dyn fmt::Debug)) -> kv::Value<'v> { - kv::Value { - inner: Inner::Debug(value), - } - } -} - -impl<'v> From<&'v (dyn fmt::Display)> for kv::Value<'v> { - fn from(value: &'v (dyn fmt::Display)) -> kv::Value<'v> { - kv::Value { - inner: Inner::Display(value), - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - use kv::value::test::Token; - - use crate::kv::value::ToValue; - - #[test] - fn fmt_capture() { - assert_eq!(kv::Value::capture_debug(&1u16).to_token(), Token::U64(1)); - assert_eq!(kv::Value::capture_display(&1u16).to_token(), Token::U64(1)); - - assert_eq!( - kv::Value::capture_debug(&Some(1u16)).to_token(), - Token::U64(1) - ); - } - - #[test] - fn fmt_cast() { - assert_eq!( - 42u32, - kv::Value::capture_debug(&42u64) - .to_u32() - .expect("invalid value") - ); - - assert_eq!( - "a string", - kv::Value::capture_display(&"a string") - .to_borrowed_str() - .expect("invalid value") - ); - } - - #[test] - fn fmt_debug() { - assert_eq!( - format!("{:?}", "a string"), - format!("{:?}", "a string".to_value()), - ); - - assert_eq!( - format!("{:04?}", 42u64), - format!("{:04?}", 42u64.to_value()), - ); - } - - #[test] - fn fmt_display() { - assert_eq!( - format!("{}", "a string"), - format!("{}", "a string".to_value()), - ); - - assert_eq!(format!("{:04}", 42u64), format!("{:04}", 42u64.to_value()),); - } -} diff --git a/src/kv/value/internal/mod.rs b/src/kv/value/internal/mod.rs deleted file mode 100644 index 4acbe683c..000000000 --- a/src/kv/value/internal/mod.rs +++ /dev/null @@ -1,210 +0,0 @@ -//! The internal `Value` serialization API. -//! -//! This implementation isn't intended to be public. It may need to change -//! for optimizations or to support new external serialization frameworks. - -use super::{Error, Fill, Slot}; - -pub(super) mod cast; -pub(super) mod fmt; -#[cfg(feature = "kv_unstable_sval")] -pub(super) mod sval; - -/// A container for a structured value for a specific kind of visitor. -#[derive(Clone, Copy)] -pub(super) enum Inner<'v> { - /// A simple primitive value that can be copied without allocating. - Primitive(Primitive<'v>), - /// A value that can be filled. - Fill(&'v (dyn Fill)), - /// A debuggable value. - Debug(&'v (dyn fmt::Debug)), - /// A displayable value. - Display(&'v (dyn fmt::Display)), - - #[cfg(feature = "kv_unstable_sval")] - /// A structured value from `sval`. - Sval(&'v (dyn sval::Value)), -} - -impl<'v> Inner<'v> { - pub(super) fn visit(self, visitor: &mut dyn Visitor<'v>) -> Result<(), Error> { - match self { - Inner::Primitive(value) => value.visit(visitor), - - Inner::Debug(value) => visitor.debug(value), - Inner::Display(value) => visitor.display(value), - - Inner::Fill(value) => value.fill(&mut Slot::new(visitor)), - - #[cfg(feature = "kv_unstable_sval")] - Inner::Sval(value) => visitor.sval(value), - } - } -} - -/// The internal serialization contract. -pub(super) trait Visitor<'v> { - fn debug(&mut self, v: &dyn fmt::Debug) -> Result<(), Error>; - fn display(&mut self, v: &dyn fmt::Display) -> Result<(), Error> { - self.debug(&format_args!("{}", v)) - } - - fn u64(&mut self, v: u64) -> Result<(), Error>; - fn i64(&mut self, v: i64) -> Result<(), Error>; - fn f64(&mut self, v: f64) -> Result<(), Error>; - fn bool(&mut self, v: bool) -> Result<(), Error>; - fn char(&mut self, v: char) -> Result<(), Error>; - - fn str(&mut self, v: &str) -> Result<(), Error>; - fn borrowed_str(&mut self, v: &'v str) -> Result<(), Error> { - self.str(v) - } - - fn none(&mut self) -> Result<(), Error>; - - #[cfg(feature = "kv_unstable_sval")] - fn sval(&mut self, v: &dyn sval::Value) -> Result<(), Error>; -} - -/// A captured primitive value. -/// -/// These values are common and cheap to copy around. -#[derive(Clone, Copy)] -pub(super) enum Primitive<'v> { - Signed(i64), - Unsigned(u64), - Float(f64), - Bool(bool), - Char(char), - Str(&'v str), - Fmt(fmt::Arguments<'v>), - None, -} - -impl<'v> Primitive<'v> { - fn visit(self, visitor: &mut dyn Visitor<'v>) -> Result<(), Error> { - match self { - Primitive::Signed(value) => visitor.i64(value), - Primitive::Unsigned(value) => visitor.u64(value), - Primitive::Float(value) => visitor.f64(value), - Primitive::Bool(value) => visitor.bool(value), - Primitive::Char(value) => visitor.char(value), - Primitive::Str(value) => visitor.borrowed_str(value), - Primitive::Fmt(value) => visitor.debug(&value), - Primitive::None => visitor.none(), - } - } -} - -impl<'v> From for Primitive<'v> { - #[inline] - fn from(v: u8) -> Self { - Primitive::Unsigned(v as u64) - } -} - -impl<'v> From for Primitive<'v> { - #[inline] - fn from(v: u16) -> Self { - Primitive::Unsigned(v as u64) - } -} - -impl<'v> From for Primitive<'v> { - #[inline] - fn from(v: u32) -> Self { - Primitive::Unsigned(v as u64) - } -} - -impl<'v> From for Primitive<'v> { - #[inline] - fn from(v: u64) -> Self { - Primitive::Unsigned(v) - } -} - -impl<'v> From for Primitive<'v> { - #[inline] - fn from(v: usize) -> Self { - Primitive::Unsigned(v as u64) - } -} - -impl<'v> From for Primitive<'v> { - #[inline] - fn from(v: i8) -> Self { - Primitive::Signed(v as i64) - } -} - -impl<'v> From for Primitive<'v> { - #[inline] - fn from(v: i16) -> Self { - Primitive::Signed(v as i64) - } -} - -impl<'v> From for Primitive<'v> { - #[inline] - fn from(v: i32) -> Self { - Primitive::Signed(v as i64) - } -} - -impl<'v> From for Primitive<'v> { - #[inline] - fn from(v: i64) -> Self { - Primitive::Signed(v) - } -} - -impl<'v> From for Primitive<'v> { - #[inline] - fn from(v: isize) -> Self { - Primitive::Signed(v as i64) - } -} - -impl<'v> From for Primitive<'v> { - #[inline] - fn from(v: f32) -> Self { - Primitive::Float(v as f64) - } -} - -impl<'v> From for Primitive<'v> { - #[inline] - fn from(v: f64) -> Self { - Primitive::Float(v) - } -} - -impl<'v> From for Primitive<'v> { - #[inline] - fn from(v: bool) -> Self { - Primitive::Bool(v) - } -} - -impl<'v> From for Primitive<'v> { - #[inline] - fn from(v: char) -> Self { - Primitive::Char(v) - } -} - -impl<'v> From<&'v str> for Primitive<'v> { - #[inline] - fn from(v: &'v str) -> Self { - Primitive::Str(v) - } -} - -impl<'v> From> for Primitive<'v> { - #[inline] - fn from(v: fmt::Arguments<'v>) -> Self { - Primitive::Fmt(v) - } -} diff --git a/src/kv/value/internal/sval.rs b/src/kv/value/internal/sval.rs deleted file mode 100644 index 252efd152..000000000 --- a/src/kv/value/internal/sval.rs +++ /dev/null @@ -1,252 +0,0 @@ -//! Integration between `Value` and `sval`. -//! -//! This module allows any `Value` to implement the `sval::Value` trait, -//! and for any `sval::Value` to be captured as a `Value`. - -extern crate sval; - -use std::fmt; - -use super::cast::{self, Cast}; -use super::{Inner, Primitive, Visitor}; -use crate::kv; -use crate::kv::value::{Error, Slot, ToValue}; - -impl<'v> kv::Value<'v> { - /// Get a value from a structured type. - /// - /// This method will attempt to capture the given value as a well-known primitive - /// before resorting to using its `Value` implementation. - pub fn capture_sval(value: &'v T) -> Self - where - T: sval::Value + 'static, - { - cast::try_from_primitive(value).unwrap_or(kv::Value { - inner: Inner::Sval(value), - }) - } - - /// Get a value from a structured type. - pub fn from_sval(value: &'v T) -> Self - where - T: sval::Value, - { - kv::Value { - inner: Inner::Sval(value), - } - } -} - -impl<'s, 'f> Slot<'s, 'f> { - /// Fill the slot with a structured value. - /// - /// The given value doesn't need to satisfy any particular lifetime constraints. - /// - /// # Panics - /// - /// Calling more than a single `fill` method on this slot will panic. - pub fn fill_sval(&mut self, value: T) -> Result<(), Error> - where - T: sval::Value, - { - self.fill(|visitor| visitor.sval(&value)) - } -} - -impl<'v> sval::Value for kv::Value<'v> { - fn stream(&self, s: &mut sval::value::Stream) -> sval::value::Result { - struct SvalVisitor<'a, 'b: 'a>(&'a mut sval::value::Stream<'b>); - - impl<'a, 'b: 'a, 'v> Visitor<'v> for SvalVisitor<'a, 'b> { - fn debug(&mut self, v: &dyn fmt::Debug) -> Result<(), Error> { - self.0 - .fmt(format_args!("{:?}", v)) - .map_err(Error::from_sval) - } - - fn u64(&mut self, v: u64) -> Result<(), Error> { - self.0.u64(v).map_err(Error::from_sval) - } - - fn i64(&mut self, v: i64) -> Result<(), Error> { - self.0.i64(v).map_err(Error::from_sval) - } - - fn f64(&mut self, v: f64) -> Result<(), Error> { - self.0.f64(v).map_err(Error::from_sval) - } - - fn bool(&mut self, v: bool) -> Result<(), Error> { - self.0.bool(v).map_err(Error::from_sval) - } - - fn char(&mut self, v: char) -> Result<(), Error> { - self.0.char(v).map_err(Error::from_sval) - } - - fn str(&mut self, v: &str) -> Result<(), Error> { - self.0.str(v).map_err(Error::from_sval) - } - - fn none(&mut self) -> Result<(), Error> { - self.0.none().map_err(Error::from_sval) - } - - fn sval(&mut self, v: &dyn sval::Value) -> Result<(), Error> { - self.0.any(v).map_err(Error::from_sval) - } - } - - self.visit(&mut SvalVisitor(s)).map_err(Error::into_sval)?; - - Ok(()) - } -} - -impl<'v> ToValue for dyn sval::Value + 'v { - fn to_value(&self) -> kv::Value { - kv::Value::from(self) - } -} - -impl<'v> From<&'v (dyn sval::Value)> for kv::Value<'v> { - fn from(value: &'v (dyn sval::Value)) -> kv::Value<'v> { - kv::Value { - inner: Inner::Sval(value), - } - } -} - -pub(in kv::value) use self::sval::Value; - -pub(super) fn fmt(f: &mut fmt::Formatter, v: &dyn sval::Value) -> Result<(), Error> { - sval::fmt::debug(f, v)?; - Ok(()) -} - -pub(super) fn cast<'v>(v: &dyn sval::Value) -> Cast<'v> { - struct CastStream<'v>(Cast<'v>); - - impl<'v> sval::Stream for CastStream<'v> { - fn u64(&mut self, v: u64) -> sval::stream::Result { - self.0 = Cast::Primitive(Primitive::Unsigned(v)); - Ok(()) - } - - fn i64(&mut self, v: i64) -> sval::stream::Result { - self.0 = Cast::Primitive(Primitive::Signed(v)); - Ok(()) - } - - fn f64(&mut self, v: f64) -> sval::stream::Result { - self.0 = Cast::Primitive(Primitive::Float(v)); - Ok(()) - } - - fn char(&mut self, v: char) -> sval::stream::Result { - self.0 = Cast::Primitive(Primitive::Char(v)); - Ok(()) - } - - fn bool(&mut self, v: bool) -> sval::stream::Result { - self.0 = Cast::Primitive(Primitive::Bool(v)); - Ok(()) - } - - #[cfg(feature = "std")] - fn str(&mut self, s: &str) -> sval::stream::Result { - self.0 = Cast::String(s.into()); - Ok(()) - } - } - - let mut cast = CastStream(Cast::Primitive(Primitive::None)); - let _ = sval::stream(&mut cast, v); - - cast.0 -} - -impl Error { - fn from_sval(_: sval::value::Error) -> Self { - Error::msg("`sval` serialization failed") - } - - fn into_sval(self) -> sval::value::Error { - sval::value::Error::msg("`sval` serialization failed") - } -} - -#[cfg(test)] -mod tests { - use super::*; - use kv::value::test::Token; - - #[test] - fn sval_capture() { - assert_eq!(kv::Value::capture_sval(&42u64).to_token(), Token::U64(42)); - } - - #[test] - fn sval_cast() { - assert_eq!( - 42u32, - kv::Value::capture_sval(&42u64) - .to_u32() - .expect("invalid value") - ); - - assert_eq!( - "a string", - kv::Value::capture_sval(&"a string") - .to_borrowed_str() - .expect("invalid value") - ); - - #[cfg(feature = "std")] - assert_eq!( - "a string", - kv::Value::capture_sval(&"a string") - .to_str() - .expect("invalid value") - ); - } - - #[test] - fn sval_structured() { - let value = kv::Value::from(42u64); - let expected = vec![sval::test::Token::Unsigned(42)]; - - assert_eq!(sval::test::tokens(value), expected); - } - - #[test] - fn sval_debug() { - struct TestSval; - - impl sval::Value for TestSval { - fn stream(&self, stream: &mut sval::value::Stream) -> sval::value::Result { - stream.u64(42) - } - } - - assert_eq!( - format!("{:04?}", 42u64), - format!("{:04?}", kv::Value::from_sval(&TestSval)), - ); - } - - #[cfg(feature = "std")] - mod std_support { - use super::*; - - #[test] - fn sval_cast() { - assert_eq!( - "a string", - kv::Value::capture_sval(&"a string".to_owned()) - .to_str() - .expect("invalid value") - ); - } - } -} diff --git a/src/kv/value/mod.rs b/src/kv/value/mod.rs deleted file mode 100644 index 8d8282624..000000000 --- a/src/kv/value/mod.rs +++ /dev/null @@ -1,180 +0,0 @@ -//! Structured values. - -mod fill; -mod impls; -mod internal; - -#[cfg(test)] -pub(in kv) mod test; - -pub use self::fill::{Fill, Slot}; -pub use kv::Error; - -use self::internal::{Inner, Primitive, Visitor}; - -/// A type that can be converted into a [`Value`](struct.Value.html). -pub trait ToValue { - /// Perform the conversion. - fn to_value(&self) -> Value; -} - -impl<'a, T> ToValue for &'a T -where - T: ToValue + ?Sized, -{ - fn to_value(&self) -> Value { - (**self).to_value() - } -} - -impl<'v> ToValue for Value<'v> { - fn to_value(&self) -> Value { - Value { inner: self.inner } - } -} - -/// A value in a structured key-value pair. -/// -/// # Capturing values -/// -/// There are a few ways to capture a value: -/// -/// - Using the `Value::capture_*` methods. -/// - Using the `Value::from_*` methods. -/// - Using the `ToValue` trait. -/// - Using the standard `From` trait. -/// - Using the `Fill` API. -/// -/// ## Using the `Value::capture_*` methods -/// -/// `Value` offers a few constructor methods that capture values of different kinds. -/// These methods require a `T: 'static` to support downcasting. -/// -/// ``` -/// use log::kv::Value; -/// -/// let value = Value::capture_debug(&42i32); -/// -/// assert_eq!(Some(42), value.to_i32()); -/// ``` -/// -/// ## Using the `Value::from_*` methods -/// -/// `Value` offers a few constructor methods that capture values of different kinds. -/// These methods don't require `T: 'static`, but can't support downcasting. -/// -/// ``` -/// use log::kv::Value; -/// -/// let value = Value::from_debug(&42i32); -/// -/// assert_eq!(None, value.to_i32()); -/// ``` -/// -/// ## Using the `ToValue` trait -/// -/// The `ToValue` trait can be used to capture values generically. -/// It's the bound used by `Source`. -/// -/// ``` -/// # use log::kv::ToValue; -/// let value = 42i32.to_value(); -/// -/// assert_eq!(Some(42), value.to_i32()); -/// ``` -/// -/// ``` -/// # use std::fmt::Debug; -/// use log::kv::ToValue; -/// -/// let value = (&42i32 as &dyn Debug).to_value(); -/// -/// assert_eq!(None, value.to_i32()); -/// ``` -/// -/// ## Using the standard `From` trait -/// -/// Standard types that implement `ToValue` also implement `From`. -/// -/// ``` -/// use log::kv::Value; -/// -/// let value = Value::from(42i32); -/// -/// assert_eq!(Some(42), value.to_i32()); -/// ``` -/// -/// ``` -/// # use std::fmt::Debug; -/// use log::kv::Value; -/// -/// let value = Value::from(&42i32 as &dyn Debug); -/// -/// assert_eq!(None, value.to_i32()); -/// ``` -/// -/// ## Using the `Fill` API -/// -/// The `Fill` trait is a way to bridge APIs that may not be directly -/// compatible with other constructor methods. -/// -/// ``` -/// use log::kv::value::{Value, Slot, Fill, Error}; -/// -/// struct FillSigned; -/// -/// impl Fill for FillSigned { -/// fn fill(&self, slot: &mut Slot) -> Result<(), Error> { -/// slot.fill_any(42i32) -/// } -/// } -/// -/// let value = Value::from_fill(&FillSigned); -/// -/// assert_eq!(Some(42), value.to_i32()); -/// ``` -/// -/// ``` -/// # use std::fmt::Debug; -/// use log::kv::value::{Value, Slot, Fill, Error}; -/// -/// struct FillDebug; -/// -/// impl Fill for FillDebug { -/// fn fill(&self, slot: &mut Slot) -> Result<(), Error> { -/// slot.fill_debug(&42i32 as &dyn Debug) -/// } -/// } -/// -/// let value = Value::from_fill(&FillDebug); -/// -/// assert_eq!(None, value.to_i32()); -/// ``` -pub struct Value<'v> { - inner: Inner<'v>, -} - -impl<'v> Value<'v> { - /// Get a value from a type implementing `ToValue`. - pub fn from_any(value: &'v T) -> Self - where - T: ToValue, - { - value.to_value() - } - - /// Get a value from an internal primitive. - fn from_primitive(value: T) -> Self - where - T: Into>, - { - Value { - inner: Inner::Primitive(value.into()), - } - } - - /// Visit the value using an internal visitor. - fn visit<'a>(&'a self, visitor: &mut dyn Visitor<'a>) -> Result<(), Error> { - self.inner.visit(visitor) - } -} diff --git a/src/kv/value/test.rs b/src/kv/value/test.rs deleted file mode 100644 index ab5f8075e..000000000 --- a/src/kv/value/test.rs +++ /dev/null @@ -1,81 +0,0 @@ -// Test support for inspecting Values - -use std::fmt; -use std::str; - -use super::internal; -use super::{Error, Value}; - -#[derive(Debug, PartialEq)] -pub(in kv) enum Token { - U64(u64), - I64(i64), - F64(f64), - Char(char), - Bool(bool), - Str(String), - None, - - #[cfg(feature = "kv_unstable_sval")] - Sval, -} - -#[cfg(test)] -impl<'v> Value<'v> { - pub(in kv) fn to_token(&self) -> Token { - struct TestVisitor(Option); - - impl<'v> internal::Visitor<'v> for TestVisitor { - fn debug(&mut self, v: &dyn fmt::Debug) -> Result<(), Error> { - self.0 = Some(Token::Str(format!("{:?}", v))); - Ok(()) - } - - fn u64(&mut self, v: u64) -> Result<(), Error> { - self.0 = Some(Token::U64(v)); - Ok(()) - } - - fn i64(&mut self, v: i64) -> Result<(), Error> { - self.0 = Some(Token::I64(v)); - Ok(()) - } - - fn f64(&mut self, v: f64) -> Result<(), Error> { - self.0 = Some(Token::F64(v)); - Ok(()) - } - - fn bool(&mut self, v: bool) -> Result<(), Error> { - self.0 = Some(Token::Bool(v)); - Ok(()) - } - - fn char(&mut self, v: char) -> Result<(), Error> { - self.0 = Some(Token::Char(v)); - Ok(()) - } - - fn str(&mut self, v: &str) -> Result<(), Error> { - self.0 = Some(Token::Str(v.into())); - Ok(()) - } - - fn none(&mut self) -> Result<(), Error> { - self.0 = Some(Token::None); - Ok(()) - } - - #[cfg(feature = "kv_unstable_sval")] - fn sval(&mut self, _: &dyn internal::sval::Value) -> Result<(), Error> { - self.0 = Some(Token::Sval); - Ok(()) - } - } - - let mut visitor = TestVisitor(None); - self.visit(&mut visitor).unwrap(); - - visitor.0.unwrap() - } -} From 785f237dc46d788b6a17c2637e42ef5b323a6f2e Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Sun, 29 Nov 2020 11:22:45 +1000 Subject: [PATCH 019/280] add value support for std::error::Error --- Cargo.toml | 4 +-- src/kv/value.rs | 69 +++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 57 insertions(+), 16 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a90852bc0..ff72249f5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ exclude = ["rfcs/**/*", "/.travis.yml", "/appveyor.yml"] build = "build.rs" [package.metadata.docs.rs] -features = ["std", "serde", "kv_unstable_sval"] +features = ["std", "serde", "kv_unstable_std", "kv_unstable_sval"] [[test]] name = "filters" @@ -47,7 +47,7 @@ std = [] # this will have a tighter MSRV before stabilization kv_unstable = ["value-bag"] kv_unstable_sval = ["kv_unstable", "value-bag/sval", "sval"] -kv_unstable_std = ["std", "kv_unstable", "value-bag/std"] +kv_unstable_std = ["std", "kv_unstable", "value-bag/error"] [dependencies] cfg-if = "1.0" diff --git a/src/kv/value.rs b/src/kv/value.rs index c30787ff7..1e958249b 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -136,6 +136,17 @@ impl<'v> Value<'v> { } } + /// Get a value from an error. + #[cfg(feature = "kv_unstable_std")] + pub fn capture_error(err: &'v T) -> Self + where + T: std::error::Error + 'static, + { + Value { + inner: ValueBag::capture_error(err), + } + } + /// Get a value from a type implementing `sval::value::Value`. #[cfg(feature = "kv_unstable_sval")] pub fn capture_sval(value: &'v T) -> Self @@ -157,13 +168,6 @@ impl<'v> Value<'v> { } } - /// Get a value from a dynamic `std::fmt::Debug`. - pub fn from_dyn_debug(value: &'v dyn fmt::Debug) -> Self { - Value { - inner: ValueBag::from_dyn_debug(value), - } - } - /// Get a value from a type implementing `std::fmt::Display`. pub fn from_display(value: &'v T) -> Self where @@ -174,13 +178,6 @@ impl<'v> Value<'v> { } } - /// Get a value from a dynamic `std::fmt::Display`. - pub fn from_dyn_display(value: &'v dyn fmt::Display) -> Self { - Value { - inner: ValueBag::from_dyn_display(value), - } - } - /// Get a value from a type implementing `sval::value::Value`. #[cfg(feature = "kv_unstable_sval")] pub fn from_sval(value: &'v T) -> Self @@ -192,6 +189,28 @@ impl<'v> Value<'v> { } } + /// Get a value from a dynamic `std::fmt::Debug`. + pub fn from_dyn_debug(value: &'v dyn fmt::Debug) -> Self { + Value { + inner: ValueBag::from_dyn_debug(value), + } + } + + /// Get a value from a dynamic `std::fmt::Display`. + pub fn from_dyn_display(value: &'v dyn fmt::Display) -> Self { + Value { + inner: ValueBag::from_dyn_display(value), + } + } + + /// Get a value from a dynamic error. + #[cfg(feature = "kv_unstable_std")] + pub fn from_dyn_error(err: &'v (dyn std::error::Error + 'static)) -> Self { + Value { + inner: ValueBag::from_dyn_error(err), + } + } + /// Get a value from a type implementing `sval::value::Value`. #[cfg(feature = "kv_unstable_sval")] pub fn from_dyn_sval(value: &'v dyn self::sval::value::Value) -> Self { @@ -235,6 +254,13 @@ impl ToValue for dyn fmt::Display { } } +#[cfg(feature = "kv_unstable_std")] +impl ToValue for dyn std::error::Error + 'static { + fn to_value(&self) -> Value { + Value::from_dyn_error(self) + } +} + #[cfg(feature = "kv_unstable_sval")] impl<'v> self::sval::value::Value for Value<'v> { fn stream(&self, stream: &mut self::sval::value::Stream) -> self::sval::value::Result { @@ -344,6 +370,12 @@ impl_value_to_primitive![ ]; impl<'v> Value<'v> { + /// Try convert this value into an error. + #[cfg(feature = "kv_unstable_std")] + pub fn to_error(&self) -> Option<&(dyn std::error::Error + 'static)> { + self.inner.to_error() + } + /// Try convert this value into a borrowed string. pub fn to_borrowed_str(&self) -> Option<&str> { self.inner.to_borrowed_str() @@ -444,6 +476,15 @@ pub(crate) mod tests { assert!(Value::from_debug(&42).to_u64().is_none()); } + #[cfg(feature = "kv_unstable_std")] + #[test] + fn test_capture_error() { + let err = std::io::Error::from(std::io::ErrorKind::Other); + + assert!(Value::capture_error(&err).to_error().is_some()); + assert!(Value::from_dyn_error(&err).to_error().is_some()); + } + #[cfg(feature = "kv_unstable_sval")] #[test] fn test_capture_sval() { From c6be2456066cb32155e8668c2c92acc85ac26886 Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Sun, 29 Nov 2020 11:29:45 +1000 Subject: [PATCH 020/280] simplify ToValue impl for str --- src/kv/value.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/kv/value.rs b/src/kv/value.rs index 1e958249b..60f25c4d1 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -275,9 +275,9 @@ impl ToValue for dyn self::sval::value::Value { } } -impl<'v> ToValue for &'v str { +impl ToValue for str { fn to_value(&self) -> Value { - Value::from(*self) + Value::from(self) } } From 71d6ed34b2e281025a08d67f2031eab7b5500f7f Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Sun, 29 Nov 2020 18:46:59 +1000 Subject: [PATCH 021/280] add serde support to Value --- Cargo.toml | 3 ++- src/kv/value.rs | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index ff72249f5..299937c3e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,7 +16,7 @@ exclude = ["rfcs/**/*", "/.travis.yml", "/appveyor.yml"] build = "build.rs" [package.metadata.docs.rs] -features = ["std", "serde", "kv_unstable_std", "kv_unstable_sval"] +features = ["std", "serde", "kv_unstable_std", "kv_unstable_sval", "kv_unstable_serde"] [[test]] name = "filters" @@ -48,6 +48,7 @@ std = [] kv_unstable = ["value-bag"] kv_unstable_sval = ["kv_unstable", "value-bag/sval", "sval"] kv_unstable_std = ["std", "kv_unstable", "value-bag/error"] +kv_unstable_serde = ["kv_unstable_std", "value-bag/serde", "serde"] [dependencies] cfg-if = "1.0" diff --git a/src/kv/value.rs b/src/kv/value.rs index 60f25c4d1..561ea8641 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -7,6 +7,9 @@ extern crate value_bag; #[cfg(feature = "kv_unstable_sval")] extern crate sval; +#[cfg(feature = "kv_unstable_serde")] +extern crate serde; + use self::value_bag::ValueBag; pub use kv::Error; @@ -147,6 +150,17 @@ impl<'v> Value<'v> { } } + #[cfg(feature = "kv_unstable_serde")] + /// Get a value from a type implementing `serde::Serialize`. + pub fn capture_serde(value: &'v T) -> Self + where + T: self::serde::Serialize + 'static, + { + Value { + inner: ValueBag::capture_serde1(value), + } + } + /// Get a value from a type implementing `sval::value::Value`. #[cfg(feature = "kv_unstable_sval")] pub fn capture_sval(value: &'v T) -> Self @@ -178,6 +192,17 @@ impl<'v> Value<'v> { } } + /// Get a value from a type implementing `serde::Serialize`. + #[cfg(feature = "kv_unstable_serde")] + pub fn from_serde(value: &'v T) -> Self + where + T: self::serde::Serialize, + { + Value { + inner: ValueBag::from_serde1(value), + } + } + /// Get a value from a type implementing `sval::value::Value`. #[cfg(feature = "kv_unstable_sval")] pub fn from_sval(value: &'v T) -> Self @@ -261,6 +286,16 @@ impl ToValue for dyn std::error::Error + 'static { } } +#[cfg(feature = "kv_unstable_serde")] +impl<'v> self::serde::Serialize for Value<'v> { + fn serialize(&self, s: S) -> Result + where + S: self::serde::Serializer, + { + self.inner.serialize(s) + } +} + #[cfg(feature = "kv_unstable_sval")] impl<'v> self::sval::value::Value for Value<'v> { fn stream(&self, stream: &mut self::sval::value::Stream) -> self::sval::value::Result { @@ -485,6 +520,14 @@ pub(crate) mod tests { assert!(Value::from_dyn_error(&err).to_error().is_some()); } + #[cfg(feature = "kv_unstable_serde")] + #[test] + fn test_capture_serde() { + assert_eq!(Some(42u64), Value::capture_serde(&42).to_u64()); + + assert_eq!(Some(42u64), Value::from_serde(&42).to_u64()); + } + #[cfg(feature = "kv_unstable_sval")] #[test] fn test_capture_sval() { From e999195dc3c3c04da2d9da5462cc34bb060fea8c Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Mon, 21 Dec 2020 11:39:00 +1000 Subject: [PATCH 022/280] expose downcasting on Value --- src/kv/value.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/kv/value.rs b/src/kv/value.rs index 561ea8641..a2fdda63e 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -253,6 +253,16 @@ impl<'v> Value<'v> { inner: value.into(), } } + + /// Check whether this value can be downcast to `T`. + pub fn is(&self) -> bool { + self.inner.is::() + } + + /// Try downcast this value to `T`. + pub fn downcast_ref(&self) -> Option<&T> { + self.inner.downcast_ref::() + } } impl<'v> fmt::Debug for Value<'v> { @@ -656,4 +666,15 @@ pub(crate) mod tests { assert!(v.to_char().is_none()); } } + + #[test] + fn test_downcast_ref() { + #[derive(Debug)] + struct Foo(u64); + + let v = Value::capture_debug(&Foo(42)); + + assert!(v.is::()); + assert_eq!(42u64, v.downcast_ref::().expect("invalid downcast").0); + } } From 960ef828894be25c9d624f1821b362b481f517f1 Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Mon, 21 Dec 2020 15:00:06 +1000 Subject: [PATCH 023/280] add adapters for serializing Sources --- Cargo.toml | 2 + src/kv/key.rs | 33 +++++ src/kv/mod.rs | 2 +- src/kv/source.rs | 321 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 357 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 299937c3e..741ffbd22 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,5 +57,7 @@ sval = { version = "1.0.0-alpha.4", optional = true, default-features = false } value-bag = { version = "1.0.0-alpha.5", optional = true, default-features = false } [dev-dependencies] +serde = { version = "1.0", features = ["derive"] } serde_test = "1.0" +sval = { version = "1.0.0-alpha.4", features = ["derive"] } value-bag = { version = "1.0.0-alpha.5", features = ["test"] } diff --git a/src/kv/key.rs b/src/kv/key.rs index 86fd0668a..762e08dcb 100644 --- a/src/kv/key.rs +++ b/src/kv/key.rs @@ -128,6 +128,39 @@ mod std_support { } } +#[cfg(feature = "kv_unstable_sval")] +mod sval_support { + use super::*; + + extern crate sval; + + use self::sval::value::{self, Value}; + + impl<'a> Value for Key<'a> { + fn stream(&self, stream: &mut value::Stream) -> value::Result { + self.key.stream(stream) + } + } +} + +#[cfg(feature = "kv_unstable_serde")] +mod serde_support { + use super::*; + + extern crate serde; + + use self::serde::{Serialize, Serializer}; + + impl<'a> Serialize for Key<'a> { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + self.key.serialize(serializer) + } + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/src/kv/mod.rs b/src/kv/mod.rs index fa697c2bb..5dc69337c 100644 --- a/src/kv/mod.rs +++ b/src/kv/mod.rs @@ -14,7 +14,7 @@ mod error; mod key; -mod source; +pub mod source; pub mod value; diff --git a/src/kv/source.rs b/src/kv/source.rs index cb5efc066..8762c621e 100644 --- a/src/kv/source.rs +++ b/src/kv/source.rs @@ -1,5 +1,11 @@ //! Sources for key-value pairs. +#[cfg(feature = "kv_unstable_sval")] +extern crate sval; + +#[cfg(feature = "kv_unstable_serde")] +extern crate serde; + use kv::{Error, Key, ToKey, ToValue, Value}; use std::fmt; @@ -372,6 +378,309 @@ mod std_support { } } +/// The result of calling `Source::as_map`. +pub struct AsMap(S); + +/// Visit this source as a map. +pub fn as_map(source: S) -> AsMap +where + S: Source, +{ + AsMap(source) +} + +impl Source for AsMap +where + S: Source, +{ + fn visit<'kvs>(&'kvs self, visitor: &mut dyn Visitor<'kvs>) -> Result<(), Error> { + self.0.visit(visitor) + } + + fn get<'v>(&'v self, key: Key) -> Option> { + self.0.get(key) + } + + fn count(&self) -> usize { + self.0.count() + } +} + +impl fmt::Debug for AsMap +where + S: Source, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut f = f.debug_map(); + self.0.visit(&mut f).map_err(|_| fmt::Error)?; + f.finish() + } +} + +/// The result of calling `Source::as_list` +pub struct AsList(S); + +/// Visit this source as a list. +pub fn as_list(source: S) -> AsList +where + S: Source, +{ + AsList(source) +} + +impl Source for AsList +where + S: Source, +{ + fn visit<'kvs>(&'kvs self, visitor: &mut dyn Visitor<'kvs>) -> Result<(), Error> { + self.0.visit(visitor) + } + + fn get<'v>(&'v self, key: Key) -> Option> { + self.0.get(key) + } + + fn count(&self) -> usize { + self.0.count() + } +} + +impl fmt::Debug for AsList +where + S: Source, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + let mut f = f.debug_list(); + self.0.visit(&mut f).map_err(|_| fmt::Error)?; + f.finish() + } +} + +#[cfg(feature = "kv_unstable_sval")] +mod sval_support { + use super::*; + + use self::sval::value; + + impl value::Value for AsMap + where + S: Source, + { + fn stream(&self, stream: &mut value::Stream) -> value::Result { + struct StreamVisitor<'a, 'b>(&'a mut value::Stream<'b>); + + impl<'a, 'b, 'kvs> Visitor<'kvs> for StreamVisitor<'a, 'b> { + fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> { + self.0 + .map_key(key) + .map_err(|_| Error::msg("failed to stream map key"))?; + self.0 + .map_value(value) + .map_err(|_| Error::msg("failed to stream map value"))?; + Ok(()) + } + } + + stream + .map_begin(Some(self.count())) + .map_err(|_| self::sval::Error::msg("failed to begin map"))?; + + self.visit(&mut StreamVisitor(stream)) + .map_err(|_| self::sval::Error::msg("failed to visit key-values"))?; + + stream + .map_end() + .map_err(|_| self::sval::Error::msg("failed to end map")) + } + } + + impl value::Value for AsList + where + S: Source, + { + fn stream(&self, stream: &mut value::Stream) -> value::Result { + struct StreamVisitor<'a, 'b>(&'a mut value::Stream<'b>); + + impl<'a, 'b, 'kvs> Visitor<'kvs> for StreamVisitor<'a, 'b> { + fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> { + self.0 + .seq_elem((key, value)) + .map_err(|_| Error::msg("failed to stream seq entry"))?; + Ok(()) + } + } + + stream + .seq_begin(Some(self.count())) + .map_err(|_| self::sval::Error::msg("failed to begin seq"))?; + + self.visit(&mut StreamVisitor(stream)) + .map_err(|_| self::sval::Error::msg("failed to visit key-values"))?; + + stream + .seq_end() + .map_err(|_| self::sval::Error::msg("failed to end seq")) + } + } + + #[cfg(test)] + mod tests { + use super::*; + + use self::sval::Value; + + use crate::kv::source; + + #[test] + fn derive_stream() { + #[derive(Value)] + pub struct MyRecordAsMap<'a> { + msg: &'a str, + kvs: source::AsMap<&'a dyn Source>, + } + + #[derive(Value)] + pub struct MyRecordAsList<'a> { + msg: &'a str, + kvs: source::AsList<&'a dyn Source>, + } + } + } +} + +#[cfg(feature = "kv_unstable_serde")] +pub mod as_map { + //! `serde` adapters for serializing a `Source` as a map. + + use super::*; + + use self::serde::{Serialize, Serializer}; + + /// Serialize a `Source` as a map. + pub fn serialize(source: &T, serializer: S) -> Result + where + T: Source, + S: Serializer, + { + as_map(source).serialize(serializer) + } +} + +#[cfg(feature = "kv_unstable_serde")] +pub mod as_list { + //! `serde` adapters for serializing a `Source` as a list. + + use super::*; + + use self::serde::{Serialize, Serializer}; + + /// Serialize a `Source` as a list. + pub fn serialize(source: &T, serializer: S) -> Result + where + T: Source, + S: Serializer, + { + as_list(source).serialize(serializer) + } +} + +#[cfg(feature = "kv_unstable_serde")] +mod serde_support { + use super::*; + + use self::serde::ser::{Error as SerError, Serialize, SerializeMap, SerializeSeq, Serializer}; + + impl Serialize for AsMap + where + T: Source, + { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + struct SerializerVisitor<'a, S>(&'a mut S); + + impl<'a, 'kvs, S> Visitor<'kvs> for SerializerVisitor<'a, S> + where + S: SerializeMap, + { + fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> { + self.0 + .serialize_entry(&key, &value) + .map_err(|_| Error::msg("failed to serialize map entry"))?; + Ok(()) + } + } + + let mut map = serializer.serialize_map(Some(self.count()))?; + + self.visit(&mut SerializerVisitor(&mut map)) + .map_err(|_| S::Error::custom("failed to visit key-values"))?; + + map.end() + } + } + + impl Serialize for AsList + where + T: Source, + { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + struct SerializerVisitor<'a, S>(&'a mut S); + + impl<'a, 'kvs, S> Visitor<'kvs> for SerializerVisitor<'a, S> + where + S: SerializeSeq, + { + fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> { + self.0 + .serialize_element(&(key, value)) + .map_err(|_| Error::msg("failed to serialize seq entry"))?; + Ok(()) + } + } + + let mut seq = serializer.serialize_seq(Some(self.count()))?; + + self.visit(&mut SerializerVisitor(&mut seq)) + .map_err(|_| S::Error::custom("failed to visit seq"))?; + + seq.end() + } + } + + #[cfg(test)] + mod tests { + use super::*; + + use self::serde::Serialize; + + use crate::kv::source; + + #[test] + fn derive_serialize() { + #[derive(Serialize)] + pub struct MyRecordAsMap<'a> { + msg: &'a str, + #[serde(flatten)] + #[serde(with = "source::as_map")] + kvs: &'a dyn Source, + } + + #[derive(Serialize)] + pub struct MyRecordAsList<'a> { + msg: &'a str, + #[serde(flatten)] + #[serde(with = "source::as_list")] + kvs: &'a dyn Source, + } + } + } +} + #[cfg(test)] mod tests { use super::*; @@ -430,4 +739,16 @@ mod tests { let source = Option::None::<(&str, i32)>; assert!(Source::get(&source, Key::from_str("a")).is_none()); } + + #[test] + fn as_map() { + let _ = crate::kv::source::as_map(("a", 1)); + let _ = crate::kv::source::as_map(&("a", 1) as &dyn Source); + } + + #[test] + fn as_list() { + let _ = crate::kv::source::as_list(("a", 1)); + let _ = crate::kv::source::as_list(&("a", 1) as &dyn Source); + } } From 0e78c11b40eaa895f0a0c0af71fb0d79219d9185 Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Mon, 21 Dec 2020 16:44:59 +1000 Subject: [PATCH 024/280] Run tests in our MSRV (#427) --- .github/workflows/main.yml | 1 + tests/Cargo.toml | 11 +++++++++++ tests/filters.rs | 2 ++ tests/macros.rs | 1 + tests/src/build.rs | 5 +++++ tests/src/lib.rs | 18 ++++++++++++++++++ 6 files changed, 38 insertions(+) create mode 100644 tests/Cargo.toml create mode 100644 tests/src/build.rs create mode 100644 tests/src/lib.rs diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5810a23e8..cee48555e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -69,6 +69,7 @@ jobs: - run: cargo build --verbose - run: cargo build --verbose --features serde - run: cargo build --verbose --features std + - run: cargo test --verbose --manifest-path tests/Cargo.toml embedded: name: Embedded diff --git a/tests/Cargo.toml b/tests/Cargo.toml new file mode 100644 index 000000000..cb6b8600f --- /dev/null +++ b/tests/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "integration" +version = "0.1.0" +publish = false +build = "src/build.rs" + +[features] +std = ["log/std"] + +[dependencies.log] +path = ".." diff --git a/tests/filters.rs b/tests/filters.rs index 3c261c469..de6bd189f 100644 --- a/tests/filters.rs +++ b/tests/filters.rs @@ -1,3 +1,4 @@ +#[cfg(not(lib_build))] #[macro_use] extern crate log; @@ -29,6 +30,7 @@ impl Log for Logger { fn flush(&self) {} } +#[cfg_attr(lib_build, test)] fn main() { let me = Arc::new(State { last_log: Mutex::new(None), diff --git a/tests/macros.rs b/tests/macros.rs index da397c3a5..4daab32f9 100644 --- a/tests/macros.rs +++ b/tests/macros.rs @@ -1,3 +1,4 @@ +#[cfg(not(lib_build))] #[macro_use] extern crate log; diff --git a/tests/src/build.rs b/tests/src/build.rs new file mode 100644 index 000000000..b10fea125 --- /dev/null +++ b/tests/src/build.rs @@ -0,0 +1,5 @@ +fn main() { + println!("cargo:rustc-cfg=lib_build"); + + println!("cargo:rerun-if-changed=src/build.rs"); +} diff --git a/tests/src/lib.rs b/tests/src/lib.rs new file mode 100644 index 000000000..34770568c --- /dev/null +++ b/tests/src/lib.rs @@ -0,0 +1,18 @@ +//! This crate is intentionally left empty. +//! +//! We have an empty library depending on `log` here so we can run integration tests +//! on older compilers without depending on the unstable `no-dev-deps` flag. + +#![allow(dead_code)] + +#[cfg(test)] +#[macro_use] +extern crate log; + +#[cfg(test)] +#[path = "../filters.rs"] +mod filters; + +#[cfg(test)] +#[path = "../macros.rs"] +mod macros; From 4c66a1cefebd44ec2487f2533f658c7244c9357a Mon Sep 17 00:00:00 2001 From: KodrAus Date: Thu, 24 Dec 2020 09:07:48 +1000 Subject: [PATCH 025/280] prepare for 0.4.12 release --- CHANGELOG.md | 18 +++++++++++++++++- Cargo.toml | 2 +- src/lib.rs | 2 +- 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6fa8be0c5..71478da36 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,21 @@ ## [Unreleased] +## [0.4.12] - 2020-12-24 + +### New + +* Support platforms without atomics by racing instead of failing to compile +* Implement `Log` for `Box` +* Update `cfg-if` to `1.0` +* Internal reworks of the structured logging API. Removed the `Fill` API +and added `source::as_map` and `source::as_list` to easily serialize a `Source` +as either a map of `{key: value, ..}` or as a list of `[(key, value), ..]`. + +### Fixed + +* Fixed deserialization of `LevelFilter` to use their `u64` index variants + ## [0.4.11] - 2020-07-09 ### New @@ -170,7 +185,8 @@ version using log 0.4.x to avoid losing module and file information. Look at the [release tags] for information about older releases. -[Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.11...HEAD +[Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.12...HEAD +[0.4.12]: https://github.com/rust-lang-nursery/log/compare/0.4.11...0.4.12 [0.4.11]: https://github.com/rust-lang-nursery/log/compare/0.4.10...0.4.11 [0.4.10]: https://github.com/rust-lang-nursery/log/compare/0.4.9...0.4.10 [0.4.9]: https://github.com/rust-lang-nursery/log/compare/0.4.8...0.4.9 diff --git a/Cargo.toml b/Cargo.toml index 741ffbd22..a82766344 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "log" -version = "0.4.11" # remember to update html_root_url +version = "0.4.12" # remember to update html_root_url authors = ["The Rust Project Developers"] license = "MIT OR Apache-2.0" readme = "README.md" diff --git a/src/lib.rs b/src/lib.rs index 2edcdf31c..4600979c9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -266,7 +266,7 @@ #![doc( html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://www.rust-lang.org/favicon.ico", - html_root_url = "https://docs.rs/log/0.4.11" + html_root_url = "https://docs.rs/log/0.4.12" )] #![warn(missing_docs)] #![deny(missing_debug_implementations)] From 44310aad68b053afbc2ba9e46fff04e18f54ed06 Mon Sep 17 00:00:00 2001 From: DevJac Date: Fri, 30 Oct 2020 15:52:42 -0600 Subject: [PATCH 026/280] Clarify ordering of log levels in the docs It was not clear whether `error` or `trace` was the maximum log level. The docs said "`error!` represents the _highest_-priority log messages and `trace!` the _lowest_". Yet, `set_max_level` regards `Trace` to be the maximum level. I attempted to clarify this by avoiding the terms "high" and "low" in the docs except for where they are applicable to the Rust order as defined in `Ord`. --- src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 2edcdf31c..a25c92bac 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1228,6 +1228,8 @@ where /// Sets the global maximum log level. /// /// Generally, this should only be called by the active logging implementation. +/// +/// Note that `Trace` is the maximum level, because it provides the maximum amount of detail in the emitted logs. #[inline] pub fn set_max_level(level: LevelFilter) { MAX_LOG_LEVEL_FILTER.store(level as usize, Ordering::SeqCst) From b1dd94a5f723d4beec15c069803420f51e342298 Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Fri, 8 Jan 2021 10:42:59 +1000 Subject: [PATCH 027/280] add path for filters and macros tests --- Cargo.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index a82766344..5ee00c5d4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,10 +20,12 @@ features = ["std", "serde", "kv_unstable_std", "kv_unstable_sval", "kv_unstable_ [[test]] name = "filters" +path = "tests/filters.rs" harness = false [[test]] name = "macros" +path = "tests/macros.rs" harness = true [features] From 0e005babc0d6107c30584d7e11590808235243ec Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Fri, 8 Jan 2021 14:01:53 +1000 Subject: [PATCH 028/280] check std feature against kv_unstable Check a few more permutations of `kv_unstable` features --- .github/workflows/main.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index cee48555e..965331ee3 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -42,6 +42,8 @@ jobs: - run: cargo test --verbose --features kv_unstable - run: cargo test --verbose --features "kv_unstable std" - run: cargo test --verbose --features "kv_unstable_sval" + - run: cargo test --verbose --features "kv_unstable_sval std" + - run: cargo test --verbose --features "kv_unstable kv_unstable_std kv_unstable_sval kv_unstable_serde" - run: cargo run --verbose --manifest-path test_max_level_features/Cargo.toml - run: cargo run --verbose --manifest-path test_max_level_features/Cargo.toml --release From b6491597eddf8e4f43bf4cc2af7275f8b26294f2 Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Fri, 8 Jan 2021 14:13:48 +1000 Subject: [PATCH 029/280] add a feature check stage --- .github/workflows/main.yml | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 965331ee3..d90d48baa 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -40,9 +40,8 @@ jobs: - run: cargo test --verbose --features serde - run: cargo test --verbose --features std - run: cargo test --verbose --features kv_unstable - - run: cargo test --verbose --features "kv_unstable std" - - run: cargo test --verbose --features "kv_unstable_sval" - - run: cargo test --verbose --features "kv_unstable_sval std" + - run: cargo test --verbose --features kv_unstable_sval + - run: cargo test --verbose --features kv_unstable_serde - run: cargo test --verbose --features "kv_unstable kv_unstable_std kv_unstable_sval kv_unstable_serde" - run: cargo run --verbose --manifest-path test_max_level_features/Cargo.toml - run: cargo run --verbose --manifest-path test_max_level_features/Cargo.toml --release @@ -59,6 +58,22 @@ jobs: rustup component add rustfmt - run: cargo fmt -- --check + features: + name: Feature check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Install Rust + run: | + rustup update nightly --no-self-update + rustup default nightly + - run: cargo build --verbose -Z avoid-dev-deps --features kv_unstable + - run: cargo build --verbose -Z avoid-dev-deps --features "kv_unstable std" + - run: cargo build --verbose -Z avoid-dev-deps --features "kv_unstable kv_unstable_sval" + - run: cargo build --verbose -Z avoid-dev-deps --features "kv_unstable kv_unstable_serde" + - run: cargo build --verbose -Z avoid-dev-deps --features "kv_unstable kv_unstable_std" + - run: cargo build --verbose -Z avoid-dev-deps --features "kv_unstable kv_unstable_sval kv_unstable_serde" + msrv: name: MSRV runs-on: ubuntu-latest From cc3d6edb5d96ef3da63f6096194d30f2ef358044 Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Fri, 8 Jan 2021 14:18:01 +1000 Subject: [PATCH 030/280] use kv_unstable_std instead of std --- src/kv/value.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/kv/value.rs b/src/kv/value.rs index a2fdda63e..bb79d9103 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -427,7 +427,7 @@ impl<'v> Value<'v> { } } -#[cfg(feature = "std")] +#[cfg(feature = "kv_unstable_std")] mod std_support { use super::*; @@ -615,7 +615,7 @@ pub(crate) mod tests { for v in str() { assert!(v.to_borrowed_str().is_some()); - #[cfg(feature = "std")] + #[cfg(feature = "kv_unstable_std")] assert!(v.to_str().is_some()); } @@ -624,13 +624,13 @@ pub(crate) mod tests { assert!(v.to_borrowed_str().is_some()); - #[cfg(feature = "std")] + #[cfg(feature = "kv_unstable_std")] assert!(v.to_str().is_some()); for v in unsigned().chain(signed()).chain(float()).chain(bool()) { assert!(v.to_borrowed_str().is_none()); - #[cfg(feature = "std")] + #[cfg(feature = "kv_unstable_std")] assert!(v.to_str().is_none()); } } From eff148e459a034959c61d8c15f254451aae3eb51 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Fri, 8 Jan 2021 14:24:25 +1000 Subject: [PATCH 031/280] prepare for 0.4.13 release --- CHANGELOG.md | 9 ++++++++- Cargo.toml | 2 +- src/lib.rs | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 71478da36..6fa94c5ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ ## [Unreleased] +## [0.4.13] - 2020-01-08 + +### Fixed + +* Fixed incorrect combination of `kv_unstable` and `std` features causing compile failures + ## [0.4.12] - 2020-12-24 ### New @@ -185,7 +191,8 @@ version using log 0.4.x to avoid losing module and file information. Look at the [release tags] for information about older releases. -[Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.12...HEAD +[Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.13...HEAD +[0.4.13]: https://github.com/rust-lang-nursery/log/compare/0.4.12...0.4.13 [0.4.12]: https://github.com/rust-lang-nursery/log/compare/0.4.11...0.4.12 [0.4.11]: https://github.com/rust-lang-nursery/log/compare/0.4.10...0.4.11 [0.4.10]: https://github.com/rust-lang-nursery/log/compare/0.4.9...0.4.10 diff --git a/Cargo.toml b/Cargo.toml index 5ee00c5d4..9892a90b3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "log" -version = "0.4.12" # remember to update html_root_url +version = "0.4.13" # remember to update html_root_url authors = ["The Rust Project Developers"] license = "MIT OR Apache-2.0" readme = "README.md" diff --git a/src/lib.rs b/src/lib.rs index 4600979c9..247424517 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -266,7 +266,7 @@ #![doc( html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://www.rust-lang.org/favicon.ico", - html_root_url = "https://docs.rs/log/0.4.12" + html_root_url = "https://docs.rs/log/0.4.13" )] #![warn(missing_docs)] #![deny(missing_debug_implementations)] From 16ecfbeeb44c200f39b379f281d54ae6c0801746 Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Fri, 8 Jan 2021 13:17:45 +0100 Subject: [PATCH 032/280] Remove usage of AtomicUsize::compare_exchange It is going to be deprecated in 1.50, but it's already producing warnings on nightly. --- src/lib.rs | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 247424517..c8cb071ac 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -324,12 +324,18 @@ impl AtomicUsize { } #[cfg(atomic_cas)] - fn compare_and_swap(&self, current: usize, new: usize, _order: Ordering) -> usize { + fn compare_exchange( + &self, + current: usize, + new: usize, + _success: Ordering, + _failure: Ordering, + ) -> Result { let prev = self.v.get(); if current == prev { self.v.set(new); } - prev + Ok(prev) } } @@ -1338,7 +1344,15 @@ fn set_logger_inner(make_logger: F) -> Result<(), SetLoggerError> where F: FnOnce() -> &'static dyn Log, { - match STATE.compare_and_swap(UNINITIALIZED, INITIALIZING, Ordering::SeqCst) { + let old_state = match STATE.compare_exchange( + UNINITIALIZED, + INITIALIZING, + Ordering::SeqCst, + Ordering::SeqCst, + ) { + Ok(s) | Err(s) => s, + }; + match old_state { UNINITIALIZED => { unsafe { LOGGER = make_logger(); From 71895e0e1e3f9f8d315cc9146ea6ab34a12949f7 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Mon, 11 Jan 2021 20:13:06 +1000 Subject: [PATCH 033/280] update changelog to reflect 0.4.13 patch --- CHANGELOG.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6fa94c5ed..1ae99ae58 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,11 +2,11 @@ ## [Unreleased] -## [0.4.13] - 2020-01-08 +* Fixed incorrect combination of `kv_unstable` and `std` features causing compile failures -### Fixed +## [0.4.13] - 2021-01-11 -* Fixed incorrect combination of `kv_unstable` and `std` features causing compile failures +* This is the same as `0.4.11`, except with a `kv_unstable_std` feature added to aid migrating current dependents to `0.4.14` (which was originally going to be `0.4.13` until it was decided to create a patch from `0.4.11` to minimize disruption). ## [0.4.12] - 2020-12-24 @@ -191,8 +191,8 @@ version using log 0.4.x to avoid losing module and file information. Look at the [release tags] for information about older releases. -[Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.13...HEAD -[0.4.13]: https://github.com/rust-lang-nursery/log/compare/0.4.12...0.4.13 +[Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.12...HEAD +[0.4.13]: https://github.com/rust-lang-nursery/log/compare/0.4.11...0.4.13 [0.4.12]: https://github.com/rust-lang-nursery/log/compare/0.4.11...0.4.12 [0.4.11]: https://github.com/rust-lang-nursery/log/compare/0.4.10...0.4.11 [0.4.10]: https://github.com/rust-lang-nursery/log/compare/0.4.9...0.4.10 From 2d1a477f5a711d7aa1bbf0ca0c2a01b02a236763 Mon Sep 17 00:00:00 2001 From: hyd-dev Date: Sat, 23 Jan 2021 23:57:36 +0800 Subject: [PATCH 034/280] Remove the `__private_api_log_lit` special case It existed because of code size reasons, but it's incompatible with `format_args_capture`. --- src/lib.rs | 19 ------------------- src/macros.rs | 12 ------------ 2 files changed, 31 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index c8cb071ac..a59ce086a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1469,25 +1469,6 @@ pub fn __private_api_log( ); } -// WARNING: this is not part of the crate's public API and is subject to change at any time -#[doc(hidden)] -pub fn __private_api_log_lit( - message: &str, - level: Level, - &(target, module_path, file, line): &(&str, &'static str, &'static str, u32), -) { - logger().log( - &Record::builder() - .args(format_args!("{}", message)) - .level(level) - .target(target) - .module_path_static(Some(module_path)) - .file_static(Some(file)) - .line(Some(line)) - .build(), - ); -} - // WARNING: this is not part of the crate's public API and is subject to change at any time #[doc(hidden)] pub fn __private_api_enabled(level: Level, target: &str) -> bool { diff --git a/src/macros.rs b/src/macros.rs index 7b87501f4..aed6fdeff 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -29,18 +29,6 @@ /// ``` #[macro_export(local_inner_macros)] macro_rules! log { - (target: $target:expr, $lvl:expr, $message:expr) => ({ - let lvl = $lvl; - if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { - // ensure that $message is a valid format string literal - let _ = __log_format_args!($message); - $crate::__private_api_log_lit( - $message, - lvl, - &($target, __log_module_path!(), __log_file!(), __log_line!()), - ); - } - }); (target: $target:expr, $lvl:expr, $($arg:tt)+) => ({ let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { From 9d4206770dd93f07cb27c3e1f41dc21c45031302 Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Wed, 27 Jan 2021 13:07:13 +1000 Subject: [PATCH 035/280] Prepare for.0.4.14 release (#447) * prepare for.0.4.14 release * update based on value-bag API * rename to_error to to_borrowed_error * note method name change in changelog * update to released value-bag --- CHANGELOG.md | 10 +++++-- Cargo.toml | 10 +++---- src/kv/value.rs | 69 ++++++++++++++++--------------------------------- src/lib.rs | 2 +- 4 files changed, 36 insertions(+), 55 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ae99ae58..4b57360e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,12 @@ ## [Unreleased] -* Fixed incorrect combination of `kv_unstable` and `std` features causing compile failures +## [0.4.14] - 2021-01-27 + +* Remove the `__private_api_log_lit` special case. +* Fixed incorrect combination of `kv_unstable` and `std` features causing compile failures. +* Remove unstable `Value::to_*` conversions that were incorrectly using `as`. +* Rename unstable `Value::to_error` to `Value::to_borrowed_error`. ## [0.4.13] - 2021-01-11 @@ -191,7 +196,8 @@ version using log 0.4.x to avoid losing module and file information. Look at the [release tags] for information about older releases. -[Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.12...HEAD +[Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.14...HEAD +[0.4.14]: https://github.com/rust-lang-nursery/log/compare/0.4.13...0.4.14 [0.4.13]: https://github.com/rust-lang-nursery/log/compare/0.4.11...0.4.13 [0.4.12]: https://github.com/rust-lang-nursery/log/compare/0.4.11...0.4.12 [0.4.11]: https://github.com/rust-lang-nursery/log/compare/0.4.10...0.4.11 diff --git a/Cargo.toml b/Cargo.toml index 9892a90b3..a86c99ce7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "log" -version = "0.4.13" # remember to update html_root_url +version = "0.4.14" # remember to update html_root_url authors = ["The Rust Project Developers"] license = "MIT OR Apache-2.0" readme = "README.md" @@ -55,11 +55,11 @@ kv_unstable_serde = ["kv_unstable_std", "value-bag/serde", "serde"] [dependencies] cfg-if = "1.0" serde = { version = "1.0", optional = true, default-features = false } -sval = { version = "1.0.0-alpha.4", optional = true, default-features = false } -value-bag = { version = "1.0.0-alpha.5", optional = true, default-features = false } +sval = { version = "1.0.0-alpha.5", optional = true, default-features = false } +value-bag = { version = "1.0.0-alpha.6", optional = true, default-features = false } [dev-dependencies] serde = { version = "1.0", features = ["derive"] } serde_test = "1.0" -sval = { version = "1.0.0-alpha.4", features = ["derive"] } -value-bag = { version = "1.0.0-alpha.5", features = ["test"] } +sval = { version = "1.0.0-alpha.5", features = ["derive"] } +value-bag = { version = "1.0.0-alpha.6", features = ["test"] } diff --git a/src/kv/value.rs b/src/kv/value.rs index bb79d9103..7dd108090 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -58,7 +58,7 @@ impl<'v> ToValue for Value<'v> { /// /// let value = Value::capture_debug(&42i32); /// -/// assert_eq!(Some(42), value.to_i32()); +/// assert_eq!(Some(42), value.to_i64()); /// ``` /// /// ## Using the `Value::from_*` methods @@ -71,7 +71,7 @@ impl<'v> ToValue for Value<'v> { /// /// let value = Value::from_debug(&42i32); /// -/// assert_eq!(None, value.to_i32()); +/// assert_eq!(None, value.to_i64()); /// ``` /// /// ## Using the `ToValue` trait @@ -83,7 +83,7 @@ impl<'v> ToValue for Value<'v> { /// # use log::kv::ToValue; /// let value = 42i32.to_value(); /// -/// assert_eq!(Some(42), value.to_i32()); +/// assert_eq!(Some(42), value.to_i64()); /// ``` /// /// ``` @@ -92,7 +92,7 @@ impl<'v> ToValue for Value<'v> { /// /// let value = (&42i32 as &dyn Debug).to_value(); /// -/// assert_eq!(None, value.to_i32()); +/// assert_eq!(None, value.to_i64()); /// ``` /// /// ## Using the standard `From` trait @@ -104,7 +104,7 @@ impl<'v> ToValue for Value<'v> { /// /// let value = Value::from(42i32); /// -/// assert_eq!(Some(42), value.to_i32()); +/// assert_eq!(Some(42), value.to_i64()); /// ``` pub struct Value<'v> { inner: ValueBag<'v>, @@ -381,31 +381,19 @@ macro_rules! impl_value_to_primitive { } } -impl_to_value_primitive![usize, u8, u16, u32, u64, isize, i8, i16, i32, i64, f32, f64, char, bool,]; +impl_to_value_primitive![ + usize, u8, u16, u32, u64, u128, isize, i8, i16, i32, i64, i128, f32, f64, char, bool, +]; impl_value_to_primitive![ - #[doc = "Try convert this value into a `usize`."] - to_usize -> usize, - #[doc = "Try convert this value into a `u8`."] - to_u8 -> u8, - #[doc = "Try convert this value into a `u16`."] - to_u16 -> u16, - #[doc = "Try convert this value into a `u32`."] - to_u32 -> u32, #[doc = "Try convert this value into a `u64`."] to_u64 -> u64, - #[doc = "Try convert this value into a `isize`."] - to_isize -> isize, - #[doc = "Try convert this value into a `i8`."] - to_i8 -> i8, - #[doc = "Try convert this value into a `i16`."] - to_i16 -> i16, - #[doc = "Try convert this value into a `i32`."] - to_i32 -> i32, #[doc = "Try convert this value into a `i64`."] to_i64 -> i64, - #[doc = "Try convert this value into a `f32`."] - to_f32 -> f32, + #[doc = "Try convert this value into a `u128`."] + to_u128 -> u128, + #[doc = "Try convert this value into a `i128`."] + to_i128 -> i128, #[doc = "Try convert this value into a `f64`."] to_f64 -> f64, #[doc = "Try convert this value into a `char`."] @@ -417,8 +405,8 @@ impl_value_to_primitive![ impl<'v> Value<'v> { /// Try convert this value into an error. #[cfg(feature = "kv_unstable_std")] - pub fn to_error(&self) -> Option<&(dyn std::error::Error + 'static)> { - self.inner.to_error() + pub fn to_borrowed_error(&self) -> Option<&(dyn std::error::Error + 'static)> { + self.inner.to_borrowed_error() } /// Try convert this value into a borrowed string. @@ -526,8 +514,8 @@ pub(crate) mod tests { fn test_capture_error() { let err = std::io::Error::from(std::io::ErrorKind::Other); - assert!(Value::capture_error(&err).to_error().is_some()); - assert!(Value::from_dyn_error(&err).to_error().is_some()); + assert!(Value::capture_error(&err).to_borrowed_error().is_some()); + assert!(Value::from_dyn_error(&err).to_borrowed_error().is_some()); } #[cfg(feature = "kv_unstable_serde")] @@ -577,35 +565,22 @@ pub(crate) mod tests { #[test] fn test_to_number() { - for v in unsigned().chain(signed()).chain(float()) { - assert!(v.to_u8().is_some()); - assert!(v.to_u16().is_some()); - assert!(v.to_u32().is_some()); + for v in unsigned() { assert!(v.to_u64().is_some()); - assert!(v.to_usize().is_some()); + assert!(v.to_i64().is_some()); + } - assert!(v.to_i8().is_some()); - assert!(v.to_i16().is_some()); - assert!(v.to_i32().is_some()); + for v in signed() { assert!(v.to_i64().is_some()); - assert!(v.to_isize().is_some()); + } - assert!(v.to_f32().is_some()); + for v in unsigned().chain(signed()).chain(float()) { assert!(v.to_f64().is_some()); } for v in bool().chain(str()).chain(char()) { - assert!(v.to_u8().is_none()); - assert!(v.to_u16().is_none()); - assert!(v.to_u32().is_none()); assert!(v.to_u64().is_none()); - - assert!(v.to_i8().is_none()); - assert!(v.to_i16().is_none()); - assert!(v.to_i32().is_none()); assert!(v.to_i64().is_none()); - - assert!(v.to_f32().is_none()); assert!(v.to_f64().is_none()); } } diff --git a/src/lib.rs b/src/lib.rs index a59ce086a..bbfb1ed31 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -266,7 +266,7 @@ #![doc( html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://www.rust-lang.org/favicon.ico", - html_root_url = "https://docs.rs/log/0.4.13" + html_root_url = "https://docs.rs/log/0.4.14" )] #![warn(missing_docs)] #![deny(missing_debug_implementations)] From 85a3ef6783eb1ba35514c023ca717f1ddef3b0bf Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Thu, 25 Mar 2021 10:18:02 +0100 Subject: [PATCH 036/280] Allow use of deprecated atomic::spin_loop_hint It's replaced by hint::spin_loop, however that has only been stable since 1.49.0. Since we still support 1.31.0 we can't use it. Once the MSRV is updated to 1.49 we can use hint::spin_loop. --- src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index bbfb1ed31..fd680de75 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1362,6 +1362,8 @@ where } INITIALIZING => { while STATE.load(Ordering::SeqCst) == INITIALIZING { + // TODO: replace with `hint::spin_loop` once MSRV is 1.49.0. + #[allow(deprecated)] std::sync::atomic::spin_loop_hint(); } Err(SetLoggerError(())) From 92fd47bf9dee2f190ed7b16fc415ba0c90cbd1f6 Mon Sep 17 00:00:00 2001 From: lunaryorn Date: Sat, 29 May 2021 13:02:33 +0200 Subject: [PATCH 037/280] Add systemd journal logger to readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d320b9c2f..340b62c9c 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,7 @@ There are many available implementations to choose from, here are some of the mo * [`fern`](https://docs.rs/fern/*/fern/) * Adaptors for other facilities: * [`syslog`](https://docs.rs/syslog/*/syslog/) + * [`systemd-journal-logger`](https://docs.rs/systemd-journal-logger/*/systemd_journal_logger/) * [`slog-stdlog`](https://docs.rs/slog-stdlog/*/slog_stdlog/) * [`android_log`](https://docs.rs/android_log/*/android_log/) * [`win_dbg_logger`](https://docs.rs/win_dbg_logger/*/win_dbg_logger/) From a1f1748bfb79a57267fe0209320a7901f1ea97f1 Mon Sep 17 00:00:00 2001 From: Delma Date: Fri, 27 Aug 2021 14:32:49 +0300 Subject: [PATCH 038/280] Make log level names array public --- src/lib.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index bbfb1ed31..edf001c40 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -359,7 +359,12 @@ const INITIALIZED: usize = 2; static MAX_LOG_LEVEL_FILTER: AtomicUsize = AtomicUsize::new(0); -static LOG_LEVEL_NAMES: [&str; 6] = ["OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE"]; +/// Array of supported filter levels for a logger. +/// +/// Values correspond to the variants of the [`LevelFilter`](enum.LevelFilter.html) enum. +/// +/// Can be used, for example, in help text shown to a user of an application. +pub static LOG_LEVEL_NAMES: [&str; 6] = ["OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE"]; static SET_LOGGER_ERROR: &str = "attempted to set a logger after the logging system \ was already initialized"; From e49f063235752784b0476e74559d142cd7786ca8 Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Sun, 29 Aug 2021 14:01:02 +0200 Subject: [PATCH 039/280] Add key-values to the macros Attempt number two/three? Too many in any case. Previously I proposed a design that followed a `struct` like syntax: ```rust info!("my message: {}", arg, { key1: "value1", key2: 123, }); ``` However it turns out that this does not work well with named arguments as reported in issues #369 and #372. The implementation was eventually reverted in pr #374. This new design takes inspiration from the `tracing` crate which already supports key-value pairs in logging events. The basic idea is to put the key-value pairs before the message and arguments. Applying the same structure like syntax as above we would get something like the following. ```rust info!({ key1: "value1", key2: 123, }, "my message: {}", arg); ``` But personally I'm not a big fan of this formatting, let's try putting everything on a single line instead. ```rust info!({ key1: "value1", key2: 123 }, "my message: {}", arg); ``` A little better, but at this point the structure like syntax is really more annoying then helpful. So, instead I've done away it, opting instead use the following syntax. ```rust info!(key1 = "value1", key2 = 123, "my message: {}", arg); ``` Two major differences: * Removed the brackets. * Colons (`:`) are replaced with equal/assignment signs (`=`). This gives us syntax similar to variable assignment. But then we run in some limitations of the macro syntax, specifically that `expr` fragments aren't allowed after `expr` fragments. To fix this I went with the easiest option of changing the last comma (`,`) after the key-value pairs to a semicolon (`;`). Making the final syntax look like the following. ```rust info!(key1 = "value1", key2 = 123; "my message: {}", arg); info!(target: "my_target", key1 = "value1", key2 = 123; "my message: {}", arg); log!(target: "my_target", log::Level::Info, key1 = "value1", key2 = 123; "my message: {}", arg); ``` Which, in my opinion and all things considered, it's too bad looking. --- src/lib.rs | 30 ++++++++++++++++++++++++++++++ src/macros.rs | 20 ++++++++++++++++++++ tests/macros.rs | 18 ++++++++++++++++++ 3 files changed, 68 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index bbfb1ed31..6239594ea 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1452,10 +1452,39 @@ pub fn logger() -> &'static dyn Log { // WARNING: this is not part of the crate's public API and is subject to change at any time #[doc(hidden)] +#[cfg(not(feature = "kv_unstable"))] pub fn __private_api_log( args: fmt::Arguments, level: Level, &(target, module_path, file, line): &(&str, &'static str, &'static str, u32), + kvs: Option<&[(&str, &str)]>, +) { + if kvs.is_some() { + panic!( + "key-value support is experimental and must be enabled using the `kv_unstable` feature" + ) + } + + logger().log( + &Record::builder() + .args(args) + .level(level) + .target(target) + .module_path_static(Some(module_path)) + .file_static(Some(file)) + .line(Some(line)) + .build(), + ); +} + +// WARNING: this is not part of the crate's public API and is subject to change at any time +#[doc(hidden)] +#[cfg(feature = "kv_unstable")] +pub fn __private_api_log( + args: fmt::Arguments, + level: Level, + &(target, module_path, file, line): &(&str, &'static str, &'static str, u32), + kvs: Option<&[(&str, &dyn kv::ToValue)]>, ) { logger().log( &Record::builder() @@ -1465,6 +1494,7 @@ pub fn __private_api_log( .module_path_static(Some(module_path)) .file_static(Some(file)) .line(Some(line)) + .key_values(&kvs) .build(), ); } diff --git a/src/macros.rs b/src/macros.rs index aed6fdeff..a90feef34 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -29,6 +29,17 @@ /// ``` #[macro_export(local_inner_macros)] macro_rules! log { + (target: $target:expr, $lvl:expr, $($key:ident = $value:expr),* ; $fmt:expr, $($arg:tt)+) => ({ + let lvl = $lvl; + if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { + $crate::__private_api_log( + __log_format_args!($fmt, $($arg)+), + lvl, + &($target, __log_module_path!(), __log_file!(), __log_line!()), + Some(&[$((__log_stringify!($key), &$value)),*]) + ); + } + }); (target: $target:expr, $lvl:expr, $($arg:tt)+) => ({ let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { @@ -36,6 +47,7 @@ macro_rules! log { __log_format_args!($($arg)+), lvl, &($target, __log_module_path!(), __log_file!(), __log_line!()), + None, ); } }); @@ -248,3 +260,11 @@ macro_rules! __log_line { line!() }; } + +#[doc(hidden)] +#[macro_export] +macro_rules! __log_stringify { + ($($args:tt)*) => { + stringify!($($args)*) + }; +} diff --git a/tests/macros.rs b/tests/macros.rs index 4daab32f9..0ccb64028 100644 --- a/tests/macros.rs +++ b/tests/macros.rs @@ -35,3 +35,21 @@ fn with_named_args() { info!("hello {cats}", cats = cats,); info!("hello {cats}", cats = cats,); } + +#[test] +#[cfg(feature = "kv_unstable")] +fn kv() { + info!(cat_1 = "chashu", cat_2 = "nori"; "hello {}", "cats"); + info!(target: "my_target", cat_1 = "chashu", cat_2 = "nori"; "hello {}", "cats"); + log!(target: "my_target", log::Level::Warn, cat_1 = "chashu", cat_2 = "nori"; "hello {}", "cats"); +} + +#[test] +#[cfg(feature = "kv_unstable")] +fn kv_expr_context() { + match "chashu" { + cat_1 => { + info!(target: "target", cat_1 = cat_1, cat_2 = "nori"; "hello {}", "cats") + } + }; +} From 9cb04d763e777714219ab24afac90b39d253f301 Mon Sep 17 00:00:00 2001 From: Ibraheem Ahmed Date: Tue, 19 Oct 2021 18:59:34 -0400 Subject: [PATCH 040/280] relax ordering in `set_max_level` atomic store --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index fd680de75..9799332a2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1236,7 +1236,7 @@ where /// Generally, this should only be called by the active logging implementation. #[inline] pub fn set_max_level(level: LevelFilter) { - MAX_LOG_LEVEL_FILTER.store(level as usize, Ordering::SeqCst) + MAX_LOG_LEVEL_FILTER.store(level as usize, Ordering::Relaxed) } /// Returns the current maximum log level. From 9e5f755a3a19fb917414202f1153c575c8dfdee6 Mon Sep 17 00:00:00 2001 From: cherryblossom000 <31467609+cherryblossom000@users.noreply.github.com> Date: Sat, 23 Oct 2021 16:57:59 +1100 Subject: [PATCH 041/280] Fix typo in docs structued -> structured --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index fd680de75..c3bc8b99c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -880,7 +880,7 @@ impl<'a> Record<'a> { self.line } - /// The structued key-value pairs associated with the message. + /// The structured key-value pairs associated with the message. #[cfg(feature = "kv_unstable")] #[inline] pub fn key_values(&self) -> &dyn kv::Source { From 48693b8fc96ab62381aeaf20d5c942e666ee2827 Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Tue, 26 Oct 2021 19:46:44 +1000 Subject: [PATCH 042/280] pin alpha deps so they're not automatically bumped --- Cargo.toml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a86c99ce7..a8bf0abb9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,11 +55,11 @@ kv_unstable_serde = ["kv_unstable_std", "value-bag/serde", "serde"] [dependencies] cfg-if = "1.0" serde = { version = "1.0", optional = true, default-features = false } -sval = { version = "1.0.0-alpha.5", optional = true, default-features = false } -value-bag = { version = "1.0.0-alpha.6", optional = true, default-features = false } +sval = { version = "=1.0.0-alpha.5", optional = true, default-features = false } +value-bag = { version = "=1.0.0-alpha.8", optional = true, default-features = false } [dev-dependencies] serde = { version = "1.0", features = ["derive"] } serde_test = "1.0" -sval = { version = "1.0.0-alpha.5", features = ["derive"] } -value-bag = { version = "1.0.0-alpha.6", features = ["test"] } +sval = { version = "=1.0.0-alpha.5", features = ["derive"] } +value-bag = { version = "=1.0.0-alpha.8", features = ["test"] } From 0355d570ffd0129d5ce5e72748b2d59c96c888c5 Mon Sep 17 00:00:00 2001 From: Delma Date: Wed, 27 Oct 2021 17:59:29 +0300 Subject: [PATCH 043/280] Instead of making array public add iterator methods --- src/lib.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index edf001c40..777d3dce4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -359,12 +359,7 @@ const INITIALIZED: usize = 2; static MAX_LOG_LEVEL_FILTER: AtomicUsize = AtomicUsize::new(0); -/// Array of supported filter levels for a logger. -/// -/// Values correspond to the variants of the [`LevelFilter`](enum.LevelFilter.html) enum. -/// -/// Can be used, for example, in help text shown to a user of an application. -pub static LOG_LEVEL_NAMES: [&str; 6] = ["OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE"]; +static LOG_LEVEL_NAMES: [&str; 6] = ["OFF", "ERROR", "WARN", "INFO", "DEBUG", "TRACE"]; static SET_LOGGER_ERROR: &str = "attempted to set a logger after the logging system \ was already initialized"; @@ -565,6 +560,11 @@ impl Level { pub fn as_str(&self) -> &'static str { LOG_LEVEL_NAMES[*self as usize] } + + /// Iterate through all supported logging levels + pub fn iter() -> impl Iterator { + (0..).flat_map(Self::from_usize) + } } /// An enum representing the available verbosity level filters of the logger. @@ -727,6 +727,11 @@ impl LevelFilter { pub fn as_str(&self) -> &'static str { LOG_LEVEL_NAMES[*self as usize] } + + /// Iterate through all supported filtering levels + pub fn iter() -> impl Iterator { + (0..).flat_map(Self::from_usize) + } } #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] From 299d3bcb5b438126c6356568bf4f2789003c37f6 Mon Sep 17 00:00:00 2001 From: Delma Date: Wed, 27 Oct 2021 18:02:07 +0300 Subject: [PATCH 044/280] Fixed a bug in Level::iter implementation --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 777d3dce4..d668c1a3a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -563,7 +563,7 @@ impl Level { /// Iterate through all supported logging levels pub fn iter() -> impl Iterator { - (0..).flat_map(Self::from_usize) + (1..).flat_map(Self::from_usize) } } From 05532fabfd3eadce4d640a364f130d729abc2b64 Mon Sep 17 00:00:00 2001 From: Delma Date: Fri, 5 Nov 2021 18:51:42 +0200 Subject: [PATCH 045/280] Added documentation on the order of iteration --- src/lib.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index d668c1a3a..b4df51259 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -562,6 +562,8 @@ impl Level { } /// Iterate through all supported logging levels + /// + /// The order of iteration is from more severe to less severe log messages pub fn iter() -> impl Iterator { (1..).flat_map(Self::from_usize) } @@ -729,6 +731,8 @@ impl LevelFilter { } /// Iterate through all supported filtering levels + /// + /// The order of iteration is from less to more verbose filtering pub fn iter() -> impl Iterator { (0..).flat_map(Self::from_usize) } From b53df056f2f0133855beaba934ecff7b8dc1de91 Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Sun, 14 Nov 2021 14:53:06 +1000 Subject: [PATCH 046/280] add a simple zero-dependency visitor for kv values --- src/kv/error.rs | 20 ++++ src/kv/value.rs | 249 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 269 insertions(+) diff --git a/src/kv/error.rs b/src/kv/error.rs index 0439b3a55..c72d32396 100644 --- a/src/kv/error.rs +++ b/src/kv/error.rs @@ -11,6 +11,7 @@ enum Inner { #[cfg(feature = "std")] Boxed(std_support::BoxedError), Msg(&'static str), + Value(value_bag::Error), Fmt, } @@ -21,6 +22,24 @@ impl Error { inner: Inner::Msg(msg), } } + + // Not public so we don't leak the `value_bag` API + pub(super) fn from_value(err: value_bag::Error) -> Self { + Error { + inner: Inner::Value(err), + } + } + + // Not public so we don't leak the `value_bag` API + pub(super) fn into_value(self) -> value_bag::Error { + match self.inner { + Inner::Value(err) => err, + #[cfg(feature = "kv_unstable_std")] + _ => value_bag::Error::boxed(self), + #[cfg(not(feature = "kv_unstable_std"))] + _ => value_bag::Error::msg("error inspecting a value"), + } + } } impl fmt::Display for Error { @@ -29,6 +48,7 @@ impl fmt::Display for Error { match &self.inner { #[cfg(feature = "std")] &Boxed(ref err) => err.fmt(f), + &Value(ref err) => err.fmt(f), &Msg(ref msg) => msg.fmt(f), &Fmt => fmt::Error.fmt(f), } diff --git a/src/kv/value.rs b/src/kv/value.rs index 7dd108090..75a5d3f9f 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -263,6 +263,73 @@ impl<'v> Value<'v> { pub fn downcast_ref(&self) -> Option<&T> { self.inner.downcast_ref::() } + + /// Inspect this value using a simple visitor. + pub fn visit(&self, visitor: impl Visit<'v>) -> Result<(), Error> { + struct Visitor(V); + + impl<'v, V> value_bag::visit::Visit<'v> for Visitor + where + V: Visit<'v>, + { + fn visit_any(&mut self, value: ValueBag) -> Result<(), value_bag::Error> { + self.0.visit_any(Value { + inner: value + }).map_err(Error::into_value) + } + + fn visit_u64(&mut self, value: u64) -> Result<(), value_bag::Error> { + self.0.visit_u64(value).map_err(Error::into_value) + } + + fn visit_i64(&mut self, value: i64) -> Result<(), value_bag::Error> { + self.0.visit_i64(value).map_err(Error::into_value) + } + + fn visit_u128(&mut self, value: u128) -> Result<(), value_bag::Error> { + self.0.visit_u128(value).map_err(Error::into_value) + } + + fn visit_i128(&mut self, value: i128) -> Result<(), value_bag::Error> { + self.0.visit_i128(value).map_err(Error::into_value) + } + + fn visit_f64(&mut self, value: f64) -> Result<(), value_bag::Error> { + self.0.visit_f64(value).map_err(Error::into_value) + } + + fn visit_bool(&mut self, value: bool) -> Result<(), value_bag::Error> { + self.0.visit_bool(value).map_err(Error::into_value) + } + + fn visit_str(&mut self, value: &str) -> Result<(), value_bag::Error> { + self.0.visit_str(value).map_err(Error::into_value) + } + + fn visit_borrowed_str(&mut self, value: &'v str) -> Result<(), value_bag::Error> { + self.0.visit_borrowed_str(value).map_err(Error::into_value) + } + + fn visit_char(&mut self, value: char) -> Result<(), value_bag::Error> { + self.0.visit_char(value).map_err(Error::into_value) + } + + #[cfg(feature = "kv_unstable_std")] + fn visit_error(&mut self, err: &(dyn std::error::Error + 'static)) -> Result<(), value_bag::Error> { + self.0.visit_error(err).map_err(Error::into_value) + } + + #[cfg(feature = "kv_unstable_std")] + fn visit_borrowed_error( + &mut self, + err: &'v (dyn std::error::Error + 'static), + ) -> Result<(), value_bag::Error> { + self.0.visit_borrowed_error(err).map_err(Error::into_value) + } + } + + self.inner.visit(&mut Visitor(visitor)).map_err(Error::from_value) + } } impl<'v> fmt::Debug for Value<'v> { @@ -448,6 +515,142 @@ mod std_support { self.inner.to_str() } } + + impl<'v> From<&'v String> for Value<'v> { + fn from(v: &'v String) -> Self { + Value::from(&**v) + } + } +} + +/// A visitor for a `Value`. +pub trait Visit<'v> { + /// Visit a `Value`. + /// + /// This is the only required method on `Visit` and acts as a fallback for any + /// more specific methods that aren't overridden. + /// The `Value` may be formatted using its `fmt::Debug` or `fmt::Display` implementation, + /// or serialized using its `sval::Value` or `serde::Serialize` implementation. + fn visit_any(&mut self, value: Value) -> Result<(), Error>; + + /// Visit an unsigned integer. + fn visit_u64(&mut self, value: u64) -> Result<(), Error> { + self.visit_any(value.into()) + } + + /// Visit a signed integer. + fn visit_i64(&mut self, value: i64) -> Result<(), Error> { + self.visit_any(value.into()) + } + + /// Visit a big unsigned integer. + fn visit_u128(&mut self, value: u128) -> Result<(), Error> { + self.visit_any(value.into()) + } + + /// Visit a big signed integer. + fn visit_i128(&mut self, value: i128) -> Result<(), Error> { + self.visit_any(value.into()) + } + + /// Visit a floating point. + fn visit_f64(&mut self, value: f64) -> Result<(), Error> { + self.visit_any(value.into()) + } + + /// Visit a boolean. + fn visit_bool(&mut self, value: bool) -> Result<(), Error> { + self.visit_any(value.into()) + } + + /// Visit a string. + fn visit_str(&mut self, value: &str) -> Result<(), Error> { + self.visit_any(value.into()) + } + + /// Visit a string. + fn visit_borrowed_str(&mut self, value: &'v str) -> Result<(), Error> { + self.visit_str(value) + } + + /// Visit a Unicode character. + fn visit_char(&mut self, value: char) -> Result<(), Error> { + let mut b = [0; 4]; + self.visit_str(&*value.encode_utf8(&mut b)) + } + + /// Visit an error. + #[cfg(feature = "kv_unstable_std")] + fn visit_error(&mut self, err: &(dyn std::error::Error + 'static)) -> Result<(), Error> { + self.visit_any(Value::from_dyn_error(err)) + } + + /// Visit an error. + #[cfg(feature = "kv_unstable_std")] + fn visit_borrowed_error( + &mut self, + err: &'v (dyn std::error::Error + 'static), + ) -> Result<(), Error> { + self.visit_any(Value::from_dyn_error(err)) + } +} + +impl<'a, 'v, T: ?Sized> Visit<'v> for &'a mut T +where + T: Visit<'v>, +{ + fn visit_any(&mut self, value: Value) -> Result<(), Error> { + (**self).visit_any(value) + } + + fn visit_u64(&mut self, value: u64) -> Result<(), Error> { + (**self).visit_u64(value) + } + + fn visit_i64(&mut self, value: i64) -> Result<(), Error> { + (**self).visit_i64(value) + } + + fn visit_u128(&mut self, value: u128) -> Result<(), Error> { + (**self).visit_u128(value) + } + + fn visit_i128(&mut self, value: i128) -> Result<(), Error> { + (**self).visit_i128(value) + } + + fn visit_f64(&mut self, value: f64) -> Result<(), Error> { + (**self).visit_f64(value) + } + + fn visit_bool(&mut self, value: bool) -> Result<(), Error> { + (**self).visit_bool(value) + } + + fn visit_str(&mut self, value: &str) -> Result<(), Error> { + (**self).visit_str(value) + } + + fn visit_borrowed_str(&mut self, value: &'v str) -> Result<(), Error> { + (**self).visit_borrowed_str(value) + } + + fn visit_char(&mut self, value: char) -> Result<(), Error> { + (**self).visit_char(value) + } + + #[cfg(feature = "kv_unstable_std")] + fn visit_error(&mut self, err: &(dyn std::error::Error + 'static)) -> Result<(), Error> { + (**self).visit_error(err) + } + + #[cfg(feature = "kv_unstable_std")] + fn visit_borrowed_error( + &mut self, + err: &'v (dyn std::error::Error + 'static), + ) -> Result<(), Error> { + (**self).visit_borrowed_error(err) + } } #[cfg(test)] @@ -652,4 +855,50 @@ pub(crate) mod tests { assert!(v.is::()); assert_eq!(42u64, v.downcast_ref::().expect("invalid downcast").0); } + + #[test] + fn test_visit_integer() { + struct Extract(Option); + + impl<'v> Visit<'v> for Extract { + fn visit_any(&mut self, value: Value) -> Result<(), Error> { + unimplemented!("unexpected value: {:?}", value) + } + + fn visit_u64(&mut self, value: u64) -> Result<(), Error> { + self.0 = Some(value); + + Ok(()) + } + } + + let mut extract = Extract(None); + Value::from(42u64).visit(&mut extract).unwrap(); + + assert_eq!(Some(42), extract.0); + } + + #[test] + fn test_visit_borrowed_str() { + struct Extract<'v>(Option<&'v str>); + + impl<'v> Visit<'v> for Extract<'v> { + fn visit_any(&mut self, value: Value) -> Result<(), Error> { + unimplemented!("unexpected value: {:?}", value) + } + + fn visit_borrowed_str(&mut self, value: &'v str) -> Result<(), Error> { + self.0 = Some(value); + + Ok(()) + } + } + + let mut extract = Extract(None); + + let short_lived = String::from("A short-lived string"); + Value::from(&*short_lived).visit(&mut extract).unwrap(); + + assert_eq!(Some("A short-lived string"), extract.0); + } } From ef6f45ae51396558433e23b7e1f2a30254a1a02e Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Sun, 14 Nov 2021 14:56:34 +1000 Subject: [PATCH 047/280] run fmt --- src/kv/value.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/kv/value.rs b/src/kv/value.rs index 75a5d3f9f..4cbbca583 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -273,9 +273,9 @@ impl<'v> Value<'v> { V: Visit<'v>, { fn visit_any(&mut self, value: ValueBag) -> Result<(), value_bag::Error> { - self.0.visit_any(Value { - inner: value - }).map_err(Error::into_value) + self.0 + .visit_any(Value { inner: value }) + .map_err(Error::into_value) } fn visit_u64(&mut self, value: u64) -> Result<(), value_bag::Error> { @@ -315,7 +315,10 @@ impl<'v> Value<'v> { } #[cfg(feature = "kv_unstable_std")] - fn visit_error(&mut self, err: &(dyn std::error::Error + 'static)) -> Result<(), value_bag::Error> { + fn visit_error( + &mut self, + err: &(dyn std::error::Error + 'static), + ) -> Result<(), value_bag::Error> { self.0.visit_error(err).map_err(Error::into_value) } @@ -328,7 +331,9 @@ impl<'v> Value<'v> { } } - self.inner.visit(&mut Visitor(visitor)).map_err(Error::from_value) + self.inner + .visit(&mut Visitor(visitor)) + .map_err(Error::from_value) } } From 0813f352058fc7966ceb957a7a6b1e3fdc06bc3d Mon Sep 17 00:00:00 2001 From: KodrAus Date: Mon, 15 Nov 2021 10:55:38 +1000 Subject: [PATCH 048/280] fix up level iterators --- src/lib.rs | 36 +++++++++++++++++++++++++++++------- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index f924e3255..65c498534 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -561,11 +561,22 @@ impl Level { LOG_LEVEL_NAMES[*self as usize] } - /// Iterate through all supported logging levels + /// Iterate through all supported logging levels. /// - /// The order of iteration is from more severe to less severe log messages + /// The order of iteration is from more severe to less severe log messages. + /// + /// # Examples + /// + /// ``` + /// use log::Level; + /// + /// let mut levels = Level::iter(); + /// + /// assert_eq!(Some(Level::Error), levels.next()); + /// assert_eq!(Some(Level::Trace), levels.last()); + /// ``` pub fn iter() -> impl Iterator { - (1..).flat_map(Self::from_usize) + (1..6).flat_map(Self::from_usize) } } @@ -709,6 +720,7 @@ impl LevelFilter { _ => None, } } + /// Returns the most verbose logging level filter. #[inline] pub fn max() -> LevelFilter { @@ -730,11 +742,22 @@ impl LevelFilter { LOG_LEVEL_NAMES[*self as usize] } - /// Iterate through all supported filtering levels + /// Iterate through all supported filtering levels. /// - /// The order of iteration is from less to more verbose filtering + /// The order of iteration is from less to more verbose filtering. + /// + /// # Examples + /// + /// ``` + /// use log::LevelFilter; + /// + /// let mut levels = LevelFilter::iter(); + /// + /// assert_eq!(Some(LevelFilter::Off), levels.next()); + /// assert_eq!(Some(LevelFilter::Trace), levels.last()); + /// ``` pub fn iter() -> impl Iterator { - (0..).flat_map(Self::from_usize) + (0..6).flat_map(Self::from_usize) } } @@ -929,7 +952,6 @@ impl<'a> Record<'a> { /// /// # Examples /// -/// /// ```edition2018 /// use log::{Level, Record}; /// From d394b0c3c3c88d6294577de6c0f234c7348176b8 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Mon, 15 Nov 2021 11:00:04 +1000 Subject: [PATCH 049/280] just unwrap since they're always valid --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 65c498534..bfd0819e9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -576,7 +576,7 @@ impl Level { /// assert_eq!(Some(Level::Trace), levels.last()); /// ``` pub fn iter() -> impl Iterator { - (1..6).flat_map(Self::from_usize) + (1..6).map(|i| Self::from_usize(i).unwrap()) } } @@ -757,7 +757,7 @@ impl LevelFilter { /// assert_eq!(Some(LevelFilter::Trace), levels.last()); /// ``` pub fn iter() -> impl Iterator { - (0..6).flat_map(Self::from_usize) + (0..6).map(|i| Self::from_usize(i).unwrap()) } } From 2d9df517b5908535848213ebfd24ca0c68828b9f Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Mon, 15 Nov 2021 15:50:08 +1000 Subject: [PATCH 050/280] add a note about use in dynamic libraries --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 340b62c9c..8a7c1eea3 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,8 @@ There are many available implementations to choose from, here are some of the mo * [`win_dbg_logger`](https://docs.rs/win_dbg_logger/*/win_dbg_logger/) * For WebAssembly binaries: * [`console_log`](https://docs.rs/console_log/*/console_log/) +* For dynamic libraries: + * You may need to construct [an FFI-safe wrapper over `log`](https://github.com/rust-lang/log/issues/421) to initialize in your libraries. Executables should choose a logger implementation and initialize it early in the runtime of the program. Logger implementations will typically include a From c68890197dc8cc2a4db311a0fbcfac608d8d119b Mon Sep 17 00:00:00 2001 From: KodrAus Date: Mon, 15 Nov 2021 16:55:34 +1000 Subject: [PATCH 051/280] fix tests when running with --all-features --- .github/workflows/main.yml | 2 ++ tests/filters.rs | 42 ++++++++++++++++++++++++++++---------- 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index d90d48baa..855a2d965 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -37,6 +37,8 @@ jobs: rustup update ${{ matrix.rust }} --no-self-update rustup default ${{ matrix.rust }} - run: cargo test --verbose + - run: cargo test --verbose --no-default-features + - run: cargo test --verbose --all-features - run: cargo test --verbose --features serde - run: cargo test --verbose --features std - run: cargo test --verbose --features kv_unstable diff --git a/tests/filters.rs b/tests/filters.rs index de6bd189f..f37751c24 100644 --- a/tests/filters.rs +++ b/tests/filters.rs @@ -1,3 +1,5 @@ +#![allow(dead_code, unused_imports)] + #[cfg(not(lib_build))] #[macro_use] extern crate log; @@ -32,18 +34,36 @@ impl Log for Logger { #[cfg_attr(lib_build, test)] fn main() { - let me = Arc::new(State { - last_log: Mutex::new(None), - }); - let a = me.clone(); - set_boxed_logger(Box::new(Logger(me))).unwrap(); + // These tests don't really make sense when static + // max level filtering is applied + #[cfg(not(any( + feature = "max_level_off", + feature = "max_level_error", + feature = "max_level_warn", + feature = "max_level_info", + feature = "max_level_debug", + feature = "max_level_trace", + feature = "max_level_off", + feature = "max_level_error", + feature = "max_level_warn", + feature = "max_level_info", + feature = "max_level_debug", + feature = "max_level_trace", + )))] + { + let me = Arc::new(State { + last_log: Mutex::new(None), + }); + let a = me.clone(); + set_boxed_logger(Box::new(Logger(me))).unwrap(); - test(&a, LevelFilter::Off); - test(&a, LevelFilter::Error); - test(&a, LevelFilter::Warn); - test(&a, LevelFilter::Info); - test(&a, LevelFilter::Debug); - test(&a, LevelFilter::Trace); + test(&a, LevelFilter::Off); + test(&a, LevelFilter::Error); + test(&a, LevelFilter::Warn); + test(&a, LevelFilter::Info); + test(&a, LevelFilter::Debug); + test(&a, LevelFilter::Trace); + } } fn test(a: &State, filter: LevelFilter) { From 4a1d48867f9266a641ba09f3cf2c9ea012a0ecf7 Mon Sep 17 00:00:00 2001 From: piegames Date: Mon, 15 Nov 2021 23:53:54 +0100 Subject: [PATCH 052/280] Add Log implementation on foreign types Closes #458. Implements Log for references to loggers, as well as loggers wrapped in `Arc` or `Pin`. More may be added in the future. Especially, we probably will want to add a blanket implementation (bounded on `Borrow`) once we have impl specialization. (Technically, we could probably already do this now, but at the risk of painting ourselves into a corner.) --- src/lib.rs | 90 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 89 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index bfd0819e9..5dfb91479 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -269,7 +269,7 @@ html_root_url = "https://docs.rs/log/0.4.14" )] #![warn(missing_docs)] -#![deny(missing_debug_implementations)] +#![deny(missing_debug_implementations, unconditional_recursion)] #![cfg_attr(all(not(feature = "std"), not(test)), no_std)] // When compiled for the rustc compiler itself we want to make sure that this is // an unstable crate @@ -1250,6 +1250,22 @@ impl Log for NopLogger { fn flush(&self) {} } +impl Log for &'_ T +where + T: ?Sized + Log, +{ + fn enabled(&self, metadata: &Metadata) -> bool { + (**self).enabled(metadata) + } + + fn log(&self, record: &Record) { + (**self).log(record) + } + fn flush(&self) { + (**self).flush() + } +} + #[cfg(feature = "std")] impl Log for std::boxed::Box where @@ -1267,6 +1283,41 @@ where } } +#[cfg(feature = "std")] +impl Log for std::pin::Pin

+where + P: std::ops::Deref + std::marker::Send + std::marker::Sync, + T: Log + ?Sized, +{ + fn enabled(&self, metadata: &Metadata) -> bool { + (**self).enabled(metadata) + } + + fn log(&self, record: &Record) { + (**self).log(record) + } + fn flush(&self) { + (**self).flush() + } +} + +#[cfg(feature = "std")] +impl Log for std::sync::Arc +where + T: ?Sized + Log, +{ + fn enabled(&self, metadata: &Metadata) -> bool { + self.as_ref().enabled(metadata) + } + + fn log(&self, record: &Record) { + self.as_ref().log(record) + } + fn flush(&self) { + self.as_ref().flush() + } +} + /// Sets the global maximum log level. /// /// Generally, this should only be called by the active logging implementation. @@ -1842,4 +1893,41 @@ mod tests { .expect("invalid value") ); } + + // Test that the `impl Log for Foo` blocks work + // This test mostly operates on a type level, so failures will be compile errors + #[test] + fn test_foreign_impl() { + use super::Log; + #[cfg(feature = "std")] + use std::{pin::Pin, sync::Arc}; + + fn assert_is_log() {} + + assert_is_log::<&dyn Log>(); + + #[cfg(feature = "std")] + assert_is_log::>(); + + #[cfg(feature = "std")] + assert_is_log::>>(); + + #[cfg(feature = "std")] + assert_is_log::>(); + + // Assert these statements for all T: Log + ?Sized + #[allow(unused)] + fn forall() { + #[cfg(feature = "std")] + assert_is_log::>(); + + #[cfg(feature = "std")] + assert_is_log::>>(); + + assert_is_log::<&T>(); + + #[cfg(feature = "std")] + assert_is_log::>(); + } + } } From 084624a0973beecae1dd949541e28c1e20a91e20 Mon Sep 17 00:00:00 2001 From: piegames Date: Wed, 17 Nov 2021 18:18:53 +0100 Subject: [PATCH 053/280] fixup! Add Log implementation on foreign types Removes the Pin implementation again, because of the MSRV of the crate beeing too low --- src/lib.rs | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 5dfb91479..1dbae3bcf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1283,24 +1283,6 @@ where } } -#[cfg(feature = "std")] -impl Log for std::pin::Pin

-where - P: std::ops::Deref + std::marker::Send + std::marker::Sync, - T: Log + ?Sized, -{ - fn enabled(&self, metadata: &Metadata) -> bool { - (**self).enabled(metadata) - } - - fn log(&self, record: &Record) { - (**self).log(record) - } - fn flush(&self) { - (**self).flush() - } -} - #[cfg(feature = "std")] impl Log for std::sync::Arc where @@ -1900,7 +1882,7 @@ mod tests { fn test_foreign_impl() { use super::Log; #[cfg(feature = "std")] - use std::{pin::Pin, sync::Arc}; + use std::sync::Arc; fn assert_is_log() {} @@ -1909,9 +1891,6 @@ mod tests { #[cfg(feature = "std")] assert_is_log::>(); - #[cfg(feature = "std")] - assert_is_log::>>(); - #[cfg(feature = "std")] assert_is_log::>(); @@ -1921,9 +1900,6 @@ mod tests { #[cfg(feature = "std")] assert_is_log::>(); - #[cfg(feature = "std")] - assert_is_log::>>(); - assert_is_log::<&T>(); #[cfg(feature = "std")] From 403f16cffb274fa492d26abe9f1da36dddc044ca Mon Sep 17 00:00:00 2001 From: wendajiang Date: Fri, 3 Dec 2021 16:27:04 +0800 Subject: [PATCH 054/280] add some readme to crate doc --- src/lib.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 1dbae3bcf..995e6de0e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -106,6 +106,13 @@ //! * Adaptors for other facilities: //! * [syslog] //! * [slog-stdlog] +//! * [systemd-journal-logger] +//! * [android_log] +//! * [win_dbg_logger] +//! * For WebAssembly binaries: +//! * [console_log] +//! * For dynamic libraries: +//! * You may need to construct an FFI-safe wrapper over `log` to initialize in your libraries //! //! # Implementing a Logger //! From 77ae39bfc74a295d848e54b4231eb89075338ee5 Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Tue, 7 Dec 2021 20:05:11 +1000 Subject: [PATCH 055/280] fix up some links and tests --- src/lib.rs | 4 ++++ tests/filters.rs | 12 ++++++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 995e6de0e..58c636b92 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -269,6 +269,10 @@ //! [slog-stdlog]: https://docs.rs/slog-stdlog/*/slog_stdlog/ //! [log4rs]: https://docs.rs/log4rs/*/log4rs/ //! [fern]: https://docs.rs/fern/*/fern/ +//! [systemd-journal-logger]: (https://docs.rs/systemd-journal-logger/*/systemd_journal_logger/) +//! [android_log]: (https://docs.rs/android_log/*/android_log/) +//! [win_dbg_logger]: (https://docs.rs/win_dbg_logger/*/win_dbg_logger/) +//! [console_log]: (https://docs.rs/console_log/*/console_log/) #![doc( html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", diff --git a/tests/filters.rs b/tests/filters.rs index f37751c24..66d6f8cd0 100644 --- a/tests/filters.rs +++ b/tests/filters.rs @@ -43,12 +43,12 @@ fn main() { feature = "max_level_info", feature = "max_level_debug", feature = "max_level_trace", - feature = "max_level_off", - feature = "max_level_error", - feature = "max_level_warn", - feature = "max_level_info", - feature = "max_level_debug", - feature = "max_level_trace", + feature = "release_max_level_off", + feature = "release_max_level_error", + feature = "release_max_level_warn", + feature = "release_max_level_info", + feature = "release_max_level_debug", + feature = "release_max_level_trace", )))] { let me = Arc::new(State { From 62c6607b259106b50be846fdfdb527e214817920 Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Tue, 7 Dec 2021 22:48:47 +1000 Subject: [PATCH 056/280] allow macros to be more consistent with kvs --- Cargo.toml | 1 + README.md | 12 ++- src/kv/value.rs | 33 ++++++++ src/lib.rs | 40 +++++++++- src/macros.rs | 106 ++++++++++++++++--------- tests/Cargo.toml | 3 + tests/macros.rs | 200 +++++++++++++++++++++++++++++++++++++++++------ 7 files changed, 331 insertions(+), 64 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a8bf0abb9..5a67bdce6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,6 +59,7 @@ sval = { version = "=1.0.0-alpha.5", optional = true, default-features = false } value-bag = { version = "=1.0.0-alpha.8", optional = true, default-features = false } [dev-dependencies] +rustversion = "1.0" serde = { version = "1.0", features = ["derive"] } serde_test = "1.0" sval = { version = "=1.0.0-alpha.5", features = ["derive"] } diff --git a/README.md b/README.md index 8a7c1eea3..c17b6486e 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ This version is explicitly tested in CI and may be bumped in any release as need ## Usage -## In libraries +### In libraries Libraries should link only to the `log` crate, and use the provided macros to log whatever information will be useful to downstream consumers: @@ -55,7 +55,7 @@ pub fn shave_the_yak(yak: &mut Yak) { } ``` -## In executables +### In executables In order to produce log output, executables have to use a logger implementation compatible with the facade. There are many available implementations to choose from, here are some of the most popular ones: @@ -87,3 +87,11 @@ function to do this. Any log messages generated before the logger is initialized will be ignored. The executable itself may use the `log` crate to log as well. + +## Structured logging + +If you enable the `kv_unstable` feature, you can associate structured data with your log records: + +```rust + +``` diff --git a/src/kv/value.rs b/src/kv/value.rs index 4cbbca583..727c249ea 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -37,6 +37,39 @@ impl<'v> ToValue for Value<'v> { } } +/// Get a value from a type implementing `std::fmt::Debug`. +#[macro_export] +macro_rules! as_debug { + ($capture:expr) => ($crate::kv::Value::from_debug(&$capture)); +} + +/// Get a value from a type implementing `std::fmt::Display`. +#[macro_export] +macro_rules! as_display { + ($capture:expr) => ($crate::kv::Value::from_display(&$capture)); +} + +/// Get a value from an error. +#[cfg(feature = "kv_unstable_std")] +#[macro_export] +macro_rules! as_error { + ($capture:expr) => ($crate::kv::Value::from_dyn_error(&$capture)); +} + +#[cfg(feature = "kv_unstable_serde")] +/// Get a value from a type implementing `serde::Serialize`. +#[macro_export] +macro_rules! as_serde { + ($capture:expr) => ($crate::kv::Value::from_serde(&$capture)); +} + +/// Get a value from a type implementing `sval::value::Value`. +#[cfg(feature = "kv_unstable_sval")] +#[macro_export] +macro_rules! as_sval { + ($capture:expr) => ($crate::kv::Value::from_sval(&$capture)); +} + /// A value in a structured key-value pair. /// /// # Capturing values diff --git a/src/lib.rs b/src/lib.rs index 58c636b92..4123a712c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,7 +24,7 @@ //! though that default may be overridden. Logger implementations typically use //! the target to filter requests based on some user configuration. //! -//! # Use +//! # Usage //! //! The basic use of the log crate is through the five logging macros: [`error!`], //! [`warn!`], [`info!`], [`debug!`] and [`trace!`] @@ -55,7 +55,7 @@ //! use log::{info, warn}; //! //! pub fn shave_the_yak(yak: &mut Yak) { -//! info!(target: "yak_events", "Commencing yak shaving for {:?}", yak); +//! info!(target = "yak_events"; "Commencing yak shaving for {:?}", yak); //! //! loop { //! match find_a_razor() { @@ -86,6 +86,42 @@ //! //! The logging system may only be initialized once. //! +//! ## Structured logging +//! +//! If you enable the `kv_unstable` feature you can associate structured values +//! with your log records. If we take the example from before, we can include +//! some additional context besides what's in the formatted message: +//! +//! ```edition2018 +//! # #[macro_use] extern crate serde; +//! # #[derive(Debug, Serialize)] pub struct Yak(String); +//! # impl Yak { fn shave(&mut self, _: u32) {} } +//! # fn find_a_razor() -> Result { Ok(1) } +//! # #[cfg(feature = "kv_unstable_serde")] +//! # fn main() { +//! use log::{info, warn, as_serde, as_error}; +//! +//! pub fn shave_the_yak(yak: &mut Yak) { +//! info!(target = "yak_events"; yak = as_serde!(yak); "Commencing yak shaving"); +//! +//! loop { +//! match find_a_razor() { +//! Ok(razor) => { +//! info!(razor = razor; "Razor located"); +//! yak.shave(razor); +//! break; +//! } +//! Err(err) => { +//! warn!(err = as_error!(err); "Unable to locate a razor, retrying"); +//! } +//! } +//! } +//! } +//! # } +//! # #[cfg(not(feature = "kv_unstable_serde"))] +//! # fn main() {} +//! ``` +//! //! # Available logging implementations //! //! In order to produce log output executables have to use diff --git a/src/macros.rs b/src/macros.rs index a90feef34..24331cc26 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -29,18 +29,21 @@ /// ``` #[macro_export(local_inner_macros)] macro_rules! log { - (target: $target:expr, $lvl:expr, $($key:ident = $value:expr),* ; $fmt:expr, $($arg:tt)+) => ({ + // log!(target = "my_target", Level::Info; key1 = 42, key2 = true; "a {} event", "log"); + (target = $target:expr, $lvl:expr; $($key:ident = $value:expr),+; $($arg:tt)+) => ({ let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { $crate::__private_api_log( - __log_format_args!($fmt, $($arg)+), + __log_format_args!($($arg)+), lvl, &($target, __log_module_path!(), __log_file!(), __log_line!()), - Some(&[$((__log_stringify!($key), &$value)),*]) + Some(&[$((__log_stringify!($key), &$value)),+]) ); } }); - (target: $target:expr, $lvl:expr, $($arg:tt)+) => ({ + + // log!(target = "my_target", Level::Info; "a {} event", "log"); + (target = $target:expr, $lvl:expr; $($arg:tt)+) => ({ let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { $crate::__private_api_log( @@ -51,7 +54,18 @@ macro_rules! log { ); } }); - ($lvl:expr, $($arg:tt)+) => (log!(target: __log_module_path!(), $lvl, $($arg)+)) + + // log!(target: "my_target", Level::Info, "a log event") + (target: $target:expr, $lvl:expr, $($arg:tt)+) => (log!(target = $target, $lvl; $($arg)+)); + + // log!(target = "my_target", Level::Info; "a log event") + (target = $target:expr, $lvl:expr; $($arg:tt)+) => (log!(target = $target, $lvl; $($arg)+)); + + // log!(Level::Info, "a log event") + ($lvl:expr, $($arg:tt)+) => (log!(target = __log_module_path!(), $lvl; $($arg)+)); + + // log!(Level::Info; "a log event") + ($lvl:expr; $($arg:tt)+) => (log!(target = __log_module_path!(), $lvl; $($arg)+)) } /// Logs a message at the error level. @@ -70,12 +84,15 @@ macro_rules! log { /// ``` #[macro_export(local_inner_macros)] macro_rules! error { - (target: $target:expr, $($arg:tt)+) => ( - log!(target: $target, $crate::Level::Error, $($arg)+) - ); - ($($arg:tt)+) => ( - log!($crate::Level::Error, $($arg)+) - ) + // error!(target = "my_target"; key1 = 42, key2 = true; "a {} event", "log") + // error!(target = "my_target"; "a {} event", "log") + (target = $target:expr; $($arg:tt)+) => (log!(target = $target, $crate::Level::Error; $($arg)+)); + + // error!(target: "my_target", "a {} event", "log") + (target: $target:expr, $($arg:tt)+) => (log!(target = $target, $crate::Level::Error; $($arg)+)); + + // error!("a {} event", "log") + ($($arg:tt)+) => (log!($crate::Level::Error; $($arg)+)) } /// Logs a message at the warn level. @@ -94,12 +111,15 @@ macro_rules! error { /// ``` #[macro_export(local_inner_macros)] macro_rules! warn { - (target: $target:expr, $($arg:tt)+) => ( - log!(target: $target, $crate::Level::Warn, $($arg)+) - ); - ($($arg:tt)+) => ( - log!($crate::Level::Warn, $($arg)+) - ) + // warn!(target = "my_target"; key1 = 42, key2 = true; "a {} event", "log") + // warn!(target = "my_target"; "a {} event", "log") + (target = $target:expr; $($arg:tt)+) => (log!(target = $target, $crate::Level::Warn; $($arg)+)); + + // warn!(target: "my_target", "a {} event", "log") + (target: $target:expr, $($arg:tt)+) => (log!(target = $target, $crate::Level::Warn; $($arg)+)); + + // warn!("a {} event", "log") + ($($arg:tt)+) => (log!($crate::Level::Warn; $($arg)+)) } /// Logs a message at the info level. @@ -120,12 +140,15 @@ macro_rules! warn { /// ``` #[macro_export(local_inner_macros)] macro_rules! info { - (target: $target:expr, $($arg:tt)+) => ( - log!(target: $target, $crate::Level::Info, $($arg)+) - ); - ($($arg:tt)+) => ( - log!($crate::Level::Info, $($arg)+) - ) + // info!(target = "my_target"; key1 = 42, key2 = true; "a {} event", "log") + // info!(target = "my_target"; "a {} event", "log") + (target = $target:expr; $($arg:tt)+) => (log!(target = $target, $crate::Level::Info; $($arg)+)); + + // info!(target: "my_target", "a {} event", "log") + (target: $target:expr, $($arg:tt)+) => (log!(target = $target, $crate::Level::Info; $($arg)+)); + + // info!("a {} event", "log") + ($($arg:tt)+) => (log!($crate::Level::Info; $($arg)+)) } /// Logs a message at the debug level. @@ -145,12 +168,15 @@ macro_rules! info { /// ``` #[macro_export(local_inner_macros)] macro_rules! debug { - (target: $target:expr, $($arg:tt)+) => ( - log!(target: $target, $crate::Level::Debug, $($arg)+) - ); - ($($arg:tt)+) => ( - log!($crate::Level::Debug, $($arg)+) - ) + // debug!(target = "my_target"; key1 = 42, key2 = true; "a {} event", "log") + // debug!(target = "my_target"; "a {} event", "log") + (target = $target:expr; $($arg:tt)+) => (log!(target = $target, $crate::Level::Debug; $($arg)+)); + + // debug!(target: "my_target", "a {} event", "log") + (target: $target:expr, $($arg:tt)+) => (log!(target = $target, $crate::Level::Debug; $($arg)+)); + + // debug!("a {} event", "log") + ($($arg:tt)+) => (log!($crate::Level::Debug; $($arg)+)) } /// Logs a message at the trace level. @@ -172,12 +198,15 @@ macro_rules! debug { /// ``` #[macro_export(local_inner_macros)] macro_rules! trace { - (target: $target:expr, $($arg:tt)+) => ( - log!(target: $target, $crate::Level::Trace, $($arg)+) - ); - ($($arg:tt)+) => ( - log!($crate::Level::Trace, $($arg)+) - ) + // trace!(target = "my_target"; key1 = 42, key2 = true; "a {} event", "log") + // trace!(target = "my_target"; "a {} event", "log") + (target = $target:expr; $($arg:tt)+) => (log!(target = $target, $crate::Level::Trace; $($arg)+)); + + // trace!(target: "my_target", "a {} event", "log") + (target: $target:expr, $($arg:tt)+) => (log!(target = $target, $crate::Level::Trace; $($arg)+)); + + // trace!("a {} event", "log") + ($($arg:tt)+) => (log!($crate::Level::Trace; $($arg)+)) } /// Determines if a message logged at the specified level in that module will @@ -208,14 +237,17 @@ macro_rules! trace { /// ``` #[macro_export(local_inner_macros)] macro_rules! log_enabled { - (target: $target:expr, $lvl:expr) => {{ + (target = $target:expr, $lvl:expr) => {{ let lvl = $lvl; lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() && $crate::__private_api_enabled(lvl, $target) }}; + (target: $target:expr, $lvl:expr) => { + log_enabled!(target = $target, $lvl) + }; ($lvl:expr) => { - log_enabled!(target: __log_module_path!(), $lvl) + log_enabled!(target = __log_module_path!(), $lvl) }; } diff --git a/tests/Cargo.toml b/tests/Cargo.toml index cb6b8600f..25ac12bec 100644 --- a/tests/Cargo.toml +++ b/tests/Cargo.toml @@ -9,3 +9,6 @@ std = ["log/std"] [dependencies.log] path = ".." + +[dev-dependencies.rustversion] +version = "1.0" diff --git a/tests/macros.rs b/tests/macros.rs index 0ccb64028..cd0e44cf7 100644 --- a/tests/macros.rs +++ b/tests/macros.rs @@ -2,46 +2,200 @@ #[macro_use] extern crate log; +macro_rules! all_log_macros { + ($($arg:tt)*) => ({ + trace!($($arg)*); + debug!($($arg)*); + info!($($arg)*); + warn!($($arg)*); + error!($($arg)*); + }); +} + #[test] -fn base() { - info!("hello"); - info!("hello",); +fn no_args() { + for lvl in log::Level::iter() { + log!(lvl, "hello"); + log!(lvl, "hello",); + + log!(target: "my_target", lvl, "hello"); + log!(target: "my_target", lvl, "hello",); + + log!(lvl; "hello"); + log!(lvl; "hello",); + + log!(target = "my_target", lvl; "hello"); + log!(target = "my_target", lvl; "hello",); + } + + all_log_macros!("hello"); + all_log_macros!("hello",); + + all_log_macros!(target = "my_target"; "hello"); + all_log_macros!(target = "my_target"; "hello",); + + all_log_macros!(target: "my_target", "hello"); + all_log_macros!(target: "my_target", "hello",); } #[test] -fn base_expr_context() { - let _ = info!("hello"); +fn anonymous_args() { + for lvl in log::Level::iter() { + log!(lvl, "hello {}", "world"); + log!(lvl, "hello {}", "world",); + + log!(target: "my_target", lvl, "hello {}", "world"); + log!(target: "my_target", lvl, "hello {}", "world",); + + log!(lvl; "hello {}", "world"); + log!(lvl; "hello {}", "world",); + + log!(target = "my_target", lvl; "hello {}", "world"); + log!(target = "my_target", lvl; "hello {}", "world",); + } + + all_log_macros!("hello {}", "world"); + all_log_macros!("hello {}", "world",); + + all_log_macros!(target = "my_target"; "hello {}", "world"); + all_log_macros!(target = "my_target"; "hello {}", "world",); + + all_log_macros!(target: "my_target", "hello {}", "world"); + all_log_macros!(target: "my_target", "hello {}", "world",); } #[test] -fn with_args() { - info!("hello {}", "cats"); - info!("hello {}", "cats",); - info!("hello {}", "cats",); +fn named_args() { + for lvl in log::Level::iter() { + log!(lvl, "hello {world}", world = "world"); + log!(lvl, "hello {world}", world = "world",); + + log!(target: "my_target", lvl, "hello {world}", world = "world"); + log!(target: "my_target", lvl, "hello {world}", world = "world",); + + log!(lvl; "hello {world}", world = "world"); + log!(lvl; "hello {world}", world = "world",); + + log!(target = "my_target", lvl; "hello {world}", world = "world"); + log!(target = "my_target", lvl; "hello {world}", world = "world",); + } + + all_log_macros!("hello {world}", world = "world"); + all_log_macros!("hello {world}", world = "world",); + + all_log_macros!(target = "my_target"; "hello {world}", world = "world"); + all_log_macros!(target = "my_target"; "hello {world}", world = "world",); + + all_log_macros!(target: "my_target", "hello {world}", world = "world"); + all_log_macros!(target: "my_target", "hello {world}", world = "world",); } #[test] -fn with_args_expr_context() { - match "cats" { - cats => info!("hello {}", cats), - }; +#[rustversion::since(1.58)] +fn implicit_named_args() { + let world = "world"; + + for lvl in log::Level::iter() { + log!(lvl, "hello {world}"); + log!(lvl, "hello {world}",); + + log!(target: "my_target", lvl, "hello {world}"); + log!(target: "my_target", lvl, "hello {world}",); + + log!(lvl; "hello {world}"); + log!(lvl; "hello {world}",); + + log!(target = "my_target", lvl; "hello {world}"); + log!(target = "my_target", lvl; "hello {world}",); + } + + all_log_macros!("hello {world}"); + all_log_macros!("hello {world}",); + + all_log_macros!(target = "my_target"; "hello {world}"); + all_log_macros!(target = "my_target"; "hello {world}",); + + all_log_macros!(target: "my_target", "hello {world}"); + all_log_macros!(target: "my_target", "hello {world}",); +} + +#[test] +fn enabled() { + for lvl in log::Level::iter() { + let _enabled = if log_enabled!(target: "my_target", lvl) { + true + } else { + false + }; + + let _enabled = if log_enabled!(target = "my_target", lvl) { + true + } else { + false + }; + } +} + +#[test] +fn expr() { + for lvl in log::Level::iter() { + let _ = log!(lvl; "hello"); + } +} + +#[test] +#[cfg(feature = "kv_unstable")] +fn kv_no_args() { + for lvl in log::Level::iter() { + log!(target = "my_target", lvl; cat_1 = "chashu", cat_2 = "nori"; "hello"); + + log!(lvl; cat_1 = "chashu", cat_2 = "nori"; "hello"); + } + + all_log_macros!(target = "my_target"; cat_1 = "chashu", cat_2 = "nori"; "hello"); + all_log_macros!(cat_1 = "chashu", cat_2 = "nori"; "hello"); } #[test] -fn with_named_args() { - let cats = "cats"; +#[cfg(feature = "kv_unstable")] +fn kv_anonymous_args() { + for lvl in log::Level::iter() { + log!(target = "my_target", lvl; cat_1 = "chashu", cat_2 = "nori"; "hello {}", "world"); + + log!(lvl; cat_1 = "chashu", cat_2 = "nori"; "hello {}", "world"); + } - info!("hello {cats}", cats = cats); - info!("hello {cats}", cats = cats,); - info!("hello {cats}", cats = cats,); + all_log_macros!(target = "my_target"; cat_1 = "chashu", cat_2 = "nori"; "hello {}", "world"); + all_log_macros!(cat_1 = "chashu", cat_2 = "nori"; "hello {}", "world"); } #[test] #[cfg(feature = "kv_unstable")] -fn kv() { - info!(cat_1 = "chashu", cat_2 = "nori"; "hello {}", "cats"); - info!(target: "my_target", cat_1 = "chashu", cat_2 = "nori"; "hello {}", "cats"); - log!(target: "my_target", log::Level::Warn, cat_1 = "chashu", cat_2 = "nori"; "hello {}", "cats"); +fn kv_named_args() { + for lvl in log::Level::iter() { + log!(target = "my_target", lvl; cat_1 = "chashu", cat_2 = "nori"; "hello {world}", world = "world"); + + log!(lvl; cat_1 = "chashu", cat_2 = "nori"; "hello {world}", world = "world"); + } + + all_log_macros!(target = "my_target"; cat_1 = "chashu", cat_2 = "nori"; "hello {world}", world = "world"); + all_log_macros!(cat_1 = "chashu", cat_2 = "nori"; "hello {world}", world = "world"); +} + +#[test] +#[cfg(feature = "kv_unstable")] +#[rustversion::since(1.58)] +fn kv_implicit_named_args() { + let world = "world"; + + for lvl in log::Level::iter() { + log!(target = "my_target", lvl; cat_1 = "chashu", cat_2 = "nori"; "hello {world}"); + + log!(lvl; cat_1 = "chashu", cat_2 = "nori"; "hello {world}"); + } + + all_log_macros!(target = "my_target"; cat_1 = "chashu", cat_2 = "nori"; "hello {world}"); + all_log_macros!(cat_1 = "chashu", cat_2 = "nori"; "hello {world}"); } #[test] @@ -49,7 +203,7 @@ fn kv() { fn kv_expr_context() { match "chashu" { cat_1 => { - info!(target: "target", cat_1 = cat_1, cat_2 = "nori"; "hello {}", "cats") + info!(target = "target"; cat_1 = cat_1, cat_2 = "nori"; "hello {}", "cats") } }; } From bbc5527da69adbb32bf5224552b14f9945542938 Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Tue, 7 Dec 2021 22:58:27 +1000 Subject: [PATCH 057/280] fill in readme example --- README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/README.md b/README.md index c17b6486e..c67207f1a 100644 --- a/README.md +++ b/README.md @@ -93,5 +93,22 @@ The executable itself may use the `log` crate to log as well. If you enable the `kv_unstable` feature, you can associate structured data with your log records: ```rust +use log::{info, trace, warn, as_serde, as_error}; +pub fn shave_the_yak(yak: &mut Yak) { + trace!(target = "yak_events"; yak = as_serde!(yak); "Commencing yak shaving"); + + loop { + match find_a_razor() { + Ok(razor) => { + info!(razor = razor; "Razor located"); + yak.shave(razor); + break; + } + Err(err) => { + warn!(err = as_error!(err); "Unable to locate a razor, retrying"); + } + } + } +} ``` From 77667f5436eaf507dadad0c3ba523c45354c72e4 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Sun, 12 Dec 2021 10:57:45 +1000 Subject: [PATCH 058/280] move implicit arg tests into module --- tests/macros.rs | 100 ++++++++++++++++++++++++++---------------------- 1 file changed, 55 insertions(+), 45 deletions(-) diff --git a/tests/macros.rs b/tests/macros.rs index cd0e44cf7..dcc88f851 100644 --- a/tests/macros.rs +++ b/tests/macros.rs @@ -90,35 +90,6 @@ fn named_args() { all_log_macros!(target: "my_target", "hello {world}", world = "world",); } -#[test] -#[rustversion::since(1.58)] -fn implicit_named_args() { - let world = "world"; - - for lvl in log::Level::iter() { - log!(lvl, "hello {world}"); - log!(lvl, "hello {world}",); - - log!(target: "my_target", lvl, "hello {world}"); - log!(target: "my_target", lvl, "hello {world}",); - - log!(lvl; "hello {world}"); - log!(lvl; "hello {world}",); - - log!(target = "my_target", lvl; "hello {world}"); - log!(target = "my_target", lvl; "hello {world}",); - } - - all_log_macros!("hello {world}"); - all_log_macros!("hello {world}",); - - all_log_macros!(target = "my_target"; "hello {world}"); - all_log_macros!(target = "my_target"; "hello {world}",); - - all_log_macros!(target: "my_target", "hello {world}"); - all_log_macros!(target: "my_target", "hello {world}",); -} - #[test] fn enabled() { for lvl in log::Level::iter() { @@ -182,22 +153,6 @@ fn kv_named_args() { all_log_macros!(cat_1 = "chashu", cat_2 = "nori"; "hello {world}", world = "world"); } -#[test] -#[cfg(feature = "kv_unstable")] -#[rustversion::since(1.58)] -fn kv_implicit_named_args() { - let world = "world"; - - for lvl in log::Level::iter() { - log!(target = "my_target", lvl; cat_1 = "chashu", cat_2 = "nori"; "hello {world}"); - - log!(lvl; cat_1 = "chashu", cat_2 = "nori"; "hello {world}"); - } - - all_log_macros!(target = "my_target"; cat_1 = "chashu", cat_2 = "nori"; "hello {world}"); - all_log_macros!(cat_1 = "chashu", cat_2 = "nori"; "hello {world}"); -} - #[test] #[cfg(feature = "kv_unstable")] fn kv_expr_context() { @@ -207,3 +162,58 @@ fn kv_expr_context() { } }; } + +#[test] +#[cfg(feature = "kv_unstable")] +fn kv_shadow_target() { + all_log_macros!(target = "kv_target"; "hello {}", "world"); + all_log_macros!(target = "kv_target", cat_1 = "chashu", cat_2 = "nori"; "hello {}", "world"); +} + +#[rustversion::since(1.58)] +mod implicit_args { + use super::*; + + #[test] + fn implicit_named_args() { + let world = "world"; + + for lvl in log::Level::iter() { + log!(lvl, "hello {world}"); + log!(lvl, "hello {world}",); + + log!(target: "my_target", lvl, "hello {world}"); + log!(target: "my_target", lvl, "hello {world}",); + + log!(lvl; "hello {world}"); + log!(lvl; "hello {world}",); + + log!(target = "my_target", lvl; "hello {world}"); + log!(target = "my_target", lvl; "hello {world}",); + } + + all_log_macros!("hello {world}"); + all_log_macros!("hello {world}",); + + all_log_macros!(target = "my_target"; "hello {world}"); + all_log_macros!(target = "my_target"; "hello {world}",); + + all_log_macros!(target: "my_target", "hello {world}"); + all_log_macros!(target: "my_target", "hello {world}",); + } + + #[test] + #[cfg(feature = "kv_unstable")] + fn kv_implicit_named_args() { + let world = "world"; + + for lvl in log::Level::iter() { + log!(target = "my_target", lvl; cat_1 = "chashu", cat_2 = "nori"; "hello {world}"); + + log!(lvl; cat_1 = "chashu", cat_2 = "nori"; "hello {world}"); + } + + all_log_macros!(target = "my_target"; cat_1 = "chashu", cat_2 = "nori"; "hello {world}"); + all_log_macros!(cat_1 = "chashu", cat_2 = "nori"; "hello {world}"); + } +} From 13b9dbcef1a87c0b35b4434b703861914d80ae3f Mon Sep 17 00:00:00 2001 From: KodrAus Date: Sun, 12 Dec 2021 11:00:46 +1000 Subject: [PATCH 059/280] add a different prop type to macro tests --- tests/macros.rs | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/tests/macros.rs b/tests/macros.rs index dcc88f851..20e905e4a 100644 --- a/tests/macros.rs +++ b/tests/macros.rs @@ -118,39 +118,39 @@ fn expr() { #[cfg(feature = "kv_unstable")] fn kv_no_args() { for lvl in log::Level::iter() { - log!(target = "my_target", lvl; cat_1 = "chashu", cat_2 = "nori"; "hello"); + log!(target = "my_target", lvl; cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); - log!(lvl; cat_1 = "chashu", cat_2 = "nori"; "hello"); + log!(lvl; cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); } - all_log_macros!(target = "my_target"; cat_1 = "chashu", cat_2 = "nori"; "hello"); - all_log_macros!(cat_1 = "chashu", cat_2 = "nori"; "hello"); + all_log_macros!(target = "my_target"; cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); + all_log_macros!(cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); } #[test] #[cfg(feature = "kv_unstable")] fn kv_anonymous_args() { for lvl in log::Level::iter() { - log!(target = "my_target", lvl; cat_1 = "chashu", cat_2 = "nori"; "hello {}", "world"); + log!(target = "my_target", lvl; cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {}", "world"); - log!(lvl; cat_1 = "chashu", cat_2 = "nori"; "hello {}", "world"); + log!(lvl; cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {}", "world"); } - all_log_macros!(target = "my_target"; cat_1 = "chashu", cat_2 = "nori"; "hello {}", "world"); - all_log_macros!(cat_1 = "chashu", cat_2 = "nori"; "hello {}", "world"); + all_log_macros!(target = "my_target"; cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {}", "world"); + all_log_macros!(cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {}", "world"); } #[test] #[cfg(feature = "kv_unstable")] fn kv_named_args() { for lvl in log::Level::iter() { - log!(target = "my_target", lvl; cat_1 = "chashu", cat_2 = "nori"; "hello {world}", world = "world"); + log!(target = "my_target", lvl; cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}", world = "world"); - log!(lvl; cat_1 = "chashu", cat_2 = "nori"; "hello {world}", world = "world"); + log!(lvl; cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}", world = "world"); } - all_log_macros!(target = "my_target"; cat_1 = "chashu", cat_2 = "nori"; "hello {world}", world = "world"); - all_log_macros!(cat_1 = "chashu", cat_2 = "nori"; "hello {world}", world = "world"); + all_log_macros!(target = "my_target"; cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}", world = "world"); + all_log_macros!(cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}", world = "world"); } #[test] @@ -167,7 +167,7 @@ fn kv_expr_context() { #[cfg(feature = "kv_unstable")] fn kv_shadow_target() { all_log_macros!(target = "kv_target"; "hello {}", "world"); - all_log_macros!(target = "kv_target", cat_1 = "chashu", cat_2 = "nori"; "hello {}", "world"); + all_log_macros!(target = "kv_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {}", "world"); } #[rustversion::since(1.58)] @@ -208,12 +208,12 @@ mod implicit_args { let world = "world"; for lvl in log::Level::iter() { - log!(target = "my_target", lvl; cat_1 = "chashu", cat_2 = "nori"; "hello {world}"); + log!(target = "my_target", lvl; cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}"); - log!(lvl; cat_1 = "chashu", cat_2 = "nori"; "hello {world}"); + log!(lvl; cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}"); } - all_log_macros!(target = "my_target"; cat_1 = "chashu", cat_2 = "nori"; "hello {world}"); - all_log_macros!(cat_1 = "chashu", cat_2 = "nori"; "hello {world}"); + all_log_macros!(target = "my_target"; cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}"); + all_log_macros!(cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}"); } } From d6e44eb2539bd27127c7bb666d87b11906a788d0 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Sun, 12 Dec 2021 11:02:50 +1000 Subject: [PATCH 060/280] add an expr test to macros --- tests/macros.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/macros.rs b/tests/macros.rs index 20e905e4a..56dbbf285 100644 --- a/tests/macros.rs +++ b/tests/macros.rs @@ -127,6 +127,19 @@ fn kv_no_args() { all_log_macros!(cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); } +#[test] +#[cfg(feature = "kv_unstable")] +fn kv_expr_args() { + for lvl in log::Level::iter() { + log!(target = "my_target", lvl; cat_math = { let mut x = 0; x += 1; x + 1 }; "hello"); + + log!(lvl; cat_math = { let mut x = 0; x += 1; x + 1 }; "hello"); + } + + all_log_macros!(target = "my_target"; cat_math = { let mut x = 0; x += 1; x + 1 }; "hello"); + all_log_macros!(cat_math = { let mut x = 0; x += 1; x + 1 }; "hello"); +} + #[test] #[cfg(feature = "kv_unstable")] fn kv_anonymous_args() { From 7ed6401b93dd151273859e57b15f96e716f31069 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Sun, 12 Dec 2021 11:13:26 +1000 Subject: [PATCH 061/280] run fmt --- src/kv/value.rs | 20 +++++++++++++++----- tests/macros.rs | 14 +++++++------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/kv/value.rs b/src/kv/value.rs index 727c249ea..c349b8c85 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -40,34 +40,44 @@ impl<'v> ToValue for Value<'v> { /// Get a value from a type implementing `std::fmt::Debug`. #[macro_export] macro_rules! as_debug { - ($capture:expr) => ($crate::kv::Value::from_debug(&$capture)); + ($capture:expr) => { + $crate::kv::Value::from_debug(&$capture) + }; } /// Get a value from a type implementing `std::fmt::Display`. #[macro_export] macro_rules! as_display { - ($capture:expr) => ($crate::kv::Value::from_display(&$capture)); + ($capture:expr) => { + $crate::kv::Value::from_display(&$capture) + }; } /// Get a value from an error. #[cfg(feature = "kv_unstable_std")] #[macro_export] macro_rules! as_error { - ($capture:expr) => ($crate::kv::Value::from_dyn_error(&$capture)); + ($capture:expr) => { + $crate::kv::Value::from_dyn_error(&$capture) + }; } #[cfg(feature = "kv_unstable_serde")] /// Get a value from a type implementing `serde::Serialize`. #[macro_export] macro_rules! as_serde { - ($capture:expr) => ($crate::kv::Value::from_serde(&$capture)); + ($capture:expr) => { + $crate::kv::Value::from_serde(&$capture) + }; } /// Get a value from a type implementing `sval::value::Value`. #[cfg(feature = "kv_unstable_sval")] #[macro_export] macro_rules! as_sval { - ($capture:expr) => ($crate::kv::Value::from_sval(&$capture)); + ($capture:expr) => { + $crate::kv::Value::from_sval(&$capture) + }; } /// A value in a structured key-value pair. diff --git a/tests/macros.rs b/tests/macros.rs index 56dbbf285..3b4dbd3a8 100644 --- a/tests/macros.rs +++ b/tests/macros.rs @@ -190,27 +190,27 @@ mod implicit_args { #[test] fn implicit_named_args() { let world = "world"; - + for lvl in log::Level::iter() { log!(lvl, "hello {world}"); log!(lvl, "hello {world}",); - + log!(target: "my_target", lvl, "hello {world}"); log!(target: "my_target", lvl, "hello {world}",); - + log!(lvl; "hello {world}"); log!(lvl; "hello {world}",); - + log!(target = "my_target", lvl; "hello {world}"); log!(target = "my_target", lvl; "hello {world}",); } - + all_log_macros!("hello {world}"); all_log_macros!("hello {world}",); - + all_log_macros!(target = "my_target"; "hello {world}"); all_log_macros!(target = "my_target"; "hello {world}",); - + all_log_macros!(target: "my_target", "hello {world}"); all_log_macros!(target: "my_target", "hello {world}",); } From 505c255f0a2e0eab946bb5740060d844bd7f2684 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Sun, 12 Dec 2021 11:20:05 +1000 Subject: [PATCH 062/280] try putting attribute on fn --- tests/macros.rs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/tests/macros.rs b/tests/macros.rs index 3b4dbd3a8..11f88503e 100644 --- a/tests/macros.rs +++ b/tests/macros.rs @@ -183,12 +183,10 @@ fn kv_shadow_target() { all_log_macros!(target = "kv_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {}", "world"); } -#[rustversion::since(1.58)] -mod implicit_args { - use super::*; - - #[test] - fn implicit_named_args() { +#[test] +fn implicit_named_args() { + #[rustversion::since(1.58)] + fn _check() { let world = "world"; for lvl in log::Level::iter() { @@ -214,10 +212,13 @@ mod implicit_args { all_log_macros!(target: "my_target", "hello {world}"); all_log_macros!(target: "my_target", "hello {world}",); } +} - #[test] - #[cfg(feature = "kv_unstable")] - fn kv_implicit_named_args() { +#[test] +#[cfg(feature = "kv_unstable")] +fn kv_implicit_named_args() { + #[rustversion::since(1.58)] + fn _check() { let world = "world"; for lvl in log::Level::iter() { From 699afffdc0af9d4801940fa61035edf407ef82bd Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Thu, 23 Dec 2021 15:07:25 +1000 Subject: [PATCH 063/280] revert requirement for target = in kv macros --- src/macros.rs | 71 +++++++++++------------------------- tests/macros.rs | 97 ++++++++++++++++++------------------------------- 2 files changed, 57 insertions(+), 111 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index 24331cc26..d1177c99a 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -29,8 +29,8 @@ /// ``` #[macro_export(local_inner_macros)] macro_rules! log { - // log!(target = "my_target", Level::Info; key1 = 42, key2 = true; "a {} event", "log"); - (target = $target:expr, $lvl:expr; $($key:ident = $value:expr),+; $($arg:tt)+) => ({ + // log!(target: "my_target", Level::Info; key1 = 42, key2 = true; "a {} event", "log"); + (target: $target:expr, $lvl:expr, $($key:ident = $value:expr),+; $($arg:tt)+) => ({ let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { $crate::__private_api_log( @@ -42,8 +42,8 @@ macro_rules! log { } }); - // log!(target = "my_target", Level::Info; "a {} event", "log"); - (target = $target:expr, $lvl:expr; $($arg:tt)+) => ({ + // log!(target: "my_target", Level::Info; "a {} event", "log"); + (target: $target:expr, $lvl:expr, $($arg:tt)+) => ({ let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { $crate::__private_api_log( @@ -55,17 +55,8 @@ macro_rules! log { } }); - // log!(target: "my_target", Level::Info, "a log event") - (target: $target:expr, $lvl:expr, $($arg:tt)+) => (log!(target = $target, $lvl; $($arg)+)); - - // log!(target = "my_target", Level::Info; "a log event") - (target = $target:expr, $lvl:expr; $($arg:tt)+) => (log!(target = $target, $lvl; $($arg)+)); - // log!(Level::Info, "a log event") - ($lvl:expr, $($arg:tt)+) => (log!(target = __log_module_path!(), $lvl; $($arg)+)); - - // log!(Level::Info; "a log event") - ($lvl:expr; $($arg:tt)+) => (log!(target = __log_module_path!(), $lvl; $($arg)+)) + ($lvl:expr, $($arg:tt)+) => (log!(target: __log_module_path!(), $lvl, $($arg)+)); } /// Logs a message at the error level. @@ -84,15 +75,12 @@ macro_rules! log { /// ``` #[macro_export(local_inner_macros)] macro_rules! error { - // error!(target = "my_target"; key1 = 42, key2 = true; "a {} event", "log") - // error!(target = "my_target"; "a {} event", "log") - (target = $target:expr; $($arg:tt)+) => (log!(target = $target, $crate::Level::Error; $($arg)+)); - + // error!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log") // error!(target: "my_target", "a {} event", "log") - (target: $target:expr, $($arg:tt)+) => (log!(target = $target, $crate::Level::Error; $($arg)+)); + (target: $target:expr, $($arg:tt)+) => (log!(target: $target, $crate::Level::Error, $($arg)+)); // error!("a {} event", "log") - ($($arg:tt)+) => (log!($crate::Level::Error; $($arg)+)) + ($($arg:tt)+) => (log!($crate::Level::Error, $($arg)+)) } /// Logs a message at the warn level. @@ -111,15 +99,12 @@ macro_rules! error { /// ``` #[macro_export(local_inner_macros)] macro_rules! warn { - // warn!(target = "my_target"; key1 = 42, key2 = true; "a {} event", "log") - // warn!(target = "my_target"; "a {} event", "log") - (target = $target:expr; $($arg:tt)+) => (log!(target = $target, $crate::Level::Warn; $($arg)+)); - + // warn!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log") // warn!(target: "my_target", "a {} event", "log") - (target: $target:expr, $($arg:tt)+) => (log!(target = $target, $crate::Level::Warn; $($arg)+)); + (target: $target:expr, $($arg:tt)+) => (log!(target: $target, $crate::Level::Warn, $($arg)+)); // warn!("a {} event", "log") - ($($arg:tt)+) => (log!($crate::Level::Warn; $($arg)+)) + ($($arg:tt)+) => (log!($crate::Level::Warn, $($arg)+)) } /// Logs a message at the info level. @@ -140,15 +125,12 @@ macro_rules! warn { /// ``` #[macro_export(local_inner_macros)] macro_rules! info { - // info!(target = "my_target"; key1 = 42, key2 = true; "a {} event", "log") - // info!(target = "my_target"; "a {} event", "log") - (target = $target:expr; $($arg:tt)+) => (log!(target = $target, $crate::Level::Info; $($arg)+)); - + // info!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log") // info!(target: "my_target", "a {} event", "log") - (target: $target:expr, $($arg:tt)+) => (log!(target = $target, $crate::Level::Info; $($arg)+)); + (target: $target:expr, $($arg:tt)+) => (log!(target: $target, $crate::Level::Info, $($arg)+)); // info!("a {} event", "log") - ($($arg:tt)+) => (log!($crate::Level::Info; $($arg)+)) + ($($arg:tt)+) => (log!($crate::Level::Info, $($arg)+)) } /// Logs a message at the debug level. @@ -168,15 +150,12 @@ macro_rules! info { /// ``` #[macro_export(local_inner_macros)] macro_rules! debug { - // debug!(target = "my_target"; key1 = 42, key2 = true; "a {} event", "log") - // debug!(target = "my_target"; "a {} event", "log") - (target = $target:expr; $($arg:tt)+) => (log!(target = $target, $crate::Level::Debug; $($arg)+)); - + // debug!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log") // debug!(target: "my_target", "a {} event", "log") - (target: $target:expr, $($arg:tt)+) => (log!(target = $target, $crate::Level::Debug; $($arg)+)); + (target: $target:expr, $($arg:tt)+) => (log!(target: $target, $crate::Level::Debug, $($arg)+)); // debug!("a {} event", "log") - ($($arg:tt)+) => (log!($crate::Level::Debug; $($arg)+)) + ($($arg:tt)+) => (log!($crate::Level::Debug, $($arg)+)) } /// Logs a message at the trace level. @@ -198,15 +177,12 @@ macro_rules! debug { /// ``` #[macro_export(local_inner_macros)] macro_rules! trace { - // trace!(target = "my_target"; key1 = 42, key2 = true; "a {} event", "log") - // trace!(target = "my_target"; "a {} event", "log") - (target = $target:expr; $($arg:tt)+) => (log!(target = $target, $crate::Level::Trace; $($arg)+)); - + // trace!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log") // trace!(target: "my_target", "a {} event", "log") - (target: $target:expr, $($arg:tt)+) => (log!(target = $target, $crate::Level::Trace; $($arg)+)); + (target: $target:expr, $($arg:tt)+) => (log!(target: $target, $crate::Level::Trace, $($arg)+)); // trace!("a {} event", "log") - ($($arg:tt)+) => (log!($crate::Level::Trace; $($arg)+)) + ($($arg:tt)+) => (log!($crate::Level::Trace, $($arg)+)) } /// Determines if a message logged at the specified level in that module will @@ -237,17 +213,14 @@ macro_rules! trace { /// ``` #[macro_export(local_inner_macros)] macro_rules! log_enabled { - (target = $target:expr, $lvl:expr) => {{ + (target: $target:expr, $lvl:expr) => {{ let lvl = $lvl; lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() && $crate::__private_api_enabled(lvl, $target) }}; - (target: $target:expr, $lvl:expr) => { - log_enabled!(target = $target, $lvl) - }; ($lvl:expr) => { - log_enabled!(target = __log_module_path!(), $lvl) + log_enabled!(target: __log_module_path!(), $lvl) }; } diff --git a/tests/macros.rs b/tests/macros.rs index 11f88503e..5ae94cc75 100644 --- a/tests/macros.rs +++ b/tests/macros.rs @@ -21,19 +21,13 @@ fn no_args() { log!(target: "my_target", lvl, "hello"); log!(target: "my_target", lvl, "hello",); - log!(lvl; "hello"); - log!(lvl; "hello",); - - log!(target = "my_target", lvl; "hello"); - log!(target = "my_target", lvl; "hello",); + log!(lvl, "hello"); + log!(lvl, "hello",); } all_log_macros!("hello"); all_log_macros!("hello",); - all_log_macros!(target = "my_target"; "hello"); - all_log_macros!(target = "my_target"; "hello",); - all_log_macros!(target: "my_target", "hello"); all_log_macros!(target: "my_target", "hello",); } @@ -47,19 +41,13 @@ fn anonymous_args() { log!(target: "my_target", lvl, "hello {}", "world"); log!(target: "my_target", lvl, "hello {}", "world",); - log!(lvl; "hello {}", "world"); - log!(lvl; "hello {}", "world",); - - log!(target = "my_target", lvl; "hello {}", "world"); - log!(target = "my_target", lvl; "hello {}", "world",); + log!(lvl, "hello {}", "world"); + log!(lvl, "hello {}", "world",); } all_log_macros!("hello {}", "world"); all_log_macros!("hello {}", "world",); - all_log_macros!(target = "my_target"; "hello {}", "world"); - all_log_macros!(target = "my_target"; "hello {}", "world",); - all_log_macros!(target: "my_target", "hello {}", "world"); all_log_macros!(target: "my_target", "hello {}", "world",); } @@ -73,19 +61,13 @@ fn named_args() { log!(target: "my_target", lvl, "hello {world}", world = "world"); log!(target: "my_target", lvl, "hello {world}", world = "world",); - log!(lvl; "hello {world}", world = "world"); - log!(lvl; "hello {world}", world = "world",); - - log!(target = "my_target", lvl; "hello {world}", world = "world"); - log!(target = "my_target", lvl; "hello {world}", world = "world",); + log!(lvl, "hello {world}", world = "world"); + log!(lvl, "hello {world}", world = "world",); } all_log_macros!("hello {world}", world = "world"); all_log_macros!("hello {world}", world = "world",); - all_log_macros!(target = "my_target"; "hello {world}", world = "world"); - all_log_macros!(target = "my_target"; "hello {world}", world = "world",); - all_log_macros!(target: "my_target", "hello {world}", world = "world"); all_log_macros!(target: "my_target", "hello {world}", world = "world",); } @@ -98,19 +80,13 @@ fn enabled() { } else { false }; - - let _enabled = if log_enabled!(target = "my_target", lvl) { - true - } else { - false - }; } } #[test] fn expr() { for lvl in log::Level::iter() { - let _ = log!(lvl; "hello"); + let _ = log!(lvl, "hello"); } } @@ -118,12 +94,13 @@ fn expr() { #[cfg(feature = "kv_unstable")] fn kv_no_args() { for lvl in log::Level::iter() { - log!(target = "my_target", lvl; cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); + log!(target: "my_target", lvl, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); - log!(lvl; cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); + log!(lvl, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); } - all_log_macros!(target = "my_target"; cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); + all_log_macros!(target: "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); + all_log_macros!(target = "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); all_log_macros!(cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); } @@ -131,12 +108,14 @@ fn kv_no_args() { #[cfg(feature = "kv_unstable")] fn kv_expr_args() { for lvl in log::Level::iter() { - log!(target = "my_target", lvl; cat_math = { let mut x = 0; x += 1; x + 1 }; "hello"); + log!(target: "my_target", lvl, cat_math = { let mut x = 0; x += 1; x + 1 }; "hello"); - log!(lvl; cat_math = { let mut x = 0; x += 1; x + 1 }; "hello"); + log!(lvl, target = "my_target", cat_math = { let mut x = 0; x += 1; x + 1 }; "hello"); + log!(lvl, cat_math = { let mut x = 0; x += 1; x + 1 }; "hello"); } - all_log_macros!(target = "my_target"; cat_math = { let mut x = 0; x += 1; x + 1 }; "hello"); + all_log_macros!(target: "my_target", cat_math = { let mut x = 0; x += 1; x + 1 }; "hello"); + all_log_macros!(target = "my_target", cat_math = { let mut x = 0; x += 1; x + 1 }; "hello"); all_log_macros!(cat_math = { let mut x = 0; x += 1; x + 1 }; "hello"); } @@ -144,12 +123,14 @@ fn kv_expr_args() { #[cfg(feature = "kv_unstable")] fn kv_anonymous_args() { for lvl in log::Level::iter() { - log!(target = "my_target", lvl; cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {}", "world"); + log!(target: "my_target", lvl, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {}", "world"); + log!(lvl, target = "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {}", "world"); - log!(lvl; cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {}", "world"); + log!(lvl, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {}", "world"); } - all_log_macros!(target = "my_target"; cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {}", "world"); + all_log_macros!(target: "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {}", "world"); + all_log_macros!(target = "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {}", "world"); all_log_macros!(cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {}", "world"); } @@ -157,12 +138,13 @@ fn kv_anonymous_args() { #[cfg(feature = "kv_unstable")] fn kv_named_args() { for lvl in log::Level::iter() { - log!(target = "my_target", lvl; cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}", world = "world"); + log!(target: "my_target", lvl, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}", world = "world"); + log!(lvl, target = "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}", world = "world"); - log!(lvl; cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}", world = "world"); + log!(lvl, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}", world = "world"); } - all_log_macros!(target = "my_target"; cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}", world = "world"); + all_log_macros!(target: "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}", world = "world"); all_log_macros!(cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}", world = "world"); } @@ -171,18 +153,11 @@ fn kv_named_args() { fn kv_expr_context() { match "chashu" { cat_1 => { - info!(target = "target"; cat_1 = cat_1, cat_2 = "nori"; "hello {}", "cats") + info!(target: "target", cat_1 = cat_1, cat_2 = "nori"; "hello {}", "cats") } }; } -#[test] -#[cfg(feature = "kv_unstable")] -fn kv_shadow_target() { - all_log_macros!(target = "kv_target"; "hello {}", "world"); - all_log_macros!(target = "kv_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {}", "world"); -} - #[test] fn implicit_named_args() { #[rustversion::since(1.58)] @@ -196,21 +171,18 @@ fn implicit_named_args() { log!(target: "my_target", lvl, "hello {world}"); log!(target: "my_target", lvl, "hello {world}",); - log!(lvl; "hello {world}"); - log!(lvl; "hello {world}",); - - log!(target = "my_target", lvl; "hello {world}"); - log!(target = "my_target", lvl; "hello {world}",); + log!(lvl, "hello {world}"); + log!(lvl, "hello {world}",); } all_log_macros!("hello {world}"); all_log_macros!("hello {world}",); - all_log_macros!(target = "my_target"; "hello {world}"); - all_log_macros!(target = "my_target"; "hello {world}",); - all_log_macros!(target: "my_target", "hello {world}"); all_log_macros!(target: "my_target", "hello {world}",); + + all_log_macros!(target = "my_target"; "hello {world}"); + all_log_macros!(target = "my_target"; "hello {world}",); } } @@ -222,12 +194,13 @@ fn kv_implicit_named_args() { let world = "world"; for lvl in log::Level::iter() { - log!(target = "my_target", lvl; cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}"); + log!(target: "my_target", lvl, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}"); - log!(lvl; cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}"); + log!(lvl, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}"); } - all_log_macros!(target = "my_target"; cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}"); + all_log_macros!(target: "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}"); + all_log_macros!(target = "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}"); all_log_macros!(cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}"); } } From 26aef64c46e6873e8cac2cb29967e813a0618620 Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Thu, 23 Dec 2021 15:13:42 +1000 Subject: [PATCH 064/280] fix up kv examples --- README.md | 2 +- src/lib.rs | 4 ++-- tests/macros.rs | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c67207f1a..a26192778 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,7 @@ If you enable the `kv_unstable` feature, you can associate structured data with use log::{info, trace, warn, as_serde, as_error}; pub fn shave_the_yak(yak: &mut Yak) { - trace!(target = "yak_events"; yak = as_serde!(yak); "Commencing yak shaving"); + trace!(target = "yak_events", yak = as_serde!(yak); "Commencing yak shaving"); loop { match find_a_razor() { diff --git a/src/lib.rs b/src/lib.rs index 4123a712c..781152a3a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -55,7 +55,7 @@ //! use log::{info, warn}; //! //! pub fn shave_the_yak(yak: &mut Yak) { -//! info!(target = "yak_events"; "Commencing yak shaving for {:?}", yak); +//! info!(target = "yak_events", "Commencing yak shaving for {:?}", yak); //! //! loop { //! match find_a_razor() { @@ -102,7 +102,7 @@ //! use log::{info, warn, as_serde, as_error}; //! //! pub fn shave_the_yak(yak: &mut Yak) { -//! info!(target = "yak_events"; yak = as_serde!(yak); "Commencing yak shaving"); +//! info!(target = "yak_events", yak = as_serde!(yak); "Commencing yak shaving"); //! //! loop { //! match find_a_razor() { diff --git a/tests/macros.rs b/tests/macros.rs index 5ae94cc75..4bb73da52 100644 --- a/tests/macros.rs +++ b/tests/macros.rs @@ -145,6 +145,7 @@ fn kv_named_args() { } all_log_macros!(target: "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}", world = "world"); + all_log_macros!(target = "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}", world = "world"); all_log_macros!(cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}", world = "world"); } From 902d9aa8b5fe4072ca7927a22f49ad2d4914ac44 Mon Sep 17 00:00:00 2001 From: Ziyue Pan Date: Mon, 27 Dec 2021 18:49:10 +0800 Subject: [PATCH 065/280] change url in README to doc.rs --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 8a7c1eea3..d309dc15c 100644 --- a/README.md +++ b/README.md @@ -62,8 +62,8 @@ There are many available implementations to choose from, here are some of the mo * Simple minimal loggers: * [`env_logger`](https://docs.rs/env_logger/*/env_logger/) - * [`simple_logger`](https://github.com/borntyping/rust-simple_logger) - * [`simplelog`](https://github.com/drakulix/simplelog.rs) + * [`simple_logger`](https://docs.rs/simple_logger/*/simple_logger/) + * [`simplelog`](https://docs.rs/simplelog/*/simplelog/) * [`pretty_env_logger`](https://docs.rs/pretty_env_logger/*/pretty_env_logger/) * [`stderrlog`](https://docs.rs/stderrlog/*/stderrlog/) * [`flexi_logger`](https://docs.rs/flexi_logger/*/flexi_logger/) From 9bb4c5d453b79834591a8be31f7c588379aeb4e3 Mon Sep 17 00:00:00 2001 From: Alex Touchet Date: Mon, 27 Dec 2021 16:19:06 -0800 Subject: [PATCH 066/280] Remove outdated Travis CI and AppVeyor references --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index a8bf0abb9..ebfe778b4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,7 +12,7 @@ A lightweight logging facade for Rust """ categories = ["development-tools::debugging"] keywords = ["logging"] -exclude = ["rfcs/**/*", "/.travis.yml", "/appveyor.yml"] +exclude = ["rfcs/**/*"] build = "build.rs" [package.metadata.docs.rs] From 806eb7fbb48a7fc177c63d289c1fcb1545f8a73e Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Thu, 30 Dec 2021 12:12:22 +1000 Subject: [PATCH 067/280] fix up CI --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 781152a3a..373745579 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -55,7 +55,7 @@ //! use log::{info, warn}; //! //! pub fn shave_the_yak(yak: &mut Yak) { -//! info!(target = "yak_events", "Commencing yak shaving for {:?}", yak); +//! info!(target: "yak_events", "Commencing yak shaving for {:?}", yak); //! //! loop { //! match find_a_razor() { @@ -102,7 +102,7 @@ //! use log::{info, warn, as_serde, as_error}; //! //! pub fn shave_the_yak(yak: &mut Yak) { -//! info!(target = "yak_events", yak = as_serde!(yak); "Commencing yak shaving"); +//! info!(target: "yak_events", yak = as_serde!(yak); "Commencing yak shaving"); //! //! loop { //! match find_a_razor() { From 68a7c2a6091cea965fe6ef26faa15056fe08465f Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Fri, 11 Feb 2022 21:08:06 +1000 Subject: [PATCH 068/280] check features with minimal versions --- .github/workflows/main.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 855a2d965..56f694071 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -76,6 +76,22 @@ jobs: - run: cargo build --verbose -Z avoid-dev-deps --features "kv_unstable kv_unstable_std" - run: cargo build --verbose -Z avoid-dev-deps --features "kv_unstable kv_unstable_sval kv_unstable_serde" + features: + name: Minimal versions + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Install Rust + run: | + rustup update nightly --no-self-update + rustup default nightly + - run: cargo build --verbose -Z minimal-versions --features kv_unstable + - run: cargo build --verbose -Z minimal-versions --features "kv_unstable std" + - run: cargo build --verbose -Z minimal-versions --features "kv_unstable kv_unstable_sval" + - run: cargo build --verbose -Z minimal-versions --features "kv_unstable kv_unstable_serde" + - run: cargo build --verbose -Z minimal-versions --features "kv_unstable kv_unstable_std" + - run: cargo build --verbose -Z minimal-versions --features "kv_unstable kv_unstable_sval kv_unstable_serde" + msrv: name: MSRV runs-on: ubuntu-latest From e50ec8669cd6d44fd55f4e1c4afd0795509d3c44 Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Fri, 11 Feb 2022 21:15:38 +1000 Subject: [PATCH 069/280] yaml --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 56f694071..860e9dfe9 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -76,7 +76,7 @@ jobs: - run: cargo build --verbose -Z avoid-dev-deps --features "kv_unstable kv_unstable_std" - run: cargo build --verbose -Z avoid-dev-deps --features "kv_unstable kv_unstable_sval kv_unstable_serde" - features: + minimalv: name: Minimal versions runs-on: ubuntu-latest steps: From 4c6c4c9cf5620f1c8869b07e0f1cd970b7a6e796 Mon Sep 17 00:00:00 2001 From: Kartavya Vashishtha Date: Sat, 19 Feb 2022 10:40:56 +0530 Subject: [PATCH 070/280] docs(readme): add mention to log_err --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 280fc2cbf..443705bf5 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,8 @@ There are many available implementations to choose from, here are some of the mo * [`console_log`](https://docs.rs/console_log/*/console_log/) * For dynamic libraries: * You may need to construct [an FFI-safe wrapper over `log`](https://github.com/rust-lang/log/issues/421) to initialize in your libraries. +* Utilities: + * [`log_err`](https://docs.rs/log_err/*/log_err/) Executables should choose a logger implementation and initialize it early in the runtime of the program. Logger implementations will typically include a From f3b4fde154c0137c611336e4107d889ad661dd06 Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Wed, 23 Feb 2022 08:39:45 +1000 Subject: [PATCH 071/280] prepare for 0.4.15 release --- CHANGELOG.md | 15 ++++++++++++++- Cargo.toml | 2 +- src/lib.rs | 2 +- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b57360e0..c9cb0637a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,18 @@ ## [Unreleased] +## [0.4.15] - 2022-02-23 + +* Silence a warning about the deprecated `spin_loop_hint`. +* Relax ordering in the atomic `set_max_level` call. +* Allow levels to be iterated over. +* Implement `Log` on some common wrapper types. +* Improvements to test coverage. +* Improvements to documentation. +* Add key-value support to the `log!` macros. +* Tighten `kv_unstable` internal dependencies so they don't bump past their current alpha. +* Add a simple visit API to `kv_unstable`. + ## [0.4.14] - 2021-01-27 * Remove the `__private_api_log_lit` special case. @@ -196,7 +208,8 @@ version using log 0.4.x to avoid losing module and file information. Look at the [release tags] for information about older releases. -[Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.14...HEAD +[Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.15...HEAD +[0.4.15]: https://github.com/rust-lang-nursery/log/compare/0.4.13...0.4.15 [0.4.14]: https://github.com/rust-lang-nursery/log/compare/0.4.13...0.4.14 [0.4.13]: https://github.com/rust-lang-nursery/log/compare/0.4.11...0.4.13 [0.4.12]: https://github.com/rust-lang-nursery/log/compare/0.4.11...0.4.12 diff --git a/Cargo.toml b/Cargo.toml index 9e18671ee..dd53e1347 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "log" -version = "0.4.14" # remember to update html_root_url +version = "0.4.15" # remember to update html_root_url authors = ["The Rust Project Developers"] license = "MIT OR Apache-2.0" readme = "README.md" diff --git a/src/lib.rs b/src/lib.rs index 373745579..0bb38fe9f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -313,7 +313,7 @@ #![doc( html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://www.rust-lang.org/favicon.ico", - html_root_url = "https://docs.rs/log/0.4.14" + html_root_url = "https://docs.rs/log/0.4.15" )] #![warn(missing_docs)] #![deny(missing_debug_implementations, unconditional_recursion)] From c626f82520f5da993e2eddbf2b59615df9f03ce6 Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Fri, 25 Feb 2022 11:39:53 +0100 Subject: [PATCH 072/280] Support static string as key value --- src/macros.rs | 13 +++++++++---- tests/macros.rs | 10 ++++++++++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index d1177c99a..ec2f4200c 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -30,14 +30,14 @@ #[macro_export(local_inner_macros)] macro_rules! log { // log!(target: "my_target", Level::Info; key1 = 42, key2 = true; "a {} event", "log"); - (target: $target:expr, $lvl:expr, $($key:ident = $value:expr),+; $($arg:tt)+) => ({ + (target: $target:expr, $lvl:expr, $($key:tt = $value:expr),+; $($arg:tt)+) => ({ let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { $crate::__private_api_log( __log_format_args!($($arg)+), lvl, &($target, __log_module_path!(), __log_file!(), __log_line!()), - Some(&[$((__log_stringify!($key), &$value)),+]) + Some(&[$((__log_key!($key), &$value)),+]) ); } }); @@ -268,8 +268,13 @@ macro_rules! __log_line { #[doc(hidden)] #[macro_export] -macro_rules! __log_stringify { - ($($args:tt)*) => { +macro_rules! __log_key { + // key1 = 42 + ($($args:ident)*) => { stringify!($($args)*) }; + // "key1" = 42 + ($($args:expr)*) => { + $($args)* + }; } diff --git a/tests/macros.rs b/tests/macros.rs index 4bb73da52..7b2483ceb 100644 --- a/tests/macros.rs +++ b/tests/macros.rs @@ -205,3 +205,13 @@ fn kv_implicit_named_args() { all_log_macros!(cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}"); } } + +#[test] +#[cfg(feature = "kv_unstable")] +fn kv_string_keys() { + for lvl in log::Level::iter() { + log!(target: "my_target", lvl, "also dogs" = "Fílos", "key/that-can't/be/an/ident" = "hi"; "hello {world}", world = "world"); + } + + all_log_macros!(target: "my_target", "also dogs" = "Fílos", "key/that-can't/be/an/ident" = "hi"; "hello {world}", world = "world"); +} From 8038ea8f9853361b0f32cb2810e1474327a8aa45 Mon Sep 17 00:00:00 2001 From: Walter Tetzner Date: Sat, 26 Feb 2022 23:26:16 -0600 Subject: [PATCH 073/280] #487 Add thumbv4t-none-eabi to the list of targets that don't support atomics. --- build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.rs b/build.rs index 2b17e0be9..93bfe13f0 100644 --- a/build.rs +++ b/build.rs @@ -33,7 +33,7 @@ fn target_has_atomic_cas(target: &str) -> bool { fn target_has_atomics(target: &str) -> bool { match &target[..] { - "msp430-none-elf" | "riscv32i-unknown-none-elf" | "riscv32imc-unknown-none-elf" => false, + "thumbv4t-none-eabi" | "msp430-none-elf" | "riscv32i-unknown-none-elf" | "riscv32imc-unknown-none-elf" => false, _ => true, } } From cb20e453951733e2bdf9949f6862775a018e7ad8 Mon Sep 17 00:00:00 2001 From: Walter Tetzner Date: Sun, 27 Feb 2022 11:36:27 -0600 Subject: [PATCH 074/280] #487 Fix formatting. --- build.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/build.rs b/build.rs index 93bfe13f0..dd8d4e0f7 100644 --- a/build.rs +++ b/build.rs @@ -33,7 +33,10 @@ fn target_has_atomic_cas(target: &str) -> bool { fn target_has_atomics(target: &str) -> bool { match &target[..] { - "thumbv4t-none-eabi" | "msp430-none-elf" | "riscv32i-unknown-none-elf" | "riscv32imc-unknown-none-elf" => false, + "thumbv4t-none-eabi" + | "msp430-none-elf" + | "riscv32i-unknown-none-elf" + | "riscv32imc-unknown-none-elf" => false, _ => true, } } From 4f9a212aa4f611c9cd192349607846ecb75886a1 Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Sun, 20 Mar 2022 18:20:53 +0100 Subject: [PATCH 075/280] Implement ToValue and From<$ty> for Value for NonZero It can already by be done by calling `.get()`, but this makes it a bit easier. --- src/kv/value.rs | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/kv/value.rs b/src/kv/value.rs index c349b8c85..cb5cb4381 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -483,6 +483,24 @@ macro_rules! impl_to_value_primitive { }; } +macro_rules! impl_to_value_nonzero_primitive { + ($($into_ty:ident,)*) => { + $( + impl ToValue for std::num::$into_ty { + fn to_value(&self) -> Value { + Value::from(self.get()) + } + } + + impl<'v> From for Value<'v> { + fn from(value: std::num::$into_ty) -> Self { + Value::from(value.get()) + } + } + )* + }; +} + macro_rules! impl_value_to_primitive { ($(#[doc = $doc:tt] $into_name:ident -> $into_ty:ty,)*) => { impl<'v> Value<'v> { @@ -500,6 +518,12 @@ impl_to_value_primitive![ usize, u8, u16, u32, u64, u128, isize, i8, i16, i32, i64, i128, f32, f64, char, bool, ]; +#[rustfmt::skip] +impl_to_value_nonzero_primitive![ + NonZeroUsize, NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, + NonZeroIsize, NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, +]; + impl_value_to_primitive![ #[doc = "Try convert this value into a `u64`."] to_u64 -> u64, @@ -720,6 +744,11 @@ pub(crate) mod tests { Value::from(32u32), Value::from(64u64), Value::from(1usize), + Value::from(std::num::NonZeroU8::new(8).unwrap()), + Value::from(std::num::NonZeroU16::new(16).unwrap()), + Value::from(std::num::NonZeroU32::new(32).unwrap()), + Value::from(std::num::NonZeroU64::new(64).unwrap()), + Value::from(std::num::NonZeroUsize::new(1).unwrap()), ] .into_iter() } @@ -731,6 +760,11 @@ pub(crate) mod tests { Value::from(-32i32), Value::from(-64i64), Value::from(-1isize), + Value::from(std::num::NonZeroI8::new(-8).unwrap()), + Value::from(std::num::NonZeroI16::new(-16).unwrap()), + Value::from(std::num::NonZeroI32::new(-32).unwrap()), + Value::from(std::num::NonZeroI64::new(-64).unwrap()), + Value::from(std::num::NonZeroIsize::new(-1).unwrap()), ] .into_iter() } From cf2033684de07a5159b1a57bf7dfbc0ca18d4ee6 Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Tue, 22 Mar 2022 13:17:53 +1000 Subject: [PATCH 076/280] update changelog for 0.4.15 with last minute additions --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c9cb0637a..b5bd5f49b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * Silence a warning about the deprecated `spin_loop_hint`. * Relax ordering in the atomic `set_max_level` call. +* Add thumbv4t-none-eabi to targets that don't support atomics * Allow levels to be iterated over. * Implement `Log` on some common wrapper types. * Improvements to test coverage. @@ -13,6 +14,8 @@ * Add key-value support to the `log!` macros. * Tighten `kv_unstable` internal dependencies so they don't bump past their current alpha. * Add a simple visit API to `kv_unstable`. +* Support `NonZero*` integers as values in structured logging +* Support static strings as keys in structured logging ## [0.4.14] - 2021-01-27 From 0b90513e65da5ecf0aa9fd599b4aaea79f763998 Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Tue, 22 Mar 2022 14:01:09 +0100 Subject: [PATCH 077/280] Fully qualify Some and None --- src/macros.rs | 4 ++-- tests/macros.rs | 13 +++++++++++++ 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index ec2f4200c..a4fe6803b 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -37,7 +37,7 @@ macro_rules! log { __log_format_args!($($arg)+), lvl, &($target, __log_module_path!(), __log_file!(), __log_line!()), - Some(&[$((__log_key!($key), &$value)),+]) + std::option::Option::Some(&[$((__log_key!($key), &$value)),+]) ); } }); @@ -50,7 +50,7 @@ macro_rules! log { __log_format_args!($($arg)+), lvl, &($target, __log_module_path!(), __log_file!(), __log_line!()), - None, + std::option::Option::None, ); } }); diff --git a/tests/macros.rs b/tests/macros.rs index 7b2483ceb..fcd8556a3 100644 --- a/tests/macros.rs +++ b/tests/macros.rs @@ -215,3 +215,16 @@ fn kv_string_keys() { all_log_macros!(target: "my_target", "also dogs" = "Fílos", "key/that-can't/be/an/ident" = "hi"; "hello {world}", world = "world"); } + +/// Some and None (from Option) are used in the macros. +#[derive(Debug)] +enum Type { + Some, + None, +} + +#[test] +fn regression_issue_494() { + use Type::*; + all_log_macros!("some message: {:?}, {:?}", None, Some); +} From 4342193c02e8fe71a72bec853fc235fd20a4d0b1 Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Tue, 22 Mar 2022 23:35:15 +1000 Subject: [PATCH 078/280] prepare for 0.4.16 release --- CHANGELOG.md | 7 ++++++- Cargo.toml | 2 +- src/lib.rs | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b5bd5f49b..8260a9e38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## [Unreleased] +## [0.4.16] - 2022-03-22 + +* Fix a conflict with unqualified `Option` use in macros. + ## [0.4.15] - 2022-02-23 * Silence a warning about the deprecated `spin_loop_hint`. @@ -211,7 +215,8 @@ version using log 0.4.x to avoid losing module and file information. Look at the [release tags] for information about older releases. -[Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.15...HEAD +[Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.16...HEAD +[0.4.16]: https://github.com/rust-lang-nursery/log/compare/0.4.15...0.4.16 [0.4.15]: https://github.com/rust-lang-nursery/log/compare/0.4.13...0.4.15 [0.4.14]: https://github.com/rust-lang-nursery/log/compare/0.4.13...0.4.14 [0.4.13]: https://github.com/rust-lang-nursery/log/compare/0.4.11...0.4.13 diff --git a/Cargo.toml b/Cargo.toml index dd53e1347..63739fa15 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "log" -version = "0.4.15" # remember to update html_root_url +version = "0.4.16" # remember to update html_root_url authors = ["The Rust Project Developers"] license = "MIT OR Apache-2.0" readme = "README.md" diff --git a/src/lib.rs b/src/lib.rs index 0bb38fe9f..e76e2ce96 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -313,7 +313,7 @@ #![doc( html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://www.rust-lang.org/favicon.ico", - html_root_url = "https://docs.rs/log/0.4.15" + html_root_url = "https://docs.rs/log/0.4.16" )] #![warn(missing_docs)] #![deny(missing_debug_implementations, unconditional_recursion)] From 3b243dd2b84b0b9f70a33dd00111823be77d6aac Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Tue, 22 Mar 2022 23:44:12 +1000 Subject: [PATCH 079/280] re-export Option to use in macros --- src/lib.rs | 6 ++++++ src/macros.rs | 4 ++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index e76e2ce96..c7b8a30a8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1625,6 +1625,12 @@ pub fn __private_api_enabled(level: Level, target: &str) -> bool { logger().enabled(&Metadata::builder().level(level).target(target).build()) } +// WARNING: this is not part of the crate's public API and is subject to change at any time +#[doc(hidden)] +pub mod __private_api { + pub use std::option::Option; +} + /// The statically resolved maximum log level. /// /// See the crate level documentation for information on how to configure this. diff --git a/src/macros.rs b/src/macros.rs index a4fe6803b..a1d71d9ca 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -37,7 +37,7 @@ macro_rules! log { __log_format_args!($($arg)+), lvl, &($target, __log_module_path!(), __log_file!(), __log_line!()), - std::option::Option::Some(&[$((__log_key!($key), &$value)),+]) + $crate::__private_api::Option::Some(&[$((__log_key!($key), &$value)),+]) ); } }); @@ -50,7 +50,7 @@ macro_rules! log { __log_format_args!($($arg)+), lvl, &($target, __log_module_path!(), __log_file!(), __log_line!()), - std::option::Option::None, + $crate::__private_api::Option::None, ); } }); From 06380b99cdc46c6ab87fef257dd631f7500dd99f Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Tue, 22 Mar 2022 23:52:16 +1000 Subject: [PATCH 080/280] fully qualify Type import for MSRV --- tests/macros.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/macros.rs b/tests/macros.rs index fcd8556a3..22b7306fd 100644 --- a/tests/macros.rs +++ b/tests/macros.rs @@ -225,6 +225,6 @@ enum Type { #[test] fn regression_issue_494() { - use Type::*; + use self::Type::*; all_log_macros!("some message: {:?}, {:?}", None, Some); } From 3d791f291da1a421d9c85c4aeaea0d087a64ce04 Mon Sep 17 00:00:00 2001 From: Julio Merino Date: Tue, 12 Apr 2022 18:07:44 -0700 Subject: [PATCH 081/280] Add reference to db_logger db_logger is a logging implementation that writes log entries to a database. At the time of this writing, it supports PostgreSQL and SQLite via the sqlx crate. --- README.md | 1 + src/lib.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/README.md b/README.md index 443705bf5..f16da73f3 100644 --- a/README.md +++ b/README.md @@ -76,6 +76,7 @@ There are many available implementations to choose from, here are some of the mo * [`slog-stdlog`](https://docs.rs/slog-stdlog/*/slog_stdlog/) * [`android_log`](https://docs.rs/android_log/*/android_log/) * [`win_dbg_logger`](https://docs.rs/win_dbg_logger/*/win_dbg_logger/) + * [`db_logger`](https://docs.rs/db_logger/*/db_logger/) * For WebAssembly binaries: * [`console_log`](https://docs.rs/console_log/*/console_log/) * For dynamic libraries: diff --git a/src/lib.rs b/src/lib.rs index c7b8a30a8..7043a6f12 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -145,6 +145,7 @@ //! * [systemd-journal-logger] //! * [android_log] //! * [win_dbg_logger] +//! * [db_logger] //! * For WebAssembly binaries: //! * [console_log] //! * For dynamic libraries: From 91d741f014814c72d2e9675479fc9c33880d1af0 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Wed, 20 Apr 2022 16:17:36 +1000 Subject: [PATCH 082/280] upgrade to value-bag 1.0.0-alpha.9 and remove by-value 128bit int conversions --- Cargo.toml | 4 ++-- src/kv/value.rs | 58 ++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 55 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 63739fa15..de310cb17 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -56,11 +56,11 @@ kv_unstable_serde = ["kv_unstable_std", "value-bag/serde", "serde"] cfg-if = "1.0" serde = { version = "1.0", optional = true, default-features = false } sval = { version = "=1.0.0-alpha.5", optional = true, default-features = false } -value-bag = { version = "=1.0.0-alpha.8", optional = true, default-features = false } +value-bag = { version = "=1.0.0-alpha.9", optional = true, default-features = false } [dev-dependencies] rustversion = "1.0" serde = { version = "1.0", features = ["derive"] } serde_test = "1.0" sval = { version = "=1.0.0-alpha.5", features = ["derive"] } -value-bag = { version = "=1.0.0-alpha.8", features = ["test"] } +value-bag = { version = "=1.0.0-alpha.9", features = ["test"] } diff --git a/src/kv/value.rs b/src/kv/value.rs index cb5cb4381..089104ab0 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -441,12 +441,60 @@ impl ToValue for str { } } +impl ToValue for u128 { + fn to_value(&self) -> Value { + Value::from(self) + } +} + +impl ToValue for i128 { + fn to_value(&self) -> Value { + Value::from(self) + } +} + +impl ToValue for std::num::NonZeroU128 { + fn to_value(&self) -> Value { + Value::from(self) + } +} + +impl ToValue for std::num::NonZeroI128 { + fn to_value(&self) -> Value { + Value::from(self) + } +} + impl<'v> From<&'v str> for Value<'v> { fn from(value: &'v str) -> Self { Value::from_value_bag(value) } } +impl<'v> From<&'v u128> for Value<'v> { + fn from(value: &'v u128) -> Self { + Value::from_value_bag(value) + } +} + +impl<'v> From<&'v i128> for Value<'v> { + fn from(value: &'v i128) -> Self { + Value::from_value_bag(value) + } +} + +impl<'v> From<&'v std::num::NonZeroU128> for Value<'v> { + fn from(v: &'v std::num::NonZeroU128) -> Value<'v> { + Value::from_value_bag(unsafe { std::mem::transmute::<&std::num::NonZeroU128, &u128>(v) }) + } +} + +impl<'v> From<&'v std::num::NonZeroI128> for Value<'v> { + fn from(v: &'v std::num::NonZeroI128) -> Value<'v> { + Value::from_value_bag(unsafe { std::mem::transmute::<&std::num::NonZeroI128, &i128>(v) }) + } +} + impl ToValue for () { fn to_value(&self) -> Value { Value::from_value_bag(()) @@ -515,13 +563,13 @@ macro_rules! impl_value_to_primitive { } impl_to_value_primitive![ - usize, u8, u16, u32, u64, u128, isize, i8, i16, i32, i64, i128, f32, f64, char, bool, + usize, u8, u16, u32, u64, isize, i8, i16, i32, i64, f32, f64, char, bool, ]; #[rustfmt::skip] impl_to_value_nonzero_primitive![ - NonZeroUsize, NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, - NonZeroIsize, NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, + NonZeroUsize, NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, + NonZeroIsize, NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, ]; impl_value_to_primitive![ @@ -617,12 +665,12 @@ pub trait Visit<'v> { /// Visit a big unsigned integer. fn visit_u128(&mut self, value: u128) -> Result<(), Error> { - self.visit_any(value.into()) + self.visit_any((&value).into()) } /// Visit a big signed integer. fn visit_i128(&mut self, value: i128) -> Result<(), Error> { - self.visit_any(value.into()) + self.visit_any((&value).into()) } /// Visit a floating point. From bb111eb90de894ee5bde9f9c49a64e732463dfb2 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Wed, 20 Apr 2022 16:27:06 +1000 Subject: [PATCH 083/280] add a macro test with common types --- tests/macros.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/macros.rs b/tests/macros.rs index 22b7306fd..16453786e 100644 --- a/tests/macros.rs +++ b/tests/macros.rs @@ -216,6 +216,28 @@ fn kv_string_keys() { all_log_macros!(target: "my_target", "also dogs" = "Fílos", "key/that-can't/be/an/ident" = "hi"; "hello {world}", world = "world"); } +#[test] +#[cfg(feature = "kv_unstable")] +fn kv_common_value_types() { + all_log_macros!( + u8 = 42u8, + u16 = 42u16, + u32 = 42u32, + u64 = 42u64, + u128 = 42u128, + i8 = -42i8, + i16 = -42i16, + i32 = -42i32, + i64 = -42i64, + i128 = -42i128, + f32 = 4.2f32, + f64 = -4.2f64, + bool = true, + str = "string"; + "hello world" + ); +} + /// Some and None (from Option) are used in the macros. #[derive(Debug)] enum Type { From 6c0a24c82d372ef40e59cc8ba518fb2ffa19668d Mon Sep 17 00:00:00 2001 From: KodrAus Date: Wed, 20 Apr 2022 16:28:54 +1000 Subject: [PATCH 084/280] add safety comments to the by-ref transmute for non-zero nums --- src/kv/value.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/kv/value.rs b/src/kv/value.rs index 089104ab0..63997aef7 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -485,12 +485,14 @@ impl<'v> From<&'v i128> for Value<'v> { impl<'v> From<&'v std::num::NonZeroU128> for Value<'v> { fn from(v: &'v std::num::NonZeroU128) -> Value<'v> { + // SAFETY: `NonZeroU128` and `u128` have the same ABI Value::from_value_bag(unsafe { std::mem::transmute::<&std::num::NonZeroU128, &u128>(v) }) } } impl<'v> From<&'v std::num::NonZeroI128> for Value<'v> { fn from(v: &'v std::num::NonZeroI128) -> Value<'v> { + // SAFETY: `NonZeroI128` and `i128` have the same ABI Value::from_value_bag(unsafe { std::mem::transmute::<&std::num::NonZeroI128, &i128>(v) }) } } From 9efaf029e8479cb5448e4f3eb0fc95f89185f863 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Wed, 20 Apr 2022 16:31:54 +1000 Subject: [PATCH 085/280] run fmt --- src/kv/value.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/kv/value.rs b/src/kv/value.rs index 63997aef7..607bc09a5 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -564,9 +564,7 @@ macro_rules! impl_value_to_primitive { } } -impl_to_value_primitive![ - usize, u8, u16, u32, u64, isize, i8, i16, i32, i64, f32, f64, char, bool, -]; +impl_to_value_primitive![usize, u8, u16, u32, u64, isize, i8, i16, i32, i64, f32, f64, char, bool,]; #[rustfmt::skip] impl_to_value_nonzero_primitive![ From 3ad46118912e688bded55c8eff0cc882cdd6cfc1 Mon Sep 17 00:00:00 2001 From: Marcel Hellwig Date: Wed, 20 Apr 2022 11:43:25 +0200 Subject: [PATCH 086/280] fix markdown links in lib.rs --- src/lib.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 7043a6f12..ff18c6029 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -306,10 +306,10 @@ //! [slog-stdlog]: https://docs.rs/slog-stdlog/*/slog_stdlog/ //! [log4rs]: https://docs.rs/log4rs/*/log4rs/ //! [fern]: https://docs.rs/fern/*/fern/ -//! [systemd-journal-logger]: (https://docs.rs/systemd-journal-logger/*/systemd_journal_logger/) -//! [android_log]: (https://docs.rs/android_log/*/android_log/) -//! [win_dbg_logger]: (https://docs.rs/win_dbg_logger/*/win_dbg_logger/) -//! [console_log]: (https://docs.rs/console_log/*/console_log/) +//! [systemd-journal-logger]: https://docs.rs/systemd-journal-logger/*/systemd_journal_logger/ +//! [android_log]: https://docs.rs/android_log/*/android_log/ +//! [win_dbg_logger]: https://docs.rs/win_dbg_logger/*/win_dbg_logger/ +//! [console_log]: https://docs.rs/console_log/*/console_log/ #![doc( html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", From c9284a68426fbe4c009507a03a313f5a20c40085 Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Wed, 20 Apr 2022 20:53:51 +1000 Subject: [PATCH 087/280] note that Log implementors should call enabled --- src/lib.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index ff18c6029..1c0703351 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1273,6 +1273,12 @@ pub trait Log: Sync + Send { /// This is used by the `log_enabled!` macro to allow callers to avoid /// expensive computation of log message arguments if the message would be /// discarded anyway. + /// + /// # For implementors + /// + /// This method isn't called automatically by the `log!` macros. + /// It's up to an implementation of the `Log` trait to call `enabled` in its own + /// `log` method implementation to guarantee that filtering is applied. fn enabled(&self, metadata: &Metadata) -> bool; /// Logs the `Record`. From c9049be6165f8231eb1145023748be372640640e Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Fri, 29 Apr 2022 08:42:34 +1000 Subject: [PATCH 088/280] make notes for implementors consistent --- src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 1c0703351..4e979c497 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1283,6 +1283,8 @@ pub trait Log: Sync + Send { /// Logs the `Record`. /// + /// # For implementors + /// /// Note that `enabled` is *not* necessarily called before this method. /// Implementations of `log` should perform all necessary filtering /// internally. From 518821e0fc6c3f6c365fb73b41a287fe64f6a8ed Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Fri, 29 Apr 2022 09:02:57 +1000 Subject: [PATCH 089/280] prepare for 0.4.17 release --- CHANGELOG.md | 7 ++++++- Cargo.toml | 2 +- src/lib.rs | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8260a9e38..6c697fa93 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## [Unreleased] +## [0.4.17] - 2022-04-29 + +* Update `kv_unstable` internal dependencies. + ## [0.4.16] - 2022-03-22 * Fix a conflict with unqualified `Option` use in macros. @@ -215,7 +219,8 @@ version using log 0.4.x to avoid losing module and file information. Look at the [release tags] for information about older releases. -[Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.16...HEAD +[Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.17...HEAD +[0.4.17]: https://github.com/rust-lang-nursery/log/compare/0.4.16...0.4.17 [0.4.16]: https://github.com/rust-lang-nursery/log/compare/0.4.15...0.4.16 [0.4.15]: https://github.com/rust-lang-nursery/log/compare/0.4.13...0.4.15 [0.4.14]: https://github.com/rust-lang-nursery/log/compare/0.4.13...0.4.14 diff --git a/Cargo.toml b/Cargo.toml index de310cb17..cf54ce142 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "log" -version = "0.4.16" # remember to update html_root_url +version = "0.4.17" # remember to update html_root_url authors = ["The Rust Project Developers"] license = "MIT OR Apache-2.0" readme = "README.md" diff --git a/src/lib.rs b/src/lib.rs index 4e979c497..93830bbca 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -314,7 +314,7 @@ #![doc( html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://www.rust-lang.org/favicon.ico", - html_root_url = "https://docs.rs/log/0.4.16" + html_root_url = "https://docs.rs/log/0.4.17" )] #![warn(missing_docs)] #![deny(missing_debug_implementations, unconditional_recursion)] From cc6e9caf25414d6d46f54f2a09b46b3ae813e4f9 Mon Sep 17 00:00:00 2001 From: Marcel Hellwig Date: Mon, 30 May 2022 16:11:12 +0200 Subject: [PATCH 090/280] fix markdown links (again) --- src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib.rs b/src/lib.rs index 93830bbca..22c1afc39 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -309,6 +309,7 @@ //! [systemd-journal-logger]: https://docs.rs/systemd-journal-logger/*/systemd_journal_logger/ //! [android_log]: https://docs.rs/android_log/*/android_log/ //! [win_dbg_logger]: https://docs.rs/win_dbg_logger/*/win_dbg_logger/ +//! [db_logger]: https://docs.rs/db_logger/*/db_logger/ //! [console_log]: https://docs.rs/console_log/*/console_log/ #![doc( From 0521b3f7c47b0a109fb3e161ed796f53005ba726 Mon Sep 17 00:00:00 2001 From: Marcel Hellwig Date: Tue, 31 May 2022 14:05:56 +0200 Subject: [PATCH 091/280] add clippy toml with msrv = 1.31 --- clippy.toml | 1 + 1 file changed, 1 insertion(+) create mode 100644 clippy.toml diff --git a/clippy.toml b/clippy.toml new file mode 100644 index 000000000..3d30690f1 --- /dev/null +++ b/clippy.toml @@ -0,0 +1 @@ +msrv = "1.31.0" From 4b52024d747f0aa1c2bcc97ba6fc550f5d64847c Mon Sep 17 00:00:00 2001 From: Marcel Hellwig Date: Tue, 31 May 2022 14:06:04 +0200 Subject: [PATCH 092/280] apply clippy lints --- build.rs | 4 +- src/kv/key.rs | 41 +----------- src/lib.rs | 162 ++++++----------------------------------------- tests/filters.rs | 10 +-- tests/macros.rs | 8 +-- 5 files changed, 29 insertions(+), 196 deletions(-) diff --git a/build.rs b/build.rs index dd8d4e0f7..11c26a333 100644 --- a/build.rs +++ b/build.rs @@ -22,7 +22,7 @@ fn main() { } fn target_has_atomic_cas(target: &str) -> bool { - match &target[..] { + match target { "thumbv6m-none-eabi" | "msp430-none-elf" | "riscv32i-unknown-none-elf" @@ -32,7 +32,7 @@ fn target_has_atomic_cas(target: &str) -> bool { } fn target_has_atomics(target: &str) -> bool { - match &target[..] { + match target { "thumbv4t-none-eabi" | "msp430-none-elf" | "riscv32i-unknown-none-elf" diff --git a/src/kv/key.rs b/src/kv/key.rs index 762e08dcb..eda5288a3 100644 --- a/src/kv/key.rs +++ b/src/kv/key.rs @@ -1,9 +1,7 @@ //! Structured keys. use std::borrow::Borrow; -use std::cmp; use std::fmt; -use std::hash; /// A type that can be converted into a [`Key`](struct.Key.html). pub trait ToKey { @@ -33,7 +31,7 @@ impl ToKey for str { } /// A key in a structured key-value pair. -#[derive(Clone)] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Key<'k> { key: &'k str, } @@ -41,7 +39,7 @@ pub struct Key<'k> { impl<'k> Key<'k> { /// Get a key from a borrowed string. pub fn from_str(key: &'k str) -> Self { - Key { key: key } + Key { key } } /// Get a borrowed string from this key. @@ -50,47 +48,12 @@ impl<'k> Key<'k> { } } -impl<'k> fmt::Debug for Key<'k> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.key.fmt(f) - } -} - impl<'k> fmt::Display for Key<'k> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.key.fmt(f) } } -impl<'k> hash::Hash for Key<'k> { - fn hash(&self, state: &mut H) - where - H: hash::Hasher, - { - self.as_str().hash(state) - } -} - -impl<'k, 'ko> PartialEq> for Key<'k> { - fn eq(&self, other: &Key<'ko>) -> bool { - self.as_str().eq(other.as_str()) - } -} - -impl<'k> Eq for Key<'k> {} - -impl<'k, 'ko> PartialOrd> for Key<'k> { - fn partial_cmp(&self, other: &Key<'ko>) -> Option { - self.as_str().partial_cmp(other.as_str()) - } -} - -impl<'k> Ord for Key<'k> { - fn cmp(&self, other: &Self) -> cmp::Ordering { - self.as_str().cmp(other.as_str()) - } -} - impl<'k> AsRef for Key<'k> { fn as_ref(&self) -> &str { self.as_str() diff --git a/src/lib.rs b/src/lib.rs index 7043a6f12..2127f4805 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -421,7 +421,7 @@ static LEVEL_PARSE_ERROR: &str = /// [`log!`](macro.log.html), and comparing a `Level` directly to a /// [`LevelFilter`](enum.LevelFilter.html). #[repr(usize)] -#[derive(Copy, Eq, Debug, Hash)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] pub enum Level { /// The "error" level. /// @@ -448,20 +448,6 @@ pub enum Level { Trace, } -impl Clone for Level { - #[inline] - fn clone(&self) -> Level { - *self - } -} - -impl PartialEq for Level { - #[inline] - fn eq(&self, other: &Level) -> bool { - *self as usize == *other as usize - } -} - impl PartialEq for Level { #[inline] fn eq(&self, other: &LevelFilter) -> bool { @@ -469,65 +455,11 @@ impl PartialEq for Level { } } -impl PartialOrd for Level { - #[inline] - fn partial_cmp(&self, other: &Level) -> Option { - Some(self.cmp(other)) - } - - #[inline] - fn lt(&self, other: &Level) -> bool { - (*self as usize) < *other as usize - } - - #[inline] - fn le(&self, other: &Level) -> bool { - *self as usize <= *other as usize - } - - #[inline] - fn gt(&self, other: &Level) -> bool { - *self as usize > *other as usize - } - - #[inline] - fn ge(&self, other: &Level) -> bool { - *self as usize >= *other as usize - } -} - impl PartialOrd for Level { #[inline] fn partial_cmp(&self, other: &LevelFilter) -> Option { Some((*self as usize).cmp(&(*other as usize))) } - - #[inline] - fn lt(&self, other: &LevelFilter) -> bool { - (*self as usize) < *other as usize - } - - #[inline] - fn le(&self, other: &LevelFilter) -> bool { - *self as usize <= *other as usize - } - - #[inline] - fn gt(&self, other: &LevelFilter) -> bool { - *self as usize > *other as usize - } - - #[inline] - fn ge(&self, other: &LevelFilter) -> bool { - *self as usize >= *other as usize - } -} - -impl Ord for Level { - #[inline] - fn cmp(&self, other: &Level) -> cmp::Ordering { - (*self as usize).cmp(&(*other as usize)) - } } fn ok_or(t: Option, e: E) -> Result { @@ -637,7 +569,7 @@ impl Level { /// [`max_level()`]: fn.max_level.html /// [`set_max_level`]: fn.set_max_level.html #[repr(usize)] -#[derive(Copy, Eq, Debug, Hash)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] pub enum LevelFilter { /// A level lower than all log levels. Off, @@ -653,22 +585,6 @@ pub enum LevelFilter { Trace, } -// Deriving generates terrible impls of these traits - -impl Clone for LevelFilter { - #[inline] - fn clone(&self) -> LevelFilter { - *self - } -} - -impl PartialEq for LevelFilter { - #[inline] - fn eq(&self, other: &LevelFilter) -> bool { - *self as usize == *other as usize - } -} - impl PartialEq for LevelFilter { #[inline] fn eq(&self, other: &Level) -> bool { @@ -676,65 +592,11 @@ impl PartialEq for LevelFilter { } } -impl PartialOrd for LevelFilter { - #[inline] - fn partial_cmp(&self, other: &LevelFilter) -> Option { - Some(self.cmp(other)) - } - - #[inline] - fn lt(&self, other: &LevelFilter) -> bool { - (*self as usize) < *other as usize - } - - #[inline] - fn le(&self, other: &LevelFilter) -> bool { - *self as usize <= *other as usize - } - - #[inline] - fn gt(&self, other: &LevelFilter) -> bool { - *self as usize > *other as usize - } - - #[inline] - fn ge(&self, other: &LevelFilter) -> bool { - *self as usize >= *other as usize - } -} - impl PartialOrd for LevelFilter { #[inline] fn partial_cmp(&self, other: &Level) -> Option { Some((*self as usize).cmp(&(*other as usize))) } - - #[inline] - fn lt(&self, other: &Level) -> bool { - (*self as usize) < *other as usize - } - - #[inline] - fn le(&self, other: &Level) -> bool { - *self as usize <= *other as usize - } - - #[inline] - fn gt(&self, other: &Level) -> bool { - *self as usize > *other as usize - } - - #[inline] - fn ge(&self, other: &Level) -> bool { - *self as usize >= *other as usize - } -} - -impl Ord for LevelFilter { - #[inline] - fn cmp(&self, other: &LevelFilter) -> cmp::Ordering { - (*self as usize).cmp(&(*other as usize)) - } } impl FromStr for LevelFilter { @@ -1142,6 +1004,12 @@ impl<'a> RecordBuilder<'a> { } } +impl<'a> Default for RecordBuilder<'a> { + fn default() -> Self { + Self::new() + } +} + /// Metadata about a log message. /// /// # Use @@ -1265,6 +1133,12 @@ impl<'a> MetadataBuilder<'a> { } } +impl<'a> Default for MetadataBuilder<'a> { + fn default() -> Self { + Self::new() + } +} + /// A trait encapsulating the operations required of a logger. pub trait Log: Sync + Send { /// Determines if a log message with the specified metadata would be @@ -1307,10 +1181,10 @@ where } fn log(&self, record: &Record) { - (**self).log(record) + (**self).log(record); } fn flush(&self) { - (**self).flush() + (**self).flush(); } } @@ -1355,7 +1229,7 @@ where /// Note that `Trace` is the maximum level, because it provides the maximum amount of detail in the emitted logs. #[inline] pub fn set_max_level(level: LevelFilter) { - MAX_LOG_LEVEL_FILTER.store(level as usize, Ordering::Relaxed) + MAX_LOG_LEVEL_FILTER.store(level as usize, Ordering::Relaxed); } /// Returns the current maximum log level. @@ -1546,7 +1420,7 @@ impl error::Error for SetLoggerError {} /// /// [`from_str`]: https://doc.rust-lang.org/std/str/trait.FromStr.html#tymethod.from_str #[allow(missing_copy_implementations)] -#[derive(Debug, PartialEq)] +#[derive(Debug, PartialEq, Eq)] pub struct ParseLevelError(()); impl fmt::Display for ParseLevelError { diff --git a/tests/filters.rs b/tests/filters.rs index 66d6f8cd0..fbbc435d8 100644 --- a/tests/filters.rs +++ b/tests/filters.rs @@ -69,15 +69,15 @@ fn main() { fn test(a: &State, filter: LevelFilter) { log::set_max_level(filter); error!(""); - last(&a, t(Level::Error, filter)); + last(a, t(Level::Error, filter)); warn!(""); - last(&a, t(Level::Warn, filter)); + last(a, t(Level::Warn, filter)); info!(""); - last(&a, t(Level::Info, filter)); + last(a, t(Level::Info, filter)); debug!(""); - last(&a, t(Level::Debug, filter)); + last(a, t(Level::Debug, filter)); trace!(""); - last(&a, t(Level::Trace, filter)); + last(a, t(Level::Trace, filter)); fn t(lvl: Level, filter: LevelFilter) -> Option { if lvl <= filter { diff --git a/tests/macros.rs b/tests/macros.rs index 22b7306fd..c48b16d26 100644 --- a/tests/macros.rs +++ b/tests/macros.rs @@ -75,18 +75,14 @@ fn named_args() { #[test] fn enabled() { for lvl in log::Level::iter() { - let _enabled = if log_enabled!(target: "my_target", lvl) { - true - } else { - false - }; + let _enabled = log_enabled!(target: "my_target", lvl); } } #[test] fn expr() { for lvl in log::Level::iter() { - let _ = log!(lvl, "hello"); + log!(lvl, "hello"); } } From b4a064c49f7b7ed6b0501347cada87c447db9964 Mon Sep 17 00:00:00 2001 From: Marcel Hellwig Date: Tue, 31 May 2022 14:12:46 +0200 Subject: [PATCH 093/280] add clippy to github workflow --- .github/workflows/main.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 860e9dfe9..2f6eeebe0 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -60,6 +60,18 @@ jobs: rustup component add rustfmt - run: cargo fmt -- --check + clippy: + name: Clippy + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Install Rust + run: | + rustup update stable --no-self-update + rustup default stable + rustup component add clippy + - run: cargo clippy --verbose + features: name: Feature check runs-on: ubuntu-latest From e0e4fd7bcba8be4304b913bd9424899b0b4f39ef Mon Sep 17 00:00:00 2001 From: Marcel Hellwig Date: Tue, 31 May 2022 13:12:18 +0200 Subject: [PATCH 094/280] add cargo doc to workflow --- .github/workflows/main.yml | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 860e9dfe9..30b366767 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -32,7 +32,7 @@ jobs: rust: stable-x86_64-gnu steps: - uses: actions/checkout@master - - name: Install Rust (rustup) + - name: Install Rust run: | rustup update ${{ matrix.rust }} --no-self-update rustup default ${{ matrix.rust }} @@ -60,6 +60,19 @@ jobs: rustup component add rustfmt - run: cargo fmt -- --check + doc: + name: Check Documentation + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - name: Install Rust + run: | + rustup update stable --no-self-update + rustup default stable + rustup component add rust-docs + - name: Run rustdoc + run: RUSTDOCFLAGS="-D warnings" cargo doc --verbose --all-features + features: name: Feature check runs-on: ubuntu-latest From e68fa19bc15af13b0d5f6522fe80d9a6c6c0771c Mon Sep 17 00:00:00 2001 From: Marcel Hellwig Date: Wed, 1 Jun 2022 07:44:33 +0200 Subject: [PATCH 095/280] clarify comment about derive impls Co-authored-by: Ashley Mannix --- src/kv/key.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/kv/key.rs b/src/kv/key.rs index eda5288a3..a35338dcc 100644 --- a/src/kv/key.rs +++ b/src/kv/key.rs @@ -31,6 +31,8 @@ impl ToKey for str { } /// A key in a structured key-value pair. +// These impls must only be based on the as_str() representation of the key +// If a new field (such as an optional index) is added to the key they must not affect comparison #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Key<'k> { key: &'k str, From 975d38a75a39b32149ac84d6b540e074b110d9ae Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Thu, 9 Jun 2022 08:50:25 +0900 Subject: [PATCH 096/280] Replace ad-hoc eq_ignore_ascii_case with slice::eq_ignore_ascii_case The latter has been available since rust 1.23.0. --- src/lib.rs | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 22c1afc39..fa334fe54 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -538,32 +538,13 @@ fn ok_or(t: Option, e: E) -> Result { } } -// Reimplemented here because std::ascii is not available in libcore -fn eq_ignore_ascii_case(a: &str, b: &str) -> bool { - fn to_ascii_uppercase(c: u8) -> u8 { - if c >= b'a' && c <= b'z' { - c - b'a' + b'A' - } else { - c - } - } - - if a.len() == b.len() { - a.bytes() - .zip(b.bytes()) - .all(|(a, b)| to_ascii_uppercase(a) == to_ascii_uppercase(b)) - } else { - false - } -} - impl FromStr for Level { type Err = ParseLevelError; fn from_str(level: &str) -> Result { ok_or( LOG_LEVEL_NAMES .iter() - .position(|&name| eq_ignore_ascii_case(name, level)) + .position(|&name| name.eq_ignore_ascii_case(level)) .into_iter() .filter(|&idx| idx != 0) .map(|idx| Level::from_usize(idx).unwrap()) @@ -744,7 +725,7 @@ impl FromStr for LevelFilter { ok_or( LOG_LEVEL_NAMES .iter() - .position(|&name| eq_ignore_ascii_case(name, level)) + .position(|&name| name.eq_ignore_ascii_case(level)) .map(|p| LevelFilter::from_usize(p).unwrap()), ParseLevelError(()), ) From 7e2dde2c0f195eb998449e411bf48ca5dfa1fdfe Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Wed, 31 Aug 2022 20:34:34 +1000 Subject: [PATCH 097/280] fix up windows targets --- .github/workflows/main.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9e7e651cd..47b2b2f5e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -23,13 +23,13 @@ jobs: rust: stable - build: win32 os: windows-latest - rust: stable-i686 + rust: stable-i686-pc-windows-msvc - build: win64 os: windows-latest - rust: stable-x86_64 + rust: stable-x86_64-pc-windows-msvc - build: mingw os: windows-latest - rust: stable-x86_64-gnu + rust: stable-x86_64-pc-windows-gnu steps: - uses: actions/checkout@master - name: Install Rust From 25683a8face1cd2c619a1989f83826d130181319 Mon Sep 17 00:00:00 2001 From: jiangying Date: Wed, 14 Sep 2022 09:45:38 +0800 Subject: [PATCH 098/280] typo fix --- src/macros.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/macros.rs b/src/macros.rs index a1d71d9ca..614961ff7 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -119,7 +119,7 @@ macro_rules! warn { /// let conn_info = Connection { port: 40, speed: 3.20 }; /// /// info!("Connected to port {} at {} Mb/s", conn_info.port, conn_info.speed); -/// info!(target: "connection_events", "Successfull connection, port: {}, speed: {}", +/// info!(target: "connection_events", "Successful connection, port: {}, speed: {}", /// conn_info.port, conn_info.speed); /// # } /// ``` From 2cf735473aec3970031f44c8578f1ba750ed0ace Mon Sep 17 00:00:00 2001 From: ErikWDev Date: Sat, 26 Nov 2022 16:57:36 +0100 Subject: [PATCH 099/280] Remove dependency on cfg_if --- Cargo.toml | 1 - src/lib.rs | 54 ++++++++++++++++++++++++++---------------------------- 2 files changed, 26 insertions(+), 29 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index cf54ce142..909b29c0c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,7 +53,6 @@ kv_unstable_std = ["std", "kv_unstable", "value-bag/error"] kv_unstable_serde = ["kv_unstable_std", "value-bag/serde", "serde"] [dependencies] -cfg-if = "1.0" serde = { version = "1.0", optional = true, default-features = false } sval = { version = "=1.0.0-alpha.5", optional = true, default-features = false } value-bag = { version = "=1.0.0-alpha.9", optional = true, default-features = false } diff --git a/src/lib.rs b/src/lib.rs index 42a3d77d2..4738fb965 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -328,9 +328,6 @@ #[cfg(all(not(feature = "std"), not(test)))] extern crate core as std; -#[macro_use] -extern crate cfg_if; - use std::cmp; #[cfg(feature = "std")] use std::error; @@ -1507,33 +1504,34 @@ pub mod __private_api { /// [`logger`]: fn.logger.html pub const STATIC_MAX_LEVEL: LevelFilter = MAX_LEVEL_INNER; -cfg_if! { - if #[cfg(all(not(debug_assertions), feature = "release_max_level_off"))] { - const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Off; - } else if #[cfg(all(not(debug_assertions), feature = "release_max_level_error"))] { - const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Error; - } else if #[cfg(all(not(debug_assertions), feature = "release_max_level_warn"))] { - const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Warn; - } else if #[cfg(all(not(debug_assertions), feature = "release_max_level_info"))] { - const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Info; - } else if #[cfg(all(not(debug_assertions), feature = "release_max_level_debug"))] { - const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Debug; - } else if #[cfg(all(not(debug_assertions), feature = "release_max_level_trace"))] { - const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Trace; - } else if #[cfg(feature = "max_level_off")] { - const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Off; - } else if #[cfg(feature = "max_level_error")] { - const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Error; - } else if #[cfg(feature = "max_level_warn")] { - const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Warn; - } else if #[cfg(feature = "max_level_info")] { - const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Info; - } else if #[cfg(feature = "max_level_debug")] { - const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Debug; +#[rustfmt::skip] +const MAX_LEVEL_INNER: LevelFilter = { + if cfg!(all(not(debug_assertions), feature = "release_max_level_off")) { + LevelFilter::Off + } else if cfg!(all(not(debug_assertions), feature = "release_max_level_error")) { + LevelFilter::Error + } else if cfg!(all(not(debug_assertions), feature = "release_max_level_warn")) { + LevelFilter::Warn + } else if cfg!(all(not(debug_assertions), feature = "release_max_level_info")) { + LevelFilter::Info + } else if cfg!(all(not(debug_assertions), feature = "release_max_level_debug")) { + LevelFilter::Debug + } else if cfg!(all(not(debug_assertions), feature = "release_max_level_trace")) { + LevelFilter::Trace + } else if cfg!(feature = "max_level_off") { + LevelFilter::Off + } else if cfg!(feature = "max_level_error") { + LevelFilter::Error + } else if cfg!(feature = "max_level_warn") { + LevelFilter::Warn + } else if cfg!(feature = "max_level_info") { + LevelFilter::Info + } else if cfg!(feature = "max_level_debug") { + LevelFilter::Debug } else { - const MAX_LEVEL_INNER: LevelFilter = LevelFilter::Trace; + LevelFilter::Trace } -} +}; #[cfg(test)] mod tests { From 969281ea142007570742838402b8dff765f31148 Mon Sep 17 00:00:00 2001 From: ErikWDev Date: Sat, 26 Nov 2022 18:04:01 +0100 Subject: [PATCH 100/280] Ensure removal of cfg_if is compatible with MSRV --- src/lib.rs | 77 ++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 51 insertions(+), 26 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 4738fb965..732637801 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1504,34 +1504,59 @@ pub mod __private_api { /// [`logger`]: fn.logger.html pub const STATIC_MAX_LEVEL: LevelFilter = MAX_LEVEL_INNER; -#[rustfmt::skip] -const MAX_LEVEL_INNER: LevelFilter = { - if cfg!(all(not(debug_assertions), feature = "release_max_level_off")) { - LevelFilter::Off - } else if cfg!(all(not(debug_assertions), feature = "release_max_level_error")) { - LevelFilter::Error - } else if cfg!(all(not(debug_assertions), feature = "release_max_level_warn")) { - LevelFilter::Warn - } else if cfg!(all(not(debug_assertions), feature = "release_max_level_info")) { - LevelFilter::Info - } else if cfg!(all(not(debug_assertions), feature = "release_max_level_debug")) { - LevelFilter::Debug - } else if cfg!(all(not(debug_assertions), feature = "release_max_level_trace")) { - LevelFilter::Trace - } else if cfg!(feature = "max_level_off") { - LevelFilter::Off - } else if cfg!(feature = "max_level_error") { - LevelFilter::Error - } else if cfg!(feature = "max_level_warn") { - LevelFilter::Warn - } else if cfg!(feature = "max_level_info") { - LevelFilter::Info - } else if cfg!(feature = "max_level_debug") { - LevelFilter::Debug - } else { +const MAX_LEVEL_INNER: LevelFilter = get_max_level_inner(); + +const fn get_max_level_inner() -> LevelFilter { + #[allow(unreachable_code)] + { + #[cfg(all(not(debug_assertions), feature = "release_max_level_off"))] + { + return LevelFilter::Off; + } + #[cfg(all(not(debug_assertions), feature = "release_max_level_error"))] + { + return LevelFilter::Error; + } + #[cfg(all(not(debug_assertions), feature = "release_max_level_warn"))] + { + return LevelFilter::Warn; + } + #[cfg(all(not(debug_assertions), feature = "release_max_level_info"))] + { + return LevelFilter::Info; + } + #[cfg(all(not(debug_assertions), feature = "release_max_level_debug"))] + { + return LevelFilter::Debug; + } + #[cfg(all(not(debug_assertions), feature = "release_max_level_trace"))] + { + return LevelFilter::Trace; + } + #[cfg(feature = "max_level_off")] + { + return LevelFilter::Off; + } + #[cfg(feature = "max_level_error")] + { + return LevelFilter::Error; + } + #[cfg(feature = "max_level_warn")] + { + return LevelFilter::Warn; + } + #[cfg(feature = "max_level_info")] + { + return LevelFilter::Info; + } + #[cfg(feature = "max_level_debug")] + { + return LevelFilter::Debug; + } + LevelFilter::Trace } -}; +} #[cfg(test)] mod tests { From 609dc67da96a5d317ca7776845f6174f404c7c74 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 8 Dec 2022 19:39:36 +0200 Subject: [PATCH 101/280] build: harden main.yml permissions Signed-off-by: Alex --- .github/workflows/main.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 47b2b2f5e..783b5052d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,6 +1,9 @@ name: CI on: [push, pull_request] +permissions: + contents: read # to fetch code (actions/checkout) + jobs: test: name: Test From f78217de018ceabba039693fb419effa3746a914 Mon Sep 17 00:00:00 2001 From: Alex Touchet Date: Fri, 16 Dec 2022 16:51:11 -0800 Subject: [PATCH 102/280] Fix build status badge --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f16da73f3..5adff6bd7 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ log A Rust library providing a lightweight logging *facade*. -[![Build status](https://img.shields.io/github/workflow/status/rust-lang/log/CI/master)](https://github.com/rust-lang/log/actions) +[![Build status](https://img.shields.io/github/actions/workflow/status/rust-lang/log/main.yml?branch=master)](https://github.com/rust-lang/log/actions) [![Latest version](https://img.shields.io/crates/v/log.svg)](https://crates.io/crates/log) [![Documentation](https://docs.rs/log/badge.svg)](https://docs.rs/log) ![License](https://img.shields.io/crates/l/log.svg) From 7f09d72e5fd5387c672b9803ead6548b45920f55 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 6 Jan 2023 16:28:51 +0100 Subject: [PATCH 103/280] Remove build.rs file --- Cargo.toml | 1 - build.rs | 46 ---------------------------------------------- src/lib.rs | 20 ++++++++++---------- 3 files changed, 10 insertions(+), 57 deletions(-) delete mode 100644 build.rs diff --git a/Cargo.toml b/Cargo.toml index 909b29c0c..f4e944942 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,6 @@ A lightweight logging facade for Rust categories = ["development-tools::debugging"] keywords = ["logging"] exclude = ["rfcs/**/*"] -build = "build.rs" [package.metadata.docs.rs] features = ["std", "serde", "kv_unstable_std", "kv_unstable_sval", "kv_unstable_serde"] diff --git a/build.rs b/build.rs deleted file mode 100644 index 11c26a333..000000000 --- a/build.rs +++ /dev/null @@ -1,46 +0,0 @@ -//! This build script detects target platforms that lack proper support for -//! atomics and sets `cfg` flags accordingly. - -use std::env; -use std::str; - -fn main() { - let target = match rustc_target() { - Some(target) => target, - None => return, - }; - - if target_has_atomic_cas(&target) { - println!("cargo:rustc-cfg=atomic_cas"); - } - - if target_has_atomics(&target) { - println!("cargo:rustc-cfg=has_atomics"); - } - - println!("cargo:rerun-if-changed=build.rs"); -} - -fn target_has_atomic_cas(target: &str) -> bool { - match target { - "thumbv6m-none-eabi" - | "msp430-none-elf" - | "riscv32i-unknown-none-elf" - | "riscv32imc-unknown-none-elf" => false, - _ => true, - } -} - -fn target_has_atomics(target: &str) -> bool { - match target { - "thumbv4t-none-eabi" - | "msp430-none-elf" - | "riscv32i-unknown-none-elf" - | "riscv32imc-unknown-none-elf" => false, - _ => true, - } -} - -fn rustc_target() -> Option { - env::var("TARGET").ok() -} diff --git a/src/lib.rs b/src/lib.rs index 732637801..0a710c77b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -342,20 +342,20 @@ mod serde; #[cfg(feature = "kv_unstable")] pub mod kv; -#[cfg(has_atomics)] +#[cfg(target_has_atomic = "ptr")] use std::sync::atomic::{AtomicUsize, Ordering}; -#[cfg(not(has_atomics))] +#[cfg(not(target_has_atomic = "ptr"))] use std::cell::Cell; -#[cfg(not(has_atomics))] +#[cfg(not(target_has_atomic = "ptr"))] use std::sync::atomic::Ordering; -#[cfg(not(has_atomics))] +#[cfg(not(target_has_atomic = "ptr"))] struct AtomicUsize { v: Cell, } -#[cfg(not(has_atomics))] +#[cfg(not(target_has_atomic = "ptr"))] impl AtomicUsize { const fn new(v: usize) -> AtomicUsize { AtomicUsize { v: Cell::new(v) } @@ -369,7 +369,7 @@ impl AtomicUsize { self.v.set(val) } - #[cfg(atomic_cas)] + #[cfg(target_has_atomic = "ptr")] fn compare_exchange( &self, current: usize, @@ -387,7 +387,7 @@ impl AtomicUsize { // Any platform without atomics is unlikely to have multiple cores, so // writing via Cell will not be a race condition. -#[cfg(not(has_atomics))] +#[cfg(not(target_has_atomic = "ptr"))] unsafe impl Sync for AtomicUsize {} // The LOGGER static holds a pointer to the global logger. It is protected by @@ -1256,7 +1256,7 @@ pub fn max_level() -> LevelFilter { /// An error is returned if a logger has already been set. /// /// [`set_logger`]: fn.set_logger.html -#[cfg(all(feature = "std", atomic_cas))] +#[cfg(all(feature = "std", target_has_atomic = "ptr"))] pub fn set_boxed_logger(logger: Box) -> Result<(), SetLoggerError> { set_logger_inner(|| Box::leak(logger)) } @@ -1314,12 +1314,12 @@ pub fn set_boxed_logger(logger: Box) -> Result<(), SetLoggerError> { /// ``` /// /// [`set_logger_racy`]: fn.set_logger_racy.html -#[cfg(atomic_cas)] +#[cfg(target_has_atomic = "ptr")] pub fn set_logger(logger: &'static dyn Log) -> Result<(), SetLoggerError> { set_logger_inner(|| logger) } -#[cfg(atomic_cas)] +#[cfg(target_has_atomic = "ptr")] fn set_logger_inner(make_logger: F) -> Result<(), SetLoggerError> where F: FnOnce() -> &'static dyn Log, From 0fe18a48a5a87f4beb835052f3445bb30e5a3e0a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 6 Jan 2023 16:32:14 +0100 Subject: [PATCH 104/280] Update minimum supported Rust version to 1.60.0 --- .github/workflows/main.yml | 4 ++-- README.md | 2 +- clippy.toml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 783b5052d..fb038d280 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -127,8 +127,8 @@ jobs: - uses: actions/checkout@master - name: Install Rust run: | - rustup update 1.31.0 --no-self-update - rustup default 1.31.0 + rustup update 1.60.0 --no-self-update + rustup default 1.60.0 - run: cargo build --verbose - run: cargo build --verbose --features serde - run: cargo build --verbose --features std diff --git a/README.md b/README.md index 5adff6bd7..41a1cb648 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ implementation that is most suitable for its use case. ## Minimum supported `rustc` -`1.31.0+` +`1.60.0+` This version is explicitly tested in CI and may be bumped in any release as needed. Maintaining compatibility with older compilers is a priority though, so the bar for bumping the minimum supported version is set very high. Any changes to the supported minimum version will be called out in the release notes. diff --git a/clippy.toml b/clippy.toml index 3d30690f1..16caf02ee 100644 --- a/clippy.toml +++ b/clippy.toml @@ -1 +1 @@ -msrv = "1.31.0" +msrv = "1.60.0" From e5f1ae9703eed70ae60e552dac1e3e8ab8371a22 Mon Sep 17 00:00:00 2001 From: David Koloski Date: Fri, 6 Jan 2023 11:08:26 -0500 Subject: [PATCH 105/280] Add `set_max_level_racy` and gate `set_max_level` Calling `set_max_level` can result in a race condition on platforms that don't have an atomic compare and swap implementation. This gates `set_max_level` behind `#[cfg(atomic_cas)]` and adds a racy alternative that can be called in these situations. This mirrors the approach for `set_logger`. --- src/lib.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 732637801..f79d3116b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1215,10 +1215,38 @@ where /// /// Note that `Trace` is the maximum level, because it provides the maximum amount of detail in the emitted logs. #[inline] +#[cfg(atomic_cas)] pub fn set_max_level(level: LevelFilter) { MAX_LOG_LEVEL_FILTER.store(level as usize, Ordering::Relaxed); } +/// A thread-unsafe version of [`set_max_level`]. +/// +/// This function is available on all platforms, even those that do not have +/// support for atomics that is needed by [`set_max_level`]. +/// +/// In almost all cases, [`set_max_level`] should be preferred. +/// +/// # Safety +/// +/// This function is only safe to call when no other level setting function is +/// called while this function still executes. +/// +/// This can be upheld by (for example) making sure that **there are no other +/// threads**, and (on embedded) that **interrupts are disabled**. +/// +/// Is is safe to use all other logging functions while this function runs +/// (including all logging macros). +/// +/// [`set_max_level`]: fn.set_max_level.html +#[inline] +pub unsafe fn set_max_level_racy(level: LevelFilter) { + // `MAX_LOG_LEVEL_FILTER` uses a `Cell` as the underlying primitive when a + // platform doesn't support `atomic_cas`, so even though this looks the same + // as `set_max_level` it may have different safety properties. + MAX_LOG_LEVEL_FILTER.store(level as usize, Ordering::Relaxed); +} + /// Returns the current maximum log level. /// /// The [`log!`], [`error!`], [`warn!`], [`info!`], [`debug!`], and [`trace!`] macros check From 2045d335c77489931774b0be2127f7efa73f8842 Mon Sep 17 00:00:00 2001 From: a1ecbr0wn Date: Tue, 7 Mar 2023 10:13:41 +0000 Subject: [PATCH 106/280] Add call_logger to the documentation --- README.md | 1 + src/lib.rs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/README.md b/README.md index 5adff6bd7..0d6041c3d 100644 --- a/README.md +++ b/README.md @@ -67,6 +67,7 @@ There are many available implementations to choose from, here are some of the mo * [`pretty_env_logger`](https://docs.rs/pretty_env_logger/*/pretty_env_logger/) * [`stderrlog`](https://docs.rs/stderrlog/*/stderrlog/) * [`flexi_logger`](https://docs.rs/flexi_logger/*/flexi_logger/) + * [`call_logger`](https://docs.rs/call_logger/*/call_logger/) * Complex configurable frameworks: * [`log4rs`](https://docs.rs/log4rs/*/log4rs/) * [`fern`](https://docs.rs/fern/*/fern/) diff --git a/src/lib.rs b/src/lib.rs index 732637801..0006c4131 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -136,6 +136,7 @@ //! * [pretty_env_logger] //! * [stderrlog] //! * [flexi_logger] +//! * [call_logger] //! * Complex configurable frameworks: //! * [log4rs] //! * [fern] @@ -302,6 +303,7 @@ //! [pretty_env_logger]: https://docs.rs/pretty_env_logger/*/pretty_env_logger/ //! [stderrlog]: https://docs.rs/stderrlog/*/stderrlog/ //! [flexi_logger]: https://docs.rs/flexi_logger/*/flexi_logger/ +//! [call_logger]: https://docs.rs/call_logger/*/call_logger/ //! [syslog]: https://docs.rs/syslog/*/syslog/ //! [slog-stdlog]: https://docs.rs/slog-stdlog/*/slog_stdlog/ //! [log4rs]: https://docs.rs/log4rs/*/log4rs/ From c644e6fb8256d369b882719380ac3773d0f4f6a6 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Sun, 9 Apr 2023 16:53:19 +1000 Subject: [PATCH 107/280] port to stable versions of value-bag and sval --- Cargo.toml | 9 +++---- src/kv/key.rs | 10 ++++++-- src/kv/source.rs | 61 +++++++++++++++++++++++++++--------------------- src/kv/value.rs | 53 +++++++++++++++++------------------------ 4 files changed, 70 insertions(+), 63 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 909b29c0c..31164d5e3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,12 +54,13 @@ kv_unstable_serde = ["kv_unstable_std", "value-bag/serde", "serde"] [dependencies] serde = { version = "1.0", optional = true, default-features = false } -sval = { version = "=1.0.0-alpha.5", optional = true, default-features = false } -value-bag = { version = "=1.0.0-alpha.9", optional = true, default-features = false } +sval = { version = "2.0", optional = true, default-features = false } +value-bag = { version = "1.0", optional = true, default-features = false } [dev-dependencies] rustversion = "1.0" serde = { version = "1.0", features = ["derive"] } serde_test = "1.0" -sval = { version = "=1.0.0-alpha.5", features = ["derive"] } -value-bag = { version = "=1.0.0-alpha.9", features = ["test"] } +sval = { version = "2.0" } +sval_derive = { version = "2.0" } +value-bag = { version = "1.0", features = ["test"] } diff --git a/src/kv/key.rs b/src/kv/key.rs index a35338dcc..d5258383c 100644 --- a/src/kv/key.rs +++ b/src/kv/key.rs @@ -48,6 +48,12 @@ impl<'k> Key<'k> { pub fn as_str(&self) -> &str { self.key } + + /// Try get a string borrowed for the `'k` lifetime from this key. + pub fn to_borrowed_str(&self) -> Option<&'k str> { + // NOTE: This API leaves room for keys to be owned + Some(self.key) + } } impl<'k> fmt::Display for Key<'k> { @@ -99,10 +105,10 @@ mod sval_support { extern crate sval; - use self::sval::value::{self, Value}; + use self::sval::Value; impl<'a> Value for Key<'a> { - fn stream(&self, stream: &mut value::Stream) -> value::Result { + fn stream<'sval, S: sval::Stream<'sval> + ?Sized>(&'sval self, stream: &mut S) -> sval::Result { self.key.stream(stream) } } diff --git a/src/kv/source.rs b/src/kv/source.rs index 8762c621e..5ea41c159 100644 --- a/src/kv/source.rs +++ b/src/kv/source.rs @@ -460,74 +460,83 @@ where mod sval_support { use super::*; - use self::sval::value; - - impl value::Value for AsMap + impl self::sval::Value for AsMap where S: Source, { - fn stream(&self, stream: &mut value::Stream) -> value::Result { - struct StreamVisitor<'a, 'b>(&'a mut value::Stream<'b>); + fn stream<'sval, SV: self::sval::Stream<'sval> + ?Sized>(&'sval self, stream: &mut SV) -> self::sval::Result { + struct StreamVisitor<'a, V: ?Sized>(&'a mut V); - impl<'a, 'b, 'kvs> Visitor<'kvs> for StreamVisitor<'a, 'b> { + impl<'a, 'kvs, V: self::sval::Stream<'kvs> + ?Sized> Visitor<'kvs> for StreamVisitor<'a, V> { fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> { - self.0 - .map_key(key) - .map_err(|_| Error::msg("failed to stream map key"))?; - self.0 - .map_value(value) - .map_err(|_| Error::msg("failed to stream map value"))?; + self.0.map_key_begin().map_err(|_| Error::msg("failed to stream map key"))?; + if let Some(key) = key.to_borrowed_str() { + self.0.value(key).map_err(|_| Error::msg("failed to stream map key"))?; + } else { + self.0.value_computed(key.as_str()).map_err(|_| Error::msg("failed to stream map key"))?; + } + self.0.map_key_end().map_err(|_| Error::msg("failed to stream map key"))?; + + // TODO: Need to borrow this here + self.0.map_value_begin().map_err(|_| Error::msg("failed to stream map value"))?; + self.0.value_computed(&value).map_err(|_| Error::msg("failed to stream map value"))?; + self.0.map_value_end().map_err(|_| Error::msg("failed to stream map value"))?; + Ok(()) } } stream .map_begin(Some(self.count())) - .map_err(|_| self::sval::Error::msg("failed to begin map"))?; + .map_err(|_| self::sval::Error::new())?; self.visit(&mut StreamVisitor(stream)) - .map_err(|_| self::sval::Error::msg("failed to visit key-values"))?; + .map_err(|_| self::sval::Error::new())?; stream .map_end() - .map_err(|_| self::sval::Error::msg("failed to end map")) + .map_err(|_| self::sval::Error::new()) } } - impl value::Value for AsList + impl self::sval::Value for AsList where S: Source, { - fn stream(&self, stream: &mut value::Stream) -> value::Result { - struct StreamVisitor<'a, 'b>(&'a mut value::Stream<'b>); + fn stream<'sval, SV: self::sval::Stream<'sval> + ?Sized>(&'sval self, stream: &mut SV) -> self::sval::Result { + struct StreamVisitor<'a, V: ?Sized>(&'a mut V); - impl<'a, 'b, 'kvs> Visitor<'kvs> for StreamVisitor<'a, 'b> { + impl<'a, 'kvs, V: self::sval::Stream<'kvs> + ?Sized> Visitor<'kvs> for StreamVisitor<'a, V> { fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> { - self.0 - .seq_elem((key, value)) - .map_err(|_| Error::msg("failed to stream seq entry"))?; + // TODO: Need to borrow this here + self.0.seq_value_begin().map_err(|_| Error::msg("failed to stream seq value"))?; + self.0.value_computed(&(key, value)).map_err(|_| Error::msg("failed to stream seq value"))?; + self.0.seq_value_end().map_err(|_| Error::msg("failed to stream seq value"))?; + Ok(()) } } stream .seq_begin(Some(self.count())) - .map_err(|_| self::sval::Error::msg("failed to begin seq"))?; + .map_err(|_| self::sval::Error::new())?; self.visit(&mut StreamVisitor(stream)) - .map_err(|_| self::sval::Error::msg("failed to visit key-values"))?; + .map_err(|_| self::sval::Error::new())?; stream .seq_end() - .map_err(|_| self::sval::Error::msg("failed to end seq")) + .map_err(|_| self::sval::Error::new()) } } #[cfg(test)] mod tests { + extern crate sval_derive; + use super::*; - use self::sval::Value; + use self::sval_derive::Value; use crate::kv::source; diff --git a/src/kv/value.rs b/src/kv/value.rs index 607bc09a5..e0dcb9da2 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -71,7 +71,7 @@ macro_rules! as_serde { }; } -/// Get a value from a type implementing `sval::value::Value`. +/// Get a value from a type implementing `self::sval::value::Value`. #[cfg(feature = "kv_unstable_sval")] #[macro_export] macro_rules! as_sval { @@ -197,21 +197,21 @@ impl<'v> Value<'v> { /// Get a value from a type implementing `serde::Serialize`. pub fn capture_serde(value: &'v T) -> Self where - T: self::serde::Serialize + 'static, + T: serde::Serialize + 'static, { Value { inner: ValueBag::capture_serde1(value), } } - /// Get a value from a type implementing `sval::value::Value`. + /// Get a value from a type implementing `self::sval::value::Value`. #[cfg(feature = "kv_unstable_sval")] pub fn capture_sval(value: &'v T) -> Self where - T: self::sval::value::Value + 'static, + T: self::sval::Value + 'static, { Value { - inner: ValueBag::capture_sval1(value), + inner: ValueBag::capture_sval2(value), } } @@ -239,7 +239,7 @@ impl<'v> Value<'v> { #[cfg(feature = "kv_unstable_serde")] pub fn from_serde(value: &'v T) -> Self where - T: self::serde::Serialize, + T: serde::Serialize, { Value { inner: ValueBag::from_serde1(value), @@ -250,10 +250,10 @@ impl<'v> Value<'v> { #[cfg(feature = "kv_unstable_sval")] pub fn from_sval(value: &'v T) -> Self where - T: self::sval::value::Value, + T: self::sval::Value, { Value { - inner: ValueBag::from_sval1(value), + inner: ValueBag::from_sval2(value), } } @@ -279,14 +279,6 @@ impl<'v> Value<'v> { } } - /// Get a value from a type implementing `sval::value::Value`. - #[cfg(feature = "kv_unstable_sval")] - pub fn from_dyn_sval(value: &'v dyn self::sval::value::Value) -> Self { - Value { - inner: ValueBag::from_dyn_sval1(value), - } - } - /// Get a value from an internal primitive. fn from_value_bag(value: T) -> Self where @@ -412,26 +404,19 @@ impl ToValue for dyn std::error::Error + 'static { } #[cfg(feature = "kv_unstable_serde")] -impl<'v> self::serde::Serialize for Value<'v> { +impl<'v> serde::Serialize for Value<'v> { fn serialize(&self, s: S) -> Result where - S: self::serde::Serializer, + S: serde::Serializer, { self.inner.serialize(s) } } #[cfg(feature = "kv_unstable_sval")] -impl<'v> self::sval::value::Value for Value<'v> { - fn stream(&self, stream: &mut self::sval::value::Stream) -> self::sval::value::Result { - self::sval::value::Value::stream(&self.inner, stream) - } -} - -#[cfg(feature = "kv_unstable_sval")] -impl ToValue for dyn self::sval::value::Value { - fn to_value(&self) -> Value { - Value::from_dyn_sval(self) +impl<'v> self::sval::Value for Value<'v> { + fn stream<'sval, S: self::sval::Stream<'sval> + ?Sized>(&'sval self, stream: &mut S) -> self::sval::Result { + self::sval::Value::stream(&self.inner, stream) } } @@ -465,6 +450,12 @@ impl ToValue for std::num::NonZeroI128 { } } +impl<'v> From> for Value<'v> { + fn from(value: ValueBag<'v>) -> Self { + Value::from_value_bag(value) + } +} + impl<'v> From<&'v str> for Value<'v> { fn from(value: &'v str) -> Self { Value::from_value_bag(value) @@ -650,7 +641,7 @@ pub trait Visit<'v> { /// This is the only required method on `Visit` and acts as a fallback for any /// more specific methods that aren't overridden. /// The `Value` may be formatted using its `fmt::Debug` or `fmt::Display` implementation, - /// or serialized using its `sval::Value` or `serde::Serialize` implementation. + /// or serialized using its `self::sval::Value` or `serde::Serialize` implementation. fn visit_any(&mut self, value: Value) -> Result<(), Error>; /// Visit an unsigned integer. @@ -777,11 +768,11 @@ where pub(crate) mod tests { use super::*; - pub(crate) use super::value_bag::test::Token; + pub(crate) use super::value_bag::test::TestToken as Token; impl<'v> Value<'v> { pub(crate) fn to_token(&self) -> Token { - self.inner.to_token() + self.inner.to_test_token() } } From 9c125f239a26946623e2369c6383dc59782f4e02 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Mon, 10 Apr 2023 17:56:03 +1000 Subject: [PATCH 108/280] borrow for 'kv from Key<'kv> and Value<'kv> --- Cargo.toml | 13 +++++++------ src/kv/key.rs | 8 ++++++++ src/kv/source.rs | 14 +++++--------- src/kv/value.rs | 15 +++++++++------ 4 files changed, 29 insertions(+), 21 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 31164d5e3..c9fddf999 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,19 +48,20 @@ std = [] # requires the latest stable # this will have a tighter MSRV before stabilization kv_unstable = ["value-bag"] -kv_unstable_sval = ["kv_unstable", "value-bag/sval", "sval"] +kv_unstable_sval = ["kv_unstable", "value-bag/sval", "sval", "sval_ref"] kv_unstable_std = ["std", "kv_unstable", "value-bag/error"] kv_unstable_serde = ["kv_unstable_std", "value-bag/serde", "serde"] [dependencies] serde = { version = "1.0", optional = true, default-features = false } -sval = { version = "2.0", optional = true, default-features = false } -value-bag = { version = "1.0", optional = true, default-features = false } +sval = { version = "2.1", optional = true, default-features = false } +sval_ref = { version = "2.1", optional = true, default-features = false } +value-bag = { version = "1.1", optional = true, default-features = false } [dev-dependencies] rustversion = "1.0" serde = { version = "1.0", features = ["derive"] } serde_test = "1.0" -sval = { version = "2.0" } -sval_derive = { version = "2.0" } -value-bag = { version = "1.0", features = ["test"] } +sval = { version = "2.1" } +sval_derive = { version = "2.1" } +value-bag = { version = "1.1", features = ["test"] } diff --git a/src/kv/key.rs b/src/kv/key.rs index d5258383c..b857d336c 100644 --- a/src/kv/key.rs +++ b/src/kv/key.rs @@ -104,14 +104,22 @@ mod sval_support { use super::*; extern crate sval; + extern crate sval_ref; use self::sval::Value; + use self::sval_ref::ValueRef; impl<'a> Value for Key<'a> { fn stream<'sval, S: sval::Stream<'sval> + ?Sized>(&'sval self, stream: &mut S) -> sval::Result { self.key.stream(stream) } } + + impl<'a> ValueRef<'a> for Key<'a> { + fn stream_ref + ?Sized>(&self, stream: &mut S) -> self::sval::Result { + self.key.stream(stream) + } + } } #[cfg(feature = "kv_unstable_serde")] diff --git a/src/kv/source.rs b/src/kv/source.rs index 5ea41c159..7812d09fb 100644 --- a/src/kv/source.rs +++ b/src/kv/source.rs @@ -2,6 +2,8 @@ #[cfg(feature = "kv_unstable_sval")] extern crate sval; +#[cfg(feature = "kv_unstable_sval")] +extern crate sval_ref; #[cfg(feature = "kv_unstable_serde")] extern crate serde; @@ -470,16 +472,11 @@ mod sval_support { impl<'a, 'kvs, V: self::sval::Stream<'kvs> + ?Sized> Visitor<'kvs> for StreamVisitor<'a, V> { fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> { self.0.map_key_begin().map_err(|_| Error::msg("failed to stream map key"))?; - if let Some(key) = key.to_borrowed_str() { - self.0.value(key).map_err(|_| Error::msg("failed to stream map key"))?; - } else { - self.0.value_computed(key.as_str()).map_err(|_| Error::msg("failed to stream map key"))?; - } + sval_ref::stream_ref(self.0, key).map_err(|_| Error::msg("failed to stream map key"))?; self.0.map_key_end().map_err(|_| Error::msg("failed to stream map key"))?; - // TODO: Need to borrow this here self.0.map_value_begin().map_err(|_| Error::msg("failed to stream map value"))?; - self.0.value_computed(&value).map_err(|_| Error::msg("failed to stream map value"))?; + sval_ref::stream_ref(self.0, value).map_err(|_| Error::msg("failed to stream map value"))?; self.0.map_value_end().map_err(|_| Error::msg("failed to stream map value"))?; Ok(()) @@ -508,9 +505,8 @@ mod sval_support { impl<'a, 'kvs, V: self::sval::Stream<'kvs> + ?Sized> Visitor<'kvs> for StreamVisitor<'a, V> { fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> { - // TODO: Need to borrow this here self.0.seq_value_begin().map_err(|_| Error::msg("failed to stream seq value"))?; - self.0.value_computed(&(key, value)).map_err(|_| Error::msg("failed to stream seq value"))?; + self::sval_ref::stream_ref(self.0, (key, value)).map_err(|_| Error::msg("failed to stream seq value"))?; self.0.seq_value_end().map_err(|_| Error::msg("failed to stream seq value"))?; Ok(()) diff --git a/src/kv/value.rs b/src/kv/value.rs index e0dcb9da2..d4b3bf39f 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -6,6 +6,8 @@ extern crate value_bag; #[cfg(feature = "kv_unstable_sval")] extern crate sval; +#[cfg(feature = "kv_unstable_sval")] +extern crate sval_ref; #[cfg(feature = "kv_unstable_serde")] extern crate serde; @@ -420,6 +422,13 @@ impl<'v> self::sval::Value for Value<'v> { } } +#[cfg(feature = "kv_unstable_sval")] +impl<'v> self::sval_ref::ValueRef<'v> for Value<'v> { + fn stream_ref + ?Sized>(&self, stream: &mut S) -> self::sval::Result { + self::sval_ref::ValueRef::stream_ref(&self.inner, stream) + } +} + impl ToValue for str { fn to_value(&self) -> Value { Value::from(self) @@ -450,12 +459,6 @@ impl ToValue for std::num::NonZeroI128 { } } -impl<'v> From> for Value<'v> { - fn from(value: ValueBag<'v>) -> Self { - Value::from_value_bag(value) - } -} - impl<'v> From<&'v str> for Value<'v> { fn from(value: &'v str) -> Self { Value::from_value_bag(value) From 955d352ccc73dbec1f4c3346e1f35823c62e0fde Mon Sep 17 00:00:00 2001 From: KodrAus Date: Mon, 10 Apr 2023 18:04:58 +1000 Subject: [PATCH 109/280] qualify path to serde --- src/kv/value.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/kv/value.rs b/src/kv/value.rs index d4b3bf39f..818743709 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -199,7 +199,7 @@ impl<'v> Value<'v> { /// Get a value from a type implementing `serde::Serialize`. pub fn capture_serde(value: &'v T) -> Self where - T: serde::Serialize + 'static, + T: self::serde::Serialize + 'static, { Value { inner: ValueBag::capture_serde1(value), @@ -241,7 +241,7 @@ impl<'v> Value<'v> { #[cfg(feature = "kv_unstable_serde")] pub fn from_serde(value: &'v T) -> Self where - T: serde::Serialize, + T: self::serde::Serialize, { Value { inner: ValueBag::from_serde1(value), @@ -406,10 +406,10 @@ impl ToValue for dyn std::error::Error + 'static { } #[cfg(feature = "kv_unstable_serde")] -impl<'v> serde::Serialize for Value<'v> { +impl<'v> self::serde::Serialize for Value<'v> { fn serialize(&self, s: S) -> Result where - S: serde::Serializer, + S: self::serde::Serializer, { self.inner.serialize(s) } From b71d3b1feb98fc67886fbed5d074c55777f15780 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Mon, 10 Apr 2023 18:05:46 +1000 Subject: [PATCH 110/280] fix up path in doc comments --- src/kv/value.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/kv/value.rs b/src/kv/value.rs index 818743709..893afa74e 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -73,7 +73,7 @@ macro_rules! as_serde { }; } -/// Get a value from a type implementing `self::sval::value::Value`. +/// Get a value from a type implementing `sval::Value`. #[cfg(feature = "kv_unstable_sval")] #[macro_export] macro_rules! as_sval { @@ -206,7 +206,7 @@ impl<'v> Value<'v> { } } - /// Get a value from a type implementing `self::sval::value::Value`. + /// Get a value from a type implementing `sval::Value`. #[cfg(feature = "kv_unstable_sval")] pub fn capture_sval(value: &'v T) -> Self where @@ -248,7 +248,7 @@ impl<'v> Value<'v> { } } - /// Get a value from a type implementing `sval::value::Value`. + /// Get a value from a type implementing `sval::Value`. #[cfg(feature = "kv_unstable_sval")] pub fn from_sval(value: &'v T) -> Self where @@ -644,7 +644,7 @@ pub trait Visit<'v> { /// This is the only required method on `Visit` and acts as a fallback for any /// more specific methods that aren't overridden. /// The `Value` may be formatted using its `fmt::Debug` or `fmt::Display` implementation, - /// or serialized using its `self::sval::Value` or `serde::Serialize` implementation. + /// or serialized using its `sval::Value` or `serde::Serialize` implementation. fn visit_any(&mut self, value: Value) -> Result<(), Error>; /// Visit an unsigned integer. From ab829c616ab52c9161197701f0662e925406f9a9 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Mon, 10 Apr 2023 18:08:12 +1000 Subject: [PATCH 111/280] run fmt --- src/kv/key.rs | 10 ++++++++-- src/kv/source.rs | 51 ++++++++++++++++++++++++++++++++---------------- src/kv/value.rs | 5 ++++- 3 files changed, 46 insertions(+), 20 deletions(-) diff --git a/src/kv/key.rs b/src/kv/key.rs index b857d336c..4f9a506ec 100644 --- a/src/kv/key.rs +++ b/src/kv/key.rs @@ -110,13 +110,19 @@ mod sval_support { use self::sval_ref::ValueRef; impl<'a> Value for Key<'a> { - fn stream<'sval, S: sval::Stream<'sval> + ?Sized>(&'sval self, stream: &mut S) -> sval::Result { + fn stream<'sval, S: sval::Stream<'sval> + ?Sized>( + &'sval self, + stream: &mut S, + ) -> sval::Result { self.key.stream(stream) } } impl<'a> ValueRef<'a> for Key<'a> { - fn stream_ref + ?Sized>(&self, stream: &mut S) -> self::sval::Result { + fn stream_ref + ?Sized>( + &self, + stream: &mut S, + ) -> self::sval::Result { self.key.stream(stream) } } diff --git a/src/kv/source.rs b/src/kv/source.rs index 7812d09fb..45fc6dce4 100644 --- a/src/kv/source.rs +++ b/src/kv/source.rs @@ -466,18 +466,31 @@ mod sval_support { where S: Source, { - fn stream<'sval, SV: self::sval::Stream<'sval> + ?Sized>(&'sval self, stream: &mut SV) -> self::sval::Result { + fn stream<'sval, SV: self::sval::Stream<'sval> + ?Sized>( + &'sval self, + stream: &mut SV, + ) -> self::sval::Result { struct StreamVisitor<'a, V: ?Sized>(&'a mut V); impl<'a, 'kvs, V: self::sval::Stream<'kvs> + ?Sized> Visitor<'kvs> for StreamVisitor<'a, V> { fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> { - self.0.map_key_begin().map_err(|_| Error::msg("failed to stream map key"))?; - sval_ref::stream_ref(self.0, key).map_err(|_| Error::msg("failed to stream map key"))?; - self.0.map_key_end().map_err(|_| Error::msg("failed to stream map key"))?; + self.0 + .map_key_begin() + .map_err(|_| Error::msg("failed to stream map key"))?; + sval_ref::stream_ref(self.0, key) + .map_err(|_| Error::msg("failed to stream map key"))?; + self.0 + .map_key_end() + .map_err(|_| Error::msg("failed to stream map key"))?; - self.0.map_value_begin().map_err(|_| Error::msg("failed to stream map value"))?; - sval_ref::stream_ref(self.0, value).map_err(|_| Error::msg("failed to stream map value"))?; - self.0.map_value_end().map_err(|_| Error::msg("failed to stream map value"))?; + self.0 + .map_value_begin() + .map_err(|_| Error::msg("failed to stream map value"))?; + sval_ref::stream_ref(self.0, value) + .map_err(|_| Error::msg("failed to stream map value"))?; + self.0 + .map_value_end() + .map_err(|_| Error::msg("failed to stream map value"))?; Ok(()) } @@ -490,9 +503,7 @@ mod sval_support { self.visit(&mut StreamVisitor(stream)) .map_err(|_| self::sval::Error::new())?; - stream - .map_end() - .map_err(|_| self::sval::Error::new()) + stream.map_end().map_err(|_| self::sval::Error::new()) } } @@ -500,14 +511,22 @@ mod sval_support { where S: Source, { - fn stream<'sval, SV: self::sval::Stream<'sval> + ?Sized>(&'sval self, stream: &mut SV) -> self::sval::Result { + fn stream<'sval, SV: self::sval::Stream<'sval> + ?Sized>( + &'sval self, + stream: &mut SV, + ) -> self::sval::Result { struct StreamVisitor<'a, V: ?Sized>(&'a mut V); impl<'a, 'kvs, V: self::sval::Stream<'kvs> + ?Sized> Visitor<'kvs> for StreamVisitor<'a, V> { fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> { - self.0.seq_value_begin().map_err(|_| Error::msg("failed to stream seq value"))?; - self::sval_ref::stream_ref(self.0, (key, value)).map_err(|_| Error::msg("failed to stream seq value"))?; - self.0.seq_value_end().map_err(|_| Error::msg("failed to stream seq value"))?; + self.0 + .seq_value_begin() + .map_err(|_| Error::msg("failed to stream seq value"))?; + self::sval_ref::stream_ref(self.0, (key, value)) + .map_err(|_| Error::msg("failed to stream seq value"))?; + self.0 + .seq_value_end() + .map_err(|_| Error::msg("failed to stream seq value"))?; Ok(()) } @@ -520,9 +539,7 @@ mod sval_support { self.visit(&mut StreamVisitor(stream)) .map_err(|_| self::sval::Error::new())?; - stream - .seq_end() - .map_err(|_| self::sval::Error::new()) + stream.seq_end().map_err(|_| self::sval::Error::new()) } } diff --git a/src/kv/value.rs b/src/kv/value.rs index 893afa74e..9485d485b 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -417,7 +417,10 @@ impl<'v> self::serde::Serialize for Value<'v> { #[cfg(feature = "kv_unstable_sval")] impl<'v> self::sval::Value for Value<'v> { - fn stream<'sval, S: self::sval::Stream<'sval> + ?Sized>(&'sval self, stream: &mut S) -> self::sval::Result { + fn stream<'sval, S: self::sval::Stream<'sval> + ?Sized>( + &'sval self, + stream: &mut S, + ) -> self::sval::Result { self::sval::Value::stream(&self.inner, stream) } } From 83117275c37be00d1d7294ccb8a5124c73bbfe18 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Mon, 10 Apr 2023 21:11:21 +1000 Subject: [PATCH 112/280] only run tests on MSRV --- .github/workflows/main.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 783b5052d..f38d3b33e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -129,9 +129,6 @@ jobs: run: | rustup update 1.31.0 --no-self-update rustup default 1.31.0 - - run: cargo build --verbose - - run: cargo build --verbose --features serde - - run: cargo build --verbose --features std - run: cargo test --verbose --manifest-path tests/Cargo.toml embedded: From 0951cee26ff76eaefd6b1ff40dd689020c9c39d4 Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Tue, 11 Apr 2023 11:36:44 +0200 Subject: [PATCH 113/280] Change wording of list of implementations --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7295bf716..3f6599a0c 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ pub fn shave_the_yak(yak: &mut Yak) { ### In executables In order to produce log output, executables have to use a logger implementation compatible with the facade. -There are many available implementations to choose from, here are some of the most popular ones: +There are many available implementations to choose from, here are some options: * Simple minimal loggers: * [`env_logger`](https://docs.rs/env_logger/*/env_logger/) @@ -81,7 +81,7 @@ There are many available implementations to choose from, here are some of the mo * For WebAssembly binaries: * [`console_log`](https://docs.rs/console_log/*/console_log/) * For dynamic libraries: - * You may need to construct [an FFI-safe wrapper over `log`](https://github.com/rust-lang/log/issues/421) to initialize in your libraries. + * You may need to construct [an FFI-safe wrapper over `log`](https://github.com/rust-lang/log/issues/421) to initialize in your libraries. * Utilities: * [`log_err`](https://docs.rs/log_err/*/log_err/) From a872bf8919a6ee6b83d4c2f732d825ed3fa9d452 Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Tue, 11 Apr 2023 11:38:11 +0200 Subject: [PATCH 114/280] Add std-logger to list of implementations --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 7295bf716..ddbebdf24 100644 --- a/README.md +++ b/README.md @@ -68,6 +68,7 @@ There are many available implementations to choose from, here are some of the mo * [`stderrlog`](https://docs.rs/stderrlog/*/stderrlog/) * [`flexi_logger`](https://docs.rs/flexi_logger/*/flexi_logger/) * [`call_logger`](https://docs.rs/call_logger/*/call_logger/) + * [`std-logger`](https://docs.rs/std-logger/*/std-logger/) * Complex configurable frameworks: * [`log4rs`](https://docs.rs/log4rs/*/log4rs/) * [`fern`](https://docs.rs/fern/*/fern/) From 025815880a7dbe814ffe57bb52cfce0041ec194e Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Tue, 11 Apr 2023 12:57:25 +0200 Subject: [PATCH 115/280] Fix std-logger link Co-authored-by: Ashley Mannix --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ddbebdf24..e780b617a 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ There are many available implementations to choose from, here are some of the mo * [`stderrlog`](https://docs.rs/stderrlog/*/stderrlog/) * [`flexi_logger`](https://docs.rs/flexi_logger/*/flexi_logger/) * [`call_logger`](https://docs.rs/call_logger/*/call_logger/) - * [`std-logger`](https://docs.rs/std-logger/*/std-logger/) + * [`std-logger`](https://docs.rs/std-logger/*/std_logger/) * Complex configurable frameworks: * [`log4rs`](https://docs.rs/log4rs/*/log4rs/) * [`fern`](https://docs.rs/fern/*/fern/) From ce9f217d584376646bac53dd9a2f9b9de7ab4be1 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Thu, 13 Apr 2023 17:08:08 +1000 Subject: [PATCH 116/280] use target_has_atomic instead of the old atomic_cas cfg --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index c4eccdaaa..63401f040 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1217,7 +1217,7 @@ where /// /// Note that `Trace` is the maximum level, because it provides the maximum amount of detail in the emitted logs. #[inline] -#[cfg(atomic_cas)] +#[cfg(target_has_atomic = "ptr")] pub fn set_max_level(level: LevelFilter) { MAX_LOG_LEVEL_FILTER.store(level as usize, Ordering::Relaxed); } @@ -1244,7 +1244,7 @@ pub fn set_max_level(level: LevelFilter) { #[inline] pub unsafe fn set_max_level_racy(level: LevelFilter) { // `MAX_LOG_LEVEL_FILTER` uses a `Cell` as the underlying primitive when a - // platform doesn't support `atomic_cas`, so even though this looks the same + // platform doesn't support `target_has_atomic = "ptr"`, so even though this looks the same // as `set_max_level` it may have different safety properties. MAX_LOG_LEVEL_FILTER.store(level as usize, Ordering::Relaxed); } From 79c330cb74c2b4b57bcc8838e0ea4bdd3adb7690 Mon Sep 17 00:00:00 2001 From: est31 Date: Sat, 15 Apr 2023 08:57:02 +0200 Subject: [PATCH 117/280] Put MSRV into Cargo.toml Also remove it from clippy.toml as clippy reads it from Cargo.toml since 1.64. CI only runs clippy from latest stable and not from the MSRV so this shouldn't be a problem. --- Cargo.toml | 1 + clippy.toml | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 clippy.toml diff --git a/Cargo.toml b/Cargo.toml index 598b2be6c..2f4e3e36f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,7 @@ A lightweight logging facade for Rust categories = ["development-tools::debugging"] keywords = ["logging"] exclude = ["rfcs/**/*"] +rust-version = "1.60.0" [package.metadata.docs.rs] features = ["std", "serde", "kv_unstable_std", "kv_unstable_sval", "kv_unstable_serde"] diff --git a/clippy.toml b/clippy.toml deleted file mode 100644 index 16caf02ee..000000000 --- a/clippy.toml +++ /dev/null @@ -1 +0,0 @@ -msrv = "1.60.0" From 1acf2f355bdf3e2b165b9c459dc256d2497dba27 Mon Sep 17 00:00:00 2001 From: OccupyMars2025 <31559413+OccupyMars2025@users.noreply.github.com> Date: Fri, 26 May 2023 17:02:20 +0800 Subject: [PATCH 118/280] src/lib.rs : prefix an unused variable with an underscore unused variable: `metadata`, according to rustc, if this is intentional, prefix it with an underscore: `_metadata` --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 63401f040..c809db36c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -690,7 +690,7 @@ impl<'a> MaybeStaticStr<'a> { /// struct SimpleLogger; /// /// impl log::Log for SimpleLogger { -/// fn enabled(&self, metadata: &log::Metadata) -> bool { +/// fn enabled(&self, _metadata: &log::Metadata) -> bool { /// true /// } /// From 7c4f808df833536927f582ca52b9eaefaf9108a4 Mon Sep 17 00:00:00 2001 From: OccupyMars2025 <31559413+OccupyMars2025@users.noreply.github.com> Date: Sat, 27 May 2023 10:48:17 +0800 Subject: [PATCH 119/280] [doc] src/macros.rs : correct grammar errors of an example in lib documentation change semicolons to commas --- src/macros.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index 614961ff7..84143dd37 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -29,7 +29,7 @@ /// ``` #[macro_export(local_inner_macros)] macro_rules! log { - // log!(target: "my_target", Level::Info; key1 = 42, key2 = true; "a {} event", "log"); + // log!(target: "my_target", Level::Info, key1 = 42, key2 = true; "a {} event", "log"); (target: $target:expr, $lvl:expr, $($key:tt = $value:expr),+; $($arg:tt)+) => ({ let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { @@ -42,7 +42,7 @@ macro_rules! log { } }); - // log!(target: "my_target", Level::Info; "a {} event", "log"); + // log!(target: "my_target", Level::Info, "a {} event", "log"); (target: $target:expr, $lvl:expr, $($arg:tt)+) => ({ let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { From 4e689bbb8f7dc7c465e6367b7022f347a0fe09e9 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Sun, 28 May 2023 13:42:24 +1000 Subject: [PATCH 120/280] Revert "Remove build.rs file" This reverts commit 7f09d72e5fd5387c672b9803ead6548b45920f55. --- .github/workflows/main.yml | 7 ++---- Cargo.toml | 6 ++--- build.rs | 46 ++++++++++++++++++++++++++++++++++++++ src/lib.rs | 21 +++++++++-------- 4 files changed, 61 insertions(+), 19 deletions(-) create mode 100644 build.rs diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index fb038d280..f38d3b33e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -127,11 +127,8 @@ jobs: - uses: actions/checkout@master - name: Install Rust run: | - rustup update 1.60.0 --no-self-update - rustup default 1.60.0 - - run: cargo build --verbose - - run: cargo build --verbose --features serde - - run: cargo build --verbose --features std + rustup update 1.31.0 --no-self-update + rustup default 1.31.0 - run: cargo test --verbose --manifest-path tests/Cargo.toml embedded: diff --git a/Cargo.toml b/Cargo.toml index 2f4e3e36f..786f74dae 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ A lightweight logging facade for Rust categories = ["development-tools::debugging"] keywords = ["logging"] exclude = ["rfcs/**/*"] -rust-version = "1.60.0" +build = "build.rs" [package.metadata.docs.rs] features = ["std", "serde", "kv_unstable_std", "kv_unstable_sval", "kv_unstable_serde"] @@ -56,7 +56,7 @@ kv_unstable_serde = ["kv_unstable_std", "value-bag/serde", "serde"] serde = { version = "1.0", optional = true, default-features = false } sval = { version = "2.1", optional = true, default-features = false } sval_ref = { version = "2.1", optional = true, default-features = false } -value-bag = { version = "1.1", optional = true, default-features = false } +value-bag = { version = "1.4", optional = true, default-features = false } [dev-dependencies] rustversion = "1.0" @@ -64,4 +64,4 @@ serde = { version = "1.0", features = ["derive"] } serde_test = "1.0" sval = { version = "2.1" } sval_derive = { version = "2.1" } -value-bag = { version = "1.1", features = ["test"] } +value-bag = { version = "1.4", features = ["test"] } diff --git a/build.rs b/build.rs new file mode 100644 index 000000000..11c26a333 --- /dev/null +++ b/build.rs @@ -0,0 +1,46 @@ +//! This build script detects target platforms that lack proper support for +//! atomics and sets `cfg` flags accordingly. + +use std::env; +use std::str; + +fn main() { + let target = match rustc_target() { + Some(target) => target, + None => return, + }; + + if target_has_atomic_cas(&target) { + println!("cargo:rustc-cfg=atomic_cas"); + } + + if target_has_atomics(&target) { + println!("cargo:rustc-cfg=has_atomics"); + } + + println!("cargo:rerun-if-changed=build.rs"); +} + +fn target_has_atomic_cas(target: &str) -> bool { + match target { + "thumbv6m-none-eabi" + | "msp430-none-elf" + | "riscv32i-unknown-none-elf" + | "riscv32imc-unknown-none-elf" => false, + _ => true, + } +} + +fn target_has_atomics(target: &str) -> bool { + match target { + "thumbv4t-none-eabi" + | "msp430-none-elf" + | "riscv32i-unknown-none-elf" + | "riscv32imc-unknown-none-elf" => false, + _ => true, + } +} + +fn rustc_target() -> Option { + env::var("TARGET").ok() +} diff --git a/src/lib.rs b/src/lib.rs index c809db36c..82c648a4d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -344,20 +344,20 @@ mod serde; #[cfg(feature = "kv_unstable")] pub mod kv; -#[cfg(target_has_atomic = "ptr")] +#[cfg(has_atomics)] use std::sync::atomic::{AtomicUsize, Ordering}; -#[cfg(not(target_has_atomic = "ptr"))] +#[cfg(not(has_atomics))] use std::cell::Cell; -#[cfg(not(target_has_atomic = "ptr"))] +#[cfg(not(has_atomics))] use std::sync::atomic::Ordering; -#[cfg(not(target_has_atomic = "ptr"))] +#[cfg(not(has_atomics))] struct AtomicUsize { v: Cell, } -#[cfg(not(target_has_atomic = "ptr"))] +#[cfg(not(has_atomics))] impl AtomicUsize { const fn new(v: usize) -> AtomicUsize { AtomicUsize { v: Cell::new(v) } @@ -371,7 +371,7 @@ impl AtomicUsize { self.v.set(val) } - #[cfg(target_has_atomic = "ptr")] + #[cfg(atomic_cas)] fn compare_exchange( &self, current: usize, @@ -389,7 +389,7 @@ impl AtomicUsize { // Any platform without atomics is unlikely to have multiple cores, so // writing via Cell will not be a race condition. -#[cfg(not(target_has_atomic = "ptr"))] +#[cfg(not(has_atomics))] unsafe impl Sync for AtomicUsize {} // The LOGGER static holds a pointer to the global logger. It is protected by @@ -1217,7 +1217,6 @@ where /// /// Note that `Trace` is the maximum level, because it provides the maximum amount of detail in the emitted logs. #[inline] -#[cfg(target_has_atomic = "ptr")] pub fn set_max_level(level: LevelFilter) { MAX_LOG_LEVEL_FILTER.store(level as usize, Ordering::Relaxed); } @@ -1286,7 +1285,7 @@ pub fn max_level() -> LevelFilter { /// An error is returned if a logger has already been set. /// /// [`set_logger`]: fn.set_logger.html -#[cfg(all(feature = "std", target_has_atomic = "ptr"))] +#[cfg(all(feature = "std", atomic_cas))] pub fn set_boxed_logger(logger: Box) -> Result<(), SetLoggerError> { set_logger_inner(|| Box::leak(logger)) } @@ -1344,12 +1343,12 @@ pub fn set_boxed_logger(logger: Box) -> Result<(), SetLoggerError> { /// ``` /// /// [`set_logger_racy`]: fn.set_logger_racy.html -#[cfg(target_has_atomic = "ptr")] +#[cfg(atomic_cas)] pub fn set_logger(logger: &'static dyn Log) -> Result<(), SetLoggerError> { set_logger_inner(|| logger) } -#[cfg(target_has_atomic = "ptr")] +#[cfg(atomic_cas)] fn set_logger_inner(make_logger: F) -> Result<(), SetLoggerError> where F: FnOnce() -> &'static dyn Log, From d062c83c4cb8d62e8a8dbe05d7559b075e32ae06 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Sun, 28 May 2023 14:01:27 +1000 Subject: [PATCH 121/280] prepare for 0.4.18 release --- CHANGELOG.md | 20 ++++++++++++++++++++ Cargo.toml | 2 +- src/lib.rs | 2 +- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c697fa93..a6f251b3f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,26 @@ ## [Unreleased] +## [0.4.18] - 2023-05-28 + +* fix markdown links (again) by @hellow554 in https://github.com/rust-lang/log/pull/513 +* add cargo doc to workflow by @hellow554 in https://github.com/rust-lang/log/pull/515 +* Apply Clippy lints by @hellow554 in https://github.com/rust-lang/log/pull/516 +* Replace ad-hoc eq_ignore_ascii_case with slice::eq_ignore_ascii_case by @glandium in https://github.com/rust-lang/log/pull/519 +* fix up windows targets by @KodrAus in https://github.com/rust-lang/log/pull/528 +* typo fix by @jiangying000 in https://github.com/rust-lang/log/pull/529 +* Remove dependency on cfg_if by @EriKWDev in https://github.com/rust-lang/log/pull/536 +* GitHub Workflows security hardening by @sashashura in https://github.com/rust-lang/log/pull/538 +* Fix build status badge by @atouchet in https://github.com/rust-lang/log/pull/539 +* Add call_logger to the documentation by @a1ecbr0wn in https://github.com/rust-lang/log/pull/547 +* Remove build.rs file by @GuillaumeGomez in https://github.com/rust-lang/log/pull/543 +* Use stable internals for key-value API by @KodrAus in https://github.com/rust-lang/log/pull/550 +* Change wording of list of implementations by @Thomasdezeeuw in https://github.com/rust-lang/log/pull/553 +* Add std-logger to list of implementations by @Thomasdezeeuw in https://github.com/rust-lang/log/pull/554 +* Add `set_max_level_racy` and gate `set_max_level` by @djkoloski in https://github.com/rust-lang/log/pull/544 +* [doc] src/lib.rs : prefix an unused variable with an underscore by @OccupyMars2025 in https://github.com/rust-lang/log/pull/561 +* [doc] src/macros.rs : correct grammar errors of an example in lib documentation by @OccupyMars2025 in https://github.com/rust-lang/log/pull/562 + ## [0.4.17] - 2022-04-29 * Update `kv_unstable` internal dependencies. diff --git a/Cargo.toml b/Cargo.toml index 786f74dae..5004b08fa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "log" -version = "0.4.17" # remember to update html_root_url +version = "0.4.18" # remember to update html_root_url authors = ["The Rust Project Developers"] license = "MIT OR Apache-2.0" readme = "README.md" diff --git a/src/lib.rs b/src/lib.rs index 82c648a4d..4297344e0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -317,7 +317,7 @@ #![doc( html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://www.rust-lang.org/favicon.ico", - html_root_url = "https://docs.rs/log/0.4.17" + html_root_url = "https://docs.rs/log/0.4.18" )] #![warn(missing_docs)] #![deny(missing_debug_implementations, unconditional_recursion)] From 3c8473d9ed17f12db4487062f64eab705ea803b3 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Tue, 11 Apr 2023 10:48:11 +1000 Subject: [PATCH 122/280] Revert "Revert "Remove build.rs file"" This reverts commit 4e689bbb8f7dc7c465e6367b7022f347a0fe09e9. --- .github/workflows/main.yml | 4 ++-- CHANGELOG.md | 9 +++++++- Cargo.toml | 2 +- build.rs | 46 -------------------------------------- src/lib.rs | 9 ++++---- 5 files changed, 16 insertions(+), 54 deletions(-) delete mode 100644 build.rs diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f38d3b33e..c2f5af492 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -127,8 +127,8 @@ jobs: - uses: actions/checkout@master - name: Install Rust run: | - rustup update 1.31.0 --no-self-update - rustup default 1.31.0 + rustup update 1.60.0 --no-self-update + rustup default 1.60.0 - run: cargo test --verbose --manifest-path tests/Cargo.toml embedded: diff --git a/CHANGELOG.md b/CHANGELOG.md index a6f251b3f..305518965 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ## [Unreleased] +## [0.4.19] - 2023-06-10 + +* Use target_has_atomic instead of the old atomic_cas cfg by @KodrAus in https://github.com/rust-lang/log/pull/555 +* Put MSRV into Cargo.toml by @est31 in https://github.com/rust-lang/log/pull/557 + ## [0.4.18] - 2023-05-28 * fix markdown links (again) by @hellow554 in https://github.com/rust-lang/log/pull/513 @@ -239,7 +244,9 @@ version using log 0.4.x to avoid losing module and file information. Look at the [release tags] for information about older releases. -[Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.17...HEAD +[Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.18...HEAD +[0.4.19]: https://github.com/rust-lang-nursery/log/compare/0.4.18...0.4.19 +[0.4.18]: https://github.com/rust-lang-nursery/log/compare/0.4.17...0.4.18 [0.4.17]: https://github.com/rust-lang-nursery/log/compare/0.4.16...0.4.17 [0.4.16]: https://github.com/rust-lang-nursery/log/compare/0.4.15...0.4.16 [0.4.15]: https://github.com/rust-lang-nursery/log/compare/0.4.13...0.4.15 diff --git a/Cargo.toml b/Cargo.toml index 5004b08fa..eabb2c4fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ A lightweight logging facade for Rust categories = ["development-tools::debugging"] keywords = ["logging"] exclude = ["rfcs/**/*"] -build = "build.rs" +rust-version = "1.60.0" [package.metadata.docs.rs] features = ["std", "serde", "kv_unstable_std", "kv_unstable_sval", "kv_unstable_serde"] diff --git a/build.rs b/build.rs deleted file mode 100644 index 11c26a333..000000000 --- a/build.rs +++ /dev/null @@ -1,46 +0,0 @@ -//! This build script detects target platforms that lack proper support for -//! atomics and sets `cfg` flags accordingly. - -use std::env; -use std::str; - -fn main() { - let target = match rustc_target() { - Some(target) => target, - None => return, - }; - - if target_has_atomic_cas(&target) { - println!("cargo:rustc-cfg=atomic_cas"); - } - - if target_has_atomics(&target) { - println!("cargo:rustc-cfg=has_atomics"); - } - - println!("cargo:rerun-if-changed=build.rs"); -} - -fn target_has_atomic_cas(target: &str) -> bool { - match target { - "thumbv6m-none-eabi" - | "msp430-none-elf" - | "riscv32i-unknown-none-elf" - | "riscv32imc-unknown-none-elf" => false, - _ => true, - } -} - -fn target_has_atomics(target: &str) -> bool { - match target { - "thumbv4t-none-eabi" - | "msp430-none-elf" - | "riscv32i-unknown-none-elf" - | "riscv32imc-unknown-none-elf" => false, - _ => true, - } -} - -fn rustc_target() -> Option { - env::var("TARGET").ok() -} diff --git a/src/lib.rs b/src/lib.rs index 4297344e0..c669206a4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -371,7 +371,7 @@ impl AtomicUsize { self.v.set(val) } - #[cfg(atomic_cas)] + #[cfg(target_has_atomic = "ptr")] fn compare_exchange( &self, current: usize, @@ -1217,6 +1217,7 @@ where /// /// Note that `Trace` is the maximum level, because it provides the maximum amount of detail in the emitted logs. #[inline] +#[cfg(target_has_atomic = "ptr")] pub fn set_max_level(level: LevelFilter) { MAX_LOG_LEVEL_FILTER.store(level as usize, Ordering::Relaxed); } @@ -1285,7 +1286,7 @@ pub fn max_level() -> LevelFilter { /// An error is returned if a logger has already been set. /// /// [`set_logger`]: fn.set_logger.html -#[cfg(all(feature = "std", atomic_cas))] +#[cfg(all(feature = "std", target_has_atomic = "ptr"))] pub fn set_boxed_logger(logger: Box) -> Result<(), SetLoggerError> { set_logger_inner(|| Box::leak(logger)) } @@ -1343,12 +1344,12 @@ pub fn set_boxed_logger(logger: Box) -> Result<(), SetLoggerError> { /// ``` /// /// [`set_logger_racy`]: fn.set_logger_racy.html -#[cfg(atomic_cas)] +#[cfg(target_has_atomic = "ptr")] pub fn set_logger(logger: &'static dyn Log) -> Result<(), SetLoggerError> { set_logger_inner(|| logger) } -#[cfg(atomic_cas)] +#[cfg(target_has_atomic = "ptr")] fn set_logger_inner(make_logger: F) -> Result<(), SetLoggerError> where F: FnOnce() -> &'static dyn Log, From 54d48fb53e6ba9cb059968c48dc9580bee4fc003 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Sun, 28 May 2023 14:15:58 +1000 Subject: [PATCH 123/280] prepare for 0.4.19 release --- Cargo.toml | 2 +- src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index eabb2c4fb..fa9ef428b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "log" -version = "0.4.18" # remember to update html_root_url +version = "0.4.19" # remember to update html_root_url authors = ["The Rust Project Developers"] license = "MIT OR Apache-2.0" readme = "README.md" diff --git a/src/lib.rs b/src/lib.rs index c669206a4..e6a41d9c2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -317,7 +317,7 @@ #![doc( html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://www.rust-lang.org/favicon.ico", - html_root_url = "https://docs.rs/log/0.4.18" + html_root_url = "https://docs.rs/log/0.4.19" )] #![warn(missing_docs)] #![deny(missing_debug_implementations, unconditional_recursion)] From 92e83c04f3dfc99c71c63e6f144878517f0fd563 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Sun, 28 May 2023 14:24:22 +1000 Subject: [PATCH 124/280] fixes for unrevert --- src/lib.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index e6a41d9c2..d267d9e53 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -344,20 +344,20 @@ mod serde; #[cfg(feature = "kv_unstable")] pub mod kv; -#[cfg(has_atomics)] +#[cfg(target_has_atomic = "ptr")] use std::sync::atomic::{AtomicUsize, Ordering}; -#[cfg(not(has_atomics))] +#[cfg(not(target_has_atomic = "ptr"))] use std::cell::Cell; -#[cfg(not(has_atomics))] +#[cfg(not(target_has_atomic = "ptr"))] use std::sync::atomic::Ordering; -#[cfg(not(has_atomics))] +#[cfg(not(target_has_atomic = "ptr"))] struct AtomicUsize { v: Cell, } -#[cfg(not(has_atomics))] +#[cfg(not(target_has_atomic = "ptr"))] impl AtomicUsize { const fn new(v: usize) -> AtomicUsize { AtomicUsize { v: Cell::new(v) } @@ -389,7 +389,7 @@ impl AtomicUsize { // Any platform without atomics is unlikely to have multiple cores, so // writing via Cell will not be a race condition. -#[cfg(not(has_atomics))] +#[cfg(not(target_has_atomic = "ptr"))] unsafe impl Sync for AtomicUsize {} // The LOGGER static holds a pointer to the global logger. It is protected by From db9e5cc2140cfb5ab0a39c84769ccd887323a49a Mon Sep 17 00:00:00 2001 From: 0xZensh Date: Tue, 28 Mar 2023 20:35:38 +0800 Subject: [PATCH 125/280] Add the structured-logger crate to the README Signed-off-by: Yan Qing --- README.md | 1 + src/lib.rs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/README.md b/README.md index dcb271b05..c6a944723 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,7 @@ There are many available implementations to choose from, here are some options: * [`flexi_logger`](https://docs.rs/flexi_logger/*/flexi_logger/) * [`call_logger`](https://docs.rs/call_logger/*/call_logger/) * [`std-logger`](https://docs.rs/std-logger/*/std_logger/) + * [`structured-logger`](https://docs.rs/structured-logger/latest/structured_logger/) * Complex configurable frameworks: * [`log4rs`](https://docs.rs/log4rs/*/log4rs/) * [`fern`](https://docs.rs/fern/*/fern/) diff --git a/src/lib.rs b/src/lib.rs index 4297344e0..0898200ea 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -137,6 +137,7 @@ //! * [stderrlog] //! * [flexi_logger] //! * [call_logger] +//! * [structured-logger] //! * Complex configurable frameworks: //! * [log4rs] //! * [fern] @@ -313,6 +314,7 @@ //! [win_dbg_logger]: https://docs.rs/win_dbg_logger/*/win_dbg_logger/ //! [db_logger]: https://docs.rs/db_logger/*/db_logger/ //! [console_log]: https://docs.rs/console_log/*/console_log/ +//! [structured-logger]: https://docs.rs/structured-logger/latest/structured_logger/ #![doc( html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", From 5322e569d0549c6c23a1dc179122b5797fba1b0a Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Mon, 29 May 2023 13:22:55 +1000 Subject: [PATCH 126/280] update changelog to reflect actual changes --- CHANGELOG.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 305518965..c45c875c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ ## [0.4.19] - 2023-06-10 -* Use target_has_atomic instead of the old atomic_cas cfg by @KodrAus in https://github.com/rust-lang/log/pull/555 +* Use target_has_atomic instead of the old atomic_cas cfg by @GuillaumeGomez in https://github.com/rust-lang/log/pull/555 * Put MSRV into Cargo.toml by @est31 in https://github.com/rust-lang/log/pull/557 ## [0.4.18] - 2023-05-28 @@ -19,7 +19,6 @@ * GitHub Workflows security hardening by @sashashura in https://github.com/rust-lang/log/pull/538 * Fix build status badge by @atouchet in https://github.com/rust-lang/log/pull/539 * Add call_logger to the documentation by @a1ecbr0wn in https://github.com/rust-lang/log/pull/547 -* Remove build.rs file by @GuillaumeGomez in https://github.com/rust-lang/log/pull/543 * Use stable internals for key-value API by @KodrAus in https://github.com/rust-lang/log/pull/550 * Change wording of list of implementations by @Thomasdezeeuw in https://github.com/rust-lang/log/pull/553 * Add std-logger to list of implementations by @Thomasdezeeuw in https://github.com/rust-lang/log/pull/554 From a556b46d3935d3e5e8a79e6858e9e9688cfd326f Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Mon, 3 Jul 2023 11:33:29 +0200 Subject: [PATCH 127/280] Remove rustversion dev-dependency Since the MSRV is now 1.60. --- Cargo.toml | 1 - tests/macros.rs | 52 ++++++++++++++++++++++--------------------------- 2 files changed, 23 insertions(+), 30 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index fa9ef428b..f4b06a562 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -59,7 +59,6 @@ sval_ref = { version = "2.1", optional = true, default-features = false } value-bag = { version = "1.4", optional = true, default-features = false } [dev-dependencies] -rustversion = "1.0" serde = { version = "1.0", features = ["derive"] } serde_test = "1.0" sval = { version = "2.1" } diff --git a/tests/macros.rs b/tests/macros.rs index 08a09b7d7..457e9a92c 100644 --- a/tests/macros.rs +++ b/tests/macros.rs @@ -157,49 +157,43 @@ fn kv_expr_context() { #[test] fn implicit_named_args() { - #[rustversion::since(1.58)] - fn _check() { - let world = "world"; + let world = "world"; - for lvl in log::Level::iter() { - log!(lvl, "hello {world}"); - log!(lvl, "hello {world}",); + for lvl in log::Level::iter() { + log!(lvl, "hello {world}"); + log!(lvl, "hello {world}",); - log!(target: "my_target", lvl, "hello {world}"); - log!(target: "my_target", lvl, "hello {world}",); + log!(target: "my_target", lvl, "hello {world}"); + log!(target: "my_target", lvl, "hello {world}",); - log!(lvl, "hello {world}"); - log!(lvl, "hello {world}",); - } + log!(lvl, "hello {world}"); + log!(lvl, "hello {world}",); + } - all_log_macros!("hello {world}"); - all_log_macros!("hello {world}",); + all_log_macros!("hello {world}"); + all_log_macros!("hello {world}",); - all_log_macros!(target: "my_target", "hello {world}"); - all_log_macros!(target: "my_target", "hello {world}",); + all_log_macros!(target: "my_target", "hello {world}"); + all_log_macros!(target: "my_target", "hello {world}",); - all_log_macros!(target = "my_target"; "hello {world}"); - all_log_macros!(target = "my_target"; "hello {world}",); - } + all_log_macros!(target = "my_target"; "hello {world}"); + all_log_macros!(target = "my_target"; "hello {world}",); } #[test] #[cfg(feature = "kv_unstable")] fn kv_implicit_named_args() { - #[rustversion::since(1.58)] - fn _check() { - let world = "world"; + let world = "world"; - for lvl in log::Level::iter() { - log!(target: "my_target", lvl, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}"); - - log!(lvl, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}"); - } + for lvl in log::Level::iter() { + log!(target: "my_target", lvl, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}"); - all_log_macros!(target: "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}"); - all_log_macros!(target = "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}"); - all_log_macros!(cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}"); + log!(lvl, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}"); } + + all_log_macros!(target: "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}"); + all_log_macros!(target = "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}"); + all_log_macros!(cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}"); } #[test] From 472e8f0952763724bae08b8259667bc836a15b4a Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Mon, 3 Jul 2023 11:52:51 +0200 Subject: [PATCH 128/280] Fix implicit_named_args test When kv_unstable is not enabled. --- tests/macros.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/macros.rs b/tests/macros.rs index 457e9a92c..228f1f5d6 100644 --- a/tests/macros.rs +++ b/tests/macros.rs @@ -176,7 +176,9 @@ fn implicit_named_args() { all_log_macros!(target: "my_target", "hello {world}"); all_log_macros!(target: "my_target", "hello {world}",); + #[cfg(feature = "kv_unstable")] all_log_macros!(target = "my_target"; "hello {world}"); + #[cfg(feature = "kv_unstable")] all_log_macros!(target = "my_target"; "hello {world}",); } From c175ad4b824a077d946578bd0f466a9bc3c1dda4 Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Mon, 3 Jul 2023 23:38:49 +0200 Subject: [PATCH 129/280] Hack around proc-macro2 version Done to make the minimal (crate) version CI happy. --- Cargo.toml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index f4b06a562..3ba01de0a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -64,3 +64,11 @@ serde_test = "1.0" sval = { version = "2.1" } sval_derive = { version = "2.1" } value-bag = { version = "1.4", features = ["test"] } + +# NOTE: log doesn't actually depent on this crate. However our dependencies, +# serde and sval, dependent on version 1.0 of the crate, which has problem fixed +# in 1.0.60, specifically in the following commit +# https://github.com/dtolnay/proc-macro2/commit/e31d61910049e097afdd3d27c37786309082bdcb. +# By defining the crate as direct dependency we can increase it's minimal +# version making the minimal (crate) version CI happy. +proc-macro2 = { version = "1.0.63", default-features = false } From 9d052b17d3ddf9b5894740c6d82899c531c789ee Mon Sep 17 00:00:00 2001 From: EFanZh Date: Tue, 11 Jul 2023 00:05:28 +0800 Subject: [PATCH 130/280] Remove `local_inner_macros` usage --- src/lib.rs | 1 + src/macros.rs | 92 ++++++++++++++------------------------------------- 2 files changed, 26 insertions(+), 67 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 95f261d78..f19f00f99 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1523,6 +1523,7 @@ pub fn __private_api_enabled(level: Level, target: &str) -> bool { #[doc(hidden)] pub mod __private_api { pub use std::option::Option; + pub use std::{file, format_args, line, module_path, stringify}; } /// The statically resolved maximum log level. diff --git a/src/macros.rs b/src/macros.rs index 84143dd37..a66c92a4e 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -27,17 +27,17 @@ /// data.0, data.1, private_data); /// # } /// ``` -#[macro_export(local_inner_macros)] +#[macro_export] macro_rules! log { // log!(target: "my_target", Level::Info, key1 = 42, key2 = true; "a {} event", "log"); (target: $target:expr, $lvl:expr, $($key:tt = $value:expr),+; $($arg:tt)+) => ({ let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { $crate::__private_api_log( - __log_format_args!($($arg)+), + $crate::__private_api::format_args!($($arg)+), lvl, - &($target, __log_module_path!(), __log_file!(), __log_line!()), - $crate::__private_api::Option::Some(&[$((__log_key!($key), &$value)),+]) + &($target, $crate::__private_api::module_path!(), $crate::__private_api::file!(), $crate::__private_api::line!()), + $crate::__private_api::Option::Some(&[$(($crate::__log_key!($key), &$value)),+]) ); } }); @@ -47,16 +47,16 @@ macro_rules! log { let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { $crate::__private_api_log( - __log_format_args!($($arg)+), + $crate::__private_api::format_args!($($arg)+), lvl, - &($target, __log_module_path!(), __log_file!(), __log_line!()), + &($target, $crate::__private_api::module_path!(), $crate::__private_api::file!(), $crate::__private_api::line!()), $crate::__private_api::Option::None, ); } }); // log!(Level::Info, "a log event") - ($lvl:expr, $($arg:tt)+) => (log!(target: __log_module_path!(), $lvl, $($arg)+)); + ($lvl:expr, $($arg:tt)+) => ($crate::log!(target: $crate::__private_api::module_path!(), $lvl, $($arg)+)); } /// Logs a message at the error level. @@ -73,14 +73,14 @@ macro_rules! log { /// error!(target: "app_events", "App Error: {}, Port: {}", err_info, 22); /// # } /// ``` -#[macro_export(local_inner_macros)] +#[macro_export] macro_rules! error { // error!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log") // error!(target: "my_target", "a {} event", "log") - (target: $target:expr, $($arg:tt)+) => (log!(target: $target, $crate::Level::Error, $($arg)+)); + (target: $target:expr, $($arg:tt)+) => ($crate::log!(target: $target, $crate::Level::Error, $($arg)+)); // error!("a {} event", "log") - ($($arg:tt)+) => (log!($crate::Level::Error, $($arg)+)) + ($($arg:tt)+) => ($crate::log!($crate::Level::Error, $($arg)+)) } /// Logs a message at the warn level. @@ -97,14 +97,14 @@ macro_rules! error { /// warn!(target: "input_events", "App received warning: {}", warn_description); /// # } /// ``` -#[macro_export(local_inner_macros)] +#[macro_export] macro_rules! warn { // warn!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log") // warn!(target: "my_target", "a {} event", "log") - (target: $target:expr, $($arg:tt)+) => (log!(target: $target, $crate::Level::Warn, $($arg)+)); + (target: $target:expr, $($arg:tt)+) => ($crate::log!(target: $target, $crate::Level::Warn, $($arg)+)); // warn!("a {} event", "log") - ($($arg:tt)+) => (log!($crate::Level::Warn, $($arg)+)) + ($($arg:tt)+) => ($crate::log!($crate::Level::Warn, $($arg)+)) } /// Logs a message at the info level. @@ -123,14 +123,14 @@ macro_rules! warn { /// conn_info.port, conn_info.speed); /// # } /// ``` -#[macro_export(local_inner_macros)] +#[macro_export] macro_rules! info { // info!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log") // info!(target: "my_target", "a {} event", "log") - (target: $target:expr, $($arg:tt)+) => (log!(target: $target, $crate::Level::Info, $($arg)+)); + (target: $target:expr, $($arg:tt)+) => ($crate::log!(target: $target, $crate::Level::Info, $($arg)+)); // info!("a {} event", "log") - ($($arg:tt)+) => (log!($crate::Level::Info, $($arg)+)) + ($($arg:tt)+) => ($crate::log!($crate::Level::Info, $($arg)+)) } /// Logs a message at the debug level. @@ -148,14 +148,14 @@ macro_rules! info { /// debug!(target: "app_events", "New position: x: {}, y: {}", pos.x, pos.y); /// # } /// ``` -#[macro_export(local_inner_macros)] +#[macro_export] macro_rules! debug { // debug!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log") // debug!(target: "my_target", "a {} event", "log") - (target: $target:expr, $($arg:tt)+) => (log!(target: $target, $crate::Level::Debug, $($arg)+)); + (target: $target:expr, $($arg:tt)+) => ($crate::log!(target: $target, $crate::Level::Debug, $($arg)+)); // debug!("a {} event", "log") - ($($arg:tt)+) => (log!($crate::Level::Debug, $($arg)+)) + ($($arg:tt)+) => ($crate::log!($crate::Level::Debug, $($arg)+)) } /// Logs a message at the trace level. @@ -175,14 +175,14 @@ macro_rules! debug { /// if pos.y >= 0.0 { "positive" } else { "negative" }); /// # } /// ``` -#[macro_export(local_inner_macros)] +#[macro_export] macro_rules! trace { // trace!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log") // trace!(target: "my_target", "a {} event", "log") - (target: $target:expr, $($arg:tt)+) => (log!(target: $target, $crate::Level::Trace, $($arg)+)); + (target: $target:expr, $($arg:tt)+) => ($crate::log!(target: $target, $crate::Level::Trace, $($arg)+)); // trace!("a {} event", "log") - ($($arg:tt)+) => (log!($crate::Level::Trace, $($arg)+)) + ($($arg:tt)+) => ($crate::log!($crate::Level::Trace, $($arg)+)) } /// Determines if a message logged at the specified level in that module will @@ -211,7 +211,7 @@ macro_rules! trace { /// # fn expensive_call() -> Data { Data { x: 0, y: 0 } } /// # fn main() {} /// ``` -#[macro_export(local_inner_macros)] +#[macro_export] macro_rules! log_enabled { (target: $target:expr, $lvl:expr) => {{ let lvl = $lvl; @@ -220,49 +220,7 @@ macro_rules! log_enabled { && $crate::__private_api_enabled(lvl, $target) }}; ($lvl:expr) => { - log_enabled!(target: __log_module_path!(), $lvl) - }; -} - -// The log macro above cannot invoke format_args directly because it uses -// local_inner_macros. A format_args invocation there would resolve to -// $crate::format_args which does not exist. Instead invoke format_args here -// outside of local_inner_macros so that it resolves (probably) to -// core::format_args or std::format_args. Same for the several macros that -// follow. -// -// This is a workaround until we drop support for pre-1.30 compilers. At that -// point we can remove use of local_inner_macros, use $crate:: when invoking -// local macros, and invoke format_args directly. -#[doc(hidden)] -#[macro_export] -macro_rules! __log_format_args { - ($($args:tt)*) => { - format_args!($($args)*) - }; -} - -#[doc(hidden)] -#[macro_export] -macro_rules! __log_module_path { - () => { - module_path!() - }; -} - -#[doc(hidden)] -#[macro_export] -macro_rules! __log_file { - () => { - file!() - }; -} - -#[doc(hidden)] -#[macro_export] -macro_rules! __log_line { - () => { - line!() + $crate::log_enabled!(target: $crate::__private_api::module_path!(), $lvl) }; } @@ -271,7 +229,7 @@ macro_rules! __log_line { macro_rules! __log_key { // key1 = 42 ($($args:ident)*) => { - stringify!($($args)*) + $crate::__private_api::stringify!($($args)*) }; // "key1" = 42 ($($args:expr)*) => { From 6d173bf94114f62217349b76bc18ed4340f12586 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Tue, 11 Jul 2023 10:07:57 +1000 Subject: [PATCH 131/280] prepare for 0.4.20 release --- CHANGELOG.md | 6 ++++++ Cargo.toml | 2 +- src/lib.rs | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c45c875c1..60870804a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ## [Unreleased] +## [0.4.20] - 2023-07-11 + +* Remove rustversion dev-dependency by @Thomasdezeeuw in https://github.com/rust-lang/log/pull/568 +* Remove `local_inner_macros` usage by @EFanZh in https://github.com/rust-lang/log/pull/570 + ## [0.4.19] - 2023-06-10 * Use target_has_atomic instead of the old atomic_cas cfg by @GuillaumeGomez in https://github.com/rust-lang/log/pull/555 @@ -244,6 +249,7 @@ version using log 0.4.x to avoid losing module and file information. Look at the [release tags] for information about older releases. [Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.18...HEAD +[0.4.20]: https://github.com/rust-lang-nursery/log/compare/0.4.19...0.4.20 [0.4.19]: https://github.com/rust-lang-nursery/log/compare/0.4.18...0.4.19 [0.4.18]: https://github.com/rust-lang-nursery/log/compare/0.4.17...0.4.18 [0.4.17]: https://github.com/rust-lang-nursery/log/compare/0.4.16...0.4.17 diff --git a/Cargo.toml b/Cargo.toml index 3ba01de0a..77ed145ef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "log" -version = "0.4.19" # remember to update html_root_url +version = "0.4.20" # remember to update html_root_url authors = ["The Rust Project Developers"] license = "MIT OR Apache-2.0" readme = "README.md" diff --git a/src/lib.rs b/src/lib.rs index f19f00f99..a9b14c33f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -319,7 +319,7 @@ #![doc( html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://www.rust-lang.org/favicon.ico", - html_root_url = "https://docs.rs/log/0.4.19" + html_root_url = "https://docs.rs/log/0.4.20" )] #![warn(missing_docs)] #![deny(missing_debug_implementations, unconditional_recursion)] From f5ab686e9b1ce6962dd4e02d6cc71a1d7ec48ea6 Mon Sep 17 00:00:00 2001 From: chrysn Date: Thu, 27 Jul 2023 13:45:18 +0200 Subject: [PATCH 132/280] doc: Add log-to-defmt to other-facilities section --- README.md | 1 + src/lib.rs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/README.md b/README.md index c6a944723..3dd645799 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,7 @@ There are many available implementations to choose from, here are some options: * [`android_log`](https://docs.rs/android_log/*/android_log/) * [`win_dbg_logger`](https://docs.rs/win_dbg_logger/*/win_dbg_logger/) * [`db_logger`](https://docs.rs/db_logger/*/db_logger/) + * [`log-to-defmt`](https://docs.rs/log-to-defmt/*/log_to_defmt/) * For WebAssembly binaries: * [`console_log`](https://docs.rs/console_log/*/console_log/) * For dynamic libraries: diff --git a/src/lib.rs b/src/lib.rs index f19f00f99..32a0f49a5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -148,6 +148,7 @@ //! * [android_log] //! * [win_dbg_logger] //! * [db_logger] +//! * [log-to-defmt] //! * For WebAssembly binaries: //! * [console_log] //! * For dynamic libraries: @@ -313,6 +314,7 @@ //! [android_log]: https://docs.rs/android_log/*/android_log/ //! [win_dbg_logger]: https://docs.rs/win_dbg_logger/*/win_dbg_logger/ //! [db_logger]: https://docs.rs/db_logger/*/db_logger/ +//! [log-to-defmt]: https://docs.rs/log-to-defmt/*/log_to_defmt/ //! [console_log]: https://docs.rs/console_log/*/console_log/ //! [structured-logger]: https://docs.rs/structured-logger/latest/structured_logger/ From 3f534d00e485ba7f029b9ef348385154e4e51dfd Mon Sep 17 00:00:00 2001 From: EFanZh Date: Sun, 6 Aug 2023 18:50:48 +0800 Subject: [PATCH 133/280] Move private APIs into a single module --- src/__private_api.rs | 55 ++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 60 +------------------------------------------- src/macros.rs | 6 ++--- 3 files changed, 59 insertions(+), 62 deletions(-) create mode 100644 src/__private_api.rs diff --git a/src/__private_api.rs b/src/__private_api.rs new file mode 100644 index 000000000..e89c07b5c --- /dev/null +++ b/src/__private_api.rs @@ -0,0 +1,55 @@ +//! WARNING: this is not part of the crate's public API and is subject to change at any time + +use crate::{Level, Metadata, Record}; +use std::fmt::Arguments; +pub use std::option::Option; +pub use std::{file, format_args, line, module_path, stringify}; + +#[cfg(not(feature = "kv_unstable"))] +pub fn log( + args: Arguments, + level: Level, + &(target, module_path, file, line): &(&str, &'static str, &'static str, u32), + kvs: Option<&[(&str, &str)]>, +) { + if kvs.is_some() { + panic!( + "key-value support is experimental and must be enabled using the `kv_unstable` feature" + ) + } + + crate::logger().log( + &Record::builder() + .args(args) + .level(level) + .target(target) + .module_path_static(Some(module_path)) + .file_static(Some(file)) + .line(Some(line)) + .build(), + ); +} + +#[cfg(feature = "kv_unstable")] +pub fn log( + args: Arguments, + level: Level, + &(target, module_path, file, line): &(&str, &'static str, &'static str, u32), + kvs: Option<&[(&str, &dyn crate::kv::ToValue)]>, +) { + crate::logger().log( + &Record::builder() + .args(args) + .level(level) + .target(target) + .module_path_static(Some(module_path)) + .file_static(Some(file)) + .line(Some(line)) + .key_values(&kvs) + .build(), + ); +} + +pub fn enabled(level: Level, target: &str) -> bool { + crate::logger().enabled(&Metadata::builder().level(level).target(target).build()) +} diff --git a/src/lib.rs b/src/lib.rs index f19f00f99..c8df4b21c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1466,65 +1466,7 @@ pub fn logger() -> &'static dyn Log { // WARNING: this is not part of the crate's public API and is subject to change at any time #[doc(hidden)] -#[cfg(not(feature = "kv_unstable"))] -pub fn __private_api_log( - args: fmt::Arguments, - level: Level, - &(target, module_path, file, line): &(&str, &'static str, &'static str, u32), - kvs: Option<&[(&str, &str)]>, -) { - if kvs.is_some() { - panic!( - "key-value support is experimental and must be enabled using the `kv_unstable` feature" - ) - } - - logger().log( - &Record::builder() - .args(args) - .level(level) - .target(target) - .module_path_static(Some(module_path)) - .file_static(Some(file)) - .line(Some(line)) - .build(), - ); -} - -// WARNING: this is not part of the crate's public API and is subject to change at any time -#[doc(hidden)] -#[cfg(feature = "kv_unstable")] -pub fn __private_api_log( - args: fmt::Arguments, - level: Level, - &(target, module_path, file, line): &(&str, &'static str, &'static str, u32), - kvs: Option<&[(&str, &dyn kv::ToValue)]>, -) { - logger().log( - &Record::builder() - .args(args) - .level(level) - .target(target) - .module_path_static(Some(module_path)) - .file_static(Some(file)) - .line(Some(line)) - .key_values(&kvs) - .build(), - ); -} - -// WARNING: this is not part of the crate's public API and is subject to change at any time -#[doc(hidden)] -pub fn __private_api_enabled(level: Level, target: &str) -> bool { - logger().enabled(&Metadata::builder().level(level).target(target).build()) -} - -// WARNING: this is not part of the crate's public API and is subject to change at any time -#[doc(hidden)] -pub mod __private_api { - pub use std::option::Option; - pub use std::{file, format_args, line, module_path, stringify}; -} +pub mod __private_api; /// The statically resolved maximum log level. /// diff --git a/src/macros.rs b/src/macros.rs index a66c92a4e..308682b6b 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -33,7 +33,7 @@ macro_rules! log { (target: $target:expr, $lvl:expr, $($key:tt = $value:expr),+; $($arg:tt)+) => ({ let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { - $crate::__private_api_log( + $crate::__private_api::log( $crate::__private_api::format_args!($($arg)+), lvl, &($target, $crate::__private_api::module_path!(), $crate::__private_api::file!(), $crate::__private_api::line!()), @@ -46,7 +46,7 @@ macro_rules! log { (target: $target:expr, $lvl:expr, $($arg:tt)+) => ({ let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { - $crate::__private_api_log( + $crate::__private_api::log( $crate::__private_api::format_args!($($arg)+), lvl, &($target, $crate::__private_api::module_path!(), $crate::__private_api::file!(), $crate::__private_api::line!()), @@ -217,7 +217,7 @@ macro_rules! log_enabled { let lvl = $lvl; lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() - && $crate::__private_api_enabled(lvl, $target) + && $crate::__private_api::enabled(lvl, $target) }}; ($lvl:expr) => { $crate::log_enabled!(target: $crate::__private_api::module_path!(), $lvl) From 3985711f74bb75a6504c41f6f4b66ad5fd29ef41 Mon Sep 17 00:00:00 2001 From: EFanZh Date: Sun, 6 Aug 2023 18:54:26 +0800 Subject: [PATCH 134/280] Group `target`, `module_path` and `file` arguments --- src/__private_api.rs | 6 ++++-- src/macros.rs | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/__private_api.rs b/src/__private_api.rs index e89c07b5c..7304deb89 100644 --- a/src/__private_api.rs +++ b/src/__private_api.rs @@ -9,7 +9,8 @@ pub use std::{file, format_args, line, module_path, stringify}; pub fn log( args: Arguments, level: Level, - &(target, module_path, file, line): &(&str, &'static str, &'static str, u32), + &(target, module_path, file): &(&str, &'static str, &'static str), + line: u32, kvs: Option<&[(&str, &str)]>, ) { if kvs.is_some() { @@ -34,7 +35,8 @@ pub fn log( pub fn log( args: Arguments, level: Level, - &(target, module_path, file, line): &(&str, &'static str, &'static str, u32), + &(target, module_path, file): &(&str, &'static str, &'static str), + line: u32, kvs: Option<&[(&str, &dyn crate::kv::ToValue)]>, ) { crate::logger().log( diff --git a/src/macros.rs b/src/macros.rs index 308682b6b..281ff2572 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -36,7 +36,8 @@ macro_rules! log { $crate::__private_api::log( $crate::__private_api::format_args!($($arg)+), lvl, - &($target, $crate::__private_api::module_path!(), $crate::__private_api::file!(), $crate::__private_api::line!()), + &($target, $crate::__private_api::module_path!(), $crate::__private_api::file!()), + $crate::__private_api::line!(), $crate::__private_api::Option::Some(&[$(($crate::__log_key!($key), &$value)),+]) ); } @@ -49,7 +50,8 @@ macro_rules! log { $crate::__private_api::log( $crate::__private_api::format_args!($($arg)+), lvl, - &($target, $crate::__private_api::module_path!(), $crate::__private_api::file!(), $crate::__private_api::line!()), + &($target, $crate::__private_api::module_path!(), $crate::__private_api::file!()), + $crate::__private_api::line!(), $crate::__private_api::Option::None, ); } From 32d440a9682520def3d30c4ac7206a32c926badb Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Sun, 20 Aug 2023 02:26:44 -0400 Subject: [PATCH 135/280] Minor clippy nits * Fix semicolons (pedantic) * Don't duplicate var name for instantiation if not needed * Use `mar_or` instead of `map.unwrap_or` --- benches/value.rs | 8 ++++---- src/kv/source.rs | 2 +- src/lib.rs | 8 ++++---- src/serde.rs | 4 ++-- tests/macros.rs | 2 +- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/benches/value.rs b/benches/value.rs index 4e6960e80..5e46a928c 100644 --- a/benches/value.rs +++ b/benches/value.rs @@ -8,17 +8,17 @@ use log::kv::Value; #[bench] fn u8_to_value(b: &mut test::Bencher) { - b.iter(|| Value::from(1u8)) + b.iter(|| Value::from(1u8)); } #[bench] fn u8_to_value_debug(b: &mut test::Bencher) { - b.iter(|| Value::from_debug(&1u8)) + b.iter(|| Value::from_debug(&1u8)); } #[bench] fn str_to_value_debug(b: &mut test::Bencher) { - b.iter(|| Value::from_debug(&"a string")) + b.iter(|| Value::from_debug(&"a string")); } #[bench] @@ -26,5 +26,5 @@ fn custom_to_value_debug(b: &mut test::Bencher) { #[derive(Debug)] struct A; - b.iter(|| Value::from_debug(&A)) + b.iter(|| Value::from_debug(&A)); } diff --git a/src/kv/source.rs b/src/kv/source.rs index 45fc6dce4..006e2e120 100644 --- a/src/kv/source.rs +++ b/src/kv/source.rs @@ -187,7 +187,7 @@ where } fn count(&self) -> usize { - self.as_ref().map(Source::count).unwrap_or(0) + self.as_ref().map_or(0, Source::count) } } diff --git a/src/lib.rs b/src/lib.rs index ab5cdfa4a..d9a0eb353 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1191,10 +1191,10 @@ where } fn log(&self, record: &Record) { - self.as_ref().log(record) + self.as_ref().log(record); } fn flush(&self) { - self.as_ref().flush() + self.as_ref().flush(); } } @@ -1208,10 +1208,10 @@ where } fn log(&self, record: &Record) { - self.as_ref().log(record) + self.as_ref().log(record); } fn flush(&self) { - self.as_ref().flush() + self.as_ref().flush(); } } diff --git a/src/serde.rs b/src/serde.rs index 50128330f..1ddd2cb91 100644 --- a/src/serde.rs +++ b/src/serde.rs @@ -213,7 +213,7 @@ mod tests { fn level_token(variant: &'static str) -> Token { Token::UnitVariant { name: "Level", - variant: variant, + variant, } } @@ -236,7 +236,7 @@ mod tests { fn level_filter_token(variant: &'static str) -> Token { Token::UnitVariant { name: "LevelFilter", - variant: variant, + variant, } } diff --git a/tests/macros.rs b/tests/macros.rs index 228f1f5d6..b978308b2 100644 --- a/tests/macros.rs +++ b/tests/macros.rs @@ -150,7 +150,7 @@ fn kv_named_args() { fn kv_expr_context() { match "chashu" { cat_1 => { - info!(target: "target", cat_1 = cat_1, cat_2 = "nori"; "hello {}", "cats") + info!(target: "target", cat_1 = cat_1, cat_2 = "nori"; "hello {}", "cats"); } }; } From 4aa55019904eef67fc693e346dce4080d299d453 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Sun, 20 Aug 2023 02:32:16 -0400 Subject: [PATCH 136/280] Simplify Display impl For some reason, `fmt::Display for Error` uses an unusual form `match &self.inner { &Value(ref err) => err.fmt(f), ...}`. It seems `Value(err)` will work just as well. If this is actually needed, we should add some comment explaining why so --- src/kv/error.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/kv/error.rs b/src/kv/error.rs index c72d32396..9643a47f2 100644 --- a/src/kv/error.rs +++ b/src/kv/error.rs @@ -47,10 +47,10 @@ impl fmt::Display for Error { use self::Inner::*; match &self.inner { #[cfg(feature = "std")] - &Boxed(ref err) => err.fmt(f), - &Value(ref err) => err.fmt(f), - &Msg(ref msg) => msg.fmt(f), - &Fmt => fmt::Error.fmt(f), + Boxed(err) => err.fmt(f), + Value(err) => err.fmt(f), + Msg(msg) => msg.fmt(f), + Fmt => fmt::Error.fmt(f), } } } From 31b683d49f288ce83bbdc463ca1dfc2373b44ad0 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Sun, 20 Aug 2023 02:36:30 -0400 Subject: [PATCH 137/280] Set all crates to 2021 edition --- .github/workflows/main.yml | 6 ++ Cargo.toml | 1 + benches/value.rs | 3 - rfcs/0296-structured-logging.md | 2 +- src/kv/key.rs | 16 ++--- src/kv/source.rs | 107 +++++++++++++---------------- src/kv/value.rs | 52 +++++--------- src/lib.rs | 12 ++-- src/serde.rs | 105 ++++++++++++++-------------- test_max_level_features/Cargo.toml | 1 + test_max_level_features/main.rs | 17 +++-- tests/Cargo.toml | 1 + tests/filters.rs | 6 +- tests/macros.rs | 16 ++--- tests/src/lib.rs | 6 +- 15 files changed, 153 insertions(+), 198 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c2f5af492..3fc335e73 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -61,7 +61,11 @@ jobs: rustup update stable --no-self-update rustup default stable rustup component add rustfmt + # log repo does not use Cargo workspaces, so `cargo fmt` will not check all the code + # perhaps this should be changed in the future - run: cargo fmt -- --check + - run: cargo fmt --manifest-path test_max_level_features/Cargo.toml -- --check + - run: cargo fmt --manifest-path tests/Cargo.toml -- --check clippy: name: Clippy @@ -74,6 +78,8 @@ jobs: rustup default stable rustup component add clippy - run: cargo clippy --verbose + - run: cargo clippy --verbose --manifest-path test_max_level_features/Cargo.toml + - run: cargo clippy --verbose --manifest-path tests/Cargo.toml doc: name: Check Documentation diff --git a/Cargo.toml b/Cargo.toml index 77ed145ef..89012be02 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,7 @@ categories = ["development-tools::debugging"] keywords = ["logging"] exclude = ["rfcs/**/*"] rust-version = "1.60.0" +edition = "2021" [package.metadata.docs.rs] features = ["std", "serde", "kv_unstable_std", "kv_unstable_sval", "kv_unstable_serde"] diff --git a/benches/value.rs b/benches/value.rs index 5e46a928c..e43be50f7 100644 --- a/benches/value.rs +++ b/benches/value.rs @@ -1,9 +1,6 @@ #![cfg(feature = "kv_unstable")] #![feature(test)] -extern crate log; -extern crate test; - use log::kv::Value; #[bench] diff --git a/rfcs/0296-structured-logging.md b/rfcs/0296-structured-logging.md index 6a53a7abb..f722749db 100644 --- a/rfcs/0296-structured-logging.md +++ b/rfcs/0296-structured-logging.md @@ -1203,7 +1203,7 @@ Some useful adapters exist as provided methods on the `Source` trait. They're si - `by_ref` to get a reference to a `Source` within a method chain. - `chain` to concatenate one source with another. This is useful for composing implementations of `Log` together for contextual logging. -- `get` to try find the value associated with a key. This is useful for well-defined key-value pairs that a framework built over `log` might want to provide, like timestamps or message templates. +- `get` to try finding the value associated with a key. This is useful for well-defined key-value pairs that a framework built over `log` might want to provide, like timestamps or message templates. - `for_each` to execute some closure over all key-value pairs. This is a convenient way to do something with each key-value pair without having to create and implement a `Visitor`. One potential downside of `for_each` is the `Result` return value, which seems surprising when the closure itself can't fail. The `Source::for_each` call might itself fail if the underlying `visit` call fails when iterating over its key-value pairs. This shouldn't be common though, so when paired with `try_for_each`, it might be reasonable to make `for_each` return a `()` and rely on `try_for_each` for surfacing any fallibility. - `try_for_each` is like `for_each`, but takes a fallible closure. - `as_map` to get a serializable map. This is a convenient way to serialize key-value pairs without having to create and implement a `Visitor`. diff --git a/src/kv/key.rs b/src/kv/key.rs index 4f9a506ec..971c866b9 100644 --- a/src/kv/key.rs +++ b/src/kv/key.rs @@ -103,11 +103,8 @@ mod std_support { mod sval_support { use super::*; - extern crate sval; - extern crate sval_ref; - - use self::sval::Value; - use self::sval_ref::ValueRef; + use sval::Value; + use sval_ref::ValueRef; impl<'a> Value for Key<'a> { fn stream<'sval, S: sval::Stream<'sval> + ?Sized>( @@ -119,10 +116,7 @@ mod sval_support { } impl<'a> ValueRef<'a> for Key<'a> { - fn stream_ref + ?Sized>( - &self, - stream: &mut S, - ) -> self::sval::Result { + fn stream_ref + ?Sized>(&self, stream: &mut S) -> sval::Result { self.key.stream(stream) } } @@ -132,9 +126,7 @@ mod sval_support { mod serde_support { use super::*; - extern crate serde; - - use self::serde::{Serialize, Serializer}; + use serde::{Serialize, Serializer}; impl<'a> Serialize for Key<'a> { fn serialize(&self, serializer: S) -> Result diff --git a/src/kv/source.rs b/src/kv/source.rs index 006e2e120..2a26c4a05 100644 --- a/src/kv/source.rs +++ b/src/kv/source.rs @@ -1,14 +1,6 @@ //! Sources for key-value pairs. -#[cfg(feature = "kv_unstable_sval")] -extern crate sval; -#[cfg(feature = "kv_unstable_sval")] -extern crate sval_ref; - -#[cfg(feature = "kv_unstable_serde")] -extern crate serde; - -use kv::{Error, Key, ToKey, ToValue, Value}; +use crate::kv::{Error, Key, ToKey, ToValue, Value}; use std::fmt; /// A source of key-value pairs. @@ -39,12 +31,12 @@ pub trait Source { /// A source that can provide a more efficient implementation of this method /// should override it. #[cfg(not(test))] - fn get<'v>(&'v self, key: Key) -> Option> { + fn get(&self, key: Key) -> Option> { get_default(self, key) } #[cfg(test)] - fn get<'v>(&'v self, key: Key) -> Option>; + fn get(&self, key: Key) -> Option>; /// Count the number of key-value pairs that can be visited. /// @@ -64,7 +56,7 @@ pub trait Source { fn count(&self) -> usize; } -/// The default implemention of `Source::get` +/// The default implementation of `Source::get` pub(crate) fn get_default<'v>(source: &'v (impl Source + ?Sized), key: Key) -> Option> { struct Get<'k, 'v> { key: Key<'k>, @@ -112,7 +104,7 @@ where Source::visit(&**self, visitor) } - fn get<'v>(&'v self, key: Key) -> Option> { + fn get(&self, key: Key) -> Option> { Source::get(&**self, key) } @@ -130,7 +122,7 @@ where visitor.visit_pair(self.0.to_key(), self.1.to_value()) } - fn get<'v>(&'v self, key: Key) -> Option> { + fn get(&self, key: Key) -> Option> { if self.0.to_key() == key { Some(self.1.to_value()) } else { @@ -155,7 +147,7 @@ where Ok(()) } - fn get<'v>(&'v self, key: Key) -> Option> { + fn get(&self, key: Key) -> Option> { for source in self { if let Some(found) = source.get(key.clone()) { return Some(found); @@ -182,7 +174,7 @@ where Ok(()) } - fn get<'v>(&'v self, key: Key) -> Option> { + fn get(&self, key: Key) -> Option> { self.as_ref().and_then(|s| s.get(key)) } @@ -250,7 +242,7 @@ mod std_support { Source::visit(&**self, visitor) } - fn get<'v>(&'v self, key: Key) -> Option> { + fn get(&self, key: Key) -> Option> { Source::get(&**self, key) } @@ -267,7 +259,7 @@ mod std_support { Source::visit(&**self, visitor) } - fn get<'v>(&'v self, key: Key) -> Option> { + fn get(&self, key: Key) -> Option> { Source::get(&**self, key) } @@ -298,7 +290,7 @@ mod std_support { Ok(()) } - fn get<'v>(&'v self, key: Key) -> Option> { + fn get(&self, key: Key) -> Option> { HashMap::get(self, key.as_str()).map(|v| v.to_value()) } @@ -319,7 +311,7 @@ mod std_support { Ok(()) } - fn get<'v>(&'v self, key: Key) -> Option> { + fn get(&self, key: Key) -> Option> { BTreeMap::get(self, key.as_str()).map(|v| v.to_value()) } @@ -330,10 +322,12 @@ mod std_support { #[cfg(test)] mod tests { - use super::*; - use kv::value::tests::Token; use std::collections::{BTreeMap, HashMap}; + use crate::kv::value::tests::Token; + + use super::*; + #[test] fn count() { assert_eq!(1, Source::count(&Box::new(("a", 1)))); @@ -348,7 +342,7 @@ mod std_support { Source::get(&source, Key::from_str("a")).unwrap().to_token() ); - let source = Box::new(Option::None::<(&str, i32)>); + let source = Box::new(None::<(&str, i32)>); assert!(Source::get(&source, Key::from_str("a")).is_none()); } @@ -399,7 +393,7 @@ where self.0.visit(visitor) } - fn get<'v>(&'v self, key: Key) -> Option> { + fn get(&self, key: Key) -> Option> { self.0.get(key) } @@ -438,7 +432,7 @@ where self.0.visit(visitor) } - fn get<'v>(&'v self, key: Key) -> Option> { + fn get(&self, key: Key) -> Option> { self.0.get(key) } @@ -462,17 +456,17 @@ where mod sval_support { use super::*; - impl self::sval::Value for AsMap + impl sval::Value for AsMap where S: Source, { - fn stream<'sval, SV: self::sval::Stream<'sval> + ?Sized>( + fn stream<'sval, SV: sval::Stream<'sval> + ?Sized>( &'sval self, stream: &mut SV, - ) -> self::sval::Result { + ) -> sval::Result { struct StreamVisitor<'a, V: ?Sized>(&'a mut V); - impl<'a, 'kvs, V: self::sval::Stream<'kvs> + ?Sized> Visitor<'kvs> for StreamVisitor<'a, V> { + impl<'a, 'kvs, V: sval::Stream<'kvs> + ?Sized> Visitor<'kvs> for StreamVisitor<'a, V> { fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> { self.0 .map_key_begin() @@ -498,31 +492,31 @@ mod sval_support { stream .map_begin(Some(self.count())) - .map_err(|_| self::sval::Error::new())?; + .map_err(|_| sval::Error::new())?; self.visit(&mut StreamVisitor(stream)) - .map_err(|_| self::sval::Error::new())?; + .map_err(|_| sval::Error::new())?; - stream.map_end().map_err(|_| self::sval::Error::new()) + stream.map_end().map_err(|_| sval::Error::new()) } } - impl self::sval::Value for AsList + impl sval::Value for AsList where S: Source, { - fn stream<'sval, SV: self::sval::Stream<'sval> + ?Sized>( + fn stream<'sval, SV: sval::Stream<'sval> + ?Sized>( &'sval self, stream: &mut SV, - ) -> self::sval::Result { + ) -> sval::Result { struct StreamVisitor<'a, V: ?Sized>(&'a mut V); - impl<'a, 'kvs, V: self::sval::Stream<'kvs> + ?Sized> Visitor<'kvs> for StreamVisitor<'a, V> { + impl<'a, 'kvs, V: sval::Stream<'kvs> + ?Sized> Visitor<'kvs> for StreamVisitor<'a, V> { fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> { self.0 .seq_value_begin() .map_err(|_| Error::msg("failed to stream seq value"))?; - self::sval_ref::stream_ref(self.0, (key, value)) + sval_ref::stream_ref(self.0, (key, value)) .map_err(|_| Error::msg("failed to stream seq value"))?; self.0 .seq_value_end() @@ -534,37 +528,32 @@ mod sval_support { stream .seq_begin(Some(self.count())) - .map_err(|_| self::sval::Error::new())?; + .map_err(|_| sval::Error::new())?; self.visit(&mut StreamVisitor(stream)) - .map_err(|_| self::sval::Error::new())?; + .map_err(|_| sval::Error::new())?; - stream.seq_end().map_err(|_| self::sval::Error::new()) + stream.seq_end().map_err(|_| sval::Error::new()) } } #[cfg(test)] mod tests { - extern crate sval_derive; - use super::*; - - use self::sval_derive::Value; - - use crate::kv::source; + use sval_derive::Value; #[test] fn derive_stream() { #[derive(Value)] pub struct MyRecordAsMap<'a> { msg: &'a str, - kvs: source::AsMap<&'a dyn Source>, + kvs: AsMap<&'a dyn Source>, } #[derive(Value)] pub struct MyRecordAsList<'a> { msg: &'a str, - kvs: source::AsList<&'a dyn Source>, + kvs: AsList<&'a dyn Source>, } } } @@ -575,8 +564,7 @@ pub mod as_map { //! `serde` adapters for serializing a `Source` as a map. use super::*; - - use self::serde::{Serialize, Serializer}; + use serde::{Serialize, Serializer}; /// Serialize a `Source` as a map. pub fn serialize(source: &T, serializer: S) -> Result @@ -593,8 +581,7 @@ pub mod as_list { //! `serde` adapters for serializing a `Source` as a list. use super::*; - - use self::serde::{Serialize, Serializer}; + use serde::{Serialize, Serializer}; /// Serialize a `Source` as a list. pub fn serialize(source: &T, serializer: S) -> Result @@ -609,8 +596,7 @@ pub mod as_list { #[cfg(feature = "kv_unstable_serde")] mod serde_support { use super::*; - - use self::serde::ser::{Error as SerError, Serialize, SerializeMap, SerializeSeq, Serializer}; + use serde::ser::{Error as SerError, Serialize, SerializeMap, SerializeSeq, Serializer}; impl Serialize for AsMap where @@ -677,10 +663,8 @@ mod serde_support { #[cfg(test)] mod tests { use super::*; - - use self::serde::Serialize; - use crate::kv::source; + use serde::Serialize; #[test] fn derive_serialize() { @@ -705,8 +689,9 @@ mod serde_support { #[cfg(test)] mod tests { + use crate::kv::value::tests::Token; + use super::*; - use kv::value::tests::Token; #[test] fn source_is_object_safe() { @@ -730,7 +715,7 @@ mod tests { visitor.visit_pair(self.key.to_key(), self.value.to_value()) } - fn get<'v>(&'v self, key: Key) -> Option> { + fn get(&self, key: Key) -> Option> { get_default(self, key) } @@ -741,7 +726,7 @@ mod tests { assert_eq!(1, Source::count(&("a", 1))); assert_eq!(2, Source::count(&[("a", 1), ("b", 2)] as &[_])); - assert_eq!(0, Source::count(&Option::None::<(&str, i32)>)); + assert_eq!(0, Source::count(&None::<(&str, i32)>)); assert_eq!(1, Source::count(&OnePair { key: "a", value: 1 })); } @@ -758,7 +743,7 @@ mod tests { ); assert!(Source::get(&source, Key::from_str("c")).is_none()); - let source = Option::None::<(&str, i32)>; + let source = None::<(&str, i32)>; assert!(Source::get(&source, Key::from_str("a")).is_none()); } diff --git a/src/kv/value.rs b/src/kv/value.rs index 9485d485b..d4c45ea7f 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -2,19 +2,9 @@ use std::fmt; -extern crate value_bag; +pub use crate::kv::Error; -#[cfg(feature = "kv_unstable_sval")] -extern crate sval; -#[cfg(feature = "kv_unstable_sval")] -extern crate sval_ref; - -#[cfg(feature = "kv_unstable_serde")] -extern crate serde; - -use self::value_bag::ValueBag; - -pub use kv::Error; +use value_bag::ValueBag; /// A type that can be converted into a [`Value`](struct.Value.html). pub trait ToValue { @@ -199,7 +189,7 @@ impl<'v> Value<'v> { /// Get a value from a type implementing `serde::Serialize`. pub fn capture_serde(value: &'v T) -> Self where - T: self::serde::Serialize + 'static, + T: serde::Serialize + 'static, { Value { inner: ValueBag::capture_serde1(value), @@ -210,7 +200,7 @@ impl<'v> Value<'v> { #[cfg(feature = "kv_unstable_sval")] pub fn capture_sval(value: &'v T) -> Self where - T: self::sval::Value + 'static, + T: sval::Value + 'static, { Value { inner: ValueBag::capture_sval2(value), @@ -241,7 +231,7 @@ impl<'v> Value<'v> { #[cfg(feature = "kv_unstable_serde")] pub fn from_serde(value: &'v T) -> Self where - T: self::serde::Serialize, + T: serde::Serialize, { Value { inner: ValueBag::from_serde1(value), @@ -252,7 +242,7 @@ impl<'v> Value<'v> { #[cfg(feature = "kv_unstable_sval")] pub fn from_sval(value: &'v T) -> Self where - T: self::sval::Value, + T: sval::Value, { Value { inner: ValueBag::from_sval2(value), @@ -406,29 +396,26 @@ impl ToValue for dyn std::error::Error + 'static { } #[cfg(feature = "kv_unstable_serde")] -impl<'v> self::serde::Serialize for Value<'v> { +impl<'v> serde::Serialize for Value<'v> { fn serialize(&self, s: S) -> Result where - S: self::serde::Serializer, + S: serde::Serializer, { self.inner.serialize(s) } } #[cfg(feature = "kv_unstable_sval")] -impl<'v> self::sval::Value for Value<'v> { - fn stream<'sval, S: self::sval::Stream<'sval> + ?Sized>( - &'sval self, - stream: &mut S, - ) -> self::sval::Result { - self::sval::Value::stream(&self.inner, stream) +impl<'v> sval::Value for Value<'v> { + fn stream<'sval, S: sval::Stream<'sval> + ?Sized>(&'sval self, stream: &mut S) -> sval::Result { + sval::Value::stream(&self.inner, stream) } } #[cfg(feature = "kv_unstable_sval")] -impl<'v> self::sval_ref::ValueRef<'v> for Value<'v> { - fn stream_ref + ?Sized>(&self, stream: &mut S) -> self::sval::Result { - self::sval_ref::ValueRef::stream_ref(&self.inner, stream) +impl<'v> sval_ref::ValueRef<'v> for Value<'v> { + fn stream_ref + ?Sized>(&self, stream: &mut S) -> sval::Result { + sval_ref::ValueRef::stream_ref(&self.inner, stream) } } @@ -601,10 +588,10 @@ impl<'v> Value<'v> { #[cfg(feature = "kv_unstable_std")] mod std_support { - use super::*; - use std::borrow::Cow; + use super::*; + impl ToValue for Box where T: ToValue + ?Sized, @@ -773,8 +760,7 @@ where #[cfg(test)] pub(crate) mod tests { use super::*; - - pub(crate) use super::value_bag::test::TestToken as Token; + pub(crate) use value_bag::test::TestToken as Token; impl<'v> Value<'v> { pub(crate) fn to_token(&self) -> Token { @@ -874,7 +860,7 @@ pub(crate) mod tests { assert_eq!("a loong string".to_value().to_string(), "a loong string"); assert_eq!(Some(true).to_value().to_string(), "true"); assert_eq!(().to_value().to_string(), "None"); - assert_eq!(Option::None::.to_value().to_string(), "None"); + assert_eq!(None::.to_value().to_string(), "None"); } #[test] @@ -890,7 +876,7 @@ pub(crate) mod tests { ); assert_eq!(Some(true).to_value().to_token(), Token::Bool(true)); assert_eq!(().to_value().to_token(), Token::None); - assert_eq!(Option::None::.to_value().to_token(), Token::None); + assert_eq!(None::.to_value().to_token(), Token::None); } #[test] diff --git a/src/lib.rs b/src/lib.rs index d9a0eb353..cc5172b8f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -93,7 +93,7 @@ //! some additional context besides what's in the formatted message: //! //! ```edition2018 -//! # #[macro_use] extern crate serde; +//! # use serde::Serialize; //! # #[derive(Debug, Serialize)] pub struct Yak(String); //! # impl Yak { fn shave(&mut self, _: u32) {} } //! # fn find_a_razor() -> Result { Ok(1) } @@ -334,12 +334,10 @@ #[cfg(all(not(feature = "std"), not(test)))] extern crate core as std; -use std::cmp; #[cfg(feature = "std")] use std::error; -use std::fmt; -use std::mem; use std::str::FromStr; +use std::{cmp, fmt, mem}; #[macro_use] mod macros; @@ -906,7 +904,7 @@ impl<'a> RecordBuilder<'a> { file: None, line: None, #[cfg(feature = "kv_unstable")] - key_values: KeyValues(&Option::None::<(kv::Key, kv::Value)>), + key_values: KeyValues(&None::<(kv::Key, kv::Value)>), }, } } @@ -1537,9 +1535,7 @@ const fn get_max_level_inner() -> LevelFilter { #[cfg(test)] mod tests { - extern crate std; use super::{Level, LevelFilter, ParseLevelError}; - use tests::std::string::ToString; #[test] fn test_levelfilter_from_str() { @@ -1748,7 +1744,7 @@ mod tests { #[cfg(feature = "kv_unstable")] fn test_record_key_values_builder() { use super::Record; - use kv::{self, Visitor}; + use crate::kv::{self, Visitor}; struct TestVisitor { seen_pairs: usize, diff --git a/src/serde.rs b/src/serde.rs index 1ddd2cb91..63bef7f97 100644 --- a/src/serde.rs +++ b/src/serde.rs @@ -1,13 +1,12 @@ #![cfg(feature = "serde")] -extern crate serde; -use self::serde::de::{ +use serde::de::{ Deserialize, DeserializeSeed, Deserializer, EnumAccess, Error, Unexpected, VariantAccess, Visitor, }; -use self::serde::ser::{Serialize, Serializer}; +use serde::ser::{Serialize, Serializer}; -use {Level, LevelFilter, LOG_LEVEL_NAMES}; +use crate::{Level, LevelFilter, LOG_LEVEL_NAMES}; use std::fmt; use std::str::{self, FromStr}; @@ -43,6 +42,17 @@ impl<'de> Deserialize<'de> for Level { formatter.write_str("log level") } + fn visit_u64(self, v: u64) -> Result + where + E: Error, + { + let variant = LOG_LEVEL_NAMES[1..] + .get(v as usize) + .ok_or_else(|| Error::invalid_value(Unexpected::Unsigned(v), &self))?; + + self.visit_str(variant) + } + fn visit_str(self, s: &str) -> Result where E: Error, @@ -60,17 +70,6 @@ impl<'de> Deserialize<'de> for Level { self.visit_str(variant) } - - fn visit_u64(self, v: u64) -> Result - where - E: Error, - { - let variant = LOG_LEVEL_NAMES[1..] - .get(v as usize) - .ok_or_else(|| Error::invalid_value(Unexpected::Unsigned(v), &self))?; - - self.visit_str(variant) - } } impl<'de> DeserializeSeed<'de> for LevelIdentifier { @@ -138,6 +137,17 @@ impl<'de> Deserialize<'de> for LevelFilter { formatter.write_str("log level filter") } + fn visit_u64(self, v: u64) -> Result + where + E: Error, + { + let variant = LOG_LEVEL_NAMES + .get(v as usize) + .ok_or_else(|| Error::invalid_value(Unexpected::Unsigned(v), &self))?; + + self.visit_str(variant) + } + fn visit_str(self, s: &str) -> Result where E: Error, @@ -155,17 +165,6 @@ impl<'de> Deserialize<'de> for LevelFilter { self.visit_str(variant) } - - fn visit_u64(self, v: u64) -> Result - where - E: Error, - { - let variant = LOG_LEVEL_NAMES - .get(v as usize) - .ok_or_else(|| Error::invalid_value(Unexpected::Unsigned(v), &self))?; - - self.visit_str(variant) - } } impl<'de> DeserializeSeed<'de> for LevelFilterIdentifier { @@ -205,10 +204,8 @@ impl<'de> Deserialize<'de> for LevelFilter { #[cfg(test)] mod tests { - extern crate serde_test; - use self::serde_test::{assert_de_tokens, assert_de_tokens_error, assert_tokens, Token}; - - use {Level, LevelFilter}; + use crate::{Level, LevelFilter}; + use serde_test::{assert_de_tokens, assert_de_tokens_error, assert_tokens, Token}; fn level_token(variant: &'static str) -> Token { Token::UnitVariant { @@ -262,7 +259,7 @@ mod tests { #[test] fn test_level_ser_de() { - let cases = [ + let cases = &[ (Level::Error, [level_token("ERROR")]), (Level::Warn, [level_token("WARN")]), (Level::Info, [level_token("INFO")]), @@ -270,14 +267,14 @@ mod tests { (Level::Trace, [level_token("TRACE")]), ]; - for &(s, expected) in &cases { - assert_tokens(&s, &expected); + for (s, expected) in cases { + assert_tokens(s, expected); } } #[test] fn test_level_case_insensitive() { - let cases = [ + let cases = &[ (Level::Error, [level_token("error")]), (Level::Warn, [level_token("warn")]), (Level::Info, [level_token("info")]), @@ -285,14 +282,14 @@ mod tests { (Level::Trace, [level_token("trace")]), ]; - for &(s, expected) in &cases { - assert_de_tokens(&s, &expected); + for (s, expected) in cases { + assert_de_tokens(s, expected); } } #[test] fn test_level_de_bytes() { - let cases = [ + let cases = &[ (Level::Error, level_bytes_tokens(b"ERROR")), (Level::Warn, level_bytes_tokens(b"WARN")), (Level::Info, level_bytes_tokens(b"INFO")), @@ -300,14 +297,14 @@ mod tests { (Level::Trace, level_bytes_tokens(b"TRACE")), ]; - for &(value, tokens) in &cases { - assert_de_tokens(&value, &tokens); + for (value, tokens) in cases { + assert_de_tokens(value, tokens); } } #[test] fn test_level_de_variant_index() { - let cases = [ + let cases = &[ (Level::Error, level_variant_tokens(0)), (Level::Warn, level_variant_tokens(1)), (Level::Info, level_variant_tokens(2)), @@ -315,8 +312,8 @@ mod tests { (Level::Trace, level_variant_tokens(4)), ]; - for &(value, tokens) in &cases { - assert_de_tokens(&value, &tokens); + for (value, tokens) in cases { + assert_de_tokens(value, tokens); } } @@ -329,7 +326,7 @@ mod tests { #[test] fn test_level_filter_ser_de() { - let cases = [ + let cases = &[ (LevelFilter::Off, [level_filter_token("OFF")]), (LevelFilter::Error, [level_filter_token("ERROR")]), (LevelFilter::Warn, [level_filter_token("WARN")]), @@ -338,14 +335,14 @@ mod tests { (LevelFilter::Trace, [level_filter_token("TRACE")]), ]; - for &(s, expected) in &cases { - assert_tokens(&s, &expected); + for (s, expected) in cases { + assert_tokens(s, expected); } } #[test] fn test_level_filter_case_insensitive() { - let cases = [ + let cases = &[ (LevelFilter::Off, [level_filter_token("off")]), (LevelFilter::Error, [level_filter_token("error")]), (LevelFilter::Warn, [level_filter_token("warn")]), @@ -354,14 +351,14 @@ mod tests { (LevelFilter::Trace, [level_filter_token("trace")]), ]; - for &(s, expected) in &cases { - assert_de_tokens(&s, &expected); + for (s, expected) in cases { + assert_de_tokens(s, expected); } } #[test] fn test_level_filter_de_bytes() { - let cases = [ + let cases = &[ (LevelFilter::Off, level_filter_bytes_tokens(b"OFF")), (LevelFilter::Error, level_filter_bytes_tokens(b"ERROR")), (LevelFilter::Warn, level_filter_bytes_tokens(b"WARN")), @@ -370,14 +367,14 @@ mod tests { (LevelFilter::Trace, level_filter_bytes_tokens(b"TRACE")), ]; - for &(value, tokens) in &cases { - assert_de_tokens(&value, &tokens); + for (value, tokens) in cases { + assert_de_tokens(value, tokens); } } #[test] fn test_level_filter_de_variant_index() { - let cases = [ + let cases = &[ (LevelFilter::Off, level_filter_variant_tokens(0)), (LevelFilter::Error, level_filter_variant_tokens(1)), (LevelFilter::Warn, level_filter_variant_tokens(2)), @@ -386,8 +383,8 @@ mod tests { (LevelFilter::Trace, level_filter_variant_tokens(5)), ]; - for &(value, tokens) in &cases { - assert_de_tokens(&value, &tokens); + for (value, tokens) in cases { + assert_de_tokens(value, tokens); } } diff --git a/test_max_level_features/Cargo.toml b/test_max_level_features/Cargo.toml index 9d0b9759b..ae23058f9 100644 --- a/test_max_level_features/Cargo.toml +++ b/test_max_level_features/Cargo.toml @@ -1,6 +1,7 @@ [package] name = "optimized" version = "0.1.0" +edition = "2021" publish = false [[bin]] diff --git a/test_max_level_features/main.rs b/test_max_level_features/main.rs index bfbf2b247..b714f2d4c 100644 --- a/test_max_level_features/main.rs +++ b/test_max_level_features/main.rs @@ -1,13 +1,10 @@ -#[macro_use] -extern crate log; - +use log::{debug, error, info, trace, warn, Level, LevelFilter, Log, Metadata, Record}; use std::sync::{Arc, Mutex}; -use log::{Level, LevelFilter, Log, Record, Metadata}; #[cfg(feature = "std")] use log::set_boxed_logger; #[cfg(not(feature = "std"))] -fn set_boxed_logger(logger: Box) -> Result<(), log::SetLoggerError> { +fn set_boxed_logger(logger: Box) -> Result<(), log::SetLoggerError> { log::set_logger(Box::leak(logger)) } @@ -30,7 +27,9 @@ impl Log for Logger { } fn main() { - let me = Arc::new(State { last_log: Mutex::new(None) }); + let me = Arc::new(State { + last_log: Mutex::new(None), + }); let a = me.clone(); set_boxed_logger(Box::new(Logger(me))).unwrap(); @@ -62,7 +61,11 @@ fn test(a: &State, filter: LevelFilter) { last(&a, None); fn t(lvl: Level, filter: LevelFilter) -> Option { - if lvl <= filter {Some(lvl)} else {None} + if lvl <= filter { + Some(lvl) + } else { + None + } } } diff --git a/tests/Cargo.toml b/tests/Cargo.toml index 25ac12bec..88f37b5d4 100644 --- a/tests/Cargo.toml +++ b/tests/Cargo.toml @@ -1,6 +1,7 @@ [package] name = "integration" version = "0.1.0" +edition = "2021" publish = false build = "src/build.rs" diff --git a/tests/filters.rs b/tests/filters.rs index fbbc435d8..3e0810d07 100644 --- a/tests/filters.rs +++ b/tests/filters.rs @@ -1,10 +1,6 @@ #![allow(dead_code, unused_imports)] -#[cfg(not(lib_build))] -#[macro_use] -extern crate log; - -use log::{Level, LevelFilter, Log, Metadata, Record}; +use log::{debug, error, info, trace, warn, Level, LevelFilter, Log, Metadata, Record}; use std::sync::{Arc, Mutex}; #[cfg(feature = "std")] diff --git a/tests/macros.rs b/tests/macros.rs index b978308b2..2ff5b4107 100644 --- a/tests/macros.rs +++ b/tests/macros.rs @@ -1,14 +1,12 @@ -#[cfg(not(lib_build))] -#[macro_use] -extern crate log; +use log::{log, log_enabled}; macro_rules! all_log_macros { ($($arg:tt)*) => ({ - trace!($($arg)*); - debug!($($arg)*); - info!($($arg)*); - warn!($($arg)*); - error!($($arg)*); + ::log::trace!($($arg)*); + ::log::debug!($($arg)*); + ::log::info!($($arg)*); + ::log::warn!($($arg)*); + ::log::error!($($arg)*); }); } @@ -150,7 +148,7 @@ fn kv_named_args() { fn kv_expr_context() { match "chashu" { cat_1 => { - info!(target: "target", cat_1 = cat_1, cat_2 = "nori"; "hello {}", "cats"); + log::info!(target: "target", cat_1 = cat_1, cat_2 = "nori"; "hello {}", "cats"); } }; } diff --git a/tests/src/lib.rs b/tests/src/lib.rs index 34770568c..73f0753ca 100644 --- a/tests/src/lib.rs +++ b/tests/src/lib.rs @@ -1,14 +1,10 @@ //! This crate is intentionally left empty. -//! +//! //! We have an empty library depending on `log` here so we can run integration tests //! on older compilers without depending on the unstable `no-dev-deps` flag. #![allow(dead_code)] -#[cfg(test)] -#[macro_use] -extern crate log; - #[cfg(test)] #[path = "../filters.rs"] mod filters; From b462186530efe875e860921790b2b30eb44b4eb9 Mon Sep 17 00:00:00 2001 From: EFanZh Date: Mon, 28 Aug 2023 22:35:02 +0800 Subject: [PATCH 138/280] Specialize empty key value pairs --- src/__private_api.rs | 90 ++++++++++++++++++++++++++++++-------------- src/macros.rs | 6 +-- 2 files changed, 64 insertions(+), 32 deletions(-) diff --git a/src/__private_api.rs b/src/__private_api.rs index 7304deb89..359deebbc 100644 --- a/src/__private_api.rs +++ b/src/__private_api.rs @@ -1,55 +1,87 @@ //! WARNING: this is not part of the crate's public API and is subject to change at any time +use self::sealed::KVs; use crate::{Level, Metadata, Record}; use std::fmt::Arguments; -pub use std::option::Option; pub use std::{file, format_args, line, module_path, stringify}; +#[cfg(feature = "kv_unstable")] +pub type Value<'a> = dyn crate::kv::value::ToValue + 'a; + #[cfg(not(feature = "kv_unstable"))] -pub fn log( +pub type Value<'a> = str; + +mod sealed { + /// Types for the `kv` argument. + pub trait KVs<'a> { + fn into_kvs(self) -> Option<&'a [(&'a str, &'a super::Value<'a>)]>; + } +} + +// Types for the `kv` argument. + +impl<'a> KVs<'a> for &'a [(&'a str, &'a Value<'a>)] { + #[inline] + fn into_kvs(self) -> Option<&'a [(&'a str, &'a Value<'a>)]> { + Some(self) + } +} + +impl<'a> KVs<'a> for () { + #[inline] + fn into_kvs(self) -> Option<&'a [(&'a str, &'a Value<'a>)]> { + None + } +} + +// Log implementation. + +fn log_impl( args: Arguments, level: Level, &(target, module_path, file): &(&str, &'static str, &'static str), line: u32, - kvs: Option<&[(&str, &str)]>, + kvs: Option<&[(&str, &Value)]>, ) { + #[cfg(not(feature = "kv_unstable"))] if kvs.is_some() { panic!( "key-value support is experimental and must be enabled using the `kv_unstable` feature" ) } - crate::logger().log( - &Record::builder() - .args(args) - .level(level) - .target(target) - .module_path_static(Some(module_path)) - .file_static(Some(file)) - .line(Some(line)) - .build(), - ); + let mut builder = Record::builder(); + + builder + .args(args) + .level(level) + .target(target) + .module_path_static(Some(module_path)) + .file_static(Some(file)) + .line(Some(line)); + + #[cfg(feature = "kv_unstable")] + builder.key_values(&kvs); + + crate::logger().log(&builder.build()); } -#[cfg(feature = "kv_unstable")] -pub fn log( +pub fn log<'a, K>( args: Arguments, level: Level, - &(target, module_path, file): &(&str, &'static str, &'static str), + target_module_path_and_file: &(&str, &'static str, &'static str), line: u32, - kvs: Option<&[(&str, &dyn crate::kv::ToValue)]>, -) { - crate::logger().log( - &Record::builder() - .args(args) - .level(level) - .target(target) - .module_path_static(Some(module_path)) - .file_static(Some(file)) - .line(Some(line)) - .key_values(&kvs) - .build(), - ); + kvs: K, +) where + K: KVs<'a>, +{ + log_impl( + args, + level, + target_module_path_and_file, + line, + kvs.into_kvs(), + ) } pub fn enabled(level: Level, target: &str) -> bool { diff --git a/src/macros.rs b/src/macros.rs index 281ff2572..30d7c10a0 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -33,12 +33,12 @@ macro_rules! log { (target: $target:expr, $lvl:expr, $($key:tt = $value:expr),+; $($arg:tt)+) => ({ let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { - $crate::__private_api::log( + $crate::__private_api::log::<&_>( $crate::__private_api::format_args!($($arg)+), lvl, &($target, $crate::__private_api::module_path!(), $crate::__private_api::file!()), $crate::__private_api::line!(), - $crate::__private_api::Option::Some(&[$(($crate::__log_key!($key), &$value)),+]) + &[$(($crate::__log_key!($key), &$value)),+] ); } }); @@ -52,7 +52,7 @@ macro_rules! log { lvl, &($target, $crate::__private_api::module_path!(), $crate::__private_api::file!()), $crate::__private_api::line!(), - $crate::__private_api::Option::None, + (), ); } }); From 665a5448207f4ff66f0074a43c5ff47441fc9a5b Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Tue, 29 Aug 2023 10:14:04 +0200 Subject: [PATCH 139/280] Replace transmute with a pointer cast This is one of the recommended alternatives to transmute function. --- src/kv/value.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/kv/value.rs b/src/kv/value.rs index d4c45ea7f..c93a300e5 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -470,14 +470,14 @@ impl<'v> From<&'v i128> for Value<'v> { impl<'v> From<&'v std::num::NonZeroU128> for Value<'v> { fn from(v: &'v std::num::NonZeroU128) -> Value<'v> { // SAFETY: `NonZeroU128` and `u128` have the same ABI - Value::from_value_bag(unsafe { std::mem::transmute::<&std::num::NonZeroU128, &u128>(v) }) + Value::from_value_bag(unsafe { &*(v as *const std::num::NonZeroU128 as *const u128) }) } } impl<'v> From<&'v std::num::NonZeroI128> for Value<'v> { fn from(v: &'v std::num::NonZeroI128) -> Value<'v> { // SAFETY: `NonZeroI128` and `i128` have the same ABI - Value::from_value_bag(unsafe { std::mem::transmute::<&std::num::NonZeroI128, &i128>(v) }) + Value::from_value_bag(unsafe { &*(v as *const std::num::NonZeroI128 as *const i128) }) } } From f100fb880a7971bae8ea4834653ef58077992317 Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Tue, 29 Aug 2023 10:16:07 +0200 Subject: [PATCH 140/280] Implement ToValue for Arc --- src/kv/value.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/kv/value.rs b/src/kv/value.rs index c93a300e5..a744b605e 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -589,6 +589,7 @@ impl<'v> Value<'v> { #[cfg(feature = "kv_unstable_std")] mod std_support { use std::borrow::Cow; + use std::sync::Arc; use super::*; @@ -601,6 +602,15 @@ mod std_support { } } + impl ToValue for Arc + where + T: ToValue + ?Sized, + { + fn to_value(&self) -> Value { + (**self).to_value() + } + } + impl ToValue for String { fn to_value(&self) -> Value { Value::from(&**self) From de5711849bb4b0ed68943a4a4c0e9955a5cc16fb Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Tue, 29 Aug 2023 10:16:22 +0200 Subject: [PATCH 141/280] Implement ToValue for Rc --- src/kv/value.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/kv/value.rs b/src/kv/value.rs index a744b605e..352f965ea 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -589,6 +589,7 @@ impl<'v> Value<'v> { #[cfg(feature = "kv_unstable_std")] mod std_support { use std::borrow::Cow; + use std::rc::Rc; use std::sync::Arc; use super::*; @@ -611,6 +612,15 @@ mod std_support { } } + impl ToValue for Rc + where + T: ToValue + ?Sized, + { + fn to_value(&self) -> Value { + (**self).to_value() + } + } + impl ToValue for String { fn to_value(&self) -> Value { Value::from(&**self) From 0af453971ef8c72c0eed98421caa907f9ab33104 Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Tue, 29 Aug 2023 10:24:49 +0200 Subject: [PATCH 142/280] Remove cfg(test) attribute from Source::{get,count} Test code can still overwrite the methods. --- src/kv/source.rs | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/src/kv/source.rs b/src/kv/source.rs index 2a26c4a05..d4231b75e 100644 --- a/src/kv/source.rs +++ b/src/kv/source.rs @@ -30,14 +30,10 @@ pub trait Source { /// /// A source that can provide a more efficient implementation of this method /// should override it. - #[cfg(not(test))] fn get(&self, key: Key) -> Option> { get_default(self, key) } - #[cfg(test)] - fn get(&self, key: Key) -> Option>; - /// Count the number of key-value pairs that can be visited. /// /// # Implementation notes @@ -47,13 +43,9 @@ pub trait Source { /// /// A subsequent call to `visit` should yield the same number of key-value pairs /// to the visitor, unless that visitor fails part way through. - #[cfg(not(test))] fn count(&self) -> usize { count_default(self) } - - #[cfg(test)] - fn count(&self) -> usize; } /// The default implementation of `Source::get` @@ -714,14 +706,6 @@ mod tests { fn visit<'kvs>(&'kvs self, visitor: &mut dyn Visitor<'kvs>) -> Result<(), Error> { visitor.visit_pair(self.key.to_key(), self.value.to_value()) } - - fn get(&self, key: Key) -> Option> { - get_default(self, key) - } - - fn count(&self) -> usize { - count_default(self) - } } assert_eq!(1, Source::count(&("a", 1))); From df6eadc2c7d130010c49c9347f81d9b37b8e0914 Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Tue, 29 Aug 2023 10:34:21 +0200 Subject: [PATCH 143/280] Implement Source for Arc --- src/kv/source.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/kv/source.rs b/src/kv/source.rs index d4231b75e..736e072d8 100644 --- a/src/kv/source.rs +++ b/src/kv/source.rs @@ -225,6 +225,7 @@ mod std_support { use std::borrow::Borrow; use std::collections::{BTreeMap, HashMap}; use std::hash::{BuildHasher, Hash}; + use std::sync::Arc; impl Source for Box where @@ -243,6 +244,23 @@ mod std_support { } } + impl Source for Arc + where + S: Source + ?Sized, + { + fn visit<'kvs>(&'kvs self, visitor: &mut dyn Visitor<'kvs>) -> Result<(), Error> { + Source::visit(&**self, visitor) + } + + fn get(&self, key: Key) -> Option> { + Source::get(&**self, key) + } + + fn count(&self) -> usize { + Source::count(&**self) + } + } + impl Source for Vec where S: Source, From 78cfeae8b5b63ba42f6286824b6c888ddb18e415 Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Tue, 29 Aug 2023 10:35:04 +0200 Subject: [PATCH 144/280] Implement Source for Rc --- src/kv/source.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/kv/source.rs b/src/kv/source.rs index 736e072d8..38edf8865 100644 --- a/src/kv/source.rs +++ b/src/kv/source.rs @@ -225,6 +225,7 @@ mod std_support { use std::borrow::Borrow; use std::collections::{BTreeMap, HashMap}; use std::hash::{BuildHasher, Hash}; + use std::rc::Rc; use std::sync::Arc; impl Source for Box @@ -261,6 +262,23 @@ mod std_support { } } + impl Source for Rc + where + S: Source + ?Sized, + { + fn visit<'kvs>(&'kvs self, visitor: &mut dyn Visitor<'kvs>) -> Result<(), Error> { + Source::visit(&**self, visitor) + } + + fn get(&self, key: Key) -> Option> { + Source::get(&**self, key) + } + + fn count(&self) -> usize { + Source::count(&**self) + } + } + impl Source for Vec where S: Source, From 154b58140a02e8d26b160339d7572cd492a2742c Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Tue, 29 Aug 2023 10:41:48 +0200 Subject: [PATCH 145/280] Small code simplification --- src/kv/source.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/kv/source.rs b/src/kv/source.rs index 38edf8865..8441e3d04 100644 --- a/src/kv/source.rs +++ b/src/kv/source.rs @@ -49,7 +49,7 @@ pub trait Source { } /// The default implementation of `Source::get` -pub(crate) fn get_default<'v>(source: &'v (impl Source + ?Sized), key: Key) -> Option> { +fn get_default<'v>(source: &'v (impl Source + ?Sized), key: Key) -> Option> { struct Get<'k, 'v> { key: Key<'k>, found: Option>, @@ -72,7 +72,7 @@ pub(crate) fn get_default<'v>(source: &'v (impl Source + ?Sized), key: Key) -> O } /// The default implementation of `Source::count`. -pub(crate) fn count_default(source: impl Source) -> usize { +fn count_default(source: impl Source) -> usize { struct Count(usize); impl<'kvs> Visitor<'kvs> for Count { @@ -159,7 +159,7 @@ where S: Source, { fn visit<'kvs>(&'kvs self, visitor: &mut dyn Visitor<'kvs>) -> Result<(), Error> { - if let Some(ref source) = *self { + if let Some(source) = self { source.visit(visitor)?; } From 432f66d7172b37c26c08606ae57d185ff1833dda Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Tue, 29 Aug 2023 10:42:28 +0200 Subject: [PATCH 146/280] Fix Source::count for [S] The previous implementation didn't consider that the underlying Source implementation S can have more than one key-value pairs. --- src/kv/source.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kv/source.rs b/src/kv/source.rs index 8441e3d04..c8e7a05a3 100644 --- a/src/kv/source.rs +++ b/src/kv/source.rs @@ -150,7 +150,7 @@ where } fn count(&self) -> usize { - self.len() + self.iter().map(Source::count).sum() } } From 0f2e26d88a845755c7121ffa902321e71dc786f6 Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Tue, 29 Aug 2023 14:47:37 +0200 Subject: [PATCH 147/280] Remove AsMap and AsList type These types are more related to serde and sval than they are to log. Because of that is falls out of scope for the log crate. --- src/kv/source.rs | 325 ----------------------------------------------- 1 file changed, 325 deletions(-) diff --git a/src/kv/source.rs b/src/kv/source.rs index c8e7a05a3..9c56f8b76 100644 --- a/src/kv/source.rs +++ b/src/kv/source.rs @@ -402,319 +402,6 @@ mod std_support { } } -/// The result of calling `Source::as_map`. -pub struct AsMap(S); - -/// Visit this source as a map. -pub fn as_map(source: S) -> AsMap -where - S: Source, -{ - AsMap(source) -} - -impl Source for AsMap -where - S: Source, -{ - fn visit<'kvs>(&'kvs self, visitor: &mut dyn Visitor<'kvs>) -> Result<(), Error> { - self.0.visit(visitor) - } - - fn get(&self, key: Key) -> Option> { - self.0.get(key) - } - - fn count(&self) -> usize { - self.0.count() - } -} - -impl fmt::Debug for AsMap -where - S: Source, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut f = f.debug_map(); - self.0.visit(&mut f).map_err(|_| fmt::Error)?; - f.finish() - } -} - -/// The result of calling `Source::as_list` -pub struct AsList(S); - -/// Visit this source as a list. -pub fn as_list(source: S) -> AsList -where - S: Source, -{ - AsList(source) -} - -impl Source for AsList -where - S: Source, -{ - fn visit<'kvs>(&'kvs self, visitor: &mut dyn Visitor<'kvs>) -> Result<(), Error> { - self.0.visit(visitor) - } - - fn get(&self, key: Key) -> Option> { - self.0.get(key) - } - - fn count(&self) -> usize { - self.0.count() - } -} - -impl fmt::Debug for AsList -where - S: Source, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut f = f.debug_list(); - self.0.visit(&mut f).map_err(|_| fmt::Error)?; - f.finish() - } -} - -#[cfg(feature = "kv_unstable_sval")] -mod sval_support { - use super::*; - - impl sval::Value for AsMap - where - S: Source, - { - fn stream<'sval, SV: sval::Stream<'sval> + ?Sized>( - &'sval self, - stream: &mut SV, - ) -> sval::Result { - struct StreamVisitor<'a, V: ?Sized>(&'a mut V); - - impl<'a, 'kvs, V: sval::Stream<'kvs> + ?Sized> Visitor<'kvs> for StreamVisitor<'a, V> { - fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> { - self.0 - .map_key_begin() - .map_err(|_| Error::msg("failed to stream map key"))?; - sval_ref::stream_ref(self.0, key) - .map_err(|_| Error::msg("failed to stream map key"))?; - self.0 - .map_key_end() - .map_err(|_| Error::msg("failed to stream map key"))?; - - self.0 - .map_value_begin() - .map_err(|_| Error::msg("failed to stream map value"))?; - sval_ref::stream_ref(self.0, value) - .map_err(|_| Error::msg("failed to stream map value"))?; - self.0 - .map_value_end() - .map_err(|_| Error::msg("failed to stream map value"))?; - - Ok(()) - } - } - - stream - .map_begin(Some(self.count())) - .map_err(|_| sval::Error::new())?; - - self.visit(&mut StreamVisitor(stream)) - .map_err(|_| sval::Error::new())?; - - stream.map_end().map_err(|_| sval::Error::new()) - } - } - - impl sval::Value for AsList - where - S: Source, - { - fn stream<'sval, SV: sval::Stream<'sval> + ?Sized>( - &'sval self, - stream: &mut SV, - ) -> sval::Result { - struct StreamVisitor<'a, V: ?Sized>(&'a mut V); - - impl<'a, 'kvs, V: sval::Stream<'kvs> + ?Sized> Visitor<'kvs> for StreamVisitor<'a, V> { - fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> { - self.0 - .seq_value_begin() - .map_err(|_| Error::msg("failed to stream seq value"))?; - sval_ref::stream_ref(self.0, (key, value)) - .map_err(|_| Error::msg("failed to stream seq value"))?; - self.0 - .seq_value_end() - .map_err(|_| Error::msg("failed to stream seq value"))?; - - Ok(()) - } - } - - stream - .seq_begin(Some(self.count())) - .map_err(|_| sval::Error::new())?; - - self.visit(&mut StreamVisitor(stream)) - .map_err(|_| sval::Error::new())?; - - stream.seq_end().map_err(|_| sval::Error::new()) - } - } - - #[cfg(test)] - mod tests { - use super::*; - use sval_derive::Value; - - #[test] - fn derive_stream() { - #[derive(Value)] - pub struct MyRecordAsMap<'a> { - msg: &'a str, - kvs: AsMap<&'a dyn Source>, - } - - #[derive(Value)] - pub struct MyRecordAsList<'a> { - msg: &'a str, - kvs: AsList<&'a dyn Source>, - } - } - } -} - -#[cfg(feature = "kv_unstable_serde")] -pub mod as_map { - //! `serde` adapters for serializing a `Source` as a map. - - use super::*; - use serde::{Serialize, Serializer}; - - /// Serialize a `Source` as a map. - pub fn serialize(source: &T, serializer: S) -> Result - where - T: Source, - S: Serializer, - { - as_map(source).serialize(serializer) - } -} - -#[cfg(feature = "kv_unstable_serde")] -pub mod as_list { - //! `serde` adapters for serializing a `Source` as a list. - - use super::*; - use serde::{Serialize, Serializer}; - - /// Serialize a `Source` as a list. - pub fn serialize(source: &T, serializer: S) -> Result - where - T: Source, - S: Serializer, - { - as_list(source).serialize(serializer) - } -} - -#[cfg(feature = "kv_unstable_serde")] -mod serde_support { - use super::*; - use serde::ser::{Error as SerError, Serialize, SerializeMap, SerializeSeq, Serializer}; - - impl Serialize for AsMap - where - T: Source, - { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - struct SerializerVisitor<'a, S>(&'a mut S); - - impl<'a, 'kvs, S> Visitor<'kvs> for SerializerVisitor<'a, S> - where - S: SerializeMap, - { - fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> { - self.0 - .serialize_entry(&key, &value) - .map_err(|_| Error::msg("failed to serialize map entry"))?; - Ok(()) - } - } - - let mut map = serializer.serialize_map(Some(self.count()))?; - - self.visit(&mut SerializerVisitor(&mut map)) - .map_err(|_| S::Error::custom("failed to visit key-values"))?; - - map.end() - } - } - - impl Serialize for AsList - where - T: Source, - { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - struct SerializerVisitor<'a, S>(&'a mut S); - - impl<'a, 'kvs, S> Visitor<'kvs> for SerializerVisitor<'a, S> - where - S: SerializeSeq, - { - fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> { - self.0 - .serialize_element(&(key, value)) - .map_err(|_| Error::msg("failed to serialize seq entry"))?; - Ok(()) - } - } - - let mut seq = serializer.serialize_seq(Some(self.count()))?; - - self.visit(&mut SerializerVisitor(&mut seq)) - .map_err(|_| S::Error::custom("failed to visit seq"))?; - - seq.end() - } - } - - #[cfg(test)] - mod tests { - use super::*; - use crate::kv::source; - use serde::Serialize; - - #[test] - fn derive_serialize() { - #[derive(Serialize)] - pub struct MyRecordAsMap<'a> { - msg: &'a str, - #[serde(flatten)] - #[serde(with = "source::as_map")] - kvs: &'a dyn Source, - } - - #[derive(Serialize)] - pub struct MyRecordAsList<'a> { - msg: &'a str, - #[serde(flatten)] - #[serde(with = "source::as_list")] - kvs: &'a dyn Source, - } - } - } -} - #[cfg(test)] mod tests { use crate::kv::value::tests::Token; @@ -766,16 +453,4 @@ mod tests { let source = None::<(&str, i32)>; assert!(Source::get(&source, Key::from_str("a")).is_none()); } - - #[test] - fn as_map() { - let _ = crate::kv::source::as_map(("a", 1)); - let _ = crate::kv::source::as_map(&("a", 1) as &dyn Source); - } - - #[test] - fn as_list() { - let _ = crate::kv::source::as_list(("a", 1)); - let _ = crate::kv::source::as_list(&("a", 1) as &dyn Source); - } } From 0c80af3ab711ec630d50be1956042d284b88e0d5 Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Tue, 29 Aug 2023 14:49:59 +0200 Subject: [PATCH 148/280] Remove ToValue for dyn fmt::{Debug,Display} and std::error::Error To support downcasting the Value::capture_* methods should be used. However with these ToValue implementations it's very easy to call to_value and call it a day, too easy as you lose the downcasting ability when you do. To prevent this gotcha remove these implenentations. --- src/kv/value.rs | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/src/kv/value.rs b/src/kv/value.rs index 352f965ea..5d401df6b 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -121,15 +121,6 @@ macro_rules! as_sval { /// assert_eq!(Some(42), value.to_i64()); /// ``` /// -/// ``` -/// # use std::fmt::Debug; -/// use log::kv::ToValue; -/// -/// let value = (&42i32 as &dyn Debug).to_value(); -/// -/// assert_eq!(None, value.to_i64()); -/// ``` -/// /// ## Using the standard `From` trait /// /// Standard types that implement `ToValue` also implement `From`. @@ -376,25 +367,6 @@ impl<'v> fmt::Display for Value<'v> { } } -impl ToValue for dyn fmt::Debug { - fn to_value(&self) -> Value { - Value::from_dyn_debug(self) - } -} - -impl ToValue for dyn fmt::Display { - fn to_value(&self) -> Value { - Value::from_dyn_display(self) - } -} - -#[cfg(feature = "kv_unstable_std")] -impl ToValue for dyn std::error::Error + 'static { - fn to_value(&self) -> Value { - Value::from_dyn_error(self) - } -} - #[cfg(feature = "kv_unstable_serde")] impl<'v> serde::Serialize for Value<'v> { fn serialize(&self, s: S) -> Result From e6b6bde8e8adea31553762958a08f54e0c6fdcde Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Tue, 29 Aug 2023 14:52:08 +0200 Subject: [PATCH 149/280] Remove Key::to_borrowed_str Key::as_str can be used instead. --- src/kv/key.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/kv/key.rs b/src/kv/key.rs index 971c866b9..858ec493a 100644 --- a/src/kv/key.rs +++ b/src/kv/key.rs @@ -48,12 +48,6 @@ impl<'k> Key<'k> { pub fn as_str(&self) -> &str { self.key } - - /// Try get a string borrowed for the `'k` lifetime from this key. - pub fn to_borrowed_str(&self) -> Option<&'k str> { - // NOTE: This API leaves room for keys to be owned - Some(self.key) - } } impl<'k> fmt::Display for Key<'k> { From 2e721355d55519911d7d7b1f382245d4e9244e18 Mon Sep 17 00:00:00 2001 From: Peter Hall Date: Thu, 14 Sep 2023 14:50:01 +0100 Subject: [PATCH 150/280] Fix incorrect lifetime in Value::to_str() --- src/kv/value.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kv/value.rs b/src/kv/value.rs index 352f965ea..f4eefbb09 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -635,7 +635,7 @@ mod std_support { impl<'v> Value<'v> { /// Try convert this value into a string. - pub fn to_str(&self) -> Option> { + pub fn to_str(&self) -> Option> { self.inner.to_str() } } From b912f79e81f70b81faa97d25c48e3b84cff1f235 Mon Sep 17 00:00:00 2001 From: Michael Diamond Date: Sat, 30 Sep 2023 12:27:42 -0700 Subject: [PATCH 151/280] Fix typo in file_static() method doc --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index cc5172b8f..46d4378af 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -795,7 +795,7 @@ impl<'a> Record<'a> { self.file.map(|s| s.get()) } - /// The module path of the message, if it is a `'static` string. + /// The source file containing the message, if it is a `'static` string. #[inline] pub fn file_static(&self) -> Option<&'static str> { match self.file { From ecaf9c97d03843982286e383b5d5b410e724e459 Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Thu, 19 Oct 2023 19:58:42 +0200 Subject: [PATCH 152/280] Add Serialization section to kv::Value docs --- src/kv/value.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/kv/value.rs b/src/kv/value.rs index 312232003..4cc5729c4 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -132,6 +132,18 @@ macro_rules! as_sval { /// /// assert_eq!(Some(42), value.to_i64()); /// ``` +/// +/// # Serialization +/// +/// `Value` provides a number of ways to be serialized. +/// +/// For basic types the [`Value::visit`] method can be used to extract the +/// underlying typed value. However this is limited in the amount of types +/// supported (see the [`Visit`] trait methods). +/// +/// For more complex types one of the following traits can be used: +/// * [`sval::Value`], requires the `kv_unstable_sval` feature. +/// * [`serde::Serialize`], requires the `kv_unstable_serde` feature. pub struct Value<'v> { inner: ValueBag<'v>, } @@ -620,6 +632,10 @@ mod std_support { } /// A visitor for a `Value`. +/// +/// Also see [`Value`'s documentation on seralization]. +/// +/// [`Value`'s documentation on seralization]: Value#serialization pub trait Visit<'v> { /// Visit a `Value`. /// From fa8ff872a178e8f4b4c0620b4bd6a18c318fbac9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre-Cl=C3=A9ment=20Tosi?= Date: Fri, 20 Oct 2023 14:59:47 +0100 Subject: [PATCH 153/280] Clarify release builds using max_level_* features Rephrase the documentation to make it clear that the max_level_* and release_max_level_* are not separate ways of setting STATIC_MAX_LEVEL for respectively debug and release builds but instead, that max_level_* are used by all builds and that release_max_level_* are just a way to override them. --- src/lib.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 46d4378af..e36d5c0ed 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -241,9 +241,7 @@ //! //! # Compile time filters //! -//! Log levels can be statically disabled at compile time via Cargo features. Log invocations at -//! disabled levels will be skipped and will not even be present in the resulting binary. -//! This level is configured separately for release and debug builds. The features are: +//! Log levels can be statically disabled at compile time by enabling one of these Cargo features: //! //! * `max_level_off` //! * `max_level_error` @@ -251,6 +249,13 @@ //! * `max_level_info` //! * `max_level_debug` //! * `max_level_trace` +//! +//! Log invocations at disabled levels will be skipped and will not even be present in the +//! resulting binary. These features control the value of the `STATIC_MAX_LEVEL` constant. The +//! logging macros check this value before logging a message. By default, no levels are disabled. +//! +//! It is possible to override this level for release builds only with the following features: +//! //! * `release_max_level_off` //! * `release_max_level_error` //! * `release_max_level_warn` @@ -258,9 +263,6 @@ //! * `release_max_level_debug` //! * `release_max_level_trace` //! -//! These features control the value of the `STATIC_MAX_LEVEL` constant. The logging macros check -//! this value before logging a message. By default, no levels are disabled. -//! //! Libraries should avoid using the max level features because they're global and can't be changed //! once they're set. //! From cc7efd8f12508eb1b41091270a6b8c219a4018a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre-Cl=C3=A9ment=20Tosi?= Date: Fri, 20 Oct 2023 10:32:14 +0100 Subject: [PATCH 154/280] Add feature-dependent tests for STATIC_MAX_LEVEL Add unit tests that check, for the current configuration of the crate features, that STATIC_MAX_LEVEL has the appropriate value. As the features are statically set (at build time), coverage of all the max_level_* and release_max_level_* value pairs must be achieved by launching cargo with different sets: levels="off debug error info trace warn" for i in '' $levels; do release=${i:+--features=release_max_level_${i}} for j in '' $levels; do debug=${j:+--features=max_level_${j}} cargo test static_max_level ${release} ${debug} cargo test static_max_level ${release} ${debug} --release done done --- src/lib.rs | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index e36d5c0ed..be5f3fd92 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -336,6 +336,7 @@ #[cfg(all(not(feature = "std"), not(test)))] extern crate core as std; +use std::cfg; #[cfg(feature = "std")] use std::error; use std::str::FromStr; @@ -1537,7 +1538,7 @@ const fn get_max_level_inner() -> LevelFilter { #[cfg(test)] mod tests { - use super::{Level, LevelFilter, ParseLevelError}; + use super::{Level, LevelFilter, ParseLevelError, STATIC_MAX_LEVEL}; #[test] fn test_levelfilter_from_str() { @@ -1650,6 +1651,54 @@ mod tests { } } + #[test] + #[cfg_attr(not(debug_assertions), ignore)] + fn test_static_max_level_debug() { + if cfg!(feature = "max_level_off") { + assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Off); + } else if cfg!(feature = "max_level_error") { + assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Error); + } else if cfg!(feature = "max_level_warn") { + assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Warn); + } else if cfg!(feature = "max_level_info") { + assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Info); + } else if cfg!(feature = "max_level_debug") { + assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Debug); + } else { + assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Trace); + } + } + + #[test] + #[cfg_attr(debug_assertions, ignore)] + fn test_static_max_level_release() { + if cfg!(feature = "release_max_level_off") { + assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Off); + } else if cfg!(feature = "release_max_level_error") { + assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Error); + } else if cfg!(feature = "release_max_level_warn") { + assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Warn); + } else if cfg!(feature = "release_max_level_info") { + assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Info); + } else if cfg!(feature = "release_max_level_debug") { + assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Debug); + } else if cfg!(feature = "release_max_level_trace") { + assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Trace); + } else if cfg!(feature = "max_level_off") { + assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Off); + } else if cfg!(feature = "max_level_error") { + assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Error); + } else if cfg!(feature = "max_level_warn") { + assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Warn); + } else if cfg!(feature = "max_level_info") { + assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Info); + } else if cfg!(feature = "max_level_debug") { + assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Debug); + } else { + assert_eq!(STATIC_MAX_LEVEL, LevelFilter::Trace); + } + } + #[test] #[cfg(feature = "std")] fn test_error_trait() { From 296fa1a4de79a67514a1046a73d8ff716d6eab50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre-Cl=C3=A9ment=20Tosi?= Date: Fri, 20 Oct 2023 16:40:25 +0100 Subject: [PATCH 155/280] Simplify STATIC_MAX_LEVEL intialization Replace get_max_level_inner() with cfg!() and a const-compatible match, now that the MSRV has been bumped to 1.60.0. --- src/lib.rs | 67 ++++++++++++------------------------------------------ 1 file changed, 14 insertions(+), 53 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index be5f3fd92..77b4c8afa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1482,59 +1482,20 @@ pub mod __private_api; /// [`logger`]: fn.logger.html pub const STATIC_MAX_LEVEL: LevelFilter = MAX_LEVEL_INNER; -const MAX_LEVEL_INNER: LevelFilter = get_max_level_inner(); - -const fn get_max_level_inner() -> LevelFilter { - #[allow(unreachable_code)] - { - #[cfg(all(not(debug_assertions), feature = "release_max_level_off"))] - { - return LevelFilter::Off; - } - #[cfg(all(not(debug_assertions), feature = "release_max_level_error"))] - { - return LevelFilter::Error; - } - #[cfg(all(not(debug_assertions), feature = "release_max_level_warn"))] - { - return LevelFilter::Warn; - } - #[cfg(all(not(debug_assertions), feature = "release_max_level_info"))] - { - return LevelFilter::Info; - } - #[cfg(all(not(debug_assertions), feature = "release_max_level_debug"))] - { - return LevelFilter::Debug; - } - #[cfg(all(not(debug_assertions), feature = "release_max_level_trace"))] - { - return LevelFilter::Trace; - } - #[cfg(feature = "max_level_off")] - { - return LevelFilter::Off; - } - #[cfg(feature = "max_level_error")] - { - return LevelFilter::Error; - } - #[cfg(feature = "max_level_warn")] - { - return LevelFilter::Warn; - } - #[cfg(feature = "max_level_info")] - { - return LevelFilter::Info; - } - #[cfg(feature = "max_level_debug")] - { - return LevelFilter::Debug; - } - - LevelFilter::Trace - } -} +const MAX_LEVEL_INNER: LevelFilter = match cfg!(debug_assertions) { + false if cfg!(feature = "release_max_level_off") => LevelFilter::Off, + false if cfg!(feature = "release_max_level_error") => LevelFilter::Error, + false if cfg!(feature = "release_max_level_warn") => LevelFilter::Warn, + false if cfg!(feature = "release_max_level_info") => LevelFilter::Info, + false if cfg!(feature = "release_max_level_debug") => LevelFilter::Debug, + false if cfg!(feature = "release_max_level_trace") => LevelFilter::Trace, + _ if cfg!(feature = "max_level_off") => LevelFilter::Off, + _ if cfg!(feature = "max_level_error") => LevelFilter::Error, + _ if cfg!(feature = "max_level_warn") => LevelFilter::Warn, + _ if cfg!(feature = "max_level_info") => LevelFilter::Info, + _ if cfg!(feature = "max_level_debug") => LevelFilter::Debug, + _ => LevelFilter::Trace, +}; #[cfg(test)] mod tests { From 05d8c46c60a48cec860d2e41da5767258923f802 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pierre-Cl=C3=A9ment=20Tosi?= Date: Fri, 20 Oct 2023 16:45:53 +0100 Subject: [PATCH 156/280] Remove intermediate MAX_LEVEL_INNER Drop the constant as it now seems unnecessary. Note: this is done in a separate commit to be easy to bisect and revert. --- src/lib.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 77b4c8afa..ec9b868b9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1480,9 +1480,7 @@ pub mod __private_api; /// should compare the level against this value. /// /// [`logger`]: fn.logger.html -pub const STATIC_MAX_LEVEL: LevelFilter = MAX_LEVEL_INNER; - -const MAX_LEVEL_INNER: LevelFilter = match cfg!(debug_assertions) { +pub const STATIC_MAX_LEVEL: LevelFilter = match cfg!(debug_assertions) { false if cfg!(feature = "release_max_level_off") => LevelFilter::Off, false if cfg!(feature = "release_max_level_error") => LevelFilter::Error, false if cfg!(feature = "release_max_level_warn") => LevelFilter::Warn, From 3237ff77f8d963c7b87dd4fe05bd84cac8fa886d Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Sun, 20 Aug 2023 02:19:38 -0400 Subject: [PATCH 157/280] Update docs to 2021 edition, test * Inline format arg in documentation and a few call places * Add a unit test for inlined format args I was surprised to discover that log crate has no edition value... Any reason to keep it at 2015? --- README.md | 4 ++-- rfcs/0296-structured-logging.md | 2 +- src/kv/value.rs | 4 ++-- src/lib.rs | 28 ++++++++++++++-------------- src/macros.rs | 22 +++++++++++----------- tests/macros.rs | 22 ++++++++++++++++++++++ 6 files changed, 52 insertions(+), 30 deletions(-) diff --git a/README.md b/README.md index 3dd645799..7dda4b9fa 100644 --- a/README.md +++ b/README.md @@ -43,12 +43,12 @@ pub fn shave_the_yak(yak: &mut Yak) { loop { match find_a_razor() { Ok(razor) => { - info!("Razor located: {}", razor); + info!("Razor located: {razor}"); yak.shave(razor); break; } Err(err) => { - warn!("Unable to locate a razor: {}, retrying", err); + warn!("Unable to locate a razor: {err}, retrying"); } } } diff --git a/rfcs/0296-structured-logging.md b/rfcs/0296-structured-logging.md index f722749db..3ee90a5cf 100644 --- a/rfcs/0296-structured-logging.md +++ b/rfcs/0296-structured-logging.md @@ -337,7 +337,7 @@ fn log_record(w: impl Write, r: &Record) -> io::Result<()> { // Write each key-value pair on a new line record .key_values() - .for_each(|k, v| writeln!("{}: {}", k, v))?; + .for_each(|k, v| writeln!("{k}: {v}"))?; Ok(()) } diff --git a/src/kv/value.rs b/src/kv/value.rs index 312232003..85f6255f8 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -967,7 +967,7 @@ pub(crate) mod tests { impl<'v> Visit<'v> for Extract { fn visit_any(&mut self, value: Value) -> Result<(), Error> { - unimplemented!("unexpected value: {:?}", value) + unimplemented!("unexpected value: {value:?}") } fn visit_u64(&mut self, value: u64) -> Result<(), Error> { @@ -989,7 +989,7 @@ pub(crate) mod tests { impl<'v> Visit<'v> for Extract<'v> { fn visit_any(&mut self, value: Value) -> Result<(), Error> { - unimplemented!("unexpected value: {:?}", value) + unimplemented!("unexpected value: {value:?}") } fn visit_borrowed_str(&mut self, value: &'v str) -> Result<(), Error> { diff --git a/src/lib.rs b/src/lib.rs index 46d4378af..2545e9b8c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -48,24 +48,24 @@ //! //! ### Examples //! -//! ```edition2018 +//! ```edition2021 //! # #[derive(Debug)] pub struct Yak(String); //! # impl Yak { fn shave(&mut self, _: u32) {} } //! # fn find_a_razor() -> Result { Ok(1) } //! use log::{info, warn}; //! //! pub fn shave_the_yak(yak: &mut Yak) { -//! info!(target: "yak_events", "Commencing yak shaving for {:?}", yak); +//! info!(target: "yak_events", "Commencing yak shaving for {yak:?}"); //! //! loop { //! match find_a_razor() { //! Ok(razor) => { -//! info!("Razor located: {}", razor); +//! info!("Razor located: {razor}"); //! yak.shave(razor); //! break; //! } //! Err(err) => { -//! warn!("Unable to locate a razor: {}, retrying", err); +//! warn!("Unable to locate a razor: {err}, retrying"); //! } //! } //! } @@ -92,7 +92,7 @@ //! with your log records. If we take the example from before, we can include //! some additional context besides what's in the formatted message: //! -//! ```edition2018 +//! ```edition2021 //! # use serde::Serialize; //! # #[derive(Debug, Serialize)] pub struct Yak(String); //! # impl Yak { fn shave(&mut self, _: u32) {} } @@ -160,7 +160,7 @@ //! logs all messages at the [`Error`][level_link], [`Warn`][level_link] or //! [`Info`][level_link] levels to stdout: //! -//! ```edition2018 +//! ```edition2021 //! use log::{Record, Level, Metadata}; //! //! struct SimpleLogger; @@ -193,7 +193,7 @@ //! provide a function that wraps a call to [`set_logger`] and //! [`set_max_level`], handling initialization of the logger: //! -//! ```edition2018 +//! ```edition2021 //! # use log::{Level, Metadata}; //! # struct SimpleLogger; //! # impl log::Log for SimpleLogger { @@ -223,7 +223,7 @@ //! identical to `set_logger` except that it takes a `Box` rather than a //! `&'static Log`: //! -//! ```edition2018 +//! ```edition2021 //! # use log::{Level, LevelFilter, Log, SetLoggerError, Metadata}; //! # struct SimpleLogger; //! # impl log::Log for SimpleLogger { @@ -688,7 +688,7 @@ impl<'a> MaybeStaticStr<'a> { /// The following example shows a simple logger that displays the level, /// module path, and message of any `Record` that is passed to it. /// -/// ```edition2018 +/// ```edition2021 /// struct SimpleLogger; /// /// impl log::Log for SimpleLogger { @@ -845,7 +845,7 @@ impl<'a> Record<'a> { /// /// # Examples /// -/// ```edition2018 +/// ```edition2021 /// use log::{Level, Record}; /// /// let record = Record::builder() @@ -860,7 +860,7 @@ impl<'a> Record<'a> { /// /// Alternatively, use [`MetadataBuilder`](struct.MetadataBuilder.html): /// -/// ```edition2018 +/// ```edition2021 /// use log::{Record, Level, MetadataBuilder}; /// /// let error_metadata = MetadataBuilder::new() @@ -1011,7 +1011,7 @@ impl<'a> Default for RecordBuilder<'a> { /// /// # Examples /// -/// ```edition2018 +/// ```edition2021 /// use log::{Record, Level, Metadata}; /// /// struct MyLogger; @@ -1065,7 +1065,7 @@ impl<'a> Metadata<'a> { /// /// # Example /// -/// ```edition2018 +/// ```edition2021 /// let target = "myApp"; /// use log::{Level, MetadataBuilder}; /// let metadata = MetadataBuilder::new() @@ -1315,7 +1315,7 @@ pub fn set_boxed_logger(logger: Box) -> Result<(), SetLoggerError> { /// /// # Examples /// -/// ```edition2018 +/// ```edition2021 /// use log::{error, info, warn, Record, Level, Metadata, LevelFilter}; /// /// static MY_LOGGER: MyLogger = MyLogger; diff --git a/src/macros.rs b/src/macros.rs index 30d7c10a0..549827cbf 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -15,7 +15,7 @@ /// /// # Examples /// -/// ```edition2018 +/// ```edition2021 /// use log::{log, Level}; /// /// # fn main() { @@ -65,14 +65,14 @@ macro_rules! log { /// /// # Examples /// -/// ```edition2018 +/// ```edition2021 /// use log::error; /// /// # fn main() { /// let (err_info, port) = ("No connection", 22); /// -/// error!("Error: {} on port {}", err_info, port); -/// error!(target: "app_events", "App Error: {}, Port: {}", err_info, 22); +/// error!("Error: {err_info} on port {port}"); +/// error!(target: "app_events", "App Error: {err_info}, Port: {port}"); /// # } /// ``` #[macro_export] @@ -89,14 +89,14 @@ macro_rules! error { /// /// # Examples /// -/// ```edition2018 +/// ```edition2021 /// use log::warn; /// /// # fn main() { /// let warn_description = "Invalid Input"; /// -/// warn!("Warning! {}!", warn_description); -/// warn!(target: "input_events", "App received warning: {}", warn_description); +/// warn!("Warning! {warn_description}!"); +/// warn!(target: "input_events", "App received warning: {warn_description}"); /// # } /// ``` #[macro_export] @@ -113,7 +113,7 @@ macro_rules! warn { /// /// # Examples /// -/// ```edition2018 +/// ```edition2021 /// use log::info; /// /// # fn main() { @@ -139,7 +139,7 @@ macro_rules! info { /// /// # Examples /// -/// ```edition2018 +/// ```edition2021 /// use log::debug; /// /// # fn main() { @@ -164,7 +164,7 @@ macro_rules! debug { /// /// # Examples /// -/// ```edition2018 +/// ```edition2021 /// use log::trace; /// /// # fn main() { @@ -195,7 +195,7 @@ macro_rules! trace { /// /// # Examples /// -/// ```edition2018 +/// ```edition2021 /// use log::Level::Debug; /// use log::{debug, log_enabled}; /// diff --git a/tests/macros.rs b/tests/macros.rs index 2ff5b4107..3afcf88da 100644 --- a/tests/macros.rs +++ b/tests/macros.rs @@ -70,6 +70,28 @@ fn named_args() { all_log_macros!(target: "my_target", "hello {world}", world = "world",); } +#[test] +fn inlined_args() { + let world = "world"; + + for lvl in log::Level::iter() { + log!(lvl, "hello {world}"); + log!(lvl, "hello {world}",); + + log!(target: "my_target", lvl, "hello {world}"); + log!(target: "my_target", lvl, "hello {world}",); + + log!(lvl, "hello {world}"); + log!(lvl, "hello {world}",); + } + + all_log_macros!("hello {world}"); + all_log_macros!("hello {world}",); + + all_log_macros!(target: "my_target", "hello {world}"); + all_log_macros!(target: "my_target", "hello {world}",); +} + #[test] fn enabled() { for lvl in log::Level::iter() { From 6403cea1a9ffb4469fa3bbee3b8e5c47d05119fa Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Mon, 28 Aug 2023 12:09:23 -0400 Subject: [PATCH 158/280] rm editions, add changelog --- CHANGELOG.md | 2 ++ src/lib.rs | 22 +++++++++++----------- src/macros.rs | 14 +++++++------- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 60870804a..45a18cdda 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Change Log ## [Unreleased] +* Migrate to 2021 edition and minor cleanups by @nyurik in https://github.com/rust-lang/log/pull/580 +* Use inline format args by @nyurik in https://github.com/rust-lang/log/pull/577 ## [0.4.20] - 2023-07-11 diff --git a/src/lib.rs b/src/lib.rs index 2545e9b8c..bb464f90c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -48,7 +48,7 @@ //! //! ### Examples //! -//! ```edition2021 +//! ``` //! # #[derive(Debug)] pub struct Yak(String); //! # impl Yak { fn shave(&mut self, _: u32) {} } //! # fn find_a_razor() -> Result { Ok(1) } @@ -92,7 +92,7 @@ //! with your log records. If we take the example from before, we can include //! some additional context besides what's in the formatted message: //! -//! ```edition2021 +//! ``` //! # use serde::Serialize; //! # #[derive(Debug, Serialize)] pub struct Yak(String); //! # impl Yak { fn shave(&mut self, _: u32) {} } @@ -160,7 +160,7 @@ //! logs all messages at the [`Error`][level_link], [`Warn`][level_link] or //! [`Info`][level_link] levels to stdout: //! -//! ```edition2021 +//! ``` //! use log::{Record, Level, Metadata}; //! //! struct SimpleLogger; @@ -193,7 +193,7 @@ //! provide a function that wraps a call to [`set_logger`] and //! [`set_max_level`], handling initialization of the logger: //! -//! ```edition2021 +//! ``` //! # use log::{Level, Metadata}; //! # struct SimpleLogger; //! # impl log::Log for SimpleLogger { @@ -223,7 +223,7 @@ //! identical to `set_logger` except that it takes a `Box` rather than a //! `&'static Log`: //! -//! ```edition2021 +//! ``` //! # use log::{Level, LevelFilter, Log, SetLoggerError, Metadata}; //! # struct SimpleLogger; //! # impl log::Log for SimpleLogger { @@ -688,7 +688,7 @@ impl<'a> MaybeStaticStr<'a> { /// The following example shows a simple logger that displays the level, /// module path, and message of any `Record` that is passed to it. /// -/// ```edition2021 +/// ``` /// struct SimpleLogger; /// /// impl log::Log for SimpleLogger { @@ -845,7 +845,7 @@ impl<'a> Record<'a> { /// /// # Examples /// -/// ```edition2021 +/// ``` /// use log::{Level, Record}; /// /// let record = Record::builder() @@ -860,7 +860,7 @@ impl<'a> Record<'a> { /// /// Alternatively, use [`MetadataBuilder`](struct.MetadataBuilder.html): /// -/// ```edition2021 +/// ``` /// use log::{Record, Level, MetadataBuilder}; /// /// let error_metadata = MetadataBuilder::new() @@ -1011,7 +1011,7 @@ impl<'a> Default for RecordBuilder<'a> { /// /// # Examples /// -/// ```edition2021 +/// ``` /// use log::{Record, Level, Metadata}; /// /// struct MyLogger; @@ -1065,7 +1065,7 @@ impl<'a> Metadata<'a> { /// /// # Example /// -/// ```edition2021 +/// ``` /// let target = "myApp"; /// use log::{Level, MetadataBuilder}; /// let metadata = MetadataBuilder::new() @@ -1315,7 +1315,7 @@ pub fn set_boxed_logger(logger: Box) -> Result<(), SetLoggerError> { /// /// # Examples /// -/// ```edition2021 +/// ``` /// use log::{error, info, warn, Record, Level, Metadata, LevelFilter}; /// /// static MY_LOGGER: MyLogger = MyLogger; diff --git a/src/macros.rs b/src/macros.rs index 549827cbf..44945f0d9 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -15,7 +15,7 @@ /// /// # Examples /// -/// ```edition2021 +/// ``` /// use log::{log, Level}; /// /// # fn main() { @@ -65,7 +65,7 @@ macro_rules! log { /// /// # Examples /// -/// ```edition2021 +/// ``` /// use log::error; /// /// # fn main() { @@ -89,7 +89,7 @@ macro_rules! error { /// /// # Examples /// -/// ```edition2021 +/// ``` /// use log::warn; /// /// # fn main() { @@ -113,7 +113,7 @@ macro_rules! warn { /// /// # Examples /// -/// ```edition2021 +/// ``` /// use log::info; /// /// # fn main() { @@ -139,7 +139,7 @@ macro_rules! info { /// /// # Examples /// -/// ```edition2021 +/// ``` /// use log::debug; /// /// # fn main() { @@ -164,7 +164,7 @@ macro_rules! debug { /// /// # Examples /// -/// ```edition2021 +/// ``` /// use log::trace; /// /// # fn main() { @@ -195,7 +195,7 @@ macro_rules! trace { /// /// # Examples /// -/// ```edition2021 +/// ``` /// use log::Level::Debug; /// use log::{debug, log_enabled}; /// From abb14d4485cc5a539b4dfcc7180cabc262465a19 Mon Sep 17 00:00:00 2001 From: Sebastian Wiesner Date: Thu, 26 Oct 2023 15:59:41 +0200 Subject: [PATCH 159/280] Add logcontrol-log and log-reload logcontrol-log provides a log adaptor for the systemd logcontrol interface which enables on-the-fly reconfiguration of logging over DBus. log-reload is a utility crate providing a log implementation that can dynamically modify and replace an underlying logger. It backs the logcontrol-log implementation. --- README.md | 2 ++ src/lib.rs | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/README.md b/README.md index 3dd645799..9a703c5f5 100644 --- a/README.md +++ b/README.md @@ -81,12 +81,14 @@ There are many available implementations to choose from, here are some options: * [`win_dbg_logger`](https://docs.rs/win_dbg_logger/*/win_dbg_logger/) * [`db_logger`](https://docs.rs/db_logger/*/db_logger/) * [`log-to-defmt`](https://docs.rs/log-to-defmt/*/log_to_defmt/) + * [`logcontrol-log`](https://docs.rs/logcontrol-log/*/logcontrol_log/) * For WebAssembly binaries: * [`console_log`](https://docs.rs/console_log/*/console_log/) * For dynamic libraries: * You may need to construct [an FFI-safe wrapper over `log`](https://github.com/rust-lang/log/issues/421) to initialize in your libraries. * Utilities: * [`log_err`](https://docs.rs/log_err/*/log_err/) + * [`log-reload`](https://docs.rs/log-reload/*/log_reload/) Executables should choose a logger implementation and initialize it early in the runtime of the program. Logger implementations will typically include a diff --git a/src/lib.rs b/src/lib.rs index 46d4378af..174e45e95 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -149,10 +149,14 @@ //! * [win_dbg_logger] //! * [db_logger] //! * [log-to-defmt] +//! * [logcontrol-log] //! * For WebAssembly binaries: //! * [console_log] //! * For dynamic libraries: //! * You may need to construct an FFI-safe wrapper over `log` to initialize in your libraries +//! * Utilities: +//! * [log_err] +//! * [log-reload] //! //! # Implementing a Logger //! @@ -317,6 +321,9 @@ //! [log-to-defmt]: https://docs.rs/log-to-defmt/*/log_to_defmt/ //! [console_log]: https://docs.rs/console_log/*/console_log/ //! [structured-logger]: https://docs.rs/structured-logger/latest/structured_logger/ +//! [logcontrol-log]: https://docs.rs/logcontrol-log/*/logcontrol_log/ +//! [log_err]: https://docs.rs/log_err/*/log_err/ +//! [log-reload]: https://docs.rs/log-reload/*/log_reload/ #![doc( html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", From 9e16f8459ac42f22694bffa6b631efcb4f6271ae Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Mon, 20 Nov 2023 00:25:15 +0100 Subject: [PATCH 160/280] Rename Value::to_str to to_cow_str (#592) --- src/kv/value.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/kv/value.rs b/src/kv/value.rs index 4cc5729c4..f8c916557 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -619,7 +619,7 @@ mod std_support { impl<'v> Value<'v> { /// Try convert this value into a string. - pub fn to_str(&self) -> Option> { + pub fn to_cow_str(&self) -> Option> { self.inner.to_str() } } @@ -910,12 +910,12 @@ pub(crate) mod tests { } #[test] - fn test_to_str() { + fn test_to_cow_str() { for v in str() { assert!(v.to_borrowed_str().is_some()); #[cfg(feature = "kv_unstable_std")] - assert!(v.to_str().is_some()); + assert!(v.to_cow_str().is_some()); } let short_lived = String::from("short lived"); @@ -924,13 +924,13 @@ pub(crate) mod tests { assert!(v.to_borrowed_str().is_some()); #[cfg(feature = "kv_unstable_std")] - assert!(v.to_str().is_some()); + assert!(v.to_cow_str().is_some()); for v in unsigned().chain(signed()).chain(float()).chain(bool()) { assert!(v.to_borrowed_str().is_none()); #[cfg(feature = "kv_unstable_std")] - assert!(v.to_str().is_none()); + assert!(v.to_cow_str().is_none()); } } From a78c02543c486c7982a599e0ec15dbc6d094ef29 Mon Sep 17 00:00:00 2001 From: simon Date: Mon, 25 Sep 2023 09:17:52 +0200 Subject: [PATCH 161/280] Add "alterable_logger" link to README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 8789e51a3..d41414473 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,7 @@ There are many available implementations to choose from, here are some options: * Utilities: * [`log_err`](https://docs.rs/log_err/*/log_err/) * [`log-reload`](https://docs.rs/log-reload/*/log_reload/) + * [`alterable_logger`](https://docs.rs/alterable_logger/*/alterable_logger) Executables should choose a logger implementation and initialize it early in the runtime of the program. Logger implementations will typically include a From 6042ec8a85f23d7e47df66074d6427b0c01ab90f Mon Sep 17 00:00:00 2001 From: EFanZh Date: Sun, 3 Dec 2023 13:10:37 +0800 Subject: [PATCH 162/280] Normalize line ending --- src/__private_api.rs | 178 +++++++++++++++++++++---------------------- 1 file changed, 89 insertions(+), 89 deletions(-) diff --git a/src/__private_api.rs b/src/__private_api.rs index 359deebbc..92bd15656 100644 --- a/src/__private_api.rs +++ b/src/__private_api.rs @@ -1,89 +1,89 @@ -//! WARNING: this is not part of the crate's public API and is subject to change at any time - -use self::sealed::KVs; -use crate::{Level, Metadata, Record}; -use std::fmt::Arguments; -pub use std::{file, format_args, line, module_path, stringify}; - -#[cfg(feature = "kv_unstable")] -pub type Value<'a> = dyn crate::kv::value::ToValue + 'a; - -#[cfg(not(feature = "kv_unstable"))] -pub type Value<'a> = str; - -mod sealed { - /// Types for the `kv` argument. - pub trait KVs<'a> { - fn into_kvs(self) -> Option<&'a [(&'a str, &'a super::Value<'a>)]>; - } -} - -// Types for the `kv` argument. - -impl<'a> KVs<'a> for &'a [(&'a str, &'a Value<'a>)] { - #[inline] - fn into_kvs(self) -> Option<&'a [(&'a str, &'a Value<'a>)]> { - Some(self) - } -} - -impl<'a> KVs<'a> for () { - #[inline] - fn into_kvs(self) -> Option<&'a [(&'a str, &'a Value<'a>)]> { - None - } -} - -// Log implementation. - -fn log_impl( - args: Arguments, - level: Level, - &(target, module_path, file): &(&str, &'static str, &'static str), - line: u32, - kvs: Option<&[(&str, &Value)]>, -) { - #[cfg(not(feature = "kv_unstable"))] - if kvs.is_some() { - panic!( - "key-value support is experimental and must be enabled using the `kv_unstable` feature" - ) - } - - let mut builder = Record::builder(); - - builder - .args(args) - .level(level) - .target(target) - .module_path_static(Some(module_path)) - .file_static(Some(file)) - .line(Some(line)); - - #[cfg(feature = "kv_unstable")] - builder.key_values(&kvs); - - crate::logger().log(&builder.build()); -} - -pub fn log<'a, K>( - args: Arguments, - level: Level, - target_module_path_and_file: &(&str, &'static str, &'static str), - line: u32, - kvs: K, -) where - K: KVs<'a>, -{ - log_impl( - args, - level, - target_module_path_and_file, - line, - kvs.into_kvs(), - ) -} - -pub fn enabled(level: Level, target: &str) -> bool { - crate::logger().enabled(&Metadata::builder().level(level).target(target).build()) -} +//! WARNING: this is not part of the crate's public API and is subject to change at any time + +use self::sealed::KVs; +use crate::{Level, Metadata, Record}; +use std::fmt::Arguments; +pub use std::{file, format_args, line, module_path, stringify}; + +#[cfg(feature = "kv_unstable")] +pub type Value<'a> = dyn crate::kv::value::ToValue + 'a; + +#[cfg(not(feature = "kv_unstable"))] +pub type Value<'a> = str; + +mod sealed { + /// Types for the `kv` argument. + pub trait KVs<'a> { + fn into_kvs(self) -> Option<&'a [(&'a str, &'a super::Value<'a>)]>; + } +} + +// Types for the `kv` argument. + +impl<'a> KVs<'a> for &'a [(&'a str, &'a Value<'a>)] { + #[inline] + fn into_kvs(self) -> Option<&'a [(&'a str, &'a Value<'a>)]> { + Some(self) + } +} + +impl<'a> KVs<'a> for () { + #[inline] + fn into_kvs(self) -> Option<&'a [(&'a str, &'a Value<'a>)]> { + None + } +} + +// Log implementation. + +fn log_impl( + args: Arguments, + level: Level, + &(target, module_path, file): &(&str, &'static str, &'static str), + line: u32, + kvs: Option<&[(&str, &Value)]>, +) { + #[cfg(not(feature = "kv_unstable"))] + if kvs.is_some() { + panic!( + "key-value support is experimental and must be enabled using the `kv_unstable` feature" + ) + } + + let mut builder = Record::builder(); + + builder + .args(args) + .level(level) + .target(target) + .module_path_static(Some(module_path)) + .file_static(Some(file)) + .line(Some(line)); + + #[cfg(feature = "kv_unstable")] + builder.key_values(&kvs); + + crate::logger().log(&builder.build()); +} + +pub fn log<'a, K>( + args: Arguments, + level: Level, + target_module_path_and_file: &(&str, &'static str, &'static str), + line: u32, + kvs: K, +) where + K: KVs<'a>, +{ + log_impl( + args, + level, + target_module_path_and_file, + line, + kvs.into_kvs(), + ) +} + +pub fn enabled(level: Level, target: &str) -> bool { + crate::logger().enabled(&Metadata::builder().level(level).target(target).build()) +} From c5ddd6fbe1403b8b01c362cd676c9cc0e74b2016 Mon Sep 17 00:00:00 2001 From: AngelicosPhosphoros Date: Sun, 17 Dec 2023 22:13:14 +0100 Subject: [PATCH 163/280] Remove `ok_or` in favor of `Option::ok_or` Usages of `Option::ok_or` were removed because it was unstable at the time. It is now stable of MSRV. --- src/lib.rs | 37 +++++++++++++------------------------ 1 file changed, 13 insertions(+), 24 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 8cd1fa86f..ad61e3ea8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -474,26 +474,17 @@ impl PartialOrd for Level { } } -fn ok_or(t: Option, e: E) -> Result { - match t { - Some(t) => Ok(t), - None => Err(e), - } -} - impl FromStr for Level { type Err = ParseLevelError; fn from_str(level: &str) -> Result { - ok_or( - LOG_LEVEL_NAMES - .iter() - .position(|&name| name.eq_ignore_ascii_case(level)) - .into_iter() - .filter(|&idx| idx != 0) - .map(|idx| Level::from_usize(idx).unwrap()) - .next(), - ParseLevelError(()), - ) + LOG_LEVEL_NAMES + .iter() + .position(|&name| name.eq_ignore_ascii_case(level)) + .into_iter() + .filter(|&idx| idx != 0) + .map(|idx| Level::from_usize(idx).unwrap()) + .next() + .ok_or(ParseLevelError(())) } } @@ -595,13 +586,11 @@ impl PartialOrd for LevelFilter { impl FromStr for LevelFilter { type Err = ParseLevelError; fn from_str(level: &str) -> Result { - ok_or( - LOG_LEVEL_NAMES - .iter() - .position(|&name| name.eq_ignore_ascii_case(level)) - .map(|p| LevelFilter::from_usize(p).unwrap()), - ParseLevelError(()), - ) + LOG_LEVEL_NAMES + .iter() + .position(|&name| name.eq_ignore_ascii_case(level)) + .map(|p| LevelFilter::from_usize(p).unwrap()) + .ok_or(ParseLevelError(())) } } From 7cb6a01dff9157f3f3dca36aa0152f144023ff60 Mon Sep 17 00:00:00 2001 From: AngelicosPhosphoros Date: Tue, 2 Jan 2024 01:57:23 +0100 Subject: [PATCH 164/280] Use `Acquire` ordering for initialization check Reasoning is provided in the code comment. --- src/lib.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index ad61e3ea8..6a3a8ca98 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1455,7 +1455,15 @@ impl error::Error for ParseLevelError {} /// /// If a logger has not been set, a no-op implementation is returned. pub fn logger() -> &'static dyn Log { - if STATE.load(Ordering::SeqCst) != INITIALIZED { + // Acquire memory ordering guarantees that current thread would see any + // memory writes that happened before store of the value + // into `STATE` with memory ordering `Release` or stronger. + // + // Since the value `INITIALIZED` is written only after `LOGGER` was + // initialized, observing it after `Acquire` load here makes both + // write to the `LOGGER` static and initialization of the logger + // internal state synchronized with current thread. + if STATE.load(Ordering::Acquire) != INITIALIZED { static NOP: NopLogger = NopLogger; &NOP } else { From dbc0a3f1ebe53cdf87dfd68ff313f95294508d97 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Fri, 26 Jan 2024 18:03:14 +1000 Subject: [PATCH 165/280] start filling in docs and remove capture/downcast value support --- src/kv/key.rs | 2 +- src/kv/mod.rs | 56 +++++++++++++++ src/kv/source.rs | 26 ++++--- src/kv/value.rs | 172 ++--------------------------------------------- 4 files changed, 80 insertions(+), 176 deletions(-) diff --git a/src/kv/key.rs b/src/kv/key.rs index 858ec493a..e53a64a6f 100644 --- a/src/kv/key.rs +++ b/src/kv/key.rs @@ -30,7 +30,7 @@ impl ToKey for str { } } -/// A key in a structured key-value pair. +/// A key in a user-defined attribute. // These impls must only be based on the as_str() representation of the key // If a new field (such as an optional index) is added to the key they must not affect comparison #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] diff --git a/src/kv/mod.rs b/src/kv/mod.rs index 5dc69337c..402c34585 100644 --- a/src/kv/mod.rs +++ b/src/kv/mod.rs @@ -11,6 +11,62 @@ //! [dependencies.log] //! features = ["kv_unstable"] //! ``` +//! +//! # Structured logging in `log` +//! +//! Structured logging enhances traditional text-based log records with user-defined +//! attributes. Structured logs can be analyzed using a variety of tranditional +//! data processing techniques, without needing to find and parse attributes from +//! unstructured text first. +//! +//! In `log`, user-defined attributes are part of a [`Source`] on the [`LogRecord`]. +//! Each attribute is a pair of [`Key`] and [`Value`]. Keys are strings and values +//! are a datum of any type that can be formatted or serialized. Simple types like +//! strings, booleans, and numbers are supported, as well as arbitrarily complex +//! structures involving nested objects and sequences. +//! +//! ## Adding attributes to log records +//! +//! Attributes appear after the message format in the `log!` macros: +//! +//! ``` +//! .. +//! ``` +//! +//! ## Working with attributes on log records +//! +//! Use the [`LogRecord::source`] method to access user-defined attributes. +//! Individual attributes can be pulled from the source: +//! +//! ``` +//! .. +//! ``` +//! +//! This is convenient when an attribute of interest is known in advance. +//! All attributes can also be enumerated using a [`Visitor`]: +//! +//! ``` +//! .. +//! ``` +//! +//! [`Value`]s in attributes have methods for conversions to common types: +//! +//! ``` +//! .. +//! ``` +//! +//! Values also have their own [`value::Visitor`] type: +//! +//! ``` +//! .. +//! ``` +//! +//! Visitors on values are lightweight and suitable for detecting primitive types. +//! To serialize a value, you can also use either `serde` or `sval`. If you're +//! in a no-std environment, you can use `sval`. In other cases, you can use `serde`. +//! +//! Values can also always be formatted using the standard `Debug` and `Display` +//! traits. mod error; mod key; diff --git a/src/kv/source.rs b/src/kv/source.rs index 9c56f8b76..510d41acd 100644 --- a/src/kv/source.rs +++ b/src/kv/source.rs @@ -1,23 +1,31 @@ -//! Sources for key-value pairs. +//! Sources for user-defined attributes. use crate::kv::{Error, Key, ToKey, ToValue, Value}; use std::fmt; -/// A source of key-value pairs. +/// A source of user-defined attributes. /// /// The source may be a single pair, a set of pairs, or a filter over a set of pairs. /// Use the [`Visitor`](trait.Visitor.html) trait to inspect the structured data /// in a source. +/// +/// # Examples +/// +/// Enumerating the attributes in a source: +/// +/// ``` +/// .. +/// ``` pub trait Source { - /// Visit key-value pairs. + /// Visit attributes. /// - /// A source doesn't have to guarantee any ordering or uniqueness of key-value pairs. + /// A source doesn't have to guarantee any ordering or uniqueness of attributes. /// If the given visitor returns an error then the source may early-return with it, - /// even if there are more key-value pairs. + /// even if there are more attributes. /// /// # Implementation notes /// - /// A source should yield the same key-value pairs to a subsequent visitor unless + /// A source should yield the same attributes to a subsequent visitor unless /// that visitor itself fails. fn visit<'kvs>(&'kvs self, visitor: &mut dyn Visitor<'kvs>) -> Result<(), Error>; @@ -34,14 +42,14 @@ pub trait Source { get_default(self, key) } - /// Count the number of key-value pairs that can be visited. + /// Count the number of attributes that can be visited. /// /// # Implementation notes /// - /// A source that knows the number of key-value pairs upfront may provide a more + /// A source that knows the number of attributes upfront may provide a more /// efficient implementation. /// - /// A subsequent call to `visit` should yield the same number of key-value pairs + /// A subsequent call to `visit` should yield the same number of attributes /// to the visitor, unless that visitor fails part way through. fn count(&self) -> usize { count_default(self) diff --git a/src/kv/value.rs b/src/kv/value.rs index 1c39bef0a..7b0f71e9d 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -29,73 +29,18 @@ impl<'v> ToValue for Value<'v> { } } -/// Get a value from a type implementing `std::fmt::Debug`. -#[macro_export] -macro_rules! as_debug { - ($capture:expr) => { - $crate::kv::Value::from_debug(&$capture) - }; -} - -/// Get a value from a type implementing `std::fmt::Display`. -#[macro_export] -macro_rules! as_display { - ($capture:expr) => { - $crate::kv::Value::from_display(&$capture) - }; -} - -/// Get a value from an error. -#[cfg(feature = "kv_unstable_std")] -#[macro_export] -macro_rules! as_error { - ($capture:expr) => { - $crate::kv::Value::from_dyn_error(&$capture) - }; -} - -#[cfg(feature = "kv_unstable_serde")] -/// Get a value from a type implementing `serde::Serialize`. -#[macro_export] -macro_rules! as_serde { - ($capture:expr) => { - $crate::kv::Value::from_serde(&$capture) - }; -} - -/// Get a value from a type implementing `sval::Value`. -#[cfg(feature = "kv_unstable_sval")] -#[macro_export] -macro_rules! as_sval { - ($capture:expr) => { - $crate::kv::Value::from_sval(&$capture) - }; -} - -/// A value in a structured key-value pair. +/// A value in a user-defined attribute. +/// +/// Values are an anonymous bag containing some structured datum. /// /// # Capturing values /// /// There are a few ways to capture a value: /// -/// - Using the `Value::capture_*` methods. /// - Using the `Value::from_*` methods. /// - Using the `ToValue` trait. /// - Using the standard `From` trait. /// -/// ## Using the `Value::capture_*` methods -/// -/// `Value` offers a few constructor methods that capture values of different kinds. -/// These methods require a `T: 'static` to support downcasting. -/// -/// ``` -/// use log::kv::Value; -/// -/// let value = Value::capture_debug(&42i32); -/// -/// assert_eq!(Some(42), value.to_i64()); -/// ``` -/// /// ## Using the `Value::from_*` methods /// /// `Value` offers a few constructor methods that capture values of different kinds. @@ -157,59 +102,6 @@ impl<'v> Value<'v> { value.to_value() } - /// Get a value from a type implementing `std::fmt::Debug`. - pub fn capture_debug(value: &'v T) -> Self - where - T: fmt::Debug + 'static, - { - Value { - inner: ValueBag::capture_debug(value), - } - } - - /// Get a value from a type implementing `std::fmt::Display`. - pub fn capture_display(value: &'v T) -> Self - where - T: fmt::Display + 'static, - { - Value { - inner: ValueBag::capture_display(value), - } - } - - /// Get a value from an error. - #[cfg(feature = "kv_unstable_std")] - pub fn capture_error(err: &'v T) -> Self - where - T: std::error::Error + 'static, - { - Value { - inner: ValueBag::capture_error(err), - } - } - - #[cfg(feature = "kv_unstable_serde")] - /// Get a value from a type implementing `serde::Serialize`. - pub fn capture_serde(value: &'v T) -> Self - where - T: serde::Serialize + 'static, - { - Value { - inner: ValueBag::capture_serde1(value), - } - } - - /// Get a value from a type implementing `sval::Value`. - #[cfg(feature = "kv_unstable_sval")] - pub fn capture_sval(value: &'v T) -> Self - where - T: sval::Value + 'static, - { - Value { - inner: ValueBag::capture_sval2(value), - } - } - /// Get a value from a type implementing `std::fmt::Debug`. pub fn from_debug(value: &'v T) -> Self where @@ -284,17 +176,10 @@ impl<'v> Value<'v> { } } - /// Check whether this value can be downcast to `T`. - pub fn is(&self) -> bool { - self.inner.is::() - } - - /// Try downcast this value to `T`. - pub fn downcast_ref(&self) -> Option<&T> { - self.inner.downcast_ref::() - } - /// Inspect this value using a simple visitor. + /// + /// When the `kv_unstable_serde` or `kv_unstable_sval` features are enabled, you can also + /// serialize a value using its `Serialize` or `Value` implementation. pub fn visit(&self, visitor: impl Visit<'v>) -> Result<(), Error> { struct Visitor(V); @@ -824,40 +709,6 @@ pub(crate) mod tests { vec![Value::from('a'), Value::from('⛰')].into_iter() } - #[test] - fn test_capture_fmt() { - assert_eq!(Some(42u64), Value::capture_display(&42).to_u64()); - assert_eq!(Some(42u64), Value::capture_debug(&42).to_u64()); - - assert!(Value::from_display(&42).to_u64().is_none()); - assert!(Value::from_debug(&42).to_u64().is_none()); - } - - #[cfg(feature = "kv_unstable_std")] - #[test] - fn test_capture_error() { - let err = std::io::Error::from(std::io::ErrorKind::Other); - - assert!(Value::capture_error(&err).to_borrowed_error().is_some()); - assert!(Value::from_dyn_error(&err).to_borrowed_error().is_some()); - } - - #[cfg(feature = "kv_unstable_serde")] - #[test] - fn test_capture_serde() { - assert_eq!(Some(42u64), Value::capture_serde(&42).to_u64()); - - assert_eq!(Some(42u64), Value::from_serde(&42).to_u64()); - } - - #[cfg(feature = "kv_unstable_sval")] - #[test] - fn test_capture_sval() { - assert_eq!(Some(42u64), Value::capture_sval(&42).to_u64()); - - assert_eq!(Some(42u64), Value::from_sval(&42).to_u64()); - } - #[test] fn test_to_value_display() { assert_eq!(42u64.to_value().to_string(), "42"); @@ -966,17 +817,6 @@ pub(crate) mod tests { } } - #[test] - fn test_downcast_ref() { - #[derive(Debug)] - struct Foo(u64); - - let v = Value::capture_debug(&Foo(42)); - - assert!(v.is::()); - assert_eq!(42u64, v.downcast_ref::().expect("invalid downcast").0); - } - #[test] fn test_visit_integer() { struct Extract(Option); From fdc1c6e0b8e1a7f5d385d1b77a10b52dd24248b0 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Mon, 29 Jan 2024 08:20:39 +1000 Subject: [PATCH 166/280] rename value::Visit to value::Visitor --- src/kv/mod.rs | 17 +++++++++++++---- src/kv/source.rs | 3 +++ src/kv/value.rs | 27 +++++++++++++++++++-------- src/lib.rs | 2 ++ 4 files changed, 37 insertions(+), 12 deletions(-) diff --git a/src/kv/mod.rs b/src/kv/mod.rs index 402c34585..deaf4615f 100644 --- a/src/kv/mod.rs +++ b/src/kv/mod.rs @@ -1,4 +1,4 @@ -//! **UNSTABLE:** Structured key-value pairs. +//! **UNSTABLE:** Structured logging. //! //! This module is unstable and breaking changes may be made //! at any time. See [the tracking issue](https://github.com/rust-lang-nursery/log/issues/328) @@ -62,11 +62,20 @@ //! ``` //! //! Visitors on values are lightweight and suitable for detecting primitive types. -//! To serialize a value, you can also use either `serde` or `sval`. If you're -//! in a no-std environment, you can use `sval`. In other cases, you can use `serde`. +//! To serialize a value, you can also use either `serde` or `sval`: +//! +//! ``` +//! .. +//! ``` +//! +//! If you're in a no-std environment, you can use `sval`. In other cases, you can use `serde`. //! //! Values can also always be formatted using the standard `Debug` and `Display` -//! traits. +//! traits: +//! +//! ``` +//! .. +//! ``` mod error; mod key; diff --git a/src/kv/source.rs b/src/kv/source.rs index 510d41acd..07e5eb706 100644 --- a/src/kv/source.rs +++ b/src/kv/source.rs @@ -1,4 +1,7 @@ //! Sources for user-defined attributes. +//! +//! This module defines the [`Source`] type and supporting APIs for +//! working with collections of attributes. use crate::kv::{Error, Key, ToKey, ToValue, Value}; use std::fmt; diff --git a/src/kv/value.rs b/src/kv/value.rs index 7b0f71e9d..e1f0cb117 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -1,4 +1,7 @@ //! Structured values. +//! +//! This module defines the [`Value`] type and supporting APIs for +//! capturing and serializing them. use std::fmt; @@ -89,6 +92,14 @@ impl<'v> ToValue for Value<'v> { /// For more complex types one of the following traits can be used: /// * [`sval::Value`], requires the `kv_unstable_sval` feature. /// * [`serde::Serialize`], requires the `kv_unstable_serde` feature. +/// +/// You don't need a [`Visit`] to serialize values. +/// +/// A value can always be serialized using any supported framework, regardless +/// of how it was captured. If, for example, a value was captured using its +/// `Display` implementation, it will serialize as a string. If it was captured +/// as a struct using its `serde::Serialize`, it will also serialize as a struct +/// through `sval`, or be formatted using a `Debug`-compatible representation. pub struct Value<'v> { inner: ValueBag<'v>, } @@ -180,12 +191,12 @@ impl<'v> Value<'v> { /// /// When the `kv_unstable_serde` or `kv_unstable_sval` features are enabled, you can also /// serialize a value using its `Serialize` or `Value` implementation. - pub fn visit(&self, visitor: impl Visit<'v>) -> Result<(), Error> { + pub fn visit(&self, visitor: impl Visitor<'v>) -> Result<(), Error> { struct Visitor(V); - impl<'v, V> value_bag::visit::Visit<'v> for Visitor + impl<'v, V> value_bag::visit::Visitor<'v> for Visitor where - V: Visit<'v>, + V: Visitor<'v>, { fn visit_any(&mut self, value: ValueBag) -> Result<(), value_bag::Error> { self.0 @@ -521,7 +532,7 @@ mod std_support { /// Also see [`Value`'s documentation on seralization]. /// /// [`Value`'s documentation on seralization]: Value#serialization -pub trait Visit<'v> { +pub trait Visitor<'v> { /// Visit a `Value`. /// /// This is the only required method on `Visit` and acts as a fallback for any @@ -592,9 +603,9 @@ pub trait Visit<'v> { } } -impl<'a, 'v, T: ?Sized> Visit<'v> for &'a mut T +impl<'a, 'v, T: ?Sized> Visitor<'v> for &'a mut T where - T: Visit<'v>, + T: Visitor<'v>, { fn visit_any(&mut self, value: Value) -> Result<(), Error> { (**self).visit_any(value) @@ -821,7 +832,7 @@ pub(crate) mod tests { fn test_visit_integer() { struct Extract(Option); - impl<'v> Visit<'v> for Extract { + impl<'v> Visitor<'v> for Extract { fn visit_any(&mut self, value: Value) -> Result<(), Error> { unimplemented!("unexpected value: {value:?}") } @@ -843,7 +854,7 @@ pub(crate) mod tests { fn test_visit_borrowed_str() { struct Extract<'v>(Option<&'v str>); - impl<'v> Visit<'v> for Extract<'v> { + impl<'v> Visitor<'v> for Extract<'v> { fn visit_any(&mut self, value: Value) -> Result<(), Error> { unimplemented!("unexpected value: {value:?}") } diff --git a/src/lib.rs b/src/lib.rs index 6a3a8ca98..6a8e57762 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -121,6 +121,8 @@ //! # #[cfg(not(feature = "kv_unstable_serde"))] //! # fn main() {} //! ``` +//! +//! See the [`kv`] module documentation for more details. //! //! # Available logging implementations //! From 7f93acaae99f4defbce9a6bbd0b52015e4ca24dd Mon Sep 17 00:00:00 2001 From: KodrAus Date: Mon, 29 Jan 2024 15:56:35 +1000 Subject: [PATCH 167/280] start factoring out value-bag --- Cargo.toml | 2 +- src/kv/source.rs | 14 ++-- src/kv/value.rs | 211 +++++++++++++++++++++++++++-------------------- 3 files changed, 129 insertions(+), 98 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 89012be02..99192dc5d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,7 +48,7 @@ std = [] # requires the latest stable # this will have a tighter MSRV before stabilization -kv_unstable = ["value-bag"] +kv_unstable = [] kv_unstable_sval = ["kv_unstable", "value-bag/sval", "sval", "sval_ref"] kv_unstable_std = ["std", "kv_unstable", "value-bag/error"] kv_unstable_serde = ["kv_unstable_std", "value-bag/serde", "serde"] diff --git a/src/kv/source.rs b/src/kv/source.rs index 07e5eb706..2f62e1999 100644 --- a/src/kv/source.rs +++ b/src/kv/source.rs @@ -363,7 +363,7 @@ mod std_support { mod tests { use std::collections::{BTreeMap, HashMap}; - use crate::kv::value::tests::Token; + use crate::kv::value; use super::*; @@ -377,7 +377,7 @@ mod std_support { fn get() { let source = vec![("a", 1), ("b", 2), ("a", 1)]; assert_eq!( - Token::I64(1), + value::inner::Token::I64(1), Source::get(&source, Key::from_str("a")).unwrap().to_token() ); @@ -393,7 +393,7 @@ mod std_support { assert_eq!(2, Source::count(&map)); assert_eq!( - Token::I64(1), + value::inner::Token::I64(1), Source::get(&map, Key::from_str("a")).unwrap().to_token() ); } @@ -406,7 +406,7 @@ mod std_support { assert_eq!(2, Source::count(&map)); assert_eq!( - Token::I64(1), + value::inner::Token::I64(1), Source::get(&map, Key::from_str("a")).unwrap().to_token() ); } @@ -415,7 +415,7 @@ mod std_support { #[cfg(test)] mod tests { - use crate::kv::value::tests::Token; + use crate::kv::value; use super::*; @@ -452,11 +452,11 @@ mod tests { fn get() { let source = &[("a", 1), ("b", 2), ("a", 1)] as &[_]; assert_eq!( - Token::I64(1), + value::inner::Token::I64(1), Source::get(source, Key::from_str("a")).unwrap().to_token() ); assert_eq!( - Token::I64(2), + value::inner::Token::I64(2), Source::get(source, Key::from_str("b")).unwrap().to_token() ); assert!(Source::get(&source, Key::from_str("c")).is_none()); diff --git a/src/kv/value.rs b/src/kv/value.rs index e1f0cb117..5b348f47f 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -7,8 +7,6 @@ use std::fmt; pub use crate::kv::Error; -use value_bag::ValueBag; - /// A type that can be converted into a [`Value`](struct.Value.html). pub trait ToValue { /// Perform the conversion. @@ -101,7 +99,7 @@ impl<'v> ToValue for Value<'v> { /// as a struct using its `serde::Serialize`, it will also serialize as a struct /// through `sval`, or be formatted using a `Debug`-compatible representation. pub struct Value<'v> { - inner: ValueBag<'v>, + inner: inner::Inner<'v>, } impl<'v> Value<'v> { @@ -119,7 +117,7 @@ impl<'v> Value<'v> { T: fmt::Debug, { Value { - inner: ValueBag::from_debug(value), + inner: inner::Inner::from_debug(value), } } @@ -129,7 +127,7 @@ impl<'v> Value<'v> { T: fmt::Display, { Value { - inner: ValueBag::from_display(value), + inner: inner::Inner::from_display(value), } } @@ -140,7 +138,7 @@ impl<'v> Value<'v> { T: serde::Serialize, { Value { - inner: ValueBag::from_serde1(value), + inner: inner::Inner::from_serde1(value), } } @@ -151,21 +149,21 @@ impl<'v> Value<'v> { T: sval::Value, { Value { - inner: ValueBag::from_sval2(value), + inner: inner::Inner::from_sval2(value), } } /// Get a value from a dynamic `std::fmt::Debug`. pub fn from_dyn_debug(value: &'v dyn fmt::Debug) -> Self { Value { - inner: ValueBag::from_dyn_debug(value), + inner: inner::Inner::from_dyn_debug(value), } } /// Get a value from a dynamic `std::fmt::Display`. pub fn from_dyn_display(value: &'v dyn fmt::Display) -> Self { Value { - inner: ValueBag::from_dyn_display(value), + inner: inner::Inner::from_dyn_display(value), } } @@ -173,14 +171,14 @@ impl<'v> Value<'v> { #[cfg(feature = "kv_unstable_std")] pub fn from_dyn_error(err: &'v (dyn std::error::Error + 'static)) -> Self { Value { - inner: ValueBag::from_dyn_error(err), + inner: inner::Inner::from_dyn_error(err), } } /// Get a value from an internal primitive. fn from_value_bag(value: T) -> Self where - T: Into>, + T: Into>, { Value { inner: value.into(), @@ -192,74 +190,7 @@ impl<'v> Value<'v> { /// When the `kv_unstable_serde` or `kv_unstable_sval` features are enabled, you can also /// serialize a value using its `Serialize` or `Value` implementation. pub fn visit(&self, visitor: impl Visitor<'v>) -> Result<(), Error> { - struct Visitor(V); - - impl<'v, V> value_bag::visit::Visitor<'v> for Visitor - where - V: Visitor<'v>, - { - fn visit_any(&mut self, value: ValueBag) -> Result<(), value_bag::Error> { - self.0 - .visit_any(Value { inner: value }) - .map_err(Error::into_value) - } - - fn visit_u64(&mut self, value: u64) -> Result<(), value_bag::Error> { - self.0.visit_u64(value).map_err(Error::into_value) - } - - fn visit_i64(&mut self, value: i64) -> Result<(), value_bag::Error> { - self.0.visit_i64(value).map_err(Error::into_value) - } - - fn visit_u128(&mut self, value: u128) -> Result<(), value_bag::Error> { - self.0.visit_u128(value).map_err(Error::into_value) - } - - fn visit_i128(&mut self, value: i128) -> Result<(), value_bag::Error> { - self.0.visit_i128(value).map_err(Error::into_value) - } - - fn visit_f64(&mut self, value: f64) -> Result<(), value_bag::Error> { - self.0.visit_f64(value).map_err(Error::into_value) - } - - fn visit_bool(&mut self, value: bool) -> Result<(), value_bag::Error> { - self.0.visit_bool(value).map_err(Error::into_value) - } - - fn visit_str(&mut self, value: &str) -> Result<(), value_bag::Error> { - self.0.visit_str(value).map_err(Error::into_value) - } - - fn visit_borrowed_str(&mut self, value: &'v str) -> Result<(), value_bag::Error> { - self.0.visit_borrowed_str(value).map_err(Error::into_value) - } - - fn visit_char(&mut self, value: char) -> Result<(), value_bag::Error> { - self.0.visit_char(value).map_err(Error::into_value) - } - - #[cfg(feature = "kv_unstable_std")] - fn visit_error( - &mut self, - err: &(dyn std::error::Error + 'static), - ) -> Result<(), value_bag::Error> { - self.0.visit_error(err).map_err(Error::into_value) - } - - #[cfg(feature = "kv_unstable_std")] - fn visit_borrowed_error( - &mut self, - err: &'v (dyn std::error::Error + 'static), - ) -> Result<(), value_bag::Error> { - self.0.visit_borrowed_error(err).map_err(Error::into_value) - } - } - - self.inner - .visit(&mut Visitor(visitor)) - .map_err(Error::from_value) + inner::visit(&self.inner, visitor) } } @@ -661,13 +592,113 @@ where } } +#[cfg(feature = "value-bag")] +pub(in crate::kv) mod inner { + use super::*; + + pub use value_bag::ValueBag as Inner; + + #[cfg(test)] + pub use value_bag::test::TestToken as Token; + + #[cfg(test)] + pub fn to_test_token<'v>(inner: &Inner<'v>) -> Token { + inner.to_test_token() + } + + pub fn visit<'v>(inner: &Inner<'v>, visitor: impl Visitor<'v>) -> Result<(), Error> { + struct InnerVisitor(V); + + impl<'v, V> value_bag::visit::Visit<'v> for InnerVisitor + where + V: Visitor<'v>, + { + fn visit_any(&mut self, value: value_bag::ValueBag) -> Result<(), value_bag::Error> { + self.0 + .visit_any(Value { inner: value }) + .map_err(Error::into_value) + } + + fn visit_u64(&mut self, value: u64) -> Result<(), value_bag::Error> { + self.0.visit_u64(value).map_err(Error::into_value) + } + + fn visit_i64(&mut self, value: i64) -> Result<(), value_bag::Error> { + self.0.visit_i64(value).map_err(Error::into_value) + } + + fn visit_u128(&mut self, value: u128) -> Result<(), value_bag::Error> { + self.0.visit_u128(value).map_err(Error::into_value) + } + + fn visit_i128(&mut self, value: i128) -> Result<(), value_bag::Error> { + self.0.visit_i128(value).map_err(Error::into_value) + } + + fn visit_f64(&mut self, value: f64) -> Result<(), value_bag::Error> { + self.0.visit_f64(value).map_err(Error::into_value) + } + + fn visit_bool(&mut self, value: bool) -> Result<(), value_bag::Error> { + self.0.visit_bool(value).map_err(Error::into_value) + } + + fn visit_str(&mut self, value: &str) -> Result<(), value_bag::Error> { + self.0.visit_str(value).map_err(Error::into_value) + } + + fn visit_borrowed_str(&mut self, value: &'v str) -> Result<(), value_bag::Error> { + self.0.visit_borrowed_str(value).map_err(Error::into_value) + } + + fn visit_char(&mut self, value: char) -> Result<(), value_bag::Error> { + self.0.visit_char(value).map_err(Error::into_value) + } + + #[cfg(feature = "kv_unstable_std")] + fn visit_error( + &mut self, + err: &(dyn std::error::Error + 'static), + ) -> Result<(), value_bag::Error> { + self.0.visit_error(err).map_err(Error::into_value) + } + + #[cfg(feature = "kv_unstable_std")] + fn visit_borrowed_error( + &mut self, + err: &'v (dyn std::error::Error + 'static), + ) -> Result<(), value_bag::Error> { + self.0.visit_borrowed_error(err).map_err(Error::into_value) + } + } + + inner + .visit(&mut InnerVisitor(visitor)) + .map_err(Error::from_value) + } +} + +#[cfg(not(feature = "value-bag"))] +pub(in crate::kv) mod inner { + use super::*; + + pub enum Inner<'v> { + + } + + pub enum Token {} + + pub fn visit(inner: &Inner<'v>, visitor: impl Visitor<'v>) -> Result<(), Error> { + todo!() + } +} + #[cfg(test)] pub(crate) mod tests { use super::*; - pub(crate) use value_bag::test::TestToken as Token; impl<'v> Value<'v> { - pub(crate) fn to_token(&self) -> Token { + pub(crate) fn to_token(&self) -> inner::Token { self.inner.to_test_token() } } @@ -735,18 +766,18 @@ pub(crate) mod tests { #[test] fn test_to_value_structured() { - assert_eq!(42u64.to_value().to_token(), Token::U64(42)); - assert_eq!(42i64.to_value().to_token(), Token::I64(42)); - assert_eq!(42.01f64.to_value().to_token(), Token::F64(42.01)); - assert_eq!(true.to_value().to_token(), Token::Bool(true)); - assert_eq!('a'.to_value().to_token(), Token::Char('a')); + assert_eq!(42u64.to_value().to_token(), inner::Token::U64(42)); + assert_eq!(42i64.to_value().to_token(), inner::Token::I64(42)); + assert_eq!(42.01f64.to_value().to_token(), inner::Token::F64(42.01)); + assert_eq!(true.to_value().to_token(), inner::Token::Bool(true)); + assert_eq!('a'.to_value().to_token(), inner::Token::Char('a')); assert_eq!( "a loong string".to_value().to_token(), - Token::Str("a loong string".into()) + inner::Token::Str("a loong string".into()) ); - assert_eq!(Some(true).to_value().to_token(), Token::Bool(true)); - assert_eq!(().to_value().to_token(), Token::None); - assert_eq!(None::.to_value().to_token(), Token::None); + assert_eq!(Some(true).to_value().to_token(), inner::Token::Bool(true)); + assert_eq!(().to_value().to_token(), inner::Token::None); + assert_eq!(None::.to_value().to_token(), inner::Token::None); } #[test] From e3a5b987b97513efb3a2699df176beb9e6a0c6cd Mon Sep 17 00:00:00 2001 From: KodrAus Date: Mon, 29 Jan 2024 16:25:09 +1000 Subject: [PATCH 168/280] stub out the internal value APIs --- src/kv/error.rs | 16 +-- src/kv/value.rs | 261 +++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 234 insertions(+), 43 deletions(-) diff --git a/src/kv/error.rs b/src/kv/error.rs index 9643a47f2..a6f48d0c6 100644 --- a/src/kv/error.rs +++ b/src/kv/error.rs @@ -1,5 +1,7 @@ use std::fmt; +use crate::kv::value; + /// An error encountered while working with structured data. #[derive(Debug)] pub struct Error { @@ -11,7 +13,7 @@ enum Inner { #[cfg(feature = "std")] Boxed(std_support::BoxedError), Msg(&'static str), - Value(value_bag::Error), + Value(value::inner::Error), Fmt, } @@ -23,21 +25,21 @@ impl Error { } } - // Not public so we don't leak the `value_bag` API - pub(super) fn from_value(err: value_bag::Error) -> Self { + // Not public so we don't leak the `value::inner` API + pub(super) fn from_value(err: value::inner::Error) -> Self { Error { inner: Inner::Value(err), } } - // Not public so we don't leak the `value_bag` API - pub(super) fn into_value(self) -> value_bag::Error { + // Not public so we don't leak the `value::inner` API + pub(super) fn into_value(self) -> value::inner::Error { match self.inner { Inner::Value(err) => err, #[cfg(feature = "kv_unstable_std")] - _ => value_bag::Error::boxed(self), + _ => value::inner::Error::boxed(self), #[cfg(not(feature = "kv_unstable_std"))] - _ => value_bag::Error::msg("error inspecting a value"), + _ => value::inner::Error::msg("error inspecting a value"), } } } diff --git a/src/kv/value.rs b/src/kv/value.rs index 5b348f47f..854c0ebc0 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -176,7 +176,7 @@ impl<'v> Value<'v> { } /// Get a value from an internal primitive. - fn from_value_bag(value: T) -> Self + fn from_inner(value: T) -> Self where T: Into>, { @@ -262,39 +262,39 @@ impl ToValue for std::num::NonZeroI128 { impl<'v> From<&'v str> for Value<'v> { fn from(value: &'v str) -> Self { - Value::from_value_bag(value) + Value::from_inner(value) } } impl<'v> From<&'v u128> for Value<'v> { fn from(value: &'v u128) -> Self { - Value::from_value_bag(value) + Value::from_inner(value) } } impl<'v> From<&'v i128> for Value<'v> { fn from(value: &'v i128) -> Self { - Value::from_value_bag(value) + Value::from_inner(value) } } impl<'v> From<&'v std::num::NonZeroU128> for Value<'v> { fn from(v: &'v std::num::NonZeroU128) -> Value<'v> { // SAFETY: `NonZeroU128` and `u128` have the same ABI - Value::from_value_bag(unsafe { &*(v as *const std::num::NonZeroU128 as *const u128) }) + Value::from_inner(unsafe { &*(v as *const std::num::NonZeroU128 as *const u128) }) } } impl<'v> From<&'v std::num::NonZeroI128> for Value<'v> { fn from(v: &'v std::num::NonZeroI128) -> Value<'v> { // SAFETY: `NonZeroI128` and `i128` have the same ABI - Value::from_value_bag(unsafe { &*(v as *const std::num::NonZeroI128 as *const i128) }) + Value::from_inner(unsafe { &*(v as *const std::num::NonZeroI128 as *const i128) }) } } impl ToValue for () { fn to_value(&self) -> Value { - Value::from_value_bag(()) + Value::from_inner(()) } } @@ -305,7 +305,7 @@ where fn to_value(&self) -> Value { match *self { Some(ref value) => value.to_value(), - None => Value::from_value_bag(()), + None => Value::from_inner(()), } } } @@ -321,7 +321,7 @@ macro_rules! impl_to_value_primitive { impl<'v> From<$into_ty> for Value<'v> { fn from(value: $into_ty) -> Self { - Value::from_value_bag(value) + Value::from_inner(value) } } )* @@ -598,6 +598,8 @@ pub(in crate::kv) mod inner { pub use value_bag::ValueBag as Inner; + pub use value_bag::Error; + #[cfg(test)] pub use value_bag::test::TestToken as Token; @@ -606,75 +608,75 @@ pub(in crate::kv) mod inner { inner.to_test_token() } - pub fn visit<'v>(inner: &Inner<'v>, visitor: impl Visitor<'v>) -> Result<(), Error> { + pub fn visit<'v>(inner: &Inner<'v>, visitor: impl Visitor<'v>) -> Result<(), crate::kv::Error> { struct InnerVisitor(V); impl<'v, V> value_bag::visit::Visit<'v> for InnerVisitor where V: Visitor<'v>, { - fn visit_any(&mut self, value: value_bag::ValueBag) -> Result<(), value_bag::Error> { + fn visit_any(&mut self, value: value_bag::ValueBag) -> Result<(), Error> { self.0 .visit_any(Value { inner: value }) - .map_err(Error::into_value) + .map_err(crate::kv::Error::into_value) } - fn visit_u64(&mut self, value: u64) -> Result<(), value_bag::Error> { - self.0.visit_u64(value).map_err(Error::into_value) + fn visit_u64(&mut self, value: u64) -> Result<(), Error> { + self.0.visit_u64(value).map_err(crate::kv::Error::into_value) } - fn visit_i64(&mut self, value: i64) -> Result<(), value_bag::Error> { - self.0.visit_i64(value).map_err(Error::into_value) + fn visit_i64(&mut self, value: i64) -> Result<(), Error> { + self.0.visit_i64(value).map_err(crate::kv::Error::into_value) } - fn visit_u128(&mut self, value: u128) -> Result<(), value_bag::Error> { - self.0.visit_u128(value).map_err(Error::into_value) + fn visit_u128(&mut self, value: u128) -> Result<(), Error> { + self.0.visit_u128(value).map_err(crate::kv::Error::into_value) } - fn visit_i128(&mut self, value: i128) -> Result<(), value_bag::Error> { - self.0.visit_i128(value).map_err(Error::into_value) + fn visit_i128(&mut self, value: i128) -> Result<(), Error> { + self.0.visit_i128(value).map_err(crate::kv::Error::into_value) } - fn visit_f64(&mut self, value: f64) -> Result<(), value_bag::Error> { - self.0.visit_f64(value).map_err(Error::into_value) + fn visit_f64(&mut self, value: f64) -> Result<(), Error> { + self.0.visit_f64(value).map_err(crate::kv::Error::into_value) } - fn visit_bool(&mut self, value: bool) -> Result<(), value_bag::Error> { - self.0.visit_bool(value).map_err(Error::into_value) + fn visit_bool(&mut self, value: bool) -> Result<(), Error> { + self.0.visit_bool(value).map_err(crate::kv::Error::into_value) } - fn visit_str(&mut self, value: &str) -> Result<(), value_bag::Error> { - self.0.visit_str(value).map_err(Error::into_value) + fn visit_str(&mut self, value: &str) -> Result<(), Error> { + self.0.visit_str(value).map_err(crate::kv::Error::into_value) } - fn visit_borrowed_str(&mut self, value: &'v str) -> Result<(), value_bag::Error> { - self.0.visit_borrowed_str(value).map_err(Error::into_value) + fn visit_borrowed_str(&mut self, value: &'v str) -> Result<(), Error> { + self.0.visit_borrowed_str(value).map_err(crate::kv::Error::into_value) } - fn visit_char(&mut self, value: char) -> Result<(), value_bag::Error> { - self.0.visit_char(value).map_err(Error::into_value) + fn visit_char(&mut self, value: char) -> Result<(), Error> { + self.0.visit_char(value).map_err(crate::kv::Error::into_value) } #[cfg(feature = "kv_unstable_std")] fn visit_error( &mut self, err: &(dyn std::error::Error + 'static), - ) -> Result<(), value_bag::Error> { - self.0.visit_error(err).map_err(Error::into_value) + ) -> Result<(), Error> { + self.0.visit_error(err).map_err(crate::kv::Error::into_value) } #[cfg(feature = "kv_unstable_std")] fn visit_borrowed_error( &mut self, err: &'v (dyn std::error::Error + 'static), - ) -> Result<(), value_bag::Error> { - self.0.visit_borrowed_error(err).map_err(Error::into_value) + ) -> Result<(), Error> { + self.0.visit_borrowed_error(err).map_err(crate::kv::Error::into_value) } } inner .visit(&mut InnerVisitor(visitor)) - .map_err(Error::from_value) + .map_err(crate::kv::Error::from_value) } } @@ -682,13 +684,200 @@ pub(in crate::kv) mod inner { pub(in crate::kv) mod inner { use super::*; + #[derive(Clone)] pub enum Inner<'v> { + Str(&'v str), + } + + impl<'v> From<()> for Inner<'v> { + fn from(v: ()) -> Self { + todo!() + } + } + + impl<'v> From for Inner<'v> { + fn from(v: bool) -> Self { + todo!() + } + } + + impl<'v> From for Inner<'v> { + fn from(v: char) -> Self { + todo!() + } + } + + impl<'v> From for Inner<'v> { + fn from(v: f32) -> Self { + todo!() + } + } + + impl<'v> From for Inner<'v> { + fn from(v: f64) -> Self { + todo!() + } + } + + impl<'v> From for Inner<'v> { + fn from(v: i8) -> Self { + todo!() + } + } + + impl<'v> From for Inner<'v> { + fn from(v: i16) -> Self { + todo!() + } + } + + impl<'v> From for Inner<'v> { + fn from(v: i32) -> Self { + todo!() + } + } + + impl<'v> From for Inner<'v> { + fn from(v: i64) -> Self { + todo!() + } + } + + impl<'v> From for Inner<'v> { + fn from(v: isize) -> Self { + todo!() + } + } + + impl<'v> From for Inner<'v> { + fn from(v: u8) -> Self { + todo!() + } + } + + impl<'v> From for Inner<'v> { + fn from(v: u16) -> Self { + todo!() + } + } + + impl<'v> From for Inner<'v> { + fn from(v: u32) -> Self { + todo!() + } + } + + impl<'v> From for Inner<'v> { + fn from(v: u64) -> Self { + todo!() + } + } + + impl<'v> From for Inner<'v> { + fn from(v: usize) -> Self { + todo!() + } + } + + impl<'v> From<&'v i128> for Inner<'v> { + fn from(v: &'v i128) -> Self { + todo!() + } + } + + impl<'v> From<&'v u128> for Inner<'v> { + fn from(v: &'v u128) -> Self { + todo!() + } + } + + impl<'v> From<&'v str> for Inner<'v> { + fn from(v: &'v str) -> Self { + todo!() + } + } + + impl<'v> fmt::Debug for Inner<'v> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + todo!() + } + } + impl<'v> fmt::Display for Inner<'v> { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + todo!() + } } + impl<'v> Inner<'v> { + pub fn from_debug(value: &'v T) -> Self { + todo!() + } + + pub fn from_display(value: &'v T) -> Self { + todo!() + } + + pub fn from_dyn_debug(value: &'v dyn fmt::Debug) -> Self { + todo!() + } + + pub fn from_dyn_display(value: &'v dyn fmt::Display) -> Self { + todo!() + } + + pub fn to_bool(&self) -> Option { + todo!() + } + + pub fn to_char(&self) -> Option { + todo!() + } + + pub fn to_f64(&self) -> Option { + todo!() + } + + pub fn to_i64(&self) -> Option { + todo!() + } + + pub fn to_u64(&self) -> Option { + todo!() + } + + pub fn to_u128(&self) -> Option { + todo!() + } + + pub fn to_i128(&self) -> Option { + todo!() + } + + pub fn to_borrowed_str(&self) -> Option<&'v str> { + todo!() + } + } + + #[derive(Debug, PartialEq, Eq)] pub enum Token {} - pub fn visit(inner: &Inner<'v>, visitor: impl Visitor<'v>) -> Result<(), Error> { + #[derive(Debug)] + pub struct Error {} + + impl Error { + pub fn msg(msg: &'static str) -> Self { + todo!() + } + } + + impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + todo!() + } + } + + pub fn visit<'v>(inner: &Inner<'v>, visitor: impl Visitor<'v>) -> Result<(), crate::kv::Error> { todo!() } } From 9fae53d74eb437eb12e95116d32e4fdf427eb56e Mon Sep 17 00:00:00 2001 From: KodrAus Date: Mon, 29 Jan 2024 16:30:27 +1000 Subject: [PATCH 169/280] fill in the test token API --- src/kv/value.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/kv/value.rs b/src/kv/value.rs index 854c0ebc0..67b5427ea 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -857,10 +857,24 @@ pub(in crate::kv) mod inner { pub fn to_borrowed_str(&self) -> Option<&'v str> { todo!() } + + #[cfg(test)] + pub fn to_test_token(&self) -> Token { + todo!() + } } - #[derive(Debug, PartialEq, Eq)] - pub enum Token {} + #[derive(Debug, PartialEq)] + pub enum Token<'v> { + None, + Bool(bool), + Char(char), + Str(&'v str), + F64(f64), + I64(i64), + U64(u64), + + } #[derive(Debug)] pub struct Error {} From 05119e1886b92b886e945b890b029e522d69fcea Mon Sep 17 00:00:00 2001 From: KodrAus Date: Mon, 29 Jan 2024 20:45:17 +1000 Subject: [PATCH 170/280] fill in some more doc examples --- Cargo.toml | 1 + src/kv/key.rs | 2 +- src/kv/mod.rs | 166 +++++++++++++++++++++++++++++++++++++++++------ src/kv/source.rs | 70 ++++++++++++++++---- src/kv/value.rs | 2 +- 5 files changed, 206 insertions(+), 35 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 99192dc5d..ef0e3eb7c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,6 +61,7 @@ value-bag = { version = "1.4", optional = true, default-features = false } [dev-dependencies] serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" serde_test = "1.0" sval = { version = "2.1" } sval_derive = { version = "2.1" } diff --git a/src/kv/key.rs b/src/kv/key.rs index e53a64a6f..fb58008c8 100644 --- a/src/kv/key.rs +++ b/src/kv/key.rs @@ -30,7 +30,7 @@ impl ToKey for str { } } -/// A key in a user-defined attribute. +/// A key in a key-value. // These impls must only be based on the as_str() representation of the key // If a new field (such as an optional index) is added to the key they must not affect comparison #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] diff --git a/src/kv/mod.rs b/src/kv/mod.rs index deaf4615f..650fc6da2 100644 --- a/src/kv/mod.rs +++ b/src/kv/mod.rs @@ -19,62 +19,186 @@ //! data processing techniques, without needing to find and parse attributes from //! unstructured text first. //! -//! In `log`, user-defined attributes are part of a [`Source`] on the [`LogRecord`]. -//! Each attribute is a pair of [`Key`] and [`Value`]. Keys are strings and values -//! are a datum of any type that can be formatted or serialized. Simple types like -//! strings, booleans, and numbers are supported, as well as arbitrarily complex +//! In `log`, user-defined attributes are part of a [`Source`] on the log record. +//! Each attribute is a key-value; a pair of [`Key`] and [`Value`]. Keys are strings +//! and values are a datum of any type that can be formatted or serialized. Simple types +//! like strings, booleans, and numbers are supported, as well as arbitrarily complex //! structures involving nested objects and sequences. //! -//! ## Adding attributes to log records +//! ## Adding key-values to log records //! -//! Attributes appear after the message format in the `log!` macros: +//! Key-values appear after the message format in the `log!` macros: //! //! ``` //! .. //! ``` //! -//! ## Working with attributes on log records +//! ## Working with key-values on log records //! -//! Use the [`LogRecord::source`] method to access user-defined attributes. -//! Individual attributes can be pulled from the source: +//! Use the [`LogRecord::key_values`] method to access key-values. +//! +//! Individual values can be pulled from the source by their key: //! //! ``` -//! .. +//! # fn main() -> Result<(), log::kv::Error> { +//! use log::kv::{Source, Key, Value}; +//! # let record = log::Record::builder().key_values(&[("a", 1)]).build(); +//! +//! // info!("Something of interest"; a = 1); +//! let a: Value = record.key_values().get(Key::from("a")).unwrap(); +//! # Ok(()) +//! # } //! ``` //! -//! This is convenient when an attribute of interest is known in advance. -//! All attributes can also be enumerated using a [`Visitor`]: +//! All key-values can also be enumerated using a [`source::Visitor`]: //! //! ``` -//! .. +//! # fn main() -> Result<(), log::kv::Error> { +//! # let record = log::Record::builder().key_values(&[("a", 1), ("b", 2), ("c", 3)]).build(); +//! use std::collections::BTreeMap; +//! +//! use log::kv::{self, Source, Key, Value, source::Visitor}; +//! +//! struct Collect<'kvs>(BTreeMap, Value<'kvs>>); +//! +//! impl<'kvs> Visitor<'kvs> for Collect<'kvs> { +//! fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), kv::Error> { +//! self.0.insert(key, value); +//! +//! Ok(()) +//! } +//! } +//! +//! let mut visitor = Collect(BTreeMap::new()); +//! +//! // info!("Something of interest"; a = 1, b = 2, c = 3); +//! record.key_values().visit(&mut visitor)?; +//! +//! let collected = visitor.0; +//! +//! assert_eq!( +//! vec!["a", "b", "c"], +//! collected +//! .keys() +//! .map(|k| k.as_str()) +//! .collect::>(), +//! ); +//! # Ok(()) +//! # } //! ``` //! -//! [`Value`]s in attributes have methods for conversions to common types: +//! [`Value`]s have methods for conversions to common types: //! //! ``` -//! .. +//! # fn main() -> Result<(), log::kv::Error> { +//! use log::kv::{Source, Key}; +//! # let record = log::Record::builder().key_values(&[("a", 1)]).build(); +//! +//! // info!("Something of interest"; a = 1); +//! let a = record.key_values().get(Key::from("a")).unwrap(); +//! +//! assert_eq!(1, a.to_i64().unwrap()); +//! # Ok(()) +//! # } //! ``` //! -//! Values also have their own [`value::Visitor`] type: +//! Values also have their own [`value::Visitor`] type. Visitors are a lightweight +//! API for working with primitives types: //! //! ``` -//! .. +//! # fn main() -> Result<(), log::kv::Error> { +//! use log::kv::{self, Source, Key, value::Visitor}; +//! # let record = log::Record::builder().key_values(&[("a", 1)]).build(); +//! +//! struct IsNumeric(bool); +//! +//! impl<'kvs> Visitor<'kvs> for IsNumeric { +//! fn visit_any(&mut self, _value: kv::Value) -> Result<(), kv::Error> { +//! self.0 = false; +//! Ok(()) +//! } +//! +//! fn visit_u64(&mut self, _value: u64) -> Result<(), kv::Error> { +//! self.0 = true; +//! Ok(()) +//! } +//! +//! fn visit_i64(&mut self, _value: i64) -> Result<(), kv::Error> { +//! self.0 = true; +//! Ok(()) +//! } +//! +//! fn visit_u128(&mut self, _value: u128) -> Result<(), kv::Error> { +//! self.0 = true; +//! Ok(()) +//! } +//! +//! fn visit_i128(&mut self, _value: i128) -> Result<(), kv::Error> { +//! self.0 = true; +//! Ok(()) +//! } +//! +//! fn visit_f64(&mut self, _value: f64) -> Result<(), kv::Error> { +//! self.0 = true; +//! Ok(()) +//! } +//! } +//! +//! // info!("Something of interest"; a = 1); +//! let a = record.key_values().get(Key::from("a")).unwrap(); +//! +//! let mut visitor = IsNumeric(false); +//! +//! a.visit(&mut visitor)?; +//! +//! let is_numeric = visitor.0; +//! +//! assert!(is_numeric); +//! # Ok(()) +//! # } //! ``` //! -//! Visitors on values are lightweight and suitable for detecting primitive types. -//! To serialize a value, you can also use either `serde` or `sval`: +//! To serialize a value to a format like JSON, you can also use either `serde` or `sval`: //! //! ``` -//! .. +//! # fn main() -> Result<(), Box> { +//! # #[cfg(feature = "serde")] +//! # { +//! # use log::kv::Key; +//! # #[derive(serde::Serialize)] struct Data { a: i32, b: bool, c: &'static str } +//! let data = Data { a: 1, b: true, c: "Some data" }; +//! # let source = [("a", log::kv::Value::from_serde(&data))]; +//! # let record = log::Record::builder().key_values(&source).build(); +//! +//! // info!("Something of interest"; a = data); +//! let a = record.key_values().get(Key::from("a")).unwrap(); +//! +//! assert_eq!("{\"a\":1,\"b\":true,\"c\":\"Some data\"}", serde_json::to_string(&a)?); +//! # } +//! # Ok(()) +//! # } //! ``` //! +//! The choice of serialization framework depends on the needs of the consumer. //! If you're in a no-std environment, you can use `sval`. In other cases, you can use `serde`. +//! Log producers and log consumers don't need to agree on the serialization framework. +//! A value can be captured using its `serde::Serialize` implementation and still be serialized +//! through `sval` without losing any structure. //! //! Values can also always be formatted using the standard `Debug` and `Display` //! traits: //! //! ``` -//! .. +//! # use log::kv::Key; +//! # #[derive(Debug)] struct Data { a: i32, b: bool, c: &'static str } +//! let data = Data { a: 1, b: true, c: "Some data" }; +//! # let source = [("a", log::kv::Value::from_debug(&data))]; +//! # let record = log::Record::builder().key_values(&source).build(); +//! +//! // info!("Something of interest"; a = data); +//! let a = record.key_values().get(Key::from("a")).unwrap(); +//! +//! assert_eq!("Data { a: 1, b: true, c: \"Some data\" }", format!("{a:?}")); //! ``` mod error; diff --git a/src/kv/source.rs b/src/kv/source.rs index 2f62e1999..69544162d 100644 --- a/src/kv/source.rs +++ b/src/kv/source.rs @@ -1,34 +1,63 @@ -//! Sources for user-defined attributes. +//! Sources for key-values. //! //! This module defines the [`Source`] type and supporting APIs for -//! working with collections of attributes. +//! working with collections of key-values. use crate::kv::{Error, Key, ToKey, ToValue, Value}; use std::fmt; -/// A source of user-defined attributes. +/// A source of key-values. /// /// The source may be a single pair, a set of pairs, or a filter over a set of pairs. /// Use the [`Visitor`](trait.Visitor.html) trait to inspect the structured data /// in a source. +/// +/// A source is like an iterator over its key-values, except with a push-based API +/// instead of a pull-based one. /// /// # Examples /// -/// Enumerating the attributes in a source: +/// Enumerating the key-values in a source: /// /// ``` -/// .. +/// # fn main() -> Result<(), log::kv::Error> { +/// use log::kv::{self, Source, Key, Value, source::Visitor}; +/// +/// // A `Visitor` that prints all key-values +/// // Visitors are fed the key-value pairs of each key-values +/// struct Printer; +/// +/// impl<'kvs> Visitor<'kvs> for Printer { +/// fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), kv::Error> { +/// println!("{key}: {value}"); +/// +/// Ok(()) +/// } +/// } +/// +/// // A source with 3 key-values +/// // Common collection types implement the `Source` trait +/// let source = &[ +/// ("a", 1), +/// ("b", 2), +/// ("c", 3), +/// ]; +/// +/// // Pass an instance of the `Visitor` to a `Source` to visit it +/// source.visit(&mut Printer)?; +/// # Ok(()) +/// # } /// ``` pub trait Source { - /// Visit attributes. + /// Visit key-values. /// - /// A source doesn't have to guarantee any ordering or uniqueness of attributes. + /// A source doesn't have to guarantee any ordering or uniqueness of key-values. /// If the given visitor returns an error then the source may early-return with it, - /// even if there are more attributes. + /// even if there are more key-values. /// /// # Implementation notes /// - /// A source should yield the same attributes to a subsequent visitor unless + /// A source should yield the same key-values to a subsequent visitor unless /// that visitor itself fails. fn visit<'kvs>(&'kvs self, visitor: &mut dyn Visitor<'kvs>) -> Result<(), Error>; @@ -45,14 +74,14 @@ pub trait Source { get_default(self, key) } - /// Count the number of attributes that can be visited. + /// Count the number of key-values that can be visited. /// /// # Implementation notes /// - /// A source that knows the number of attributes upfront may provide a more + /// A source that knows the number of key-values upfront may provide a more /// efficient implementation. /// - /// A subsequent call to `visit` should yield the same number of attributes + /// A subsequent call to `visit` should yield the same number of key-values /// to the visitor, unless that visitor fails part way through. fn count(&self) -> usize { count_default(self) @@ -165,6 +194,23 @@ where } } +impl Source for [S; N] +where + S: Source, +{ + fn visit<'kvs>(&'kvs self, visitor: &mut dyn Visitor<'kvs>) -> Result<(), Error> { + Source::visit(self as &[_], visitor) + } + + fn get(&self, key: Key) -> Option> { + Source::get(self as &[_], key) + } + + fn count(&self) -> usize { + Source::count(self as &[_]) + } +} + impl Source for Option where S: Source, diff --git a/src/kv/value.rs b/src/kv/value.rs index 67b5427ea..1abc01bde 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -30,7 +30,7 @@ impl<'v> ToValue for Value<'v> { } } -/// A value in a user-defined attribute. +/// A value in a key-value. /// /// Values are an anonymous bag containing some structured datum. /// From 009637717e5b824eb7c1e8d50558b49efd0c6ff0 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Tue, 30 Jan 2024 08:02:41 +1000 Subject: [PATCH 171/280] some more kv docs --- src/kv/mod.rs | 81 ++++++++++++++++++---------------- src/kv/source.rs | 14 +++--- src/kv/value.rs | 110 +++++++++++++++++++++++++++++++++++------------ src/lib.rs | 2 +- 4 files changed, 135 insertions(+), 72 deletions(-) diff --git a/src/kv/mod.rs b/src/kv/mod.rs index 650fc6da2..7bff51fb2 100644 --- a/src/kv/mod.rs +++ b/src/kv/mod.rs @@ -20,31 +20,33 @@ //! unstructured text first. //! //! In `log`, user-defined attributes are part of a [`Source`] on the log record. -//! Each attribute is a key-value; a pair of [`Key`] and [`Value`]. Keys are strings -//! and values are a datum of any type that can be formatted or serialized. Simple types +//! Each attribute is a key-value; a pair of [`Key`] and [`Value`]. Keys are strings +//! and values are a datum of any type that can be formatted or serialized. Simple types //! like strings, booleans, and numbers are supported, as well as arbitrarily complex //! structures involving nested objects and sequences. //! //! ## Adding key-values to log records //! -//! Key-values appear after the message format in the `log!` macros: +//! Key-values appear before the message format in the `log!` macros: //! //! ``` -//! .. +//! # use log::info; +//! info!(a = 1; "Something of interest"); //! ``` //! //! ## Working with key-values on log records //! //! Use the [`LogRecord::key_values`] method to access key-values. -//! +//! //! Individual values can be pulled from the source by their key: //! //! ``` //! # fn main() -> Result<(), log::kv::Error> { //! use log::kv::{Source, Key, Value}; //! # let record = log::Record::builder().key_values(&[("a", 1)]).build(); -//! -//! // info!("Something of interest"; a = 1); +//! +//! // info!(a = 1; "Something of interest"); +//! //! let a: Value = record.key_values().get(Key::from("a")).unwrap(); //! # Ok(()) //! # } @@ -56,28 +58,29 @@ //! # fn main() -> Result<(), log::kv::Error> { //! # let record = log::Record::builder().key_values(&[("a", 1), ("b", 2), ("c", 3)]).build(); //! use std::collections::BTreeMap; -//! +//! //! use log::kv::{self, Source, Key, Value, source::Visitor}; -//! +//! //! struct Collect<'kvs>(BTreeMap, Value<'kvs>>); -//! +//! //! impl<'kvs> Visitor<'kvs> for Collect<'kvs> { //! fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), kv::Error> { //! self.0.insert(key, value); -//! +//! //! Ok(()) //! } //! } -//! +//! //! let mut visitor = Collect(BTreeMap::new()); -//! -//! // info!("Something of interest"; a = 1, b = 2, c = 3); +//! +//! // info!(a = 1, b = 2, c = 3; "Something of interest"); +//! //! record.key_values().visit(&mut visitor)?; -//! +//! //! let collected = visitor.0; -//! +//! //! assert_eq!( -//! vec!["a", "b", "c"], +//! vec!["a", "b", "c"], //! collected //! .keys() //! .map(|k| k.as_str()) @@ -93,10 +96,11 @@ //! # fn main() -> Result<(), log::kv::Error> { //! use log::kv::{Source, Key}; //! # let record = log::Record::builder().key_values(&[("a", 1)]).build(); -//! -//! // info!("Something of interest"; a = 1); +//! +//! // info!(a = 1; "Something of interest"); +//! //! let a = record.key_values().get(Key::from("a")).unwrap(); -//! +//! //! assert_eq!(1, a.to_i64().unwrap()); //! # Ok(()) //! # } @@ -109,9 +113,9 @@ //! # fn main() -> Result<(), log::kv::Error> { //! use log::kv::{self, Source, Key, value::Visitor}; //! # let record = log::Record::builder().key_values(&[("a", 1)]).build(); -//! +//! //! struct IsNumeric(bool); -//! +//! //! impl<'kvs> Visitor<'kvs> for IsNumeric { //! fn visit_any(&mut self, _value: kv::Value) -> Result<(), kv::Error> { //! self.0 = false; @@ -143,23 +147,24 @@ //! Ok(()) //! } //! } -//! -//! // info!("Something of interest"; a = 1); +//! +//! // info!(a = 1; "Something of interest"); +//! //! let a = record.key_values().get(Key::from("a")).unwrap(); -//! +//! //! let mut visitor = IsNumeric(false); -//! +//! //! a.visit(&mut visitor)?; -//! +//! //! let is_numeric = visitor.0; -//! +//! //! assert!(is_numeric); //! # Ok(()) //! # } //! ``` //! //! To serialize a value to a format like JSON, you can also use either `serde` or `sval`: -//! +//! //! ``` //! # fn main() -> Result<(), Box> { //! # #[cfg(feature = "serde")] @@ -169,16 +174,17 @@ //! let data = Data { a: 1, b: true, c: "Some data" }; //! # let source = [("a", log::kv::Value::from_serde(&data))]; //! # let record = log::Record::builder().key_values(&source).build(); -//! -//! // info!("Something of interest"; a = data); +//! +//! // info!(a = data; "Something of interest"); +//! //! let a = record.key_values().get(Key::from("a")).unwrap(); -//! +//! //! assert_eq!("{\"a\":1,\"b\":true,\"c\":\"Some data\"}", serde_json::to_string(&a)?); //! # } //! # Ok(()) //! # } //! ``` -//! +//! //! The choice of serialization framework depends on the needs of the consumer. //! If you're in a no-std environment, you can use `sval`. In other cases, you can use `serde`. //! Log producers and log consumers don't need to agree on the serialization framework. @@ -187,17 +193,18 @@ //! //! Values can also always be formatted using the standard `Debug` and `Display` //! traits: -//! +//! //! ``` //! # use log::kv::Key; //! # #[derive(Debug)] struct Data { a: i32, b: bool, c: &'static str } //! let data = Data { a: 1, b: true, c: "Some data" }; //! # let source = [("a", log::kv::Value::from_debug(&data))]; //! # let record = log::Record::builder().key_values(&source).build(); -//! -//! // info!("Something of interest"; a = data); +//! +//! // info!(a = data; "Something of interest"); +//! //! let a = record.key_values().get(Key::from("a")).unwrap(); -//! +//! //! assert_eq!("Data { a: 1, b: true, c: \"Some data\" }", format!("{a:?}")); //! ``` diff --git a/src/kv/source.rs b/src/kv/source.rs index 69544162d..87d955417 100644 --- a/src/kv/source.rs +++ b/src/kv/source.rs @@ -1,5 +1,5 @@ //! Sources for key-values. -//! +//! //! This module defines the [`Source`] type and supporting APIs for //! working with collections of key-values. @@ -11,7 +11,7 @@ use std::fmt; /// The source may be a single pair, a set of pairs, or a filter over a set of pairs. /// Use the [`Visitor`](trait.Visitor.html) trait to inspect the structured data /// in a source. -/// +/// /// A source is like an iterator over its key-values, except with a push-based API /// instead of a pull-based one. /// @@ -22,19 +22,19 @@ use std::fmt; /// ``` /// # fn main() -> Result<(), log::kv::Error> { /// use log::kv::{self, Source, Key, Value, source::Visitor}; -/// +/// /// // A `Visitor` that prints all key-values /// // Visitors are fed the key-value pairs of each key-values /// struct Printer; -/// +/// /// impl<'kvs> Visitor<'kvs> for Printer { /// fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), kv::Error> { /// println!("{key}: {value}"); -/// +/// /// Ok(()) /// } /// } -/// +/// /// // A source with 3 key-values /// // Common collection types implement the `Source` trait /// let source = &[ @@ -42,7 +42,7 @@ use std::fmt; /// ("b", 2), /// ("c", 3), /// ]; -/// +/// /// // Pass an instance of the `Visitor` to a `Source` to visit it /// source.visit(&mut Printer)?; /// # Ok(()) diff --git a/src/kv/value.rs b/src/kv/value.rs index 1abc01bde..c8cdf6dbb 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -1,5 +1,5 @@ //! Structured values. -//! +//! //! This module defines the [`Value`] type and supporting APIs for //! capturing and serializing them. @@ -45,7 +45,6 @@ impl<'v> ToValue for Value<'v> { /// ## Using the `Value::from_*` methods /// /// `Value` offers a few constructor methods that capture values of different kinds. -/// These methods don't require `T: 'static`, but can't support downcasting. /// /// ``` /// use log::kv::Value; @@ -79,25 +78,43 @@ impl<'v> ToValue for Value<'v> { /// assert_eq!(Some(42), value.to_i64()); /// ``` /// +/// # Data model +/// +/// Values can hold one of a number of types: +/// +/// - **Null:** The absence of any other meaningful value. Note that +/// `Some(Value::null())` is not the same as `None`. The former is +/// `null` while the latter is `undefined`. This is important to be +/// able to tell the difference between a key-value that was logged, +/// but its value was empty (`Some(Value::null())`) and a key-value +/// that was never logged at all (`None`). +/// - **Strings:** `str`, `char`. +/// - **Booleans:** `bool`. +/// - **Integers:** `u8`-`u128`, `i8`-`i128`, `NonZero*`. +/// - **Floating point numbers:** `f32`-`f64`. +/// - **Errors:** `dyn (Error + 'static)`. +/// - **`serde`:** Any type in `serde`'s data model. +/// - **`sval`:** Any type in `sval`'s data model. +/// /// # Serialization /// -/// `Value` provides a number of ways to be serialized. +/// Values provide a number of ways to be serialized. /// /// For basic types the [`Value::visit`] method can be used to extract the /// underlying typed value. However this is limited in the amount of types -/// supported (see the [`Visit`] trait methods). +/// supported (see the [`Visitor`] trait methods). /// /// For more complex types one of the following traits can be used: -/// * [`sval::Value`], requires the `kv_unstable_sval` feature. -/// * [`serde::Serialize`], requires the `kv_unstable_serde` feature. -/// -/// You don't need a [`Visit`] to serialize values. -/// +/// * `sval::Value`, requires the `kv_unstable_sval` feature. +/// * `serde::Serialize`, requires the `kv_unstable_serde` feature. +/// +/// You don't need a visitor to serialize values through `serde` or `sval`. +/// /// A value can always be serialized using any supported framework, regardless /// of how it was captured. If, for example, a value was captured using its -/// `Display` implementation, it will serialize as a string. If it was captured -/// as a struct using its `serde::Serialize`, it will also serialize as a struct -/// through `sval`, or be formatted using a `Debug`-compatible representation. +/// `Display` implementation, it will serialize through `serde` as a string. If it was +/// captured as a struct using `serde`, it will also serialize as a struct +/// through `sval`, or can be formatted using a `Debug`-compatible representation. pub struct Value<'v> { inner: inner::Inner<'v>, } @@ -175,6 +192,13 @@ impl<'v> Value<'v> { } } + /// Get a `null` value. + pub fn null() -> Self { + Value { + inner: inner::Inner::empty(), + } + } + /// Get a value from an internal primitive. fn from_inner(value: T) -> Self where @@ -458,15 +482,22 @@ mod std_support { } } -/// A visitor for a `Value`. +/// A visitor for a [`Value`]. /// -/// Also see [`Value`'s documentation on seralization]. +/// Also see [`Value`'s documentation on seralization]. Visitors are a simple alternative +/// to a more fully-featured serialization framework like `serde` or `sval`. A visitor +/// can differentiate primitive types through methods like [`Visitor::visit_bool`] and +/// [`Visitor::visit_str`], but more complex types like maps and sequences +/// will fallthrough to [`Visitor::visit_any`]. +/// +/// If you're trying to serialize a value to a format like JSON, you can use either `serde` +/// or `sval` directly with the value. You don't need a visitor. /// /// [`Value`'s documentation on seralization]: Value#serialization pub trait Visitor<'v> { /// Visit a `Value`. /// - /// This is the only required method on `Visit` and acts as a fallback for any + /// This is the only required method on `Visitor` and acts as a fallback for any /// more specific methods that aren't overridden. /// The `Value` may be formatted using its `fmt::Debug` or `fmt::Display` implementation, /// or serialized using its `sval::Value` or `serde::Serialize` implementation. @@ -622,39 +653,57 @@ pub(in crate::kv) mod inner { } fn visit_u64(&mut self, value: u64) -> Result<(), Error> { - self.0.visit_u64(value).map_err(crate::kv::Error::into_value) + self.0 + .visit_u64(value) + .map_err(crate::kv::Error::into_value) } fn visit_i64(&mut self, value: i64) -> Result<(), Error> { - self.0.visit_i64(value).map_err(crate::kv::Error::into_value) + self.0 + .visit_i64(value) + .map_err(crate::kv::Error::into_value) } fn visit_u128(&mut self, value: u128) -> Result<(), Error> { - self.0.visit_u128(value).map_err(crate::kv::Error::into_value) + self.0 + .visit_u128(value) + .map_err(crate::kv::Error::into_value) } fn visit_i128(&mut self, value: i128) -> Result<(), Error> { - self.0.visit_i128(value).map_err(crate::kv::Error::into_value) + self.0 + .visit_i128(value) + .map_err(crate::kv::Error::into_value) } fn visit_f64(&mut self, value: f64) -> Result<(), Error> { - self.0.visit_f64(value).map_err(crate::kv::Error::into_value) + self.0 + .visit_f64(value) + .map_err(crate::kv::Error::into_value) } fn visit_bool(&mut self, value: bool) -> Result<(), Error> { - self.0.visit_bool(value).map_err(crate::kv::Error::into_value) + self.0 + .visit_bool(value) + .map_err(crate::kv::Error::into_value) } fn visit_str(&mut self, value: &str) -> Result<(), Error> { - self.0.visit_str(value).map_err(crate::kv::Error::into_value) + self.0 + .visit_str(value) + .map_err(crate::kv::Error::into_value) } fn visit_borrowed_str(&mut self, value: &'v str) -> Result<(), Error> { - self.0.visit_borrowed_str(value).map_err(crate::kv::Error::into_value) + self.0 + .visit_borrowed_str(value) + .map_err(crate::kv::Error::into_value) } fn visit_char(&mut self, value: char) -> Result<(), Error> { - self.0.visit_char(value).map_err(crate::kv::Error::into_value) + self.0 + .visit_char(value) + .map_err(crate::kv::Error::into_value) } #[cfg(feature = "kv_unstable_std")] @@ -662,7 +711,9 @@ pub(in crate::kv) mod inner { &mut self, err: &(dyn std::error::Error + 'static), ) -> Result<(), Error> { - self.0.visit_error(err).map_err(crate::kv::Error::into_value) + self.0 + .visit_error(err) + .map_err(crate::kv::Error::into_value) } #[cfg(feature = "kv_unstable_std")] @@ -670,7 +721,9 @@ pub(in crate::kv) mod inner { &mut self, err: &'v (dyn std::error::Error + 'static), ) -> Result<(), Error> { - self.0.visit_borrowed_error(err).map_err(crate::kv::Error::into_value) + self.0 + .visit_borrowed_error(err) + .map_err(crate::kv::Error::into_value) } } @@ -826,6 +879,10 @@ pub(in crate::kv) mod inner { todo!() } + pub fn empty() -> Self { + todo!() + } + pub fn to_bool(&self) -> Option { todo!() } @@ -873,7 +930,6 @@ pub(in crate::kv) mod inner { F64(f64), I64(i64), U64(u64), - } #[derive(Debug)] diff --git a/src/lib.rs b/src/lib.rs index 6a8e57762..86f3f8ec2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -121,7 +121,7 @@ //! # #[cfg(not(feature = "kv_unstable_serde"))] //! # fn main() {} //! ``` -//! +//! //! See the [`kv`] module documentation for more details. //! //! # Available logging implementations From 54c34f7fbd330c3dffd10addd75480e527a0bae5 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Tue, 30 Jan 2024 20:35:35 +1000 Subject: [PATCH 172/280] start filling in no-dependency value --- Cargo.toml | 2 +- src/kv/value.rs | 244 ++++++++++++++++++++++++++++++------------------ 2 files changed, 152 insertions(+), 94 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ef0e3eb7c..690f25cee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,7 +57,7 @@ kv_unstable_serde = ["kv_unstable_std", "value-bag/serde", "serde"] serde = { version = "1.0", optional = true, default-features = false } sval = { version = "2.1", optional = true, default-features = false } sval_ref = { version = "2.1", optional = true, default-features = false } -value-bag = { version = "1.4", optional = true, default-features = false } +value-bag = { version = "1.4", optional = true, default-features = false, features = ["inline-i128"] } [dev-dependencies] serde = { version = "1.0", features = ["derive"] } diff --git a/src/kv/value.rs b/src/kv/value.rs index c8cdf6dbb..f5f4fc057 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -260,62 +260,12 @@ impl ToValue for str { } } -impl ToValue for u128 { - fn to_value(&self) -> Value { - Value::from(self) - } -} - -impl ToValue for i128 { - fn to_value(&self) -> Value { - Value::from(self) - } -} - -impl ToValue for std::num::NonZeroU128 { - fn to_value(&self) -> Value { - Value::from(self) - } -} - -impl ToValue for std::num::NonZeroI128 { - fn to_value(&self) -> Value { - Value::from(self) - } -} - impl<'v> From<&'v str> for Value<'v> { fn from(value: &'v str) -> Self { Value::from_inner(value) } } -impl<'v> From<&'v u128> for Value<'v> { - fn from(value: &'v u128) -> Self { - Value::from_inner(value) - } -} - -impl<'v> From<&'v i128> for Value<'v> { - fn from(value: &'v i128) -> Self { - Value::from_inner(value) - } -} - -impl<'v> From<&'v std::num::NonZeroU128> for Value<'v> { - fn from(v: &'v std::num::NonZeroU128) -> Value<'v> { - // SAFETY: `NonZeroU128` and `u128` have the same ABI - Value::from_inner(unsafe { &*(v as *const std::num::NonZeroU128 as *const u128) }) - } -} - -impl<'v> From<&'v std::num::NonZeroI128> for Value<'v> { - fn from(v: &'v std::num::NonZeroI128) -> Value<'v> { - // SAFETY: `NonZeroI128` and `i128` have the same ABI - Value::from_inner(unsafe { &*(v as *const std::num::NonZeroI128 as *const i128) }) - } -} - impl ToValue for () { fn to_value(&self) -> Value { Value::from_inner(()) @@ -383,12 +333,12 @@ macro_rules! impl_value_to_primitive { } } -impl_to_value_primitive![usize, u8, u16, u32, u64, isize, i8, i16, i32, i64, f32, f64, char, bool,]; +impl_to_value_primitive![usize, u8, u16, u32, u64, u128, isize, i8, i16, i32, i64, i128, f32, f64, char, bool,]; #[rustfmt::skip] impl_to_value_nonzero_primitive![ - NonZeroUsize, NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, - NonZeroIsize, NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, + NonZeroUsize, NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128, + NonZeroIsize, NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, ]; impl_value_to_primitive![ @@ -503,6 +453,11 @@ pub trait Visitor<'v> { /// or serialized using its `sval::Value` or `serde::Serialize` implementation. fn visit_any(&mut self, value: Value) -> Result<(), Error>; + /// Visit an empty value. + fn visit_null(&mut self) -> Result<(), Error> { + self.visit_any(Value::null()) + } + /// Visit an unsigned integer. fn visit_u64(&mut self, value: u64) -> Result<(), Error> { self.visit_any(value.into()) @@ -515,12 +470,12 @@ pub trait Visitor<'v> { /// Visit a big unsigned integer. fn visit_u128(&mut self, value: u128) -> Result<(), Error> { - self.visit_any((&value).into()) + self.visit_any((value).into()) } /// Visit a big signed integer. fn visit_i128(&mut self, value: i128) -> Result<(), Error> { - self.visit_any((&value).into()) + self.visit_any((value).into()) } /// Visit a floating point. @@ -573,6 +528,10 @@ where (**self).visit_any(value) } + fn visit_null(&mut self) -> Result<(), Error> { + (**self).visit_null() + } + fn visit_u64(&mut self, value: u64) -> Result<(), Error> { (**self).visit_u64(value) } @@ -739,188 +698,287 @@ pub(in crate::kv) mod inner { #[derive(Clone)] pub enum Inner<'v> { + None, + Bool(bool), Str(&'v str), + Char(char), + I64(i64), + U64(u64), + F64(f64), + I128(i128), + U128(u128), + Debug(&'v dyn fmt::Debug), + Display(&'v dyn fmt::Display), } impl<'v> From<()> for Inner<'v> { fn from(v: ()) -> Self { - todo!() + Inner::None } } impl<'v> From for Inner<'v> { fn from(v: bool) -> Self { - todo!() + Inner::Bool(v) } } impl<'v> From for Inner<'v> { fn from(v: char) -> Self { - todo!() + Inner::Char(v) } } impl<'v> From for Inner<'v> { fn from(v: f32) -> Self { - todo!() + Inner::F64(v as f64) } } impl<'v> From for Inner<'v> { fn from(v: f64) -> Self { - todo!() + Inner::F64(v) } } impl<'v> From for Inner<'v> { fn from(v: i8) -> Self { - todo!() + Inner::I64(v as i64) } } impl<'v> From for Inner<'v> { fn from(v: i16) -> Self { - todo!() + Inner::I64(v as i64) } } impl<'v> From for Inner<'v> { fn from(v: i32) -> Self { - todo!() + Inner::I64(v as i64) } } impl<'v> From for Inner<'v> { fn from(v: i64) -> Self { - todo!() + Inner::I64(v as i64) } } impl<'v> From for Inner<'v> { fn from(v: isize) -> Self { - todo!() + Inner::I64(v as i64) } } impl<'v> From for Inner<'v> { fn from(v: u8) -> Self { - todo!() + Inner::U64(v as u64) } } impl<'v> From for Inner<'v> { fn from(v: u16) -> Self { - todo!() + Inner::U64(v as u64) } } impl<'v> From for Inner<'v> { fn from(v: u32) -> Self { - todo!() + Inner::U64(v as u64) } } impl<'v> From for Inner<'v> { fn from(v: u64) -> Self { - todo!() + Inner::U64(v as u64) } } impl<'v> From for Inner<'v> { fn from(v: usize) -> Self { - todo!() + Inner::U64(v as u64) } } - impl<'v> From<&'v i128> for Inner<'v> { - fn from(v: &'v i128) -> Self { - todo!() + impl<'v> From for Inner<'v> { + fn from(v: i128) -> Self { + Inner::I128(v) } } - impl<'v> From<&'v u128> for Inner<'v> { - fn from(v: &'v u128) -> Self { - todo!() + impl<'v> From for Inner<'v> { + fn from(v: u128) -> Self { + Inner::U128(v) } } impl<'v> From<&'v str> for Inner<'v> { fn from(v: &'v str) -> Self { - todo!() + Inner::Str(v) } } impl<'v> fmt::Debug for Inner<'v> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - todo!() + match self { + Inner::None => fmt::Debug::fmt(&None::<()>, f), + Inner::Bool(v) => fmt::Debug::fmt(v, f), + Inner::Str(v) => fmt::Debug::fmt(v, f), + Inner::Char(v) => fmt::Debug::fmt(v, f), + Inner::I64(v) => fmt::Debug::fmt(v, f), + Inner::U64(v) => fmt::Debug::fmt(v, f), + Inner::F64(v) => fmt::Debug::fmt(v, f), + Inner::I128(v) => fmt::Debug::fmt(v, f), + Inner::U128(v) => fmt::Debug::fmt(v, f), + Inner::Debug(v) => fmt::Debug::fmt(v, f), + Inner::Display(v) => fmt::Display::fmt(v, f), + } } } impl<'v> fmt::Display for Inner<'v> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - todo!() + match self { + Inner::None => fmt::Debug::fmt(&None::<()>, f), + Inner::Bool(v) => fmt::Display::fmt(v, f), + Inner::Str(v) => fmt::Display::fmt(v, f), + Inner::Char(v) => fmt::Display::fmt(v, f), + Inner::I64(v) => fmt::Display::fmt(v, f), + Inner::U64(v) => fmt::Display::fmt(v, f), + Inner::F64(v) => fmt::Display::fmt(v, f), + Inner::I128(v) => fmt::Display::fmt(v, f), + Inner::U128(v) => fmt::Display::fmt(v, f), + Inner::Debug(v) => fmt::Debug::fmt(v, f), + Inner::Display(v) => fmt::Display::fmt(v, f), + } } } impl<'v> Inner<'v> { pub fn from_debug(value: &'v T) -> Self { - todo!() + Inner::Debug(value) } pub fn from_display(value: &'v T) -> Self { - todo!() + Inner::Display(value) } pub fn from_dyn_debug(value: &'v dyn fmt::Debug) -> Self { - todo!() + Inner::Debug(value) } pub fn from_dyn_display(value: &'v dyn fmt::Display) -> Self { - todo!() + Inner::Display(value) } pub fn empty() -> Self { - todo!() + Inner::None } pub fn to_bool(&self) -> Option { - todo!() + match self { + Inner::Bool(v) => Some(*v), + _ => None, + } } pub fn to_char(&self) -> Option { - todo!() + match self { + Inner::Char(v) => Some(*v), + _ => None, + } } pub fn to_f64(&self) -> Option { - todo!() + match self { + Inner::F64(v) => Some(*v), + Inner::I64(v) => { + let v: i32 = (*v).try_into().ok()?; + v.try_into().ok() + }, + Inner::U64(v) => { + let v: u32 = (*v).try_into().ok()?; + v.try_into().ok() + }, + Inner::I128(v) => { + let v: i32 = (*v).try_into().ok()?; + v.try_into().ok() + }, + Inner::U128(v) => { + let v: u32 = (*v).try_into().ok()?; + v.try_into().ok() + }, + _ => None, + } } pub fn to_i64(&self) -> Option { - todo!() + match self { + Inner::I64(v) => Some(*v), + Inner::U64(v) => (*v).try_into().ok(), + Inner::I128(v) => (*v).try_into().ok(), + Inner::U128(v) => (*v).try_into().ok(), + _ => None, + } } pub fn to_u64(&self) -> Option { - todo!() + match self { + Inner::U64(v) => Some(*v), + Inner::I64(v) => (*v).try_into().ok(), + Inner::I128(v) => (*v).try_into().ok(), + Inner::U128(v) => (*v).try_into().ok(), + _ => None, + } } pub fn to_u128(&self) -> Option { - todo!() + match self { + Inner::U128(v) => Some(*v), + Inner::I64(v) => (*v).try_into().ok(), + Inner::U64(v) => (*v).try_into().ok(), + Inner::I128(v) => (*v).try_into().ok(), + _ => None, + } } pub fn to_i128(&self) -> Option { - todo!() + match self { + Inner::I128(v) => Some(*v), + Inner::I64(v) => (*v).try_into().ok(), + Inner::U64(v) => (*v).try_into().ok(), + Inner::U128(v) => (*v).try_into().ok(), + _ => None, + } } pub fn to_borrowed_str(&self) -> Option<&'v str> { - todo!() + match self { + Inner::Str(v) => Some(v), + _ => None, + } } #[cfg(test)] pub fn to_test_token(&self) -> Token { - todo!() + match self { + Inner::None => Token::None, + Inner::Bool(v) => Token::Bool(*v), + Inner::Str(v) => Token::Str(*v), + Inner::Char(v) => Token::Char(*v), + Inner::I64(v) => Token::I64(*v), + Inner::U64(v) => Token::U64(*v), + Inner::F64(v) => Token::F64(*v), + Inner::I128(v) => unimplemented!(), + Inner::U128(v) => unimplemented!(), + Inner::Debug(v) => unimplemented!(), + Inner::Display(v) => unimplemented!(), + } } } + #[cfg(test)] #[derive(Debug, PartialEq)] pub enum Token<'v> { None, From 05d7bed9e405d83e417d1748e03888976974ef4c Mon Sep 17 00:00:00 2001 From: KodrAus Date: Wed, 31 Jan 2024 10:42:32 +1000 Subject: [PATCH 173/280] fill in visitor for inline value --- Cargo.toml | 4 ++-- src/kv/value.rs | 20 ++++++++++++++++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 690f25cee..c30944c56 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,7 +57,7 @@ kv_unstable_serde = ["kv_unstable_std", "value-bag/serde", "serde"] serde = { version = "1.0", optional = true, default-features = false } sval = { version = "2.1", optional = true, default-features = false } sval_ref = { version = "2.1", optional = true, default-features = false } -value-bag = { version = "1.4", optional = true, default-features = false, features = ["inline-i128"] } +value-bag = { version = "1.7", optional = true, default-features = false, features = ["inline-i128"] } [dev-dependencies] serde = { version = "1.0", features = ["derive"] } @@ -65,7 +65,7 @@ serde_json = "1.0" serde_test = "1.0" sval = { version = "2.1" } sval_derive = { version = "2.1" } -value-bag = { version = "1.4", features = ["test"] } +value-bag = { version = "1.7", features = ["test"] } # NOTE: log doesn't actually depent on this crate. However our dependencies, # serde and sval, dependent on version 1.0 of the crate, which has problem fixed diff --git a/src/kv/value.rs b/src/kv/value.rs index f5f4fc057..2a16f192c 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -611,6 +611,10 @@ pub(in crate::kv) mod inner { .map_err(crate::kv::Error::into_value) } + fn visit_empty(&mut self) -> Result<(), Error> { + self.0.visit_null().map_err(crate::kv::Error::into_value) + } + fn visit_u64(&mut self, value: u64) -> Result<(), Error> { self.0 .visit_u64(value) @@ -1005,8 +1009,20 @@ pub(in crate::kv) mod inner { } } - pub fn visit<'v>(inner: &Inner<'v>, visitor: impl Visitor<'v>) -> Result<(), crate::kv::Error> { - todo!() + pub fn visit<'v>(inner: &Inner<'v>, mut visitor: impl Visitor<'v>) -> Result<(), crate::kv::Error> { + match inner { + Inner::None => visitor.visit_null(), + Inner::Bool(v) => visitor.visit_bool(*v), + Inner::Str(v) => visitor.visit_borrowed_str(*v), + Inner::Char(v) => visitor.visit_char(*v), + Inner::I64(v) => visitor.visit_i64(*v), + Inner::U64(v) => visitor.visit_u64(*v), + Inner::F64(v) => visitor.visit_f64(*v), + Inner::I128(v) => visitor.visit_i128(*v), + Inner::U128(v) => visitor.visit_u128(*v), + Inner::Debug(v) => visitor.visit_any(Value::from_dyn_debug(*v)), + Inner::Display(v) => visitor.visit_any(Value::from_dyn_display(*v)), + } } } From e711b62c7efd2bb1a2cdb48160bf65b9ae0f3355 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Wed, 31 Jan 2024 12:28:02 +1000 Subject: [PATCH 174/280] fix up some warnings --- src/kv/error.rs | 20 +++++++++++--------- src/kv/value.rs | 17 +---------------- 2 files changed, 12 insertions(+), 25 deletions(-) diff --git a/src/kv/error.rs b/src/kv/error.rs index a6f48d0c6..d654be780 100644 --- a/src/kv/error.rs +++ b/src/kv/error.rs @@ -1,7 +1,5 @@ use std::fmt; -use crate::kv::value; - /// An error encountered while working with structured data. #[derive(Debug)] pub struct Error { @@ -13,7 +11,8 @@ enum Inner { #[cfg(feature = "std")] Boxed(std_support::BoxedError), Msg(&'static str), - Value(value::inner::Error), + #[cfg(feature = "value-bag")] + Value(crate::kv::value::inner::Error), Fmt, } @@ -25,21 +24,23 @@ impl Error { } } - // Not public so we don't leak the `value::inner` API - pub(super) fn from_value(err: value::inner::Error) -> Self { + // Not public so we don't leak the `crate::kv::value::inner` API + #[cfg(feature = "value-bag")] + pub(super) fn from_value(err: crate::kv::value::inner::Error) -> Self { Error { inner: Inner::Value(err), } } - // Not public so we don't leak the `value::inner` API - pub(super) fn into_value(self) -> value::inner::Error { + // Not public so we don't leak the `crate::kv::value::inner` API + #[cfg(feature = "value-bag")] + pub(super) fn into_value(self) -> crate::kv::value::inner::Error { match self.inner { Inner::Value(err) => err, #[cfg(feature = "kv_unstable_std")] - _ => value::inner::Error::boxed(self), + _ => crate::kv::value::inner::Error::boxed(self), #[cfg(not(feature = "kv_unstable_std"))] - _ => value::inner::Error::msg("error inspecting a value"), + _ => crate::kv::value::inner::Error::msg("error inspecting a value"), } } } @@ -50,6 +51,7 @@ impl fmt::Display for Error { match &self.inner { #[cfg(feature = "std")] Boxed(err) => err.fmt(f), + #[cfg(feature = "value-bag")] Value(err) => err.fmt(f), Msg(msg) => msg.fmt(f), Fmt => fmt::Error.fmt(f), diff --git a/src/kv/value.rs b/src/kv/value.rs index 2a16f192c..60828a27a 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -716,7 +716,7 @@ pub(in crate::kv) mod inner { } impl<'v> From<()> for Inner<'v> { - fn from(v: ()) -> Self { + fn from(_: ()) -> Self { Inner::None } } @@ -994,21 +994,6 @@ pub(in crate::kv) mod inner { U64(u64), } - #[derive(Debug)] - pub struct Error {} - - impl Error { - pub fn msg(msg: &'static str) -> Self { - todo!() - } - } - - impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - todo!() - } - } - pub fn visit<'v>(inner: &Inner<'v>, mut visitor: impl Visitor<'v>) -> Result<(), crate::kv::Error> { match inner { Inner::None => visitor.visit_null(), From 67885e05f630243938667319f684d890f146703e Mon Sep 17 00:00:00 2001 From: KodrAus Date: Wed, 31 Jan 2024 13:07:59 +1000 Subject: [PATCH 175/280] add some docs on how Value is implemented --- src/kv/value.rs | 55 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 45 insertions(+), 10 deletions(-) diff --git a/src/kv/value.rs b/src/kv/value.rs index 60828a27a..971bf6bbf 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -333,7 +333,9 @@ macro_rules! impl_value_to_primitive { } } -impl_to_value_primitive![usize, u8, u16, u32, u64, u128, isize, i8, i16, i32, i64, i128, f32, f64, char, bool,]; +impl_to_value_primitive![ + usize, u8, u16, u32, u64, u128, isize, i8, i16, i32, i64, i128, f32, f64, char, bool, +]; #[rustfmt::skip] impl_to_value_nonzero_primitive![ @@ -584,6 +586,13 @@ where #[cfg(feature = "value-bag")] pub(in crate::kv) mod inner { + /** + An implementation of `Value` based on a library called `value_bag`. + + `value_bag` was written specifically for use in `log`'s value, but was split out when it outgrew + the codebase here. It's a general-purpose type-erasure library that handles mapping between + more fully-featured serialization frameworks. + */ use super::*; pub use value_bag::ValueBag as Inner; @@ -698,6 +707,19 @@ pub(in crate::kv) mod inner { #[cfg(not(feature = "value-bag"))] pub(in crate::kv) mod inner { + /** + This is a dependency-free implementation of `Value` when there's no serialization frameworks involved. + In these simple cases a more fully featured solution like `value_bag` isn't needed, so we avoid pulling it in. + + There are a few things here that need to remain consistent with the `value_bag`-based implementation: + + 1. Conversions should always produce the same results. If a conversion here returns `Some`, then + the same `value_bag`-based conversion must also. Of particular note here are floats to ints; they're + based on the standard library's `TryInto` conversions, which need to be convert to `i32` or `u32`, + and then to `f64`. + 2. Visitors should always be called in the same way. If a particular type of value calls `visit_i64`, + then the same `value_bag`-based visitor must also. + */ use super::*; #[derive(Clone)] @@ -900,19 +922,19 @@ pub(in crate::kv) mod inner { Inner::I64(v) => { let v: i32 = (*v).try_into().ok()?; v.try_into().ok() - }, + } Inner::U64(v) => { let v: u32 = (*v).try_into().ok()?; v.try_into().ok() - }, + } Inner::I128(v) => { let v: i32 = (*v).try_into().ok()?; v.try_into().ok() - }, + } Inner::U128(v) => { let v: u32 = (*v).try_into().ok()?; v.try_into().ok() - }, + } _ => None, } } @@ -974,10 +996,10 @@ pub(in crate::kv) mod inner { Inner::I64(v) => Token::I64(*v), Inner::U64(v) => Token::U64(*v), Inner::F64(v) => Token::F64(*v), - Inner::I128(v) => unimplemented!(), - Inner::U128(v) => unimplemented!(), - Inner::Debug(v) => unimplemented!(), - Inner::Display(v) => unimplemented!(), + Inner::I128(_) => unimplemented!(), + Inner::U128(_) => unimplemented!(), + Inner::Debug(_) => unimplemented!(), + Inner::Display(_) => unimplemented!(), } } } @@ -994,7 +1016,10 @@ pub(in crate::kv) mod inner { U64(u64), } - pub fn visit<'v>(inner: &Inner<'v>, mut visitor: impl Visitor<'v>) -> Result<(), crate::kv::Error> { + pub fn visit<'v>( + inner: &Inner<'v>, + mut visitor: impl Visitor<'v>, + ) -> Result<(), crate::kv::Error> { match inner { Inner::None => visitor.visit_null(), Inner::Bool(v) => visitor.visit_bool(*v), @@ -1120,6 +1145,16 @@ pub(crate) mod tests { } } + #[test] + fn test_to_float() { + // Only integers from i32::MIN..=u32::MAX can be converted into floats + assert!(Value::from(i32::MIN).to_f64().is_some()); + assert!(Value::from(u32::MAX).to_f64().is_some()); + + assert!(Value::from((i32::MIN as i64) - 1).to_f64().is_none()); + assert!(Value::from((u32::MAX as u64) + 1).to_f64().is_none()); + } + #[test] fn test_to_cow_str() { for v in str() { From 0374a25554b9f2af5a4f442ea63325f20115d81e Mon Sep 17 00:00:00 2001 From: KodrAus Date: Tue, 13 Feb 2024 20:07:58 +1000 Subject: [PATCH 176/280] work on macro support for capturing --- README.md | 6 +-- src/__private_api.rs | 54 ++++++++++++++++---- src/kv/mod.rs | 58 ++++++++++----------- src/kv/source.rs | 14 ++--- src/kv/value.rs | 51 +++++++++++++------ src/lib.rs | 8 +-- src/macros.rs | 119 ++++++++++++++++++++++++++++++++++++++++++- tests/Cargo.toml | 4 ++ tests/macros.rs | 47 +++++++++++++++++ 9 files changed, 292 insertions(+), 69 deletions(-) diff --git a/README.md b/README.md index d41414473..7b188719f 100644 --- a/README.md +++ b/README.md @@ -103,10 +103,10 @@ The executable itself may use the `log` crate to log as well. If you enable the `kv_unstable` feature, you can associate structured data with your log records: ```rust -use log::{info, trace, warn, as_serde, as_error}; +use log::{info, trace, warn}; pub fn shave_the_yak(yak: &mut Yak) { - trace!(target = "yak_events", yak = as_serde!(yak); "Commencing yak shaving"); + trace!(target = "yak_events", yak:serde = yak; "Commencing yak shaving"); loop { match find_a_razor() { @@ -116,7 +116,7 @@ pub fn shave_the_yak(yak: &mut Yak) { break; } Err(err) => { - warn!(err = as_error!(err); "Unable to locate a razor, retrying"); + warn!(err:error = err; "Unable to locate a razor, retrying"); } } } diff --git a/src/__private_api.rs b/src/__private_api.rs index 92bd15656..8ea869958 100644 --- a/src/__private_api.rs +++ b/src/__private_api.rs @@ -5,31 +5,28 @@ use crate::{Level, Metadata, Record}; use std::fmt::Arguments; pub use std::{file, format_args, line, module_path, stringify}; -#[cfg(feature = "kv_unstable")] -pub type Value<'a> = dyn crate::kv::value::ToValue + 'a; - #[cfg(not(feature = "kv_unstable"))] -pub type Value<'a> = str; +pub type Value<'a> = &'a str; mod sealed { /// Types for the `kv` argument. pub trait KVs<'a> { - fn into_kvs(self) -> Option<&'a [(&'a str, &'a super::Value<'a>)]>; + fn into_kvs(self) -> Option<&'a [(&'a str, super::Value<'a>)]>; } } // Types for the `kv` argument. -impl<'a> KVs<'a> for &'a [(&'a str, &'a Value<'a>)] { +impl<'a> KVs<'a> for &'a [(&'a str, Value<'a>)] { #[inline] - fn into_kvs(self) -> Option<&'a [(&'a str, &'a Value<'a>)]> { + fn into_kvs(self) -> Option<&'a [(&'a str, Value<'a>)]> { Some(self) } } impl<'a> KVs<'a> for () { #[inline] - fn into_kvs(self) -> Option<&'a [(&'a str, &'a Value<'a>)]> { + fn into_kvs(self) -> Option<&'a [(&'a str, Value<'a>)]> { None } } @@ -41,7 +38,7 @@ fn log_impl( level: Level, &(target, module_path, file): &(&str, &'static str, &'static str), line: u32, - kvs: Option<&[(&str, &Value)]>, + kvs: Option<&[(&str, Value)]>, ) { #[cfg(not(feature = "kv_unstable"))] if kvs.is_some() { @@ -87,3 +84,42 @@ pub fn log<'a, K>( pub fn enabled(level: Level, target: &str) -> bool { crate::logger().enabled(&Metadata::builder().level(level).target(target).build()) } + +#[cfg(feature = "kv_unstable")] +mod kv_support { + use super::*; + + use crate::kv; + + pub type Value<'a> = kv::Value<'a>; + + pub fn capture_to_value<'a, V: kv::value::ToValue + ?Sized>(v: &'a &'a V) -> Value<'a> { + v.to_value() + } + + pub fn capture_debug<'a, V: core::fmt::Debug + ?Sized>(v: &'a &'a V) -> Value<'a> { + Value::from_debug(v) + } + + pub fn capture_display<'a, V: core::fmt::Display + ?Sized>(v: &'a &'a V) -> Value<'a> { + Value::from_display(v) + } + + #[cfg(feature = "kv_unstable_std")] + pub fn capture_error<'a>(v: &'a (dyn std::error::Error + 'static)) -> Value<'a> { + Value::from_dyn_error(v) + } + + #[cfg(feature = "kv_unstable_sval")] + pub fn capture_sval<'a, V: sval::Value + ?Sized>(v: &'a &'a V) -> Value<'a> { + Value::from_sval(v) + } + + #[cfg(feature = "kv_unstable_serde")] + pub fn capture_serde<'a, V: serde::Serialize + ?Sized>(v: &'a &'a V) -> Value<'a> { + Value::from_serde(v) + } +} + +#[cfg(feature = "kv_unstable")] +pub use self::kv_support::*; diff --git a/src/kv/mod.rs b/src/kv/mod.rs index 650fc6da2..1b86bda93 100644 --- a/src/kv/mod.rs +++ b/src/kv/mod.rs @@ -20,8 +20,8 @@ //! unstructured text first. //! //! In `log`, user-defined attributes are part of a [`Source`] on the log record. -//! Each attribute is a key-value; a pair of [`Key`] and [`Value`]. Keys are strings -//! and values are a datum of any type that can be formatted or serialized. Simple types +//! Each attribute is a key-value; a pair of [`Key`] and [`Value`]. Keys are strings +//! and values are a datum of any type that can be formatted or serialized. Simple types //! like strings, booleans, and numbers are supported, as well as arbitrarily complex //! structures involving nested objects and sequences. //! @@ -36,14 +36,14 @@ //! ## Working with key-values on log records //! //! Use the [`LogRecord::key_values`] method to access key-values. -//! +//! //! Individual values can be pulled from the source by their key: //! //! ``` //! # fn main() -> Result<(), log::kv::Error> { //! use log::kv::{Source, Key, Value}; //! # let record = log::Record::builder().key_values(&[("a", 1)]).build(); -//! +//! //! // info!("Something of interest"; a = 1); //! let a: Value = record.key_values().get(Key::from("a")).unwrap(); //! # Ok(()) @@ -56,28 +56,28 @@ //! # fn main() -> Result<(), log::kv::Error> { //! # let record = log::Record::builder().key_values(&[("a", 1), ("b", 2), ("c", 3)]).build(); //! use std::collections::BTreeMap; -//! +//! //! use log::kv::{self, Source, Key, Value, source::Visitor}; -//! +//! //! struct Collect<'kvs>(BTreeMap, Value<'kvs>>); -//! +//! //! impl<'kvs> Visitor<'kvs> for Collect<'kvs> { //! fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), kv::Error> { //! self.0.insert(key, value); -//! +//! //! Ok(()) //! } //! } -//! +//! //! let mut visitor = Collect(BTreeMap::new()); -//! +//! //! // info!("Something of interest"; a = 1, b = 2, c = 3); //! record.key_values().visit(&mut visitor)?; -//! +//! //! let collected = visitor.0; -//! +//! //! assert_eq!( -//! vec!["a", "b", "c"], +//! vec!["a", "b", "c"], //! collected //! .keys() //! .map(|k| k.as_str()) @@ -93,10 +93,10 @@ //! # fn main() -> Result<(), log::kv::Error> { //! use log::kv::{Source, Key}; //! # let record = log::Record::builder().key_values(&[("a", 1)]).build(); -//! +//! //! // info!("Something of interest"; a = 1); //! let a = record.key_values().get(Key::from("a")).unwrap(); -//! +//! //! assert_eq!(1, a.to_i64().unwrap()); //! # Ok(()) //! # } @@ -109,9 +109,9 @@ //! # fn main() -> Result<(), log::kv::Error> { //! use log::kv::{self, Source, Key, value::Visitor}; //! # let record = log::Record::builder().key_values(&[("a", 1)]).build(); -//! +//! //! struct IsNumeric(bool); -//! +//! //! impl<'kvs> Visitor<'kvs> for IsNumeric { //! fn visit_any(&mut self, _value: kv::Value) -> Result<(), kv::Error> { //! self.0 = false; @@ -143,23 +143,23 @@ //! Ok(()) //! } //! } -//! +//! //! // info!("Something of interest"; a = 1); //! let a = record.key_values().get(Key::from("a")).unwrap(); -//! +//! //! let mut visitor = IsNumeric(false); -//! +//! //! a.visit(&mut visitor)?; -//! +//! //! let is_numeric = visitor.0; -//! +//! //! assert!(is_numeric); //! # Ok(()) //! # } //! ``` //! //! To serialize a value to a format like JSON, you can also use either `serde` or `sval`: -//! +//! //! ``` //! # fn main() -> Result<(), Box> { //! # #[cfg(feature = "serde")] @@ -169,16 +169,16 @@ //! let data = Data { a: 1, b: true, c: "Some data" }; //! # let source = [("a", log::kv::Value::from_serde(&data))]; //! # let record = log::Record::builder().key_values(&source).build(); -//! +//! //! // info!("Something of interest"; a = data); //! let a = record.key_values().get(Key::from("a")).unwrap(); -//! +//! //! assert_eq!("{\"a\":1,\"b\":true,\"c\":\"Some data\"}", serde_json::to_string(&a)?); //! # } //! # Ok(()) //! # } //! ``` -//! +//! //! The choice of serialization framework depends on the needs of the consumer. //! If you're in a no-std environment, you can use `sval`. In other cases, you can use `serde`. //! Log producers and log consumers don't need to agree on the serialization framework. @@ -187,17 +187,17 @@ //! //! Values can also always be formatted using the standard `Debug` and `Display` //! traits: -//! +//! //! ``` //! # use log::kv::Key; //! # #[derive(Debug)] struct Data { a: i32, b: bool, c: &'static str } //! let data = Data { a: 1, b: true, c: "Some data" }; //! # let source = [("a", log::kv::Value::from_debug(&data))]; //! # let record = log::Record::builder().key_values(&source).build(); -//! +//! //! // info!("Something of interest"; a = data); //! let a = record.key_values().get(Key::from("a")).unwrap(); -//! +//! //! assert_eq!("Data { a: 1, b: true, c: \"Some data\" }", format!("{a:?}")); //! ``` diff --git a/src/kv/source.rs b/src/kv/source.rs index 69544162d..87d955417 100644 --- a/src/kv/source.rs +++ b/src/kv/source.rs @@ -1,5 +1,5 @@ //! Sources for key-values. -//! +//! //! This module defines the [`Source`] type and supporting APIs for //! working with collections of key-values. @@ -11,7 +11,7 @@ use std::fmt; /// The source may be a single pair, a set of pairs, or a filter over a set of pairs. /// Use the [`Visitor`](trait.Visitor.html) trait to inspect the structured data /// in a source. -/// +/// /// A source is like an iterator over its key-values, except with a push-based API /// instead of a pull-based one. /// @@ -22,19 +22,19 @@ use std::fmt; /// ``` /// # fn main() -> Result<(), log::kv::Error> { /// use log::kv::{self, Source, Key, Value, source::Visitor}; -/// +/// /// // A `Visitor` that prints all key-values /// // Visitors are fed the key-value pairs of each key-values /// struct Printer; -/// +/// /// impl<'kvs> Visitor<'kvs> for Printer { /// fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), kv::Error> { /// println!("{key}: {value}"); -/// +/// /// Ok(()) /// } /// } -/// +/// /// // A source with 3 key-values /// // Common collection types implement the `Source` trait /// let source = &[ @@ -42,7 +42,7 @@ use std::fmt; /// ("b", 2), /// ("c", 3), /// ]; -/// +/// /// // Pass an instance of the `Visitor` to a `Source` to visit it /// source.visit(&mut Printer)?; /// # Ok(()) diff --git a/src/kv/value.rs b/src/kv/value.rs index 1abc01bde..43e682825 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -1,5 +1,5 @@ //! Structured values. -//! +//! //! This module defines the [`Value`] type and supporting APIs for //! capturing and serializing them. @@ -90,9 +90,9 @@ impl<'v> ToValue for Value<'v> { /// For more complex types one of the following traits can be used: /// * [`sval::Value`], requires the `kv_unstable_sval` feature. /// * [`serde::Serialize`], requires the `kv_unstable_serde` feature. -/// +/// /// You don't need a [`Visit`] to serialize values. -/// +/// /// A value can always be serialized using any supported framework, regardless /// of how it was captured. If, for example, a value was captured using its /// `Display` implementation, it will serialize as a string. If it was captured @@ -622,39 +622,57 @@ pub(in crate::kv) mod inner { } fn visit_u64(&mut self, value: u64) -> Result<(), Error> { - self.0.visit_u64(value).map_err(crate::kv::Error::into_value) + self.0 + .visit_u64(value) + .map_err(crate::kv::Error::into_value) } fn visit_i64(&mut self, value: i64) -> Result<(), Error> { - self.0.visit_i64(value).map_err(crate::kv::Error::into_value) + self.0 + .visit_i64(value) + .map_err(crate::kv::Error::into_value) } fn visit_u128(&mut self, value: u128) -> Result<(), Error> { - self.0.visit_u128(value).map_err(crate::kv::Error::into_value) + self.0 + .visit_u128(value) + .map_err(crate::kv::Error::into_value) } fn visit_i128(&mut self, value: i128) -> Result<(), Error> { - self.0.visit_i128(value).map_err(crate::kv::Error::into_value) + self.0 + .visit_i128(value) + .map_err(crate::kv::Error::into_value) } fn visit_f64(&mut self, value: f64) -> Result<(), Error> { - self.0.visit_f64(value).map_err(crate::kv::Error::into_value) + self.0 + .visit_f64(value) + .map_err(crate::kv::Error::into_value) } fn visit_bool(&mut self, value: bool) -> Result<(), Error> { - self.0.visit_bool(value).map_err(crate::kv::Error::into_value) + self.0 + .visit_bool(value) + .map_err(crate::kv::Error::into_value) } fn visit_str(&mut self, value: &str) -> Result<(), Error> { - self.0.visit_str(value).map_err(crate::kv::Error::into_value) + self.0 + .visit_str(value) + .map_err(crate::kv::Error::into_value) } fn visit_borrowed_str(&mut self, value: &'v str) -> Result<(), Error> { - self.0.visit_borrowed_str(value).map_err(crate::kv::Error::into_value) + self.0 + .visit_borrowed_str(value) + .map_err(crate::kv::Error::into_value) } fn visit_char(&mut self, value: char) -> Result<(), Error> { - self.0.visit_char(value).map_err(crate::kv::Error::into_value) + self.0 + .visit_char(value) + .map_err(crate::kv::Error::into_value) } #[cfg(feature = "kv_unstable_std")] @@ -662,7 +680,9 @@ pub(in crate::kv) mod inner { &mut self, err: &(dyn std::error::Error + 'static), ) -> Result<(), Error> { - self.0.visit_error(err).map_err(crate::kv::Error::into_value) + self.0 + .visit_error(err) + .map_err(crate::kv::Error::into_value) } #[cfg(feature = "kv_unstable_std")] @@ -670,7 +690,9 @@ pub(in crate::kv) mod inner { &mut self, err: &'v (dyn std::error::Error + 'static), ) -> Result<(), Error> { - self.0.visit_borrowed_error(err).map_err(crate::kv::Error::into_value) + self.0 + .visit_borrowed_error(err) + .map_err(crate::kv::Error::into_value) } } @@ -873,7 +895,6 @@ pub(in crate::kv) mod inner { F64(f64), I64(i64), U64(u64), - } #[derive(Debug)] diff --git a/src/lib.rs b/src/lib.rs index 6a8e57762..e0577ce97 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -99,10 +99,10 @@ //! # fn find_a_razor() -> Result { Ok(1) } //! # #[cfg(feature = "kv_unstable_serde")] //! # fn main() { -//! use log::{info, warn, as_serde, as_error}; +//! use log::{info, warn}; //! //! pub fn shave_the_yak(yak: &mut Yak) { -//! info!(target: "yak_events", yak = as_serde!(yak); "Commencing yak shaving"); +//! info!(target: "yak_events", yak:serde = yak; "Commencing yak shaving"); //! //! loop { //! match find_a_razor() { @@ -112,7 +112,7 @@ //! break; //! } //! Err(err) => { -//! warn!(err = as_error!(err); "Unable to locate a razor, retrying"); +//! warn!(err:error = err; "Unable to locate a razor, retrying"); //! } //! } //! } @@ -121,7 +121,7 @@ //! # #[cfg(not(feature = "kv_unstable_serde"))] //! # fn main() {} //! ``` -//! +//! //! See the [`kv`] module documentation for more details. //! //! # Available logging implementations diff --git a/src/macros.rs b/src/macros.rs index 44945f0d9..3e8ba4e73 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -30,7 +30,7 @@ #[macro_export] macro_rules! log { // log!(target: "my_target", Level::Info, key1 = 42, key2 = true; "a {} event", "log"); - (target: $target:expr, $lvl:expr, $($key:tt = $value:expr),+; $($arg:tt)+) => ({ + (target: $target:expr, $lvl:expr, $($key:tt $(:$capture:tt)? = $value:expr),+; $($arg:tt)+) => ({ let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { $crate::__private_api::log::<&_>( @@ -38,7 +38,7 @@ macro_rules! log { lvl, &($target, $crate::__private_api::module_path!(), $crate::__private_api::file!()), $crate::__private_api::line!(), - &[$(($crate::__log_key!($key), &$value)),+] + &[$(($crate::__log_key!($key), $crate::__log_value!(($value)$(:$capture)*))),+] ); } }); @@ -228,6 +228,7 @@ macro_rules! log_enabled { #[doc(hidden)] #[macro_export] +#[cfg(feature = "kv_unstable")] macro_rules! __log_key { // key1 = 42 ($($args:ident)*) => { @@ -238,3 +239,117 @@ macro_rules! __log_key { $($args)* }; } + +#[doc(hidden)] +#[macro_export] +#[cfg(not(feature = "kv_unstable"))] +macro_rules! __log_key { + ($($args:tt)*) => { + compile_error!("key value support requires the `kv_unstable` feature of `log`") + }; +} + +#[doc(hidden)] +#[macro_export] +#[cfg(feature = "kv_unstable")] +macro_rules! __log_value { + // Default + (($args:expr)) => { + $crate::__log_value!(($args):value) + }; + // ToValue + (($args:expr):value) => { + $crate::__private_api::capture_to_value(&&$args) + }; + // Debug + (($args:expr):?) => { + $crate::__private_api::capture_debug(&&$args) + }; + (($args:expr):debug) => { + $crate::__private_api::capture_debug(&&$args) + }; + // Display + (($args:expr):%) => { + $crate::__private_api::capture_display(&&$args) + }; + (($args:expr):display) => { + $crate::__private_api::capture_display(&&$args) + }; + //Error + (($args:expr):error) => { + $crate::__log_value_error!($args) + }; + // sval::Value + (($args:expr):sval) => { + $crate::__log_value_sval!($args) + }; + // serde::Serialize + (($args:expr):serde) => { + $crate::__log_value_serde!($args) + }; +} + +#[doc(hidden)] +#[macro_export] +#[cfg(not(feature = "kv_unstable"))] +macro_rules! __log_value { + ($($args:tt)*) => { + compile_error!("key value support requires the `kv_unstable` feature of `log`") + }; +} + +#[doc(hidden)] +#[macro_export] +#[cfg(not(feature = "kv_unstable_std"))] +macro_rules! __log_value_error { + ($args:expr) => { + compile_error!("capturing values as `std::error::Error` requites the `kv_unstable_std` feature of `log`") + } +} + +#[doc(hidden)] +#[macro_export] +#[cfg(feature = "kv_unstable_sval")] +macro_rules! __log_value_sval { + ($args:expr) => { + $crate::__private_api::capture_sval(&&$args) + }; +} + +#[doc(hidden)] +#[macro_export] +#[cfg(not(feature = "kv_unstable_sval"))] +macro_rules! __log_value_sval { + ($args:expr) => { + compile_error!( + "capturing values as `sval::Value` requites the `kv_unstable_sval` feature of `log`" + ) + }; +} + +#[doc(hidden)] +#[macro_export] +#[cfg(feature = "kv_unstable_serde")] +macro_rules! __log_value_serde { + ($args:expr) => { + $crate::__private_api::capture_serde(&&$args) + }; +} + +#[doc(hidden)] +#[macro_export] +#[cfg(not(feature = "kv_unstable_serde"))] +macro_rules! __log_value_serde { + ($args:expr) => { + compile_error!("capturing values as `serde::Serialize` requites the `kv_unstable_serde` feature of `log`") + } +} + +#[doc(hidden)] +#[macro_export] +#[cfg(feature = "kv_unstable_std")] +macro_rules! __log_value_error { + ($args:expr) => { + $crate::__private_api::capture_error(&$args) + }; +} diff --git a/tests/Cargo.toml b/tests/Cargo.toml index 88f37b5d4..7d0d3e853 100644 --- a/tests/Cargo.toml +++ b/tests/Cargo.toml @@ -7,6 +7,10 @@ build = "src/build.rs" [features] std = ["log/std"] +kv_unstable = ["log/kv_unstable"] +kv_unstable_std = ["log/kv_unstable_std"] +kv_unstable_sval = ["log/kv_unstable_sval"] +kv_unstable_serde = ["log/kv_unstable_serde"] [dependencies.log] path = ".." diff --git a/tests/macros.rs b/tests/macros.rs index 3afcf88da..47cc957d9 100644 --- a/tests/macros.rs +++ b/tests/macros.rs @@ -250,6 +250,53 @@ fn kv_common_value_types() { ); } +#[test] +#[cfg(feature = "kv_unstable")] +fn kv_debug() { + all_log_macros!( + a:? = 42, + b:debug = 42; + "hello world" + ); +} + +#[test] +#[cfg(feature = "kv_unstable")] +fn kv_display() { + all_log_macros!( + a:% = 42, + b:display = 42; + "hello world" + ); +} + +#[test] +#[cfg(feature = "kv_unstable_std")] +fn kv_error() { + all_log_macros!( + a:error = std::io::Error::new(std::io::ErrorKind::Other, "an error"); + "hello world" + ); +} + +#[test] +#[cfg(feature = "kv_unstable_sval")] +fn kv_sval() { + all_log_macros!( + a:sval = 42; + "hello world" + ); +} + +#[test] +#[cfg(feature = "kv_unstable_serde")] +fn kv_serde() { + all_log_macros!( + a:serde = 42; + "hello world" + ); +} + /// Some and None (from Option) are used in the macros. #[derive(Debug)] enum Type { From 6b483c62cd8f4072117722e113334fd0782a535a Mon Sep 17 00:00:00 2001 From: KodrAus Date: Tue, 13 Feb 2024 20:17:58 +1000 Subject: [PATCH 177/280] make capturing docs easier to read --- src/kv/mod.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/kv/mod.rs b/src/kv/mod.rs index 18c2dbd9d..8a0eb1a56 100644 --- a/src/kv/mod.rs +++ b/src/kv/mod.rs @@ -45,13 +45,13 @@ //! //! The following capturing modifiers are supported: //! -//! - `:?`: `Debug`. -//! - `:debug`: `Debug`. -//! - `:%`: `Display`. -//! - `:display`: `Display`. -//! - `:error`: `std::error::Error` (requires the `kv_unstable_error` feature). -//! - `:sval`: `sval::Value` (requires the `kv_unstable_sval` feature). -//! - `:serde`: `serde::Serialize` (requires the `kv_unstable_serde` feature). +//! - `:?` will capture the value using `Debug`. +//! - `:debug` will capture the value using `Debug`. +//! - `:%` will capture the value using `Display`. +//! - `:display` will capture the value using `Display`. +//! - `:error` will capture the value using `std::error::Error` (requires the `kv_unstable_error` feature). +//! - `:sval` will capture the value using `sval::Value` (requires the `kv_unstable_sval` feature). +//! - `:serde` will capture the value using `serde::Serialize` (requires the `kv_unstable_serde` feature). //! //! ## Working with key-values on log records //! From d8dc6a834bae3bb55b0121e78adcfb31ffb64681 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Tue, 13 Feb 2024 20:30:05 +1000 Subject: [PATCH 178/280] rename source::Visitor to VisitSource and value::Visitor to VisitValue --- src/kv/mod.rs | 19 +++++++-------- src/kv/source.rs | 62 ++++++++++++++++++++++++------------------------ src/kv/value.rs | 40 +++++++++++++++---------------- src/lib.rs | 8 +++---- 4 files changed, 63 insertions(+), 66 deletions(-) diff --git a/src/kv/mod.rs b/src/kv/mod.rs index 8a0eb1a56..6d38dbe50 100644 --- a/src/kv/mod.rs +++ b/src/kv/mod.rs @@ -71,18 +71,18 @@ //! # } //! ``` //! -//! All key-values can also be enumerated using a [`source::Visitor`]: +//! All key-values can also be enumerated using a [`VisitSource`]: //! //! ``` //! # fn main() -> Result<(), log::kv::Error> { //! # let record = log::Record::builder().key_values(&[("a", 1), ("b", 2), ("c", 3)]).build(); //! use std::collections::BTreeMap; //! -//! use log::kv::{self, Source, Key, Value, source::Visitor}; +//! use log::kv::{self, Source, Key, Value, VisitSource}; //! //! struct Collect<'kvs>(BTreeMap, Value<'kvs>>); //! -//! impl<'kvs> Visitor<'kvs> for Collect<'kvs> { +//! impl<'kvs> VisitSource<'kvs> for Collect<'kvs> { //! fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), kv::Error> { //! self.0.insert(key, value); //! @@ -125,17 +125,17 @@ //! # } //! ``` //! -//! Values also have their own [`value::Visitor`] type. Visitors are a lightweight +//! Values also have their own [`VisitValue`] type. Value visitors are a lightweight //! API for working with primitives types: //! //! ``` //! # fn main() -> Result<(), log::kv::Error> { -//! use log::kv::{self, Source, Key, value::Visitor}; +//! use log::kv::{self, Source, Key, VisitValue}; //! # let record = log::Record::builder().key_values(&[("a", 1)]).build(); //! //! struct IsNumeric(bool); //! -//! impl<'kvs> Visitor<'kvs> for IsNumeric { +//! impl<'kvs> VisitValue<'kvs> for IsNumeric { //! fn visit_any(&mut self, _value: kv::Value) -> Result<(), kv::Error> { //! self.0 = false; //! Ok(()) @@ -230,12 +230,9 @@ mod error; mod key; pub mod source; - pub mod value; pub use self::error::Error; pub use self::key::{Key, ToKey}; -pub use self::source::{Source, Visitor}; - -#[doc(inline)] -pub use self::value::{ToValue, Value}; +pub use self::source::{Source, VisitSource}; +pub use self::value::{ToValue, Value, VisitValue}; diff --git a/src/kv/source.rs b/src/kv/source.rs index 87d955417..df4fe1bd8 100644 --- a/src/kv/source.rs +++ b/src/kv/source.rs @@ -9,7 +9,7 @@ use std::fmt; /// A source of key-values. /// /// The source may be a single pair, a set of pairs, or a filter over a set of pairs. -/// Use the [`Visitor`](trait.Visitor.html) trait to inspect the structured data +/// Use the [`VisitSource`](trait.VisitSource.html) trait to inspect the structured data /// in a source. /// /// A source is like an iterator over its key-values, except with a push-based API @@ -21,13 +21,13 @@ use std::fmt; /// /// ``` /// # fn main() -> Result<(), log::kv::Error> { -/// use log::kv::{self, Source, Key, Value, source::Visitor}; +/// use log::kv::{self, Source, Key, Value, source::VisitSource}; /// -/// // A `Visitor` that prints all key-values -/// // Visitors are fed the key-value pairs of each key-values +/// // A `VisitSource` that prints all key-values +/// // VisitSources are fed the key-value pairs of each key-values /// struct Printer; /// -/// impl<'kvs> Visitor<'kvs> for Printer { +/// impl<'kvs> VisitSource<'kvs> for Printer { /// fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), kv::Error> { /// println!("{key}: {value}"); /// @@ -43,7 +43,7 @@ use std::fmt; /// ("c", 3), /// ]; /// -/// // Pass an instance of the `Visitor` to a `Source` to visit it +/// // Pass an instance of the `VisitSource` to a `Source` to visit it /// source.visit(&mut Printer)?; /// # Ok(()) /// # } @@ -59,7 +59,7 @@ pub trait Source { /// /// A source should yield the same key-values to a subsequent visitor unless /// that visitor itself fails. - fn visit<'kvs>(&'kvs self, visitor: &mut dyn Visitor<'kvs>) -> Result<(), Error>; + fn visit<'kvs>(&'kvs self, visitor: &mut dyn VisitSource<'kvs>) -> Result<(), Error>; /// Get the value for a given key. /// @@ -95,7 +95,7 @@ fn get_default<'v>(source: &'v (impl Source + ?Sized), key: Key) -> Option>, } - impl<'k, 'kvs> Visitor<'kvs> for Get<'k, 'kvs> { + impl<'k, 'kvs> VisitSource<'kvs> for Get<'k, 'kvs> { fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> { if self.key == key { self.found = Some(value); @@ -115,7 +115,7 @@ fn get_default<'v>(source: &'v (impl Source + ?Sized), key: Key) -> Option usize { struct Count(usize); - impl<'kvs> Visitor<'kvs> for Count { + impl<'kvs> VisitSource<'kvs> for Count { fn visit_pair(&mut self, _: Key<'kvs>, _: Value<'kvs>) -> Result<(), Error> { self.0 += 1; @@ -132,7 +132,7 @@ impl<'a, T> Source for &'a T where T: Source + ?Sized, { - fn visit<'kvs>(&'kvs self, visitor: &mut dyn Visitor<'kvs>) -> Result<(), Error> { + fn visit<'kvs>(&'kvs self, visitor: &mut dyn VisitSource<'kvs>) -> Result<(), Error> { Source::visit(&**self, visitor) } @@ -150,7 +150,7 @@ where K: ToKey, V: ToValue, { - fn visit<'kvs>(&'kvs self, visitor: &mut dyn Visitor<'kvs>) -> Result<(), Error> { + fn visit<'kvs>(&'kvs self, visitor: &mut dyn VisitSource<'kvs>) -> Result<(), Error> { visitor.visit_pair(self.0.to_key(), self.1.to_value()) } @@ -171,7 +171,7 @@ impl Source for [S] where S: Source, { - fn visit<'kvs>(&'kvs self, visitor: &mut dyn Visitor<'kvs>) -> Result<(), Error> { + fn visit<'kvs>(&'kvs self, visitor: &mut dyn VisitSource<'kvs>) -> Result<(), Error> { for source in self { source.visit(visitor)?; } @@ -198,7 +198,7 @@ impl Source for [S; N] where S: Source, { - fn visit<'kvs>(&'kvs self, visitor: &mut dyn Visitor<'kvs>) -> Result<(), Error> { + fn visit<'kvs>(&'kvs self, visitor: &mut dyn VisitSource<'kvs>) -> Result<(), Error> { Source::visit(self as &[_], visitor) } @@ -215,7 +215,7 @@ impl Source for Option where S: Source, { - fn visit<'kvs>(&'kvs self, visitor: &mut dyn Visitor<'kvs>) -> Result<(), Error> { + fn visit<'kvs>(&'kvs self, visitor: &mut dyn VisitSource<'kvs>) -> Result<(), Error> { if let Some(source) = self { source.visit(visitor)?; } @@ -233,42 +233,42 @@ where } /// A visitor for the key-value pairs in a [`Source`](trait.Source.html). -pub trait Visitor<'kvs> { +pub trait VisitSource<'kvs> { /// Visit a key-value pair. fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error>; } -impl<'a, 'kvs, T> Visitor<'kvs> for &'a mut T +impl<'a, 'kvs, T> VisitSource<'kvs> for &'a mut T where - T: Visitor<'kvs> + ?Sized, + T: VisitSource<'kvs> + ?Sized, { fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> { (**self).visit_pair(key, value) } } -impl<'a, 'b: 'a, 'kvs> Visitor<'kvs> for fmt::DebugMap<'a, 'b> { +impl<'a, 'b: 'a, 'kvs> VisitSource<'kvs> for fmt::DebugMap<'a, 'b> { fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> { self.entry(&key, &value); Ok(()) } } -impl<'a, 'b: 'a, 'kvs> Visitor<'kvs> for fmt::DebugList<'a, 'b> { +impl<'a, 'b: 'a, 'kvs> VisitSource<'kvs> for fmt::DebugList<'a, 'b> { fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> { self.entry(&(key, value)); Ok(()) } } -impl<'a, 'b: 'a, 'kvs> Visitor<'kvs> for fmt::DebugSet<'a, 'b> { +impl<'a, 'b: 'a, 'kvs> VisitSource<'kvs> for fmt::DebugSet<'a, 'b> { fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> { self.entry(&(key, value)); Ok(()) } } -impl<'a, 'b: 'a, 'kvs> Visitor<'kvs> for fmt::DebugTuple<'a, 'b> { +impl<'a, 'b: 'a, 'kvs> VisitSource<'kvs> for fmt::DebugTuple<'a, 'b> { fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> { self.field(&key); self.field(&value); @@ -289,7 +289,7 @@ mod std_support { where S: Source + ?Sized, { - fn visit<'kvs>(&'kvs self, visitor: &mut dyn Visitor<'kvs>) -> Result<(), Error> { + fn visit<'kvs>(&'kvs self, visitor: &mut dyn VisitSource<'kvs>) -> Result<(), Error> { Source::visit(&**self, visitor) } @@ -306,7 +306,7 @@ mod std_support { where S: Source + ?Sized, { - fn visit<'kvs>(&'kvs self, visitor: &mut dyn Visitor<'kvs>) -> Result<(), Error> { + fn visit<'kvs>(&'kvs self, visitor: &mut dyn VisitSource<'kvs>) -> Result<(), Error> { Source::visit(&**self, visitor) } @@ -323,7 +323,7 @@ mod std_support { where S: Source + ?Sized, { - fn visit<'kvs>(&'kvs self, visitor: &mut dyn Visitor<'kvs>) -> Result<(), Error> { + fn visit<'kvs>(&'kvs self, visitor: &mut dyn VisitSource<'kvs>) -> Result<(), Error> { Source::visit(&**self, visitor) } @@ -340,7 +340,7 @@ mod std_support { where S: Source, { - fn visit<'kvs>(&'kvs self, visitor: &mut dyn Visitor<'kvs>) -> Result<(), Error> { + fn visit<'kvs>(&'kvs self, visitor: &mut dyn VisitSource<'kvs>) -> Result<(), Error> { Source::visit(&**self, visitor) } @@ -353,9 +353,9 @@ mod std_support { } } - impl<'kvs, V> Visitor<'kvs> for Box + impl<'kvs, V> VisitSource<'kvs> for Box where - V: Visitor<'kvs> + ?Sized, + V: VisitSource<'kvs> + ?Sized, { fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> { (**self).visit_pair(key, value) @@ -368,7 +368,7 @@ mod std_support { V: ToValue, S: BuildHasher, { - fn visit<'kvs>(&'kvs self, visitor: &mut dyn Visitor<'kvs>) -> Result<(), Error> { + fn visit<'kvs>(&'kvs self, visitor: &mut dyn VisitSource<'kvs>) -> Result<(), Error> { for (key, value) in self { visitor.visit_pair(key.to_key(), value.to_value())?; } @@ -389,7 +389,7 @@ mod std_support { K: ToKey + Borrow + Ord, V: ToValue, { - fn visit<'kvs>(&'kvs self, visitor: &mut dyn Visitor<'kvs>) -> Result<(), Error> { + fn visit<'kvs>(&'kvs self, visitor: &mut dyn VisitSource<'kvs>) -> Result<(), Error> { for (key, value) in self { visitor.visit_pair(key.to_key(), value.to_value())?; } @@ -472,7 +472,7 @@ mod tests { #[test] fn visitor_is_object_safe() { - fn _check(_: &dyn Visitor) {} + fn _check(_: &dyn VisitSource) {} } #[test] @@ -483,7 +483,7 @@ mod tests { } impl Source for OnePair { - fn visit<'kvs>(&'kvs self, visitor: &mut dyn Visitor<'kvs>) -> Result<(), Error> { + fn visit<'kvs>(&'kvs self, visitor: &mut dyn VisitSource<'kvs>) -> Result<(), Error> { visitor.visit_pair(self.key.to_key(), self.value.to_value()) } } diff --git a/src/kv/value.rs b/src/kv/value.rs index 971bf6bbf..a4dd8f618 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -102,7 +102,7 @@ impl<'v> ToValue for Value<'v> { /// /// For basic types the [`Value::visit`] method can be used to extract the /// underlying typed value. However this is limited in the amount of types -/// supported (see the [`Visitor`] trait methods). +/// supported (see the [`VisitValue`] trait methods). /// /// For more complex types one of the following traits can be used: /// * `sval::Value`, requires the `kv_unstable_sval` feature. @@ -213,7 +213,7 @@ impl<'v> Value<'v> { /// /// When the `kv_unstable_serde` or `kv_unstable_sval` features are enabled, you can also /// serialize a value using its `Serialize` or `Value` implementation. - pub fn visit(&self, visitor: impl Visitor<'v>) -> Result<(), Error> { + pub fn visit(&self, visitor: impl VisitValue<'v>) -> Result<(), Error> { inner::visit(&self.inner, visitor) } } @@ -436,20 +436,20 @@ mod std_support { /// A visitor for a [`Value`]. /// -/// Also see [`Value`'s documentation on seralization]. Visitors are a simple alternative -/// to a more fully-featured serialization framework like `serde` or `sval`. A visitor -/// can differentiate primitive types through methods like [`Visitor::visit_bool`] and -/// [`Visitor::visit_str`], but more complex types like maps and sequences -/// will fallthrough to [`Visitor::visit_any`]. +/// Also see [`Value`'s documentation on seralization]. Value visitors are a simple alternative +/// to a more fully-featured serialization framework like `serde` or `sval`. A value visitor +/// can differentiate primitive types through methods like [`VisitValue::visit_bool`] and +/// [`VisitValue::visit_str`], but more complex types like maps and sequences +/// will fallthrough to [`VisitValue::visit_any`]. /// /// If you're trying to serialize a value to a format like JSON, you can use either `serde` /// or `sval` directly with the value. You don't need a visitor. /// /// [`Value`'s documentation on seralization]: Value#serialization -pub trait Visitor<'v> { +pub trait VisitValue<'v> { /// Visit a `Value`. /// - /// This is the only required method on `Visitor` and acts as a fallback for any + /// This is the only required method on `VisitValue` and acts as a fallback for any /// more specific methods that aren't overridden. /// The `Value` may be formatted using its `fmt::Debug` or `fmt::Display` implementation, /// or serialized using its `sval::Value` or `serde::Serialize` implementation. @@ -522,9 +522,9 @@ pub trait Visitor<'v> { } } -impl<'a, 'v, T: ?Sized> Visitor<'v> for &'a mut T +impl<'a, 'v, T: ?Sized> VisitValue<'v> for &'a mut T where - T: Visitor<'v>, + T: VisitValue<'v>, { fn visit_any(&mut self, value: Value) -> Result<(), Error> { (**self).visit_any(value) @@ -607,12 +607,12 @@ pub(in crate::kv) mod inner { inner.to_test_token() } - pub fn visit<'v>(inner: &Inner<'v>, visitor: impl Visitor<'v>) -> Result<(), crate::kv::Error> { - struct InnerVisitor(V); + pub fn visit<'v>(inner: &Inner<'v>, visitor: impl VisitValue<'v>) -> Result<(), crate::kv::Error> { + struct InnerVisitValue(V); - impl<'v, V> value_bag::visit::Visit<'v> for InnerVisitor + impl<'v, V> value_bag::visit::Visit<'v> for InnerVisitValue where - V: Visitor<'v>, + V: VisitValue<'v>, { fn visit_any(&mut self, value: value_bag::ValueBag) -> Result<(), Error> { self.0 @@ -700,7 +700,7 @@ pub(in crate::kv) mod inner { } inner - .visit(&mut InnerVisitor(visitor)) + .visit(&mut InnerVisitValue(visitor)) .map_err(crate::kv::Error::from_value) } } @@ -717,7 +717,7 @@ pub(in crate::kv) mod inner { the same `value_bag`-based conversion must also. Of particular note here are floats to ints; they're based on the standard library's `TryInto` conversions, which need to be convert to `i32` or `u32`, and then to `f64`. - 2. Visitors should always be called in the same way. If a particular type of value calls `visit_i64`, + 2. VisitValues should always be called in the same way. If a particular type of value calls `visit_i64`, then the same `value_bag`-based visitor must also. */ use super::*; @@ -1018,7 +1018,7 @@ pub(in crate::kv) mod inner { pub fn visit<'v>( inner: &Inner<'v>, - mut visitor: impl Visitor<'v>, + mut visitor: impl VisitValue<'v>, ) -> Result<(), crate::kv::Error> { match inner { Inner::None => visitor.visit_null(), @@ -1216,7 +1216,7 @@ pub(crate) mod tests { fn test_visit_integer() { struct Extract(Option); - impl<'v> Visitor<'v> for Extract { + impl<'v> VisitValue<'v> for Extract { fn visit_any(&mut self, value: Value) -> Result<(), Error> { unimplemented!("unexpected value: {value:?}") } @@ -1238,7 +1238,7 @@ pub(crate) mod tests { fn test_visit_borrowed_str() { struct Extract<'v>(Option<&'v str>); - impl<'v> Visitor<'v> for Extract<'v> { + impl<'v> VisitValue<'v> for Extract<'v> { fn visit_any(&mut self, value: Value) -> Result<(), Error> { unimplemented!("unexpected value: {value:?}") } diff --git a/src/lib.rs b/src/lib.rs index e0577ce97..8abbfcb2e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1760,13 +1760,13 @@ mod tests { #[cfg(feature = "kv_unstable")] fn test_record_key_values_builder() { use super::Record; - use crate::kv::{self, Visitor}; + use crate::kv::{self, VisitSource}; - struct TestVisitor { + struct TestVisitSource { seen_pairs: usize, } - impl<'kvs> Visitor<'kvs> for TestVisitor { + impl<'kvs> VisitSource<'kvs> for TestVisitSource { fn visit_pair( &mut self, _: kv::Key<'kvs>, @@ -1780,7 +1780,7 @@ mod tests { let kvs: &[(&str, i32)] = &[("a", 1), ("b", 2)]; let record_test = Record::builder().key_values(&kvs).build(); - let mut visitor = TestVisitor { seen_pairs: 0 }; + let mut visitor = TestVisitSource { seen_pairs: 0 }; record_test.key_values().visit(&mut visitor).unwrap(); From f6b89c0377c04b3ba4e5c090a9ca603048ddf64c Mon Sep 17 00:00:00 2001 From: KodrAus Date: Fri, 16 Feb 2024 15:08:13 +1000 Subject: [PATCH 179/280] update and clarify docs, make internal kv modules private --- src/__private_api.rs | 6 +++++- src/kv/mod.rs | 36 +++++++++++++++++++++++------------- src/kv/source.rs | 3 +-- 3 files changed, 29 insertions(+), 16 deletions(-) diff --git a/src/__private_api.rs b/src/__private_api.rs index 8ea869958..ce08a5e98 100644 --- a/src/__private_api.rs +++ b/src/__private_api.rs @@ -93,7 +93,11 @@ mod kv_support { pub type Value<'a> = kv::Value<'a>; - pub fn capture_to_value<'a, V: kv::value::ToValue + ?Sized>(v: &'a &'a V) -> Value<'a> { + // NOTE: Many functions here accept a double reference &&V + // This is so V itself can be ?Sized, while still letting us + // erase it to some dyn Trait (because &T is sized) + + pub fn capture_to_value<'a, V: kv::ToValue + ?Sized>(v: &'a &'a V) -> Value<'a> { v.to_value() } diff --git a/src/kv/mod.rs b/src/kv/mod.rs index 6d38dbe50..a0ef2b9c3 100644 --- a/src/kv/mod.rs +++ b/src/kv/mod.rs @@ -15,9 +15,8 @@ //! # Structured logging in `log` //! //! Structured logging enhances traditional text-based log records with user-defined -//! attributes. Structured logs can be analyzed using a variety of tranditional -//! data processing techniques, without needing to find and parse attributes from -//! unstructured text first. +//! attributes. Structured logs can be analyzed using a variety of data processing +//! techniques, without needing to find and parse attributes from unstructured text first. //! //! In `log`, user-defined attributes are part of a [`Source`] on the log record. //! Each attribute is a key-value; a pair of [`Key`] and [`Value`]. Keys are strings @@ -49,13 +48,13 @@ //! - `:debug` will capture the value using `Debug`. //! - `:%` will capture the value using `Display`. //! - `:display` will capture the value using `Display`. -//! - `:error` will capture the value using `std::error::Error` (requires the `kv_unstable_error` feature). +//! - `:error` will capture the value using `std::error::Error` (requires the `kv_unstable_std` feature). //! - `:sval` will capture the value using `sval::Value` (requires the `kv_unstable_sval` feature). //! - `:serde` will capture the value using `serde::Serialize` (requires the `kv_unstable_serde` feature). //! //! ## Working with key-values on log records //! -//! Use the [`LogRecord::key_values`] method to access key-values. +//! Use the [`Record::key_values`](../struct.Record.html#method.key_values) method to access key-values. //! //! Individual values can be pulled from the source by their key: //! @@ -75,7 +74,6 @@ //! //! ``` //! # fn main() -> Result<(), log::kv::Error> { -//! # let record = log::Record::builder().key_values(&[("a", 1), ("b", 2), ("c", 3)]).build(); //! use std::collections::BTreeMap; //! //! use log::kv::{self, Source, Key, Value, VisitSource}; @@ -92,6 +90,7 @@ //! //! let mut visitor = Collect(BTreeMap::new()); //! +//! # let record = log::Record::builder().key_values(&[("a", 1), ("b", 2), ("c", 3)]).build(); //! // info!(a = 1, b = 2, c = 3; "Something of interest"); //! //! record.key_values().visit(&mut visitor)?; @@ -189,11 +188,16 @@ //! # #[cfg(feature = "serde")] //! # { //! # use log::kv::Key; -//! # #[derive(serde::Serialize)] struct Data { a: i32, b: bool, c: &'static str } +//! #[derive(serde::Serialize)] +//! struct Data { +//! a: i32, b: bool, +//! c: &'static str, +//! } +//! //! let data = Data { a: 1, b: true, c: "Some data" }; +//! //! # let source = [("a", log::kv::Value::from_serde(&data))]; //! # let record = log::Record::builder().key_values(&source).build(); -//! //! // info!(a = data; "Something of interest"); //! //! let a = record.key_values().get(Key::from("a")).unwrap(); @@ -208,18 +212,24 @@ //! If you're in a no-std environment, you can use `sval`. In other cases, you can use `serde`. //! Log producers and log consumers don't need to agree on the serialization framework. //! A value can be captured using its `serde::Serialize` implementation and still be serialized -//! through `sval` without losing any structure. +//! through `sval` without losing any structure or data. //! //! Values can also always be formatted using the standard `Debug` and `Display` //! traits: //! //! ``` //! # use log::kv::Key; -//! # #[derive(Debug)] struct Data { a: i32, b: bool, c: &'static str } +//! # #[derive(Debug)] +//! struct Data { +//! a: i32, +//! b: bool, +//! c: &'static str, +//! } +//! //! let data = Data { a: 1, b: true, c: "Some data" }; +//! //! # let source = [("a", log::kv::Value::from_debug(&data))]; //! # let record = log::Record::builder().key_values(&source).build(); -//! //! // info!(a = data; "Something of interest"); //! //! let a = record.key_values().get(Key::from("a")).unwrap(); @@ -229,8 +239,8 @@ mod error; mod key; -pub mod source; -pub mod value; +mod source; +mod value; pub use self::error::Error; pub use self::key::{Key, ToKey}; diff --git a/src/kv/source.rs b/src/kv/source.rs index df4fe1bd8..d3ba3f2fa 100644 --- a/src/kv/source.rs +++ b/src/kv/source.rs @@ -81,8 +81,7 @@ pub trait Source { /// A source that knows the number of key-values upfront may provide a more /// efficient implementation. /// - /// A subsequent call to `visit` should yield the same number of key-values - /// to the visitor, unless that visitor fails part way through. + /// A subsequent call to `visit` should yield the same number of key-values. fn count(&self) -> usize { count_default(self) } From 6d9e98aa03650e7770bd4bb67391e765d36a77fd Mon Sep 17 00:00:00 2001 From: KodrAus Date: Fri, 16 Feb 2024 15:09:18 +1000 Subject: [PATCH 180/280] run fmt --- src/kv/mod.rs | 10 +++++----- src/kv/value.rs | 5 ++++- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/kv/mod.rs b/src/kv/mod.rs index a0ef2b9c3..f7f91f4b9 100644 --- a/src/kv/mod.rs +++ b/src/kv/mod.rs @@ -15,7 +15,7 @@ //! # Structured logging in `log` //! //! Structured logging enhances traditional text-based log records with user-defined -//! attributes. Structured logs can be analyzed using a variety of data processing +//! attributes. Structured logs can be analyzed using a variety of data processing //! techniques, without needing to find and parse attributes from unstructured text first. //! //! In `log`, user-defined attributes are part of a [`Source`] on the log record. @@ -32,18 +32,18 @@ //! # use log::info; //! info!(a = 1; "Something of interest"); //! ``` -//! +//! //! Values are capturing using the [`ToValue`] trait by default. To capture a value //! using a different trait implementation, use a modifier after its key. Here's how //! the same example can capture `a` using its `Debug` implementation instead: -//! +//! //! ``` //! # use log::info; //! info!(a:? = 1; "Something of interest"); //! ``` -//! +//! //! The following capturing modifiers are supported: -//! +//! //! - `:?` will capture the value using `Debug`. //! - `:debug` will capture the value using `Debug`. //! - `:%` will capture the value using `Display`. diff --git a/src/kv/value.rs b/src/kv/value.rs index a4dd8f618..646a22d9d 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -607,7 +607,10 @@ pub(in crate::kv) mod inner { inner.to_test_token() } - pub fn visit<'v>(inner: &Inner<'v>, visitor: impl VisitValue<'v>) -> Result<(), crate::kv::Error> { + pub fn visit<'v>( + inner: &Inner<'v>, + visitor: impl VisitValue<'v>, + ) -> Result<(), crate::kv::Error> { struct InnerVisitValue(V); impl<'v, V> value_bag::visit::Visit<'v> for InnerVisitValue From 44b8e990596b3d0cd21f669e62d9cb0790ea827e Mon Sep 17 00:00:00 2001 From: KodrAus Date: Fri, 16 Feb 2024 15:14:35 +1000 Subject: [PATCH 181/280] fix up some warnings --- src/__private_api.rs | 2 -- src/kv/mod.rs | 1 + src/kv/source.rs | 2 +- src/kv/value.rs | 5 ----- 4 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/__private_api.rs b/src/__private_api.rs index ce08a5e98..5686142c8 100644 --- a/src/__private_api.rs +++ b/src/__private_api.rs @@ -87,8 +87,6 @@ pub fn enabled(level: Level, target: &str) -> bool { #[cfg(feature = "kv_unstable")] mod kv_support { - use super::*; - use crate::kv; pub type Value<'a> = kv::Value<'a>; diff --git a/src/kv/mod.rs b/src/kv/mod.rs index f7f91f4b9..84d392cd4 100644 --- a/src/kv/mod.rs +++ b/src/kv/mod.rs @@ -66,6 +66,7 @@ //! // info!(a = 1; "Something of interest"); //! //! let a: Value = record.key_values().get(Key::from("a")).unwrap(); +//! assert_eq!(1, a.to_i64().unwrap()); //! # Ok(()) //! # } //! ``` diff --git a/src/kv/source.rs b/src/kv/source.rs index d3ba3f2fa..33d5a1a73 100644 --- a/src/kv/source.rs +++ b/src/kv/source.rs @@ -21,7 +21,7 @@ use std::fmt; /// /// ``` /// # fn main() -> Result<(), log::kv::Error> { -/// use log::kv::{self, Source, Key, Value, source::VisitSource}; +/// use log::kv::{self, Source, Key, Value, VisitSource}; /// /// // A `VisitSource` that prints all key-values /// // VisitSources are fed the key-value pairs of each key-values diff --git a/src/kv/value.rs b/src/kv/value.rs index 646a22d9d..2e0d423e6 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -602,11 +602,6 @@ pub(in crate::kv) mod inner { #[cfg(test)] pub use value_bag::test::TestToken as Token; - #[cfg(test)] - pub fn to_test_token<'v>(inner: &Inner<'v>) -> Token { - inner.to_test_token() - } - pub fn visit<'v>( inner: &Inner<'v>, visitor: impl VisitValue<'v>, From a6c40954b1767a53cb0a80a98d00adfde889dec9 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Fri, 16 Feb 2024 15:16:54 +1000 Subject: [PATCH 182/280] add a few more notes to the source --- src/macros.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/macros.rs b/src/macros.rs index 3e8ba4e73..74de7f892 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -29,7 +29,7 @@ /// ``` #[macro_export] macro_rules! log { - // log!(target: "my_target", Level::Info, key1 = 42, key2 = true; "a {} event", "log"); + // log!(target: "my_target", Level::Info, key1:? = 42, key2 = true; "a {} event", "log"); (target: $target:expr, $lvl:expr, $($key:tt $(:$capture:tt)? = $value:expr),+; $($arg:tt)+) => ({ let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { @@ -226,6 +226,9 @@ macro_rules! log_enabled { }; } +// These macros use a pattern of #[cfg]s to produce nicer error +// messages when log features aren't available + #[doc(hidden)] #[macro_export] #[cfg(feature = "kv_unstable")] From 52460f9928541f9d014493d846a5fd0e90f9ba8a Mon Sep 17 00:00:00 2001 From: KodrAus Date: Fri, 16 Feb 2024 15:40:52 +1000 Subject: [PATCH 183/280] stabilize the kv features --- .github/workflows/main.yml | 36 ++++++++++++++++++---------------- Cargo.toml | 18 ++++++++++------- README.md | 2 +- benches/value.rs | 2 +- src/__private_api.rs | 20 +++++++++---------- src/kv/error.rs | 4 ++-- src/kv/key.rs | 4 ++-- src/kv/mod.rs | 16 ++++++--------- src/kv/value.rs | 40 +++++++++++++++++++------------------- src/lib.rs | 26 ++++++++++++------------- src/macros.rs | 40 ++++++++++++++++++++------------------ tests/Cargo.toml | 8 ++++---- tests/macros.rs | 30 ++++++++++++++-------------- 13 files changed, 124 insertions(+), 122 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 3fc335e73..3c263a434 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -44,10 +44,10 @@ jobs: - run: cargo test --verbose --all-features - run: cargo test --verbose --features serde - run: cargo test --verbose --features std - - run: cargo test --verbose --features kv_unstable - - run: cargo test --verbose --features kv_unstable_sval - - run: cargo test --verbose --features kv_unstable_serde - - run: cargo test --verbose --features "kv_unstable kv_unstable_std kv_unstable_sval kv_unstable_serde" + - run: cargo test --verbose --features kv + - run: cargo test --verbose --features kv_sval + - run: cargo test --verbose --features kv_serde + - run: cargo test --verbose --features "kv kv_std kv_sval kv_serde" - run: cargo run --verbose --manifest-path test_max_level_features/Cargo.toml - run: cargo run --verbose --manifest-path test_max_level_features/Cargo.toml --release @@ -103,12 +103,12 @@ jobs: run: | rustup update nightly --no-self-update rustup default nightly - - run: cargo build --verbose -Z avoid-dev-deps --features kv_unstable - - run: cargo build --verbose -Z avoid-dev-deps --features "kv_unstable std" - - run: cargo build --verbose -Z avoid-dev-deps --features "kv_unstable kv_unstable_sval" - - run: cargo build --verbose -Z avoid-dev-deps --features "kv_unstable kv_unstable_serde" - - run: cargo build --verbose -Z avoid-dev-deps --features "kv_unstable kv_unstable_std" - - run: cargo build --verbose -Z avoid-dev-deps --features "kv_unstable kv_unstable_sval kv_unstable_serde" + - run: cargo build --verbose -Z avoid-dev-deps --features kv + - run: cargo build --verbose -Z avoid-dev-deps --features "kv std" + - run: cargo build --verbose -Z avoid-dev-deps --features "kv kv_sval" + - run: cargo build --verbose -Z avoid-dev-deps --features "kv kv_serde" + - run: cargo build --verbose -Z avoid-dev-deps --features "kv kv_std" + - run: cargo build --verbose -Z avoid-dev-deps --features "kv kv_sval kv_serde" minimalv: name: Minimal versions @@ -119,12 +119,12 @@ jobs: run: | rustup update nightly --no-self-update rustup default nightly - - run: cargo build --verbose -Z minimal-versions --features kv_unstable - - run: cargo build --verbose -Z minimal-versions --features "kv_unstable std" - - run: cargo build --verbose -Z minimal-versions --features "kv_unstable kv_unstable_sval" - - run: cargo build --verbose -Z minimal-versions --features "kv_unstable kv_unstable_serde" - - run: cargo build --verbose -Z minimal-versions --features "kv_unstable kv_unstable_std" - - run: cargo build --verbose -Z minimal-versions --features "kv_unstable kv_unstable_sval kv_unstable_serde" + - run: cargo build --verbose -Z minimal-versions --features kv + - run: cargo build --verbose -Z minimal-versions --features "kv std" + - run: cargo build --verbose -Z minimal-versions --features "kv kv_sval" + - run: cargo build --verbose -Z minimal-versions --features "kv kv_serde" + - run: cargo build --verbose -Z minimal-versions --features "kv kv_std" + - run: cargo build --verbose -Z minimal-versions --features "kv kv_sval kv_serde" msrv: name: MSRV @@ -135,7 +135,9 @@ jobs: run: | rustup update 1.60.0 --no-self-update rustup default 1.60.0 - - run: cargo test --verbose --manifest-path tests/Cargo.toml + - run: | + cargo test --verbose --manifest-path tests/Cargo.toml + cargo test --verbose --manifest-path tests/Cargo.toml --features kv embedded: name: Embedded diff --git a/Cargo.toml b/Cargo.toml index c30944c56..5992d0a9e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ rust-version = "1.60.0" edition = "2021" [package.metadata.docs.rs] -features = ["std", "serde", "kv_unstable_std", "kv_unstable_sval", "kv_unstable_serde"] +features = ["std", "serde", "kv_std", "kv_sval", "kv_serde"] [[test]] name = "filters" @@ -46,12 +46,16 @@ release_max_level_trace = [] std = [] -# requires the latest stable -# this will have a tighter MSRV before stabilization -kv_unstable = [] -kv_unstable_sval = ["kv_unstable", "value-bag/sval", "sval", "sval_ref"] -kv_unstable_std = ["std", "kv_unstable", "value-bag/error"] -kv_unstable_serde = ["kv_unstable_std", "value-bag/serde", "serde"] +kv = [] +kv_sval = ["kv", "value-bag/sval", "sval", "sval_ref"] +kv_std = ["std", "kv", "value-bag/error"] +kv_serde = ["kv_std", "value-bag/serde", "serde"] + +# Legacy: use `kv_*` instead +kv_unstable = ["kv"] +kv_unstable_sval = ["kv_sval"] +kv_unstable_std = ["kv_std"] +kv_unstable_serde = ["kv_serde"] [dependencies] serde = { version = "1.0", optional = true, default-features = false } diff --git a/README.md b/README.md index 7b188719f..01fd30875 100644 --- a/README.md +++ b/README.md @@ -100,7 +100,7 @@ The executable itself may use the `log` crate to log as well. ## Structured logging -If you enable the `kv_unstable` feature, you can associate structured data with your log records: +If you enable the `kv` feature, you can associate structured data with your log records: ```rust use log::{info, trace, warn}; diff --git a/benches/value.rs b/benches/value.rs index e43be50f7..3d0f18bfe 100644 --- a/benches/value.rs +++ b/benches/value.rs @@ -1,4 +1,4 @@ -#![cfg(feature = "kv_unstable")] +#![cfg(feature = "kv")] #![feature(test)] use log::kv::Value; diff --git a/src/__private_api.rs b/src/__private_api.rs index 5686142c8..fd0a5a762 100644 --- a/src/__private_api.rs +++ b/src/__private_api.rs @@ -5,7 +5,7 @@ use crate::{Level, Metadata, Record}; use std::fmt::Arguments; pub use std::{file, format_args, line, module_path, stringify}; -#[cfg(not(feature = "kv_unstable"))] +#[cfg(not(feature = "kv"))] pub type Value<'a> = &'a str; mod sealed { @@ -40,11 +40,9 @@ fn log_impl( line: u32, kvs: Option<&[(&str, Value)]>, ) { - #[cfg(not(feature = "kv_unstable"))] + #[cfg(not(feature = "kv"))] if kvs.is_some() { - panic!( - "key-value support is experimental and must be enabled using the `kv_unstable` feature" - ) + panic!("key-value support is experimental and must be enabled using the `kv` feature") } let mut builder = Record::builder(); @@ -57,7 +55,7 @@ fn log_impl( .file_static(Some(file)) .line(Some(line)); - #[cfg(feature = "kv_unstable")] + #[cfg(feature = "kv")] builder.key_values(&kvs); crate::logger().log(&builder.build()); @@ -85,7 +83,7 @@ pub fn enabled(level: Level, target: &str) -> bool { crate::logger().enabled(&Metadata::builder().level(level).target(target).build()) } -#[cfg(feature = "kv_unstable")] +#[cfg(feature = "kv")] mod kv_support { use crate::kv; @@ -107,21 +105,21 @@ mod kv_support { Value::from_display(v) } - #[cfg(feature = "kv_unstable_std")] + #[cfg(feature = "kv_std")] pub fn capture_error<'a>(v: &'a (dyn std::error::Error + 'static)) -> Value<'a> { Value::from_dyn_error(v) } - #[cfg(feature = "kv_unstable_sval")] + #[cfg(feature = "kv_sval")] pub fn capture_sval<'a, V: sval::Value + ?Sized>(v: &'a &'a V) -> Value<'a> { Value::from_sval(v) } - #[cfg(feature = "kv_unstable_serde")] + #[cfg(feature = "kv_serde")] pub fn capture_serde<'a, V: serde::Serialize + ?Sized>(v: &'a &'a V) -> Value<'a> { Value::from_serde(v) } } -#[cfg(feature = "kv_unstable")] +#[cfg(feature = "kv")] pub use self::kv_support::*; diff --git a/src/kv/error.rs b/src/kv/error.rs index d654be780..7efa5af36 100644 --- a/src/kv/error.rs +++ b/src/kv/error.rs @@ -37,9 +37,9 @@ impl Error { pub(super) fn into_value(self) -> crate::kv::value::inner::Error { match self.inner { Inner::Value(err) => err, - #[cfg(feature = "kv_unstable_std")] + #[cfg(feature = "kv_std")] _ => crate::kv::value::inner::Error::boxed(self), - #[cfg(not(feature = "kv_unstable_std"))] + #[cfg(not(feature = "kv_std"))] _ => crate::kv::value::inner::Error::msg("error inspecting a value"), } } diff --git a/src/kv/key.rs b/src/kv/key.rs index fb58008c8..9a64b956f 100644 --- a/src/kv/key.rs +++ b/src/kv/key.rs @@ -93,7 +93,7 @@ mod std_support { } } -#[cfg(feature = "kv_unstable_sval")] +#[cfg(feature = "kv_sval")] mod sval_support { use super::*; @@ -116,7 +116,7 @@ mod sval_support { } } -#[cfg(feature = "kv_unstable_serde")] +#[cfg(feature = "kv_serde")] mod serde_support { use super::*; diff --git a/src/kv/mod.rs b/src/kv/mod.rs index 84d392cd4..44f7b06df 100644 --- a/src/kv/mod.rs +++ b/src/kv/mod.rs @@ -1,15 +1,11 @@ -//! **UNSTABLE:** Structured logging. +//! Structured logging. //! -//! This module is unstable and breaking changes may be made -//! at any time. See [the tracking issue](https://github.com/rust-lang-nursery/log/issues/328) -//! for more details. -//! -//! Add the `kv_unstable` feature to your `Cargo.toml` to enable +//! Add the `kv` feature to your `Cargo.toml` to enable //! this module: //! //! ```toml //! [dependencies.log] -//! features = ["kv_unstable"] +//! features = ["kv"] //! ``` //! //! # Structured logging in `log` @@ -48,9 +44,9 @@ //! - `:debug` will capture the value using `Debug`. //! - `:%` will capture the value using `Display`. //! - `:display` will capture the value using `Display`. -//! - `:error` will capture the value using `std::error::Error` (requires the `kv_unstable_std` feature). -//! - `:sval` will capture the value using `sval::Value` (requires the `kv_unstable_sval` feature). -//! - `:serde` will capture the value using `serde::Serialize` (requires the `kv_unstable_serde` feature). +//! - `:error` will capture the value using `std::error::Error` (requires the `kv_std` feature). +//! - `:sval` will capture the value using `sval::Value` (requires the `kv_sval` feature). +//! - `:serde` will capture the value using `serde::Serialize` (requires the `kv_serde` feature). //! //! ## Working with key-values on log records //! diff --git a/src/kv/value.rs b/src/kv/value.rs index 2e0d423e6..6bfff4e4e 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -105,8 +105,8 @@ impl<'v> ToValue for Value<'v> { /// supported (see the [`VisitValue`] trait methods). /// /// For more complex types one of the following traits can be used: -/// * `sval::Value`, requires the `kv_unstable_sval` feature. -/// * `serde::Serialize`, requires the `kv_unstable_serde` feature. +/// * `sval::Value`, requires the `kv_sval` feature. +/// * `serde::Serialize`, requires the `kv_serde` feature. /// /// You don't need a visitor to serialize values through `serde` or `sval`. /// @@ -149,7 +149,7 @@ impl<'v> Value<'v> { } /// Get a value from a type implementing `serde::Serialize`. - #[cfg(feature = "kv_unstable_serde")] + #[cfg(feature = "kv_serde")] pub fn from_serde(value: &'v T) -> Self where T: serde::Serialize, @@ -160,7 +160,7 @@ impl<'v> Value<'v> { } /// Get a value from a type implementing `sval::Value`. - #[cfg(feature = "kv_unstable_sval")] + #[cfg(feature = "kv_sval")] pub fn from_sval(value: &'v T) -> Self where T: sval::Value, @@ -185,7 +185,7 @@ impl<'v> Value<'v> { } /// Get a value from a dynamic error. - #[cfg(feature = "kv_unstable_std")] + #[cfg(feature = "kv_std")] pub fn from_dyn_error(err: &'v (dyn std::error::Error + 'static)) -> Self { Value { inner: inner::Inner::from_dyn_error(err), @@ -211,7 +211,7 @@ impl<'v> Value<'v> { /// Inspect this value using a simple visitor. /// - /// When the `kv_unstable_serde` or `kv_unstable_sval` features are enabled, you can also + /// When the `kv_serde` or `kv_sval` features are enabled, you can also /// serialize a value using its `Serialize` or `Value` implementation. pub fn visit(&self, visitor: impl VisitValue<'v>) -> Result<(), Error> { inner::visit(&self.inner, visitor) @@ -230,7 +230,7 @@ impl<'v> fmt::Display for Value<'v> { } } -#[cfg(feature = "kv_unstable_serde")] +#[cfg(feature = "kv_serde")] impl<'v> serde::Serialize for Value<'v> { fn serialize(&self, s: S) -> Result where @@ -240,14 +240,14 @@ impl<'v> serde::Serialize for Value<'v> { } } -#[cfg(feature = "kv_unstable_sval")] +#[cfg(feature = "kv_sval")] impl<'v> sval::Value for Value<'v> { fn stream<'sval, S: sval::Stream<'sval> + ?Sized>(&'sval self, stream: &mut S) -> sval::Result { sval::Value::stream(&self.inner, stream) } } -#[cfg(feature = "kv_unstable_sval")] +#[cfg(feature = "kv_sval")] impl<'v> sval_ref::ValueRef<'v> for Value<'v> { fn stream_ref + ?Sized>(&self, stream: &mut S) -> sval::Result { sval_ref::ValueRef::stream_ref(&self.inner, stream) @@ -362,7 +362,7 @@ impl_value_to_primitive![ impl<'v> Value<'v> { /// Try convert this value into an error. - #[cfg(feature = "kv_unstable_std")] + #[cfg(feature = "kv_std")] pub fn to_borrowed_error(&self) -> Option<&(dyn std::error::Error + 'static)> { self.inner.to_borrowed_error() } @@ -373,7 +373,7 @@ impl<'v> Value<'v> { } } -#[cfg(feature = "kv_unstable_std")] +#[cfg(feature = "kv_std")] mod std_support { use std::borrow::Cow; use std::rc::Rc; @@ -507,13 +507,13 @@ pub trait VisitValue<'v> { } /// Visit an error. - #[cfg(feature = "kv_unstable_std")] + #[cfg(feature = "kv_std")] fn visit_error(&mut self, err: &(dyn std::error::Error + 'static)) -> Result<(), Error> { self.visit_any(Value::from_dyn_error(err)) } /// Visit an error. - #[cfg(feature = "kv_unstable_std")] + #[cfg(feature = "kv_std")] fn visit_borrowed_error( &mut self, err: &'v (dyn std::error::Error + 'static), @@ -570,12 +570,12 @@ where (**self).visit_char(value) } - #[cfg(feature = "kv_unstable_std")] + #[cfg(feature = "kv_std")] fn visit_error(&mut self, err: &(dyn std::error::Error + 'static)) -> Result<(), Error> { (**self).visit_error(err) } - #[cfg(feature = "kv_unstable_std")] + #[cfg(feature = "kv_std")] fn visit_borrowed_error( &mut self, err: &'v (dyn std::error::Error + 'static), @@ -676,7 +676,7 @@ pub(in crate::kv) mod inner { .map_err(crate::kv::Error::into_value) } - #[cfg(feature = "kv_unstable_std")] + #[cfg(feature = "kv_std")] fn visit_error( &mut self, err: &(dyn std::error::Error + 'static), @@ -686,7 +686,7 @@ pub(in crate::kv) mod inner { .map_err(crate::kv::Error::into_value) } - #[cfg(feature = "kv_unstable_std")] + #[cfg(feature = "kv_std")] fn visit_borrowed_error( &mut self, err: &'v (dyn std::error::Error + 'static), @@ -1158,7 +1158,7 @@ pub(crate) mod tests { for v in str() { assert!(v.to_borrowed_str().is_some()); - #[cfg(feature = "kv_unstable_std")] + #[cfg(feature = "kv_std")] assert!(v.to_cow_str().is_some()); } @@ -1167,13 +1167,13 @@ pub(crate) mod tests { assert!(v.to_borrowed_str().is_some()); - #[cfg(feature = "kv_unstable_std")] + #[cfg(feature = "kv_std")] assert!(v.to_cow_str().is_some()); for v in unsigned().chain(signed()).chain(float()).chain(bool()) { assert!(v.to_borrowed_str().is_none()); - #[cfg(feature = "kv_unstable_std")] + #[cfg(feature = "kv_std")] assert!(v.to_cow_str().is_none()); } } diff --git a/src/lib.rs b/src/lib.rs index 8abbfcb2e..feb14e115 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -88,7 +88,7 @@ //! //! ## Structured logging //! -//! If you enable the `kv_unstable` feature you can associate structured values +//! If you enable the `kv` feature you can associate structured values //! with your log records. If we take the example from before, we can include //! some additional context besides what's in the formatted message: //! @@ -97,7 +97,7 @@ //! # #[derive(Debug, Serialize)] pub struct Yak(String); //! # impl Yak { fn shave(&mut self, _: u32) {} } //! # fn find_a_razor() -> Result { Ok(1) } -//! # #[cfg(feature = "kv_unstable_serde")] +//! # #[cfg(feature = "kv_serde")] //! # fn main() { //! use log::{info, warn}; //! @@ -118,7 +118,7 @@ //! } //! } //! # } -//! # #[cfg(not(feature = "kv_unstable_serde"))] +//! # #[cfg(not(feature = "kv_serde"))] //! # fn main() {} //! ``` //! @@ -355,7 +355,7 @@ use std::{cmp, fmt, mem}; mod macros; mod serde; -#[cfg(feature = "kv_unstable")] +#[cfg(feature = "kv")] pub mod kv; #[cfg(target_has_atomic = "ptr")] @@ -723,7 +723,7 @@ pub struct Record<'a> { module_path: Option>, file: Option>, line: Option, - #[cfg(feature = "kv_unstable")] + #[cfg(feature = "kv")] key_values: KeyValues<'a>, } @@ -731,11 +731,11 @@ pub struct Record<'a> { // `#[derive(Debug)]` on `Record`. It also // provides a useful `Debug` implementation for // the underlying `Source`. -#[cfg(feature = "kv_unstable")] +#[cfg(feature = "kv")] #[derive(Clone)] struct KeyValues<'a>(&'a dyn kv::Source); -#[cfg(feature = "kv_unstable")] +#[cfg(feature = "kv")] impl<'a> fmt::Debug for KeyValues<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let mut visitor = f.debug_map(); @@ -812,14 +812,14 @@ impl<'a> Record<'a> { } /// The structured key-value pairs associated with the message. - #[cfg(feature = "kv_unstable")] + #[cfg(feature = "kv")] #[inline] pub fn key_values(&self) -> &dyn kv::Source { self.key_values.0 } /// Create a new [`RecordBuilder`](struct.RecordBuilder.html) based on this record. - #[cfg(feature = "kv_unstable")] + #[cfg(feature = "kv")] #[inline] pub fn to_builder(&self) -> RecordBuilder { RecordBuilder { @@ -904,7 +904,7 @@ impl<'a> RecordBuilder<'a> { module_path: None, file: None, line: None, - #[cfg(feature = "kv_unstable")] + #[cfg(feature = "kv")] key_values: KeyValues(&None::<(kv::Key, kv::Value)>), }, } @@ -974,7 +974,7 @@ impl<'a> RecordBuilder<'a> { } /// Set [`key_values`](struct.Record.html#method.key_values) - #[cfg(feature = "kv_unstable")] + #[cfg(feature = "kv")] #[inline] pub fn key_values(&mut self, kvs: &'a dyn kv::Source) -> &mut RecordBuilder<'a> { self.record.key_values = KeyValues(kvs); @@ -1757,7 +1757,7 @@ mod tests { } #[test] - #[cfg(feature = "kv_unstable")] + #[cfg(feature = "kv")] fn test_record_key_values_builder() { use super::Record; use crate::kv::{self, VisitSource}; @@ -1788,7 +1788,7 @@ mod tests { } #[test] - #[cfg(feature = "kv_unstable")] + #[cfg(feature = "kv")] fn test_record_key_values_get_coerce() { use super::Record; diff --git a/src/macros.rs b/src/macros.rs index 74de7f892..9ad6e7f08 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -231,7 +231,7 @@ macro_rules! log_enabled { #[doc(hidden)] #[macro_export] -#[cfg(feature = "kv_unstable")] +#[cfg(feature = "kv")] macro_rules! __log_key { // key1 = 42 ($($args:ident)*) => { @@ -245,16 +245,16 @@ macro_rules! __log_key { #[doc(hidden)] #[macro_export] -#[cfg(not(feature = "kv_unstable"))] +#[cfg(not(feature = "kv"))] macro_rules! __log_key { ($($args:tt)*) => { - compile_error!("key value support requires the `kv_unstable` feature of `log`") + compile_error!("key value support requires the `kv` feature of `log`") }; } #[doc(hidden)] #[macro_export] -#[cfg(feature = "kv_unstable")] +#[cfg(feature = "kv")] macro_rules! __log_value { // Default (($args:expr)) => { @@ -294,25 +294,27 @@ macro_rules! __log_value { #[doc(hidden)] #[macro_export] -#[cfg(not(feature = "kv_unstable"))] +#[cfg(not(feature = "kv"))] macro_rules! __log_value { ($($args:tt)*) => { - compile_error!("key value support requires the `kv_unstable` feature of `log`") + compile_error!("key value support requires the `kv` feature of `log`") }; } #[doc(hidden)] #[macro_export] -#[cfg(not(feature = "kv_unstable_std"))] +#[cfg(not(feature = "kv_std"))] macro_rules! __log_value_error { ($args:expr) => { - compile_error!("capturing values as `std::error::Error` requites the `kv_unstable_std` feature of `log`") - } + compile_error!( + "capturing values as `std::error::Error` requites the `kv_std` feature of `log`" + ) + }; } #[doc(hidden)] #[macro_export] -#[cfg(feature = "kv_unstable_sval")] +#[cfg(feature = "kv_sval")] macro_rules! __log_value_sval { ($args:expr) => { $crate::__private_api::capture_sval(&&$args) @@ -321,18 +323,16 @@ macro_rules! __log_value_sval { #[doc(hidden)] #[macro_export] -#[cfg(not(feature = "kv_unstable_sval"))] +#[cfg(not(feature = "kv_sval"))] macro_rules! __log_value_sval { ($args:expr) => { - compile_error!( - "capturing values as `sval::Value` requites the `kv_unstable_sval` feature of `log`" - ) + compile_error!("capturing values as `sval::Value` requites the `kv_sval` feature of `log`") }; } #[doc(hidden)] #[macro_export] -#[cfg(feature = "kv_unstable_serde")] +#[cfg(feature = "kv_serde")] macro_rules! __log_value_serde { ($args:expr) => { $crate::__private_api::capture_serde(&&$args) @@ -341,16 +341,18 @@ macro_rules! __log_value_serde { #[doc(hidden)] #[macro_export] -#[cfg(not(feature = "kv_unstable_serde"))] +#[cfg(not(feature = "kv_serde"))] macro_rules! __log_value_serde { ($args:expr) => { - compile_error!("capturing values as `serde::Serialize` requites the `kv_unstable_serde` feature of `log`") - } + compile_error!( + "capturing values as `serde::Serialize` requites the `kv_serde` feature of `log`" + ) + }; } #[doc(hidden)] #[macro_export] -#[cfg(feature = "kv_unstable_std")] +#[cfg(feature = "kv_std")] macro_rules! __log_value_error { ($args:expr) => { $crate::__private_api::capture_error(&$args) diff --git a/tests/Cargo.toml b/tests/Cargo.toml index 7d0d3e853..8754bb16a 100644 --- a/tests/Cargo.toml +++ b/tests/Cargo.toml @@ -7,10 +7,10 @@ build = "src/build.rs" [features] std = ["log/std"] -kv_unstable = ["log/kv_unstable"] -kv_unstable_std = ["log/kv_unstable_std"] -kv_unstable_sval = ["log/kv_unstable_sval"] -kv_unstable_serde = ["log/kv_unstable_serde"] +kv = ["log/kv"] +kv_std = ["log/kv_std"] +kv_sval = ["log/kv_sval"] +kv_serde = ["log/kv_serde"] [dependencies.log] path = ".." diff --git a/tests/macros.rs b/tests/macros.rs index 47cc957d9..07bdf53f0 100644 --- a/tests/macros.rs +++ b/tests/macros.rs @@ -107,7 +107,7 @@ fn expr() { } #[test] -#[cfg(feature = "kv_unstable")] +#[cfg(feature = "kv")] fn kv_no_args() { for lvl in log::Level::iter() { log!(target: "my_target", lvl, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); @@ -121,7 +121,7 @@ fn kv_no_args() { } #[test] -#[cfg(feature = "kv_unstable")] +#[cfg(feature = "kv")] fn kv_expr_args() { for lvl in log::Level::iter() { log!(target: "my_target", lvl, cat_math = { let mut x = 0; x += 1; x + 1 }; "hello"); @@ -136,7 +136,7 @@ fn kv_expr_args() { } #[test] -#[cfg(feature = "kv_unstable")] +#[cfg(feature = "kv")] fn kv_anonymous_args() { for lvl in log::Level::iter() { log!(target: "my_target", lvl, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {}", "world"); @@ -151,7 +151,7 @@ fn kv_anonymous_args() { } #[test] -#[cfg(feature = "kv_unstable")] +#[cfg(feature = "kv")] fn kv_named_args() { for lvl in log::Level::iter() { log!(target: "my_target", lvl, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}", world = "world"); @@ -166,7 +166,7 @@ fn kv_named_args() { } #[test] -#[cfg(feature = "kv_unstable")] +#[cfg(feature = "kv")] fn kv_expr_context() { match "chashu" { cat_1 => { @@ -196,14 +196,14 @@ fn implicit_named_args() { all_log_macros!(target: "my_target", "hello {world}"); all_log_macros!(target: "my_target", "hello {world}",); - #[cfg(feature = "kv_unstable")] + #[cfg(feature = "kv")] all_log_macros!(target = "my_target"; "hello {world}"); - #[cfg(feature = "kv_unstable")] + #[cfg(feature = "kv")] all_log_macros!(target = "my_target"; "hello {world}",); } #[test] -#[cfg(feature = "kv_unstable")] +#[cfg(feature = "kv")] fn kv_implicit_named_args() { let world = "world"; @@ -219,7 +219,7 @@ fn kv_implicit_named_args() { } #[test] -#[cfg(feature = "kv_unstable")] +#[cfg(feature = "kv")] fn kv_string_keys() { for lvl in log::Level::iter() { log!(target: "my_target", lvl, "also dogs" = "Fílos", "key/that-can't/be/an/ident" = "hi"; "hello {world}", world = "world"); @@ -229,7 +229,7 @@ fn kv_string_keys() { } #[test] -#[cfg(feature = "kv_unstable")] +#[cfg(feature = "kv")] fn kv_common_value_types() { all_log_macros!( u8 = 42u8, @@ -251,7 +251,7 @@ fn kv_common_value_types() { } #[test] -#[cfg(feature = "kv_unstable")] +#[cfg(feature = "kv")] fn kv_debug() { all_log_macros!( a:? = 42, @@ -261,7 +261,7 @@ fn kv_debug() { } #[test] -#[cfg(feature = "kv_unstable")] +#[cfg(feature = "kv")] fn kv_display() { all_log_macros!( a:% = 42, @@ -271,7 +271,7 @@ fn kv_display() { } #[test] -#[cfg(feature = "kv_unstable_std")] +#[cfg(feature = "kv_std")] fn kv_error() { all_log_macros!( a:error = std::io::Error::new(std::io::ErrorKind::Other, "an error"); @@ -280,7 +280,7 @@ fn kv_error() { } #[test] -#[cfg(feature = "kv_unstable_sval")] +#[cfg(feature = "kv_sval")] fn kv_sval() { all_log_macros!( a:sval = 42; @@ -289,7 +289,7 @@ fn kv_sval() { } #[test] -#[cfg(feature = "kv_unstable_serde")] +#[cfg(feature = "kv_serde")] fn kv_serde() { all_log_macros!( a:serde = 42; From 90a347bd836873264a393a35bfd90fe478fadae2 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Mon, 19 Feb 2024 07:22:40 +1000 Subject: [PATCH 184/280] restore removed APIs as deprecated --- Cargo.toml | 3 +- src/kv/mod.rs | 11 ++++ src/kv/source.rs | 4 ++ src/kv/value.rs | 136 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 153 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 5992d0a9e..3074e9cfa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,7 +51,8 @@ kv_sval = ["kv", "value-bag/sval", "sval", "sval_ref"] kv_std = ["std", "kv", "value-bag/error"] kv_serde = ["kv_std", "value-bag/serde", "serde"] -# Legacy: use `kv_*` instead +# Deprecated: use `kv_*` instead +# These `*_unstable` features will be removed in a future release kv_unstable = ["kv"] kv_unstable_sval = ["kv_sval"] kv_unstable_std = ["kv_std"] diff --git a/src/kv/mod.rs b/src/kv/mod.rs index 44f7b06df..6dbfe6f66 100644 --- a/src/kv/mod.rs +++ b/src/kv/mod.rs @@ -236,10 +236,21 @@ mod error; mod key; + +#[cfg(not(feature = "kv_unstable"))] mod source; +#[cfg(not(feature = "kv_unstable"))] mod value; pub use self::error::Error; pub use self::key::{Key, ToKey}; pub use self::source::{Source, VisitSource}; pub use self::value::{ToValue, Value, VisitValue}; + +#[cfg(feature = "kv_unstable")] +pub mod source; +#[cfg(feature = "kv_unstable")] +pub mod value; + +#[cfg(feature = "kv_unstable")] +pub use self::source::Visitor; diff --git a/src/kv/source.rs b/src/kv/source.rs index 33d5a1a73..0ca267ce3 100644 --- a/src/kv/source.rs +++ b/src/kv/source.rs @@ -458,6 +458,10 @@ mod std_support { } } +// NOTE: Deprecated; but aliases can't carry this attribute +#[cfg(feature = "kv_unstable")] +pub use VisitSource as Visitor; + #[cfg(test)] mod tests { use crate::kv::value; diff --git a/src/kv/value.rs b/src/kv/value.rs index 6bfff4e4e..96cb411d1 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -298,6 +298,12 @@ macro_rules! impl_to_value_primitive { Value::from_inner(value) } } + + impl<'v> From<&'v $into_ty> for Value<'v> { + fn from(value: &'v $into_ty) -> Self { + Value::from_inner(*value) + } + } )* }; } @@ -316,6 +322,12 @@ macro_rules! impl_to_value_nonzero_primitive { Value::from(value.get()) } } + + impl<'v> From<&'v std::num::$into_ty> for Value<'v> { + fn from(value: &'v std::num::$into_ty) -> Self { + Value::from(value.get()) + } + } )* }; } @@ -1034,6 +1046,130 @@ pub(in crate::kv) mod inner { } } +impl<'v> Value<'v> { + /// Get a value from a type implementing `std::fmt::Debug`. + #[cfg(feature = "kv_unstable")] + #[deprecated(note = "use `from_debug` instead")] + pub fn capture_debug(value: &'v T) -> Self + where + T: fmt::Debug + 'static, + { + Value::from_debug(value) + } + + /// Get a value from a type implementing `std::fmt::Display`. + #[cfg(feature = "kv_unstable")] + #[deprecated(note = "use `from_display` instead")] + pub fn capture_display(value: &'v T) -> Self + where + T: fmt::Display + 'static, + { + Value::from_display(value) + } + + /// Get a value from an error. + #[cfg(feature = "kv_unstable_std")] + #[deprecated(note = "use `from_dyn_error` instead")] + pub fn capture_error(err: &'v T) -> Self + where + T: std::error::Error + 'static, + { + Value::from_dyn_error(err) + } + + /// Get a value from a type implementing `serde::Serialize`. + #[cfg(feature = "kv_unstable_serde")] + #[deprecated(note = "use `from_serde` instead")] + pub fn capture_serde(value: &'v T) -> Self + where + T: serde::Serialize + 'static, + { + Value::from_serde(value) + } + + /// Get a value from a type implementing `sval::Value`. + #[cfg(feature = "kv_unstable_sval")] + #[deprecated(note = "use `from_sval` instead")] + pub fn capture_sval(value: &'v T) -> Self + where + T: sval::Value + 'static, + { + Value::from_sval(value) + } + + /// Check whether this value can be downcast to `T`. + #[cfg(feature = "kv_unstable")] + #[deprecated( + note = "downcasting has been removed; log an issue at https://github.com/rust-lang/log/issues if this is something you rely on" + )] + pub fn is(&self) -> bool { + false + } + + /// Try downcast this value to `T`. + #[cfg(feature = "kv_unstable")] + #[deprecated( + note = "downcasting has been removed; log an issue at https://github.com/rust-lang/log/issues if this is something you rely on" + )] + pub fn downcast_ref(&self) -> Option<&T> { + None + } +} + +// NOTE: Deprecated; but aliases can't carry this attribute +#[cfg(feature = "kv_unstable")] +pub use VisitValue as Visitor; + +/// Get a value from a type implementing `std::fmt::Debug`. +#[cfg(feature = "kv_unstable")] +#[deprecated(note = "use the `key:? = value` macro syntax instead")] +#[macro_export] +macro_rules! as_debug { + ($capture:expr) => { + $crate::kv::Value::from_debug(&$capture) + }; +} + +/// Get a value from a type implementing `std::fmt::Display`. +#[cfg(feature = "kv_unstable")] +#[deprecated(note = "use the `key:% = value` macro syntax instead")] +#[macro_export] +macro_rules! as_display { + ($capture:expr) => { + $crate::kv::Value::from_display(&$capture) + }; +} + +/// Get a value from an error. +#[cfg(feature = "kv_unstable_std")] +#[deprecated(note = "use the `key:error = value` macro syntax instead")] +#[macro_export] +macro_rules! as_error { + ($capture:expr) => { + $crate::kv::Value::from_dyn_error(&$capture) + }; +} + +#[cfg(feature = "kv_unstable_serde")] +#[deprecated(note = "use the `key:serde = value` macro syntax instead")] +/// Get a value from a type implementing `serde::Serialize`. +#[macro_export] +macro_rules! as_serde { + ($capture:expr) => { + $crate::kv::Value::from_serde(&$capture) + }; +} + +/// Get a value from a type implementing `sval::Value`. +#[cfg(feature = "kv_unstable_sval")] +#[deprecated(note = "use the `key:sval = value` macro syntax instead")] +#[macro_export] +macro_rules! as_sval { + ($capture:expr) => { + $crate::kv::Value::from_sval(&$capture) + }; +} + #[cfg(test)] pub(crate) mod tests { use super::*; From ad917118a5e781d0dd60b3a75ba519ce9839ba70 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Mon, 19 Feb 2024 07:36:01 +1000 Subject: [PATCH 185/280] support field shorthand in macros --- README.md | 2 +- src/kv/mod.rs | 11 ++++++++++- src/kv/value.rs | 2 +- src/lib.rs | 2 +- src/macros.rs | 17 +++++++++++++---- tests/macros.rs | 11 ++++++++++- 6 files changed, 36 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 01fd30875..c959ac56d 100644 --- a/README.md +++ b/README.md @@ -116,7 +116,7 @@ pub fn shave_the_yak(yak: &mut Yak) { break; } Err(err) => { - warn!(err:error = err; "Unable to locate a razor, retrying"); + warn!(err:err; "Unable to locate a razor, retrying"); } } } diff --git a/src/kv/mod.rs b/src/kv/mod.rs index 6dbfe6f66..1ccb82514 100644 --- a/src/kv/mod.rs +++ b/src/kv/mod.rs @@ -29,6 +29,15 @@ //! info!(a = 1; "Something of interest"); //! ``` //! +//! Key-values support the same shorthand identifer syntax as `format_args`: +//! +//! ``` +//! # use log::info; +//! let a = 1; +//! +//! info!(a; "Something of interest"); +//! ``` +//! //! Values are capturing using the [`ToValue`] trait by default. To capture a value //! using a different trait implementation, use a modifier after its key. Here's how //! the same example can capture `a` using its `Debug` implementation instead: @@ -44,7 +53,7 @@ //! - `:debug` will capture the value using `Debug`. //! - `:%` will capture the value using `Display`. //! - `:display` will capture the value using `Display`. -//! - `:error` will capture the value using `std::error::Error` (requires the `kv_std` feature). +//! - `:err` will capture the value using `std::error::Error` (requires the `kv_std` feature). //! - `:sval` will capture the value using `sval::Value` (requires the `kv_sval` feature). //! - `:serde` will capture the value using `serde::Serialize` (requires the `kv_serde` feature). //! diff --git a/src/kv/value.rs b/src/kv/value.rs index 96cb411d1..c7efa279d 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -1142,7 +1142,7 @@ macro_rules! as_display { /// Get a value from an error. #[cfg(feature = "kv_unstable_std")] -#[deprecated(note = "use the `key:error = value` macro syntax instead")] +#[deprecated(note = "use the `key:err = value` macro syntax instead")] #[macro_export] macro_rules! as_error { ($capture:expr) => { diff --git a/src/lib.rs b/src/lib.rs index feb14e115..c1f88fe8d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -112,7 +112,7 @@ //! break; //! } //! Err(err) => { -//! warn!(err:error = err; "Unable to locate a razor, retrying"); +//! warn!(err:err; "Unable to locate a razor, retrying"); //! } //! } //! } diff --git a/src/macros.rs b/src/macros.rs index 9ad6e7f08..ccccd5bd6 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -30,7 +30,7 @@ #[macro_export] macro_rules! log { // log!(target: "my_target", Level::Info, key1:? = 42, key2 = true; "a {} event", "log"); - (target: $target:expr, $lvl:expr, $($key:tt $(:$capture:tt)? = $value:expr),+; $($arg:tt)+) => ({ + (target: $target:expr, $lvl:expr, $($key:tt $(:$capture:tt)? $(= $value:expr)?),+; $($arg:tt)+) => ({ let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { $crate::__private_api::log::<&_>( @@ -38,7 +38,7 @@ macro_rules! log { lvl, &($target, $crate::__private_api::module_path!(), $crate::__private_api::file!()), $crate::__private_api::line!(), - &[$(($crate::__log_key!($key), $crate::__log_value!(($value)$(:$capture)*))),+] + &[$(($crate::__log_key!($key), $crate::__log_value!($key $(:$capture)* = $($value)*))),+] ); } }); @@ -256,10 +256,19 @@ macro_rules! __log_key { #[macro_export] #[cfg(feature = "kv")] macro_rules! __log_value { - // Default - (($args:expr)) => { + // Entrypoint + ($key:tt = $args:expr) => { $crate::__log_value!(($args):value) }; + ($key:tt :$capture:tt = $args:expr) => { + $crate::__log_value!(($args):$capture) + }; + ($key:ident =) => { + $crate::__log_value!(($key):value) + }; + ($key:ident :$capture:tt =) => { + $crate::__log_value!(($key):$capture) + }; // ToValue (($args:expr):value) => { $crate::__private_api::capture_to_value(&&$args) diff --git a/tests/macros.rs b/tests/macros.rs index 07bdf53f0..20da6ac44 100644 --- a/tests/macros.rs +++ b/tests/macros.rs @@ -165,6 +165,15 @@ fn kv_named_args() { all_log_macros!(cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}", world = "world"); } +#[test] +#[cfg(feature = "kv")] +fn kv_ident() { + let cat_1 = "chashu"; + let cat_2 = "nori"; + + all_log_macros!(cat_1, cat_2:%, cat_count = 2; "hello {world}", world = "world"); +} + #[test] #[cfg(feature = "kv")] fn kv_expr_context() { @@ -274,7 +283,7 @@ fn kv_display() { #[cfg(feature = "kv_std")] fn kv_error() { all_log_macros!( - a:error = std::io::Error::new(std::io::ErrorKind::Other, "an error"); + a:err = std::io::Error::new(std::io::ErrorKind::Other, "an error"); "hello world" ); } From 31bb4b0ff36e458c6bef304a336b71f6342ddcc7 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Mon, 19 Feb 2024 07:41:02 +1000 Subject: [PATCH 186/280] move error macros together --- src/macros.rs | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index ccccd5bd6..6297eb853 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -310,17 +310,6 @@ macro_rules! __log_value { }; } -#[doc(hidden)] -#[macro_export] -#[cfg(not(feature = "kv_std"))] -macro_rules! __log_value_error { - ($args:expr) => { - compile_error!( - "capturing values as `std::error::Error` requites the `kv_std` feature of `log`" - ) - }; -} - #[doc(hidden)] #[macro_export] #[cfg(feature = "kv_sval")] @@ -367,3 +356,14 @@ macro_rules! __log_value_error { $crate::__private_api::capture_error(&$args) }; } + +#[doc(hidden)] +#[macro_export] +#[cfg(not(feature = "kv_std"))] +macro_rules! __log_value_error { + ($args:expr) => { + compile_error!( + "capturing values as `std::error::Error` requites the `kv_std` feature of `log`" + ) + }; +} From 73e953905b970ef765a86bf6cbd69bc2c5e2bac4 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Mon, 19 Feb 2024 07:47:32 +1000 Subject: [PATCH 187/280] fix up capturing of :err --- src/macros.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/macros.rs b/src/macros.rs index 6297eb853..48a7447ef 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -288,7 +288,7 @@ macro_rules! __log_value { $crate::__private_api::capture_display(&&$args) }; //Error - (($args:expr):error) => { + (($args:expr):err) => { $crate::__log_value_error!($args) }; // sval::Value From cf85c38d3519745d60e7b891c4b2025050a8389f Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Tue, 20 Feb 2024 07:29:14 +1000 Subject: [PATCH 188/280] add needed subfeatures to kv_unstable Co-authored-by: Thomas de Zeeuw --- Cargo.toml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3074e9cfa..cf64b43e7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,10 +53,10 @@ kv_serde = ["kv_std", "value-bag/serde", "serde"] # Deprecated: use `kv_*` instead # These `*_unstable` features will be removed in a future release -kv_unstable = ["kv"] -kv_unstable_sval = ["kv_sval"] -kv_unstable_std = ["kv_std"] -kv_unstable_serde = ["kv_serde"] +kv_unstable = ["kv", "value-bag"] +kv_unstable_sval = ["kv_sval", "kv_unstable"] +kv_unstable_std = ["kv_std", "kv_unstable"] +kv_unstable_serde = ["kv_serde", "kv_unstable_std"] [dependencies] serde = { version = "1.0", optional = true, default-features = false } From 646e9ab9917fb79e44b6b36b8375106a1a09766c Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Tue, 20 Feb 2024 07:29:43 +1000 Subject: [PATCH 189/280] use original Visitor name for VisitValue Co-authored-by: Thomas de Zeeuw --- src/kv/value.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kv/value.rs b/src/kv/value.rs index c7efa279d..1511dd02e 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -1118,7 +1118,7 @@ impl<'v> Value<'v> { // NOTE: Deprecated; but aliases can't carry this attribute #[cfg(feature = "kv_unstable")] -pub use VisitValue as Visitor; +pub use VisitValue as Visit; /// Get a value from a type implementing `std::fmt::Debug`. #[cfg(feature = "kv_unstable")] From 2b220bf3b705f2abc0ee591c7eb17972a979da3a Mon Sep 17 00:00:00 2001 From: KodrAus Date: Tue, 20 Feb 2024 07:36:07 +1000 Subject: [PATCH 190/280] clean up structured logging example --- README.md | 13 +++++++++---- src/lib.rs | 8 ++++---- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index c959ac56d..d6a08f558 100644 --- a/README.md +++ b/README.md @@ -106,17 +106,22 @@ If you enable the `kv` feature, you can associate structured data with your log use log::{info, trace, warn}; pub fn shave_the_yak(yak: &mut Yak) { - trace!(target = "yak_events", yak:serde = yak; "Commencing yak shaving"); + // `yak:serde` will capture `yak` using its `serde::Serialize` impl + // + // You could also use `:?` for `Debug`, or `:%` for `Display`. For a + // full list, see the `log` crate documentation + trace!(target = "yak_events", yak:serde; "Commencing yak shaving"); loop { match find_a_razor() { Ok(razor) => { - info!(razor = razor; "Razor located"); + info!(razor; "Razor located"); yak.shave(razor); break; } - Err(err) => { - warn!(err:err; "Unable to locate a razor, retrying"); + Err(e) => { + // `e:err` will capture `e` using its `std::error::Error` impl + warn!(e:err; "Unable to locate a razor, retrying"); } } } diff --git a/src/lib.rs b/src/lib.rs index c1f88fe8d..505d24961 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -102,17 +102,17 @@ //! use log::{info, warn}; //! //! pub fn shave_the_yak(yak: &mut Yak) { -//! info!(target: "yak_events", yak:serde = yak; "Commencing yak shaving"); +//! info!(target: "yak_events", yak:serde; "Commencing yak shaving"); //! //! loop { //! match find_a_razor() { //! Ok(razor) => { -//! info!(razor = razor; "Razor located"); +//! info!(razor; "Razor located"); //! yak.shave(razor); //! break; //! } -//! Err(err) => { -//! warn!(err:err; "Unable to locate a razor, retrying"); +//! Err(e) => { +//! warn!(e:err; "Unable to locate a razor, retrying"); //! } //! } //! } From 6153cb289f0e7b80f00ae07dbe5ee41cf3d3fcb0 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Tue, 27 Feb 2024 20:21:12 +1000 Subject: [PATCH 191/280] prepare for 0.4.21 release --- CHANGELOG.md | 35 ++++++++++++++++++++++++++++++++--- Cargo.toml | 2 +- src/lib.rs | 2 +- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 45a18cdda..77633b170 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,36 @@ # Change Log ## [Unreleased] -* Migrate to 2021 edition and minor cleanups by @nyurik in https://github.com/rust-lang/log/pull/580 -* Use inline format args by @nyurik in https://github.com/rust-lang/log/pull/577 + +## [0.4.21] - 2024-02-27 + +## What's Changed +* Minor clippy nits by @nyurik in https://github.com/rust-lang/log/pull/578 +* Simplify Display impl by @nyurik in https://github.com/rust-lang/log/pull/579 +* Set all crates to 2021 edition by @nyurik in https://github.com/rust-lang/log/pull/580 +* Various changes based on review by @Thomasdezeeuw in https://github.com/rust-lang/log/pull/583 +* Fix typo in file_static() method doc by @dimo414 in https://github.com/rust-lang/log/pull/590 +* Specialize empty key value pairs by @EFanZh in https://github.com/rust-lang/log/pull/576 +* Fix incorrect lifetime in Value::to_str() by @peterjoel in https://github.com/rust-lang/log/pull/587 +* Remove some API of the key-value feature by @Thomasdezeeuw in https://github.com/rust-lang/log/pull/585 +* Add logcontrol-log and log-reload by @swsnr in https://github.com/rust-lang/log/pull/595 +* Add Serialization section to kv::Value docs by @Thomasdezeeuw in https://github.com/rust-lang/log/pull/593 +* Rename Value::to_str to to_cow_str by @Thomasdezeeuw in https://github.com/rust-lang/log/pull/592 +* Clarify documentation and simplify initialization of `STATIC_MAX_LEVEL` by @ptosi in https://github.com/rust-lang/log/pull/594 +* Update docs to 2021 edition, test by @nyurik in https://github.com/rust-lang/log/pull/577 +* Add "alterable_logger" link to README.md by @brummer-simon in https://github.com/rust-lang/log/pull/589 +* Normalize line ending by @EFanZh in https://github.com/rust-lang/log/pull/602 +* Remove `ok_or` in favor of `Option::ok_or` by @AngelicosPhosphoros in https://github.com/rust-lang/log/pull/607 +* Use `Acquire` ordering for initialization check by @AngelicosPhosphoros in https://github.com/rust-lang/log/pull/610 +* Get structured logging API ready for stabilization by @KodrAus in https://github.com/rust-lang/log/pull/613 + +## New Contributors +* @nyurik made their first contribution in https://github.com/rust-lang/log/pull/578 +* @dimo414 made their first contribution in https://github.com/rust-lang/log/pull/590 +* @peterjoel made their first contribution in https://github.com/rust-lang/log/pull/587 +* @ptosi made their first contribution in https://github.com/rust-lang/log/pull/594 +* @brummer-simon made their first contribution in https://github.com/rust-lang/log/pull/589 +* @AngelicosPhosphoros made their first contribution in https://github.com/rust-lang/log/pull/607 ## [0.4.20] - 2023-07-11 @@ -250,7 +278,8 @@ version using log 0.4.x to avoid losing module and file information. Look at the [release tags] for information about older releases. -[Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.18...HEAD +[Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.21...HEAD +[0.4.21]: https://github.com/rust-lang/log/compare/0.4.20...0.4.21 [0.4.20]: https://github.com/rust-lang-nursery/log/compare/0.4.19...0.4.20 [0.4.19]: https://github.com/rust-lang-nursery/log/compare/0.4.18...0.4.19 [0.4.18]: https://github.com/rust-lang-nursery/log/compare/0.4.17...0.4.18 diff --git a/Cargo.toml b/Cargo.toml index cf64b43e7..c0ea52a77 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "log" -version = "0.4.20" # remember to update html_root_url +version = "0.4.21" # remember to update html_root_url authors = ["The Rust Project Developers"] license = "MIT OR Apache-2.0" readme = "README.md" diff --git a/src/lib.rs b/src/lib.rs index 505d24961..6b5eafbf4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -332,7 +332,7 @@ #![doc( html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://www.rust-lang.org/favicon.ico", - html_root_url = "https://docs.rs/log/0.4.20" + html_root_url = "https://docs.rs/log/0.4.21" )] #![warn(missing_docs)] #![deny(missing_debug_implementations, unconditional_recursion)] From d9f4a65678c31a87f718bf17014f2c7e8e31171b Mon Sep 17 00:00:00 2001 From: Divkov575 Date: Sat, 16 Mar 2024 10:23:11 -0400 Subject: [PATCH 192/280] added line_numbers.rs --- tests/line_numbers.rs | 58 +++++++++++++++++++++++++++++++++++++++++++ tests/src/lib.rs | 5 ++++ 2 files changed, 63 insertions(+) create mode 100644 tests/line_numbers.rs diff --git a/tests/line_numbers.rs b/tests/line_numbers.rs new file mode 100644 index 000000000..2e3b2b045 --- /dev/null +++ b/tests/line_numbers.rs @@ -0,0 +1,58 @@ +#![allow(dead_code, unused_imports)] + +use log::{debug, error, info, trace, warn, Level, LevelFilter, Log, Metadata, Record}; +use std::sync::{Arc, Mutex}; + +#[cfg(feature = "std")] +use log::set_boxed_logger; + +#[cfg(not(feature = "std"))] +fn set_boxed_logger(logger: Box) -> Result<(), log::SetLoggerError> { + log::set_logger(Box::leak(logger)) +} + +struct State<'a> { + last_log: Mutex>>, +} + +struct Logger<'a>(Arc>); + +impl Log for Logger { + fn enabled(&self, _: &Metadata) -> bool { + true + } + + fn log(&self, record: Record) { + *self.0.last_log.lock().unwrap() = Some(record); + } + fn flush(&self) {} +} + +#[cfg_attr(lib_build, test)] +fn main() { + let me = Arc::new(State { + last_log: Mutex::new(None), + }); + let a = me.clone(); + set_boxed_logger(Box::new(Logger(me))).unwrap(); + + + error!(""); + last(&a, 40); + warn!(""); + last(&a, 42); + info!(""); + last(&a, 44); + debug!(""); + last(&a, 46); + trace!(""); + last(&a, 48); + +} + +fn last(state: &State, expected: u32) { + let last_log= state.last_log.lock().unwrap().take().unwrap(); + let line_number = last_log.line().unwrap(); + + assert_eq!(line_number, expected); +} diff --git a/tests/src/lib.rs b/tests/src/lib.rs index 73f0753ca..49e0d03e1 100644 --- a/tests/src/lib.rs +++ b/tests/src/lib.rs @@ -12,3 +12,8 @@ mod filters; #[cfg(test)] #[path = "../macros.rs"] mod macros; + + +#[cfg(test)] +#[path = "../line_numbers.rs"] +mod line_numbers; From 96c3fdc9ad304a238f51b1dfe516732b02aaf076 Mon Sep 17 00:00:00 2001 From: Divkov575 Date: Sat, 16 Mar 2024 10:47:58 -0400 Subject: [PATCH 193/280] changed state to state in order to store line number only --- tests/line_numbers.rs | 36 +++++++++++------------------------- 1 file changed, 11 insertions(+), 25 deletions(-) diff --git a/tests/line_numbers.rs b/tests/line_numbers.rs index 2e3b2b045..de280e748 100644 --- a/tests/line_numbers.rs +++ b/tests/line_numbers.rs @@ -11,48 +11,34 @@ fn set_boxed_logger(logger: Box) -> Result<(), log::SetLoggerError> { log::set_logger(Box::leak(logger)) } -struct State<'a> { - last_log: Mutex>>, -} +struct State { last_log: Mutex> } -struct Logger<'a>(Arc>); +struct Logger(Arc); impl Log for Logger { fn enabled(&self, _: &Metadata) -> bool { true } - fn log(&self, record: Record) { - *self.0.last_log.lock().unwrap() = Some(record); + fn log(&self, record: &Record) { + *self.0.last_log.lock().unwrap() = Some(record.line().unwrap()); } fn flush(&self) {} } -#[cfg_attr(lib_build, test)] -fn main() { - let me = Arc::new(State { - last_log: Mutex::new(None), - }); - let a = me.clone(); - set_boxed_logger(Box::new(Logger(me))).unwrap(); - +#[test] +fn line_number() { + let default_state = Arc::new(State { last_log: Mutex::new(None) }); + let state = default_state.clone(); + set_boxed_logger(Box::new(Logger(default_state))).unwrap(); - error!(""); - last(&a, 40); - warn!(""); - last(&a, 42); info!(""); - last(&a, 44); - debug!(""); - last(&a, 46); - trace!(""); - last(&a, 48); + last(&state, 35); } fn last(state: &State, expected: u32) { - let last_log= state.last_log.lock().unwrap().take().unwrap(); - let line_number = last_log.line().unwrap(); + let line_number = state.last_log.lock().unwrap().take().unwrap(); assert_eq!(line_number, expected); } From eeaeeb80bdf2674978d3d95c741f5b903fd9c7fd Mon Sep 17 00:00:00 2001 From: Divkov575 Date: Sat, 16 Mar 2024 13:02:06 -0400 Subject: [PATCH 194/280] extra option wrapping record.lien() on line 21 removed --- tests/line_numbers.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/tests/line_numbers.rs b/tests/line_numbers.rs index de280e748..fd9f84cfc 100644 --- a/tests/line_numbers.rs +++ b/tests/line_numbers.rs @@ -16,13 +16,10 @@ struct State { last_log: Mutex> } struct Logger(Arc); impl Log for Logger { - fn enabled(&self, _: &Metadata) -> bool { - true - } + fn enabled(&self, _: &Metadata) -> bool { true } + + fn log(&self, record: &Record) { *self.0.last_log.lock().unwrap() = record.line(); } - fn log(&self, record: &Record) { - *self.0.last_log.lock().unwrap() = Some(record.line().unwrap()); - } fn flush(&self) {} } @@ -32,8 +29,12 @@ fn line_number() { let state = default_state.clone(); set_boxed_logger(Box::new(Logger(default_state))).unwrap(); + // let record = RecordBuilder::new().args(format_args!("")).metadata(Metadata::builder().build()).module_path(None).file(None).line(Some(5)).build(); + // let logger = Logger(a.clone()); + // logger.log(&record); + info!(""); - last(&state, 35); + last(&state, 36); } From 8e1fa960a5270633d925dacf5aacc6aba8ff8b93 Mon Sep 17 00:00:00 2001 From: Divkov575 Date: Tue, 19 Mar 2024 08:00:22 -0400 Subject: [PATCH 195/280] added checks for log filtering + set_max_level log --- tests/line_numbers.rs | 61 +++++++++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 19 deletions(-) diff --git a/tests/line_numbers.rs b/tests/line_numbers.rs index fd9f84cfc..7adb76936 100644 --- a/tests/line_numbers.rs +++ b/tests/line_numbers.rs @@ -1,8 +1,10 @@ +// ensure line number (from log!() calling position) is correctly within log record + #![allow(dead_code, unused_imports)] -use log::{debug, error, info, trace, warn, Level, LevelFilter, Log, Metadata, Record}; use std::sync::{Arc, Mutex}; +use log::{info, LevelFilter, Log, Metadata, Record}; #[cfg(feature = "std")] use log::set_boxed_logger; @@ -11,35 +13,56 @@ fn set_boxed_logger(logger: Box) -> Result<(), log::SetLoggerError> { log::set_logger(Box::leak(logger)) } -struct State { last_log: Mutex> } +struct State { + last_log: Mutex>, +} struct Logger(Arc); impl Log for Logger { - fn enabled(&self, _: &Metadata) -> bool { true } + fn enabled(&self, _: &Metadata) -> bool { + true + } - fn log(&self, record: &Record) { *self.0.last_log.lock().unwrap() = record.line(); } + fn log(&self, record: &Record) { + *self.0.last_log.lock().unwrap() = record.line(); + } fn flush(&self) {} } #[test] fn line_number() { - let default_state = Arc::new(State { last_log: Mutex::new(None) }); - let state = default_state.clone(); - set_boxed_logger(Box::new(Logger(default_state))).unwrap(); - - // let record = RecordBuilder::new().args(format_args!("")).metadata(Metadata::builder().build()).module_path(None).file(None).line(Some(5)).build(); - // let logger = Logger(a.clone()); - // logger.log(&record); - - info!(""); - last(&state, 36); + // These tests don't really make sense when static + // max level filtering is applied + #[cfg(not(any( + feature = "max_level_off", + feature = "max_level_error", + feature = "max_level_warn", + feature = "max_level_info", + feature = "max_level_debug", + feature = "max_level_trace", + feature = "release_max_level_off", + feature = "release_max_level_error", + feature = "release_max_level_warn", + feature = "release_max_level_info", + feature = "release_max_level_debug", + feature = "release_max_level_trace", + )))] + { + let default_state = Arc::new(State { + last_log: Mutex::new(None), + }); + let state = default_state.clone(); + set_boxed_logger(Box::new(Logger(default_state))).unwrap(); + log::set_max_level(LevelFilter::Trace); + info!(""); + check_line(&state, 61); + } + fn check_line(state: &State, expected: u32) { + let line_number = state.last_log.lock().unwrap().take().unwrap(); + assert_eq!(line_number, expected); + } } -fn last(state: &State, expected: u32) { - let line_number = state.last_log.lock().unwrap().take().unwrap(); - - assert_eq!(line_number, expected); -} From cffcd66e5442fb44a9c3580e85c27061e7eb9482 Mon Sep 17 00:00:00 2001 From: Divkov575 Date: Tue, 19 Mar 2024 08:02:36 -0400 Subject: [PATCH 196/280] fmt + update line# for assertion --- tests/line_numbers.rs | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/tests/line_numbers.rs b/tests/line_numbers.rs index 7adb76936..3aed38cc4 100644 --- a/tests/line_numbers.rs +++ b/tests/line_numbers.rs @@ -4,9 +4,9 @@ use std::sync::{Arc, Mutex}; -use log::{info, LevelFilter, Log, Metadata, Record}; #[cfg(feature = "std")] use log::set_boxed_logger; +use log::{info, LevelFilter, Log, Metadata, Record}; #[cfg(not(feature = "std"))] fn set_boxed_logger(logger: Box) -> Result<(), log::SetLoggerError> { @@ -36,18 +36,18 @@ fn line_number() { // These tests don't really make sense when static // max level filtering is applied #[cfg(not(any( - feature = "max_level_off", - feature = "max_level_error", - feature = "max_level_warn", - feature = "max_level_info", - feature = "max_level_debug", - feature = "max_level_trace", - feature = "release_max_level_off", - feature = "release_max_level_error", - feature = "release_max_level_warn", - feature = "release_max_level_info", - feature = "release_max_level_debug", - feature = "release_max_level_trace", + feature = "max_level_off", + feature = "max_level_error", + feature = "max_level_warn", + feature = "max_level_info", + feature = "max_level_debug", + feature = "max_level_trace", + feature = "release_max_level_off", + feature = "release_max_level_error", + feature = "release_max_level_warn", + feature = "release_max_level_info", + feature = "release_max_level_debug", + feature = "release_max_level_trace", )))] { let default_state = Arc::new(State { @@ -58,11 +58,10 @@ fn line_number() { log::set_max_level(LevelFilter::Trace); info!(""); - check_line(&state, 61); + check_line(&state, 60); } fn check_line(state: &State, expected: u32) { let line_number = state.last_log.lock().unwrap().take().unwrap(); assert_eq!(line_number, expected); } } - From d94009e43204b9dd7d106e04b6755bfef29e7a4e Mon Sep 17 00:00:00 2001 From: Divkov575 Date: Tue, 19 Mar 2024 11:43:59 -0400 Subject: [PATCH 197/280] added line_numbers test to cargo.toml and lib.rs --- Cargo.toml | 5 +++++ tests/line_numbers.rs | 8 +++----- tests/src/lib.rs | 1 - 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c0ea52a77..83518332f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,11 @@ name = "filters" path = "tests/filters.rs" harness = false +[[test]] +name = "line_numbers" +path = "tests/line_numbers.rs" +harness = true + [[test]] name = "macros" path = "tests/macros.rs" diff --git a/tests/line_numbers.rs b/tests/line_numbers.rs index 3aed38cc4..9a376f800 100644 --- a/tests/line_numbers.rs +++ b/tests/line_numbers.rs @@ -2,11 +2,11 @@ #![allow(dead_code, unused_imports)] +use log::{info, LevelFilter, Log, Metadata, Record}; use std::sync::{Arc, Mutex}; #[cfg(feature = "std")] use log::set_boxed_logger; -use log::{info, LevelFilter, Log, Metadata, Record}; #[cfg(not(feature = "std"))] fn set_boxed_logger(logger: Box) -> Result<(), log::SetLoggerError> { @@ -32,9 +32,7 @@ impl Log for Logger { } #[test] -fn line_number() { - // These tests don't really make sense when static - // max level filtering is applied +fn line_numbers() { #[cfg(not(any( feature = "max_level_off", feature = "max_level_error", @@ -58,7 +56,7 @@ fn line_number() { log::set_max_level(LevelFilter::Trace); info!(""); - check_line(&state, 60); + check_line(&state, 58); } fn check_line(state: &State, expected: u32) { let line_number = state.last_log.lock().unwrap().take().unwrap(); diff --git a/tests/src/lib.rs b/tests/src/lib.rs index 49e0d03e1..795f60651 100644 --- a/tests/src/lib.rs +++ b/tests/src/lib.rs @@ -13,7 +13,6 @@ mod filters; #[path = "../macros.rs"] mod macros; - #[cfg(test)] #[path = "../line_numbers.rs"] mod line_numbers; From 8f79efefa17a1e9197feecbdf9df2af1f83c73ff Mon Sep 17 00:00:00 2001 From: Divkov575 Date: Tue, 19 Mar 2024 12:41:41 -0400 Subject: [PATCH 198/280] removed harness from line_numbers test --- Cargo.toml | 2 +- tests/line_numbers.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 83518332f..03eb08ee1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ harness = false [[test]] name = "line_numbers" path = "tests/line_numbers.rs" -harness = true +harness = false [[test]] name = "macros" diff --git a/tests/line_numbers.rs b/tests/line_numbers.rs index 9a376f800..41fb1537d 100644 --- a/tests/line_numbers.rs +++ b/tests/line_numbers.rs @@ -31,8 +31,8 @@ impl Log for Logger { fn flush(&self) {} } -#[test] -fn line_numbers() { +#[cfg_attr(lib_build, test)] +fn main() { #[cfg(not(any( feature = "max_level_off", feature = "max_level_error", From 6c2dade6055a98c740c8201d4b94bc6b21a4aa1a Mon Sep 17 00:00:00 2001 From: KodrAus Date: Wed, 20 Mar 2024 08:11:55 +1000 Subject: [PATCH 199/280] add some clarifications to the library docs --- src/lib.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 6b5eafbf4..69c627a8e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -40,6 +40,8 @@ //! [`debug!`]: ./macro.debug.html //! [`trace!`]: ./macro.trace.html //! [`println!`]: https://doc.rust-lang.org/stable/std/macro.println.html +//! +//! Avoid writing expressions with side-effects in log statements. They may not be evaluated. //! //! ## In libraries //! @@ -1149,6 +1151,11 @@ pub trait Log: Sync + Send { fn log(&self, record: &Record); /// Flushes any buffered records. + /// + /// # For implementors + /// + /// This method isn't called automatically by the `log!` macros. + /// It can be called manually on shut-down to ensure any in-flight records are flushed. fn flush(&self); } From adb7b53e293f7f654e3e6a2d6d1cc3a8c1d46cb7 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Wed, 20 Mar 2024 08:13:24 +1000 Subject: [PATCH 200/280] run fmt --- src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 69c627a8e..17e9fd0dd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -40,7 +40,7 @@ //! [`debug!`]: ./macro.debug.html //! [`trace!`]: ./macro.trace.html //! [`println!`]: https://doc.rust-lang.org/stable/std/macro.println.html -//! +//! //! Avoid writing expressions with side-effects in log statements. They may not be evaluated. //! //! ## In libraries @@ -1151,9 +1151,9 @@ pub trait Log: Sync + Send { fn log(&self, record: &Record); /// Flushes any buffered records. - /// + /// /// # For implementors - /// + /// /// This method isn't called automatically by the `log!` macros. /// It can be called manually on shut-down to ensure any in-flight records are flushed. fn flush(&self); From 90edfc3b17dd065cc14d403aed3b2360e397ff96 Mon Sep 17 00:00:00 2001 From: Divkov575 Date: Fri, 22 Mar 2024 21:02:17 -0400 Subject: [PATCH 201/280] (filters.rs & line_numbers.rs -> integration.rs) --- Cargo.toml | 12 ++-- tests/filters.rs | 90 -------------------------- tests/integration.rs | 143 ++++++++++++++++++++++++++++++++++++++++++ tests/line_numbers.rs | 65 ------------------- tests/src/lib.rs | 7 +-- 5 files changed, 149 insertions(+), 168 deletions(-) delete mode 100644 tests/filters.rs create mode 100644 tests/integration.rs delete mode 100644 tests/line_numbers.rs diff --git a/Cargo.toml b/Cargo.toml index 03eb08ee1..25e571279 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,14 +20,9 @@ edition = "2021" features = ["std", "serde", "kv_std", "kv_sval", "kv_serde"] [[test]] -name = "filters" -path = "tests/filters.rs" -harness = false - -[[test]] -name = "line_numbers" -path = "tests/line_numbers.rs" -harness = false +name = "integration" +path = "tests/integration.rs" +harness = true [[test]] name = "macros" @@ -64,6 +59,7 @@ kv_unstable_std = ["kv_std", "kv_unstable"] kv_unstable_serde = ["kv_serde", "kv_unstable_std"] [dependencies] +lazy_static = "1.4.0" serde = { version = "1.0", optional = true, default-features = false } sval = { version = "2.1", optional = true, default-features = false } sval_ref = { version = "2.1", optional = true, default-features = false } diff --git a/tests/filters.rs b/tests/filters.rs deleted file mode 100644 index 3e0810d07..000000000 --- a/tests/filters.rs +++ /dev/null @@ -1,90 +0,0 @@ -#![allow(dead_code, unused_imports)] - -use log::{debug, error, info, trace, warn, Level, LevelFilter, Log, Metadata, Record}; -use std::sync::{Arc, Mutex}; - -#[cfg(feature = "std")] -use log::set_boxed_logger; - -#[cfg(not(feature = "std"))] -fn set_boxed_logger(logger: Box) -> Result<(), log::SetLoggerError> { - log::set_logger(Box::leak(logger)) -} - -struct State { - last_log: Mutex>, -} - -struct Logger(Arc); - -impl Log for Logger { - fn enabled(&self, _: &Metadata) -> bool { - true - } - - fn log(&self, record: &Record) { - *self.0.last_log.lock().unwrap() = Some(record.level()); - } - fn flush(&self) {} -} - -#[cfg_attr(lib_build, test)] -fn main() { - // These tests don't really make sense when static - // max level filtering is applied - #[cfg(not(any( - feature = "max_level_off", - feature = "max_level_error", - feature = "max_level_warn", - feature = "max_level_info", - feature = "max_level_debug", - feature = "max_level_trace", - feature = "release_max_level_off", - feature = "release_max_level_error", - feature = "release_max_level_warn", - feature = "release_max_level_info", - feature = "release_max_level_debug", - feature = "release_max_level_trace", - )))] - { - let me = Arc::new(State { - last_log: Mutex::new(None), - }); - let a = me.clone(); - set_boxed_logger(Box::new(Logger(me))).unwrap(); - - test(&a, LevelFilter::Off); - test(&a, LevelFilter::Error); - test(&a, LevelFilter::Warn); - test(&a, LevelFilter::Info); - test(&a, LevelFilter::Debug); - test(&a, LevelFilter::Trace); - } -} - -fn test(a: &State, filter: LevelFilter) { - log::set_max_level(filter); - error!(""); - last(a, t(Level::Error, filter)); - warn!(""); - last(a, t(Level::Warn, filter)); - info!(""); - last(a, t(Level::Info, filter)); - debug!(""); - last(a, t(Level::Debug, filter)); - trace!(""); - last(a, t(Level::Trace, filter)); - - fn t(lvl: Level, filter: LevelFilter) -> Option { - if lvl <= filter { - Some(lvl) - } else { - None - } - } -} - -fn last(state: &State, expected: Option) { - let lvl = state.last_log.lock().unwrap().take(); - assert_eq!(lvl, expected); -} diff --git a/tests/integration.rs b/tests/integration.rs new file mode 100644 index 000000000..98abc23d0 --- /dev/null +++ b/tests/integration.rs @@ -0,0 +1,143 @@ +#![allow(dead_code, unused_imports)] + +use lazy_static::lazy_static; +use log::{debug, error, info, trace, warn, Level, LevelFilter, Log, Metadata, Record}; +use std::mem::MaybeUninit; +use std::sync::atomic::AtomicBool; +use std::sync::{Arc, Mutex}; + +#[cfg(feature = "std")] +use log::set_boxed_logger; + +#[cfg(not(feature = "std"))] +fn set_boxed_logger(logger: Box) -> Result<(), log::SetLoggerError> { + log::set_logger(Box::leak(logger)) +} + +struct State { + last_log_level: Mutex>, + last_log_location: Mutex>, +} + +struct Logger(Arc); + +impl Log for Logger { + fn enabled(&self, _: &Metadata) -> bool { + true + } + + fn log(&self, record: &Record) { + *self.0.last_log_level.lock().unwrap() = Some(record.level()); + *self.0.last_log_location.lock().unwrap() = record.line(); + } + fn flush(&self) {} +} + +static mut setup_state: Mutex = Mutex::new(false); + +lazy_static! { + static ref a: Arc = Arc::new(State { + last_log_level: Mutex::new(None), + last_log_location: Mutex::new(None), + }); +} + +fn setup() { + unsafe { + let mut guard = setup_state.lock().unwrap(); + if *guard == false { + set_boxed_logger(Box::new(Logger(a.clone()))).unwrap(); + *guard = true; + } + } +} + +#[test] +fn filters() { + // These tests don't really make sense when static + // max level filtering is applied + #[cfg(not(any( + feature = "max_level_off", + feature = "max_level_error", + feature = "max_level_warn", + feature = "max_level_info", + feature = "max_level_debug", + feature = "max_level_trace", + feature = "release_max_level_off", + feature = "release_max_level_error", + feature = "release_max_level_warn", + feature = "release_max_level_info", + feature = "release_max_level_debug", + feature = "release_max_level_trace", + )))] + { + setup(); + + test_filter(&a, LevelFilter::Off); + test_filter(&a, LevelFilter::Error); + test_filter(&a, LevelFilter::Warn); + test_filter(&a, LevelFilter::Info); + test_filter(&a, LevelFilter::Debug); + test_filter(&a, LevelFilter::Trace); + } + + fn test_filter(b: &State, filter: LevelFilter) { + log::set_max_level(filter); + error!(""); + last(b, t(Level::Error, filter)); + warn!(""); + last(b, t(Level::Warn, filter)); + info!(""); + last(b, t(Level::Info, filter)); + debug!(""); + last(b, t(Level::Debug, filter)); + trace!(""); + last(b, t(Level::Trace, filter)); + + fn last(state: &State, expected: Option) { + let lvl = state.last_log_level.lock().unwrap().take(); + assert_eq!(lvl, expected); + } + + fn t(lvl: Level, filter: LevelFilter) -> Option { + if lvl <= filter { + Some(lvl) + } else { + None + } + } + } +} + +#[test] +fn line_numbers() { + #[cfg(not(any( + feature = "max_level_off", + feature = "max_level_error", + feature = "max_level_warn", + feature = "max_level_info", + feature = "max_level_debug", + feature = "max_level_trace", + feature = "release_max_level_off", + feature = "release_max_level_error", + feature = "release_max_level_warn", + feature = "release_max_level_info", + feature = "release_max_level_debug", + feature = "release_max_level_trace", + )))] + { + setup(); + log::set_max_level(LevelFilter::Trace); + + info!(""); // ensure check_line function follows log macro + check_log_location(&a); + } + #[track_caller] + fn check_log_location(state: &State) { + // gets check_line calling location -> compares w/ location preserved in most recent log + // ensure check_line function follows log macro + let location = std::panic::Location::caller().line(); + let line_number = state.last_log_location.lock().unwrap().take().unwrap(); + assert_eq!(line_number, location - 1); + } +} diff --git a/tests/line_numbers.rs b/tests/line_numbers.rs deleted file mode 100644 index 41fb1537d..000000000 --- a/tests/line_numbers.rs +++ /dev/null @@ -1,65 +0,0 @@ -// ensure line number (from log!() calling position) is correctly within log record - -#![allow(dead_code, unused_imports)] - -use log::{info, LevelFilter, Log, Metadata, Record}; -use std::sync::{Arc, Mutex}; - -#[cfg(feature = "std")] -use log::set_boxed_logger; - -#[cfg(not(feature = "std"))] -fn set_boxed_logger(logger: Box) -> Result<(), log::SetLoggerError> { - log::set_logger(Box::leak(logger)) -} - -struct State { - last_log: Mutex>, -} - -struct Logger(Arc); - -impl Log for Logger { - fn enabled(&self, _: &Metadata) -> bool { - true - } - - fn log(&self, record: &Record) { - *self.0.last_log.lock().unwrap() = record.line(); - } - - fn flush(&self) {} -} - -#[cfg_attr(lib_build, test)] -fn main() { - #[cfg(not(any( - feature = "max_level_off", - feature = "max_level_error", - feature = "max_level_warn", - feature = "max_level_info", - feature = "max_level_debug", - feature = "max_level_trace", - feature = "release_max_level_off", - feature = "release_max_level_error", - feature = "release_max_level_warn", - feature = "release_max_level_info", - feature = "release_max_level_debug", - feature = "release_max_level_trace", - )))] - { - let default_state = Arc::new(State { - last_log: Mutex::new(None), - }); - let state = default_state.clone(); - set_boxed_logger(Box::new(Logger(default_state))).unwrap(); - log::set_max_level(LevelFilter::Trace); - - info!(""); - check_line(&state, 58); - } - fn check_line(state: &State, expected: u32) { - let line_number = state.last_log.lock().unwrap().take().unwrap(); - assert_eq!(line_number, expected); - } -} diff --git a/tests/src/lib.rs b/tests/src/lib.rs index 795f60651..951fc2430 100644 --- a/tests/src/lib.rs +++ b/tests/src/lib.rs @@ -6,13 +6,10 @@ #![allow(dead_code)] #[cfg(test)] -#[path = "../filters.rs"] -mod filters; +#[path = "../integration.rs"] +mod integration; #[cfg(test)] #[path = "../macros.rs"] mod macros; -#[cfg(test)] -#[path = "../line_numbers.rs"] -mod line_numbers; From 2cec229e047e6c5de87302c2b5dda6c0084ed6b6 Mon Sep 17 00:00:00 2001 From: Christian Iversen Date: Sat, 23 Mar 2024 10:46:13 +0100 Subject: [PATCH 202/280] Add links to `colog` crate, which provides logging with reasonable defaults, and customizable styling --- README.md | 1 + src/lib.rs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/README.md b/README.md index d6a08f558..d4a08b12b 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,7 @@ There are many available implementations to choose from, here are some options: * Simple minimal loggers: * [`env_logger`](https://docs.rs/env_logger/*/env_logger/) + * [`colog`](https://docs.rs/colog/*/colog/) * [`simple_logger`](https://docs.rs/simple_logger/*/simple_logger/) * [`simplelog`](https://docs.rs/simplelog/*/simplelog/) * [`pretty_env_logger`](https://docs.rs/pretty_env_logger/*/pretty_env_logger/) diff --git a/src/lib.rs b/src/lib.rs index 17e9fd0dd..d636dc835 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -135,6 +135,7 @@ //! //! * Simple minimal loggers: //! * [env_logger] +//! * [colog] //! * [simple_logger] //! * [simplelog] //! * [pretty_env_logger] @@ -310,6 +311,7 @@ //! [`try_set_logger_raw`]: fn.try_set_logger_raw.html //! [`shutdown_logger_raw`]: fn.shutdown_logger_raw.html //! [env_logger]: https://docs.rs/env_logger/*/env_logger/ +//! [colog]: https://docs.rs/colog/*/colog/ //! [simple_logger]: https://github.com/borntyping/rust-simple_logger //! [simplelog]: https://github.com/drakulix/simplelog.rs //! [pretty_env_logger]: https://docs.rs/pretty_env_logger/*/pretty_env_logger/ From 36b1a1cac9babeb6c854ef5ee23931838df1aaa5 Mon Sep 17 00:00:00 2001 From: Divkov575 Date: Sun, 24 Mar 2024 10:39:34 -0400 Subject: [PATCH 203/280] combined tests test_filter & test_line_number -> 1 main function --- tests/integration.rs | 116 +++++++++++++++---------------------------- 1 file changed, 41 insertions(+), 75 deletions(-) diff --git a/tests/integration.rs b/tests/integration.rs index 98abc23d0..7b8c1be0f 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -1,9 +1,6 @@ #![allow(dead_code, unused_imports)] -use lazy_static::lazy_static; use log::{debug, error, info, trace, warn, Level, LevelFilter, Log, Metadata, Record}; -use std::mem::MaybeUninit; -use std::sync::atomic::AtomicBool; use std::sync::{Arc, Mutex}; #[cfg(feature = "std")] @@ -32,28 +29,9 @@ impl Log for Logger { } fn flush(&self) {} } - -static mut setup_state: Mutex = Mutex::new(false); - -lazy_static! { - static ref a: Arc = Arc::new(State { - last_log_level: Mutex::new(None), - last_log_location: Mutex::new(None), - }); -} - -fn setup() { - unsafe { - let mut guard = setup_state.lock().unwrap(); - if *guard == false { - set_boxed_logger(Box::new(Logger(a.clone()))).unwrap(); - *guard = true; - } - } -} - +// #[cfg_attr(lib_build, test)] #[test] -fn filters() { +fn main() { // These tests don't really make sense when static // max level filtering is applied #[cfg(not(any( @@ -71,7 +49,12 @@ fn filters() { feature = "release_max_level_trace", )))] { - setup(); + let me = Arc::new(State { + last_log_level: Mutex::new(None), + last_log_location: Mutex::new(None), + }); + let a = me.clone(); + set_boxed_logger(Box::new(Logger(me))).unwrap(); test_filter(&a, LevelFilter::Off); test_filter(&a, LevelFilter::Error); @@ -79,65 +62,48 @@ fn filters() { test_filter(&a, LevelFilter::Info); test_filter(&a, LevelFilter::Debug); test_filter(&a, LevelFilter::Trace); - } - - fn test_filter(b: &State, filter: LevelFilter) { - log::set_max_level(filter); - error!(""); - last(b, t(Level::Error, filter)); - warn!(""); - last(b, t(Level::Warn, filter)); - info!(""); - last(b, t(Level::Info, filter)); - debug!(""); - last(b, t(Level::Debug, filter)); - trace!(""); - last(b, t(Level::Trace, filter)); - fn last(state: &State, expected: Option) { - let lvl = state.last_log_level.lock().unwrap().take(); - assert_eq!(lvl, expected); - } + test_line_numbers(&a); + } +} - fn t(lvl: Level, filter: LevelFilter) -> Option { - if lvl <= filter { - Some(lvl) - } else { - None - } +fn test_filter(a: &State, filter: LevelFilter) { + // tests to ensure logs with a level beneath 'max_level' are filtered out + log::set_max_level(filter); + error!(""); + last(a, t(Level::Error, filter)); + warn!(""); + last(a, t(Level::Warn, filter)); + info!(""); + last(a, t(Level::Info, filter)); + debug!(""); + last(a, t(Level::Debug, filter)); + trace!(""); + last(a, t(Level::Trace, filter)); + + fn t(lvl: Level, filter: LevelFilter) -> Option { + if lvl <= filter { + Some(lvl) + } else { + None } } + fn last(state: &State, expected: Option) { + let lvl = state.last_log_level.lock().unwrap().take(); + assert_eq!(lvl, expected); + } } -#[test] -fn line_numbers() { - #[cfg(not(any( - feature = "max_level_off", - feature = "max_level_error", - feature = "max_level_warn", - feature = "max_level_info", - feature = "max_level_debug", - feature = "max_level_trace", - feature = "release_max_level_off", - feature = "release_max_level_error", - feature = "release_max_level_warn", - feature = "release_max_level_info", - feature = "release_max_level_debug", - feature = "release_max_level_trace", - )))] - { - setup(); - log::set_max_level(LevelFilter::Trace); +fn test_line_numbers(state: &State) { + log::set_max_level(LevelFilter::Trace); + + info!(""); // ensure check_line function follows log macro + check_log_location(&state); - info!(""); // ensure check_line function follows log macro - check_log_location(&a); - } #[track_caller] fn check_log_location(state: &State) { - // gets check_line calling location -> compares w/ location preserved in most recent log - // ensure check_line function follows log macro - let location = std::panic::Location::caller().line(); - let line_number = state.last_log_location.lock().unwrap().take().unwrap(); + let location = std::panic::Location::caller().line(); // get function calling location + let line_number = state.last_log_location.lock().unwrap().take().unwrap(); // get location of most recent log assert_eq!(line_number, location - 1); } } From 3aea361cffdffa60d58f3eef538433696666a64f Mon Sep 17 00:00:00 2001 From: Divkov575 Date: Sun, 24 Mar 2024 10:59:20 -0400 Subject: [PATCH 204/280] fmt + change test harness + remove (unnecessary) lazy_static from dev-deps --- Cargo.toml | 3 +-- tests/integration.rs | 3 +-- tests/src/lib.rs | 1 - 3 files changed, 2 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 25e571279..72fcdb0e4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,7 @@ features = ["std", "serde", "kv_std", "kv_sval", "kv_serde"] [[test]] name = "integration" path = "tests/integration.rs" -harness = true +harness = false [[test]] name = "macros" @@ -59,7 +59,6 @@ kv_unstable_std = ["kv_std", "kv_unstable"] kv_unstable_serde = ["kv_serde", "kv_unstable_std"] [dependencies] -lazy_static = "1.4.0" serde = { version = "1.0", optional = true, default-features = false } sval = { version = "2.1", optional = true, default-features = false } sval_ref = { version = "2.1", optional = true, default-features = false } diff --git a/tests/integration.rs b/tests/integration.rs index 7b8c1be0f..7bf456e02 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -29,8 +29,7 @@ impl Log for Logger { } fn flush(&self) {} } -// #[cfg_attr(lib_build, test)] -#[test] +#[cfg_attr(lib_build, test)] fn main() { // These tests don't really make sense when static // max level filtering is applied diff --git a/tests/src/lib.rs b/tests/src/lib.rs index 951fc2430..a791a0c87 100644 --- a/tests/src/lib.rs +++ b/tests/src/lib.rs @@ -12,4 +12,3 @@ mod integration; #[cfg(test)] #[path = "../macros.rs"] mod macros; - From 17b73a485bf41f6be0c588f90f1455727310ace7 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Fri, 29 Mar 2024 21:12:20 +1000 Subject: [PATCH 205/280] clarify the actual set of functions that can race in _racy variants --- src/lib.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index d636dc835..9fba82056 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1243,13 +1243,13 @@ pub fn set_max_level(level: LevelFilter) { /// /// # Safety /// -/// This function is only safe to call when no other level setting function is -/// called while this function still executes. +/// This function is only safe to call when it cannot race with any other +/// calls to `set_max_level` or `set_max_level_racy`. /// /// This can be upheld by (for example) making sure that **there are no other /// threads**, and (on embedded) that **interrupts are disabled**. /// -/// Is is safe to use all other logging functions while this function runs +/// It is safe to use all other logging functions while this function runs /// (including all logging macros). /// /// [`set_max_level`]: fn.set_max_level.html @@ -1403,8 +1403,8 @@ where /// /// # Safety /// -/// This function is only safe to call when no other logger initialization -/// function is called while this function still executes. +/// This function is only safe to call when it cannot race with any other +/// calls to `set_logger` or `set_logger_racy`. /// /// This can be upheld by (for example) making sure that **there are no other /// threads**, and (on embedded) that **interrupts are disabled**. From 54eebd2f74c6f98e5979b098f832d24b0dcaeda7 Mon Sep 17 00:00:00 2001 From: Alec Rohloff Date: Fri, 29 Mar 2024 18:07:37 -0400 Subject: [PATCH 206/280] Replace deprecated std::sync::atomic::spin_loop_hint() --- src/lib.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index d636dc835..30ffc142e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1384,9 +1384,7 @@ where } INITIALIZING => { while STATE.load(Ordering::SeqCst) == INITIALIZING { - // TODO: replace with `hint::spin_loop` once MSRV is 1.49.0. - #[allow(deprecated)] - std::sync::atomic::spin_loop_hint(); + std::hint::spin_loop(); } Err(SetLoggerError(())) } From 10ab47209a178499084c8e77798d460c76680aac Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Sun, 31 Mar 2024 20:16:41 +0200 Subject: [PATCH 207/280] Check usage of max_level features With this change log will to fail to compile if two or more (release_)max_level_* features are used. --- src/lib.rs | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 81095bca8..19f44188c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -346,6 +346,45 @@ #![cfg_attr(rustbuild, feature(staged_api, rustc_private))] #![cfg_attr(rustbuild, unstable(feature = "rustc_private", issue = "27812"))] +#[cfg(any( + all(feature = "max_level_off", feature = "max_level_error"), + all(feature = "max_level_off", feature = "max_level_warn"), + all(feature = "max_level_off", feature = "max_level_info"), + all(feature = "max_level_off", feature = "max_level_debug"), + all(feature = "max_level_off", feature = "max_level_trace"), + all(feature = "max_level_error", feature = "max_level_warn"), + all(feature = "max_level_error", feature = "max_level_info"), + all(feature = "max_level_error", feature = "max_level_debug"), + all(feature = "max_level_error", feature = "max_level_trace"), + all(feature = "max_level_warn", feature = "max_level_info"), + all(feature = "max_level_warn", feature = "max_level_debug"), + all(feature = "max_level_warn", feature = "max_level_trace"), + all(feature = "max_level_info", feature = "max_level_debug"), + all(feature = "max_level_info", feature = "max_level_trace"), + all(feature = "max_level_debug", feature = "max_level_trace"), +))] +compile_error!("multiple max_level_* features set"); + +#[rustfmt::skip] +#[cfg(any( + all(feature = "release_max_level_off", feature = "release_max_level_error"), + all(feature = "release_max_level_off", feature = "release_max_level_warn"), + all(feature = "release_max_level_off", feature = "release_max_level_info"), + all(feature = "release_max_level_off", feature = "release_max_level_debug"), + all(feature = "release_max_level_off", feature = "release_max_level_trace"), + all(feature = "release_max_level_error", feature = "release_max_level_warn"), + all(feature = "release_max_level_error", feature = "release_max_level_info"), + all(feature = "release_max_level_error", feature = "release_max_level_debug"), + all(feature = "release_max_level_error", feature = "release_max_level_trace"), + all(feature = "release_max_level_warn", feature = "release_max_level_info"), + all(feature = "release_max_level_warn", feature = "release_max_level_debug"), + all(feature = "release_max_level_warn", feature = "release_max_level_trace"), + all(feature = "release_max_level_info", feature = "release_max_level_debug"), + all(feature = "release_max_level_info", feature = "release_max_level_trace"), + all(feature = "release_max_level_debug", feature = "release_max_level_trace"), +))] +compile_error!("multiple release_max_level_* features set"); + #[cfg(all(not(feature = "std"), not(test)))] extern crate core as std; From 710560ecb7035a6baf1fd9d97d7f09d0cc075006 Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Sun, 31 Mar 2024 20:26:59 +0200 Subject: [PATCH 208/280] Don't use --all-features in CI --- .github/workflows/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 3c263a434..f1eab4b88 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -41,7 +41,7 @@ jobs: rustup default ${{ matrix.rust }} - run: cargo test --verbose - run: cargo test --verbose --no-default-features - - run: cargo test --verbose --all-features + - run: cargo test --verbose --features std,serde,sval,sval_ref,value-bag,kv,kv_std,kv_sval,kv_serde - run: cargo test --verbose --features serde - run: cargo test --verbose --features std - run: cargo test --verbose --features kv @@ -92,7 +92,7 @@ jobs: rustup default stable rustup component add rust-docs - name: Run rustdoc - run: RUSTDOCFLAGS="-D warnings" cargo doc --verbose --all-features + run: RUSTDOCFLAGS="-D warnings" cargo doc --verbose --features std,serde,sval,sval_ref,value-bag,kv,kv_std,kv_sval,kv_serde features: name: Feature check From 1307ade1122549badf2b8fdd10c11e519eaa029a Mon Sep 17 00:00:00 2001 From: Thomas de Zeeuw Date: Sun, 31 Mar 2024 20:32:17 +0200 Subject: [PATCH 209/280] Remove unneeded import Already imported by super::* --- src/kv/source.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/kv/source.rs b/src/kv/source.rs index 0ca267ce3..f463e6d2b 100644 --- a/src/kv/source.rs +++ b/src/kv/source.rs @@ -406,8 +406,6 @@ mod std_support { #[cfg(test)] mod tests { - use std::collections::{BTreeMap, HashMap}; - use crate::kv::value; use super::*; From 507b672660288f0223edb6353d34f8733fa0a2f4 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Tue, 25 Jun 2024 10:58:09 +1000 Subject: [PATCH 210/280] loosen orderings for logger initialization --- src/lib.rs | 25 +++++++++---------------- tests/Cargo.toml | 3 +++ 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 19f44188c..72f825d1f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -341,10 +341,6 @@ #![warn(missing_docs)] #![deny(missing_debug_implementations, unconditional_recursion)] #![cfg_attr(all(not(feature = "std"), not(test)), no_std)] -// When compiled for the rustc compiler itself we want to make sure that this is -// an unstable crate -#![cfg_attr(rustbuild, feature(staged_api, rustc_private))] -#![cfg_attr(rustbuild, unstable(feature = "rustc_private", issue = "27812"))] #[cfg(any( all(feature = "max_level_off", feature = "max_level_error"), @@ -1405,24 +1401,21 @@ fn set_logger_inner(make_logger: F) -> Result<(), SetLoggerError> where F: FnOnce() -> &'static dyn Log, { - let old_state = match STATE.compare_exchange( + match STATE.compare_exchange( UNINITIALIZED, INITIALIZING, - Ordering::SeqCst, - Ordering::SeqCst, + Ordering::Acquire, + Ordering::Relaxed, ) { - Ok(s) | Err(s) => s, - }; - match old_state { - UNINITIALIZED => { + Ok(UNINITIALIZED) => { unsafe { LOGGER = make_logger(); } - STATE.store(INITIALIZED, Ordering::SeqCst); + STATE.store(INITIALIZED, Ordering::Release); Ok(()) } - INITIALIZING => { - while STATE.load(Ordering::SeqCst) == INITIALIZING { + Err(INITIALIZING) => { + while STATE.load(Ordering::Relaxed) == INITIALIZING { std::hint::spin_loop(); } Err(SetLoggerError(())) @@ -1451,10 +1444,10 @@ where /// /// [`set_logger`]: fn.set_logger.html pub unsafe fn set_logger_racy(logger: &'static dyn Log) -> Result<(), SetLoggerError> { - match STATE.load(Ordering::SeqCst) { + match STATE.load(Ordering::Acquire) { UNINITIALIZED => { LOGGER = logger; - STATE.store(INITIALIZED, Ordering::SeqCst); + STATE.store(INITIALIZED, Ordering::Release); Ok(()) } INITIALIZING => { diff --git a/tests/Cargo.toml b/tests/Cargo.toml index 8754bb16a..bc8621558 100644 --- a/tests/Cargo.toml +++ b/tests/Cargo.toml @@ -5,6 +5,9 @@ edition = "2021" publish = false build = "src/build.rs" +[lints.rust] +unexpected_cfgs = { level = "allow", check-cfg = ['cfg(lib_build)'] } + [features] std = ["log/std"] kv = ["log/kv"] From c9e5e13e9b02ec80e784c6fe4deacdc8f3194fca Mon Sep 17 00:00:00 2001 From: KodrAus Date: Tue, 25 Jun 2024 11:16:21 +1000 Subject: [PATCH 211/280] use Location::caller() for file and line info --- src/__private_api.rs | 26 ++++++++++++-------------- src/lib.rs | 4 ---- src/macros.rs | 6 ++---- tests/Cargo.toml | 3 +++ 4 files changed, 17 insertions(+), 22 deletions(-) diff --git a/src/__private_api.rs b/src/__private_api.rs index fd0a5a762..11bc2fc1c 100644 --- a/src/__private_api.rs +++ b/src/__private_api.rs @@ -3,7 +3,8 @@ use self::sealed::KVs; use crate::{Level, Metadata, Record}; use std::fmt::Arguments; -pub use std::{file, format_args, line, module_path, stringify}; +use std::panic::Location; +pub use std::{format_args, module_path, stringify}; #[cfg(not(feature = "kv"))] pub type Value<'a> = &'a str; @@ -36,8 +37,7 @@ impl<'a> KVs<'a> for () { fn log_impl( args: Arguments, level: Level, - &(target, module_path, file): &(&str, &'static str, &'static str), - line: u32, + &(target, module_path, loc): &(&str, &'static str, &'static Location), kvs: Option<&[(&str, Value)]>, ) { #[cfg(not(feature = "kv"))] @@ -52,8 +52,8 @@ fn log_impl( .level(level) .target(target) .module_path_static(Some(module_path)) - .file_static(Some(file)) - .line(Some(line)); + .file_static(Some(loc.file())) + .line(Some(loc.line())); #[cfg(feature = "kv")] builder.key_values(&kvs); @@ -64,25 +64,23 @@ fn log_impl( pub fn log<'a, K>( args: Arguments, level: Level, - target_module_path_and_file: &(&str, &'static str, &'static str), - line: u32, + target_module_path_and_loc: &(&str, &'static str, &'static Location), kvs: K, ) where K: KVs<'a>, { - log_impl( - args, - level, - target_module_path_and_file, - line, - kvs.into_kvs(), - ) + log_impl(args, level, target_module_path_and_loc, kvs.into_kvs()) } pub fn enabled(level: Level, target: &str) -> bool { crate::logger().enabled(&Metadata::builder().level(level).target(target).build()) } +#[track_caller] +pub fn loc() -> &'static Location<'static> { + Location::caller() +} + #[cfg(feature = "kv")] mod kv_support { use crate::kv; diff --git a/src/lib.rs b/src/lib.rs index 19f44188c..f9e6708fb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -341,10 +341,6 @@ #![warn(missing_docs)] #![deny(missing_debug_implementations, unconditional_recursion)] #![cfg_attr(all(not(feature = "std"), not(test)), no_std)] -// When compiled for the rustc compiler itself we want to make sure that this is -// an unstable crate -#![cfg_attr(rustbuild, feature(staged_api, rustc_private))] -#![cfg_attr(rustbuild, unstable(feature = "rustc_private", issue = "27812"))] #[cfg(any( all(feature = "max_level_off", feature = "max_level_error"), diff --git a/src/macros.rs b/src/macros.rs index 48a7447ef..87693f2b1 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -36,8 +36,7 @@ macro_rules! log { $crate::__private_api::log::<&_>( $crate::__private_api::format_args!($($arg)+), lvl, - &($target, $crate::__private_api::module_path!(), $crate::__private_api::file!()), - $crate::__private_api::line!(), + &($target, $crate::__private_api::module_path!(), $crate::__private_api::loc()), &[$(($crate::__log_key!($key), $crate::__log_value!($key $(:$capture)* = $($value)*))),+] ); } @@ -50,8 +49,7 @@ macro_rules! log { $crate::__private_api::log( $crate::__private_api::format_args!($($arg)+), lvl, - &($target, $crate::__private_api::module_path!(), $crate::__private_api::file!()), - $crate::__private_api::line!(), + &($target, $crate::__private_api::module_path!(), $crate::__private_api::loc()), (), ); } diff --git a/tests/Cargo.toml b/tests/Cargo.toml index 8754bb16a..bc8621558 100644 --- a/tests/Cargo.toml +++ b/tests/Cargo.toml @@ -5,6 +5,9 @@ edition = "2021" publish = false build = "src/build.rs" +[lints.rust] +unexpected_cfgs = { level = "allow", check-cfg = ['cfg(lib_build)'] } + [features] std = ["log/std"] kv = ["log/kv"] From d1a8306aadb88d56b74c73cdce4ef0153fb549cb Mon Sep 17 00:00:00 2001 From: KodrAus Date: Thu, 27 Jun 2024 07:33:32 +1000 Subject: [PATCH 212/280] prepare for 0.4.22 release --- CHANGELOG.md | 20 ++++++++++++++++++++ Cargo.toml | 2 +- src/lib.rs | 2 +- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 77633b170..2c89834df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,26 @@ ## [Unreleased] +## [0.4.22] - 2024-06-27 + +## What's Changed +* Add some clarifications to the library docs by @KodrAus in https://github.com/rust-lang/log/pull/620 +* Add links to `colog` crate by @chrivers in https://github.com/rust-lang/log/pull/621 +* adding line_number test + updating some testing infrastructure by @DIvkov575 in https://github.com/rust-lang/log/pull/619 +* Clarify the actual set of functions that can race in _racy variants by @KodrAus in https://github.com/rust-lang/log/pull/623 +* Replace deprecated std::sync::atomic::spin_loop_hint() by @Catamantaloedis in https://github.com/rust-lang/log/pull/625 +* Check usage of max_level features by @Thomasdezeeuw in https://github.com/rust-lang/log/pull/627 +* Remove unneeded import by @Thomasdezeeuw in https://github.com/rust-lang/log/pull/628 +* Loosen orderings for logger initialization in https://github.com/rust-lang/log/pull/632. Originally by @pwoolcoc in https://github.com/rust-lang/log/pull/599 +* Use Location::caller() for file and line info in https://github.com/rust-lang/log/pull/633. Originally by @Cassy343 in https://github.com/rust-lang/log/pull/520 + +## New Contributors +* @chrivers made their first contribution in https://github.com/rust-lang/log/pull/621 +* @DIvkov575 made their first contribution in https://github.com/rust-lang/log/pull/619 +* @Catamantaloedis made their first contribution in https://github.com/rust-lang/log/pull/625 + +**Full Changelog**: https://github.com/rust-lang/log/compare/0.4.21...0.4.22 + ## [0.4.21] - 2024-02-27 ## What's Changed diff --git a/Cargo.toml b/Cargo.toml index 72fcdb0e4..c3ac8c67a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "log" -version = "0.4.21" # remember to update html_root_url +version = "0.4.22" # remember to update html_root_url authors = ["The Rust Project Developers"] license = "MIT OR Apache-2.0" readme = "README.md" diff --git a/src/lib.rs b/src/lib.rs index 72f825d1f..6b43a9ae1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -336,7 +336,7 @@ #![doc( html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://www.rust-lang.org/favicon.ico", - html_root_url = "https://docs.rs/log/0.4.21" + html_root_url = "https://docs.rs/log/0.4.22" )] #![warn(missing_docs)] #![deny(missing_debug_implementations, unconditional_recursion)] From 0aaa10df468fe18cc7dd16a2140e4c5b0a195b51 Mon Sep 17 00:00:00 2001 From: kleinmarb Date: Wed, 31 Jul 2024 22:35:17 +0200 Subject: [PATCH 213/280] Fix some typos --- .idea/.gitignore | 5 +++++ .idea/log.iml | 13 +++++++++++++ .idea/modules.xml | 8 ++++++++ .idea/vcs.xml | 6 ++++++ CHANGELOG.md | 8 ++++---- Cargo.toml | 4 ++-- rfcs/0296-structured-logging.md | 2 +- src/kv/mod.rs | 2 +- src/kv/value.rs | 10 +++++----- src/serde.rs | 6 +++--- tests/src/lib.rs | 2 +- 11 files changed, 49 insertions(+), 17 deletions(-) create mode 100644 .idea/.gitignore create mode 100644 .idea/log.iml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 000000000..b58b603fe --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,5 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ diff --git a/.idea/log.iml b/.idea/log.iml new file mode 100644 index 000000000..7a99ccf7a --- /dev/null +++ b/.idea/log.iml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 000000000..0882239c8 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 000000000..35eb1ddfb --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c89834df..83a72a879 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -64,7 +64,7 @@ ## [0.4.18] - 2023-05-28 -* fix markdown links (again) by @hellow554 in https://github.com/rust-lang/log/pull/513 +* fix Markdown links (again) by @hellow554 in https://github.com/rust-lang/log/pull/513 * add cargo doc to workflow by @hellow554 in https://github.com/rust-lang/log/pull/515 * Apply Clippy lints by @hellow554 in https://github.com/rust-lang/log/pull/516 * Replace ad-hoc eq_ignore_ascii_case with slice::eq_ignore_ascii_case by @glandium in https://github.com/rust-lang/log/pull/519 @@ -99,7 +99,7 @@ * Improvements to test coverage. * Improvements to documentation. * Add key-value support to the `log!` macros. -* Tighten `kv_unstable` internal dependencies so they don't bump past their current alpha. +* Tighten `kv_unstable` internal dependencies, so they don't bump past their current alpha. * Add a simple visit API to `kv_unstable`. * Support `NonZero*` integers as values in structured logging * Support static strings as keys in structured logging @@ -149,7 +149,7 @@ as either a map of `{key: value, ..}` or as a list of `[(key, value), ..]`. ### Fixed -* Fixed the `log!` macros so they work in expression context (this regressed in `0.4.9`, which has been yanked). +* Fixed the `log!` macros, so they work in expression context (this regressed in `0.4.9`, which has been yanked). ## [0.4.9] - 2019-12-12 (yanked) @@ -260,7 +260,7 @@ version using log 0.4.x to avoid losing module and file information. * The `logger` free function returns a reference to the logger implementation. This, along with the ability to construct `Record`s, makes it possible to bridge from another logging framework to this one without digging into the private internals of the crate. The standard `error!` `warn!`, - etc, macros now exclusively use the public API of the crate rather than "secret" internal APIs. + etc., macros now exclusively use the public API of the crate rather than "secret" internal APIs. * `Log::flush` has been added to allow crates to tell the logging implementation to ensure that all "in flight" log events have been persisted. This can be used, for example, just before an application exits to ensure that asynchronous log sinks finish their work. diff --git a/Cargo.toml b/Cargo.toml index c3ac8c67a..3fddf07a7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -72,10 +72,10 @@ sval = { version = "2.1" } sval_derive = { version = "2.1" } value-bag = { version = "1.7", features = ["test"] } -# NOTE: log doesn't actually depent on this crate. However our dependencies, +# NOTE: log doesn't actually depent on this crate. However, our dependencies, # serde and sval, dependent on version 1.0 of the crate, which has problem fixed # in 1.0.60, specifically in the following commit # https://github.com/dtolnay/proc-macro2/commit/e31d61910049e097afdd3d27c37786309082bdcb. -# By defining the crate as direct dependency we can increase it's minimal +# By defining the crate as direct dependency we can increase its minimal # version making the minimal (crate) version CI happy. proc-macro2 = { version = "1.0.63", default-features = false } diff --git a/rfcs/0296-structured-logging.md b/rfcs/0296-structured-logging.md index 3ee90a5cf..835588c6b 100644 --- a/rfcs/0296-structured-logging.md +++ b/rfcs/0296-structured-logging.md @@ -1633,7 +1633,7 @@ Structured logging is a paradigm that's supported by logging frameworks in many ## Rust -The `slog` library is a structured logging framework for Rust. Its API predates a stable `serde` crate so it defines its own traits that are similar to `serde::Serialize`. A log record consists of a rendered message and bag of structured key-value pairs. `slog` goes further than this RFC proposes by requiring callers of its `log!` macros to state whether key-values are owned or borrowed by the record, and whether the data is safe to share across threads. +The `slog` library is a structured logging framework for Rust. Its API predates a stable `serde` crate, so it defines its own traits that are similar to `serde::Serialize`. A log record consists of a rendered message and bag of structured key-value pairs. `slog` goes further than this RFC proposes by requiring callers of its `log!` macros to state whether key-values are owned or borrowed by the record, and whether the data is safe to share across threads. This RFC proposes an API that's inspired by `slog`, but doesn't directly support distinguishing between owned or borrowed key-value pairs. Everything is borrowed. That means the only way to send a `Record` to another thread is to serialize it into a different type. diff --git a/src/kv/mod.rs b/src/kv/mod.rs index 1ccb82514..8c71e0765 100644 --- a/src/kv/mod.rs +++ b/src/kv/mod.rs @@ -29,7 +29,7 @@ //! info!(a = 1; "Something of interest"); //! ``` //! -//! Key-values support the same shorthand identifer syntax as `format_args`: +//! Key-values support the same shorthand identifier syntax as `format_args`: //! //! ``` //! # use log::info; diff --git a/src/kv/value.rs b/src/kv/value.rs index 1511dd02e..b580ea3ff 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -101,7 +101,7 @@ impl<'v> ToValue for Value<'v> { /// Values provide a number of ways to be serialized. /// /// For basic types the [`Value::visit`] method can be used to extract the -/// underlying typed value. However this is limited in the amount of types +/// underlying typed value. However, this is limited in the amount of types /// supported (see the [`VisitValue`] trait methods). /// /// For more complex types one of the following traits can be used: @@ -373,13 +373,13 @@ impl_value_to_primitive![ ]; impl<'v> Value<'v> { - /// Try convert this value into an error. + /// Try to convert this value into an error. #[cfg(feature = "kv_std")] pub fn to_borrowed_error(&self) -> Option<&(dyn std::error::Error + 'static)> { self.inner.to_borrowed_error() } - /// Try convert this value into a borrowed string. + /// Try to convert this value into a borrowed string. pub fn to_borrowed_str(&self) -> Option<&str> { self.inner.to_borrowed_str() } @@ -433,7 +433,7 @@ mod std_support { } impl<'v> Value<'v> { - /// Try convert this value into a string. + /// Try to convert this value into a string. pub fn to_cow_str(&self) -> Option> { self.inner.to_str() } @@ -725,7 +725,7 @@ pub(in crate::kv) mod inner { 1. Conversions should always produce the same results. If a conversion here returns `Some`, then the same `value_bag`-based conversion must also. Of particular note here are floats to ints; they're - based on the standard library's `TryInto` conversions, which need to be convert to `i32` or `u32`, + based on the standard library's `TryInto` conversions, which need to be converted to `i32` or `u32`, and then to `f64`. 2. VisitValues should always be called in the same way. If a particular type of value calls `visit_i64`, then the same `value_bag`-based visitor must also. diff --git a/src/serde.rs b/src/serde.rs index 63bef7f97..db732395b 100644 --- a/src/serde.rs +++ b/src/serde.rs @@ -11,7 +11,7 @@ use crate::{Level, LevelFilter, LOG_LEVEL_NAMES}; use std::fmt; use std::str::{self, FromStr}; -// The Deserialize impls are handwritten to be case insensitive using FromStr. +// The Deserialize impls are handwritten to be case-insensitive using FromStr. impl Serialize for Level { fn serialize(&self, serializer: S) -> Result @@ -57,7 +57,7 @@ impl<'de> Deserialize<'de> for Level { where E: Error, { - // Case insensitive. + // Case-insensitive. FromStr::from_str(s).map_err(|_| Error::unknown_variant(s, &LOG_LEVEL_NAMES[1..])) } @@ -152,7 +152,7 @@ impl<'de> Deserialize<'de> for LevelFilter { where E: Error, { - // Case insensitive. + // Case-insensitive. FromStr::from_str(s).map_err(|_| Error::unknown_variant(s, &LOG_LEVEL_NAMES)) } diff --git a/tests/src/lib.rs b/tests/src/lib.rs index a791a0c87..a4835fabc 100644 --- a/tests/src/lib.rs +++ b/tests/src/lib.rs @@ -1,6 +1,6 @@ //! This crate is intentionally left empty. //! -//! We have an empty library depending on `log` here so we can run integration tests +//! We have an empty library depending on `log` here, so we can run integration tests //! on older compilers without depending on the unstable `no-dev-deps` flag. #![allow(dead_code)] From 0a47ca6da26b1576f573084f789bcedfa529a25b Mon Sep 17 00:00:00 2001 From: tison Date: Fri, 2 Aug 2024 20:26:16 +0800 Subject: [PATCH 214/280] Add logforth to implementation --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index d4a08b12b..aa6e9406a 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,7 @@ There are many available implementations to choose from, here are some options: * [`structured-logger`](https://docs.rs/structured-logger/latest/structured_logger/) * Complex configurable frameworks: * [`log4rs`](https://docs.rs/log4rs/*/log4rs/) + * [`logforth`](https://crates.io/crates/logforth) * [`fern`](https://docs.rs/fern/*/fern/) * Adaptors for other facilities: * [`syslog`](https://docs.rs/syslog/*/syslog/) From af182a981897a963fb0633f038e98b327b15ff05 Mon Sep 17 00:00:00 2001 From: tison Date: Fri, 2 Aug 2024 20:59:44 +0800 Subject: [PATCH 215/280] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index aa6e9406a..07a9d8b3a 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ There are many available implementations to choose from, here are some options: * [`structured-logger`](https://docs.rs/structured-logger/latest/structured_logger/) * Complex configurable frameworks: * [`log4rs`](https://docs.rs/log4rs/*/log4rs/) - * [`logforth`](https://crates.io/crates/logforth) + * [`logforth`](https://docs.rs/logforth/*/logforth/) * [`fern`](https://docs.rs/fern/*/fern/) * Adaptors for other facilities: * [`syslog`](https://docs.rs/syslog/*/syslog/) From 1879fc475f9b7078201cccd247c776ee90a68b89 Mon Sep 17 00:00:00 2001 From: kleinmarb Date: Fri, 2 Aug 2024 15:13:34 +0200 Subject: [PATCH 216/280] Remove .idea directory --- .idea/.gitignore | 5 ----- .idea/log.iml | 13 ------------- .idea/modules.xml | 8 -------- .idea/vcs.xml | 6 ------ 4 files changed, 32 deletions(-) delete mode 100644 .idea/.gitignore delete mode 100644 .idea/log.iml delete mode 100644 .idea/modules.xml delete mode 100644 .idea/vcs.xml diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index b58b603fe..000000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ diff --git a/.idea/log.iml b/.idea/log.iml deleted file mode 100644 index 7a99ccf7a..000000000 --- a/.idea/log.iml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 0882239c8..000000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 35eb1ddfb..000000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file From 3537507ed1a7fa193f985a1eeded4ea655d7aae8 Mon Sep 17 00:00:00 2001 From: kleinmarb Date: Fri, 2 Aug 2024 15:14:14 +0200 Subject: [PATCH 217/280] Add .idea to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 2c96eb1b6..150301459 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ target/ Cargo.lock +.idea/ From e52de505dfe85a3be9eef8e87980509eedabb295 Mon Sep 17 00:00:00 2001 From: Asuna Date: Tue, 8 Oct 2024 13:28:14 +0800 Subject: [PATCH 218/280] Add `spdlog-rs` link to README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 07a9d8b3a..dab20c8a4 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,7 @@ There are many available implementations to choose from, here are some options: * [`log4rs`](https://docs.rs/log4rs/*/log4rs/) * [`logforth`](https://docs.rs/logforth/*/logforth/) * [`fern`](https://docs.rs/fern/*/fern/) + * [`spdlog-rs`](https://docs.rs/spdlog-rs/*/spdlog/) * Adaptors for other facilities: * [`syslog`](https://docs.rs/syslog/*/syslog/) * [`systemd-journal-logger`](https://docs.rs/systemd-journal-logger/*/systemd_journal_logger/) From 9ab7fea8af7e48399d56dcc09fcd41a52fc06f28 Mon Sep 17 00:00:00 2001 From: tison Date: Wed, 13 Nov 2024 23:49:04 +0800 Subject: [PATCH 219/280] docs: Add logforth as an impl --- src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 6b43a9ae1..7e8e3f54e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -145,6 +145,7 @@ //! * [structured-logger] //! * Complex configurable frameworks: //! * [log4rs] +//! * [logforth] //! * [fern] //! * Adaptors for other facilities: //! * [syslog] @@ -321,6 +322,7 @@ //! [syslog]: https://docs.rs/syslog/*/syslog/ //! [slog-stdlog]: https://docs.rs/slog-stdlog/*/slog_stdlog/ //! [log4rs]: https://docs.rs/log4rs/*/log4rs/ +//! [logforth]: https://docs.rs/logforth/*/logforth/ //! [fern]: https://docs.rs/fern/*/fern/ //! [systemd-journal-logger]: https://docs.rs/systemd-journal-logger/*/systemd_journal_logger/ //! [android_log]: https://docs.rs/android_log/*/android_log/ From ac76985c47adb84c31cfa8a2cf103d4fd8c96792 Mon Sep 17 00:00:00 2001 From: Steven Roose Date: Wed, 13 Nov 2024 15:55:26 -0300 Subject: [PATCH 220/280] Add correct lifetime to kv::Value::to_borrowed_str --- src/kv/value.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kv/value.rs b/src/kv/value.rs index b580ea3ff..2b9ca2510 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -380,7 +380,7 @@ impl<'v> Value<'v> { } /// Try to convert this value into a borrowed string. - pub fn to_borrowed_str(&self) -> Option<&str> { + pub fn to_borrowed_str(&self) -> Option<&'v str> { self.inner.to_borrowed_str() } } From 3b14f1718259f39d22107f3a3a1f88198b3be3fb Mon Sep 17 00:00:00 2001 From: DDAN17 <55860416+DDAN-17@users.noreply.github.com> Date: Sun, 17 Nov 2024 02:47:21 +0000 Subject: [PATCH 221/280] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index dab20c8a4..310e585d9 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,7 @@ There are many available implementations to choose from, here are some options: * [`call_logger`](https://docs.rs/call_logger/*/call_logger/) * [`std-logger`](https://docs.rs/std-logger/*/std_logger/) * [`structured-logger`](https://docs.rs/structured-logger/latest/structured_logger/) + * [`clang_log`](https://docs.rs/clang_log/latest/clang_log) * Complex configurable frameworks: * [`log4rs`](https://docs.rs/log4rs/*/log4rs/) * [`logforth`](https://docs.rs/logforth/*/logforth/) From 937fc2799cb6e40ad924ecb9a1fc1ac6ba0039f5 Mon Sep 17 00:00:00 2001 From: DDAN17 <55860416+DDAN-17@users.noreply.github.com> Date: Sun, 17 Nov 2024 02:49:02 +0000 Subject: [PATCH 222/280] Update lib.rs --- src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 6b43a9ae1..e58eb8d3c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -143,6 +143,7 @@ //! * [flexi_logger] //! * [call_logger] //! * [structured-logger] +//! * [clang_log] //! * Complex configurable frameworks: //! * [log4rs] //! * [fern] @@ -332,6 +333,7 @@ //! [logcontrol-log]: https://docs.rs/logcontrol-log/*/logcontrol_log/ //! [log_err]: https://docs.rs/log_err/*/log_err/ //! [log-reload]: https://docs.rs/log-reload/*/log_reload/ +//! [clang_log]: https://docs.rs/clang_log/latest/clang_log #![doc( html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", From 87674d3a8dabee04ee8b52c6b0667a31735361e1 Mon Sep 17 00:00:00 2001 From: Brian Bosak Date: Fri, 6 Dec 2024 13:27:30 -0800 Subject: [PATCH 223/280] Bind lifetimes of &str returned from Key by the lifetime of 'k rather than the lifetime of the Key struct --- src/kv/key.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/kv/key.rs b/src/kv/key.rs index 9a64b956f..b0cea5cb1 100644 --- a/src/kv/key.rs +++ b/src/kv/key.rs @@ -45,7 +45,7 @@ impl<'k> Key<'k> { } /// Get a borrowed string from this key. - pub fn as_str(&self) -> &str { + pub fn as_str(&self) -> &'k str { self.key } } @@ -57,7 +57,7 @@ impl<'k> fmt::Display for Key<'k> { } impl<'k> AsRef for Key<'k> { - fn as_ref(&self) -> &str { + fn as_ref(&self) -> &'k str { self.as_str() } } From 134d252f0599d19070fd02f93600d48254e6f91f Mon Sep 17 00:00:00 2001 From: gbbosak <51209748+gbbosak@users.noreply.github.com> Date: Fri, 6 Dec 2024 21:45:57 +0000 Subject: [PATCH 224/280] Revert AsRef impl, as the feature needed for that isn't yet stable. --- src/kv/key.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kv/key.rs b/src/kv/key.rs index b0cea5cb1..5221c98f1 100644 --- a/src/kv/key.rs +++ b/src/kv/key.rs @@ -57,7 +57,7 @@ impl<'k> fmt::Display for Key<'k> { } impl<'k> AsRef for Key<'k> { - fn as_ref(&self) -> &'k str { + fn as_ref(&self) -> &str { self.as_str() } } From bbbd1424252eb5e6e6c6ca930483aa86a7b4f77e Mon Sep 17 00:00:00 2001 From: Tjardo Date: Sat, 21 Dec 2024 21:20:13 +0100 Subject: [PATCH 225/280] Add Ftail logger to README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 310e585d9..f8b544911 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,7 @@ There are many available implementations to choose from, here are some options: * [`std-logger`](https://docs.rs/std-logger/*/std_logger/) * [`structured-logger`](https://docs.rs/structured-logger/latest/structured_logger/) * [`clang_log`](https://docs.rs/clang_log/latest/clang_log) + * [`ftail`](https://docs.rs/ftail/latest/ftail/) * Complex configurable frameworks: * [`log4rs`](https://docs.rs/log4rs/*/log4rs/) * [`logforth`](https://docs.rs/logforth/*/logforth/) From 9b9c32c0ccfb7cfe98549551dbc4916bc14e6556 Mon Sep 17 00:00:00 2001 From: Tjardo Date: Sat, 21 Dec 2024 21:25:34 +0100 Subject: [PATCH 226/280] Add Ftail logger to lib.rs --- src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 3179268a3..2e70f3141 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -144,6 +144,7 @@ //! * [call_logger] //! * [structured-logger] //! * [clang_log] +//! * [ftail] //! * Complex configurable frameworks: //! * [log4rs] //! * [logforth] @@ -336,6 +337,7 @@ //! [log_err]: https://docs.rs/log_err/*/log_err/ //! [log-reload]: https://docs.rs/log-reload/*/log_reload/ //! [clang_log]: https://docs.rs/clang_log/latest/clang_log +//! [ftail]: https://docs.rs/ftail/latest/ftail #![doc( html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", From 7e79d7f5b3bdc85c5893ca3ad8b9d3a383c4f25c Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Mon, 23 Dec 2024 08:57:24 +1000 Subject: [PATCH 227/280] fix up key lifetimes and add method to try get a borrowed key --- src/kv/key.rs | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/kv/key.rs b/src/kv/key.rs index 5221c98f1..6e00a2ca8 100644 --- a/src/kv/key.rs +++ b/src/kv/key.rs @@ -35,6 +35,7 @@ impl ToKey for str { // If a new field (such as an optional index) is added to the key they must not affect comparison #[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Key<'k> { + // NOTE: This may become `Cow<'k, str>` key: &'k str, } @@ -45,9 +46,23 @@ impl<'k> Key<'k> { } /// Get a borrowed string from this key. - pub fn as_str(&self) -> &'k str { + /// + /// The lifetime of the returned string is bound to the borrow of `self` rather + /// than to `'k`. + pub fn as_str(&self) -> &str { self.key } + + /// Try get a borrowed string for the lifetime `'k` from this key. + /// + /// If the key is a borrow of a longer lived string, this method will return `Some`. + /// If the key is internally buffered, this method will return `None`. + pub fn to_borrowed_str(&self) -> Option<&'k str> { + // NOTE: If the internals of `Key` support buffering this + // won't be unconditionally `Some` anymore. We want to keep + // this option open + Some(self.key) + } } impl<'k> fmt::Display for Key<'k> { @@ -140,4 +155,9 @@ mod tests { fn key_from_string() { assert_eq!("a key", Key::from_str("a key").as_str()); } + + #[test] + fn key_to_borrowed() { + assert_eq!("a key", Key::from_str("a key").to_borrowed_str().unwrap()); + } } From 2f8736e3236565c18a597ffb83416ffc95a6b9ba Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Fri, 10 Jan 2025 10:24:32 +1000 Subject: [PATCH 228/280] prepare for 0.4.23 release --- CHANGELOG.md | 28 +++++++++++++++++++++++++++- Cargo.toml | 2 +- src/lib.rs | 2 +- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 83a72a879..f0222892f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,30 @@ ## [Unreleased] +## [0.4.23] - 2025-01-10 + +## What's Changed +* Fix some typos by @Kleinmarb in https://github.com/rust-lang/log/pull/637 +* Add logforth to implementation by @tisonkun in https://github.com/rust-lang/log/pull/638 +* Add `spdlog-rs` link to README by @SpriteOvO in https://github.com/rust-lang/log/pull/639 +* Add correct lifetime to kv::Value::to_borrowed_str by @stevenroose in https://github.com/rust-lang/log/pull/643 +* docs: Add logforth as an impl by @tisonkun in https://github.com/rust-lang/log/pull/642 +* Add clang_log implementation by @DDAN-17 in https://github.com/rust-lang/log/pull/646 +* Bind lifetimes of &str returned from Key by the lifetime of 'k rather than the lifetime of the Key struct by @gbbosak in https://github.com/rust-lang/log/pull/648 +* Fix up key lifetimes and add method to try get a borrowed key by @KodrAus in https://github.com/rust-lang/log/pull/653 +* Add Ftail implementation by @tjardoo in https://github.com/rust-lang/log/pull/652 + +## New Contributors +* @Kleinmarb made their first contribution in https://github.com/rust-lang/log/pull/637 +* @tisonkun made their first contribution in https://github.com/rust-lang/log/pull/638 +* @SpriteOvO made their first contribution in https://github.com/rust-lang/log/pull/639 +* @stevenroose made their first contribution in https://github.com/rust-lang/log/pull/643 +* @DDAN-17 made their first contribution in https://github.com/rust-lang/log/pull/646 +* @gbbosak made their first contribution in https://github.com/rust-lang/log/pull/648 +* @tjardoo made their first contribution in https://github.com/rust-lang/log/pull/652 + +**Full Changelog**: https://github.com/rust-lang/log/compare/0.4.22...0.4.23 + ## [0.4.22] - 2024-06-27 ## What's Changed @@ -298,7 +322,9 @@ version using log 0.4.x to avoid losing module and file information. Look at the [release tags] for information about older releases. -[Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.21...HEAD +[Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.23...HEAD +[0.4.23]: https://github.com/rust-lang/log/compare/0.4.22...0.4.23 +[0.4.22]: https://github.com/rust-lang/log/compare/0.4.21...0.4.22 [0.4.21]: https://github.com/rust-lang/log/compare/0.4.20...0.4.21 [0.4.20]: https://github.com/rust-lang-nursery/log/compare/0.4.19...0.4.20 [0.4.19]: https://github.com/rust-lang-nursery/log/compare/0.4.18...0.4.19 diff --git a/Cargo.toml b/Cargo.toml index 3fddf07a7..6b912508e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "log" -version = "0.4.22" # remember to update html_root_url +version = "0.4.23" # remember to update html_root_url authors = ["The Rust Project Developers"] license = "MIT OR Apache-2.0" readme = "README.md" diff --git a/src/lib.rs b/src/lib.rs index 2e70f3141..4988926db 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -342,7 +342,7 @@ #![doc( html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://www.rust-lang.org/favicon.ico", - html_root_url = "https://docs.rs/log/0.4.22" + html_root_url = "https://docs.rs/log/0.4.23" )] #![warn(missing_docs)] #![deny(missing_debug_implementations, unconditional_recursion)] From 34eb68cc577797ef82b8253d35a19770fc0857b4 Mon Sep 17 00:00:00 2001 From: tison Date: Fri, 10 Jan 2025 08:36:04 +0800 Subject: [PATCH 229/280] Relax feature flag for value's std_support Signed-off-by: tison --- src/kv/value.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kv/value.rs b/src/kv/value.rs index 2b9ca2510..a4285fe38 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -385,7 +385,7 @@ impl<'v> Value<'v> { } } -#[cfg(feature = "kv_std")] +#[cfg(feature = "std")] mod std_support { use std::borrow::Cow; use std::rc::Rc; From 8b06d9bfe3a8031bfbaa7cfae22494cd94ab5ca7 Mon Sep 17 00:00:00 2001 From: tison Date: Fri, 10 Jan 2025 08:45:35 +0800 Subject: [PATCH 230/280] value-bag distinct Signed-off-by: tison --- src/kv/value.rs | 16 +++++++++------- src/lib.rs | 1 + 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/kv/value.rs b/src/kv/value.rs index a4285fe38..d74dd0720 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -3,6 +3,7 @@ //! This module defines the [`Value`] type and supporting APIs for //! capturing and serializing them. +use alloc::borrow::Cow; use std::fmt; pub use crate::kv::Error; @@ -432,13 +433,6 @@ mod std_support { } } - impl<'v> Value<'v> { - /// Try to convert this value into a string. - pub fn to_cow_str(&self) -> Option> { - self.inner.to_str() - } - } - impl<'v> From<&'v String> for Value<'v> { fn from(v: &'v String) -> Self { Value::from(&**v) @@ -446,6 +440,14 @@ mod std_support { } } +#[cfg(all(feature = "std", feature = "value-bag"))] +impl<'v> Value<'v> { + /// Try to convert this value into a string. + pub fn to_cow_str(&self) -> Option> { + self.inner.to_str() + } +} + /// A visitor for a [`Value`]. /// /// Also see [`Value`'s documentation on seralization]. Value visitors are a simple alternative diff --git a/src/lib.rs b/src/lib.rs index 2e70f3141..f7b8011a5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -389,6 +389,7 @@ compile_error!("multiple release_max_level_* features set"); #[cfg(all(not(feature = "std"), not(test)))] extern crate core as std; +extern crate alloc; use std::cfg; #[cfg(feature = "std")] From 2db4a1bb3011d93982667167b8f09c2a1288e7f4 Mon Sep 17 00:00:00 2001 From: tison Date: Fri, 10 Jan 2025 08:47:01 +0800 Subject: [PATCH 231/280] add test Signed-off-by: tison --- .github/workflows/main.yml | 1 + src/kv/value.rs | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index f1eab4b88..892a630be 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -47,6 +47,7 @@ jobs: - run: cargo test --verbose --features kv - run: cargo test --verbose --features kv_sval - run: cargo test --verbose --features kv_serde + - run: cargo test --verbose --features kv,std - run: cargo test --verbose --features "kv kv_std kv_sval kv_serde" - run: cargo run --verbose --manifest-path test_max_level_features/Cargo.toml - run: cargo run --verbose --manifest-path test_max_level_features/Cargo.toml --release diff --git a/src/kv/value.rs b/src/kv/value.rs index d74dd0720..067469b75 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -448,6 +448,14 @@ impl<'v> Value<'v> { } } +#[cfg(all(feature = "std", not(feature = "value-bag")))] +impl<'v> Value<'v> { + /// Try to convert this value into a string. + pub fn to_cow_str(&self) -> Option> { + self.inner.to_borrowed_str().map(Cow::Borrowed) + } +} + /// A visitor for a [`Value`]. /// /// Also see [`Value`'s documentation on seralization]. Value visitors are a simple alternative From a61f95d19a1f841ca8fe82f0130f81f8d7aa74ee Mon Sep 17 00:00:00 2001 From: tison Date: Fri, 10 Jan 2025 08:49:25 +0800 Subject: [PATCH 232/280] tidy Signed-off-by: tison --- src/kv/value.rs | 7 +++---- src/lib.rs | 1 - 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/kv/value.rs b/src/kv/value.rs index 067469b75..6616ee961 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -3,7 +3,6 @@ //! This module defines the [`Value`] type and supporting APIs for //! capturing and serializing them. -use alloc::borrow::Cow; use std::fmt; pub use crate::kv::Error; @@ -443,7 +442,7 @@ mod std_support { #[cfg(all(feature = "std", feature = "value-bag"))] impl<'v> Value<'v> { /// Try to convert this value into a string. - pub fn to_cow_str(&self) -> Option> { + pub fn to_cow_str(&self) -> Option> { self.inner.to_str() } } @@ -451,8 +450,8 @@ impl<'v> Value<'v> { #[cfg(all(feature = "std", not(feature = "value-bag")))] impl<'v> Value<'v> { /// Try to convert this value into a string. - pub fn to_cow_str(&self) -> Option> { - self.inner.to_borrowed_str().map(Cow::Borrowed) + pub fn to_cow_str(&self) -> Option> { + self.inner.to_borrowed_str().map(std::borrow::Cow::Borrowed) } } diff --git a/src/lib.rs b/src/lib.rs index f7b8011a5..2e70f3141 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -389,7 +389,6 @@ compile_error!("multiple release_max_level_* features set"); #[cfg(all(not(feature = "std"), not(test)))] extern crate core as std; -extern crate alloc; use std::cfg; #[cfg(feature = "std")] From b1824f2c28bb1973b0b39f4bbd506a1803424b0a Mon Sep 17 00:00:00 2001 From: KodrAus Date: Fri, 10 Jan 2025 20:47:43 +1000 Subject: [PATCH 233/280] use cargo hack in CI to test all feature combinations --- .github/workflows/main.yml | 12 ++---------- Cargo.toml | 4 ++-- 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 892a630be..893e7e7d9 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -39,16 +39,8 @@ jobs: run: | rustup update ${{ matrix.rust }} --no-self-update rustup default ${{ matrix.rust }} - - run: cargo test --verbose - - run: cargo test --verbose --no-default-features - - run: cargo test --verbose --features std,serde,sval,sval_ref,value-bag,kv,kv_std,kv_sval,kv_serde - - run: cargo test --verbose --features serde - - run: cargo test --verbose --features std - - run: cargo test --verbose --features kv - - run: cargo test --verbose --features kv_sval - - run: cargo test --verbose --features kv_serde - - run: cargo test --verbose --features kv,std - - run: cargo test --verbose --features "kv kv_std kv_sval kv_serde" + cargo install cargo-hack + - run: cargo hack test --feature-powerset --lib --exclude-features max_level_off,max_level_error,max_level_warn,max_level_info,max_level_debug,max_level_trace,release_max_level_off,release_max_level_error,release_max_level_warn,release_max_level_info,release_max_level_debug,release_max_level_trace - run: cargo run --verbose --manifest-path test_max_level_features/Cargo.toml - run: cargo run --verbose --manifest-path test_max_level_features/Cargo.toml --release diff --git a/Cargo.toml b/Cargo.toml index 6b912508e..f22b5e92d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,11 +44,11 @@ release_max_level_info = [] release_max_level_debug = [] release_max_level_trace = [] -std = [] +std = ["value-bag?/error"] kv = [] kv_sval = ["kv", "value-bag/sval", "sval", "sval_ref"] -kv_std = ["std", "kv", "value-bag/error"] +kv_std = ["std", "kv"] kv_serde = ["kv_std", "value-bag/serde", "serde"] # Deprecated: use `kv_*` instead From 29fe9e60ff2e0239c1350394066a1871a9d9b9f3 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Fri, 10 Jan 2025 20:51:23 +1000 Subject: [PATCH 234/280] fix up feature activation --- Cargo.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f22b5e92d..c5f582081 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,11 +44,11 @@ release_max_level_info = [] release_max_level_debug = [] release_max_level_trace = [] -std = ["value-bag?/error"] +std = ["value-bag?/std"] kv = [] kv_sval = ["kv", "value-bag/sval", "sval", "sval_ref"] -kv_std = ["std", "kv"] +kv_std = ["std", "kv", "value-bag/error"] kv_serde = ["kv_std", "value-bag/serde", "serde"] # Deprecated: use `kv_*` instead From 2994f0a62c1f479ca1fff2a2100fe07c8fb7bd29 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Sat, 11 Jan 2025 07:52:44 +1000 Subject: [PATCH 235/280] prepare for 0.4.24 release --- CHANGELOG.md | 13 +++++++++++-- Cargo.toml | 2 +- src/lib.rs | 2 +- 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f0222892f..348906a93 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,15 @@ ## [Unreleased] -## [0.4.23] - 2025-01-10 +## [0.4.24] - 2025-01-11 + +## What's Changed +* Fix up kv feature activation by @KodrAus in https://github.com/rust-lang/log/pull/659 + + +**Full Changelog**: https://github.com/rust-lang/log/compare/0.4.23...0.4.24 + +## [0.4.23] - 2025-01-10 (yanked) ## What's Changed * Fix some typos by @Kleinmarb in https://github.com/rust-lang/log/pull/637 @@ -322,7 +330,8 @@ version using log 0.4.x to avoid losing module and file information. Look at the [release tags] for information about older releases. -[Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.23...HEAD +[Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.24...HEAD +[0.4.24]: https://github.com/rust-lang/log/compare/0.4.23...0.4.24 [0.4.23]: https://github.com/rust-lang/log/compare/0.4.22...0.4.23 [0.4.22]: https://github.com/rust-lang/log/compare/0.4.21...0.4.22 [0.4.21]: https://github.com/rust-lang/log/compare/0.4.20...0.4.21 diff --git a/Cargo.toml b/Cargo.toml index c5f582081..fa51a3ed9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "log" -version = "0.4.23" # remember to update html_root_url +version = "0.4.24" # remember to update html_root_url authors = ["The Rust Project Developers"] license = "MIT OR Apache-2.0" readme = "README.md" diff --git a/src/lib.rs b/src/lib.rs index 4988926db..46f4cc636 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -342,7 +342,7 @@ #![doc( html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://www.rust-lang.org/favicon.ico", - html_root_url = "https://docs.rs/log/0.4.23" + html_root_url = "https://docs.rs/log/0.4.24" )] #![warn(missing_docs)] #![deny(missing_debug_implementations, unconditional_recursion)] From 36e7e3f69636c484c94048bf5f56590a80d4c728 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Mon, 13 Jan 2025 08:25:08 +1000 Subject: [PATCH 236/280] revert loosening of kv cargo features --- Cargo.toml | 2 +- src/kv/value.rs | 25 ++++++++----------------- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index fa51a3ed9..0d668c903 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,7 +44,7 @@ release_max_level_info = [] release_max_level_debug = [] release_max_level_trace = [] -std = ["value-bag?/std"] +std = [] kv = [] kv_sval = ["kv", "value-bag/sval", "sval", "sval_ref"] diff --git a/src/kv/value.rs b/src/kv/value.rs index 6616ee961..ef9429832 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -385,7 +385,7 @@ impl<'v> Value<'v> { } } -#[cfg(feature = "std")] +#[cfg(feature = "kv_std")] mod std_support { use std::borrow::Cow; use std::rc::Rc; @@ -432,6 +432,13 @@ mod std_support { } } + impl<'v> Value<'v> { + /// Try convert this value into a string. + pub fn to_cow_str(&self) -> Option> { + self.inner.to_str() + } + } + impl<'v> From<&'v String> for Value<'v> { fn from(v: &'v String) -> Self { Value::from(&**v) @@ -439,22 +446,6 @@ mod std_support { } } -#[cfg(all(feature = "std", feature = "value-bag"))] -impl<'v> Value<'v> { - /// Try to convert this value into a string. - pub fn to_cow_str(&self) -> Option> { - self.inner.to_str() - } -} - -#[cfg(all(feature = "std", not(feature = "value-bag")))] -impl<'v> Value<'v> { - /// Try to convert this value into a string. - pub fn to_cow_str(&self) -> Option> { - self.inner.to_borrowed_str().map(std::borrow::Cow::Borrowed) - } -} - /// A visitor for a [`Value`]. /// /// Also see [`Value`'s documentation on seralization]. Value visitors are a simple alternative From 02797301236d45a8d6049fa20f803aacdb49f693 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Tue, 14 Jan 2025 09:15:48 +1000 Subject: [PATCH 237/280] prepare for 0.4.25 release --- CHANGELOG.md | 11 ++++++++++- Cargo.toml | 2 +- src/lib.rs | 2 +- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 348906a93..6ade6b277 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ ## [Unreleased] +## [0.4.25] - 2025-01-14 + +## What's Changed +* Revert loosening of kv cargo features by @KodrAus in https://github.com/rust-lang/log/pull/662 + + +**Full Changelog**: https://github.com/rust-lang/log/compare/0.4.24...0.4.25 + ## [0.4.24] - 2025-01-11 ## What's Changed @@ -330,7 +338,8 @@ version using log 0.4.x to avoid losing module and file information. Look at the [release tags] for information about older releases. -[Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.24...HEAD +[Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.25...HEAD +[0.4.25]: https://github.com/rust-lang/log/compare/0.4.24...0.4.25 [0.4.24]: https://github.com/rust-lang/log/compare/0.4.23...0.4.24 [0.4.23]: https://github.com/rust-lang/log/compare/0.4.22...0.4.23 [0.4.22]: https://github.com/rust-lang/log/compare/0.4.21...0.4.22 diff --git a/Cargo.toml b/Cargo.toml index 0d668c903..aed59c6c9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "log" -version = "0.4.24" # remember to update html_root_url +version = "0.4.25" # remember to update html_root_url authors = ["The Rust Project Developers"] license = "MIT OR Apache-2.0" readme = "README.md" diff --git a/src/lib.rs b/src/lib.rs index 46f4cc636..9f8b8a947 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -342,7 +342,7 @@ #![doc( html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://www.rust-lang.org/favicon.ico", - html_root_url = "https://docs.rs/log/0.4.24" + html_root_url = "https://docs.rs/log/0.4.25" )] #![warn(missing_docs)] #![deny(missing_debug_implementations, unconditional_recursion)] From d5061b629afecc32724060a874990b8d33408c30 Mon Sep 17 00:00:00 2001 From: tison Date: Sat, 1 Feb 2025 15:45:58 +0800 Subject: [PATCH 238/280] Add an optional logger param Signed-off-by: tison --- src/__private_api.rs | 23 +++++--- src/macros.rs | 126 +++++++++++++++++++++++++++++++++++++------ 2 files changed, 127 insertions(+), 22 deletions(-) diff --git a/src/__private_api.rs b/src/__private_api.rs index 11bc2fc1c..1331568bf 100644 --- a/src/__private_api.rs +++ b/src/__private_api.rs @@ -1,7 +1,7 @@ //! WARNING: this is not part of the crate's public API and is subject to change at any time use self::sealed::KVs; -use crate::{Level, Metadata, Record}; +use crate::{Level, Log, Metadata, Record}; use std::fmt::Arguments; use std::panic::Location; pub use std::{format_args, module_path, stringify}; @@ -34,7 +34,8 @@ impl<'a> KVs<'a> for () { // Log implementation. -fn log_impl( +fn log_impl( + logger: &L, args: Arguments, level: Level, &(target, module_path, loc): &(&str, &'static str, &'static Location), @@ -58,22 +59,30 @@ fn log_impl( #[cfg(feature = "kv")] builder.key_values(&kvs); - crate::logger().log(&builder.build()); + logger.log(&builder.build()); } -pub fn log<'a, K>( +pub fn log<'a, K, L>( + logger: &L, args: Arguments, level: Level, target_module_path_and_loc: &(&str, &'static str, &'static Location), kvs: K, ) where K: KVs<'a>, + L: Log, { - log_impl(args, level, target_module_path_and_loc, kvs.into_kvs()) + log_impl( + logger, + args, + level, + target_module_path_and_loc, + kvs.into_kvs(), + ) } -pub fn enabled(level: Level, target: &str) -> bool { - crate::logger().enabled(&Metadata::builder().level(level).target(target).build()) +pub fn enabled(logger: &L, level: Level, target: &str) -> bool { + logger.enabled(&Metadata::builder().level(level).target(target).build()) } #[track_caller] diff --git a/src/macros.rs b/src/macros.rs index 87693f2b1..d68881fb0 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -29,11 +29,13 @@ /// ``` #[macro_export] macro_rules! log { - // log!(target: "my_target", Level::Info, key1:? = 42, key2 = true; "a {} event", "log"); - (target: $target:expr, $lvl:expr, $($key:tt $(:$capture:tt)? $(= $value:expr)?),+; $($arg:tt)+) => ({ + // log!(logger: my_logger, target: "my_target", Level::Info, key1:? = 42, key2 = true; "a {} event", "log"); + (logger: $logger:expr, target: $target:expr, $lvl:expr, $($key:tt $(:$capture:tt)? $(= $value:expr)?),+; $($arg:tt)+) => ({ + let logger = &$logger; let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { $crate::__private_api::log::<&_>( + logger, $crate::__private_api::format_args!($($arg)+), lvl, &($target, $crate::__private_api::module_path!(), $crate::__private_api::loc()), @@ -42,11 +44,13 @@ macro_rules! log { } }); - // log!(target: "my_target", Level::Info, "a {} event", "log"); - (target: $target:expr, $lvl:expr, $($arg:tt)+) => ({ + // log!(logger: my_logger, target: "my_target", Level::Info, "a {} event", "log"); + (logger: $logger:expr, target: $target:expr, $lvl:expr, $($arg:tt)+) => ({ + let logger = &$logger; let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { $crate::__private_api::log( + logger, $crate::__private_api::format_args!($($arg)+), lvl, &($target, $crate::__private_api::module_path!(), $crate::__private_api::loc()), @@ -55,8 +59,20 @@ macro_rules! log { } }); + // log!(logger: my_logger, Level::Info, "a log event") + (logger: $logger:expr, $lvl:expr, $($arg:tt)+) => ({ + $crate::log!(logger: $logger, target: $crate::__private_api::module_path!(), $lvl, $($arg)+) + }); + + // log!(target: "my_target", Level::Info, "a log event") + (target: $target:expr, $lvl:expr, $($arg:tt)+) => ({ + $crate::log!(logger: $crate::logger(), target: $target, $lvl, $($arg)+) + }); + // log!(Level::Info, "a log event") - ($lvl:expr, $($arg:tt)+) => ($crate::log!(target: $crate::__private_api::module_path!(), $lvl, $($arg)+)); + ($lvl:expr, $($arg:tt)+) => ({ + $crate::log!(target: $crate::__private_api::module_path!(), $lvl, $($arg)+) + }); } /// Logs a message at the error level. @@ -75,9 +91,23 @@ macro_rules! log { /// ``` #[macro_export] macro_rules! error { + // error!(logger: my_logger, target: "my_target", key1 = 42, key2 = true; "a {} event", "log") + // error!(logger: my_logger, target: "my_target", "a {} event", "log") + (logger: $logger:expr, target: $target:expr, $($arg:tt)+) => ({ + $crate::log!(logger: $logger, target: $target, $crate::Level::Error, $($arg)+) + }); + + // error!(logger: my_logger, key1 = 42, key2 = true; "a {} event", "log") + // error!(logger: my_logger, "a {} event", "log") + (logger: $logger:expr, $($arg:tt)+) => ({ + $crate::log!(logger: $logger, $crate::Level::Error, $($arg)+) + }); + // error!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log") // error!(target: "my_target", "a {} event", "log") - (target: $target:expr, $($arg:tt)+) => ($crate::log!(target: $target, $crate::Level::Error, $($arg)+)); + (target: $target:expr, $($arg:tt)+) => ({ + $crate::log!(target: $target, $crate::Level::Error, $($arg)+) + }); // error!("a {} event", "log") ($($arg:tt)+) => ($crate::log!($crate::Level::Error, $($arg)+)) @@ -99,9 +129,23 @@ macro_rules! error { /// ``` #[macro_export] macro_rules! warn { + // warn!(logger: my_logger, target: "my_target", key1 = 42, key2 = true; "a {} event", "log") + // warn!(logger: my_logger, target: "my_target", "a {} event", "log") + (logger: $logger:expr, target: $target:expr, $($arg:tt)+) => ({ + $crate::log!(logger: $logger, target: $target, $crate::Level::Warn, $($arg)+) + }); + + // warn!(logger: my_logger, key1 = 42, key2 = true; "a {} event", "log") + // warn!(logger: my_logger, "a {} event", "log") + (logger: $logger:expr, $($arg:tt)+) => ({ + $crate::log!(logger: $logger, $crate::Level::Warn, $($arg)+) + }); + // warn!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log") // warn!(target: "my_target", "a {} event", "log") - (target: $target:expr, $($arg:tt)+) => ($crate::log!(target: $target, $crate::Level::Warn, $($arg)+)); + (target: $target:expr, $($arg:tt)+) => ({ + $crate::log!(target: $target, $crate::Level::Warn, $($arg)+) + }); // warn!("a {} event", "log") ($($arg:tt)+) => ($crate::log!($crate::Level::Warn, $($arg)+)) @@ -125,9 +169,23 @@ macro_rules! warn { /// ``` #[macro_export] macro_rules! info { + // info!(logger: my_logger, target: "my_target", key1 = 42, key2 = true; "a {} event", "log") + // info!(logger: my_logger, target: "my_target", "a {} event", "log") + (logger: $logger:expr, target: $target:expr, $($arg:tt)+) => ({ + $crate::log!(logger: $logger, target: $target, $crate::Level::Info, $($arg)+) + }); + + // info!(logger: my_logger, key1 = 42, key2 = true; "a {} event", "log") + // info!(logger: my_logger, "a {} event", "log") + (logger: $logger:expr, $($arg:tt)+) => ({ + $crate::log!(logger: $logger, $crate::Level::Info, $($arg)+) + }); + // info!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log") // info!(target: "my_target", "a {} event", "log") - (target: $target:expr, $($arg:tt)+) => ($crate::log!(target: $target, $crate::Level::Info, $($arg)+)); + (target: $target:expr, $($arg:tt)+) => ({ + $crate::log!(target: $target, $crate::Level::Info, $($arg)+) + }); // info!("a {} event", "log") ($($arg:tt)+) => ($crate::log!($crate::Level::Info, $($arg)+)) @@ -150,9 +208,23 @@ macro_rules! info { /// ``` #[macro_export] macro_rules! debug { + // debug!(logger: my_logger, target: "my_target", key1 = 42, key2 = true; "a {} event", "log") + // debug!(logger: my_logger, target: "my_target", "a {} event", "log") + (logger: $logger:expr, target: $target:expr, $($arg:tt)+) => ({ + $crate::log!(logger: $logger, target: $target, $crate::Level::Debug, $($arg)+) + }); + + // debug!(logger: my_logger, key1 = 42, key2 = true; "a {} event", "log") + // debug!(logger: my_logger, "a {} event", "log") + (logger: $logger:expr, $($arg:tt)+) => ({ + $crate::log!(logger: $logger, $crate::Level::Debug, $($arg)+) + }); + // debug!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log") // debug!(target: "my_target", "a {} event", "log") - (target: $target:expr, $($arg:tt)+) => ($crate::log!(target: $target, $crate::Level::Debug, $($arg)+)); + (target: $target:expr, $($arg:tt)+) => ({ + $crate::log!(target: $target, $crate::Level::Debug, $($arg)+) + }); // debug!("a {} event", "log") ($($arg:tt)+) => ($crate::log!($crate::Level::Debug, $($arg)+)) @@ -177,9 +249,23 @@ macro_rules! debug { /// ``` #[macro_export] macro_rules! trace { + // trace!(logger: my_logger, target: "my_target", key1 = 42, key2 = true; "a {} event", "log") + // trace!(logger: my_logger, target: "my_target", "a {} event", "log") + (logger: $logger:expr, target: $target:expr, $($arg:tt)+) => ({ + $crate::log!(logger: $logger, target: $target, $crate::Level::Trace, $($arg)+) + }); + + // trace!(logger: my_logger, key1 = 42, key2 = true; "a {} event", "log") + // trace!(logger: my_logger, "a {} event", "log") + (logger: $logger:expr, $($arg:tt)+) => ({ + $crate::log!(logger: $logger, $crate::Level::Trace, $($arg)+) + }); + // trace!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log") // trace!(target: "my_target", "a {} event", "log") - (target: $target:expr, $($arg:tt)+) => ($crate::log!(target: $target, $crate::Level::Trace, $($arg)+)); + (target: $target:expr, $($arg:tt)+) => ({ + $crate::log!(target: $target, $crate::Level::Trace, $($arg)+) + }); // trace!("a {} event", "log") ($($arg:tt)+) => ($crate::log!($crate::Level::Trace, $($arg)+)) @@ -213,15 +299,25 @@ macro_rules! trace { /// ``` #[macro_export] macro_rules! log_enabled { - (target: $target:expr, $lvl:expr) => {{ + (logger: $logger:expr, target: $target:expr, $lvl:expr) => ({ + let logger = &$logger; let lvl = $lvl; lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() - && $crate::__private_api::enabled(lvl, $target) - }}; - ($lvl:expr) => { + && $crate::__private_api::enabled(logger, lvl, $target) + }); + + (logger: $logger:expr, $lvl:expr) => ({ + $crate::log_enabled!(logger: $logger, target: $crate::__private_api::module_path!(), $lvl) + }); + + (target: $target:expr, $lvl:expr) => ({ + $crate::log_enabled!(logger: $crate::logger(), target: $target, $lvl) + }); + + ($lvl:expr) => ({ $crate::log_enabled!(target: $crate::__private_api::module_path!(), $lvl) - }; + }); } // These macros use a pattern of #[cfg]s to produce nicer error From 2851f2bac373edd1c3cf1317dc72ae912ab67e53 Mon Sep 17 00:00:00 2001 From: tison Date: Sat, 1 Feb 2025 16:03:23 +0800 Subject: [PATCH 239/280] fixup MSRV Signed-off-by: tison --- src/macros.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/macros.rs b/src/macros.rs index d68881fb0..d901e24a7 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -34,7 +34,7 @@ macro_rules! log { let logger = &$logger; let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { - $crate::__private_api::log::<&_>( + $crate::__private_api::log( logger, $crate::__private_api::format_args!($($arg)+), lvl, From a3f72c8fbe31eb06e7aa3451da6246470c0eade4 Mon Sep 17 00:00:00 2001 From: tison Date: Sat, 1 Feb 2025 16:06:19 +0800 Subject: [PATCH 240/280] separate logger Signed-off-by: tison --- tests/integration.rs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/tests/integration.rs b/tests/integration.rs index 7bf456e02..ca104d8ae 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -53,31 +53,31 @@ fn main() { last_log_location: Mutex::new(None), }); let a = me.clone(); - set_boxed_logger(Box::new(Logger(me))).unwrap(); + let logger = Logger(me); - test_filter(&a, LevelFilter::Off); - test_filter(&a, LevelFilter::Error); - test_filter(&a, LevelFilter::Warn); - test_filter(&a, LevelFilter::Info); - test_filter(&a, LevelFilter::Debug); - test_filter(&a, LevelFilter::Trace); + test_filter(&logger, &a, LevelFilter::Off); + test_filter(&logger, &a, LevelFilter::Error); + test_filter(&logger, &a, LevelFilter::Warn); + test_filter(&logger, &a, LevelFilter::Info); + test_filter(&logger, &a, LevelFilter::Debug); + test_filter(&logger, &a, LevelFilter::Trace); - test_line_numbers(&a); + test_line_numbers(&logger, &a); } } -fn test_filter(a: &State, filter: LevelFilter) { +fn test_filter(logger: &dyn Log, a: &State, filter: LevelFilter) { // tests to ensure logs with a level beneath 'max_level' are filtered out log::set_max_level(filter); - error!(""); + error!(logger: logger, ""); last(a, t(Level::Error, filter)); - warn!(""); + warn!(logger: logger, ""); last(a, t(Level::Warn, filter)); - info!(""); + info!(logger: logger, ""); last(a, t(Level::Info, filter)); - debug!(""); + debug!(logger: logger, ""); last(a, t(Level::Debug, filter)); - trace!(""); + trace!(logger: logger, ""); last(a, t(Level::Trace, filter)); fn t(lvl: Level, filter: LevelFilter) -> Option { @@ -93,10 +93,10 @@ fn test_filter(a: &State, filter: LevelFilter) { } } -fn test_line_numbers(state: &State) { +fn test_line_numbers(logger: &dyn Log, state: &State) { log::set_max_level(LevelFilter::Trace); - info!(""); // ensure check_line function follows log macro + info!(logger: logger, ""); // ensure check_line function follows log macro check_log_location(&state); #[track_caller] From dd835fe38e484a8b5bd9acf6d0465c36d70acfcc Mon Sep 17 00:00:00 2001 From: tison Date: Sat, 1 Feb 2025 17:42:57 +0800 Subject: [PATCH 241/280] fixup msrv tests Signed-off-by: tison --- src/macros.rs | 2 +- tests/macros.rs | 21 ++++++++++++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index d901e24a7..3135aaf46 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -34,7 +34,7 @@ macro_rules! log { let logger = &$logger; let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { - $crate::__private_api::log( + $crate::__private_api::log::<&_, _>( logger, $crate::__private_api::format_args!($($arg)+), lvl, diff --git a/tests/macros.rs b/tests/macros.rs index 20da6ac44..ba2815dbb 100644 --- a/tests/macros.rs +++ b/tests/macros.rs @@ -1,4 +1,4 @@ -use log::{log, log_enabled}; +use log::{log, log_enabled, Log, Metadata, Record}; macro_rules! all_log_macros { ($($arg:tt)*) => ({ @@ -10,6 +10,16 @@ macro_rules! all_log_macros { }); } +struct NopLogger; + +impl Log for NopLogger { + fn enabled(&self, _: &Metadata) -> bool { + false + } + fn log(&self, _: &Record) {} + fn flush(&self) {} +} + #[test] fn no_args() { for lvl in log::Level::iter() { @@ -28,6 +38,12 @@ fn no_args() { all_log_macros!(target: "my_target", "hello"); all_log_macros!(target: "my_target", "hello",); + + let nop = NopLogger; + all_log_macros!(logger: nop, "hello"); + all_log_macros!(logger: nop, "hello",); + all_log_macros!(logger: nop, target: "my_target", "hello"); + all_log_macros!(logger: nop, target: "my_target", "hello",); } #[test] @@ -115,6 +131,9 @@ fn kv_no_args() { log!(lvl, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); } + let nop = NopLogger; + all_log_macros!(logger: nop, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); + all_log_macros!(logger: nop, target: "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); all_log_macros!(target: "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); all_log_macros!(target = "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); all_log_macros!(cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); From 310c9b43ffe767dec16531c7839861b28f709ee9 Mon Sep 17 00:00:00 2001 From: Asuna Date: Fri, 14 Feb 2025 03:57:03 +0800 Subject: [PATCH 242/280] Derive `Clone` for `kv::Value` --- src/kv/value.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/kv/value.rs b/src/kv/value.rs index ef9429832..b4851af2a 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -115,6 +115,7 @@ impl<'v> ToValue for Value<'v> { /// `Display` implementation, it will serialize through `serde` as a string. If it was /// captured as a struct using `serde`, it will also serialize as a struct /// through `sval`, or can be formatted using a `Debug`-compatible representation. +#[derive(Clone)] pub struct Value<'v> { inner: inner::Inner<'v>, } From 931d8832d0c60d062ee61d228def4044efcbd8c0 Mon Sep 17 00:00:00 2001 From: Asuna Date: Fri, 14 Feb 2025 08:53:03 +0800 Subject: [PATCH 243/280] Add `spdlog-rs` link to crate doc --- src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 9f8b8a947..e2d12c57d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -149,6 +149,7 @@ //! * [log4rs] //! * [logforth] //! * [fern] +//! * [spdlog-rs] //! * Adaptors for other facilities: //! * [syslog] //! * [slog-stdlog] @@ -326,6 +327,7 @@ //! [log4rs]: https://docs.rs/log4rs/*/log4rs/ //! [logforth]: https://docs.rs/logforth/*/logforth/ //! [fern]: https://docs.rs/fern/*/fern/ +//! [spdlog-rs]: https://docs.rs/spdlog-rs/*/spdlog/ //! [systemd-journal-logger]: https://docs.rs/systemd-journal-logger/*/systemd_journal_logger/ //! [android_log]: https://docs.rs/android_log/*/android_log/ //! [win_dbg_logger]: https://docs.rs/win_dbg_logger/*/win_dbg_logger/ From 5aba0c2290067bf527bbff762cf5414096502446 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Tue, 18 Feb 2025 09:36:52 +1000 Subject: [PATCH 244/280] prepare for 0.4.26 release --- CHANGELOG.md | 12 +++++++++++- Cargo.toml | 2 +- src/lib.rs | 2 +- 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ade6b277..11cfaea37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,15 @@ ## [Unreleased] +## [0.4.26] - 2025-02-18 + +## What's Changed +* Derive `Clone` for `kv::Value` by @SpriteOvO in https://github.com/rust-lang/log/pull/668 +* Add `spdlog-rs` link to crate doc by @SpriteOvO in https://github.com/rust-lang/log/pull/669 + + +**Full Changelog**: https://github.com/rust-lang/log/compare/0.4.25...0.4.26 + ## [0.4.25] - 2025-01-14 ## What's Changed @@ -338,7 +347,8 @@ version using log 0.4.x to avoid losing module and file information. Look at the [release tags] for information about older releases. -[Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.25...HEAD +[Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.26...HEAD +[0.4.26]: https://github.com/rust-lang/log/compare/0.4.25...0.4.26 [0.4.25]: https://github.com/rust-lang/log/compare/0.4.24...0.4.25 [0.4.24]: https://github.com/rust-lang/log/compare/0.4.23...0.4.24 [0.4.23]: https://github.com/rust-lang/log/compare/0.4.22...0.4.23 diff --git a/Cargo.toml b/Cargo.toml index aed59c6c9..0c8b53763 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "log" -version = "0.4.25" # remember to update html_root_url +version = "0.4.26" # remember to update html_root_url authors = ["The Rust Project Developers"] license = "MIT OR Apache-2.0" readme = "README.md" diff --git a/src/lib.rs b/src/lib.rs index e2d12c57d..843893d01 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -344,7 +344,7 @@ #![doc( html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://www.rust-lang.org/favicon.ico", - html_root_url = "https://docs.rs/log/0.4.25" + html_root_url = "https://docs.rs/log/0.4.26" )] #![warn(missing_docs)] #![deny(missing_debug_implementations, unconditional_recursion)] From ba8b3c5ce684be9316db98d67618d7aea0912ada Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Thu, 6 Feb 2025 03:16:07 -0500 Subject: [PATCH 245/280] Enable clippy support for format-like macros Add `#[clippy::format_args]` as described in https://doc.rust-lang.org/nightly/clippy/attribs.html#clippyformat_args --- src/macros.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/macros.rs b/src/macros.rs index 87693f2b1..0f78f8525 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -28,6 +28,7 @@ /// # } /// ``` #[macro_export] +#[clippy::format_args] macro_rules! log { // log!(target: "my_target", Level::Info, key1:? = 42, key2 = true; "a {} event", "log"); (target: $target:expr, $lvl:expr, $($key:tt $(:$capture:tt)? $(= $value:expr)?),+; $($arg:tt)+) => ({ @@ -74,6 +75,7 @@ macro_rules! log { /// # } /// ``` #[macro_export] +#[clippy::format_args] macro_rules! error { // error!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log") // error!(target: "my_target", "a {} event", "log") @@ -98,6 +100,7 @@ macro_rules! error { /// # } /// ``` #[macro_export] +#[clippy::format_args] macro_rules! warn { // warn!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log") // warn!(target: "my_target", "a {} event", "log") @@ -124,6 +127,7 @@ macro_rules! warn { /// # } /// ``` #[macro_export] +#[clippy::format_args] macro_rules! info { // info!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log") // info!(target: "my_target", "a {} event", "log") @@ -149,6 +153,7 @@ macro_rules! info { /// # } /// ``` #[macro_export] +#[clippy::format_args] macro_rules! debug { // debug!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log") // debug!(target: "my_target", "a {} event", "log") @@ -176,6 +181,7 @@ macro_rules! debug { /// # } /// ``` #[macro_export] +#[clippy::format_args] macro_rules! trace { // trace!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log") // trace!(target: "my_target", "a {} event", "log") From 98dc73f3d8cf34b9586399bdf890127f7b465c29 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Thu, 20 Feb 2025 20:48:22 -0500 Subject: [PATCH 246/280] A few minor lint fixes --- src/lib.rs | 6 +++--- tests/integration.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 843893d01..a862b5fa9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -292,7 +292,7 @@ //! configured in your `Cargo.toml`. //! //! * `std` allows use of `std` crate instead of the default `core`. Enables using `std::error` and -//! `set_boxed_logger` functionality. +//! `set_boxed_logger` functionality. //! * `serde` enables support for serialization and deserialization of `Level` and `LevelFilter`. //! //! ```toml @@ -1035,7 +1035,7 @@ impl<'a> RecordBuilder<'a> { } } -impl<'a> Default for RecordBuilder<'a> { +impl Default for RecordBuilder<'_> { fn default() -> Self { Self::new() } @@ -1164,7 +1164,7 @@ impl<'a> MetadataBuilder<'a> { } } -impl<'a> Default for MetadataBuilder<'a> { +impl Default for MetadataBuilder<'_> { fn default() -> Self { Self::new() } diff --git a/tests/integration.rs b/tests/integration.rs index 7bf456e02..651fe6cd9 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -97,7 +97,7 @@ fn test_line_numbers(state: &State) { log::set_max_level(LevelFilter::Trace); info!(""); // ensure check_line function follows log macro - check_log_location(&state); + check_log_location(state); #[track_caller] fn check_log_location(state: &State) { From cde258593221716c7b64c049d6619b49b30dd4de Mon Sep 17 00:00:00 2001 From: tison Date: Thu, 27 Feb 2025 21:50:48 +0800 Subject: [PATCH 247/280] allows us to pass zero-sized logger Signed-off-by: tison --- src/__private_api.rs | 6 +++--- src/macros.rs | 6 +++--- tests/macros.rs | 14 ++++++-------- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/__private_api.rs b/src/__private_api.rs index 1331568bf..57f038120 100644 --- a/src/__private_api.rs +++ b/src/__private_api.rs @@ -35,7 +35,7 @@ impl<'a> KVs<'a> for () { // Log implementation. fn log_impl( - logger: &L, + logger: L, args: Arguments, level: Level, &(target, module_path, loc): &(&str, &'static str, &'static Location), @@ -63,7 +63,7 @@ fn log_impl( } pub fn log<'a, K, L>( - logger: &L, + logger: L, args: Arguments, level: Level, target_module_path_and_loc: &(&str, &'static str, &'static Location), @@ -81,7 +81,7 @@ pub fn log<'a, K, L>( ) } -pub fn enabled(logger: &L, level: Level, target: &str) -> bool { +pub fn enabled(logger: L, level: Level, target: &str) -> bool { logger.enabled(&Metadata::builder().level(level).target(target).build()) } diff --git a/src/macros.rs b/src/macros.rs index 272c42f42..e9cf962b7 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -32,7 +32,7 @@ macro_rules! log { // log!(logger: my_logger, target: "my_target", Level::Info, key1:? = 42, key2 = true; "a {} event", "log"); (logger: $logger:expr, target: $target:expr, $lvl:expr, $($key:tt $(:$capture:tt)? $(= $value:expr)?),+; $($arg:tt)+) => ({ - let logger = &$logger; + let logger = $logger; let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { $crate::__private_api::log::<&_, _>( @@ -47,7 +47,7 @@ macro_rules! log { // log!(logger: my_logger, target: "my_target", Level::Info, "a {} event", "log"); (logger: $logger:expr, target: $target:expr, $lvl:expr, $($arg:tt)+) => ({ - let logger = &$logger; + let logger = $logger; let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { $crate::__private_api::log( @@ -306,7 +306,7 @@ macro_rules! trace { #[macro_export] macro_rules! log_enabled { (logger: $logger:expr, target: $target:expr, $lvl:expr) => ({ - let logger = &$logger; + let logger = $logger; let lvl = $lvl; lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() diff --git a/tests/macros.rs b/tests/macros.rs index ba2815dbb..e4023ea22 100644 --- a/tests/macros.rs +++ b/tests/macros.rs @@ -39,11 +39,10 @@ fn no_args() { all_log_macros!(target: "my_target", "hello"); all_log_macros!(target: "my_target", "hello",); - let nop = NopLogger; - all_log_macros!(logger: nop, "hello"); - all_log_macros!(logger: nop, "hello",); - all_log_macros!(logger: nop, target: "my_target", "hello"); - all_log_macros!(logger: nop, target: "my_target", "hello",); + all_log_macros!(logger: NopLogger, "hello"); + all_log_macros!(logger: NopLogger, "hello",); + all_log_macros!(logger: NopLogger, target: "my_target", "hello"); + all_log_macros!(logger: NopLogger, target: "my_target", "hello",); } #[test] @@ -131,9 +130,8 @@ fn kv_no_args() { log!(lvl, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); } - let nop = NopLogger; - all_log_macros!(logger: nop, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); - all_log_macros!(logger: nop, target: "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); + all_log_macros!(logger: NopLogger, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); + all_log_macros!(logger: NopLogger, target: "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); all_log_macros!(target: "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); all_log_macros!(target = "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); all_log_macros!(cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); From 2bb47d65a5c6f94bdc1d694bec4824431201e31a Mon Sep 17 00:00:00 2001 From: tison Date: Fri, 28 Feb 2025 11:41:32 +0800 Subject: [PATCH 248/280] use a zero-sized GlobalLogger Signed-off-by: tison --- src/lib.rs | 24 +++++++++++++++++++++++- src/macros.rs | 4 ++-- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index a862b5fa9..2dd300874 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1204,7 +1204,7 @@ pub trait Log: Sync + Send { fn flush(&self); } -// Just used as a dummy initial value for LOGGER +/// A dummy initial value for LOGGER. struct NopLogger; impl Log for NopLogger { @@ -1216,6 +1216,28 @@ impl Log for NopLogger { fn flush(&self) {} } +/// The global logger proxy. +/// +/// This zero-sized type implements the [`Log`] trait by forwarding calls +/// to the logger registered with the `set_boxed_logger` or `set_logger` +/// methods if there is one, or a nop logger as default. +#[derive(Copy, Clone, Default, Debug)] +pub struct GlobalLogger; + +impl Log for GlobalLogger { + fn enabled(&self, metadata: &Metadata) -> bool { + logger().enabled(metadata) + } + + fn log(&self, record: &Record) { + logger().log(record) + } + + fn flush(&self) { + logger().flush() + } +} + impl Log for &'_ T where T: ?Sized + Log, diff --git a/src/macros.rs b/src/macros.rs index e9cf962b7..e962b1b62 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -67,7 +67,7 @@ macro_rules! log { // log!(target: "my_target", Level::Info, "a log event") (target: $target:expr, $lvl:expr, $($arg:tt)+) => ({ - $crate::log!(logger: $crate::logger(), target: $target, $lvl, $($arg)+) + $crate::log!(logger: $crate::GlobalLogger, target: $target, $lvl, $($arg)+) }); // log!(Level::Info, "a log event") @@ -318,7 +318,7 @@ macro_rules! log_enabled { }); (target: $target:expr, $lvl:expr) => ({ - $crate::log_enabled!(logger: $crate::logger(), target: $target, $lvl) + $crate::log_enabled!(logger: $crate::GlobalLogger, target: $target, $lvl) }); ($lvl:expr) => ({ From 11af9f190acd102c1db194205c7ec18b2a15a7b6 Mon Sep 17 00:00:00 2001 From: tison Date: Mon, 17 Mar 2025 22:23:34 +0800 Subject: [PATCH 249/280] move logger expr to execute conditionally Signed-off-by: tison --- src/macros.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index e962b1b62..9d2a1810e 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -32,9 +32,9 @@ macro_rules! log { // log!(logger: my_logger, target: "my_target", Level::Info, key1:? = 42, key2 = true; "a {} event", "log"); (logger: $logger:expr, target: $target:expr, $lvl:expr, $($key:tt $(:$capture:tt)? $(= $value:expr)?),+; $($arg:tt)+) => ({ - let logger = $logger; let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { + let logger = $logger; $crate::__private_api::log::<&_, _>( logger, $crate::__private_api::format_args!($($arg)+), @@ -47,9 +47,9 @@ macro_rules! log { // log!(logger: my_logger, target: "my_target", Level::Info, "a {} event", "log"); (logger: $logger:expr, target: $target:expr, $lvl:expr, $($arg:tt)+) => ({ - let logger = $logger; let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { + let logger = $logger; $crate::__private_api::log( logger, $crate::__private_api::format_args!($($arg)+), From da3dd1feb86f8c57029e90cd1c422c3a0dd7343e Mon Sep 17 00:00:00 2001 From: tison Date: Mon, 17 Mar 2025 22:50:34 +0800 Subject: [PATCH 250/280] add docs Signed-off-by: tison --- src/macros.rs | 91 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 68 insertions(+), 23 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index 9d2a1810e..49166fe02 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -13,20 +13,56 @@ /// This macro will generically log with the specified `Level` and `format!` /// based argument list. /// -/// # Examples -/// /// ``` /// use log::{log, Level}; /// -/// # fn main() { /// let data = (42, "Forty-two"); /// let private_data = "private"; /// /// log!(Level::Error, "Received errors: {}, {}", data.0, data.1); -/// log!(target: "app_events", Level::Warn, "App warning: {}, {}, {}", -/// data.0, data.1, private_data); -/// # } /// ``` +/// +/// Optionally, you can specify a `target` argument to attach a specific target +/// to the log record. By default, the target is the module path of the caller. +/// +/// ``` +/// use log::{log, Level}; +/// +/// let data = (42, "Forty-two"); +/// let private_data = "private"; +/// +/// log!( +/// target: "app_events", +/// Level::Error, +/// "Received errors: {}, {}", +/// data.0, data.1 +/// ); +/// ``` +/// +/// And optionally, you can specify a `logger` argument to use a specific logger +/// instead of the default global logger. +/// +/// ``` +/// # struct MyLogger {} +/// # impl Log for MyLogger { +/// # fn enabled(&self, _metadata: &log::Metadata) -> bool { +/// # false +/// # } +/// # fn log(&self, _record: &log::Record) {} +/// # fn flush(&self) {} +/// # } +/// use log::{log, Level, Log}; +/// +/// let data = (42, "Forty-two"); +/// let private_data = "private"; +/// +/// let my_logger = MyLogger {}; +/// log!( +/// logger: &my_logger, +/// Level::Error, +/// "Received errors: {}, {}", +/// data.0, data.1 +/// ); #[macro_export] #[clippy::format_args] macro_rules! log { @@ -81,14 +117,14 @@ macro_rules! log { /// # Examples /// /// ``` -/// use log::error; +/// use log::{error, GlobalLogger}; /// -/// # fn main() { /// let (err_info, port) = ("No connection", 22); +/// let my_logger = GlobalLogger; // can be any logger implementing the Log trait /// /// error!("Error: {err_info} on port {port}"); /// error!(target: "app_events", "App Error: {err_info}, Port: {port}"); -/// # } +/// error!(logger: my_logger, "App Error: {err_info}, Port: {port}"); /// ``` #[macro_export] #[clippy::format_args] @@ -120,14 +156,14 @@ macro_rules! error { /// # Examples /// /// ``` -/// use log::warn; +/// use log::{warn, GlobalLogger}; /// -/// # fn main() { /// let warn_description = "Invalid Input"; +/// let my_logger = GlobalLogger; // can be any logger implementing the Log trait /// /// warn!("Warning! {warn_description}!"); /// warn!(target: "input_events", "App received warning: {warn_description}"); -/// # } +/// warn!(logger: my_logger, "App received warning: {warn_description}"); /// ``` #[macro_export] #[clippy::format_args] @@ -159,16 +195,23 @@ macro_rules! warn { /// # Examples /// /// ``` -/// use log::info; +/// use log::{info, GlobalLogger}; /// -/// # fn main() { /// # struct Connection { port: u32, speed: f32 } /// let conn_info = Connection { port: 40, speed: 3.20 }; +/// let my_logger = GlobalLogger; // can be any logger implementing the Log trait /// /// info!("Connected to port {} at {} Mb/s", conn_info.port, conn_info.speed); -/// info!(target: "connection_events", "Successful connection, port: {}, speed: {}", -/// conn_info.port, conn_info.speed); -/// # } +/// info!( +/// target: "connection_events", +/// "Successful connection, port: {}, speed: {}", +/// conn_info.port, conn_info.speed +/// ); +/// info!( +/// logger: my_logger, +/// "Successful connection, port: {}, speed: {}", +/// conn_info.port, conn_info.speed +/// ); /// ``` #[macro_export] #[clippy::format_args] @@ -200,15 +243,15 @@ macro_rules! info { /// # Examples /// /// ``` -/// use log::debug; +/// use log::{debug, GlobalLogger}; /// -/// # fn main() { /// # struct Position { x: f32, y: f32 } /// let pos = Position { x: 3.234, y: -1.223 }; +/// let my_logger = GlobalLogger; // can be any logger implementing the Log trait /// /// debug!("New position: x: {}, y: {}", pos.x, pos.y); /// debug!(target: "app_events", "New position: x: {}, y: {}", pos.x, pos.y); -/// # } +/// debug!(logger: my_logger, "New position: x: {}, y: {}", pos.x, pos.y); /// ``` #[macro_export] #[clippy::format_args] @@ -240,17 +283,19 @@ macro_rules! debug { /// # Examples /// /// ``` -/// use log::trace; +/// use log::{trace, GlobalLogger}; /// -/// # fn main() { /// # struct Position { x: f32, y: f32 } /// let pos = Position { x: 3.234, y: -1.223 }; +/// let my_logger = GlobalLogger; // can be any logger implementing the Log trait /// /// trace!("Position is: x: {}, y: {}", pos.x, pos.y); /// trace!(target: "app_events", "x is {} and y is {}", /// if pos.x >= 0.0 { "positive" } else { "negative" }, /// if pos.y >= 0.0 { "positive" } else { "negative" }); -/// # } +/// trace!(logger: my_logger, "x is {} and y is {}", +/// if pos.x >= 0.0 { "positive" } else { "negative" }, +/// if pos.y >= 0.0 { "positive" } else { "negative" }); /// ``` #[macro_export] #[clippy::format_args] From 0bf505d472664531baac462f23985aa37ebfef7c Mon Sep 17 00:00:00 2001 From: tison Date: Mon, 17 Mar 2025 22:54:27 +0800 Subject: [PATCH 251/280] more docs Signed-off-by: tison --- src/macros.rs | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index 49166fe02..5207c0d75 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -117,10 +117,10 @@ macro_rules! log { /// # Examples /// /// ``` -/// use log::{error, GlobalLogger}; +/// use log::error; /// +/// # let my_logger = log::GlobalLogger; /// let (err_info, port) = ("No connection", 22); -/// let my_logger = GlobalLogger; // can be any logger implementing the Log trait /// /// error!("Error: {err_info} on port {port}"); /// error!(target: "app_events", "App Error: {err_info}, Port: {port}"); @@ -156,10 +156,10 @@ macro_rules! error { /// # Examples /// /// ``` -/// use log::{warn, GlobalLogger}; +/// use log::warn; /// +/// # let my_logger = log::GlobalLogger; /// let warn_description = "Invalid Input"; -/// let my_logger = GlobalLogger; // can be any logger implementing the Log trait /// /// warn!("Warning! {warn_description}!"); /// warn!(target: "input_events", "App received warning: {warn_description}"); @@ -195,11 +195,11 @@ macro_rules! warn { /// # Examples /// /// ``` -/// use log::{info, GlobalLogger}; +/// use log::info; /// +/// # let my_logger = log::GlobalLogger; /// # struct Connection { port: u32, speed: f32 } /// let conn_info = Connection { port: 40, speed: 3.20 }; -/// let my_logger = GlobalLogger; // can be any logger implementing the Log trait /// /// info!("Connected to port {} at {} Mb/s", conn_info.port, conn_info.speed); /// info!( @@ -243,11 +243,11 @@ macro_rules! info { /// # Examples /// /// ``` -/// use log::{debug, GlobalLogger}; +/// use log::debug; /// +/// # let my_logger = log::GlobalLogger; /// # struct Position { x: f32, y: f32 } /// let pos = Position { x: 3.234, y: -1.223 }; -/// let my_logger = GlobalLogger; // can be any logger implementing the Log trait /// /// debug!("New position: x: {}, y: {}", pos.x, pos.y); /// debug!(target: "app_events", "New position: x: {}, y: {}", pos.x, pos.y); @@ -283,11 +283,11 @@ macro_rules! debug { /// # Examples /// /// ``` -/// use log::{trace, GlobalLogger}; +/// use log::trace; /// +/// # let my_logger = log::GlobalLogger; /// # struct Position { x: f32, y: f32 } /// let pos = Position { x: 3.234, y: -1.223 }; -/// let my_logger = GlobalLogger; // can be any logger implementing the Log trait /// /// trace!("Position is: x: {}, y: {}", pos.x, pos.y); /// trace!(target: "app_events", "x is {} and y is {}", @@ -331,22 +331,25 @@ macro_rules! trace { /// # Examples /// /// ``` -/// use log::Level::Debug; -/// use log::{debug, log_enabled}; +/// use log::{debug, log_enabled, Level}; /// -/// # fn foo() { -/// if log_enabled!(Debug) { +/// # struct Data { x: u32, y: u32 } +/// # fn expensive_call() -> Data { Data { x: 0, y: 0 } } +/// # let my_logger = log::GlobalLogger; +/// if log_enabled!(Level::Debug) { /// let data = expensive_call(); /// debug!("expensive debug data: {} {}", data.x, data.y); /// } -/// if log_enabled!(target: "Global", Debug) { +/// +/// if log_enabled!(target: "Global", Level::Debug) { +/// let data = expensive_call(); +/// debug!(target: "Global", "expensive debug data: {} {}", data.x, data.y); +/// } +/// +/// if log_enabled!(logger: my_logger, Level::Debug) { /// let data = expensive_call(); /// debug!(target: "Global", "expensive debug data: {} {}", data.x, data.y); /// } -/// # } -/// # struct Data { x: u32, y: u32 } -/// # fn expensive_call() -> Data { Data { x: 0, y: 0 } } -/// # fn main() {} /// ``` #[macro_export] macro_rules! log_enabled { From 66a7ab7ff093c5da9c599cd2cd39b11fed3470e3 Mon Sep 17 00:00:00 2001 From: tison Date: Wed, 19 Mar 2025 07:07:46 +0800 Subject: [PATCH 252/280] address comment Signed-off-by: tison --- src/macros.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index 5207c0d75..0de7d5cde 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -70,9 +70,8 @@ macro_rules! log { (logger: $logger:expr, target: $target:expr, $lvl:expr, $($key:tt $(:$capture:tt)? $(= $value:expr)?),+; $($arg:tt)+) => ({ let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { - let logger = $logger; $crate::__private_api::log::<&_, _>( - logger, + $logger, $crate::__private_api::format_args!($($arg)+), lvl, &($target, $crate::__private_api::module_path!(), $crate::__private_api::loc()), @@ -85,9 +84,8 @@ macro_rules! log { (logger: $logger:expr, target: $target:expr, $lvl:expr, $($arg:tt)+) => ({ let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { - let logger = $logger; $crate::__private_api::log( - logger, + $logger, $crate::__private_api::format_args!($($arg)+), lvl, &($target, $crate::__private_api::module_path!(), $crate::__private_api::loc()), @@ -354,11 +352,10 @@ macro_rules! trace { #[macro_export] macro_rules! log_enabled { (logger: $logger:expr, target: $target:expr, $lvl:expr) => ({ - let logger = $logger; let lvl = $lvl; lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() - && $crate::__private_api::enabled(logger, lvl, $target) + && $crate::__private_api::enabled($logger, lvl, $target) }); (logger: $logger:expr, $lvl:expr) => ({ From 088f9f35ea3dd3ea6b75d8346e8a9dbcf406b430 Mon Sep 17 00:00:00 2001 From: tison Date: Fri, 21 Mar 2025 15:18:31 +0800 Subject: [PATCH 253/280] address comments Signed-off-by: tison --- src/__private_api.rs | 26 ++++++++++++++++++++++++-- src/lib.rs | 22 ---------------------- src/macros.rs | 20 ++++++++++---------- tests/macros.rs | 16 ++++++++-------- 4 files changed, 42 insertions(+), 42 deletions(-) diff --git a/src/__private_api.rs b/src/__private_api.rs index 57f038120..e2744bef6 100644 --- a/src/__private_api.rs +++ b/src/__private_api.rs @@ -1,7 +1,7 @@ //! WARNING: this is not part of the crate's public API and is subject to change at any time use self::sealed::KVs; -use crate::{Level, Log, Metadata, Record}; +use crate::{logger, Level, Log, Metadata, Record}; use std::fmt::Arguments; use std::panic::Location; pub use std::{format_args, module_path, stringify}; @@ -34,6 +34,28 @@ impl<'a> KVs<'a> for () { // Log implementation. +/// The global logger proxy. +/// +/// This zero-sized type implements the [`Log`] trait by forwarding calls +/// to the logger registered with the `set_boxed_logger` or `set_logger` +/// methods if there is one, or a nop logger as default. +#[derive(Copy, Clone, Default, Debug)] +pub struct GlobalLogger; + +impl Log for GlobalLogger { + fn enabled(&self, metadata: &Metadata) -> bool { + logger().enabled(metadata) + } + + fn log(&self, record: &Record) { + logger().log(record) + } + + fn flush(&self) { + logger().flush() + } +} + fn log_impl( logger: L, args: Arguments, @@ -63,7 +85,7 @@ fn log_impl( } pub fn log<'a, K, L>( - logger: L, + logger: &L, args: Arguments, level: Level, target_module_path_and_loc: &(&str, &'static str, &'static Location), diff --git a/src/lib.rs b/src/lib.rs index 2dd300874..054ce9c21 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1216,28 +1216,6 @@ impl Log for NopLogger { fn flush(&self) {} } -/// The global logger proxy. -/// -/// This zero-sized type implements the [`Log`] trait by forwarding calls -/// to the logger registered with the `set_boxed_logger` or `set_logger` -/// methods if there is one, or a nop logger as default. -#[derive(Copy, Clone, Default, Debug)] -pub struct GlobalLogger; - -impl Log for GlobalLogger { - fn enabled(&self, metadata: &Metadata) -> bool { - logger().enabled(metadata) - } - - fn log(&self, record: &Record) { - logger().log(record) - } - - fn flush(&self) { - logger().flush() - } -} - impl Log for &'_ T where T: ?Sized + Log, diff --git a/src/macros.rs b/src/macros.rs index 0de7d5cde..a20e8172b 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -71,7 +71,7 @@ macro_rules! log { let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { $crate::__private_api::log::<&_, _>( - $logger, + &($logger), $crate::__private_api::format_args!($($arg)+), lvl, &($target, $crate::__private_api::module_path!(), $crate::__private_api::loc()), @@ -85,7 +85,7 @@ macro_rules! log { let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { $crate::__private_api::log( - $logger, + &($logger), $crate::__private_api::format_args!($($arg)+), lvl, &($target, $crate::__private_api::module_path!(), $crate::__private_api::loc()), @@ -101,7 +101,7 @@ macro_rules! log { // log!(target: "my_target", Level::Info, "a log event") (target: $target:expr, $lvl:expr, $($arg:tt)+) => ({ - $crate::log!(logger: $crate::GlobalLogger, target: $target, $lvl, $($arg)+) + $crate::log!(logger: $crate::__private_api::GlobalLogger, target: $target, $lvl, $($arg)+) }); // log!(Level::Info, "a log event") @@ -117,7 +117,7 @@ macro_rules! log { /// ``` /// use log::error; /// -/// # let my_logger = log::GlobalLogger; +/// # let my_logger = log::__private_api::GlobalLogger; /// let (err_info, port) = ("No connection", 22); /// /// error!("Error: {err_info} on port {port}"); @@ -156,7 +156,7 @@ macro_rules! error { /// ``` /// use log::warn; /// -/// # let my_logger = log::GlobalLogger; +/// # let my_logger = log::__private_api::GlobalLogger; /// let warn_description = "Invalid Input"; /// /// warn!("Warning! {warn_description}!"); @@ -195,7 +195,7 @@ macro_rules! warn { /// ``` /// use log::info; /// -/// # let my_logger = log::GlobalLogger; +/// # let my_logger = log::__private_api::GlobalLogger; /// # struct Connection { port: u32, speed: f32 } /// let conn_info = Connection { port: 40, speed: 3.20 }; /// @@ -243,7 +243,7 @@ macro_rules! info { /// ``` /// use log::debug; /// -/// # let my_logger = log::GlobalLogger; +/// # let my_logger = log::__private_api::GlobalLogger; /// # struct Position { x: f32, y: f32 } /// let pos = Position { x: 3.234, y: -1.223 }; /// @@ -283,7 +283,7 @@ macro_rules! debug { /// ``` /// use log::trace; /// -/// # let my_logger = log::GlobalLogger; +/// # let my_logger = log::__private_api::GlobalLogger; /// # struct Position { x: f32, y: f32 } /// let pos = Position { x: 3.234, y: -1.223 }; /// @@ -333,7 +333,7 @@ macro_rules! trace { /// /// # struct Data { x: u32, y: u32 } /// # fn expensive_call() -> Data { Data { x: 0, y: 0 } } -/// # let my_logger = log::GlobalLogger; +/// # let my_logger = log::__private_api::GlobalLogger; /// if log_enabled!(Level::Debug) { /// let data = expensive_call(); /// debug!("expensive debug data: {} {}", data.x, data.y); @@ -363,7 +363,7 @@ macro_rules! log_enabled { }); (target: $target:expr, $lvl:expr) => ({ - $crate::log_enabled!(logger: $crate::GlobalLogger, target: $target, $lvl) + $crate::log_enabled!(logger: $crate::__private_api::GlobalLogger, target: $target, $lvl) }); ($lvl:expr) => ({ diff --git a/tests/macros.rs b/tests/macros.rs index e4023ea22..35b8c8981 100644 --- a/tests/macros.rs +++ b/tests/macros.rs @@ -10,9 +10,9 @@ macro_rules! all_log_macros { }); } -struct NopLogger; +struct Logger; -impl Log for NopLogger { +impl Log for Logger { fn enabled(&self, _: &Metadata) -> bool { false } @@ -39,10 +39,10 @@ fn no_args() { all_log_macros!(target: "my_target", "hello"); all_log_macros!(target: "my_target", "hello",); - all_log_macros!(logger: NopLogger, "hello"); - all_log_macros!(logger: NopLogger, "hello",); - all_log_macros!(logger: NopLogger, target: "my_target", "hello"); - all_log_macros!(logger: NopLogger, target: "my_target", "hello",); + all_log_macros!(logger: Logger, "hello"); + all_log_macros!(logger: Logger, "hello",); + all_log_macros!(logger: Logger, target: "my_target", "hello"); + all_log_macros!(logger: Logger, target: "my_target", "hello",); } #[test] @@ -130,8 +130,8 @@ fn kv_no_args() { log!(lvl, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); } - all_log_macros!(logger: NopLogger, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); - all_log_macros!(logger: NopLogger, target: "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); + all_log_macros!(logger: Logger, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); + all_log_macros!(logger: Logger, target: "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); all_log_macros!(target: "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); all_log_macros!(target = "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); all_log_macros!(cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); From 7aacc8fea367dd6518f02db792af8b6215ed33d6 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Sun, 23 Mar 2025 14:22:24 +1000 Subject: [PATCH 254/280] pass global logger by value, supplied logger by ref --- src/__private_api.rs | 2 +- src/macros.rs | 126 +++++++++++++++++++++++++++++++------------ 2 files changed, 92 insertions(+), 36 deletions(-) diff --git a/src/__private_api.rs b/src/__private_api.rs index e2744bef6..609374757 100644 --- a/src/__private_api.rs +++ b/src/__private_api.rs @@ -85,7 +85,7 @@ fn log_impl( } pub fn log<'a, K, L>( - logger: &L, + logger: L, args: Arguments, level: Level, target_module_path_and_loc: &(&str, &'static str, &'static Location), diff --git a/src/macros.rs b/src/macros.rs index a20e8172b..ff2dd8c5a 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -66,12 +66,56 @@ #[macro_export] #[clippy::format_args] macro_rules! log { + // log!(logger: my_logger, target: "my_target", Level::Info, "a {} event", "log"); + (logger: $logger:expr, target: $target:expr, $lvl:expr, $($arg:tt)+) => ({ + $crate::__log!( + logger: $crate::__log_logger!($logger), + target: $target, + $lvl, + $($arg)+ + ) + }); + + // log!(logger: my_logger, Level::Info, "a log event") + (logger: $logger:expr, $lvl:expr, $($arg:tt)+) => ({ + $crate::__log!( + logger: $crate::__log_logger!($logger), + target: $crate::__private_api::module_path!(), + $lvl, + $($arg)+ + ) + }); + + // log!(target: "my_target", Level::Info, "a log event") + (target: $target:expr, $lvl:expr, $($arg:tt)+) => ({ + $crate::__log!( + logger: $crate::__log_logger!(__log_global_logger), + target: $target, + $lvl, + $($arg)+ + ) + }); + + // log!(Level::Info, "a log event") + ($lvl:expr, $($arg:tt)+) => ({ + $crate::__log!( + logger: $crate::__log_logger!(__log_global_logger), + target: $crate::__private_api::module_path!(), + $lvl, + $($arg)+ + ) + }); +} + +#[doc(hidden)] +#[macro_export] +macro_rules! __log { // log!(logger: my_logger, target: "my_target", Level::Info, key1:? = 42, key2 = true; "a {} event", "log"); (logger: $logger:expr, target: $target:expr, $lvl:expr, $($key:tt $(:$capture:tt)? $(= $value:expr)?),+; $($arg:tt)+) => ({ let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { - $crate::__private_api::log::<&_, _>( - &($logger), + $crate::__private_api::log( + $logger, $crate::__private_api::format_args!($($arg)+), lvl, &($target, $crate::__private_api::module_path!(), $crate::__private_api::loc()), @@ -85,7 +129,7 @@ macro_rules! log { let lvl = $lvl; if lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() { $crate::__private_api::log( - &($logger), + $logger, $crate::__private_api::format_args!($($arg)+), lvl, &($target, $crate::__private_api::module_path!(), $crate::__private_api::loc()), @@ -93,21 +137,6 @@ macro_rules! log { ); } }); - - // log!(logger: my_logger, Level::Info, "a log event") - (logger: $logger:expr, $lvl:expr, $($arg:tt)+) => ({ - $crate::log!(logger: $logger, target: $crate::__private_api::module_path!(), $lvl, $($arg)+) - }); - - // log!(target: "my_target", Level::Info, "a log event") - (target: $target:expr, $lvl:expr, $($arg:tt)+) => ({ - $crate::log!(logger: $crate::__private_api::GlobalLogger, target: $target, $lvl, $($arg)+) - }); - - // log!(Level::Info, "a log event") - ($lvl:expr, $($arg:tt)+) => ({ - $crate::log!(target: $crate::__private_api::module_path!(), $lvl, $($arg)+) - }); } /// Logs a message at the error level. @@ -130,13 +159,13 @@ macro_rules! error { // error!(logger: my_logger, target: "my_target", key1 = 42, key2 = true; "a {} event", "log") // error!(logger: my_logger, target: "my_target", "a {} event", "log") (logger: $logger:expr, target: $target:expr, $($arg:tt)+) => ({ - $crate::log!(logger: $logger, target: $target, $crate::Level::Error, $($arg)+) + $crate::log!(logger: $crate::__log_logger!($logger), target: $target, $crate::Level::Error, $($arg)+) }); // error!(logger: my_logger, key1 = 42, key2 = true; "a {} event", "log") // error!(logger: my_logger, "a {} event", "log") (logger: $logger:expr, $($arg:tt)+) => ({ - $crate::log!(logger: $logger, $crate::Level::Error, $($arg)+) + $crate::log!(logger: $crate::__log_logger!($logger), $crate::Level::Error, $($arg)+) }); // error!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log") @@ -169,13 +198,13 @@ macro_rules! warn { // warn!(logger: my_logger, target: "my_target", key1 = 42, key2 = true; "a {} event", "log") // warn!(logger: my_logger, target: "my_target", "a {} event", "log") (logger: $logger:expr, target: $target:expr, $($arg:tt)+) => ({ - $crate::log!(logger: $logger, target: $target, $crate::Level::Warn, $($arg)+) + $crate::log!(logger: $crate::__log_logger!($logger), target: $target, $crate::Level::Warn, $($arg)+) }); // warn!(logger: my_logger, key1 = 42, key2 = true; "a {} event", "log") // warn!(logger: my_logger, "a {} event", "log") (logger: $logger:expr, $($arg:tt)+) => ({ - $crate::log!(logger: $logger, $crate::Level::Warn, $($arg)+) + $crate::log!(logger: $crate::__log_logger!($logger), $crate::Level::Warn, $($arg)+) }); // warn!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log") @@ -217,13 +246,13 @@ macro_rules! info { // info!(logger: my_logger, target: "my_target", key1 = 42, key2 = true; "a {} event", "log") // info!(logger: my_logger, target: "my_target", "a {} event", "log") (logger: $logger:expr, target: $target:expr, $($arg:tt)+) => ({ - $crate::log!(logger: $logger, target: $target, $crate::Level::Info, $($arg)+) + $crate::log!(logger: $crate::__log_logger!($logger), target: $target, $crate::Level::Info, $($arg)+) }); // info!(logger: my_logger, key1 = 42, key2 = true; "a {} event", "log") // info!(logger: my_logger, "a {} event", "log") (logger: $logger:expr, $($arg:tt)+) => ({ - $crate::log!(logger: $logger, $crate::Level::Info, $($arg)+) + $crate::log!(logger: $crate::__log_logger!($logger), $crate::Level::Info, $($arg)+) }); // info!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log") @@ -257,13 +286,13 @@ macro_rules! debug { // debug!(logger: my_logger, target: "my_target", key1 = 42, key2 = true; "a {} event", "log") // debug!(logger: my_logger, target: "my_target", "a {} event", "log") (logger: $logger:expr, target: $target:expr, $($arg:tt)+) => ({ - $crate::log!(logger: $logger, target: $target, $crate::Level::Debug, $($arg)+) + $crate::log!(logger: $crate::__log_logger!($logger), target: $target, $crate::Level::Debug, $($arg)+) }); // debug!(logger: my_logger, key1 = 42, key2 = true; "a {} event", "log") // debug!(logger: my_logger, "a {} event", "log") (logger: $logger:expr, $($arg:tt)+) => ({ - $crate::log!(logger: $logger, $crate::Level::Debug, $($arg)+) + $crate::log!(logger: $crate::__log_logger!($logger), $crate::Level::Debug, $($arg)+) }); // debug!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log") @@ -301,13 +330,13 @@ macro_rules! trace { // trace!(logger: my_logger, target: "my_target", key1 = 42, key2 = true; "a {} event", "log") // trace!(logger: my_logger, target: "my_target", "a {} event", "log") (logger: $logger:expr, target: $target:expr, $($arg:tt)+) => ({ - $crate::log!(logger: $logger, target: $target, $crate::Level::Trace, $($arg)+) + $crate::log!(logger: $crate::__log_logger!($logger), target: $target, $crate::Level::Trace, $($arg)+) }); // trace!(logger: my_logger, key1 = 42, key2 = true; "a {} event", "log") // trace!(logger: my_logger, "a {} event", "log") (logger: $logger:expr, $($arg:tt)+) => ({ - $crate::log!(logger: $logger, $crate::Level::Trace, $($arg)+) + $crate::log!(logger: $crate::__log_logger!($logger), $crate::Level::Trace, $($arg)+) }); // trace!(target: "my_target", key1 = 42, key2 = true; "a {} event", "log") @@ -351,23 +380,50 @@ macro_rules! trace { /// ``` #[macro_export] macro_rules! log_enabled { + // log_enabled!(logger: my_logger, target: "my_target", Level::Info) (logger: $logger:expr, target: $target:expr, $lvl:expr) => ({ - let lvl = $lvl; - lvl <= $crate::STATIC_MAX_LEVEL - && lvl <= $crate::max_level() - && $crate::__private_api::enabled($logger, lvl, $target) + $crate::__log_enabled!(logger: $crate::__log_logger!($logger), target: $target, $lvl) }); + // log_enabled!(logger: my_logger, Level::Info) (logger: $logger:expr, $lvl:expr) => ({ - $crate::log_enabled!(logger: $logger, target: $crate::__private_api::module_path!(), $lvl) + $crate::__log_enabled!(logger: $crate::__log_logger!($logger), target: $crate::__private_api::module_path!(), $lvl) }); + // log_enabled!(target: "my_target", Level::Info) (target: $target:expr, $lvl:expr) => ({ - $crate::log_enabled!(logger: $crate::__private_api::GlobalLogger, target: $target, $lvl) + $crate::__log_enabled!(logger: $crate::__log_logger!(__log_global_logger), target: $target, $lvl) }); + // log_enabled!(Level::Info) ($lvl:expr) => ({ - $crate::log_enabled!(target: $crate::__private_api::module_path!(), $lvl) + $crate::__log_enabled!(logger: $crate::__log_logger!(__log_global_logger), target: $crate::__private_api::module_path!(), $lvl) + }); +} + +#[doc(hidden)] +#[macro_export] +macro_rules! __log_enabled { + // log_enabled!(logger: my_logger, target: "my_target", Level::Info) + (logger: $logger:expr, target: $target:expr, $lvl:expr) => ({ + let lvl = $lvl; + lvl <= $crate::STATIC_MAX_LEVEL + && lvl <= $crate::max_level() + && $crate::__private_api::enabled($logger, lvl, $target) + }); +} + +// Determine the logger to use, and whether to take it by-value or by reference + +#[doc(hidden)] +#[macro_export] +macro_rules! __log_logger { + (__log_global_logger) => ({ + $crate::__private_api::GlobalLogger + }); + + ($logger:expr) => ({ + &($logger) }); } From 39d4c3ab88b5d4096ce9c8d795e9a1187e83c9d6 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Sun, 23 Mar 2025 14:24:43 +1000 Subject: [PATCH 255/280] run fmt --- src/macros.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/macros.rs b/src/macros.rs index ff2dd8c5a..5f0e49f18 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -405,12 +405,12 @@ macro_rules! log_enabled { #[macro_export] macro_rules! __log_enabled { // log_enabled!(logger: my_logger, target: "my_target", Level::Info) - (logger: $logger:expr, target: $target:expr, $lvl:expr) => ({ + (logger: $logger:expr, target: $target:expr, $lvl:expr) => {{ let lvl = $lvl; lvl <= $crate::STATIC_MAX_LEVEL && lvl <= $crate::max_level() && $crate::__private_api::enabled($logger, lvl, $target) - }); + }}; } // Determine the logger to use, and whether to take it by-value or by reference @@ -418,13 +418,13 @@ macro_rules! __log_enabled { #[doc(hidden)] #[macro_export] macro_rules! __log_logger { - (__log_global_logger) => ({ + (__log_global_logger) => {{ $crate::__private_api::GlobalLogger - }); + }}; - ($logger:expr) => ({ + ($logger:expr) => {{ &($logger) - }); + }}; } // These macros use a pattern of #[cfg]s to produce nicer error From dfa067e65c49db82b2ace612982007efef09b8b4 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Sun, 23 Mar 2025 14:25:45 +1000 Subject: [PATCH 256/280] fix up kv passing --- src/macros.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/macros.rs b/src/macros.rs index 5f0e49f18..dc51f6c83 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -119,7 +119,7 @@ macro_rules! __log { $crate::__private_api::format_args!($($arg)+), lvl, &($target, $crate::__private_api::module_path!(), $crate::__private_api::loc()), - &[$(($crate::__log_key!($key), $crate::__log_value!($key $(:$capture)* = $($value)*))),+] + &[$(($crate::__log_key!($key), $crate::__log_value!($key $(:$capture)* = $($value)*))),+] as &[_], ); } }); From 71e034ffa62b79aa67acda4b1569493bc5f9e107 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Mon, 24 Mar 2025 05:45:35 +1000 Subject: [PATCH 257/280] expand logger tests --- tests/macros.rs | 110 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 101 insertions(+), 9 deletions(-) diff --git a/tests/macros.rs b/tests/macros.rs index 35b8c8981..dded475c1 100644 --- a/tests/macros.rs +++ b/tests/macros.rs @@ -10,6 +10,7 @@ macro_rules! all_log_macros { }); } +// Not `Copy` struct Logger; impl Log for Logger { @@ -22,6 +23,8 @@ impl Log for Logger { #[test] fn no_args() { + let logger = Logger; + for lvl in log::Level::iter() { log!(lvl, "hello"); log!(lvl, "hello",); @@ -29,8 +32,11 @@ fn no_args() { log!(target: "my_target", lvl, "hello"); log!(target: "my_target", lvl, "hello",); - log!(lvl, "hello"); - log!(lvl, "hello",); + log!(logger: logger, lvl, "hello"); + log!(logger: logger, lvl, "hello",); + + log!(logger: logger, target: "my_target", lvl, "hello"); + log!(logger: logger, target: "my_target", lvl, "hello",); } all_log_macros!("hello"); @@ -39,10 +45,11 @@ fn no_args() { all_log_macros!(target: "my_target", "hello"); all_log_macros!(target: "my_target", "hello",); - all_log_macros!(logger: Logger, "hello"); - all_log_macros!(logger: Logger, "hello",); - all_log_macros!(logger: Logger, target: "my_target", "hello"); - all_log_macros!(logger: Logger, target: "my_target", "hello",); + all_log_macros!(logger: logger, "hello"); + all_log_macros!(logger: logger, "hello",); + + all_log_macros!(logger: logger, target: "my_target", "hello"); + all_log_macros!(logger: logger, target: "my_target", "hello",); } #[test] @@ -63,6 +70,14 @@ fn anonymous_args() { all_log_macros!(target: "my_target", "hello {}", "world"); all_log_macros!(target: "my_target", "hello {}", "world",); + + let logger = Logger; + + all_log_macros!(logger: logger, "hello {}", "world"); + all_log_macros!(logger: logger, "hello {}", "world",); + + all_log_macros!(logger: logger, target: "my_target", "hello {}", "world"); + all_log_macros!(logger: logger, target: "my_target", "hello {}", "world",); } #[test] @@ -83,6 +98,14 @@ fn named_args() { all_log_macros!(target: "my_target", "hello {world}", world = "world"); all_log_macros!(target: "my_target", "hello {world}", world = "world",); + + let logger = Logger; + + all_log_macros!(logger: logger, "hello {world}", world = "world"); + all_log_macros!(logger: logger, "hello {world}", world = "world",); + + all_log_macros!(logger: logger, target: "my_target", "hello {world}", world = "world"); + all_log_macros!(logger: logger, target: "my_target", "hello {world}", world = "world",); } #[test] @@ -105,81 +128,136 @@ fn inlined_args() { all_log_macros!(target: "my_target", "hello {world}"); all_log_macros!(target: "my_target", "hello {world}",); + + let logger = Logger; + + all_log_macros!(logger: logger, "hello {world}"); + all_log_macros!(logger: logger, "hello {world}",); + + all_log_macros!(logger: logger, target: "my_target", "hello {world}"); + all_log_macros!(logger: logger, target: "my_target", "hello {world}",); } #[test] fn enabled() { + let logger = Logger; + for lvl in log::Level::iter() { + let _enabled = log_enabled!(lvl); let _enabled = log_enabled!(target: "my_target", lvl); + let _enabled = log_enabled!(logger: logger, target: "my_target", lvl); + let _enabled = log_enabled!(logger: logger, lvl); } } #[test] fn expr() { + let logger = Logger; + for lvl in log::Level::iter() { log!(lvl, "hello"); + + log!(logger: logger, lvl, "hello"); } } #[test] #[cfg(feature = "kv")] fn kv_no_args() { + let logger = Logger; + for lvl in log::Level::iter() { log!(target: "my_target", lvl, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); - log!(lvl, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); + + log!(logger: logger, target: "my_target", lvl, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); + log!(logger: logger, lvl, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); } - all_log_macros!(logger: Logger, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); - all_log_macros!(logger: Logger, target: "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); all_log_macros!(target: "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); all_log_macros!(target = "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); all_log_macros!(cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); + + all_log_macros!(logger: logger, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); + all_log_macros!(logger: logger, target: "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello"); } #[test] #[cfg(feature = "kv")] fn kv_expr_args() { + let logger = Logger; + for lvl in log::Level::iter() { log!(target: "my_target", lvl, cat_math = { let mut x = 0; x += 1; x + 1 }; "hello"); log!(lvl, target = "my_target", cat_math = { let mut x = 0; x += 1; x + 1 }; "hello"); log!(lvl, cat_math = { let mut x = 0; x += 1; x + 1 }; "hello"); + + log!(logger: logger, target: "my_target", lvl, cat_math = { let mut x = 0; x += 1; x + 1 }; "hello"); + + log!(logger: logger, lvl, target = "my_target", cat_math = { let mut x = 0; x += 1; x + 1 }; "hello"); + log!(logger: logger, lvl, cat_math = { let mut x = 0; x += 1; x + 1 }; "hello"); } all_log_macros!(target: "my_target", cat_math = { let mut x = 0; x += 1; x + 1 }; "hello"); all_log_macros!(target = "my_target", cat_math = { let mut x = 0; x += 1; x + 1 }; "hello"); all_log_macros!(cat_math = { let mut x = 0; x += 1; x + 1 }; "hello"); + + all_log_macros!(logger: logger, target: "my_target", cat_math = { let mut x = 0; x += 1; x + 1 }; "hello"); + all_log_macros!(logger: logger, target = "my_target", cat_math = { let mut x = 0; x += 1; x + 1 }; "hello"); + all_log_macros!(logger: logger, cat_math = { let mut x = 0; x += 1; x + 1 }; "hello"); } #[test] #[cfg(feature = "kv")] fn kv_anonymous_args() { + let logger = Logger; + for lvl in log::Level::iter() { log!(target: "my_target", lvl, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {}", "world"); log!(lvl, target = "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {}", "world"); log!(lvl, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {}", "world"); + + log!(logger: logger, target: "my_target", lvl, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {}", "world"); + log!(logger: logger, lvl, target = "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {}", "world"); + + log!(logger: logger, lvl, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {}", "world"); } all_log_macros!(target: "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {}", "world"); all_log_macros!(target = "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {}", "world"); all_log_macros!(cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {}", "world"); + + all_log_macros!(logger: logger, target: "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {}", "world"); + all_log_macros!(logger: logger, target = "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {}", "world"); + all_log_macros!(logger: logger, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {}", "world"); } #[test] #[cfg(feature = "kv")] fn kv_named_args() { + let logger = Logger; + for lvl in log::Level::iter() { log!(target: "my_target", lvl, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}", world = "world"); log!(lvl, target = "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}", world = "world"); log!(lvl, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}", world = "world"); + + log!(logger: logger, target: "my_target", lvl, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}", world = "world"); + log!(logger: logger, lvl, target = "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}", world = "world"); + + log!(logger: logger, lvl, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}", world = "world"); } all_log_macros!(target: "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}", world = "world"); all_log_macros!(target = "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}", world = "world"); all_log_macros!(cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}", world = "world"); + + all_log_macros!(logger: logger, target: "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}", world = "world"); + all_log_macros!(logger: logger, target = "my_target", cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}", world = "world"); + all_log_macros!(logger: logger, cat_1 = "chashu", cat_2 = "nori", cat_count = 2; "hello {world}", world = "world"); } #[test] @@ -323,6 +401,20 @@ fn kv_serde() { ); } +#[test] +fn logger_short_lived() { + all_log_macros!(logger: Logger, "hello"); + all_log_macros!(logger: &Logger, "hello"); +} + +#[test] +fn logger_expr() { + all_log_macros!(logger: { + let logger = Logger; + logger + }, "hello"); +} + /// Some and None (from Option) are used in the macros. #[derive(Debug)] enum Type { From 02486e458cfc8e5e6a0a5bc0586db095a3e33b87 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Mon, 24 Mar 2025 05:56:21 +1000 Subject: [PATCH 258/280] fill in more tests for logger argument --- src/__private_api.rs | 7 ++----- src/macros.rs | 10 +++++++++- tests/integration.rs | 8 -------- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/__private_api.rs b/src/__private_api.rs index 609374757..58d4c0fab 100644 --- a/src/__private_api.rs +++ b/src/__private_api.rs @@ -35,11 +35,7 @@ impl<'a> KVs<'a> for () { // Log implementation. /// The global logger proxy. -/// -/// This zero-sized type implements the [`Log`] trait by forwarding calls -/// to the logger registered with the `set_boxed_logger` or `set_logger` -/// methods if there is one, or a nop logger as default. -#[derive(Copy, Clone, Default, Debug)] +#[derive(Debug)] pub struct GlobalLogger; impl Log for GlobalLogger { @@ -56,6 +52,7 @@ impl Log for GlobalLogger { } } +// Split from `log` to reduce generics and code size fn log_impl( logger: L, args: Arguments, diff --git a/src/macros.rs b/src/macros.rs index dc51f6c83..b03ae5c67 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -58,11 +58,17 @@ /// /// let my_logger = MyLogger {}; /// log!( -/// logger: &my_logger, +/// logger: my_logger, /// Level::Error, /// "Received errors: {}, {}", /// data.0, data.1 /// ); +/// +/// The `logger` argument accepts a value that implements the `Log` trait. The value +/// will be borrowed within the macro. +/// +/// Note that the global level set via Cargo features, or through `set_max_level` will +/// still apply, even when a custom logger is supplied with the `logger` argument. #[macro_export] #[clippy::format_args] macro_rules! log { @@ -378,6 +384,8 @@ macro_rules! trace { /// debug!(target: "Global", "expensive debug data: {} {}", data.x, data.y); /// } /// ``` +/// +/// This macro accepts the same `target` and `logger` arguments as [`macro@log`]. #[macro_export] macro_rules! log_enabled { // log_enabled!(logger: my_logger, target: "my_target", Level::Info) diff --git a/tests/integration.rs b/tests/integration.rs index 14f7a427d..0b8522d71 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -3,14 +3,6 @@ use log::{debug, error, info, trace, warn, Level, LevelFilter, Log, Metadata, Record}; use std::sync::{Arc, Mutex}; -#[cfg(feature = "std")] -use log::set_boxed_logger; - -#[cfg(not(feature = "std"))] -fn set_boxed_logger(logger: Box) -> Result<(), log::SetLoggerError> { - log::set_logger(Box::leak(logger)) -} - struct State { last_log_level: Mutex>, last_log_location: Mutex>, From d229c7355bb2d985454a99846f57b51fd4ad58d4 Mon Sep 17 00:00:00 2001 From: KodrAus Date: Mon, 24 Mar 2025 06:09:40 +1000 Subject: [PATCH 259/280] fix unclosed code block --- src/macros.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/macros.rs b/src/macros.rs index b03ae5c67..14e4ac64b 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -63,6 +63,7 @@ /// "Received errors: {}, {}", /// data.0, data.1 /// ); +/// ``` /// /// The `logger` argument accepts a value that implements the `Log` trait. The value /// will be borrowed within the macro. From cc131ef268bb3214c14fea43a409d1fec62fb32f Mon Sep 17 00:00:00 2001 From: KodrAus Date: Mon, 24 Mar 2025 08:07:39 +1000 Subject: [PATCH 260/280] prepare for 0.4.27 release --- CHANGELOG.md | 14 +++++++++++++- Cargo.toml | 2 +- src/lib.rs | 2 +- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 11cfaea37..87a98937e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,17 @@ ## [Unreleased] +## [0.4.27] - 2025-03-24 + +## What's Changed +* A few minor lint fixes by @nyurik in https://github.com/rust-lang/log/pull/671 +* Enable clippy support for format-like macros by @nyurik in https://github.com/rust-lang/log/pull/665 +* Add an optional logger param by @tisonkun in https://github.com/rust-lang/log/pull/664 +* Pass global logger by value, supplied logger by ref by @KodrAus in https://github.com/rust-lang/log/pull/673 + + +**Full Changelog**: https://github.com/rust-lang/log/compare/0.4.26...0.4.27 + ## [0.4.26] - 2025-02-18 ## What's Changed @@ -347,7 +358,8 @@ version using log 0.4.x to avoid losing module and file information. Look at the [release tags] for information about older releases. -[Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.26...HEAD +[Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.27...HEAD +[0.4.27]: https://github.com/rust-lang/log/compare/0.4.26...0.4.27 [0.4.26]: https://github.com/rust-lang/log/compare/0.4.25...0.4.26 [0.4.25]: https://github.com/rust-lang/log/compare/0.4.24...0.4.25 [0.4.24]: https://github.com/rust-lang/log/compare/0.4.23...0.4.24 diff --git a/Cargo.toml b/Cargo.toml index 0c8b53763..00d3a7ce3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "log" -version = "0.4.26" # remember to update html_root_url +version = "0.4.27" # remember to update html_root_url authors = ["The Rust Project Developers"] license = "MIT OR Apache-2.0" readme = "README.md" diff --git a/src/lib.rs b/src/lib.rs index 054ce9c21..eb37f55cc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -344,7 +344,7 @@ #![doc( html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://www.rust-lang.org/favicon.ico", - html_root_url = "https://docs.rs/log/0.4.26" + html_root_url = "https://docs.rs/log/0.4.27" )] #![warn(missing_docs)] #![deny(missing_debug_implementations, unconditional_recursion)] From e52ac8d10f115ca00503eb378fa49d5e31bcebfb Mon Sep 17 00:00:00 2001 From: tison Date: Mon, 24 Mar 2025 08:54:57 +0800 Subject: [PATCH 261/280] ci: drop really old trick and use new actions Signed-off-by: tison --- .github/workflows/main.yml | 123 ++++++++++++++----------------------- tests/Cargo.toml | 22 ------- tests/src/build.rs | 5 -- tests/src/lib.rs | 14 ----- 4 files changed, 47 insertions(+), 117 deletions(-) delete mode 100644 tests/Cargo.toml delete mode 100644 tests/src/build.rs delete mode 100644 tests/src/lib.rs diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 893e7e7d9..4e9b95152 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,101 +1,77 @@ name: CI on: [push, pull_request] -permissions: - contents: read # to fetch code (actions/checkout) - jobs: test: name: Test runs-on: ${{ matrix.os }} strategy: matrix: - build: [stable, beta, nightly, macos, win32, win64, mingw] include: - build: stable - os: ubuntu-latest + os: ubuntu-24.04 rust: stable - build: beta - os: ubuntu-latest + os: ubuntu-24.04 rust: beta - build: nightly - os: ubuntu-latest + os: ubuntu-24.04 rust: nightly - build: macos - os: macos-latest + os: macos-14 rust: stable - build: win32 - os: windows-latest + os: windows-2022 rust: stable-i686-pc-windows-msvc - build: win64 - os: windows-latest + os: windows-2022 rust: stable-x86_64-pc-windows-msvc - build: mingw - os: windows-latest + os: windows-2022 rust: stable-x86_64-pc-windows-gnu steps: - - uses: actions/checkout@master - - name: Install Rust - run: | - rustup update ${{ matrix.rust }} --no-self-update - rustup default ${{ matrix.rust }} - cargo install cargo-hack + - uses: actions/checkout@v4 + - name: Install toolchain + uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.rust }} + - uses: taiki-e/install-action@cargo-hack - run: cargo hack test --feature-powerset --lib --exclude-features max_level_off,max_level_error,max_level_warn,max_level_info,max_level_debug,max_level_trace,release_max_level_off,release_max_level_error,release_max_level_warn,release_max_level_info,release_max_level_debug,release_max_level_trace - run: cargo run --verbose --manifest-path test_max_level_features/Cargo.toml - run: cargo run --verbose --manifest-path test_max_level_features/Cargo.toml --release - rustfmt: - name: Rustfmt - runs-on: ubuntu-latest + check: + name: Check Format and Clippy + runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@master - - name: Install Rust - run: | - rustup update stable --no-self-update - rustup default stable - rustup component add rustfmt - # log repo does not use Cargo workspaces, so `cargo fmt` will not check all the code - # perhaps this should be changed in the future + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + components: clippy,rustfmt - run: cargo fmt -- --check - run: cargo fmt --manifest-path test_max_level_features/Cargo.toml -- --check - - run: cargo fmt --manifest-path tests/Cargo.toml -- --check - - clippy: - name: Clippy - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@master - - name: Install Rust - run: | - rustup update stable --no-self-update - rustup default stable - rustup component add clippy - run: cargo clippy --verbose - run: cargo clippy --verbose --manifest-path test_max_level_features/Cargo.toml - - run: cargo clippy --verbose --manifest-path tests/Cargo.toml doc: name: Check Documentation - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@master - - name: Install Rust - run: | - rustup update stable --no-self-update - rustup default stable - rustup component add rust-docs + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable + with: + components: rust-docs - name: Run rustdoc - run: RUSTDOCFLAGS="-D warnings" cargo doc --verbose --features std,serde,sval,sval_ref,value-bag,kv,kv_std,kv_sval,kv_serde + env: + RUSTDOCFLAGS: "-D warnings" + run: cargo doc --verbose --features std,serde,sval,sval_ref,value-bag,kv,kv_std,kv_sval,kv_serde features: name: Feature check - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@master - - name: Install Rust - run: | - rustup update nightly --no-self-update - rustup default nightly + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@nightly - run: cargo build --verbose -Z avoid-dev-deps --features kv - run: cargo build --verbose -Z avoid-dev-deps --features "kv std" - run: cargo build --verbose -Z avoid-dev-deps --features "kv kv_sval" @@ -105,13 +81,10 @@ jobs: minimalv: name: Minimal versions - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@master - - name: Install Rust - run: | - rustup update nightly --no-self-update - rustup default nightly + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@nightly - run: cargo build --verbose -Z minimal-versions --features kv - run: cargo build --verbose -Z minimal-versions --features "kv std" - run: cargo build --verbose -Z minimal-versions --features "kv kv_sval" @@ -121,26 +94,24 @@ jobs: msrv: name: MSRV - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@master - - name: Install Rust - run: | - rustup update 1.60.0 --no-self-update - rustup default 1.60.0 - - run: | - cargo test --verbose --manifest-path tests/Cargo.toml - cargo test --verbose --manifest-path tests/Cargo.toml --features kv + - uses: actions/checkout@v4 + - name: Install toolchain + uses: dtolnay/rust-toolchain@master + with: + toolchain: 1.60.0 + - uses: taiki-e/install-action@cargo-hack + - run: cargo hack test --feature-powerset --lib --exclude-features max_level_off,max_level_error,max_level_warn,max_level_info,max_level_debug,max_level_trace,release_max_level_off,release_max_level_error,release_max_level_warn,release_max_level_info,release_max_level_debug,release_max_level_trace + - run: cargo run --verbose --manifest-path test_max_level_features/Cargo.toml + - run: cargo run --verbose --manifest-path test_max_level_features/Cargo.toml --release embedded: name: Embedded - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 steps: - - uses: actions/checkout@master - - name: Install Rust - run: | - rustup update stable --no-self-update - rustup default stable + - uses: actions/checkout@v4 + - uses: dtolnay/rust-toolchain@stable - run: rustup target add thumbv6m-none-eabi riscv32imc-unknown-none-elf - run: cargo build --verbose --target=thumbv6m-none-eabi - run: cargo build --verbose --target=riscv32imc-unknown-none-elf diff --git a/tests/Cargo.toml b/tests/Cargo.toml deleted file mode 100644 index bc8621558..000000000 --- a/tests/Cargo.toml +++ /dev/null @@ -1,22 +0,0 @@ -[package] -name = "integration" -version = "0.1.0" -edition = "2021" -publish = false -build = "src/build.rs" - -[lints.rust] -unexpected_cfgs = { level = "allow", check-cfg = ['cfg(lib_build)'] } - -[features] -std = ["log/std"] -kv = ["log/kv"] -kv_std = ["log/kv_std"] -kv_sval = ["log/kv_sval"] -kv_serde = ["log/kv_serde"] - -[dependencies.log] -path = ".." - -[dev-dependencies.rustversion] -version = "1.0" diff --git a/tests/src/build.rs b/tests/src/build.rs deleted file mode 100644 index b10fea125..000000000 --- a/tests/src/build.rs +++ /dev/null @@ -1,5 +0,0 @@ -fn main() { - println!("cargo:rustc-cfg=lib_build"); - - println!("cargo:rerun-if-changed=src/build.rs"); -} diff --git a/tests/src/lib.rs b/tests/src/lib.rs deleted file mode 100644 index a4835fabc..000000000 --- a/tests/src/lib.rs +++ /dev/null @@ -1,14 +0,0 @@ -//! This crate is intentionally left empty. -//! -//! We have an empty library depending on `log` here, so we can run integration tests -//! on older compilers without depending on the unstable `no-dev-deps` flag. - -#![allow(dead_code)] - -#[cfg(test)] -#[path = "../integration.rs"] -mod integration; - -#[cfg(test)] -#[path = "../macros.rs"] -mod macros; From 26f662526df916583877717df9e77510deb92aaf Mon Sep 17 00:00:00 2001 From: tison Date: Mon, 24 Mar 2025 08:59:24 +0800 Subject: [PATCH 262/280] serde requires 1.61+ Signed-off-by: tison --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4e9b95152..bd834e344 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -102,7 +102,7 @@ jobs: with: toolchain: 1.60.0 - uses: taiki-e/install-action@cargo-hack - - run: cargo hack test --feature-powerset --lib --exclude-features max_level_off,max_level_error,max_level_warn,max_level_info,max_level_debug,max_level_trace,release_max_level_off,release_max_level_error,release_max_level_warn,release_max_level_info,release_max_level_debug,release_max_level_trace + - run: cargo hack test --feature-powerset --lib --exclude-features serde,kv_serde,kv_unstable_serde,max_level_off,max_level_error,max_level_warn,max_level_info,max_level_debug,max_level_trace,release_max_level_off,release_max_level_error,release_max_level_warn,release_max_level_info,release_max_level_debug,release_max_level_trace - run: cargo run --verbose --manifest-path test_max_level_features/Cargo.toml - run: cargo run --verbose --manifest-path test_max_level_features/Cargo.toml --release From f1372a879d43d5d3b9d571670d2131e0f2275db9 Mon Sep 17 00:00:00 2001 From: tison Date: Mon, 24 Mar 2025 09:37:05 +0800 Subject: [PATCH 263/280] another way Signed-off-by: tison --- .github/workflows/main.yml | 8 +++++++- Cargo.toml | 14 +++++++++++--- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index bd834e344..9942e490c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -95,6 +95,8 @@ jobs: msrv: name: MSRV runs-on: ubuntu-24.04 + env: + RUSTFLAGS: "--cfg test_msrv" steps: - uses: actions/checkout@v4 - name: Install toolchain @@ -102,7 +104,11 @@ jobs: with: toolchain: 1.60.0 - uses: taiki-e/install-action@cargo-hack - - run: cargo hack test --feature-powerset --lib --exclude-features serde,kv_serde,kv_unstable_serde,max_level_off,max_level_error,max_level_warn,max_level_info,max_level_debug,max_level_trace,release_max_level_off,release_max_level_error,release_max_level_warn,release_max_level_info,release_max_level_debug,release_max_level_trace + - run: > + cargo hack test --feature-powerset --lib + # value-bag 1.7 requires rustc 1.61.0 for const fn + --exclude-features kv_sval,kv_std,kv_serde,kv_unstable_sval,kv_unstable_std,kv_unstable_serde,\ + max_level_off,max_level_error,max_level_warn,max_level_info,max_level_debug,max_level_trace,release_max_level_off,release_max_level_error,release_max_level_warn,release_max_level_info,release_max_level_debug,release_max_level_trace - run: cargo run --verbose --manifest-path test_max_level_features/Cargo.toml - run: cargo run --verbose --manifest-path test_max_level_features/Cargo.toml --release diff --git a/Cargo.toml b/Cargo.toml index 0c8b53763..92728a66e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -66,16 +66,24 @@ value-bag = { version = "1.7", optional = true, default-features = false, featur [dev-dependencies] serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" -serde_test = "1.0" +serde_json = { version = "1.0" } +serde_test = { version = "1.0" } sval = { version = "2.1" } sval_derive = { version = "2.1" } value-bag = { version = "1.7", features = ["test"] } -# NOTE: log doesn't actually depent on this crate. However, our dependencies, +# NOTE: log doesn't actually depend on this crate. However, our dependencies, # serde and sval, dependent on version 1.0 of the crate, which has problem fixed # in 1.0.60, specifically in the following commit # https://github.com/dtolnay/proc-macro2/commit/e31d61910049e097afdd3d27c37786309082bdcb. # By defining the crate as direct dependency we can increase its minimal # version making the minimal (crate) version CI happy. proc-macro2 = { version = "1.0.63", default-features = false } + +# NOTE: log doesn't actually depend on these crates. However, to pass MSRV tests +# we need to pin the version of the following crates whose newer versions +# requires rustc 1.61.0 or newer. +[target.'cfg(test_msrv)'.dev-dependencies] +memchr = { version = "=2.6.2" } +serde_derive = { version = "=1.0.210" } +syn = { version = "=2.0.67" } From 2cac1dd32430d7bb916260d9bf7d56ad4d70b482 Mon Sep 17 00:00:00 2001 From: tison Date: Mon, 24 Mar 2025 09:40:02 +0800 Subject: [PATCH 264/280] everything requires 1.61.0 Signed-off-by: tison --- .github/workflows/main.yml | 10 ++-------- Cargo.toml | 10 +--------- README.md | 2 +- 3 files changed, 4 insertions(+), 18 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 9942e490c..16098954e 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -95,20 +95,14 @@ jobs: msrv: name: MSRV runs-on: ubuntu-24.04 - env: - RUSTFLAGS: "--cfg test_msrv" steps: - uses: actions/checkout@v4 - name: Install toolchain uses: dtolnay/rust-toolchain@master with: - toolchain: 1.60.0 + toolchain: 1.61.0 - uses: taiki-e/install-action@cargo-hack - - run: > - cargo hack test --feature-powerset --lib - # value-bag 1.7 requires rustc 1.61.0 for const fn - --exclude-features kv_sval,kv_std,kv_serde,kv_unstable_sval,kv_unstable_std,kv_unstable_serde,\ - max_level_off,max_level_error,max_level_warn,max_level_info,max_level_debug,max_level_trace,release_max_level_off,release_max_level_error,release_max_level_warn,release_max_level_info,release_max_level_debug,release_max_level_trace + - run: cargo hack test --feature-powerset --lib --exclude-features max_level_off,max_level_error,max_level_warn,max_level_info,max_level_debug,max_level_trace,release_max_level_off,release_max_level_error,release_max_level_warn,release_max_level_info,release_max_level_debug,release_max_level_trace - run: cargo run --verbose --manifest-path test_max_level_features/Cargo.toml - run: cargo run --verbose --manifest-path test_max_level_features/Cargo.toml --release diff --git a/Cargo.toml b/Cargo.toml index 92728a66e..64071e105 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ A lightweight logging facade for Rust categories = ["development-tools::debugging"] keywords = ["logging"] exclude = ["rfcs/**/*"] -rust-version = "1.60.0" +rust-version = "1.61.0" edition = "2021" [package.metadata.docs.rs] @@ -79,11 +79,3 @@ value-bag = { version = "1.7", features = ["test"] } # By defining the crate as direct dependency we can increase its minimal # version making the minimal (crate) version CI happy. proc-macro2 = { version = "1.0.63", default-features = false } - -# NOTE: log doesn't actually depend on these crates. However, to pass MSRV tests -# we need to pin the version of the following crates whose newer versions -# requires rustc 1.61.0 or newer. -[target.'cfg(test_msrv)'.dev-dependencies] -memchr = { version = "=2.6.2" } -serde_derive = { version = "=1.0.210" } -syn = { version = "=2.0.67" } diff --git a/README.md b/README.md index f8b544911..9d5113d24 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ implementation that is most suitable for its use case. ## Minimum supported `rustc` -`1.60.0+` +`1.61.0+` This version is explicitly tested in CI and may be bumped in any release as needed. Maintaining compatibility with older compilers is a priority though, so the bar for bumping the minimum supported version is set very high. Any changes to the supported minimum version will be called out in the release notes. From 828abbc4d0a230f25690f41b08143bcb862e099a Mon Sep 17 00:00:00 2001 From: tison Date: Mon, 24 Mar 2025 09:55:26 +0800 Subject: [PATCH 265/280] try patching Signed-off-by: tison --- Cargo.toml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 64071e105..f7a653d28 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -79,3 +79,9 @@ value-bag = { version = "1.7", features = ["test"] } # By defining the crate as direct dependency we can increase its minimal # version making the minimal (crate) version CI happy. proc-macro2 = { version = "1.0.63", default-features = false } + +[patch.crates-io] +sval = { git = "https://github.com/tisonkun/sval.git", rev = "06aa86b" } +sval_buffer = { git = "https://github.com/tisonkun/sval.git", rev = "06aa86b" } +sval_nested = { git = "https://github.com/tisonkun/sval.git", rev = "06aa86b" } +sval_ref = { git = "https://github.com/tisonkun/sval.git", rev = "06aa86b" } \ No newline at end of file From 6eb2731b04c07a714a4f3e3b91c60ad17d53130e Mon Sep 17 00:00:00 2001 From: tison Date: Mon, 24 Mar 2025 18:50:13 +0800 Subject: [PATCH 266/280] undo pin runner name Signed-off-by: tison --- .github/workflows/main.yml | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 16098954e..487b06e7f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -9,25 +9,25 @@ jobs: matrix: include: - build: stable - os: ubuntu-24.04 + os: ubuntu-latest rust: stable - build: beta - os: ubuntu-24.04 + os: ubuntu-latest rust: beta - build: nightly - os: ubuntu-24.04 + os: ubuntu-latest rust: nightly - build: macos - os: macos-14 + os: macos-latest rust: stable - build: win32 - os: windows-2022 + os: windows-latest rust: stable-i686-pc-windows-msvc - build: win64 - os: windows-2022 + os: windows-latest rust: stable-x86_64-pc-windows-msvc - build: mingw - os: windows-2022 + os: windows-latest rust: stable-x86_64-pc-windows-gnu steps: - uses: actions/checkout@v4 @@ -42,7 +42,7 @@ jobs: check: name: Check Format and Clippy - runs-on: ubuntu-24.04 + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable @@ -55,7 +55,7 @@ jobs: doc: name: Check Documentation - runs-on: ubuntu-24.04 + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable @@ -68,7 +68,7 @@ jobs: features: name: Feature check - runs-on: ubuntu-24.04 + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@nightly @@ -81,7 +81,7 @@ jobs: minimalv: name: Minimal versions - runs-on: ubuntu-24.04 + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@nightly @@ -94,7 +94,7 @@ jobs: msrv: name: MSRV - runs-on: ubuntu-24.04 + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Install toolchain @@ -108,7 +108,7 @@ jobs: embedded: name: Embedded - runs-on: ubuntu-24.04 + runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable From 28026bf39f7978945beb478a606c6e58bf4585ef Mon Sep 17 00:00:00 2001 From: tison Date: Mon, 24 Mar 2025 18:51:47 +0800 Subject: [PATCH 267/280] ensure workflow permissions Signed-off-by: tison --- .github/workflows/main.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 487b06e7f..b17e179dd 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,6 +1,10 @@ name: CI on: [push, pull_request] +# Ensure only read permission is granted +permissions: + contents: read + jobs: test: name: Test From d70c00c788c576eded4c2931b43cd0c7dbfd6e5d Mon Sep 17 00:00:00 2001 From: tison Date: Mon, 24 Mar 2025 18:55:05 +0800 Subject: [PATCH 268/280] install toolchain by scripts Signed-off-by: tison --- .github/workflows/main.yml | 47 ++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b17e179dd..398871756 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -36,10 +36,10 @@ jobs: steps: - uses: actions/checkout@v4 - name: Install toolchain - uses: dtolnay/rust-toolchain@master - with: - toolchain: ${{ matrix.rust }} - - uses: taiki-e/install-action@cargo-hack + run: | + rustup update ${{ matrix.rust }} --no-self-update + rustup default ${{ matrix.rust }} + cargo install cargo-hack - run: cargo hack test --feature-powerset --lib --exclude-features max_level_off,max_level_error,max_level_warn,max_level_info,max_level_debug,max_level_trace,release_max_level_off,release_max_level_error,release_max_level_warn,release_max_level_info,release_max_level_debug,release_max_level_trace - run: cargo run --verbose --manifest-path test_max_level_features/Cargo.toml - run: cargo run --verbose --manifest-path test_max_level_features/Cargo.toml --release @@ -49,9 +49,11 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@stable - with: - components: clippy,rustfmt + - name: Install toolchain + run: | + rustup update stable --no-self-update + rustup default stable + rustup component add clippy,rustfmt - run: cargo fmt -- --check - run: cargo fmt --manifest-path test_max_level_features/Cargo.toml -- --check - run: cargo clippy --verbose @@ -62,9 +64,11 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@stable - with: - components: rust-docs + - name: Install toolchain + run: | + rustup update stable --no-self-update + rustup default stable + rustup component add rust-docs - name: Run rustdoc env: RUSTDOCFLAGS: "-D warnings" @@ -75,7 +79,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@nightly + - name: Install toolchain + run: | + rustup update nightly --no-self-update + rustup default nightly - run: cargo build --verbose -Z avoid-dev-deps --features kv - run: cargo build --verbose -Z avoid-dev-deps --features "kv std" - run: cargo build --verbose -Z avoid-dev-deps --features "kv kv_sval" @@ -88,7 +95,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@nightly + - name: Install toolchain + run: | + rustup update nightly --no-self-update + rustup default nightly - run: cargo build --verbose -Z minimal-versions --features kv - run: cargo build --verbose -Z minimal-versions --features "kv std" - run: cargo build --verbose -Z minimal-versions --features "kv kv_sval" @@ -102,10 +112,10 @@ jobs: steps: - uses: actions/checkout@v4 - name: Install toolchain - uses: dtolnay/rust-toolchain@master - with: - toolchain: 1.61.0 - - uses: taiki-e/install-action@cargo-hack + run: | + rustup update 1.61.0 --no-self-update + rustup default 1.61.0 + cargo install cargo-hack - run: cargo hack test --feature-powerset --lib --exclude-features max_level_off,max_level_error,max_level_warn,max_level_info,max_level_debug,max_level_trace,release_max_level_off,release_max_level_error,release_max_level_warn,release_max_level_info,release_max_level_debug,release_max_level_trace - run: cargo run --verbose --manifest-path test_max_level_features/Cargo.toml - run: cargo run --verbose --manifest-path test_max_level_features/Cargo.toml --release @@ -115,7 +125,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: dtolnay/rust-toolchain@stable + - name: Install toolchain + run: | + rustup update stable --no-self-update + rustup default stable - run: rustup target add thumbv6m-none-eabi riscv32imc-unknown-none-elf - run: cargo build --verbose --target=thumbv6m-none-eabi - run: cargo build --verbose --target=riscv32imc-unknown-none-elf From 593250979147a7579ca0f4a1ef5fc963d6322338 Mon Sep 17 00:00:00 2001 From: tison Date: Mon, 24 Mar 2025 18:57:19 +0800 Subject: [PATCH 269/280] sval 2.14.1 Signed-off-by: tison --- Cargo.toml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f7a653d28..7940d586f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -60,7 +60,7 @@ kv_unstable_serde = ["kv_serde", "kv_unstable_std"] [dependencies] serde = { version = "1.0", optional = true, default-features = false } -sval = { version = "2.1", optional = true, default-features = false } +sval = { version = "2.14.1", optional = true, default-features = false } sval_ref = { version = "2.1", optional = true, default-features = false } value-bag = { version = "1.7", optional = true, default-features = false, features = ["inline-i128"] } @@ -79,9 +79,3 @@ value-bag = { version = "1.7", features = ["test"] } # By defining the crate as direct dependency we can increase its minimal # version making the minimal (crate) version CI happy. proc-macro2 = { version = "1.0.63", default-features = false } - -[patch.crates-io] -sval = { git = "https://github.com/tisonkun/sval.git", rev = "06aa86b" } -sval_buffer = { git = "https://github.com/tisonkun/sval.git", rev = "06aa86b" } -sval_nested = { git = "https://github.com/tisonkun/sval.git", rev = "06aa86b" } -sval_ref = { git = "https://github.com/tisonkun/sval.git", rev = "06aa86b" } \ No newline at end of file From 5173090324150350768be91af150015a19e642ca Mon Sep 17 00:00:00 2001 From: tison Date: Mon, 24 Mar 2025 19:00:08 +0800 Subject: [PATCH 270/280] fixup scripts Signed-off-by: tison --- .github/workflows/main.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 398871756..bcf73cafb 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -39,7 +39,7 @@ jobs: run: | rustup update ${{ matrix.rust }} --no-self-update rustup default ${{ matrix.rust }} - cargo install cargo-hack + cargo +stable install cargo-hack --locked - run: cargo hack test --feature-powerset --lib --exclude-features max_level_off,max_level_error,max_level_warn,max_level_info,max_level_debug,max_level_trace,release_max_level_off,release_max_level_error,release_max_level_warn,release_max_level_info,release_max_level_debug,release_max_level_trace - run: cargo run --verbose --manifest-path test_max_level_features/Cargo.toml - run: cargo run --verbose --manifest-path test_max_level_features/Cargo.toml --release @@ -53,7 +53,7 @@ jobs: run: | rustup update stable --no-self-update rustup default stable - rustup component add clippy,rustfmt + rustup component add clippy rustfmt - run: cargo fmt -- --check - run: cargo fmt --manifest-path test_max_level_features/Cargo.toml -- --check - run: cargo clippy --verbose @@ -115,7 +115,7 @@ jobs: run: | rustup update 1.61.0 --no-self-update rustup default 1.61.0 - cargo install cargo-hack + cargo +stable install cargo-hack --locked - run: cargo hack test --feature-powerset --lib --exclude-features max_level_off,max_level_error,max_level_warn,max_level_info,max_level_debug,max_level_trace,release_max_level_off,release_max_level_error,release_max_level_warn,release_max_level_info,release_max_level_debug,release_max_level_trace - run: cargo run --verbose --manifest-path test_max_level_features/Cargo.toml - run: cargo run --verbose --manifest-path test_max_level_features/Cargo.toml --release From faca8cbfce4db115a5976b44791c824cbb81543c Mon Sep 17 00:00:00 2001 From: tison Date: Mon, 24 Mar 2025 19:01:49 +0800 Subject: [PATCH 271/280] update change log Signed-off-by: tison --- CHANGELOG.md | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 11cfaea37..7a9b2adff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,12 @@ ## [Unreleased] +### Notable Changes +* MSRV is bumped to 1.61.0 in https://github.com/rust-lang/log/pull/676 + ## [0.4.26] - 2025-02-18 -## What's Changed +### What's Changed * Derive `Clone` for `kv::Value` by @SpriteOvO in https://github.com/rust-lang/log/pull/668 * Add `spdlog-rs` link to crate doc by @SpriteOvO in https://github.com/rust-lang/log/pull/669 @@ -13,7 +16,7 @@ ## [0.4.25] - 2025-01-14 -## What's Changed +### What's Changed * Revert loosening of kv cargo features by @KodrAus in https://github.com/rust-lang/log/pull/662 @@ -21,7 +24,7 @@ ## [0.4.24] - 2025-01-11 -## What's Changed +### What's Changed * Fix up kv feature activation by @KodrAus in https://github.com/rust-lang/log/pull/659 @@ -29,7 +32,7 @@ ## [0.4.23] - 2025-01-10 (yanked) -## What's Changed +### What's Changed * Fix some typos by @Kleinmarb in https://github.com/rust-lang/log/pull/637 * Add logforth to implementation by @tisonkun in https://github.com/rust-lang/log/pull/638 * Add `spdlog-rs` link to README by @SpriteOvO in https://github.com/rust-lang/log/pull/639 @@ -40,7 +43,7 @@ * Fix up key lifetimes and add method to try get a borrowed key by @KodrAus in https://github.com/rust-lang/log/pull/653 * Add Ftail implementation by @tjardoo in https://github.com/rust-lang/log/pull/652 -## New Contributors +### New Contributors * @Kleinmarb made their first contribution in https://github.com/rust-lang/log/pull/637 * @tisonkun made their first contribution in https://github.com/rust-lang/log/pull/638 * @SpriteOvO made their first contribution in https://github.com/rust-lang/log/pull/639 @@ -53,7 +56,7 @@ ## [0.4.22] - 2024-06-27 -## What's Changed +### What's Changed * Add some clarifications to the library docs by @KodrAus in https://github.com/rust-lang/log/pull/620 * Add links to `colog` crate by @chrivers in https://github.com/rust-lang/log/pull/621 * adding line_number test + updating some testing infrastructure by @DIvkov575 in https://github.com/rust-lang/log/pull/619 @@ -64,7 +67,7 @@ * Loosen orderings for logger initialization in https://github.com/rust-lang/log/pull/632. Originally by @pwoolcoc in https://github.com/rust-lang/log/pull/599 * Use Location::caller() for file and line info in https://github.com/rust-lang/log/pull/633. Originally by @Cassy343 in https://github.com/rust-lang/log/pull/520 -## New Contributors +### New Contributors * @chrivers made their first contribution in https://github.com/rust-lang/log/pull/621 * @DIvkov575 made their first contribution in https://github.com/rust-lang/log/pull/619 * @Catamantaloedis made their first contribution in https://github.com/rust-lang/log/pull/625 @@ -73,7 +76,7 @@ ## [0.4.21] - 2024-02-27 -## What's Changed +### What's Changed * Minor clippy nits by @nyurik in https://github.com/rust-lang/log/pull/578 * Simplify Display impl by @nyurik in https://github.com/rust-lang/log/pull/579 * Set all crates to 2021 edition by @nyurik in https://github.com/rust-lang/log/pull/580 @@ -93,7 +96,7 @@ * Use `Acquire` ordering for initialization check by @AngelicosPhosphoros in https://github.com/rust-lang/log/pull/610 * Get structured logging API ready for stabilization by @KodrAus in https://github.com/rust-lang/log/pull/613 -## New Contributors +### New Contributors * @nyurik made their first contribution in https://github.com/rust-lang/log/pull/578 * @dimo414 made their first contribution in https://github.com/rust-lang/log/pull/590 * @peterjoel made their first contribution in https://github.com/rust-lang/log/pull/587 From b9c84e8dd9a003608f7545f1e7331192f8398c78 Mon Sep 17 00:00:00 2001 From: tison Date: Mon, 24 Mar 2025 19:07:14 +0800 Subject: [PATCH 272/280] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f09f8271..79d3c3475 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ ## [0.4.27] - 2025-03-24 -## What's Changed +### What's Changed * A few minor lint fixes by @nyurik in https://github.com/rust-lang/log/pull/671 * Enable clippy support for format-like macros by @nyurik in https://github.com/rust-lang/log/pull/665 * Add an optional logger param by @tisonkun in https://github.com/rust-lang/log/pull/664 From 50c2018d50517bf8ec9aafae12b3a6993c29213f Mon Sep 17 00:00:00 2001 From: tison Date: Tue, 25 Mar 2025 07:10:26 +0800 Subject: [PATCH 273/280] fixup running IT cases Signed-off-by: tison --- .github/workflows/main.yml | 4 ++-- Cargo.toml | 10 ---------- tests/integration.rs | 5 +++-- 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index bcf73cafb..3f5988fbd 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -40,7 +40,7 @@ jobs: rustup update ${{ matrix.rust }} --no-self-update rustup default ${{ matrix.rust }} cargo +stable install cargo-hack --locked - - run: cargo hack test --feature-powerset --lib --exclude-features max_level_off,max_level_error,max_level_warn,max_level_info,max_level_debug,max_level_trace,release_max_level_off,release_max_level_error,release_max_level_warn,release_max_level_info,release_max_level_debug,release_max_level_trace + - run: cargo hack test --feature-powerset --exclude-features max_level_off,max_level_error,max_level_warn,max_level_info,max_level_debug,max_level_trace,release_max_level_off,release_max_level_error,release_max_level_warn,release_max_level_info,release_max_level_debug,release_max_level_trace - run: cargo run --verbose --manifest-path test_max_level_features/Cargo.toml - run: cargo run --verbose --manifest-path test_max_level_features/Cargo.toml --release @@ -116,7 +116,7 @@ jobs: rustup update 1.61.0 --no-self-update rustup default 1.61.0 cargo +stable install cargo-hack --locked - - run: cargo hack test --feature-powerset --lib --exclude-features max_level_off,max_level_error,max_level_warn,max_level_info,max_level_debug,max_level_trace,release_max_level_off,release_max_level_error,release_max_level_warn,release_max_level_info,release_max_level_debug,release_max_level_trace + - run: cargo hack test --feature-powerset --exclude-features max_level_off,max_level_error,max_level_warn,max_level_info,max_level_debug,max_level_trace,release_max_level_off,release_max_level_error,release_max_level_warn,release_max_level_info,release_max_level_debug,release_max_level_trace - run: cargo run --verbose --manifest-path test_max_level_features/Cargo.toml - run: cargo run --verbose --manifest-path test_max_level_features/Cargo.toml --release diff --git a/Cargo.toml b/Cargo.toml index 6a44b10d6..44ef6c342 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,16 +19,6 @@ edition = "2021" [package.metadata.docs.rs] features = ["std", "serde", "kv_std", "kv_sval", "kv_serde"] -[[test]] -name = "integration" -path = "tests/integration.rs" -harness = false - -[[test]] -name = "macros" -path = "tests/macros.rs" -harness = true - [features] max_level_off = [] max_level_error = [] diff --git a/tests/integration.rs b/tests/integration.rs index 0b8522d71..9bcb04697 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -21,8 +21,9 @@ impl Log for Logger { } fn flush(&self) {} } -#[cfg_attr(lib_build, test)] -fn main() { + +#[test] +fn test_integration() { // These tests don't really make sense when static // max level filtering is applied #[cfg(not(any( From 53594839745cb2bc8ba09d6ba9a3758f45c5da47 Mon Sep 17 00:00:00 2001 From: xixishidibei Date: Wed, 2 Apr 2025 21:58:58 +0800 Subject: [PATCH 274/280] chore: fix some typos in comment Signed-off-by: xixishidibei --- src/kv/value.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/kv/value.rs b/src/kv/value.rs index b4851af2a..e604c806c 100644 --- a/src/kv/value.rs +++ b/src/kv/value.rs @@ -449,7 +449,7 @@ mod std_support { /// A visitor for a [`Value`]. /// -/// Also see [`Value`'s documentation on seralization]. Value visitors are a simple alternative +/// Also see [`Value`'s documentation on serialization]. Value visitors are a simple alternative /// to a more fully-featured serialization framework like `serde` or `sval`. A value visitor /// can differentiate primitive types through methods like [`VisitValue::visit_bool`] and /// [`VisitValue::visit_str`], but more complex types like maps and sequences @@ -458,7 +458,7 @@ mod std_support { /// If you're trying to serialize a value to a format like JSON, you can use either `serde` /// or `sval` directly with the value. You don't need a visitor. /// -/// [`Value`'s documentation on seralization]: Value#serialization +/// [`Value`'s documentation on serialization]: Value#serialization pub trait VisitValue<'v> { /// Visit a `Value`. /// From 44984954670f3144af1d1f323e36690bb72788f4 Mon Sep 17 00:00:00 2001 From: Zylos <217501196+ZylosLumen@users.noreply.github.com> Date: Thu, 3 Jul 2025 21:59:00 -0400 Subject: [PATCH 275/280] Unhide `#[derive(Debug)]` in example --- src/kv/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/kv/mod.rs b/src/kv/mod.rs index 8c71e0765..34e61c3ae 100644 --- a/src/kv/mod.rs +++ b/src/kv/mod.rs @@ -225,7 +225,7 @@ //! //! ``` //! # use log::kv::Key; -//! # #[derive(Debug)] +//! #[derive(Debug)] //! struct Data { //! a: i32, //! b: bool, From 1091f2cbd21817872235eff67b8e0e68e5ec4e41 Mon Sep 17 00:00:00 2001 From: Sheldon Lee Date: Fri, 18 Jul 2025 10:19:25 -0400 Subject: [PATCH 276/280] Chore:delete compare_exchange method for AtomicUsize on platforms without atomics Since it's never been compiled or used. --- src/lib.rs | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index eb37f55cc..a73955b5b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -431,21 +431,6 @@ impl AtomicUsize { fn store(&self, val: usize, _order: Ordering) { self.v.set(val) } - - #[cfg(target_has_atomic = "ptr")] - fn compare_exchange( - &self, - current: usize, - new: usize, - _success: Ordering, - _failure: Ordering, - ) -> Result { - let prev = self.v.get(); - if current == prev { - self.v.set(new); - } - Ok(prev) - } } // Any platform without atomics is unlikely to have multiple cores, so From 2b63dfada6394c537682de4834ae45eaf3bad216 Mon Sep 17 00:00:00 2001 From: Joe Ardent Date: Thu, 31 Jul 2025 12:03:15 -0700 Subject: [PATCH 277/280] Add `up()` and `down()` methods for `Level` and `LevelFilter` --- src/lib.rs | 134 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index a73955b5b..5e5bc3a0f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -576,6 +576,48 @@ impl Level { pub fn iter() -> impl Iterator { (1..6).map(|i| Self::from_usize(i).unwrap()) } + + /// Get the next-highest `Level` from this one. + /// + /// If the current `Level` is at the highest level, the returned `Level` will be the same as the + /// current one. + /// + /// # Examples + /// + /// ``` + /// use log::Level; + /// + /// let level = Level::Info; + /// + /// assert_eq!(Level::Debug, level.up()); + /// assert_eq!(Level::Trace, level.up().up()); + /// assert_eq!(Level::Trace, level.up().up().up()); // max level + /// ``` + pub fn up(&self) -> Self { + let current = *self as usize; + Self::from_usize(current + 1).unwrap_or(*self) + } + + /// Get the next-lowest `Level` from this one. + /// + /// If the current `Level` is at the lowest level, the returned `Level` will be the same as the + /// current one. + /// + /// # Examples + /// + /// ``` + /// use log::Level; + /// + /// let level = Level::Info; + /// + /// assert_eq!(Level::Warn, level.down()); + /// assert_eq!(Level::Error, level.down().down()); + /// assert_eq!(Level::Error, level.down().down().down()); // min level + /// ``` + pub fn down(&self) -> Self { + let current = *self as usize; + Self::from_usize(current.saturating_sub(1)).unwrap_or(*self) + } } /// An enum representing the available verbosity level filters of the logger. @@ -685,6 +727,49 @@ impl LevelFilter { pub fn iter() -> impl Iterator { (0..6).map(|i| Self::from_usize(i).unwrap()) } + + /// Get the next-highest `LevelFilter` from this one. + /// + /// If the current `LevelFilter` is at the highest level, the returned `LevelFilter` will be the + /// same as the current one. + /// + /// # Examples + /// + /// ``` + /// use log::LevelFilter; + /// + /// let level_filter = LevelFilter::Info; + /// + /// assert_eq!(LevelFilter::Debug, level_filter.up()); + /// assert_eq!(LevelFilter::Trace, level_filter.up().up()); + /// assert_eq!(LevelFilter::Trace, level_filter.up().up().up()); // max level + /// ``` + pub fn up(&self) -> Self { + let current = *self as usize; + Self::from_usize(current + 1).unwrap_or(*self) + } + + /// Get the next-lowest `LevelFilter` from this one. + /// + /// If the current `LevelFilter` is at the lowest level, the returned `LevelFilter` will be the + /// same as the current one. + /// + /// # Examples + /// + /// ``` + /// use log::LevelFilter; + /// + /// let level_filter = LevelFilter::Info; + /// + /// assert_eq!(LevelFilter::Warn, level_filter.down()); + /// assert_eq!(LevelFilter::Error, level_filter.down().down()); + /// assert_eq!(LevelFilter::Off, level_filter.down().down().down()); + /// assert_eq!(LevelFilter::Off, level_filter.down().down().down().down()); // min level + /// ``` + pub fn down(&self) -> Self { + let current = *self as usize; + Self::from_usize(current.saturating_sub(1)).unwrap_or(*self) + } } #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)] @@ -1648,6 +1733,55 @@ mod tests { } } + #[test] + fn test_level_up() { + let info = Level::Info; + let up = info.up(); + assert_eq!(up, Level::Debug); + + let trace = Level::Trace; + let up = trace.up(); + // trace is already highest level + assert_eq!(up, trace); + } + + #[test] + fn test_level_filter_up() { + let info = LevelFilter::Info; + let up = info.up(); + assert_eq!(up, LevelFilter::Debug); + + let trace = LevelFilter::Trace; + let up = trace.up(); + // trace is already highest level + assert_eq!(up, trace); + } + + #[test] + fn test_level_down() { + let info = Level::Info; + let down = info.down(); + assert_eq!(down, Level::Warn); + + let error = Level::Error; + let down = error.down(); + // error is already lowest level + assert_eq!(down, error); + } + + #[test] + fn test_level_filter_down() { + let info = LevelFilter::Info; + let down = info.down(); + assert_eq!(down, LevelFilter::Warn); + + let error = LevelFilter::Error; + let down = error.down(); + assert_eq!(down, LevelFilter::Off); + // Off is already the lowest + assert_eq!(down.down(), down); + } + #[test] #[cfg_attr(not(debug_assertions), ignore)] fn test_static_max_level_debug() { From 95d44f8af52df35d78adb766bef79d8f489022a0 Mon Sep 17 00:00:00 2001 From: Joe Ardent Date: Sun, 31 Aug 2025 13:56:31 -0700 Subject: [PATCH 278/280] change names of log-level-changing methods to be more descriptive --- src/lib.rs | 52 ++++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 5e5bc3a0f..394469d75 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -589,11 +589,11 @@ impl Level { /// /// let level = Level::Info; /// - /// assert_eq!(Level::Debug, level.up()); - /// assert_eq!(Level::Trace, level.up().up()); - /// assert_eq!(Level::Trace, level.up().up().up()); // max level + /// assert_eq!(Level::Debug, level.increment_severity()); + /// assert_eq!(Level::Trace, level.increment_severity().increment_severity()); + /// assert_eq!(Level::Trace, level.increment_severity().increment_severity().increment_severity()); // max level /// ``` - pub fn up(&self) -> Self { + pub fn increment_severity(&self) -> Self { let current = *self as usize; Self::from_usize(current + 1).unwrap_or(*self) } @@ -610,11 +610,11 @@ impl Level { /// /// let level = Level::Info; /// - /// assert_eq!(Level::Warn, level.down()); - /// assert_eq!(Level::Error, level.down().down()); - /// assert_eq!(Level::Error, level.down().down().down()); // min level + /// assert_eq!(Level::Warn, level.decrement_severity()); + /// assert_eq!(Level::Error, level.decrement_severity().decrement_severity()); + /// assert_eq!(Level::Error, level.decrement_severity().decrement_severity().decrement_severity()); // min level /// ``` - pub fn down(&self) -> Self { + pub fn decrement_severity(&self) -> Self { let current = *self as usize; Self::from_usize(current.saturating_sub(1)).unwrap_or(*self) } @@ -740,11 +740,11 @@ impl LevelFilter { /// /// let level_filter = LevelFilter::Info; /// - /// assert_eq!(LevelFilter::Debug, level_filter.up()); - /// assert_eq!(LevelFilter::Trace, level_filter.up().up()); - /// assert_eq!(LevelFilter::Trace, level_filter.up().up().up()); // max level + /// assert_eq!(LevelFilter::Debug, level_filter.increment_severity()); + /// assert_eq!(LevelFilter::Trace, level_filter.increment_severity().increment_severity()); + /// assert_eq!(LevelFilter::Trace, level_filter.increment_severity().increment_severity().increment_severity()); // max level /// ``` - pub fn up(&self) -> Self { + pub fn increment_severity(&self) -> Self { let current = *self as usize; Self::from_usize(current + 1).unwrap_or(*self) } @@ -761,12 +761,12 @@ impl LevelFilter { /// /// let level_filter = LevelFilter::Info; /// - /// assert_eq!(LevelFilter::Warn, level_filter.down()); - /// assert_eq!(LevelFilter::Error, level_filter.down().down()); - /// assert_eq!(LevelFilter::Off, level_filter.down().down().down()); - /// assert_eq!(LevelFilter::Off, level_filter.down().down().down().down()); // min level + /// assert_eq!(LevelFilter::Warn, level_filter.decrement_severity()); + /// assert_eq!(LevelFilter::Error, level_filter.decrement_severity().decrement_severity()); + /// assert_eq!(LevelFilter::Off, level_filter.decrement_severity().decrement_severity().decrement_severity()); + /// assert_eq!(LevelFilter::Off, level_filter.decrement_severity().decrement_severity().decrement_severity().decrement_severity()); // min level /// ``` - pub fn down(&self) -> Self { + pub fn decrement_severity(&self) -> Self { let current = *self as usize; Self::from_usize(current.saturating_sub(1)).unwrap_or(*self) } @@ -1736,11 +1736,11 @@ mod tests { #[test] fn test_level_up() { let info = Level::Info; - let up = info.up(); + let up = info.increment_severity(); assert_eq!(up, Level::Debug); let trace = Level::Trace; - let up = trace.up(); + let up = trace.increment_severity(); // trace is already highest level assert_eq!(up, trace); } @@ -1748,11 +1748,11 @@ mod tests { #[test] fn test_level_filter_up() { let info = LevelFilter::Info; - let up = info.up(); + let up = info.increment_severity(); assert_eq!(up, LevelFilter::Debug); let trace = LevelFilter::Trace; - let up = trace.up(); + let up = trace.increment_severity(); // trace is already highest level assert_eq!(up, trace); } @@ -1760,11 +1760,11 @@ mod tests { #[test] fn test_level_down() { let info = Level::Info; - let down = info.down(); + let down = info.decrement_severity(); assert_eq!(down, Level::Warn); let error = Level::Error; - let down = error.down(); + let down = error.decrement_severity(); // error is already lowest level assert_eq!(down, error); } @@ -1772,14 +1772,14 @@ mod tests { #[test] fn test_level_filter_down() { let info = LevelFilter::Info; - let down = info.down(); + let down = info.decrement_severity(); assert_eq!(down, LevelFilter::Warn); let error = LevelFilter::Error; - let down = error.down(); + let down = error.decrement_severity(); assert_eq!(down, LevelFilter::Off); // Off is already the lowest - assert_eq!(down.down(), down); + assert_eq!(down.decrement_severity(), down); } #[test] From e0630c6485c6ca6da22888c319d2c3d2e53cb1ae Mon Sep 17 00:00:00 2001 From: KodrAus Date: Tue, 2 Sep 2025 15:57:55 +1000 Subject: [PATCH 279/280] prepare for 0.4.28 release --- CHANGELOG.md | 20 +++++++++++++++++++- Cargo.toml | 2 +- src/lib.rs | 2 +- 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 79d3c3475..86c9e52e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,23 @@ ## [Unreleased] +## [0.4.28] - 2025-09-02 + +## What's Changed +* ci: drop really old trick and ensure MSRV for all feature combo by @tisonkun in https://github.com/rust-lang/log/pull/676 +* chore: fix some typos in comment by @xixishidibei in https://github.com/rust-lang/log/pull/677 +* Unhide `#[derive(Debug)]` in example by @ZylosLumen in https://github.com/rust-lang/log/pull/688 +* Chore: delete compare_exchange method for AtomicUsize on platforms without atomics by @HaoliangXu in https://github.com/rust-lang/log/pull/690 +* Add `increment_severity()` and `decrement_severity()` methods for `Level` and `LevelFilter` by @nebkor in https://github.com/rust-lang/log/pull/692 + +## New Contributors +* @xixishidibei made their first contribution in https://github.com/rust-lang/log/pull/677 +* @ZylosLumen made their first contribution in https://github.com/rust-lang/log/pull/688 +* @HaoliangXu made their first contribution in https://github.com/rust-lang/log/pull/690 +* @nebkor made their first contribution in https://github.com/rust-lang/log/pull/692 + +**Full Changelog**: https://github.com/rust-lang/log/compare/0.4.27...0.4.28 + ### Notable Changes * MSRV is bumped to 1.61.0 in https://github.com/rust-lang/log/pull/676 @@ -362,7 +379,8 @@ version using log 0.4.x to avoid losing module and file information. Look at the [release tags] for information about older releases. -[Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.27...HEAD +[Unreleased]: https://github.com/rust-lang-nursery/log/compare/0.4.28...HEAD +[0.4.28]: https://github.com/rust-lang/log/compare/0.4.27...0.4.28 [0.4.27]: https://github.com/rust-lang/log/compare/0.4.26...0.4.27 [0.4.26]: https://github.com/rust-lang/log/compare/0.4.25...0.4.26 [0.4.25]: https://github.com/rust-lang/log/compare/0.4.24...0.4.25 diff --git a/Cargo.toml b/Cargo.toml index 44ef6c342..47b847133 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "log" -version = "0.4.27" # remember to update html_root_url +version = "0.4.28" # remember to update html_root_url authors = ["The Rust Project Developers"] license = "MIT OR Apache-2.0" readme = "README.md" diff --git a/src/lib.rs b/src/lib.rs index 394469d75..47f2cf132 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -344,7 +344,7 @@ #![doc( html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://www.rust-lang.org/favicon.ico", - html_root_url = "https://docs.rs/log/0.4.27" + html_root_url = "https://docs.rs/log/0.4.28" )] #![warn(missing_docs)] #![deny(missing_debug_implementations, unconditional_recursion)] From 57719dbef54de1c9b91b986845e4285d09c9e644 Mon Sep 17 00:00:00 2001 From: Ashley Mannix Date: Tue, 2 Sep 2025 18:31:18 +1000 Subject: [PATCH 280/280] focus on user-facing source changes in the changelog --- CHANGELOG.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 86c9e52e1..48f669334 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,8 +6,6 @@ ## What's Changed * ci: drop really old trick and ensure MSRV for all feature combo by @tisonkun in https://github.com/rust-lang/log/pull/676 -* chore: fix some typos in comment by @xixishidibei in https://github.com/rust-lang/log/pull/677 -* Unhide `#[derive(Debug)]` in example by @ZylosLumen in https://github.com/rust-lang/log/pull/688 * Chore: delete compare_exchange method for AtomicUsize on platforms without atomics by @HaoliangXu in https://github.com/rust-lang/log/pull/690 * Add `increment_severity()` and `decrement_severity()` methods for `Level` and `LevelFilter` by @nebkor in https://github.com/rust-lang/log/pull/692