logforth_core/
kv.rs

1// Copyright 2024 FastLabs Developers
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! Key-value pairs in a log record or a diagnostic context.
16
17pub extern crate value_bag;
18
19use std::borrow::Cow;
20use std::fmt;
21use std::slice;
22
23use value_bag::OwnedValueBag;
24use value_bag::ValueBag;
25
26use crate::Error;
27use crate::str::OwnedStr;
28use crate::str::RefStr;
29
30/// A visitor to walk through key-value pairs.
31pub trait Visitor {
32    /// Visit a key-value pair.
33    fn visit(&mut self, key: Key, value: Value) -> Result<(), Error>;
34}
35
36/// A value in a key-value pair.
37pub type Value<'a> = ValueBag<'a>;
38
39/// A key in a key-value pair.
40#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
41pub struct Key<'a>(RefStr<'a>);
42
43impl Key<'static> {
44    /// Create a new key from a static `&str`.
45    pub const fn new(k: &'static str) -> Key<'static> {
46        Key(RefStr::Static(k))
47    }
48}
49
50impl fmt::Display for Key<'_> {
51    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
52        fmt::Display::fmt(&self.0, f)
53    }
54}
55
56impl<'a> Key<'a> {
57    /// Create a new key from a `&str`.
58    ///
59    /// The [`Key::new`] method should be preferred where possible.
60    pub const fn new_ref(k: &'a str) -> Key<'a> {
61        Key(RefStr::Borrowed(k))
62    }
63
64    /// Convert to an owned key.
65    pub fn to_owned(&self) -> KeyOwned {
66        KeyOwned(self.0.into_owned())
67    }
68
69    /// Convert to a `Cow` str.
70    pub fn to_cow(&self) -> Cow<'static, str> {
71        self.0.into_cow_static()
72    }
73
74    /// Get the key string.
75    pub fn as_str(&self) -> &str {
76        self.0.get()
77    }
78}
79
80/// An owned value in a key-value pair.
81pub type ValueOwned = OwnedValueBag;
82
83/// An owned key in a key-value pair.
84#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
85pub struct KeyOwned(OwnedStr);
86
87impl KeyOwned {
88    /// Create a `Key` ref.
89    pub fn by_ref(&self) -> Key<'_> {
90        Key(self.0.by_ref())
91    }
92}
93
94impl fmt::Display for KeyOwned {
95    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
96        fmt::Display::fmt(&self.0, f)
97    }
98}
99
100/// A collection of key-value pairs.
101pub struct KeyValues<'a>(KeyValuesState<'a>);
102
103enum KeyValuesState<'a> {
104    Borrowed(&'a [(Key<'a>, Value<'a>)]),
105    Owned(&'a [(KeyOwned, ValueOwned)]),
106}
107
108impl<'a> KeyValues<'a> {
109    /// Get the number of key-value pairs.
110    pub fn len(&self) -> usize {
111        match self.0 {
112            KeyValuesState::Borrowed(p) => p.len(),
113            KeyValuesState::Owned(p) => p.len(),
114        }
115    }
116
117    /// Check if there are no key-value pairs.
118    pub fn is_empty(&self) -> bool {
119        match self.0 {
120            KeyValuesState::Borrowed(p) => p.is_empty(),
121            KeyValuesState::Owned(p) => p.is_empty(),
122        }
123    }
124
125    /// Get an iterator over the key-value pairs.
126    pub fn iter(&self) -> KeyValuesIter<'a> {
127        match &self.0 {
128            KeyValuesState::Borrowed(p) => KeyValuesIter(KeyValuesIterState::Borrowed(p.iter())),
129            KeyValuesState::Owned(p) => KeyValuesIter(KeyValuesIterState::Owned(p.iter())),
130        }
131    }
132
133    /// Get the value for a given key.
134    ///
135    /// If the key appears multiple times in the source then which key is returned is undetermined.
136    pub fn get(&self, key: &str) -> Option<Value<'a>> {
137        match &self.0 {
138            KeyValuesState::Borrowed(p) => p.iter().find_map(|(k, v)| {
139                if k.0.get() != key {
140                    None
141                } else {
142                    Some(v.clone())
143                }
144            }),
145            KeyValuesState::Owned(p) => p.iter().find_map(|(k, v)| {
146                if k.0.get() != key {
147                    None
148                } else {
149                    Some(v.by_ref())
150                }
151            }),
152        }
153    }
154
155    /// Visit the key-value pairs with the provided visitor.
156    pub fn visit(&self, visitor: &mut dyn Visitor) -> Result<(), Error> {
157        for (k, v) in self.iter() {
158            visitor.visit(k, v)?;
159        }
160        Ok(())
161    }
162}
163
164impl fmt::Debug for KeyValues<'_> {
165    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
166        f.debug_list().entries(self.iter()).finish()
167    }
168}
169
170impl Clone for KeyValues<'_> {
171    fn clone(&self) -> Self {
172        match &self.0 {
173            KeyValuesState::Borrowed(p) => KeyValues(KeyValuesState::Borrowed(p)),
174            KeyValuesState::Owned(p) => KeyValues(KeyValuesState::Owned(p)),
175        }
176    }
177}
178
179impl Default for KeyValues<'_> {
180    fn default() -> Self {
181        KeyValues(KeyValuesState::Borrowed(&[]))
182    }
183}
184
185impl<'a> IntoIterator for KeyValues<'a> {
186    type Item = (Key<'a>, Value<'a>);
187    type IntoIter = KeyValuesIter<'a>;
188
189    fn into_iter(self) -> Self::IntoIter {
190        self.iter()
191    }
192}
193
194impl<'a> From<&'a [(Key<'a>, Value<'a>)]> for KeyValues<'a> {
195    fn from(kvs: &'a [(Key<'a>, Value<'a>)]) -> Self {
196        Self(KeyValuesState::Borrowed(kvs))
197    }
198}
199
200impl<'a> From<&'a [(KeyOwned, ValueOwned)]> for KeyValues<'a> {
201    fn from(kvs: &'a [(KeyOwned, ValueOwned)]) -> Self {
202        Self(KeyValuesState::Owned(kvs))
203    }
204}
205
206/// An iterator over key-value pairs.
207pub struct KeyValuesIter<'a>(KeyValuesIterState<'a>);
208
209enum KeyValuesIterState<'a> {
210    Borrowed(slice::Iter<'a, (Key<'a>, Value<'a>)>),
211    Owned(slice::Iter<'a, (KeyOwned, ValueOwned)>),
212}
213
214impl<'a> Iterator for KeyValuesIter<'a> {
215    type Item = (Key<'a>, Value<'a>);
216
217    fn next(&mut self) -> Option<Self::Item> {
218        match &mut self.0 {
219            KeyValuesIterState::Borrowed(iter) => iter.next().map(|(k, v)| (k.clone(), v.clone())),
220            KeyValuesIterState::Owned(iter) => iter.next().map(|(k, v)| (k.by_ref(), v.by_ref())),
221        }
222    }
223
224    fn size_hint(&self) -> (usize, Option<usize>) {
225        match &self.0 {
226            KeyValuesIterState::Borrowed(iter) => iter.size_hint(),
227            KeyValuesIterState::Owned(iter) => iter.size_hint(),
228        }
229    }
230}