//! 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 std::fmt;
/// A source of key-value pairs.
///
/// 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.
pub trait Source {
/// Visit key-value pairs.
///
/// A source doesn't have to guarantee any ordering or uniqueness of key-value pairs.
/// If the given visitor returns an error then the source may early-return with it,
/// even if there are more key-value pairs.
///
/// # Implementation notes
///
/// A source should yield the same key-value pairs to a subsequent visitor unless
/// that visitor itself fails.
fn visit<'kvs>(&' kvs self , visitor: &mut dyn Visitor<'kvs>) -> Result<(), Error>;
/// Get the value for a given key.
///
/// If the key appears multiple times in the source then which key is returned
/// is implementation specific.
///
/// # Implementation notes
///
/// 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<Value<'v>> {
get_default(self , key)
}
#[ cfg(test)]
fn get<'v>(&' v self , key: Key) -> Option<Value<'v>>;
/// Count the number of key-value pairs that can be visited.
///
/// # Implementation notes
///
/// A source that knows the number of key-value pairs upfront may provide a more
/// efficient implementation.
///
/// 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 implemention of `Source::get`
pub (crate ) fn get_default<'v>(source: &' v (impl Source + ?Sized), key: Key) -> Option<Value<'v>> {
struct Get<'k, ' v> {
key: Key<'k>,
found: Option<Value<'v>>,
}
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 ;
Ok(())
}
}
let mut count = Count(0 );
let _ = source.visit(&mut count);
count.0
}
impl <'a, T> Source for &' a T
where
T: Source + ?Sized,
{
fn visit<'kvs>(&' kvs self , visitor: &mut dyn Visitor<'kvs>) -> Result<(), Error> {
Source::visit(&**self , visitor)
}
fn get<'v>(&' v self , key: Key) -> Option<Value<'v>> {
Source::get(&**self , key)
}
fn count(&self ) -> usize {
Source::count(&**self )
}
}
impl <K, V> Source for (K, V)
where
K: ToKey,
V: ToValue,
{
fn visit<'kvs>(&' kvs self , visitor: &mut dyn Visitor<'kvs>) -> Result<(), Error> {
visitor.visit_pair(self .0 .to_key(), self .1 .to_value())
}
fn get<'v>(&' v self , key: Key) -> Option<Value<'v>> {
if self .0 .to_key() == key {
Some(self .1 .to_value())
} else {
None
}
}
fn count(&self ) -> usize {
1
}
}
impl <S> Source for [S]
where
S: Source,
{
fn visit<'kvs>(&' kvs self , visitor: &mut dyn Visitor<'kvs>) -> Result<(), Error> {
for source in self {
source.visit(visitor)?;
}
Ok(())
}
fn get<'v>(&' v self , key: Key) -> Option<Value<'v>> {
for source in self {
if let Some(found) = source.get(key.clone()) {
return Some(found);
}
}
None
}
fn count(&self ) -> usize {
self .len()
}
}
impl <S> Source for Option<S>
where
S: Source,
{
fn visit<'kvs>(&' kvs self , visitor: &mut dyn Visitor<'kvs>) -> Result<(), Error> {
if let Some(ref source) = *self {
source.visit(visitor)?;
}
Ok(())
}
fn get<'v>(&' v self , key: Key) -> Option<Value<'v>> {
self .as_ref().and_then(|s| s.get(key))
}
fn count(&self ) -> usize {
self .as_ref().map(Source::count).unwrap_or(0 )
}
}
/// A visitor for the key-value pairs in a [`Source`](trait.Source.html).
pub trait Visitor<'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
where
T: Visitor<'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> {
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> {
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> {
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> {
fn visit_pair(&mut self , key: Key<'kvs>, value: Value<' kvs>) -> Result<(), Error> {
self .field(&key);
self .field(&value);
Ok(())
}
}
#[ cfg(feature = "std" )]
mod std_support {
use super ::*;
use std::borrow::Borrow;
use std::collections::{BTreeMap, HashMap};
use std::hash::{BuildHasher, Hash};
impl <S> Source for Box <S>
where
S: Source + ?Sized,
{
fn visit<'kvs>(&' kvs self , visitor: &mut dyn Visitor<'kvs>) -> Result<(), Error> {
Source::visit(&**self , visitor)
}
fn get<'v>(&' v self , key: Key) -> Option<Value<'v>> {
Source::get(&**self , key)
}
fn count(&self ) -> usize {
Source::count(&**self )
}
}
impl <S> Source for Vec<S>
where
S: Source,
{
fn visit<'kvs>(&' kvs self , visitor: &mut dyn Visitor<'kvs>) -> Result<(), Error> {
Source::visit(&**self , visitor)
}
fn get<'v>(&' v self , key: Key) -> Option<Value<'v>> {
Source::get(&**self , key)
}
fn count(&self ) -> usize {
Source::count(&**self )
}
}
impl <'kvs, V> Visitor<' kvs> for Box <V>
where
V: Visitor<'kvs> + ?Sized,
{
fn visit_pair(&mut self , key: Key<'kvs>, value: Value<' kvs>) -> Result<(), Error> {
(**self ).visit_pair(key, value)
}
}
impl <K, V, S> Source for HashMap<K, V, S>
where
K: ToKey + Borrow<str> + Eq + Hash,
V: ToValue,
S: BuildHasher,
{
fn visit<'kvs>(&' kvs self , visitor: &mut dyn Visitor<'kvs>) -> Result<(), Error> {
for (key, value) in self {
visitor.visit_pair(key.to_key(), value.to_value())?;
}
Ok(())
}
fn get<'v>(&' v self , key: Key) -> Option<Value<'v>> {
HashMap::get(self , key.as_str()).map(|v| v.to_value())
}
fn count(&self ) -> usize {
self .len()
}
}
impl <K, V> Source for BTreeMap<K, V>
where
K: ToKey + Borrow<str> + Ord,
V: ToValue,
{
fn visit<'kvs>(&' kvs self , visitor: &mut dyn Visitor<'kvs>) -> Result<(), Error> {
for (key, value) in self {
visitor.visit_pair(key.to_key(), value.to_value())?;
}
Ok(())
}
fn get<'v>(&' v self , key: Key) -> Option<Value<'v>> {
BTreeMap::get(self , key.as_str()).map(|v| v.to_value())
}
fn count(&self ) -> usize {
self .len()
}
}
#[ cfg(test)]
mod tests {
use super ::*;
use kv::value::tests::Token;
use std::collections::{BTreeMap, HashMap};
#[ test]
fn count() {
assert_eq!(1 , Source::count(&Box ::new(("a" , 1 ))));
assert_eq!(2 , Source::count(&vec![("a" , 1 ), ("b" , 2 )]));
}
#[ test]
fn get() {
let source = vec![("a" , 1 ), ("b" , 2 ), ("a" , 1 )];
assert_eq!(
Token::I64(1 ),
Source::get(&source, Key::from_str("a" )).unwrap().to_token()
);
let source = Box ::new(Option::None::<(&str, i32)>);
assert!(Source::get(&source, Key::from_str("a" )).is_none());
}
#[ test]
fn hash_map() {
let mut map = HashMap::new();
map.insert("a" , 1 );
map.insert("b" , 2 );
assert_eq!(2 , Source::count(&map));
assert_eq!(
Token::I64(1 ),
Source::get(&map, Key::from_str("a" )).unwrap().to_token()
);
}
#[ test]
fn btree_map() {
let mut map = BTreeMap::new();
map.insert("a" , 1 );
map.insert("b" , 2 );
assert_eq!(2 , Source::count(&map));
assert_eq!(
Token::I64(1 ),
Source::get(&map, Key::from_str("a" )).unwrap().to_token()
);
}
}
}
/// The result of calling `Source::as_map`.
pub struct AsMap<S>(S);
/// Visit this source as a map.
pub fn as_map<S>(source: S) -> AsMap<S>
where
S: Source,
{
AsMap(source)
}
impl <S> Source for AsMap<S>
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<Value<'v>> {
self .0 .get(key)
}
fn count(&self ) -> usize {
self .0 .count()
}
}
impl <S> fmt::Debug for AsMap<S>
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>(S);
/// Visit this source as a list.
pub fn as_list<S>(source: S) -> AsList<S>
where
S: Source,
{
AsList(source)
}
impl <S> Source for AsList<S>
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<Value<'v>> {
self .0 .get(key)
}
fn count(&self ) -> usize {
self .0 .count()
}
}
impl <S> fmt::Debug for AsList<S>
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 <S> self ::sval::Value for AsMap<S>
where
S: Source,
{
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_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(|_| self ::sval::Error::new())?;
self .visit(&mut StreamVisitor(stream))
.map_err(|_| self ::sval::Error::new())?;
stream.map_end().map_err(|_| self ::sval::Error::new())
}
}
impl <S> self ::sval::Value for AsList<S>
where
S: Source,
{
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" ))?;
Ok(())
}
}
stream
.seq_begin(Some(self .count()))
.map_err(|_| self ::sval::Error::new())?;
self .visit(&mut StreamVisitor(stream))
.map_err(|_| self ::sval::Error::new())?;
stream.seq_end().map_err(|_| self ::sval::Error::new())
}
}
#[ cfg(test)]
mod tests {
extern crate sval_derive;
use super ::*;
use self ::sval_derive::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<T, S>(source: &T, serializer: S) -> Result<S::Ok, S::Error>
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<T, S>(source: &T, serializer: S) -> Result<S::Ok, S::Error>
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 <T> Serialize for AsMap<T>
where
T: Source,
{
fn serialize<S>(&self , serializer: S) -> Result<S::Ok, S::Error>
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 <T> Serialize for AsList<T>
where
T: Source,
{
fn serialize<S>(&self , serializer: S) -> Result<S::Ok, S::Error>
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 ::*;
use kv::value::tests::Token;
#[ test]
fn source_is_object_safe() {
fn _check(_: &dyn Source) {}
}
#[ test]
fn visitor_is_object_safe() {
fn _check(_: &dyn Visitor) {}
}
#[ test]
fn count() {
struct OnePair {
key: &'static str,
value: i32,
}
impl Source for OnePair {
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<Value<'v>> {
get_default(self , key)
}
fn count(&self ) -> usize {
count_default(self )
}
}
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!(1 , Source::count(&OnePair { key: "a" , value: 1 }));
}
#[ test]
fn get() {
let source = &[("a" , 1 ), ("b" , 2 ), ("a" , 1 )] as &[_];
assert_eq!(
Token::I64(1 ),
Source::get(source, Key::from_str("a" )).unwrap().to_token()
);
assert_eq!(
Token::I64(2 ),
Source::get(source, Key::from_str("b" )).unwrap().to_token()
);
assert!(Source::get(&source, Key::from_str("c" )).is_none());
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);
}
}
Messung V0.5 in Prozent C=84 H=86 G=84
¤ Dauer der Verarbeitung: 0.23 Sekunden
(vorverarbeitet am 2026-06-18)
¤
*© Formatika GbR, Deutschland