Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions src/__private_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,30 @@ use std::fmt::Arguments;
use std::panic::Location;
pub use std::{format_args, module_path, stringify};

#[cfg(not(feature = "kv"))]
pub type Key<'a> = &'a str;
#[cfg(not(feature = "kv"))]
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, super::Value<'a>)]>;
fn into_kvs(self) -> Option<&'a [(super::Key<'a>, super::Value<'a>)]>;
}
}

// Types for the `kv` argument.

impl<'a> KVs<'a> for &'a [(&'a str, Value<'a>)] {
impl<'a> KVs<'a> for &'a [(Key<'a>, Value<'a>)] {
#[inline]
fn into_kvs(self) -> Option<&'a [(&'a str, Value<'a>)]> {
fn into_kvs(self) -> Option<&'a [(Key<'a>, Value<'a>)]> {
Some(self)
}
}

impl<'a> KVs<'a> for () {
#[inline]
fn into_kvs(self) -> Option<&'a [(&'a str, Value<'a>)]> {
fn into_kvs(self) -> Option<&'a [(Key<'a>, Value<'a>)]> {
None
}
}
Expand Down Expand Up @@ -58,7 +60,7 @@ fn log_impl<L: Log>(
args: Arguments,
level: Level,
&(target, module_path, loc): &(&str, &'static str, &'static Location),
kvs: Option<&[(&str, Value)]>,
kvs: Option<&[(Key, Value)]>,
) {
#[cfg(not(feature = "kv"))]
if kvs.is_some() {
Expand Down Expand Up @@ -113,6 +115,7 @@ pub fn loc() -> &'static Location<'static> {
mod kv_support {
use crate::kv;

pub type Key<'a> = kv::Key<'a>;
pub type Value<'a> = kv::Value<'a>;

// NOTE: Many functions here accept a double reference &&V
Expand Down
37 changes: 27 additions & 10 deletions src/kv/key.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Structured keys.

use crate::MaybeStaticStr;
use std::borrow::Borrow;
use std::fmt;

Expand Down Expand Up @@ -35,40 +36,56 @@ 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,
key: MaybeStaticStr<'k>,
}

impl<'k> Key<'k> {
/// Get a key from a borrowed string.
#[allow(clippy::should_implement_trait)] // Part of the public API now.
pub fn from_str(key: &'k str) -> Self {
Key { key }
Key {
key: MaybeStaticStr::Borrowed(key),
}
}

/// Get a key from a static str.
pub fn from_str_static(key: &'static str) -> Self {
Key {
key: MaybeStaticStr::Static(key),
}
}

/// Get a borrowed string from this key.
///
/// 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
self.key.get()
}

/// Try get a borrowed string for the lifetime `'k` from this key.
/// Try to 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)
Some(self.key.get())
}

/// Try to get a static string from this key.
pub fn to_static_str(&self) -> Option<&'static str> {
match self.key {
MaybeStaticStr::Static(s) => Some(s),
MaybeStaticStr::Borrowed(_) => None,
}
}
}

impl<'k> fmt::Display for Key<'k> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.key.fmt(f)
self.key.get().fmt(f)
}
}

Expand Down Expand Up @@ -121,13 +138,13 @@ mod sval_support {
&'sval self,
stream: &mut S,
) -> sval::Result {
self.key.stream(stream)
self.key.get().stream(stream)
}
}

impl<'a> ValueRef<'a> for Key<'a> {
fn stream_ref<S: sval::Stream<'a> + ?Sized>(&self, stream: &mut S) -> sval::Result {
self.key.stream(stream)
self.key.get().stream(stream)
}
}
}
Expand All @@ -143,7 +160,7 @@ mod serde_support {
where
S: Serializer,
{
self.key.serialize(serializer)
self.key.get().serialize(serializer)
}
}
}
Expand Down
12 changes: 8 additions & 4 deletions src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -444,12 +444,16 @@ macro_rules! __log_logger {
#[cfg(feature = "kv")]
macro_rules! __log_key {
// key1 = 42
($($args:ident)*) => {
$crate::__private_api::stringify!($($args)*)
($args:ident) => {
$crate::__private_api::Key::from_str_static($crate::__private_api::stringify!($args))
};
// "key1" = 42
($($args:expr)*) => {
$($args)*
($args:literal) => {
$crate::__private_api::Key::from_str_static($args)
};
// key = 42, where key is an expression
($args:expr) => {
$crate::__private_api::Key::from_str($args)
};
}

Expand Down
10 changes: 10 additions & 0 deletions tests/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,16 @@ fn kv_ident() {
all_log_macros!(cat_1, cat_2:%, cat_count = 2; "hello {world}", world = "world");
}

#[test]
#[cfg(feature = "kv")]
fn kv_static_keys() {
assert_eq!(Some("cat_1"), log::__log_key!(cat_1).to_static_str());
assert_eq!(Some("cat_1"), log::__log_key!("cat_1").to_static_str());

let cat_1 = "chashu".to_string();
assert_eq!(None, log::__log_key!(cat_1.as_str()).to_static_str());
}

#[test]
#[cfg(feature = "kv")]
fn kv_expr_context() {
Expand Down
Loading