macro_rules! define_numeric_newtype {
($(#[$meta:meta])* $name:ident, $inner:ty) => {
$(#[$meta])*
#[derive(
Debug,
Default,
Clone,
Copy,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
Serialize,
Deserialize,
)]
pub struct $name($inner);
impl $name {
#[must_use]
pub const fn new(value: $inner) -> Self {
Self(value)
}
#[must_use]
pub const fn value(self) -> $inner {
self.0
}
}
impl std::fmt::Display for $name {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.fmt(f)
}
}
impl From<$inner> for $name {
fn from(value: $inner) -> Self {
Self(value)
}
}
impl From<$name> for $inner {
fn from(value: $name) -> Self {
value.0
}
}
};
}
macro_rules! define_bytes32_newtype {
($name:ident) => {
#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct $name(pub [u8; 32]);
impl $name {
#[must_use]
pub const fn new(bytes: [u8; 32]) -> Self {
Self(bytes)
}
#[must_use]
pub fn from_hex(s: &str) -> Option<Self> {
let s = $crate::wire::strip_0x(s);
let bytes = hex::decode(s).ok()?;
if bytes.len() != 32 {
return None;
}
let mut arr = [0u8; 32];
arr.copy_from_slice(&bytes);
Some(Self(arr))
}
#[must_use]
pub fn hex(&self) -> String {
hex::encode(self.0)
}
#[must_use]
pub const fn as_bytes(&self) -> &[u8; 32] {
&self.0
}
}
impl std::fmt::Display for $name {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.hex())
}
}
impl std::fmt::Debug for $name {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple(stringify!($name)).field(&self.hex()).finish()
}
}
impl serde::Serialize for $name {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_str(&self.hex())
}
}
impl<'de> serde::Deserialize<'de> for $name {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
Self::from_hex(&s).ok_or_else(|| {
serde::de::Error::custom(format!("invalid {} hex: {:?}", stringify!($name), s))
})
}
}
};
}