log/kv/
source.rs

1//! Sources for key-values.
2//!
3//! This module defines the [`Source`] type and supporting APIs for
4//! working with collections of key-values.
5
6use crate::kv::{Error, Key, ToKey, ToValue, Value};
7use std::fmt;
8
9/// A source of key-values.
10///
11/// The source may be a single pair, a set of pairs, or a filter over a set of pairs.
12/// Use the [`VisitSource`](trait.VisitSource.html) trait to inspect the structured data
13/// in a source.
14///
15/// A source is like an iterator over its key-values, except with a push-based API
16/// instead of a pull-based one.
17///
18/// # Examples
19///
20/// Enumerating the key-values in a source:
21///
22/// ```
23/// # fn main() -> Result<(), log::kv::Error> {
24/// use log::kv::{self, Source, Key, Value, VisitSource};
25///
26/// // A `VisitSource` that prints all key-values
27/// // VisitSources are fed the key-value pairs of each key-values
28/// struct Printer;
29///
30/// impl<'kvs> VisitSource<'kvs> for Printer {
31///     fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), kv::Error> {
32///         println!("{key}: {value}");
33///
34///         Ok(())
35///     }
36/// }
37///
38/// // A source with 3 key-values
39/// // Common collection types implement the `Source` trait
40/// let source = &[
41///     ("a", 1),
42///     ("b", 2),
43///     ("c", 3),
44/// ];
45///
46/// // Pass an instance of the `VisitSource` to a `Source` to visit it
47/// source.visit(&mut Printer)?;
48/// # Ok(())
49/// # }
50/// ```
51pub trait Source {
52    /// Visit key-values.
53    ///
54    /// A source doesn't have to guarantee any ordering or uniqueness of key-values.
55    /// If the given visitor returns an error then the source may early-return with it,
56    /// even if there are more key-values.
57    ///
58    /// # Implementation notes
59    ///
60    /// A source should yield the same key-values to a subsequent visitor unless
61    /// that visitor itself fails.
62    fn visit<'kvs>(&'kvs self, visitor: &mut dyn VisitSource<'kvs>) -> Result<(), Error>;
63
64    /// Get the value for a given key.
65    ///
66    /// If the key appears multiple times in the source then which key is returned
67    /// is implementation specific.
68    ///
69    /// # Implementation notes
70    ///
71    /// A source that can provide a more efficient implementation of this method
72    /// should override it.
73    fn get(&self, key: Key) -> Option<Value<'_>> {
74        get_default(self, key)
75    }
76
77    /// Count the number of key-values that can be visited.
78    ///
79    /// # Implementation notes
80    ///
81    /// A source that knows the number of key-values upfront may provide a more
82    /// efficient implementation.
83    ///
84    /// A subsequent call to `visit` should yield the same number of key-values.
85    fn count(&self) -> usize {
86        count_default(self)
87    }
88}
89
90/// The default implementation of `Source::get`
91fn get_default<'v>(source: &'v (impl Source + ?Sized), key: Key) -> Option<Value<'v>> {
92    struct Get<'k, 'v> {
93        key: Key<'k>,
94        found: Option<Value<'v>>,
95    }
96
97    impl<'k, 'kvs> VisitSource<'kvs> for Get<'k, 'kvs> {
98        fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> {
99            if self.key == key {
100                self.found = Some(value);
101            }
102
103            Ok(())
104        }
105    }
106
107    let mut get = Get { key, found: None };
108
109    let _ = source.visit(&mut get);
110    get.found
111}
112
113/// The default implementation of `Source::count`.
114fn count_default(source: impl Source) -> usize {
115    struct Count(usize);
116
117    impl<'kvs> VisitSource<'kvs> for Count {
118        fn visit_pair(&mut self, _: Key<'kvs>, _: Value<'kvs>) -> Result<(), Error> {
119            self.0 += 1;
120
121            Ok(())
122        }
123    }
124
125    let mut count = Count(0);
126    let _ = source.visit(&mut count);
127    count.0
128}
129
130impl<T> Source for &T
131where
132    T: Source + ?Sized,
133{
134    fn visit<'kvs>(&'kvs self, visitor: &mut dyn VisitSource<'kvs>) -> Result<(), Error> {
135        Source::visit(&**self, visitor)
136    }
137
138    fn get(&self, key: Key) -> Option<Value<'_>> {
139        Source::get(&**self, key)
140    }
141
142    fn count(&self) -> usize {
143        Source::count(&**self)
144    }
145}
146
147impl<K, V> Source for (K, V)
148where
149    K: ToKey,
150    V: ToValue,
151{
152    fn visit<'kvs>(&'kvs self, visitor: &mut dyn VisitSource<'kvs>) -> Result<(), Error> {
153        visitor.visit_pair(self.0.to_key(), self.1.to_value())
154    }
155
156    fn get(&self, key: Key) -> Option<Value<'_>> {
157        if self.0.to_key() == key {
158            Some(self.1.to_value())
159        } else {
160            None
161        }
162    }
163
164    fn count(&self) -> usize {
165        1
166    }
167}
168
169impl<S> Source for [S]
170where
171    S: Source,
172{
173    fn visit<'kvs>(&'kvs self, visitor: &mut dyn VisitSource<'kvs>) -> Result<(), Error> {
174        for source in self {
175            source.visit(visitor)?;
176        }
177
178        Ok(())
179    }
180
181    fn get(&self, key: Key) -> Option<Value<'_>> {
182        for source in self {
183            if let Some(found) = source.get(key.clone()) {
184                return Some(found);
185            }
186        }
187
188        None
189    }
190
191    fn count(&self) -> usize {
192        self.iter().map(Source::count).sum()
193    }
194}
195
196impl<const N: usize, S> Source for [S; N]
197where
198    S: Source,
199{
200    fn visit<'kvs>(&'kvs self, visitor: &mut dyn VisitSource<'kvs>) -> Result<(), Error> {
201        Source::visit(self as &[_], visitor)
202    }
203
204    fn get(&self, key: Key) -> Option<Value<'_>> {
205        Source::get(self as &[_], key)
206    }
207
208    fn count(&self) -> usize {
209        Source::count(self as &[_])
210    }
211}
212
213impl<S> Source for Option<S>
214where
215    S: Source,
216{
217    fn visit<'kvs>(&'kvs self, visitor: &mut dyn VisitSource<'kvs>) -> Result<(), Error> {
218        if let Some(source) = self {
219            source.visit(visitor)?;
220        }
221
222        Ok(())
223    }
224
225    fn get(&self, key: Key) -> Option<Value<'_>> {
226        self.as_ref().and_then(|s| s.get(key))
227    }
228
229    fn count(&self) -> usize {
230        self.as_ref().map_or(0, Source::count)
231    }
232}
233
234/// A visitor for the key-value pairs in a [`Source`](trait.Source.html).
235pub trait VisitSource<'kvs> {
236    /// Visit a key-value pair.
237    fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error>;
238}
239
240#[allow(clippy::needless_lifetimes)] // Not needless.
241impl<'a, 'kvs, T> VisitSource<'kvs> for &'a mut T
242where
243    T: VisitSource<'kvs> + ?Sized,
244{
245    fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> {
246        (**self).visit_pair(key, value)
247    }
248}
249
250impl<'a, 'b: 'a, 'kvs> VisitSource<'kvs> for fmt::DebugMap<'a, 'b> {
251    fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> {
252        self.entry(&key, &value);
253        Ok(())
254    }
255}
256
257impl<'a, 'b: 'a, 'kvs> VisitSource<'kvs> for fmt::DebugList<'a, 'b> {
258    fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> {
259        self.entry(&(key, value));
260        Ok(())
261    }
262}
263
264impl<'a, 'b: 'a, 'kvs> VisitSource<'kvs> for fmt::DebugSet<'a, 'b> {
265    fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> {
266        self.entry(&(key, value));
267        Ok(())
268    }
269}
270
271impl<'a, 'b: 'a, 'kvs> VisitSource<'kvs> for fmt::DebugTuple<'a, 'b> {
272    fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> {
273        self.field(&key);
274        self.field(&value);
275        Ok(())
276    }
277}
278
279#[cfg(feature = "std")]
280mod std_support {
281    use super::*;
282    use std::borrow::Borrow;
283    use std::collections::{BTreeMap, HashMap};
284    use std::hash::{BuildHasher, Hash};
285    use std::rc::Rc;
286    use std::sync::Arc;
287
288    impl<S> Source for Box<S>
289    where
290        S: Source + ?Sized,
291    {
292        fn visit<'kvs>(&'kvs self, visitor: &mut dyn VisitSource<'kvs>) -> Result<(), Error> {
293            Source::visit(&**self, visitor)
294        }
295
296        fn get(&self, key: Key) -> Option<Value<'_>> {
297            Source::get(&**self, key)
298        }
299
300        fn count(&self) -> usize {
301            Source::count(&**self)
302        }
303    }
304
305    impl<S> Source for Arc<S>
306    where
307        S: Source + ?Sized,
308    {
309        fn visit<'kvs>(&'kvs self, visitor: &mut dyn VisitSource<'kvs>) -> Result<(), Error> {
310            Source::visit(&**self, visitor)
311        }
312
313        fn get(&self, key: Key) -> Option<Value<'_>> {
314            Source::get(&**self, key)
315        }
316
317        fn count(&self) -> usize {
318            Source::count(&**self)
319        }
320    }
321
322    impl<S> Source for Rc<S>
323    where
324        S: Source + ?Sized,
325    {
326        fn visit<'kvs>(&'kvs self, visitor: &mut dyn VisitSource<'kvs>) -> Result<(), Error> {
327            Source::visit(&**self, visitor)
328        }
329
330        fn get(&self, key: Key) -> Option<Value<'_>> {
331            Source::get(&**self, key)
332        }
333
334        fn count(&self) -> usize {
335            Source::count(&**self)
336        }
337    }
338
339    impl<S> Source for Vec<S>
340    where
341        S: Source,
342    {
343        fn visit<'kvs>(&'kvs self, visitor: &mut dyn VisitSource<'kvs>) -> Result<(), Error> {
344            Source::visit(&**self, visitor)
345        }
346
347        fn get(&self, key: Key) -> Option<Value<'_>> {
348            Source::get(&**self, key)
349        }
350
351        fn count(&self) -> usize {
352            Source::count(&**self)
353        }
354    }
355
356    impl<'kvs, V> VisitSource<'kvs> for Box<V>
357    where
358        V: VisitSource<'kvs> + ?Sized,
359    {
360        fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> {
361            (**self).visit_pair(key, value)
362        }
363    }
364
365    impl<K, V, S> Source for HashMap<K, V, S>
366    where
367        K: ToKey + Borrow<str> + Eq + Hash,
368        V: ToValue,
369        S: BuildHasher,
370    {
371        fn visit<'kvs>(&'kvs self, visitor: &mut dyn VisitSource<'kvs>) -> Result<(), Error> {
372            for (key, value) in self {
373                visitor.visit_pair(key.to_key(), value.to_value())?;
374            }
375            Ok(())
376        }
377
378        fn get(&self, key: Key) -> Option<Value<'_>> {
379            HashMap::get(self, key.as_str()).map(|v| v.to_value())
380        }
381
382        fn count(&self) -> usize {
383            self.len()
384        }
385    }
386
387    impl<K, V> Source for BTreeMap<K, V>
388    where
389        K: ToKey + Borrow<str> + Ord,
390        V: ToValue,
391    {
392        fn visit<'kvs>(&'kvs self, visitor: &mut dyn VisitSource<'kvs>) -> Result<(), Error> {
393            for (key, value) in self {
394                visitor.visit_pair(key.to_key(), value.to_value())?;
395            }
396            Ok(())
397        }
398
399        fn get(&self, key: Key) -> Option<Value<'_>> {
400            BTreeMap::get(self, key.as_str()).map(|v| v.to_value())
401        }
402
403        fn count(&self) -> usize {
404            self.len()
405        }
406    }
407
408    #[cfg(test)]
409    mod tests {
410        use crate::kv::value;
411
412        use super::*;
413
414        #[test]
415        fn count() {
416            assert_eq!(1, Source::count(&Box::new(("a", 1))));
417            assert_eq!(2, Source::count(&vec![("a", 1), ("b", 2)]));
418        }
419
420        #[test]
421        fn get() {
422            let source = vec![("a", 1), ("b", 2), ("a", 1)];
423            assert_eq!(
424                value::inner::Token::I64(1),
425                Source::get(&source, Key::from_str("a")).unwrap().to_token()
426            );
427
428            let source = Box::new(None::<(&str, i32)>);
429            assert!(Source::get(&source, Key::from_str("a")).is_none());
430        }
431
432        #[test]
433        fn hash_map() {
434            let mut map = HashMap::new();
435            map.insert("a", 1);
436            map.insert("b", 2);
437
438            assert_eq!(2, Source::count(&map));
439            assert_eq!(
440                value::inner::Token::I64(1),
441                Source::get(&map, Key::from_str("a")).unwrap().to_token()
442            );
443        }
444
445        #[test]
446        fn btree_map() {
447            let mut map = BTreeMap::new();
448            map.insert("a", 1);
449            map.insert("b", 2);
450
451            assert_eq!(2, Source::count(&map));
452            assert_eq!(
453                value::inner::Token::I64(1),
454                Source::get(&map, Key::from_str("a")).unwrap().to_token()
455            );
456        }
457    }
458}
459
460// NOTE: Deprecated; but aliases can't carry this attribute
461#[cfg(feature = "kv_unstable")]
462pub use VisitSource as Visitor;
463
464#[cfg(test)]
465mod tests {
466    use crate::kv::value;
467
468    use super::*;
469
470    #[test]
471    fn source_is_object_safe() {
472        fn _check(_: &dyn Source) {}
473    }
474
475    #[test]
476    fn visitor_is_object_safe() {
477        fn _check(_: &dyn VisitSource) {}
478    }
479
480    #[test]
481    fn count() {
482        struct OnePair {
483            key: &'static str,
484            value: i32,
485        }
486
487        impl Source for OnePair {
488            fn visit<'kvs>(&'kvs self, visitor: &mut dyn VisitSource<'kvs>) -> Result<(), Error> {
489                visitor.visit_pair(self.key.to_key(), self.value.to_value())
490            }
491        }
492
493        assert_eq!(1, Source::count(&("a", 1)));
494        assert_eq!(2, Source::count(&[("a", 1), ("b", 2)] as &[_]));
495        assert_eq!(0, Source::count(&None::<(&str, i32)>));
496        assert_eq!(1, Source::count(&OnePair { key: "a", value: 1 }));
497    }
498
499    #[test]
500    fn get() {
501        let source = &[("a", 1), ("b", 2), ("a", 1)] as &[_];
502        assert_eq!(
503            value::inner::Token::I64(1),
504            Source::get(source, Key::from_str("a")).unwrap().to_token()
505        );
506        assert_eq!(
507            value::inner::Token::I64(2),
508            Source::get(source, Key::from_str("b")).unwrap().to_token()
509        );
510        assert!(Source::get(&source, Key::from_str("c")).is_none());
511
512        let source = None::<(&str, i32)>;
513        assert!(Source::get(&source, Key::from_str("a")).is_none());
514    }
515}