// SPDX-License-Identifier: CC0-1.0 //! Bitcoin serde utilities. //! //! This module is for special serde serializations. //! pub mod btreemap_byte_values { //! Module for serialization of BTreeMaps with hex byte values. #![allow(missing_docs)] // NOTE: This module can be exactly copied to use with HashMap. use crate::prelude::*; use crate::hashes::hex::{FromHex, ToHex}; use serde; pub fn serialize(v: &BTreeMap>, s: S) -> Result where S: serde::Serializer, T: serde::Serialize + core::hash::Hash + Eq + Ord, { use serde::ser::SerializeMap; // Don't do anything special when not human readable. if !s.is_human_readable() { serde::Serialize::serialize(v, s) } else { let mut map = s.serialize_map(Some(v.len()))?; for (key, value) in v.iter() { map.serialize_entry(key, &value.to_hex())?; } map.end() } } pub fn deserialize<'de, D, T>(d: D) -> Result>, D::Error> where D: serde::Deserializer<'de>, T: serde::Deserialize<'de> + core::hash::Hash + Eq + Ord, { use core::marker::PhantomData; struct Visitor(PhantomData); impl<'de, T> serde::de::Visitor<'de> for Visitor where T: serde::Deserialize<'de> + core::hash::Hash + Eq + Ord, { type Value = BTreeMap>; fn expecting(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { write!(f, "a map with hexadecimal values") } fn visit_map>(self, mut a: A) -> Result { let mut ret = BTreeMap::new(); while let Some((key, value)) = a.next_entry()? { ret.insert(key, FromHex::from_hex(value).map_err(serde::de::Error::custom)?); } Ok(ret) } } // Don't do anything special when not human readable. if !d.is_human_readable() { serde::Deserialize::deserialize(d) } else { d.deserialize_map(Visitor(PhantomData)) } } } pub mod btreemap_as_seq { //! Module for serialization of BTreeMaps as lists of sequences because //! serde_json will not serialize hashmaps with non-string keys be default. #![allow(missing_docs)] // NOTE: This module can be exactly copied to use with HashMap. use crate::prelude::*; use serde; pub fn serialize(v: &BTreeMap, s: S) -> Result where S: serde::Serializer, T: serde::Serialize + core::hash::Hash + Eq + Ord, U: serde::Serialize, { use serde::ser::SerializeSeq; // Don't do anything special when not human readable. if !s.is_human_readable() { serde::Serialize::serialize(v, s) } else { let mut seq = s.serialize_seq(Some(v.len()))?; for pair in v.iter() { seq.serialize_element(&pair)?; } seq.end() } } pub fn deserialize<'de, D, T, U>(d: D) -> Result, D::Error> where D: serde::Deserializer<'de>, T: serde::Deserialize<'de> + core::hash::Hash + Eq + Ord, U: serde::Deserialize<'de>, { use core::marker::PhantomData; struct Visitor(PhantomData<(T, U)>); impl<'de, T, U> serde::de::Visitor<'de> for Visitor where T: serde::Deserialize<'de> + core::hash::Hash + Eq + Ord, U: serde::Deserialize<'de>, { type Value = BTreeMap; fn expecting(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { write!(f, "a sequence of pairs") } fn visit_seq>(self, mut a: A) -> Result { let mut ret = BTreeMap::new(); while let Some((key, value)) = a.next_element()? { ret.insert(key, value); } Ok(ret) } } // Don't do anything special when not human readable. if !d.is_human_readable() { serde::Deserialize::deserialize(d) } else { d.deserialize_seq(Visitor(PhantomData)) } } } pub mod btreemap_as_seq_byte_values { //! Module for serialization of BTreeMaps as lists of sequences because //! serde_json will not serialize hashmaps with non-string keys be default. #![allow(missing_docs)] // NOTE: This module can be exactly copied to use with HashMap. use crate::prelude::*; use serde; /// A custom key-value pair type that serialized the bytes as hex. #[derive(Debug, Deserialize)] #[serde(crate = "actual_serde")] struct OwnedPair( T, #[serde(deserialize_with = "crate::serde_utils::hex_bytes::deserialize")] Vec, ); /// A custom key-value pair type that serialized the bytes as hex. #[derive(Debug, Serialize)] #[serde(crate = "actual_serde")] struct BorrowedPair<'a, T: 'static>( &'a T, #[serde(serialize_with = "crate::serde_utils::hex_bytes::serialize")] &'a [u8], ); pub fn serialize(v: &BTreeMap>, s: S) -> Result where S: serde::Serializer, T: serde::Serialize + core::hash::Hash + Eq + Ord + 'static, { use serde::ser::SerializeSeq; // Don't do anything special when not human readable. if !s.is_human_readable() { serde::Serialize::serialize(v, s) } else { let mut seq = s.serialize_seq(Some(v.len()))?; for (key, value) in v.iter() { seq.serialize_element(&BorrowedPair(key, value))?; } seq.end() } } pub fn deserialize<'de, D, T>(d: D) -> Result>, D::Error> where D: serde::Deserializer<'de>, T: serde::Deserialize<'de> + core::hash::Hash + Eq + Ord, { use core::marker::PhantomData; struct Visitor(PhantomData); impl<'de, T> serde::de::Visitor<'de> for Visitor where T: serde::Deserialize<'de> + core::hash::Hash + Eq + Ord, { type Value = BTreeMap>; fn expecting(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { write!(f, "a sequence of pairs") } fn visit_seq>(self, mut a: A) -> Result { let mut ret = BTreeMap::new(); while let Option::Some(OwnedPair(key, value)) = a.next_element()? { ret.insert(key, value); } Ok(ret) } } // Don't do anything special when not human readable. if !d.is_human_readable() { serde::Deserialize::deserialize(d) } else { d.deserialize_seq(Visitor(PhantomData)) } } } pub mod hex_bytes { //! Module for serialization of byte arrays as hex strings. #![allow(missing_docs)] use hashes::hex::{FromHex, ToHex}; use serde; pub fn serialize(bytes: &T, s: S) -> Result where T: serde::Serialize + AsRef<[u8]>, S: serde::Serializer { // Don't do anything special when not human readable. if !s.is_human_readable() { serde::Serialize::serialize(bytes, s) } else { s.serialize_str(&bytes.as_ref().to_hex()) } } pub fn deserialize<'de, D, B>(d: D) -> Result where D: serde::Deserializer<'de>, B: serde::Deserialize<'de> + FromHex, { struct Visitor(core::marker::PhantomData); impl<'de, B: FromHex> serde::de::Visitor<'de> for Visitor { type Value = B; fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result { formatter.write_str("an ASCII hex string") } fn visit_bytes(self, v: &[u8]) -> Result where E: serde::de::Error, { if let Ok(hex) = core::str::from_utf8(v) { FromHex::from_hex(hex).map_err(E::custom) } else { return Err(E::invalid_value(serde::de::Unexpected::Bytes(v), &self)); } } fn visit_str(self, v: &str) -> Result where E: serde::de::Error, { FromHex::from_hex(v).map_err(E::custom) } } // Don't do anything special when not human readable. if !d.is_human_readable() { serde::Deserialize::deserialize(d) } else { d.deserialize_str(Visitor(core::marker::PhantomData)) } } }