Merge rust-bitcoin/rust-bitcoin#1291: Remove `user_enum` macro
f429c22599
Remove user_enum macro (Tobin C. Harding)ad29084582
Add Network serde roundtrip test (Tobin C. Harding) Pull request description: Remove the `user_enum` macro because it is only used once and is unnecessarily complicated. Patch 1: Add a preparatory unit test to make sure patch 2 maintains the current serde logic. Patch 2: Simplify `Network` by removing `user_enum` ACKs for top commit: Kixunil: ACKf429c22599
apoelstra: ACKf429c22599
Tree-SHA512: 770ee0aa82be711ed11bdfda338de8d13071743cdc8d7e3e1252a6759dfdfa2be6ff1d8cd286acef75dc5a5d73a6bc5f565b02cb20d4b549e0714cef5d7c1973
This commit is contained in:
commit
b309f41076
|
@ -538,94 +538,6 @@ macro_rules! impl_bytes_newtype {
|
||||||
}
|
}
|
||||||
pub(crate) use impl_bytes_newtype;
|
pub(crate) use impl_bytes_newtype;
|
||||||
|
|
||||||
macro_rules! user_enum {
|
|
||||||
(
|
|
||||||
$(#[$attr:meta])*
|
|
||||||
pub enum $name:ident {
|
|
||||||
$(#[$doc:meta]
|
|
||||||
$elem:ident <-> $txt:literal),*
|
|
||||||
}
|
|
||||||
) => (
|
|
||||||
$(#[$attr])*
|
|
||||||
pub enum $name {
|
|
||||||
$(#[$doc] $elem),*
|
|
||||||
}
|
|
||||||
|
|
||||||
impl core::fmt::Display for $name {
|
|
||||||
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
|
||||||
f.pad(match *self {
|
|
||||||
$($name::$elem => $txt),*
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl core::str::FromStr for $name {
|
|
||||||
type Err = $crate::io::Error;
|
|
||||||
#[inline]
|
|
||||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
|
||||||
match s {
|
|
||||||
$($txt => Ok($name::$elem)),*,
|
|
||||||
_ => {
|
|
||||||
#[cfg(not(feature = "std"))] let message = "Unknown network";
|
|
||||||
#[cfg(feature = "std")] let message = format!("Unknown network (type {})", s);
|
|
||||||
Err($crate::io::Error::new(
|
|
||||||
$crate::io::ErrorKind::InvalidInput,
|
|
||||||
message,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
|
|
||||||
impl<'de> $crate::serde::Deserialize<'de> for $name {
|
|
||||||
#[inline]
|
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
|
||||||
where
|
|
||||||
D: $crate::serde::Deserializer<'de>,
|
|
||||||
{
|
|
||||||
use core::fmt::{self, Formatter};
|
|
||||||
|
|
||||||
struct Visitor;
|
|
||||||
impl<'de> $crate::serde::de::Visitor<'de> for Visitor {
|
|
||||||
type Value = $name;
|
|
||||||
|
|
||||||
fn expecting(&self, f: &mut Formatter) -> fmt::Result {
|
|
||||||
f.write_str("an enum value")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
|
|
||||||
where
|
|
||||||
E: $crate::serde::de::Error,
|
|
||||||
{
|
|
||||||
static FIELDS: &'static [&'static str] = &[$(stringify!($txt)),*];
|
|
||||||
|
|
||||||
$( if v == $txt { Ok($name::$elem) } )else*
|
|
||||||
else {
|
|
||||||
Err(E::unknown_variant(v, FIELDS))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
deserializer.deserialize_str(Visitor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "serde")]
|
|
||||||
#[cfg_attr(docsrs, doc(cfg(feature = "serde")))]
|
|
||||||
impl $crate::serde::Serialize for $name {
|
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
||||||
where
|
|
||||||
S: $crate::serde::Serializer,
|
|
||||||
{
|
|
||||||
serializer.collect_str(&self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
pub(crate) use user_enum;
|
|
||||||
|
|
||||||
/// Asserts a boolean expression at compile time.
|
/// Asserts a boolean expression at compile time.
|
||||||
macro_rules! const_assert {
|
macro_rules! const_assert {
|
||||||
($x:expr) => {{
|
($x:expr) => {{
|
||||||
|
|
|
@ -27,10 +27,13 @@
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
use core::{fmt, ops, convert::From};
|
use core::{fmt, ops, convert::From};
|
||||||
|
use core::str::FromStr;
|
||||||
|
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::io;
|
use crate::io;
|
||||||
use crate::consensus::encode::{self, Encodable, Decodable};
|
use crate::consensus::encode::{self, Encodable, Decodable};
|
||||||
use crate::internal_macros::user_enum;
|
|
||||||
|
|
||||||
/// Version of the protocol as appearing in network message headers
|
/// Version of the protocol as appearing in network message headers
|
||||||
/// This constant is used to signal to other peers which features you support.
|
/// This constant is used to signal to other peers which features you support.
|
||||||
|
@ -49,19 +52,21 @@ use crate::internal_macros::user_enum;
|
||||||
/// 60001 - Support `pong` message and nonce in `ping` message
|
/// 60001 - Support `pong` message and nonce in `ping` message
|
||||||
pub const PROTOCOL_VERSION: u32 = 70001;
|
pub const PROTOCOL_VERSION: u32 = 70001;
|
||||||
|
|
||||||
user_enum! {
|
/// The cryptocurrency network to act on.
|
||||||
/// The cryptocurrency to act on
|
#[derive(Copy, PartialEq, Eq, PartialOrd, Ord, Clone, Hash, Debug)]
|
||||||
#[derive(Copy, PartialEq, Eq, PartialOrd, Ord, Clone, Hash, Debug)]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub enum Network {
|
#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
|
||||||
/// Classic Bitcoin
|
#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
|
||||||
Bitcoin <-> "bitcoin",
|
#[non_exhaustive]
|
||||||
/// Bitcoin's testnet
|
pub enum Network {
|
||||||
Testnet <-> "testnet",
|
/// Mainnet Bitcoin.
|
||||||
/// Bitcoin's signet
|
Bitcoin,
|
||||||
Signet <-> "signet",
|
/// Bitcoin's testnet network.
|
||||||
/// Bitcoin's regtest
|
Testnet,
|
||||||
Regtest <-> "regtest"
|
/// Bitcoin's signet network.
|
||||||
}
|
Signet,
|
||||||
|
/// Bitcoin's regtest network.
|
||||||
|
Regtest,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Network {
|
impl Network {
|
||||||
|
@ -108,6 +113,43 @@ impl Network {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Network {
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
|
||||||
|
use Network::*;
|
||||||
|
|
||||||
|
let s = match *self {
|
||||||
|
Bitcoin => "bitcoin",
|
||||||
|
Testnet => "testnet",
|
||||||
|
Signet => "signet",
|
||||||
|
Regtest => "regtest",
|
||||||
|
};
|
||||||
|
write!(f, "{}", s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for Network {
|
||||||
|
type Err = io::Error;
|
||||||
|
#[inline]
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
use Network::*;
|
||||||
|
|
||||||
|
let network = match s {
|
||||||
|
"bitcoin" => Bitcoin,
|
||||||
|
"testnet" => Testnet,
|
||||||
|
"signet" => Signet,
|
||||||
|
"regtest" => Regtest,
|
||||||
|
_ => {
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
let message = format!("Unknown network (type {})", s);
|
||||||
|
#[cfg(not(feature = "std"))]
|
||||||
|
let message = "Unknown network";
|
||||||
|
return Err(io::Error::new(io::ErrorKind::InvalidInput, message));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Ok(network)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Flags to indicate which network services a node supports.
|
/// Flags to indicate which network services a node supports.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct ServiceFlags(u64);
|
pub struct ServiceFlags(u64);
|
||||||
|
@ -348,4 +390,22 @@ mod tests {
|
||||||
let flag = ServiceFlags::WITNESS | 0xf0.into();
|
let flag = ServiceFlags::WITNESS | 0xf0.into();
|
||||||
assert_eq!("ServiceFlags(WITNESS|COMPACT_FILTERS|0xb0)", flag.to_string());
|
assert_eq!("ServiceFlags(WITNESS|COMPACT_FILTERS|0xb0)", flag.to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
fn serde_roundtrip() {
|
||||||
|
use Network::*;
|
||||||
|
let tests = vec![(Bitcoin, "bitcoin"), (Testnet, "testnet"), (Signet, "signet"), (Regtest, "regtest")];
|
||||||
|
|
||||||
|
for tc in tests {
|
||||||
|
let network = tc.0;
|
||||||
|
|
||||||
|
let want = format!("\"{}\"", tc.1);
|
||||||
|
let got = serde_json::to_string(&tc.0).expect("failed to serialize network");
|
||||||
|
assert_eq!(got, want);
|
||||||
|
|
||||||
|
let back: Network = serde_json::from_str(&got).expect("failed to deserialize network");
|
||||||
|
assert_eq!(back, network);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue