//! Sources for key-value pairs. #[cfg(feature = "kv_unstable_sval")] extern crate sval; #[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> { get_default(self, key) } #[cfg(test)] fn get<'v>(&'v self, key: Key) -> Option>; /// 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> { struct Get<'k, 'v> { key: Key<'k>, found: Option>, } 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> { Source::get(&**self, key) } fn count(&self) -> usize { Source::count(&**self) } } impl 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> { if self.0.to_key() == key { Some(self.1.to_value()) } else { None } } fn count(&self) -> usize { 1 } } impl 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> { for source in self { if let Some(found) = source.get(key.clone()) { return Some(found); } } None } fn count(&self) -> usize { self.len() } } impl Source for Option 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> { 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 Source for Box 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> { Source::get(&**self, key) } fn count(&self) -> usize { Source::count(&**self) } } impl Source for Vec 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> { Source::get(&**self, key) } fn count(&self) -> usize { Source::count(&**self) } } impl<'kvs, V> Visitor<'kvs> for Box where V: Visitor<'kvs> + ?Sized, { fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> { (**self).visit_pair(key, value) } } impl Source for HashMap where K: ToKey + Borrow + 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> { HashMap::get(self, key.as_str()).map(|v| v.to_value()) } fn count(&self) -> usize { self.len() } } impl Source for BTreeMap where K: ToKey + Borrow + 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> { 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); /// Visit this source as a map. pub fn as_map(source: S) -> AsMap where S: Source, { AsMap(source) } impl Source for AsMap 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> { self.0.get(key) } fn count(&self) -> usize { self.0.count() } } impl fmt::Debug for AsMap 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); /// Visit this source as a list. pub fn as_list(source: S) -> AsList where S: Source, { AsList(source) } impl Source for AsList 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> { self.0.get(key) } fn count(&self) -> usize { self.0.count() } } impl fmt::Debug for AsList 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::*; use self::sval::value; impl value::Value for AsMap where S: Source, { fn stream(&self, stream: &mut value::Stream) -> value::Result { struct StreamVisitor<'a, 'b>(&'a mut value::Stream<'b>); impl<'a, 'b, 'kvs> Visitor<'kvs> for StreamVisitor<'a, 'b> { fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> { self.0 .map_key(key) .map_err(|_| Error::msg("failed to stream map key"))?; self.0 .map_value(value) .map_err(|_| Error::msg("failed to stream map value"))?; Ok(()) } } stream .map_begin(Some(self.count())) .map_err(|_| self::sval::Error::msg("failed to begin map"))?; self.visit(&mut StreamVisitor(stream)) .map_err(|_| self::sval::Error::msg("failed to visit key-values"))?; stream .map_end() .map_err(|_| self::sval::Error::msg("failed to end map")) } } impl value::Value for AsList where S: Source, { fn stream(&self, stream: &mut value::Stream) -> value::Result { struct StreamVisitor<'a, 'b>(&'a mut value::Stream<'b>); impl<'a, 'b, 'kvs> Visitor<'kvs> for StreamVisitor<'a, 'b> { fn visit_pair(&mut self, key: Key<'kvs>, value: Value<'kvs>) -> Result<(), Error> { self.0 .seq_elem((key, value)) .map_err(|_| Error::msg("failed to stream seq entry"))?; Ok(()) } } stream .seq_begin(Some(self.count())) .map_err(|_| self::sval::Error::msg("failed to begin seq"))?; self.visit(&mut StreamVisitor(stream)) .map_err(|_| self::sval::Error::msg("failed to visit key-values"))?; stream .seq_end() .map_err(|_| self::sval::Error::msg("failed to end seq")) } } #[cfg(test)] mod tests { use super::*; use self::sval::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(source: &T, serializer: S) -> Result 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(source: &T, serializer: S) -> Result 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 Serialize for AsMap where T: Source, { fn serialize(&self, serializer: S) -> Result 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 Serialize for AsList where T: Source, { fn serialize(&self, serializer: S) -> Result 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> { 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); } }