Merge rust-bitcoin/rust-bitcoin#3666: Implement serde modules for `FeeRate`
f5eb8f4747
api: Run just check-api (Tobin C. Harding)472b1d3ff3
units: Add serde regression test (Tobin C. Harding)dedae8acf2
Implement custom serde modules for FeeRate (Tobin C. Harding)d94e5f03e6
Move fee_rate.rs to module (Tobin C. Harding)c3c1f6f82d
Add missing license comment to test file (Tobin C. Harding) Pull request description: Implement and enforce explicit unit when serializing. This is as we do for `Amount` (see #3672 for similar). To test it, and as part of the 1.0 effort; add regression tests for `serde` stuff in `units`. With this applied one must use attributes to serialize `FeeRate`. ```rust #[derive(Serialize, Deserialize)] pub struct Foo { #[serde(with = "bitcoin_units::fee_rate::serde::as_sat_per_kwu")] pub fee_rate: FeeRate, } ``` ACKs for top commit: apoelstra: ACK f5eb8f4747a7cd303cad2b7f8f442bb31862c52a; successfully ran local tests; great idea! Tree-SHA512: 0968ead568b1e3142efd4c0e856192ddde0f441de84215cbb0950b60a56922f1abaf6d4ccfe243b722a6883c0a927d26bcfba979acf3ca84c4f21baba73af764
This commit is contained in:
commit
6501b0d781
|
@ -129,6 +129,7 @@ name = "bitcoin-units"
|
|||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"arbitrary",
|
||||
"bincode",
|
||||
"bitcoin-internals",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
|
|
@ -128,6 +128,7 @@ name = "bitcoin-units"
|
|||
version = "0.2.0"
|
||||
dependencies = [
|
||||
"arbitrary",
|
||||
"bincode",
|
||||
"bitcoin-internals",
|
||||
"serde",
|
||||
"serde_json",
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#[non_exhaustive] pub struct bitcoin_units::amount::MissingDenominationError
|
||||
#[non_exhaustive] pub struct bitcoin_units::amount::PossiblyConfusingDenominationError(_)
|
||||
#[non_exhaustive] pub struct bitcoin_units::amount::UnknownDenominationError(_)
|
||||
#[non_exhaustive] pub struct bitcoin_units::fee_rate::serde::OverflowError
|
||||
#[non_exhaustive] pub struct bitcoin_units::locktime::absolute::ConversionError
|
||||
#[non_exhaustive] pub struct bitcoin_units::parse::ParseIntError
|
||||
impl bitcoin_units::Amount
|
||||
|
@ -52,6 +53,7 @@ impl core::clone::Clone for bitcoin_units::block::BlockHeight
|
|||
impl core::clone::Clone for bitcoin_units::block::BlockInterval
|
||||
impl core::clone::Clone for bitcoin_units::block::TooBigForRelativeBlockHeightError
|
||||
impl core::clone::Clone for bitcoin_units::fee_rate::FeeRate
|
||||
impl core::clone::Clone for bitcoin_units::fee_rate::serde::OverflowError
|
||||
impl core::clone::Clone for bitcoin_units::locktime::absolute::ConversionError
|
||||
impl core::clone::Clone for bitcoin_units::locktime::absolute::Height
|
||||
impl core::clone::Clone for bitcoin_units::locktime::absolute::ParseHeightError
|
||||
|
@ -82,6 +84,7 @@ impl core::cmp::Eq for bitcoin_units::block::BlockHeight
|
|||
impl core::cmp::Eq for bitcoin_units::block::BlockInterval
|
||||
impl core::cmp::Eq for bitcoin_units::block::TooBigForRelativeBlockHeightError
|
||||
impl core::cmp::Eq for bitcoin_units::fee_rate::FeeRate
|
||||
impl core::cmp::Eq for bitcoin_units::fee_rate::serde::OverflowError
|
||||
impl core::cmp::Eq for bitcoin_units::locktime::absolute::ConversionError
|
||||
impl core::cmp::Eq for bitcoin_units::locktime::absolute::Height
|
||||
impl core::cmp::Eq for bitcoin_units::locktime::absolute::ParseHeightError
|
||||
|
@ -122,6 +125,7 @@ impl core::cmp::PartialEq for bitcoin_units::block::BlockHeight
|
|||
impl core::cmp::PartialEq for bitcoin_units::block::BlockInterval
|
||||
impl core::cmp::PartialEq for bitcoin_units::block::TooBigForRelativeBlockHeightError
|
||||
impl core::cmp::PartialEq for bitcoin_units::fee_rate::FeeRate
|
||||
impl core::cmp::PartialEq for bitcoin_units::fee_rate::serde::OverflowError
|
||||
impl core::cmp::PartialEq for bitcoin_units::locktime::absolute::ConversionError
|
||||
impl core::cmp::PartialEq for bitcoin_units::locktime::absolute::Height
|
||||
impl core::cmp::PartialEq for bitcoin_units::locktime::absolute::ParseHeightError
|
||||
|
@ -170,6 +174,7 @@ impl core::convert::From<bitcoin_units::weight::Weight> for u64
|
|||
impl core::convert::From<core::convert::Infallible> for bitcoin_units::amount::ParseAmountError
|
||||
impl core::convert::From<core::convert::Infallible> for bitcoin_units::amount::ParseDenominationError
|
||||
impl core::convert::From<core::convert::Infallible> for bitcoin_units::amount::ParseError
|
||||
impl core::convert::From<core::convert::Infallible> for bitcoin_units::fee_rate::serde::OverflowError
|
||||
impl core::convert::From<core::convert::Infallible> for bitcoin_units::parse::PrefixedHexError
|
||||
impl core::convert::From<core::convert::Infallible> for bitcoin_units::parse::UnprefixedHexError
|
||||
impl core::convert::From<u16> for bitcoin_units::locktime::relative::Height
|
||||
|
@ -218,6 +223,7 @@ impl core::error::Error for bitcoin_units::amount::PossiblyConfusingDenomination
|
|||
impl core::error::Error for bitcoin_units::amount::TooPreciseError
|
||||
impl core::error::Error for bitcoin_units::amount::UnknownDenominationError
|
||||
impl core::error::Error for bitcoin_units::block::TooBigForRelativeBlockHeightError
|
||||
impl core::error::Error for bitcoin_units::fee_rate::serde::OverflowError
|
||||
impl core::error::Error for bitcoin_units::locktime::absolute::ConversionError
|
||||
impl core::error::Error for bitcoin_units::locktime::absolute::ParseHeightError
|
||||
impl core::error::Error for bitcoin_units::locktime::absolute::ParseTimeError
|
||||
|
@ -244,6 +250,7 @@ impl core::fmt::Debug for bitcoin_units::block::BlockHeight
|
|||
impl core::fmt::Debug for bitcoin_units::block::BlockInterval
|
||||
impl core::fmt::Debug for bitcoin_units::block::TooBigForRelativeBlockHeightError
|
||||
impl core::fmt::Debug for bitcoin_units::fee_rate::FeeRate
|
||||
impl core::fmt::Debug for bitcoin_units::fee_rate::serde::OverflowError
|
||||
impl core::fmt::Debug for bitcoin_units::locktime::absolute::ConversionError
|
||||
impl core::fmt::Debug for bitcoin_units::locktime::absolute::Height
|
||||
impl core::fmt::Debug for bitcoin_units::locktime::absolute::ParseHeightError
|
||||
|
@ -274,6 +281,7 @@ impl core::fmt::Display for bitcoin_units::block::BlockHeight
|
|||
impl core::fmt::Display for bitcoin_units::block::BlockInterval
|
||||
impl core::fmt::Display for bitcoin_units::block::TooBigForRelativeBlockHeightError
|
||||
impl core::fmt::Display for bitcoin_units::fee_rate::FeeRate
|
||||
impl core::fmt::Display for bitcoin_units::fee_rate::serde::OverflowError
|
||||
impl core::fmt::Display for bitcoin_units::locktime::absolute::ConversionError
|
||||
impl core::fmt::Display for bitcoin_units::locktime::absolute::Height
|
||||
impl core::fmt::Display for bitcoin_units::locktime::absolute::ParseHeightError
|
||||
|
@ -333,6 +341,7 @@ impl core::marker::Freeze for bitcoin_units::block::BlockHeight
|
|||
impl core::marker::Freeze for bitcoin_units::block::BlockInterval
|
||||
impl core::marker::Freeze for bitcoin_units::block::TooBigForRelativeBlockHeightError
|
||||
impl core::marker::Freeze for bitcoin_units::fee_rate::FeeRate
|
||||
impl core::marker::Freeze for bitcoin_units::fee_rate::serde::OverflowError
|
||||
impl core::marker::Freeze for bitcoin_units::locktime::absolute::ConversionError
|
||||
impl core::marker::Freeze for bitcoin_units::locktime::absolute::Height
|
||||
impl core::marker::Freeze for bitcoin_units::locktime::absolute::ParseHeightError
|
||||
|
@ -364,6 +373,7 @@ impl core::marker::Send for bitcoin_units::block::BlockHeight
|
|||
impl core::marker::Send for bitcoin_units::block::BlockInterval
|
||||
impl core::marker::Send for bitcoin_units::block::TooBigForRelativeBlockHeightError
|
||||
impl core::marker::Send for bitcoin_units::fee_rate::FeeRate
|
||||
impl core::marker::Send for bitcoin_units::fee_rate::serde::OverflowError
|
||||
impl core::marker::Send for bitcoin_units::locktime::absolute::ConversionError
|
||||
impl core::marker::Send for bitcoin_units::locktime::absolute::Height
|
||||
impl core::marker::Send for bitcoin_units::locktime::absolute::ParseHeightError
|
||||
|
@ -394,6 +404,7 @@ impl core::marker::StructuralPartialEq for bitcoin_units::block::BlockHeight
|
|||
impl core::marker::StructuralPartialEq for bitcoin_units::block::BlockInterval
|
||||
impl core::marker::StructuralPartialEq for bitcoin_units::block::TooBigForRelativeBlockHeightError
|
||||
impl core::marker::StructuralPartialEq for bitcoin_units::fee_rate::FeeRate
|
||||
impl core::marker::StructuralPartialEq for bitcoin_units::fee_rate::serde::OverflowError
|
||||
impl core::marker::StructuralPartialEq for bitcoin_units::locktime::absolute::ConversionError
|
||||
impl core::marker::StructuralPartialEq for bitcoin_units::locktime::absolute::Height
|
||||
impl core::marker::StructuralPartialEq for bitcoin_units::locktime::absolute::ParseHeightError
|
||||
|
@ -425,6 +436,7 @@ impl core::marker::Sync for bitcoin_units::block::BlockHeight
|
|||
impl core::marker::Sync for bitcoin_units::block::BlockInterval
|
||||
impl core::marker::Sync for bitcoin_units::block::TooBigForRelativeBlockHeightError
|
||||
impl core::marker::Sync for bitcoin_units::fee_rate::FeeRate
|
||||
impl core::marker::Sync for bitcoin_units::fee_rate::serde::OverflowError
|
||||
impl core::marker::Sync for bitcoin_units::locktime::absolute::ConversionError
|
||||
impl core::marker::Sync for bitcoin_units::locktime::absolute::Height
|
||||
impl core::marker::Sync for bitcoin_units::locktime::absolute::ParseHeightError
|
||||
|
@ -456,6 +468,7 @@ impl core::marker::Unpin for bitcoin_units::block::BlockHeight
|
|||
impl core::marker::Unpin for bitcoin_units::block::BlockInterval
|
||||
impl core::marker::Unpin for bitcoin_units::block::TooBigForRelativeBlockHeightError
|
||||
impl core::marker::Unpin for bitcoin_units::fee_rate::FeeRate
|
||||
impl core::marker::Unpin for bitcoin_units::fee_rate::serde::OverflowError
|
||||
impl core::marker::Unpin for bitcoin_units::locktime::absolute::ConversionError
|
||||
impl core::marker::Unpin for bitcoin_units::locktime::absolute::Height
|
||||
impl core::marker::Unpin for bitcoin_units::locktime::absolute::ParseHeightError
|
||||
|
@ -556,6 +569,7 @@ impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::block::BlockHeig
|
|||
impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::block::BlockInterval
|
||||
impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::block::TooBigForRelativeBlockHeightError
|
||||
impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::fee_rate::FeeRate
|
||||
impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::fee_rate::serde::OverflowError
|
||||
impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::absolute::ConversionError
|
||||
impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::absolute::Height
|
||||
impl core::panic::unwind_safe::RefUnwindSafe for bitcoin_units::locktime::absolute::ParseHeightError
|
||||
|
@ -587,6 +601,7 @@ impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::block::BlockHeight
|
|||
impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::block::BlockInterval
|
||||
impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::block::TooBigForRelativeBlockHeightError
|
||||
impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::fee_rate::FeeRate
|
||||
impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::fee_rate::serde::OverflowError
|
||||
impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::absolute::ConversionError
|
||||
impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::absolute::Height
|
||||
impl core::panic::unwind_safe::UnwindSafe for bitcoin_units::locktime::absolute::ParseHeightError
|
||||
|
@ -612,7 +627,6 @@ impl core::str::traits::FromStr for bitcoin_units::locktime::relative::Time
|
|||
impl core::str::traits::FromStr for bitcoin_units::weight::Weight
|
||||
impl serde::ser::Serialize for bitcoin_units::block::BlockHeight
|
||||
impl serde::ser::Serialize for bitcoin_units::block::BlockInterval
|
||||
impl serde::ser::Serialize for bitcoin_units::fee_rate::FeeRate
|
||||
impl serde::ser::Serialize for bitcoin_units::locktime::absolute::Height
|
||||
impl serde::ser::Serialize for bitcoin_units::locktime::absolute::Time
|
||||
impl serde::ser::Serialize for bitcoin_units::locktime::relative::Height
|
||||
|
@ -644,7 +658,6 @@ impl<'a> core::ops::arith::Sub<&'a bitcoin_units::fee_rate::FeeRate> for &bitcoi
|
|||
impl<'a> core::ops::arith::Sub<&'a bitcoin_units::weight::Weight> for &bitcoin_units::weight::Weight
|
||||
impl<'de> serde::de::Deserialize<'de> for bitcoin_units::block::BlockHeight
|
||||
impl<'de> serde::de::Deserialize<'de> for bitcoin_units::block::BlockInterval
|
||||
impl<'de> serde::de::Deserialize<'de> for bitcoin_units::fee_rate::FeeRate
|
||||
impl<'de> serde::de::Deserialize<'de> for bitcoin_units::locktime::absolute::Height
|
||||
impl<'de> serde::de::Deserialize<'de> for bitcoin_units::locktime::absolute::Time
|
||||
impl<'de> serde::de::Deserialize<'de> for bitcoin_units::locktime::relative::Height
|
||||
|
@ -1034,7 +1047,6 @@ pub fn bitcoin_units::fee_rate::FeeRate::add_assign(&mut self, rhs: bitcoin_unit
|
|||
pub fn bitcoin_units::fee_rate::FeeRate::arbitrary(u: &mut arbitrary::unstructured::Unstructured<'a>) -> arbitrary::error::Result<Self>
|
||||
pub fn bitcoin_units::fee_rate::FeeRate::clone(&self) -> bitcoin_units::fee_rate::FeeRate
|
||||
pub fn bitcoin_units::fee_rate::FeeRate::cmp(&self, other: &bitcoin_units::fee_rate::FeeRate) -> core::cmp::Ordering
|
||||
pub fn bitcoin_units::fee_rate::FeeRate::deserialize<__D>(__deserializer: __D) -> core::result::Result<Self, <__D as serde::de::Deserializer>::Error> where __D: serde::de::Deserializer<'de>
|
||||
pub fn bitcoin_units::fee_rate::FeeRate::eq(&self, other: &bitcoin_units::fee_rate::FeeRate) -> bool
|
||||
pub fn bitcoin_units::fee_rate::FeeRate::fee_vb(self, vb: u64) -> core::option::Option<bitcoin_units::Amount>
|
||||
pub fn bitcoin_units::fee_rate::FeeRate::fee_wu(self, weight: bitcoin_units::weight::Weight) -> core::option::Option<bitcoin_units::Amount>
|
||||
|
@ -1044,7 +1056,6 @@ pub fn bitcoin_units::fee_rate::FeeRate::from_str(s: &str) -> core::result::Resu
|
|||
pub fn bitcoin_units::fee_rate::FeeRate::hash<__H: core::hash::Hasher>(&self, state: &mut __H)
|
||||
pub fn bitcoin_units::fee_rate::FeeRate::mul(self, rhs: bitcoin_units::weight::Weight) -> Self::Output
|
||||
pub fn bitcoin_units::fee_rate::FeeRate::partial_cmp(&self, other: &bitcoin_units::fee_rate::FeeRate) -> core::option::Option<core::cmp::Ordering>
|
||||
pub fn bitcoin_units::fee_rate::FeeRate::serialize<__S>(&self, __serializer: __S) -> core::result::Result<<__S as serde::ser::Serializer>::Ok, <__S as serde::ser::Serializer>::Error> where __S: serde::ser::Serializer
|
||||
pub fn bitcoin_units::fee_rate::FeeRate::sub(self, rhs: &bitcoin_units::fee_rate::FeeRate) -> Self::Output
|
||||
pub fn bitcoin_units::fee_rate::FeeRate::sub(self, rhs: bitcoin_units::fee_rate::FeeRate) -> Self::Output
|
||||
pub fn bitcoin_units::fee_rate::FeeRate::sub_assign(&mut self, rhs: &bitcoin_units::fee_rate::FeeRate)
|
||||
|
@ -1054,6 +1065,22 @@ pub fn bitcoin_units::fee_rate::FeeRate::sum<I>(iter: I) -> Self where I: core::
|
|||
pub fn bitcoin_units::fee_rate::FeeRate::try_from(s: &str) -> core::result::Result<Self, Self::Error>
|
||||
pub fn bitcoin_units::fee_rate::FeeRate::try_from(s: alloc::boxed::Box<str>) -> core::result::Result<Self, Self::Error>
|
||||
pub fn bitcoin_units::fee_rate::FeeRate::try_from(s: alloc::string::String) -> core::result::Result<Self, Self::Error>
|
||||
pub fn bitcoin_units::fee_rate::serde::OverflowError::clone(&self) -> bitcoin_units::fee_rate::serde::OverflowError
|
||||
pub fn bitcoin_units::fee_rate::serde::OverflowError::eq(&self, other: &bitcoin_units::fee_rate::serde::OverflowError) -> bool
|
||||
pub fn bitcoin_units::fee_rate::serde::OverflowError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
|
||||
pub fn bitcoin_units::fee_rate::serde::OverflowError::from(never: core::convert::Infallible) -> Self
|
||||
pub fn bitcoin_units::fee_rate::serde::as_sat_per_kwu::deserialize<'d, D: serde::de::Deserializer<'d>>(d: D) -> core::result::Result<bitcoin_units::fee_rate::FeeRate, <D as serde::de::Deserializer>::Error>
|
||||
pub fn bitcoin_units::fee_rate::serde::as_sat_per_kwu::opt::deserialize<'d, D: serde::de::Deserializer<'d>>(d: D) -> core::result::Result<core::option::Option<bitcoin_units::fee_rate::FeeRate>, <D as serde::de::Deserializer>::Error>
|
||||
pub fn bitcoin_units::fee_rate::serde::as_sat_per_kwu::opt::serialize<S: serde::ser::Serializer>(f: &core::option::Option<bitcoin_units::fee_rate::FeeRate>, s: S) -> core::result::Result<<S as serde::ser::Serializer>::Ok, <S as serde::ser::Serializer>::Error>
|
||||
pub fn bitcoin_units::fee_rate::serde::as_sat_per_kwu::serialize<S: serde::ser::Serializer>(f: &bitcoin_units::fee_rate::FeeRate, s: S) -> core::result::Result<<S as serde::ser::Serializer>::Ok, <S as serde::ser::Serializer>::Error>
|
||||
pub fn bitcoin_units::fee_rate::serde::as_sat_per_vb_ceil::deserialize<'d, D: serde::de::Deserializer<'d>>(d: D) -> core::result::Result<bitcoin_units::fee_rate::FeeRate, <D as serde::de::Deserializer>::Error>
|
||||
pub fn bitcoin_units::fee_rate::serde::as_sat_per_vb_ceil::opt::deserialize<'d, D: serde::de::Deserializer<'d>>(d: D) -> core::result::Result<core::option::Option<bitcoin_units::fee_rate::FeeRate>, <D as serde::de::Deserializer>::Error>
|
||||
pub fn bitcoin_units::fee_rate::serde::as_sat_per_vb_ceil::opt::serialize<S: serde::ser::Serializer>(f: &core::option::Option<bitcoin_units::fee_rate::FeeRate>, s: S) -> core::result::Result<<S as serde::ser::Serializer>::Ok, <S as serde::ser::Serializer>::Error>
|
||||
pub fn bitcoin_units::fee_rate::serde::as_sat_per_vb_ceil::serialize<S: serde::ser::Serializer>(f: &bitcoin_units::fee_rate::FeeRate, s: S) -> core::result::Result<<S as serde::ser::Serializer>::Ok, <S as serde::ser::Serializer>::Error>
|
||||
pub fn bitcoin_units::fee_rate::serde::as_sat_per_vb_floor::deserialize<'d, D: serde::de::Deserializer<'d>>(d: D) -> core::result::Result<bitcoin_units::fee_rate::FeeRate, <D as serde::de::Deserializer>::Error>
|
||||
pub fn bitcoin_units::fee_rate::serde::as_sat_per_vb_floor::opt::deserialize<'d, D: serde::de::Deserializer<'d>>(d: D) -> core::result::Result<core::option::Option<bitcoin_units::fee_rate::FeeRate>, <D as serde::de::Deserializer>::Error>
|
||||
pub fn bitcoin_units::fee_rate::serde::as_sat_per_vb_floor::opt::serialize<S: serde::ser::Serializer>(f: &core::option::Option<bitcoin_units::fee_rate::FeeRate>, s: S) -> core::result::Result<<S as serde::ser::Serializer>::Ok, <S as serde::ser::Serializer>::Error>
|
||||
pub fn bitcoin_units::fee_rate::serde::as_sat_per_vb_floor::serialize<S: serde::ser::Serializer>(f: &bitcoin_units::fee_rate::FeeRate, s: S) -> core::result::Result<<S as serde::ser::Serializer>::Ok, <S as serde::ser::Serializer>::Error>
|
||||
pub fn bitcoin_units::locktime::absolute::ConversionError::clone(&self) -> bitcoin_units::locktime::absolute::ConversionError
|
||||
pub fn bitcoin_units::locktime::absolute::ConversionError::eq(&self, other: &bitcoin_units::locktime::absolute::ConversionError) -> bool
|
||||
pub fn bitcoin_units::locktime::absolute::ConversionError::fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result
|
||||
|
@ -1208,6 +1235,13 @@ pub mod bitcoin_units::amount::serde::as_str
|
|||
pub mod bitcoin_units::amount::serde::as_str::opt
|
||||
pub mod bitcoin_units::block
|
||||
pub mod bitcoin_units::fee_rate
|
||||
pub mod bitcoin_units::fee_rate::serde
|
||||
pub mod bitcoin_units::fee_rate::serde::as_sat_per_kwu
|
||||
pub mod bitcoin_units::fee_rate::serde::as_sat_per_kwu::opt
|
||||
pub mod bitcoin_units::fee_rate::serde::as_sat_per_vb_ceil
|
||||
pub mod bitcoin_units::fee_rate::serde::as_sat_per_vb_ceil::opt
|
||||
pub mod bitcoin_units::fee_rate::serde::as_sat_per_vb_floor
|
||||
pub mod bitcoin_units::fee_rate::serde::as_sat_per_vb_floor::opt
|
||||
pub mod bitcoin_units::locktime
|
||||
pub mod bitcoin_units::locktime::absolute
|
||||
pub mod bitcoin_units::locktime::relative
|
||||
|
|
|
@ -25,6 +25,7 @@ arbitrary = { version = "1.4", optional = true }
|
|||
|
||||
[dev-dependencies]
|
||||
internals = { package = "bitcoin-internals", version = "0.4.0", features = ["test-serde"] }
|
||||
bincode = "1.3.1"
|
||||
serde_test = "1.0"
|
||||
serde_json = "1.0"
|
||||
|
||||
|
|
|
@ -2,12 +2,13 @@
|
|||
|
||||
//! Implements `FeeRate` and assoctiated features.
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
pub mod serde;
|
||||
|
||||
use core::{fmt, ops};
|
||||
|
||||
#[cfg(feature = "arbitrary")]
|
||||
use arbitrary::{Arbitrary, Unstructured};
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::amount::Amount;
|
||||
use crate::weight::Weight;
|
||||
|
@ -17,8 +18,6 @@ use crate::weight::Weight;
|
|||
/// This is an integer newtype representing fee rate in `sat/kwu`. It provides protection against mixing
|
||||
/// up the types as well as basic formatting features.
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
#[cfg_attr(feature = "serde", serde(transparent))]
|
||||
pub struct FeeRate(u64);
|
||||
|
||||
impl FeeRate {
|
|
@ -0,0 +1,255 @@
|
|||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// Module implements standardized serde-specific trait methods.
|
||||
#![allow(missing_docs)]
|
||||
#![allow(clippy::trivially_copy_pass_by_ref)]
|
||||
|
||||
//! This module adds serde serialization and deserialization support for amounts.
|
||||
//!
|
||||
//! Since there is not a default way to serialize and deserialize Amounts, multiple
|
||||
//! ways are supported and it's up to the user to decide which serialiation to use.
|
||||
//!
|
||||
//! The provided modules can be used as follows:
|
||||
//!
|
||||
//! ```
|
||||
//! use serde::{Serialize, Deserialize};
|
||||
//! use bitcoin_units::FeeRate;
|
||||
//!
|
||||
//! #[derive(Serialize, Deserialize)]
|
||||
//! pub struct Foo {
|
||||
//! #[serde(with = "bitcoin_units::fee_rate::serde::as_sat_per_kwu")]
|
||||
//! pub fee_rate: FeeRate,
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
use core::fmt;
|
||||
|
||||
pub mod as_sat_per_kwu {
|
||||
//! Serialize and deserialize [`FeeRate`] denominated in satoshis per 1000 weight units.
|
||||
//!
|
||||
//! Use with `#[serde(with = "fee_rate::serde::as_sat_per_kwu")]`.
|
||||
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
use crate::FeeRate;
|
||||
|
||||
pub fn serialize<S: Serializer>(f: &FeeRate, s: S) -> Result<S::Ok, S::Error> {
|
||||
u64::serialize(&f.to_sat_per_kwu(), s)
|
||||
}
|
||||
|
||||
pub fn deserialize<'d, D: Deserializer<'d>>(d: D) -> Result<FeeRate, D::Error> {
|
||||
Ok(FeeRate::from_sat_per_kwu(u64::deserialize(d)?))
|
||||
}
|
||||
|
||||
pub mod opt {
|
||||
//! Serialize and deserialize [`Option<FeeRate>`] denominated in satoshis per 1000 weight units.
|
||||
//!
|
||||
//! Use with `#[serde(with = "fee_rate::serde::as_sat_per_kwu::opt")]`.
|
||||
|
||||
use core::fmt;
|
||||
|
||||
use serde::{de, Deserialize, Deserializer, Serializer};
|
||||
|
||||
use crate::FeeRate;
|
||||
|
||||
pub fn serialize<S: Serializer>(f: &Option<FeeRate>, s: S) -> Result<S::Ok, S::Error> {
|
||||
match *f {
|
||||
Some(f) => s.serialize_some(&f.to_sat_per_kwu()),
|
||||
None => s.serialize_none(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn deserialize<'d, D: Deserializer<'d>>(d: D) -> Result<Option<FeeRate>, D::Error> {
|
||||
struct VisitOpt;
|
||||
|
||||
impl<'de> de::Visitor<'de> for VisitOpt {
|
||||
type Value = Option<FeeRate>;
|
||||
|
||||
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "An Option<FeeRate>")
|
||||
}
|
||||
|
||||
fn visit_none<E>(self) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn visit_some<D>(self, d: D) -> Result<Self::Value, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
Ok(Some(FeeRate::from_sat_per_kwu(u64::deserialize(d)?)))
|
||||
}
|
||||
}
|
||||
d.deserialize_option(VisitOpt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub mod as_sat_per_vb_floor {
|
||||
//! Serialize and deserialize [`FeeRate`] denominated in satoshis per virtual byte.
|
||||
//!
|
||||
//! When serializing use floor division to convert per kwu to per virtual byte.
|
||||
//! Use with `#[serde(with = "fee_rate::serde::as_sat_per_vb_floor")]`.
|
||||
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
use crate::fee_rate::serde::OverflowError;
|
||||
use crate::fee_rate::FeeRate;
|
||||
|
||||
pub fn serialize<S: Serializer>(f: &FeeRate, s: S) -> Result<S::Ok, S::Error> {
|
||||
u64::serialize(&f.to_sat_per_vb_floor(), s)
|
||||
}
|
||||
|
||||
// Errors on overflow.
|
||||
pub fn deserialize<'d, D: Deserializer<'d>>(d: D) -> Result<FeeRate, D::Error> {
|
||||
Ok(FeeRate::from_sat_per_vb(u64::deserialize(d)?)
|
||||
.ok_or(OverflowError)
|
||||
.map_err(serde::de::Error::custom)?)
|
||||
}
|
||||
|
||||
pub mod opt {
|
||||
//! Serialize and deserialize [`Option<FeeRate>`] denominated in satoshis per virtual byte.
|
||||
//!
|
||||
//! When serializing use floor division to convert per kwu to per virtual byte.
|
||||
//! Use with `#[serde(with = "fee_rate::serde::as_sat_per_vb_floor::opt")]`.
|
||||
|
||||
use core::fmt;
|
||||
|
||||
use serde::{de, Deserialize, Deserializer, Serializer};
|
||||
|
||||
use crate::fee_rate::serde::OverflowError;
|
||||
use crate::fee_rate::FeeRate;
|
||||
|
||||
pub fn serialize<S: Serializer>(f: &Option<FeeRate>, s: S) -> Result<S::Ok, S::Error> {
|
||||
match *f {
|
||||
Some(f) => s.serialize_some(&f.to_sat_per_vb_floor()),
|
||||
None => s.serialize_none(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn deserialize<'d, D: Deserializer<'d>>(d: D) -> Result<Option<FeeRate>, D::Error> {
|
||||
struct VisitOpt;
|
||||
|
||||
impl<'de> de::Visitor<'de> for VisitOpt {
|
||||
type Value = Option<FeeRate>;
|
||||
|
||||
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "An Option<FeeRate>")
|
||||
}
|
||||
|
||||
fn visit_none<E>(self) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn visit_some<D>(self, d: D) -> Result<Self::Value, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
Ok(Some(
|
||||
FeeRate::from_sat_per_vb(u64::deserialize(d)?)
|
||||
.ok_or(OverflowError)
|
||||
.map_err(serde::de::Error::custom)?,
|
||||
))
|
||||
}
|
||||
}
|
||||
d.deserialize_option(VisitOpt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub mod as_sat_per_vb_ceil {
|
||||
//! Serialize and deserialize [`FeeRate`] denominated in satoshis per virtual byte.
|
||||
//!
|
||||
//! When serializing use ceil division to convert per kwu to per virtual byte.
|
||||
//! Use with `#[serde(with = "fee_rate::serde::as_sat_per_vb")]`.
|
||||
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
|
||||
use crate::fee_rate::serde::OverflowError;
|
||||
use crate::fee_rate::FeeRate;
|
||||
|
||||
pub fn serialize<S: Serializer>(f: &FeeRate, s: S) -> Result<S::Ok, S::Error> {
|
||||
u64::serialize(&f.to_sat_per_vb_ceil(), s)
|
||||
}
|
||||
|
||||
// Errors on overflow.
|
||||
pub fn deserialize<'d, D: Deserializer<'d>>(d: D) -> Result<FeeRate, D::Error> {
|
||||
Ok(FeeRate::from_sat_per_vb(u64::deserialize(d)?)
|
||||
.ok_or(OverflowError)
|
||||
.map_err(serde::de::Error::custom)?)
|
||||
}
|
||||
|
||||
pub mod opt {
|
||||
//! Serialize and deserialize [`Option<FeeRate>`] denominated in satoshis per virtual byte.
|
||||
//!
|
||||
//! When serializing use ceil division to convert per kwu to per virtual byte.
|
||||
//! Use with `#[serde(with = "fee_rate::serde::as_sat_per_vb_ceil::opt")]`.
|
||||
|
||||
use core::fmt;
|
||||
|
||||
use serde::{de, Deserialize, Deserializer, Serializer};
|
||||
|
||||
use crate::fee_rate::serde::OverflowError;
|
||||
use crate::fee_rate::FeeRate;
|
||||
|
||||
pub fn serialize<S: Serializer>(f: &Option<FeeRate>, s: S) -> Result<S::Ok, S::Error> {
|
||||
match *f {
|
||||
Some(f) => s.serialize_some(&f.to_sat_per_vb_ceil()),
|
||||
None => s.serialize_none(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn deserialize<'d, D: Deserializer<'d>>(d: D) -> Result<Option<FeeRate>, D::Error> {
|
||||
struct VisitOpt;
|
||||
|
||||
impl<'de> de::Visitor<'de> for VisitOpt {
|
||||
type Value = Option<FeeRate>;
|
||||
|
||||
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "An Option<FeeRate>")
|
||||
}
|
||||
|
||||
fn visit_none<E>(self) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn visit_some<D>(self, d: D) -> Result<Self::Value, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
Ok(Some(
|
||||
FeeRate::from_sat_per_vb(u64::deserialize(d)?)
|
||||
.ok_or(OverflowError)
|
||||
.map_err(serde::de::Error::custom)?,
|
||||
))
|
||||
}
|
||||
}
|
||||
d.deserialize_option(VisitOpt)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Overflow occurred while deserializing fee rate per virtual byte.
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[non_exhaustive]
|
||||
pub struct OverflowError;
|
||||
|
||||
internals::impl_from_infallible!(OverflowError);
|
||||
|
||||
impl fmt::Display for OverflowError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "overflow occurred while deserializing fee rate per virtual byte")
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl std::error::Error for OverflowError {}
|
|
@ -1,3 +1,5 @@
|
|||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
//! Test the API surface of `units`.
|
||||
//!
|
||||
//! The point of these tests are to check the API surface as opposed to test the API functionality.
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,97 @@
|
|||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
//! Test the `serde` implementations for types in `units`.
|
||||
|
||||
#![cfg(feature = "alloc")]
|
||||
#![cfg(feature = "serde")]
|
||||
|
||||
use bincode::serialize;
|
||||
use bitcoin_units::locktime::{absolute, relative};
|
||||
use bitcoin_units::{Amount, BlockHeight, BlockInterval, FeeRate, SignedAmount, Weight};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// A struct that includes all the types that implement or support `serde` traits.
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
struct Serde {
|
||||
#[serde(with = "bitcoin_units::amount::serde::as_sat")]
|
||||
unsigned_as_sat: Amount,
|
||||
#[serde(with = "bitcoin_units::amount::serde::as_btc")]
|
||||
unsigned_as_btc: Amount,
|
||||
#[serde(with = "bitcoin_units::amount::serde::as_sat::opt")]
|
||||
unsigned_opt_as_sat: Option<Amount>,
|
||||
#[serde(with = "bitcoin_units::amount::serde::as_btc::opt")]
|
||||
unsigned_opt_as_btc: Option<Amount>,
|
||||
|
||||
#[serde(with = "bitcoin_units::amount::serde::as_sat")]
|
||||
signed_as_sat: SignedAmount,
|
||||
#[serde(with = "bitcoin_units::amount::serde::as_btc")]
|
||||
signed_as_btc: SignedAmount,
|
||||
#[serde(with = "bitcoin_units::amount::serde::as_sat::opt")]
|
||||
signed_opt_as_sat: Option<SignedAmount>,
|
||||
#[serde(with = "bitcoin_units::amount::serde::as_btc::opt")]
|
||||
signed_opt_as_btc: Option<SignedAmount>,
|
||||
|
||||
#[serde(with = "bitcoin_units::fee_rate::serde::as_sat_per_vb_floor")]
|
||||
vb_floor: FeeRate,
|
||||
#[serde(with = "bitcoin_units::fee_rate::serde::as_sat_per_vb_ceil")]
|
||||
vb_ceil: FeeRate,
|
||||
#[serde(with = "bitcoin_units::fee_rate::serde::as_sat_per_kwu")]
|
||||
kwu: FeeRate,
|
||||
#[serde(with = "bitcoin_units::fee_rate::serde::as_sat_per_vb_floor::opt")]
|
||||
opt_vb_floor: Option<FeeRate>,
|
||||
#[serde(with = "bitcoin_units::fee_rate::serde::as_sat_per_vb_ceil::opt")]
|
||||
opt_vb_ceil: Option<FeeRate>,
|
||||
#[serde(with = "bitcoin_units::fee_rate::serde::as_sat_per_kwu::opt")]
|
||||
opt_kwu: Option<FeeRate>,
|
||||
|
||||
a: BlockHeight,
|
||||
b: BlockInterval,
|
||||
c: absolute::Height,
|
||||
d: absolute::Time,
|
||||
e: relative::Height,
|
||||
f: relative::Time,
|
||||
g: Weight,
|
||||
}
|
||||
|
||||
impl Serde {
|
||||
/// Constructs an arbitrary instance.
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
unsigned_as_sat: Amount::MAX,
|
||||
unsigned_as_btc: Amount::MAX,
|
||||
|
||||
unsigned_opt_as_sat: Some(Amount::MAX),
|
||||
unsigned_opt_as_btc: Some(Amount::MAX),
|
||||
|
||||
signed_as_sat: SignedAmount::MAX,
|
||||
signed_as_btc: SignedAmount::MAX,
|
||||
|
||||
signed_opt_as_sat: Some(SignedAmount::MAX),
|
||||
signed_opt_as_btc: Some(SignedAmount::MAX),
|
||||
|
||||
vb_floor: FeeRate::BROADCAST_MIN,
|
||||
vb_ceil: FeeRate::BROADCAST_MIN,
|
||||
kwu: FeeRate::BROADCAST_MIN,
|
||||
|
||||
opt_vb_floor: Some(FeeRate::BROADCAST_MIN),
|
||||
opt_vb_ceil: Some(FeeRate::BROADCAST_MIN),
|
||||
opt_kwu: Some(FeeRate::BROADCAST_MIN),
|
||||
|
||||
a: BlockHeight::MAX,
|
||||
b: BlockInterval::MAX,
|
||||
c: absolute::Height::MAX,
|
||||
d: absolute::Time::MAX,
|
||||
e: relative::Height::MAX,
|
||||
f: relative::Time::MAX,
|
||||
g: Weight::MAX,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn serde_regression() {
|
||||
let t = Serde::new();
|
||||
let got = serialize(&t).unwrap();
|
||||
let want = include_bytes!("data/serde_bincode");
|
||||
assert_eq!(got, want);
|
||||
}
|
Loading…
Reference in New Issue