165 lines
3.6 KiB
Rust
165 lines
3.6 KiB
Rust
//! Structured keys.
|
|
|
|
use std::borrow::Borrow;
|
|
use std::fmt;
|
|
|
|
/// A type that can be converted into a [`Key`](struct.Key.html).
|
|
pub trait ToKey {
|
|
/// Perform the conversion.
|
|
fn to_key(&self) -> Key<'_>;
|
|
}
|
|
|
|
impl<T> ToKey for &T
|
|
where
|
|
T: ToKey + ?Sized,
|
|
{
|
|
fn to_key(&self) -> Key<'_> {
|
|
(**self).to_key()
|
|
}
|
|
}
|
|
|
|
impl<'k> ToKey for Key<'k> {
|
|
fn to_key(&self) -> Key<'_> {
|
|
Key { key: self.key }
|
|
}
|
|
}
|
|
|
|
impl ToKey for str {
|
|
fn to_key(&self) -> Key<'_> {
|
|
Key::from_str(self)
|
|
}
|
|
}
|
|
|
|
/// 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)]
|
|
pub struct Key<'k> {
|
|
// NOTE: This may become `Cow<'k, str>`
|
|
key: &'k str,
|
|
}
|
|
|
|
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 }
|
|
}
|
|
|
|
/// 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
|
|
}
|
|
|
|
/// 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> {
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
self.key.fmt(f)
|
|
}
|
|
}
|
|
|
|
impl<'k> AsRef<str> for Key<'k> {
|
|
fn as_ref(&self) -> &str {
|
|
self.as_str()
|
|
}
|
|
}
|
|
|
|
impl<'k> Borrow<str> for Key<'k> {
|
|
fn borrow(&self) -> &str {
|
|
self.as_str()
|
|
}
|
|
}
|
|
|
|
impl<'k> From<&'k str> for Key<'k> {
|
|
fn from(s: &'k str) -> Self {
|
|
Key::from_str(s)
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "std")]
|
|
mod std_support {
|
|
use super::*;
|
|
|
|
use std::borrow::Cow;
|
|
|
|
impl ToKey for String {
|
|
fn to_key(&self) -> Key<'_> {
|
|
Key::from_str(self)
|
|
}
|
|
}
|
|
|
|
impl<'a> ToKey for Cow<'a, str> {
|
|
fn to_key(&self) -> Key<'_> {
|
|
Key::from_str(self)
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "kv_sval")]
|
|
mod sval_support {
|
|
use super::*;
|
|
|
|
use sval::Value;
|
|
use 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<S: sval::Stream<'a> + ?Sized>(&self, stream: &mut S) -> sval::Result {
|
|
self.key.stream(stream)
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(feature = "kv_serde")]
|
|
mod serde_support {
|
|
use super::*;
|
|
|
|
use serde_core::{Serialize, Serializer};
|
|
|
|
impl<'a> Serialize for Key<'a> {
|
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
where
|
|
S: Serializer,
|
|
{
|
|
self.key.serialize(serializer)
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
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());
|
|
}
|
|
}
|