sdk_common/src/serialization.rs

157 lines
4.6 KiB
Rust

use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde::de::Error;
use sp_client::bitcoin::hex::{DisplayHex, FromHex};
use sp_client::bitcoin::OutPoint;
use std::collections::{BTreeMap, HashMap};
use crate::{pcd::Member, process::Process};
#[derive(Debug, Serialize, Deserialize)]
pub struct OutPointMemberMap(#[serde(with = "members_map")] pub HashMap<OutPoint, Member>);
#[derive(Debug, Serialize, Deserialize)]
pub struct OutPointProcessMap(#[serde(with = "outpoint_map")] pub HashMap<OutPoint, Process>);
// These helper functions convert a [u8; 32] to/from a hex string.
pub(crate) fn serialize_hex<S>(bytes: &[u8; 32], serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let hex_str = bytes.to_lower_hex_string();
serializer.serialize_str(&hex_str)
}
pub(crate) fn deserialize_hex<'de, D>(deserializer: D) -> Result<[u8; 32], D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
let bytes = Vec::from_hex(&s).map_err(D::Error::custom)?;
if bytes.len() != 32 {
return Err(D::Error::custom("Invalid length for [u8;32]"));
}
let mut arr = [0u8; 32];
arr.copy_from_slice(&bytes);
Ok(arr)
}
pub mod members_map {
use super::*;
use crate::pcd::Member;
pub fn serialize<S>(
map: &HashMap<OutPoint, Member>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let map: HashMap<OutPoint, Member> = map
.iter()
.map(|(k, v)| (*k, v.to_owned()))
.collect();
map.serialize(serializer)
}
pub fn deserialize<'de, D>(
deserializer: D,
) -> Result<HashMap<OutPoint, Member>, D::Error>
where
D: Deserializer<'de>,
{
let map: HashMap<OutPoint, Member> = HashMap::deserialize(deserializer)?;
Ok(map)
}
}
pub mod outpoint_map {
use super::*;
use crate::process::Process;
pub fn serialize<S>(
map: &HashMap<OutPoint, Process>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
// Convert OutPoint keys to Strings
let map: HashMap<String, Process> = map
.into_iter()
.map(|(k, v)| (k.to_string(), v.clone()))
.collect();
// Serialize as HashMap<String, Process>
map.serialize(serializer)
}
pub fn deserialize<'de, D>(
deserializer: D,
) -> Result<HashMap<OutPoint, Process>, D::Error>
where
D: Deserializer<'de>,
{
// Deserialize as HashMap<String, Process>
let map: HashMap<String, Process> = HashMap::deserialize(deserializer)?;
// Convert String keys back to OutPoint
let result: Result<HashMap<OutPoint, Process>, D::Error> = map
.into_iter()
.map(|(k, v)| {
let outpoint = k
.parse()
.map_err(serde::de::Error::custom)?;
Ok((outpoint, v))
})
.collect();
result
}
}
// Custom module for converting a BTreeMap<String, [u8;32]> using hex conversion.
pub mod hex_array_btree {
use super::*;
// Serializes a BTreeMap<String, [u8; 32]> as a BTreeMap<String, String>
// where the value is a hex-encoded string.
pub fn serialize<S>(
map: &BTreeMap<String, [u8; 32]>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
// Convert each [u8; 32] to a hex string.
let hex_map: BTreeMap<String, String> = map
.iter()
.map(|(k, v)| (k.clone(), v.to_lower_hex_string()))
.collect();
hex_map.serialize(serializer)
}
// Deserializes a BTreeMap<String, [u8; 32]> from a BTreeMap<String, String>
// where the value is expected to be a hex-encoded string.
pub fn deserialize<'de, D>(
deserializer: D,
) -> Result<BTreeMap<String, [u8; 32]>, D::Error>
where
D: Deserializer<'de>,
{
// Deserialize into a temporary map with hex string values.
let hex_map: BTreeMap<String, String> = BTreeMap::deserialize(deserializer)?;
let mut map = BTreeMap::new();
// Convert each hex string back into a [u8; 32].
for (key, hex_str) in hex_map {
let bytes = Vec::from_hex(&hex_str).map_err(D::Error::custom)?;
if bytes.len() != 32 {
return Err(D::Error::custom("Invalid length for [u8;32]"));
}
let mut array = [0u8; 32];
array.copy_from_slice(&bytes);
map.insert(key, array);
}
Ok(map)
}
}