Remove user_enum macro

The `user_enum` macro is only used a single time. The macro includes
custom serde logic which can be trivially derived instead.

Remove the `user_enum` macro and just implement `Network` the old
fashioned way. Doing so simplifies the code.
This commit is contained in:
Tobin C. Harding 2022-09-20 15:27:25 +10:00
parent ad29084582
commit f429c22599
2 changed files with 56 additions and 102 deletions

View File

@ -538,94 +538,6 @@ macro_rules! 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.
macro_rules! const_assert {
($x:expr) => {{

View File

@ -27,10 +27,13 @@
//! ```
use core::{fmt, ops, convert::From};
use core::str::FromStr;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use crate::io;
use crate::consensus::encode::{self, Encodable, Decodable};
use crate::internal_macros::user_enum;
/// Version of the protocol as appearing in network message headers
/// 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
pub const PROTOCOL_VERSION: u32 = 70001;
user_enum! {
/// The cryptocurrency to act on
#[derive(Copy, PartialEq, Eq, PartialOrd, Ord, Clone, Hash, Debug)]
pub enum Network {
/// Classic Bitcoin
Bitcoin <-> "bitcoin",
/// Bitcoin's testnet
Testnet <-> "testnet",
/// Bitcoin's signet
Signet <-> "signet",
/// Bitcoin's regtest
Regtest <-> "regtest"
}
/// The cryptocurrency network to act on.
#[derive(Copy, PartialEq, Eq, PartialOrd, Ord, Clone, Hash, Debug)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(crate = "actual_serde"))]
#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
#[non_exhaustive]
pub enum Network {
/// Mainnet Bitcoin.
Bitcoin,
/// Bitcoin's testnet network.
Testnet,
/// Bitcoin's signet network.
Signet,
/// Bitcoin's regtest network.
Regtest,
}
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.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ServiceFlags(u64);