use crate::models::FlagCollection;
use alloc::format;
use alloc::vec::Vec;
use core::hash::BuildHasherDefault;
use core::{convert::TryFrom, fmt::Debug};
use fnv::FnvHasher;
use serde::{de, ser, Deserialize, Deserializer, Serialize, Serializer};
use serde_json::Value;
use strum::IntoEnumIterator;
pub type HashMap<K, V> = hashbrown::HashMap<K, V, BuildHasherDefault<FnvHasher>>;
fn serialize_flag<F, S>(flags: &FlagCollection<F>, s: S) -> Result<S::Ok, S::Error>
where
F: Serialize + IntoEnumIterator,
S: Serializer,
{
let flags_value_result: Result<Value, serde_json::Error> = serde_json::to_value(flags);
match flags_value_result {
Ok(flags_as_value) => {
let flag_vec_result: Result<Vec<u32>, serde_json::Error> =
serde_json::from_value(flags_as_value);
match flag_vec_result {
Ok(flags_vec) => s.serialize_u32(flags_vec.iter().sum()),
Err(_) => {
Err(ser::Error::custom("SerdeIntermediateStepError: Failed to turn flags into `Vec<u32>` during serialization"))
}
}
}
Err(_) => Err(ser::Error::custom(
"SerdeIntermediateStepError: Failed to turn flags into `Value` during serialization",
)),
}
}
fn deserialize_flags<'de, D, F>(d: D) -> Result<FlagCollection<F>, D::Error>
where
F: Serialize + IntoEnumIterator + Debug,
D: Deserializer<'de>,
{
let flags_u32 = u32::deserialize(d)?;
FlagCollection::<F>::try_from(flags_u32).map_err(|_e| {
de::Error::custom(format!(
"SerdeIntermediateStepError: Failed to turn `u32` into `FlagCollection<{}>` during deserialization",
core::any::type_name::<F>()
))
})
}
pub(crate) mod txn_flags {
use core::fmt::Debug;
use crate::_serde::{deserialize_flags, serialize_flag};
use serde::{Deserializer, Serialize, Serializer};
use crate::models::FlagCollection;
use strum::IntoEnumIterator;
pub fn serialize<F, S>(flags: &FlagCollection<F>, s: S) -> Result<S::Ok, S::Error>
where
F: Serialize + IntoEnumIterator + Debug,
S: Serializer,
{
if flags.0.is_empty() {
s.serialize_u32(0)
} else {
serialize_flag(flags, s)
}
}
pub fn deserialize<'de, F, D>(d: D) -> Result<FlagCollection<F>, D::Error>
where
F: Serialize + IntoEnumIterator + Debug,
D: Deserializer<'de>,
{
let flags_vec_result: Result<FlagCollection<F>, D::Error> = deserialize_flags(d);
match flags_vec_result {
Ok(flags_vec) => {
if flags_vec.0.is_empty() {
Ok(FlagCollection::<F>::default())
} else {
Ok(flags_vec)
}
}
Err(error) => Err(error),
}
}
}
pub(crate) mod lgr_obj_flags {
use core::fmt::Debug;
use crate::_serde::{deserialize_flags, serialize_flag};
use crate::models::FlagCollection;
use serde::{Deserializer, Serialize, Serializer};
use strum::IntoEnumIterator;
pub fn serialize<F, S>(flags: &FlagCollection<F>, s: S) -> Result<S::Ok, S::Error>
where
F: Serialize + IntoEnumIterator,
S: Serializer,
{
if !flags.0.is_empty() {
serialize_flag(flags, s)
} else {
s.serialize_u32(0)
}
}
pub fn deserialize<'de, F, D>(d: D) -> Result<FlagCollection<F>, D::Error>
where
F: Serialize + IntoEnumIterator + Debug,
D: Deserializer<'de>,
{
deserialize_flags(d)
}
}
#[macro_export]
macro_rules! serde_with_tag {
(
$(#[$attr:meta])*
pub struct $name:ident<$lt:lifetime> {
$(
$(#[$doc:meta])*
pub $field:ident: $ty:ty,
)*
}
) => {
$(#[$attr])*
pub struct $name<$lt> {
$(
$(#[$doc])*
pub $field: $ty,
)*
}
impl<$lt> ::serde::Serialize for $name<$lt> {
fn serialize<S>(&self, serializer: S) -> ::core::result::Result<S::Ok, S::Error>
where
S: ::serde::Serializer
{
#[derive(::serde::Serialize)]
#[serde(rename_all = "PascalCase")]
#[::serde_with::skip_serializing_none]
struct Helper<$lt> {
$(
$field: $ty,
)*
}
let helper = Helper {
$(
$field: self.$field.clone(),
)*
};
let mut state = serializer.serialize_map(Some(1))?;
state.serialize_key(stringify!($name))?;
state.serialize_value(&helper)?;
state.end()
}
}
impl<'de: $lt, $lt> ::serde::Deserialize<'de> for $name<$lt> {
#[allow(non_snake_case)]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
#[derive(::serde::Deserialize)]
#[serde(rename_all = "PascalCase")]
#[::serde_with::skip_serializing_none]
struct Helper<$lt> {
$(
$field: $ty,
)*
}
let hash_map: $crate::_serde::HashMap<&$lt str, Helper<$lt>> = $crate::_serde::HashMap::deserialize(deserializer)?;
let helper_result = hash_map.get(stringify!($name));
match helper_result {
Some(helper) => {
Ok(Self {
$(
$field: helper.$field.clone().into(),
)*
})
}
None => {
Err(::serde::de::Error::custom("SerdeIntermediateStepError: Unable to find model name as json key."))
}
}
}
}
};
(
$(#[$attr:meta])*
pub struct $name:ident {
$(
$(#[$doc:meta])*
pub $field:ident: $ty:ty,
)*
}
) => {
$(#[$attr])*
pub struct $name {
$(
$(#[$doc])*
pub $field: $ty,
)*
}
impl ::serde::Serialize for $name {
fn serialize<S>(&self, serializer: S) -> ::core::result::Result<S::Ok, S::Error>
where
S: ::serde::Serializer
{
#[derive(::serde::Serialize)]
#[serde(rename_all = "PascalCase")]
#[::serde_with::skip_serializing_none]
struct Helper {
$(
$field: $ty,
)*
}
let helper = Helper {
$(
$field: self.$field.clone(),
)*
};
let mut state = serializer.serialize_map(Some(1))?;
state.serialize_key(stringify!($name))?;
state.serialize_value(&helper)?;
state.end()
}
}
impl<'de> ::serde::Deserialize<'de> for $name {
#[allow(non_snake_case)]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
#[derive(::serde::Deserialize)]
#[serde(rename_all = "PascalCase")]
#[::serde_with::skip_serializing_none]
struct Helper {
$(
$field: $ty,
)*
}
let hash_map: $crate::_serde::HashMap<&'de str, Helper> = $crate::_serde::HashMap::deserialize(deserializer)?;
let helper_result = hash_map.get(stringify!($name));
match helper_result {
Some(helper) => {
Ok(Self {
$(
$field: helper.$field.clone().into(),
)*
})
}
None => {
Err(::serde::de::Error::custom("SerdeIntermediateStepError: Unable to find model name as json key."))
}
}
}
}
};
}