1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
//! Fast Read-Only Key Value structures.
//!
use crate::types::map_builder::IntoMapBuilder;
use crate::types::Puff;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::collections::hash_map::{IntoIter, IntoKeys, IntoValues};
use std::collections::HashMap;
use std::hash::Hash;
use std::sync::Arc;
/// Fast Read-Only Key Value structures.
///
/// Puff's `Map` type uses [std::collections::hash_map::HashMap] under the hood. However, in order
/// for it to handle cheap clones, it is wrapped in an Arc, making it read-only.
///
/// Maps can only be constructed from types implementing `IntoMapBuilder`.
///
/// ```
/// use puff_rs::types::Map;
///
/// let map = Map::from_builder(vec![(123, 456)]);
/// assert_eq!(map.get(123), Some(456))
/// ```
///
#[derive(Clone)]
pub struct Map<K: Clone, V: Clone>(Arc<HashMap<K, V>>);
impl<K: Serialize + Clone + Eq + Hash, V: Serialize + Clone> Serialize for Map<K, V> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.0.serialize(serializer)
}
}
impl<'de, K: Deserialize<'de> + Clone + Eq + Hash + Puff, V: Deserialize<'de> + Clone + Puff>
Deserialize<'de> for Map<K, V>
{
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
HashMap::deserialize(deserializer).map(|v| Map::from_hash_map(v))
}
}
impl<K, T> Map<K, T>
where
K: Puff + Hash + Eq,
T: Puff + Send + 'static,
{
/// Create a new empty Map
///
/// # Examples
///
/// ```
/// use puff_rs::types::Map;
/// let map: Map<u32, u32> = Map::new();
/// ```
pub fn new() -> Map<K, T> {
Map(Arc::new(HashMap::new()))
}
/// Take a datatype that implements `IntoMapBuilder` and turn it into a read-only `Map`
///
/// # Examples
///
/// ```
/// use puff_rs::types::Map;
/// let map = Map::from_builder(vec![(123, 456)]);
/// ```
pub fn from_builder<B: IntoMapBuilder<K, T>>(builder: B) -> Map<K, T> {
builder.into_map_builder().into_map()
}
/// Create a new Map from a raw HashMap.
///
/// # Examples
///
/// ```
/// use std::collections::HashMap;
/// use puff_rs::types::Map;
/// let map: Map<i32, i32> = Map::from_hash_map(HashMap::new());
/// ```
pub fn from_hash_map(hm: HashMap<K, T>) -> Map<K, T> {
Map(Arc::new(hm))
}
/// Returns true if the map contains no elements.
///
/// # Examples
///
/// ```
/// use puff_rs::types::Map;
/// let map: Map<i32, i32> = Map::new();
/// assert!(map.is_empty())
/// ```
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
/// Returns the data associated with the key.
///
/// # Examples
///
/// ```
/// use puff_rs::types::Map;
/// let map = Map::from_builder(vec![(123, 456)]);
/// assert_eq!(map.get(123), Some(456))
/// ```
pub fn get(&self, index: K) -> Option<T> {
self.0.get(&index).map(|v| v.puff())
}
/// Returns the key, value pair corresponding to the key
///
/// # Examples
///
/// ```
/// use puff_rs::types::Map;
/// let map = Map::from_builder(vec![(123, 456)]);
/// assert_eq!(map.get_key_value(123), Some((123, 456)))
/// ```
pub fn get_key_value(&self, index: K) -> Option<(K, T)> {
self.0
.get_key_value(&index)
.map(|(k, v)| (k.puff(), v.puff()))
}
/// The length of the Map
///
/// # Examples
///
/// ```
/// use puff_rs::types::Map;
/// let map: Map<i32, i32> = Map::new();
/// assert_eq!(map.len(), 0)
/// ```
pub fn len(&self) -> usize {
self.0.len()
}
/// Iterate over the Map.
///
/// Note: normally calling `.iter()` on a Map iterates over `(&K, &V)`,
/// however, puff's `Map` cheaply clones the data so that concrete data is returned instead.
/// If this is not desirable, manually iterate over the underlying type using `arc_hashmap`.
///
/// This applies to all Iterators in `Map` (`keys`, `values`, `items`).
pub fn iter(&self) -> IntoIter<K, T> {
// Yeah, cloning a HashMap isn't ideal, but we will deal with making proper iterators later.
let hm = HashMap::clone(&self.0);
hm.into_iter()
}
/// Iterate over all items, cloning their references.
pub fn items(self) -> IntoIter<K, T> {
self.iter()
}
/// Iterate over all keys, cloning their references.
pub fn keys(self) -> IntoKeys<K, T> {
// Yeah, cloning a HashMap isn't ideal, but we will deal with making proper iterators later.
let hm = HashMap::clone(&self.0);
hm.into_keys()
}
/// Iterate over all values, cloning their references.
pub fn values(self) -> IntoValues<K, T> {
// Yeah, cloning a HashMap isn't ideal, but we will deal with making proper iterators later.
let hm = HashMap::clone(&self.0);
hm.into_values()
}
/// Returns a reference to the underlying raw `HashMap`
pub fn arc_hashmap(self) -> Arc<HashMap<K, T>> {
self.0.clone()
}
}
impl<K: Puff, V: Puff> Puff for Map<K, V> {}