From aa6a3530a626c17a875c0d961ece2ef8ab73d7fb Mon Sep 17 00:00:00 2001 From: Sergi Delgado Segura Date: Sat, 15 Apr 2023 08:49:45 +0200 Subject: [PATCH] Adds as_core_arg serde module to network The new module provides serde functions to convert from/to Bitcoin Core network variants Includes tests suggested by @tcharding --- bitcoin/src/network/constants.rs | 67 ++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/bitcoin/src/network/constants.rs b/bitcoin/src/network/constants.rs index 1259cb5a..61c416ec 100644 --- a/bitcoin/src/network/constants.rs +++ b/bitcoin/src/network/constants.rs @@ -173,6 +173,52 @@ impl Network { } } +#[cfg(feature = "serde")] +pub mod as_core_arg { + //! Module for serialization/deserialization of network variants into/from Bitcoin Core values + #![allow(missing_docs)] + + use serde; + + use crate::Network; + + pub fn serialize(network: &Network, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(network.to_core_arg()) + } + + pub fn deserialize<'de, D>(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + struct NetworkVisitor; + + impl<'de> serde::de::Visitor<'de> for NetworkVisitor { + type Value = Network; + + fn visit_str(self, s: &str) -> Result { + Network::from_core_arg(s).map_err(|_| { + E::invalid_value( + serde::de::Unexpected::Str(s), + &"bitcoin network encoded as a string (either main, test, signet or regtest)", + ) + }) + } + + fn expecting(&self, formatter: &mut core::fmt::Formatter) -> core::fmt::Result { + write!( + formatter, + "bitcoin network encoded as a string (either main, test, signet or regtest)" + ) + } + } + + deserializer.deserialize_str(NetworkVisitor) + } +} + /// An error in parsing network string. #[derive(Debug, Clone, PartialEq, Eq)] pub struct ParseNetworkError(String); @@ -671,4 +717,25 @@ mod tests { assert_eq!(net.to_core_arg(), *core_arg); } } + + #[cfg(feature = "serde")] + #[test] + fn serde_as_core_arg() { + #[derive(Serialize, Deserialize, PartialEq, Debug)] + #[serde(crate = "actual_serde")] + struct T { + #[serde(with = "crate::network::constants::as_core_arg")] + pub network: Network, + } + + serde_test::assert_tokens( + &T { network: Network::Bitcoin }, + &[ + serde_test::Token::Struct { name: "T", len: 1 }, + serde_test::Token::Str("network"), + serde_test::Token::Str("main"), + serde_test::Token::StructEnd, + ], + ); + } }