units: pull u32 conversions for BlockHeight/BlockInterval into macro
There is a lot of duplicated code between BlockHeight and BlockInterval. It obfuscates the differences between them: which timelock types they can be converted to/from and what their arithmetic properties are.
This commit is contained in:
parent
7ca45e861b
commit
a3228d4636
|
@ -22,46 +22,71 @@ use serde::{Deserialize, Serialize};
|
||||||
use crate::locktime;
|
use crate::locktime;
|
||||||
use crate::locktime::{absolute, relative};
|
use crate::locktime::{absolute, relative};
|
||||||
|
|
||||||
/// The block height, zero denotes the genesis block.
|
macro_rules! impl_u32_wrapper {
|
||||||
///
|
{
|
||||||
/// This type is not meant for constructing height based timelocks, this is a general purpose block
|
$(#[$($type_attrs:tt)*])*
|
||||||
/// height abstraction. For locktimes please see [`locktime::absolute::Height`].
|
$type_vis:vis struct $newtype:ident($inner_vis:vis u32);
|
||||||
///
|
} => {
|
||||||
/// This is a thin wrapper around a `u32` that may take on all values of a `u32`.
|
$(#[$($type_attrs)*])*
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
$type_vis struct $newtype($inner_vis u32);
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
|
||||||
// Public to try and make it really clear that there are no invariants.
|
|
||||||
pub struct BlockHeight(pub u32);
|
|
||||||
|
|
||||||
impl BlockHeight {
|
impl $newtype {
|
||||||
/// Block height 0, the genesis block.
|
/// Block height 0, the genesis block.
|
||||||
pub const ZERO: Self = BlockHeight(0);
|
pub const ZERO: Self = Self(0);
|
||||||
|
|
||||||
/// The minimum block height (0), the genesis block.
|
/// The minimum block height (0), the genesis block.
|
||||||
pub const MIN: Self = Self::ZERO;
|
pub const MIN: Self = Self::ZERO;
|
||||||
|
|
||||||
/// The maximum block height.
|
/// The maximum block height.
|
||||||
pub const MAX: Self = BlockHeight(u32::MAX);
|
pub const MAX: Self = Self(u32::MAX);
|
||||||
|
|
||||||
/// Constructs a new block height from a `u32`.
|
/// Constructs a new block height from a `u32`.
|
||||||
pub const fn from_u32(inner: u32) -> Self { Self(inner) }
|
pub const fn from_u32(inner: u32) -> Self { Self(inner) }
|
||||||
|
|
||||||
/// Returns block height as a `u32`.
|
/// Returns block height as a `u32`.
|
||||||
pub const fn to_u32(self) -> u32 { self.0 }
|
pub const fn to_u32(self) -> u32 { self.0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for $newtype {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
|
||||||
|
}
|
||||||
|
|
||||||
|
crate::impl_parse_str_from_int_infallible!($newtype, u32, from);
|
||||||
|
|
||||||
|
impl From<u32> for $newtype {
|
||||||
|
fn from(inner: u32) -> Self { Self::from_u32(inner) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<$newtype> for u32 {
|
||||||
|
fn from(height: $newtype) -> Self { height.to_u32() }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "arbitrary")]
|
||||||
|
impl<'a> Arbitrary<'a> for $newtype {
|
||||||
|
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
|
||||||
|
let choice = u.int_in_range(0..=2)?;
|
||||||
|
match choice {
|
||||||
|
0 => Ok(Self::ZERO),
|
||||||
|
1 => Ok(Self::MIN),
|
||||||
|
2 => Ok(Self::MAX),
|
||||||
|
_ => Ok(Self::from_u32(u32::arbitrary(u)?)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for BlockHeight {
|
impl_u32_wrapper! {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
|
/// A block height. Zero denotes the genesis block.
|
||||||
}
|
///
|
||||||
|
/// This type is not meant for constructing height based timelocks. It is a general purpose
|
||||||
crate::impl_parse_str_from_int_infallible!(BlockHeight, u32, from);
|
/// blockheight abstraction. For locktimes please see [`locktime::absolute::Height`].
|
||||||
|
///
|
||||||
impl From<u32> for BlockHeight {
|
/// This is a thin wrapper around a `u32` that may take on all values of a `u32`.
|
||||||
fn from(inner: u32) -> Self { Self::from_u32(inner) }
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
}
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
// Public to try and make it really clear that there are no invariants.
|
||||||
impl From<BlockHeight> for u32 {
|
pub struct BlockHeight(pub u32);
|
||||||
fn from(height: BlockHeight) -> Self { height.to_u32() }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<absolute::Height> for BlockHeight {
|
impl From<absolute::Height> for BlockHeight {
|
||||||
|
@ -86,47 +111,17 @@ impl TryFrom<BlockHeight> for absolute::Height {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The block interval.
|
impl_u32_wrapper! {
|
||||||
///
|
/// An unsigned block interval.
|
||||||
/// Block interval is an integer type denoting the number of blocks that has passed since some point
|
///
|
||||||
/// i.e., this type is meant for usage as a relative block measure.
|
/// Block interval is an integer type representing a difference between the heights of two blocks.
|
||||||
///
|
///
|
||||||
/// This type is not meant for constructing relative height based timelocks, this is a general
|
/// This type is not meant for constructing relative height based timelocks. It is a general
|
||||||
/// purpose block interval abstraction. For locktimes please see [`locktime::relative::Height`].
|
/// purpose block interval abstraction. For locktimes please see [`locktime::relative::Height`].
|
||||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
// Public to try and make it really clear that there are no invariants.
|
// Public to try and make it really clear that there are no invariants.
|
||||||
pub struct BlockInterval(pub u32);
|
pub struct BlockInterval(pub u32);
|
||||||
|
|
||||||
impl BlockInterval {
|
|
||||||
/// Block interval 0 i.e., the current block.
|
|
||||||
pub const ZERO: Self = BlockInterval(0);
|
|
||||||
|
|
||||||
/// The minimum block interval (0).
|
|
||||||
pub const MIN: Self = Self::ZERO;
|
|
||||||
|
|
||||||
/// The maximum block interval.
|
|
||||||
pub const MAX: Self = BlockInterval(u32::MAX);
|
|
||||||
|
|
||||||
/// Constructs a new block interval from a `u32`.
|
|
||||||
pub const fn from_u32(inner: u32) -> Self { Self(inner) }
|
|
||||||
|
|
||||||
/// Returns block interval as a `u32`.
|
|
||||||
pub const fn to_u32(self) -> u32 { self.0 }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for BlockInterval {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
|
|
||||||
}
|
|
||||||
|
|
||||||
crate::impl_parse_str_from_int_infallible!(BlockInterval, u32, from);
|
|
||||||
|
|
||||||
impl From<u32> for BlockInterval {
|
|
||||||
fn from(inner: u32) -> Self { Self::from_u32(inner) }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<BlockInterval> for u32 {
|
|
||||||
fn from(height: BlockInterval) -> Self { height.to_u32() }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<relative::HeightInterval> for BlockInterval {
|
impl From<relative::HeightInterval> for BlockInterval {
|
||||||
|
@ -244,30 +239,6 @@ impl<'a> core::iter::Sum<&'a BlockInterval> for BlockInterval {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "arbitrary")]
|
|
||||||
impl<'a> Arbitrary<'a> for BlockHeight {
|
|
||||||
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
|
|
||||||
let choice = u.int_in_range(0..=2)?;
|
|
||||||
match choice {
|
|
||||||
0 => Ok(BlockHeight::MIN),
|
|
||||||
1 => Ok(BlockHeight::MAX),
|
|
||||||
_ => Ok(BlockHeight::from_u32(u32::arbitrary(u)?)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "arbitrary")]
|
|
||||||
impl<'a> Arbitrary<'a> for BlockInterval {
|
|
||||||
fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
|
|
||||||
let choice = u.int_in_range(0..=2)?;
|
|
||||||
match choice {
|
|
||||||
0 => Ok(BlockInterval::MIN),
|
|
||||||
1 => Ok(BlockInterval::MAX),
|
|
||||||
_ => Ok(BlockInterval::from_u32(u32::arbitrary(u)?)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
Loading…
Reference in New Issue