use std::fmt;
use std::marker::PhantomData;
use serde::de::{MapAccess, Visitor};
use serde::ser::SerializeMap;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
pub(crate) fn serialize<S, T>(entries: &[(String, T)], serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
T: Serialize,
{
let mut map = serializer.serialize_map(Some(entries.len()))?;
for (name, value) in entries {
map.serialize_entry(name, value)?;
}
map.end()
}
pub(crate) fn deserialize<'de, D, T>(deserializer: D) -> Result<Vec<(String, T)>, D::Error>
where
D: Deserializer<'de>,
T: Deserialize<'de>,
{
struct Entries<T>(PhantomData<T>);
impl<'de, T: Deserialize<'de>> Visitor<'de> for Entries<T> {
type Value = Vec<(String, T)>;
fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("a map")
}
fn visit_map<A: MapAccess<'de>>(self, mut access: A) -> Result<Self::Value, A::Error> {
let mut entries = Vec::with_capacity(cautious_capacity(access.size_hint()));
while let Some(entry) = access.next_entry()? {
entries.push(entry);
}
Ok(entries)
}
}
deserializer.deserialize_map(Entries(PhantomData))
}
pub(crate) fn cautious_capacity(hint: Option<usize>) -> usize {
const MAX_PREALLOCATED: usize = 4096;
hint.unwrap_or(0).min(MAX_PREALLOCATED)
}
pub(crate) fn get<'a, T>(entries: &'a [(String, T)], name: &str) -> Option<&'a T> {
entries
.iter()
.find(|(key, _)| key == name)
.map(|(_, value)| value)
}