use serde::de::Error;
use serde::ser::SerializeSeq;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::ops::{Deref, DerefMut};
#[derive(Debug, Clone, Eq, PartialEq, Default)]
pub struct Map(Vec<(Key, String)>);
impl Map {
pub fn new() -> Self {
Self::default()
}
pub fn get<S: AsRef<str>>(&self, value_name: S) -> Option<&str> {
let value_name = value_name.as_ref();
self.0
.iter()
.filter_map(|(k, v)| {
if k.as_str() == value_name {
Some(v.as_str())
} else {
None
}
})
.next()
}
pub fn get_all<S: AsRef<str>>(&self, value_name: S) -> impl Iterator<Item = &str> {
self.0.iter().filter_map(move |(k, v)| {
if k.as_str() == value_name.as_ref() {
Some(v.as_str())
} else {
None
}
})
}
pub fn push<K: Into<Key>, V: Into<String>>(&mut self, value_name: K, value: V) {
self.0.push((value_name.into(), value.into()));
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
#[must_use]
pub fn iter(&self) -> Iter {
Iter(self.0.iter())
}
}
impl Deref for Map {
type Target = [(Key, String)];
fn deref(&self) -> &Self::Target {
self.0.as_slice()
}
}
impl DerefMut for Map {
fn deref_mut(&mut self) -> &mut Self::Target {
self.0.as_mut_slice()
}
}
impl Serialize for Map {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut seq = serializer.serialize_seq(Some(self.0.len()))?;
for (key, value) in &self.0 {
seq.serialize_element(&format!("{}={}", key, value))?;
}
seq.end()
}
}
impl<'de> Deserialize<'de> for Map {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let entries = <Option<Vec<String>>>::deserialize(deserializer)?;
let vec = entries
.unwrap_or_default()
.into_iter()
.map(|mut string: String| {
if let Some(eq_index) = string.find('=') {
let value = string.split_off(eq_index + 1);
string.truncate(eq_index);
Key::try_from(string)
.map(|key| (key, value))
.map_err(D::Error::custom)
} else {
Err(D::Error::custom("invalid map entry: missing \"=\""))
}
})
.collect::<Result<Vec<(Key, String)>, D::Error>>()?;
Ok(Self(vec))
}
}
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
pub struct Key(String);
impl Key {
pub fn as_str(&self) -> &str {
self.0.as_str()
}
pub fn from_static(value: &'static str) -> Self {
Self::try_from(String::from(value)).expect("static string must be a valid Key")
}
}
impl AsRef<str> for Key {
fn as_ref(&self) -> &str {
self.0.as_str()
}
}
impl std::fmt::Display for Key {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.write_str(self.as_str())
}
}
impl PartialEq<&str> for Key {
fn eq(&self, other: &&str) -> bool {
self.as_str() == *other
}
}
impl PartialEq<Key> for &str {
fn eq(&self, other: &Key) -> bool {
*self == other.as_str()
}
}
impl TryFrom<String> for Key {
type Error = InvalidKeyError;
fn try_from(value: String) -> Result<Self, Self::Error> {
if value.contains(' ')
|| value.contains('<')
|| value.contains('>')
|| value.contains('&')
|| value.contains(',')
|| value.contains('=')
{
Err(InvalidKeyError(value))
} else {
Ok(Key(value))
}
}
}
impl From<&'static str> for Key {
fn from(key: &'static str) -> Self {
Key::from_static(key)
}
}
impl std::str::FromStr for Key {
type Err = InvalidKeyError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
String::from(s).try_into()
}
}
impl From<Key> for String {
fn from(key: Key) -> Self {
key.0
}
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct InvalidKeyError(String);
impl std::fmt::Display for InvalidKeyError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "invalid map key: {:?}", self.0)
}
}
impl std::error::Error for InvalidKeyError {}
impl FromIterator<(Key, String)> for Map {
fn from_iter<T: IntoIterator<Item = (Key, String)>>(iter: T) -> Self {
Self(iter.into_iter().collect())
}
}
impl<'a> FromIterator<(Key, &'a str)> for Map {
fn from_iter<T: IntoIterator<Item = (Key, &'a str)>>(iter: T) -> Self {
Self(
iter.into_iter()
.map(|(k, v)| (k, String::from(v)))
.collect(),
)
}
}
impl<'a> FromIterator<(&'static str, &'a str)> for Map {
fn from_iter<T: IntoIterator<Item = (&'static str, &'a str)>>(iter: T) -> Self {
Self(
iter.into_iter()
.map(|(k, v)| (Key::from_static(k), String::from(v)))
.collect(),
)
}
}
pub struct Iter<'a>(std::slice::Iter<'a, (Key, String)>);
impl<'a> Iterator for Iter<'a> {
type Item = (&'a Key, &'a str);
fn next(&mut self) -> Option<Self::Item> {
self.0.next().map(|(k, v)| (k, v.as_str()))
}
}
pub struct IterMut<'a>(std::slice::IterMut<'a, (Key, String)>);
impl<'a> Iterator for IterMut<'a> {
type Item = (&'a mut Key, &'a mut String);
fn next(&mut self) -> Option<Self::Item> {
self.0.next().map(|(k, v)| (k, v))
}
}
impl<'a> IntoIterator for &'a Map {
type Item = (&'a Key, &'a str);
type IntoIter = Iter<'a>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a> IntoIterator for Map {
type Item = (Key, String);
type IntoIter = std::vec::IntoIter<(Key, String)>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn deserialize() {
#[derive(Deserialize)]
struct Doc {
#[serde(rename = "{http://www.incident.com/cap/1.0}:cap:area")]
area: Area,
}
#[derive(Deserialize)]
struct Area {
#[serde(rename = "{http://www.incident.com/cap/1.0}cap:geocode")]
pub geocode: Map,
}
let doc: Doc = xml_serde::from_str(
r#"
<cap:area xmlns:cap="http://www.incident.com/cap/1.0">
<cap:geocode>fips6=006109</cap:geocode>
<cap:geocode>fips6=006109</cap:geocode>
<cap:geocode>fips6=006103</cap:geocode>
</cap:area>
"#,
)
.expect("parse");
assert_eq!(
doc.area
.geocode
.0
.iter()
.map(|(k, v)| (k.as_str(), v.as_str()))
.collect::<Vec<_>>(),
vec![
("fips6", "006109"),
("fips6", "006109"),
("fips6", "006103"),
]
);
}
}