pub(super) static NEWTYPE_SYMBOL: &str = "\u{037E}STRINGSET\u{037E}";
#[inline]
pub(crate) fn should_serialize_as_string_set(name: &str) -> bool {
std::ptr::eq(name, NEWTYPE_SYMBOL)
}
pub fn serialize<T, S>(value: &T, serializer: S) -> Result<S::Ok, S::Error>
where
T: serde_core::Serialize,
S: serde_core::Serializer,
{
serializer.serialize_newtype_struct(NEWTYPE_SYMBOL, &value)
}
pub fn deserialize<'de, T, D>(deserializer: D) -> Result<T, D::Error>
where
T: serde_core::Deserialize<'de>,
D: serde_core::Deserializer<'de>,
{
T::deserialize(deserializer)
}
pub struct StringSet<T>(pub T);
impl<T> serde_core::Serialize for StringSet<T>
where
T: serde_core::Serialize,
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde_core::Serializer,
{
serializer.serialize_newtype_struct(NEWTYPE_SYMBOL, &self.0)
}
}
#[inline(never)]
pub(crate) fn convert_to_set(value: crate::AttributeValue) -> crate::Result<crate::AttributeValue> {
let vals = match value {
crate::AttributeValue::L(vals) => vals,
_ => return Err(crate::error::ErrorImpl::NotSetlike.into()),
};
let set = vals
.into_iter()
.map(|v| {
if let crate::AttributeValue::S(s) = v {
Ok(s)
} else {
Err(crate::error::ErrorImpl::StringSetExpectedType.into())
}
})
.collect::<Result<_, _>>()?;
Ok(crate::AttributeValue::Ss(set))
}
#[cfg(test)]
mod tests {
use serde_derive::{Deserialize, Serialize};
use crate::string_set::StringSet;
#[test]
fn newtype_strings_set_in_struct() {
let set = vec!["test".to_string(), "test2".to_string()];
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
struct Struct {
#[serde(with = "crate::string_set")]
set: Vec<String>,
}
let item: crate::Item = dbg!(crate::to_item(Struct { set }).unwrap());
assert_eq!(
item["set"],
crate::AttributeValue::Ss(vec!["test".to_string(), "test2".to_string(),])
);
}
#[test]
fn newtype_set_for_strings() {
let set = vec!["test", "test2"];
let val: crate::AttributeValue = dbg!(crate::to_attribute_value(StringSet(set)).unwrap());
assert_eq!(
val,
crate::AttributeValue::Ss(vec!["test".to_string(), "test2".to_string(),])
);
}
}