use serde::de::{MapAccess, Visitor};
use serde::ser::SerializeMap;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::collections::BTreeMap;
use std::fmt;
use std::sync::Arc;
use super::values::Value;
pub type PropKey = String;
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct PropMap(Arc<Vec<(PropKey, Value)>>);
impl PropMap {
pub fn new() -> Self {
Self::default()
}
pub fn from_sorted_pairs(pairs: Vec<(PropKey, Value)>) -> Self {
debug_assert!(
pairs.windows(2).all(|w| *w[0].0 < *w[1].0),
"PropMap::from_sorted_pairs got unsorted or duplicated keys"
);
Self(Arc::new(pairs))
}
pub fn from_pairs(mut pairs: Vec<(PropKey, Value)>) -> Self {
pairs.sort_by(|a, b| a.0.cmp(&b.0));
dedup_keep_last(&mut pairs);
Self(Arc::new(pairs))
}
#[inline]
pub fn get(&self, key: &str) -> Option<&Value> {
self.position(key).map(|i| &self.0[i].1)
}
#[inline]
pub fn get_key_value(&self, key: &str) -> Option<(&PropKey, &Value)> {
self.position(key).map(|i| {
let (k, v) = &self.0[i];
(k, v)
})
}
#[inline]
pub fn contains_key(&self, key: &str) -> bool {
self.position(key).is_some()
}
#[inline]
pub fn len(&self) -> usize {
self.0.len()
}
#[inline]
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
#[inline]
pub fn iter(&self) -> impl Iterator<Item = (&str, &Value)> + Clone {
self.0.iter().map(|(k, v)| (&**k, v))
}
#[inline]
pub fn keys(&self) -> impl Iterator<Item = &str> + Clone {
self.0.iter().map(|(k, _)| &**k)
}
#[inline]
pub fn values(&self) -> impl Iterator<Item = &Value> + Clone {
self.0.iter().map(|(_, v)| v)
}
pub fn insert(&mut self, key: impl Into<PropKey>, value: Value) -> Option<Value> {
let key = key.into();
let entries = Arc::make_mut(&mut self.0);
match entries.binary_search_by(|(k, _)| (**k).cmp(&key)) {
Ok(i) => Some(std::mem::replace(&mut entries[i].1, value)),
Err(i) => {
entries.insert(i, (key, value));
None
}
}
}
pub fn remove(&mut self, key: &str) -> Option<Value> {
let entries = Arc::make_mut(&mut self.0);
match entries.binary_search_by(|(k, _)| (**k).cmp(key)) {
Ok(i) => Some(entries.remove(i).1),
Err(_) => None,
}
}
pub fn get_mut(&mut self, key: &str) -> Option<&mut Value> {
let i = self.position(key)?;
Some(&mut Arc::make_mut(&mut self.0)[i].1)
}
pub fn retain(&mut self, mut f: impl FnMut(&str, &Value) -> bool) {
Arc::make_mut(&mut self.0).retain(|(k, v)| f(k, v));
}
pub fn into_pairs(self) -> Vec<(PropKey, Value)> {
Arc::try_unwrap(self.0).unwrap_or_else(|arc| (*arc).clone())
}
#[inline]
fn position(&self, key: &str) -> Option<usize> {
self.0.binary_search_by(|(k, _)| (**k).cmp(key)).ok()
}
}
fn dedup_keep_last(pairs: &mut Vec<(PropKey, Value)>) {
if pairs.len() < 2 {
return;
}
let mut write = 0usize;
for read in 1..pairs.len() {
if pairs[read].0 == pairs[write].0 {
pairs.swap(write, read);
} else {
write += 1;
pairs.swap(write, read);
}
}
pairs.truncate(write + 1);
}
pub type PropMapIter<'a> = std::iter::Map<
std::slice::Iter<'a, (PropKey, Value)>,
fn(&'a (PropKey, Value)) -> (&'a str, &'a Value),
>;
impl<'a> IntoIterator for &'a PropMap {
type Item = (&'a str, &'a Value);
type IntoIter = PropMapIter<'a>;
fn into_iter(self) -> Self::IntoIter {
fn split(e: &(PropKey, Value)) -> (&str, &Value) {
(&e.0, &e.1)
}
self.0
.iter()
.map(split as fn(&'a (PropKey, Value)) -> (&'a str, &'a Value))
}
}
impl IntoIterator for PropMap {
type Item = (PropKey, Value);
type IntoIter = std::vec::IntoIter<(PropKey, Value)>;
fn into_iter(self) -> Self::IntoIter {
self.into_pairs().into_iter()
}
}
impl FromIterator<(PropKey, Value)> for PropMap {
fn from_iter<T: IntoIterator<Item = (PropKey, Value)>>(iter: T) -> Self {
Self::from_pairs(iter.into_iter().collect())
}
}
impl<'a> FromIterator<(&'a str, Value)> for PropMap {
fn from_iter<T: IntoIterator<Item = (&'a str, Value)>>(iter: T) -> Self {
Self::from_pairs(
iter.into_iter()
.map(|(k, v)| (PropKey::from(k), v))
.collect(),
)
}
}
impl From<BTreeMap<String, Value>> for PropMap {
fn from(map: BTreeMap<String, Value>) -> Self {
Self::from_sorted_pairs(
map.into_iter()
.map(|(k, v)| (PropKey::from(k), v))
.collect(),
)
}
}
impl From<PropMap> for BTreeMap<String, Value> {
fn from(map: PropMap) -> Self {
map.into_pairs()
.into_iter()
.map(|(k, v)| (k.to_string(), v))
.collect()
}
}
impl Serialize for PropMap {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let mut map = serializer.serialize_map(Some(self.0.len()))?;
for (k, v) in self.0.iter() {
map.serialize_entry(&**k, v)?;
}
map.end()
}
}
struct PropKeySeed;
impl<'de> Deserialize<'de> for PropKeyWrapper {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
deserializer.deserialize_str(PropKeySeed)
}
}
struct PropKeyWrapper(PropKey);
impl<'de> Visitor<'de> for PropKeySeed {
type Value = PropKeyWrapper;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("a property key string")
}
fn visit_str<E: serde::de::Error>(self, v: &str) -> Result<Self::Value, E> {
Ok(PropKeyWrapper(PropKey::from(v)))
}
fn visit_string<E: serde::de::Error>(self, v: String) -> Result<Self::Value, E> {
Ok(PropKeyWrapper(PropKey::from(v)))
}
}
impl<'de> Deserialize<'de> for PropMap {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct MapVisitor;
impl<'de> Visitor<'de> for MapVisitor {
type Value = PropMap;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("a map of property names to values")
}
fn visit_map<A: MapAccess<'de>>(self, mut access: A) -> Result<PropMap, A::Error> {
let mut pairs: Vec<(PropKey, Value)> =
Vec::with_capacity(access.size_hint().unwrap_or(0).min(64));
while let Some((PropKeyWrapper(k), v)) =
access.next_entry::<PropKeyWrapper, Value>()?
{
pairs.push((k, v));
}
if pairs.windows(2).all(|w| w[0].0 < w[1].0) {
Ok(PropMap::from_sorted_pairs(pairs))
} else {
Ok(PropMap::from_pairs(pairs))
}
}
}
deserializer.deserialize_map(MapVisitor)
}
}
#[cfg(test)]
mod tests;