use proc_macro2::TokenStream as TokenStream2;
use quote::quote;
use syn::{LitInt, LitStr};
use crate::derive::config::EnumBitsetConfig;
#[allow(dead_code)]
impl EnumBitsetConfig {
pub(crate) fn impl_serde_map(&self) -> TokenStream2 {
let mut output = TokenStream2::new();
if self.serde.ser {
output.extend(self.impl_serde_map_ser());
}
if self.serde.de {
output.extend(self.impl_serde_map_de());
}
output
}
fn impl_serde_map_ser(&self) -> TokenStream2 {
{
let n_variants = LitInt::new(&self.variants.len().to_string(), self.base_type.span());
let base_ty = &self.base_type;
let set_ty = &self.set_type;
let serde = &self.serde.serde_crate;
let variants = self.variants.iter().map(|variant| {
let name = &variant.ident;
quote! {
map.serialize_key(&#base_ty :: #name)?;
map.serialize_value(&self.contains(&#base_ty :: #name))?;
}
});
quote! {
use #serde::{Serialize, Serializer, ser::{SerializeMap}};
const _: fn() = || {
fn base_enum_for_bitsets_must_be_serializable<T: Serialize>() {}
base_enum_for_bitsets_must_be_serializable::<#set_ty>();
};
impl Serialize for #set_ty {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut map = serializer.serialize_map(Some(#n_variants))?;
#(#variants)*
map.end()
}
}
}
}
}
fn impl_serde_map_de(&self) -> TokenStream2 {
let name = &self.set_type;
let base = &self.base_type;
let serde = &self.serde.serde_crate;
let expect = LitStr::new(
&format!("a map from `{name}` variants to boolean values"),
name.span(),
);
quote! {
use #serde::{Deserialize, Deserializer, de::{SeqAccess, Visitor}};
const _: fn() = || {
fn base_enum_for_bitsets_must_be_deserializable<T: for<'de> Deserialize<'de>>() {}
base_enum_for_bitsets_must_be_deserializable::<#name>();
};
impl<'de> Deserialize<'de> for #name {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct VisitMap;
impl<'de> Visitor<'de> for VisitMap {
type Value = #name;
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
formatter.write_str(#expect)
}
fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
where A: #serde::de::MapAccess<'de>
{
let mut result = #name::new();
while let Some(variant) = map.next_key::<#base>()? {
let value : bool = map.next_value()?;
if value {
result.insert(variant);
}
}
Ok(result)
}
}
deserializer.deserialize_map(VisitMap)
}
}
}
}
}