Skip to main content

bitcoin_units/fee_rate/
serde.rs

1// SPDX-License-Identifier: CC0-1.0
2
3// Module implements standardized serde-specific trait methods.
4#![allow(missing_docs)]
5#![allow(clippy::trivially_copy_pass_by_ref)]
6#![allow(clippy::missing_errors_doc)]
7
8//! This module adds serde serialization and deserialization support for fee rates.
9//!
10//! Since there is not a default way to serialize and deserialize fee rates, multiple
11//! ways are supported and it's up to the user to decide which serialization to use.
12//!
13//! The provided modules can be used as follows:
14//!
15//! ```
16//! use serde::{Serialize, Deserialize};
17//! use bitcoin_units::{fee_rate, FeeRate};
18//!
19//! #[derive(Serialize, Deserialize)]
20//! pub struct Foo {
21//!     #[serde(with = "fee_rate::serde::as_sat_per_kwu_floor")]
22//!     pub fee_rate: FeeRate,
23//! }
24//! ```
25
26use core::convert::Infallible;
27use core::fmt;
28
29pub mod as_sat_per_kwu_floor {
30    //! Serialize and deserialize [`FeeRate`] denominated in satoshis per 1000 weight units.
31    //!
32    //! Use with `#[serde(with = "fee_rate::serde::as_sat_per_kwu_floor")]`.
33
34    use serde::{Deserialize, Deserializer, Serialize, Serializer};
35
36    use crate::{Amount, FeeRate};
37
38    #[inline]
39    pub fn serialize<S: Serializer>(f: &FeeRate, s: S) -> Result<S::Ok, S::Error> {
40        u64::serialize(&f.to_sat_per_kwu_floor(), s)
41    }
42
43    #[inline]
44    pub fn deserialize<'d, D: Deserializer<'d>>(d: D) -> Result<FeeRate, D::Error> {
45        let sat = u64::deserialize(d)?;
46        FeeRate::from_per_kwu(
47            Amount::from_sat(sat).map_err(|_| serde::de::Error::custom("amount out of range"))?,
48        )
49        .into_result()
50        .map_err(|_| serde::de::Error::custom("fee rate too big for sats/kwu"))
51    }
52
53    pub mod opt {
54        //! Serialize and deserialize [`Option<FeeRate>`] denominated in satoshis per 1000 weight units.
55        //!
56        //! Use with `#[serde(with = "fee_rate::serde::as_sat_per_kwu_floor::opt")]`.
57
58        use core::fmt;
59
60        use serde::{de, Deserializer, Serializer};
61
62        use crate::FeeRate;
63
64        #[inline]
65        #[allow(clippy::ref_option)] // API forced by serde.
66        pub fn serialize<S: Serializer>(f: &Option<FeeRate>, s: S) -> Result<S::Ok, S::Error> {
67            match *f {
68                Some(f) => s.serialize_some(&f.to_sat_per_kwu_floor()),
69                None => s.serialize_none(),
70            }
71        }
72
73        pub fn deserialize<'d, D: Deserializer<'d>>(d: D) -> Result<Option<FeeRate>, D::Error> {
74            struct VisitOpt;
75
76            impl<'de> de::Visitor<'de> for VisitOpt {
77                type Value = Option<FeeRate>;
78
79                fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
80                    write!(f, "an Option<u64>")
81                }
82
83                #[inline]
84                fn visit_none<E>(self) -> Result<Self::Value, E>
85                where
86                    E: de::Error,
87                {
88                    Ok(None)
89                }
90
91                #[inline]
92                fn visit_some<D>(self, d: D) -> Result<Self::Value, D::Error>
93                where
94                    D: Deserializer<'de>,
95                {
96                    Ok(Some(super::deserialize(d)?))
97                }
98            }
99            d.deserialize_option(VisitOpt)
100        }
101    }
102
103    #[cfg(feature = "alloc")]
104    pub mod vec {
105        //! Serialize and deserialize [`Vec<FeeRate>`] denominated in satoshis per 1000 weight units.
106        //!
107        //! Use with `#[serde(with = "fee_rate::serde::as_sat_per_kwu_floor::vec")]`.
108
109        use alloc::vec::Vec;
110        use core::fmt;
111
112        use serde::de::{self, SeqAccess};
113        use serde::{Deserialize, Deserializer, Serializer};
114
115        use crate::FeeRate;
116
117        pub fn serialize<S: Serializer>(f: &[FeeRate], s: S) -> Result<S::Ok, S::Error> {
118            s.collect_seq(f.iter().map(|rate| rate.to_sat_per_kwu_floor()))
119        }
120
121        // Errors on overflow.
122        pub fn deserialize<'d, D: Deserializer<'d>>(d: D) -> Result<Vec<FeeRate>, D::Error> {
123            struct VisitVec;
124
125            impl<'de> de::Visitor<'de> for VisitVec {
126                type Value = Vec<FeeRate>;
127
128                fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
129                    write!(f, "a sequence of u64")
130                }
131
132                fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
133                where
134                    A: SeqAccess<'de>,
135                {
136                    #[derive(Deserialize)]
137                    #[serde(transparent)]
138                    struct Wrapper(#[serde(with = "super")] FeeRate);
139
140                    let mut out = Vec::with_capacity(seq.size_hint().unwrap_or(0));
141                    while let Some(wrapped) = seq.next_element::<Wrapper>()? {
142                        out.push(wrapped.0);
143                    }
144                    Ok(out)
145                }
146            }
147
148            d.deserialize_seq(VisitVec)
149        }
150    }
151}
152
153pub mod as_sat_per_vb_floor {
154    //! Serialize and deserialize [`FeeRate`] denominated in satoshis per virtual byte.
155    //!
156    //! When serializing use floor division to convert per kwu to per virtual byte.
157    //! Use with `#[serde(with = "fee_rate::serde::as_sat_per_vb_floor")]`.
158
159    use serde::{Deserialize, Deserializer, Serialize, Serializer};
160
161    use crate::{Amount, FeeRate};
162
163    #[inline]
164    pub fn serialize<S: Serializer>(f: &FeeRate, s: S) -> Result<S::Ok, S::Error> {
165        u64::serialize(&f.to_sat_per_vb_floor(), s)
166    }
167
168    // Errors on overflow.
169    #[inline]
170    pub fn deserialize<'d, D: Deserializer<'d>>(d: D) -> Result<FeeRate, D::Error> {
171        let sat = u64::deserialize(d)?;
172        FeeRate::from_per_vb(
173            Amount::from_sat(sat).map_err(|_| serde::de::Error::custom("amount out of range"))?,
174        )
175        .into_result()
176        .map_err(|_| serde::de::Error::custom("fee rate too big for sats/vb"))
177    }
178
179    pub mod opt {
180        //! Serialize and deserialize [`Option<FeeRate>`] denominated in satoshis per virtual byte.
181        //!
182        //! When serializing use floor division to convert per kwu to per virtual byte.
183        //! Use with `#[serde(with = "fee_rate::serde::as_sat_per_vb_floor::opt")]`.
184
185        use core::fmt;
186
187        use serde::{de, Deserializer, Serializer};
188
189        use crate::fee_rate::FeeRate;
190
191        #[inline]
192        #[allow(clippy::ref_option)] // API forced by serde.
193        pub fn serialize<S: Serializer>(f: &Option<FeeRate>, s: S) -> Result<S::Ok, S::Error> {
194            match *f {
195                Some(f) => s.serialize_some(&f.to_sat_per_vb_floor()),
196                None => s.serialize_none(),
197            }
198        }
199
200        pub fn deserialize<'d, D: Deserializer<'d>>(d: D) -> Result<Option<FeeRate>, D::Error> {
201            struct VisitOpt;
202
203            impl<'de> de::Visitor<'de> for VisitOpt {
204                type Value = Option<FeeRate>;
205
206                fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
207                    write!(f, "an Option<u64>")
208                }
209
210                #[inline]
211                fn visit_none<E>(self) -> Result<Self::Value, E>
212                where
213                    E: de::Error,
214                {
215                    Ok(None)
216                }
217
218                #[inline]
219                fn visit_some<D>(self, d: D) -> Result<Self::Value, D::Error>
220                where
221                    D: Deserializer<'de>,
222                {
223                    Ok(Some(super::deserialize(d)?))
224                }
225            }
226            d.deserialize_option(VisitOpt)
227        }
228    }
229
230    #[cfg(feature = "alloc")]
231    pub mod vec {
232        //! Serialize and deserialize [`Vec<FeeRate>`] denominated in satoshis per virtual byte.
233        //!
234        //! When serializing use floor division to convert per kwu to per virtual byte.
235        //! Use with `#[serde(with = "fee_rate::serde::as_sat_per_vb_floor::vec")]`.
236
237        use alloc::vec::Vec;
238        use core::fmt;
239
240        use serde::de::{self, SeqAccess};
241        use serde::{Deserialize, Deserializer, Serializer};
242
243        use crate::FeeRate;
244
245        pub fn serialize<S: Serializer>(f: &[FeeRate], s: S) -> Result<S::Ok, S::Error> {
246            s.collect_seq(f.iter().map(|rate| rate.to_sat_per_vb_floor()))
247        }
248
249        // Errors on overflow.
250        pub fn deserialize<'d, D: Deserializer<'d>>(d: D) -> Result<Vec<FeeRate>, D::Error> {
251            struct VisitVec;
252
253            impl<'de> de::Visitor<'de> for VisitVec {
254                type Value = Vec<FeeRate>;
255
256                fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
257                    write!(f, "a sequence of u64")
258                }
259
260                fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
261                where
262                    A: SeqAccess<'de>,
263                {
264                    #[derive(Deserialize)]
265                    #[serde(transparent)]
266                    struct Wrapper(#[serde(with = "super")] FeeRate);
267
268                    let mut out = Vec::with_capacity(seq.size_hint().unwrap_or(0));
269                    while let Some(wrapped) = seq.next_element::<Wrapper>()? {
270                        out.push(wrapped.0);
271                    }
272                    Ok(out)
273                }
274            }
275
276            d.deserialize_seq(VisitVec)
277        }
278    }
279}
280
281pub mod as_sat_per_vb_ceil {
282    //! Serialize and deserialize [`FeeRate`] denominated in satoshis per virtual byte.
283    //!
284    //! When serializing use ceil division to convert per kwu to per virtual byte.
285    //! Use with `#[serde(with = "fee_rate::serde::as_sat_per_vb_ceil")]`.
286
287    use serde::{Deserialize, Deserializer, Serialize, Serializer};
288
289    use crate::{Amount, FeeRate};
290
291    #[inline]
292    pub fn serialize<S: Serializer>(f: &FeeRate, s: S) -> Result<S::Ok, S::Error> {
293        u64::serialize(&f.to_sat_per_vb_ceil(), s)
294    }
295
296    // Errors on overflow.
297    #[inline]
298    pub fn deserialize<'d, D: Deserializer<'d>>(d: D) -> Result<FeeRate, D::Error> {
299        let sat = u64::deserialize(d)?;
300        FeeRate::from_per_vb(
301            Amount::from_sat(sat).map_err(|_| serde::de::Error::custom("amount out of range"))?,
302        )
303        .into_result()
304        .map_err(|_| serde::de::Error::custom("fee rate too big for sats/vb"))
305    }
306
307    pub mod opt {
308        //! Serialize and deserialize [`Option<FeeRate>`] denominated in satoshis per virtual byte.
309        //!
310        //! When serializing use ceil division to convert per kwu to per virtual byte.
311        //! Use with `#[serde(with = "fee_rate::serde::as_sat_per_vb_ceil::opt")]`.
312
313        use core::fmt;
314
315        use serde::{de, Deserializer, Serializer};
316
317        use crate::fee_rate::FeeRate;
318
319        #[inline]
320        #[allow(clippy::ref_option)] // API forced by serde.
321        pub fn serialize<S: Serializer>(f: &Option<FeeRate>, s: S) -> Result<S::Ok, S::Error> {
322            match *f {
323                Some(f) => s.serialize_some(&f.to_sat_per_vb_ceil()),
324                None => s.serialize_none(),
325            }
326        }
327
328        pub fn deserialize<'d, D: Deserializer<'d>>(d: D) -> Result<Option<FeeRate>, D::Error> {
329            struct VisitOpt;
330
331            impl<'de> de::Visitor<'de> for VisitOpt {
332                type Value = Option<FeeRate>;
333
334                fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
335                    write!(f, "an Option<u64>")
336                }
337
338                #[inline]
339                fn visit_none<E>(self) -> Result<Self::Value, E>
340                where
341                    E: de::Error,
342                {
343                    Ok(None)
344                }
345
346                #[inline]
347                fn visit_some<D>(self, d: D) -> Result<Self::Value, D::Error>
348                where
349                    D: Deserializer<'de>,
350                {
351                    Ok(Some(super::deserialize(d)?))
352                }
353            }
354            d.deserialize_option(VisitOpt)
355        }
356    }
357
358    #[cfg(feature = "alloc")]
359    pub mod vec {
360        //! Serialize and deserialize [`Vec<FeeRate>`] denominated in satoshis per virtual byte.
361        //!
362        //! When serializing use ceil division to convert per kwu to per virtual byte.
363        //! Use with `#[serde(with = "fee_rate::serde::as_sat_per_vb_ceil::vec")]`.
364
365        use alloc::vec::Vec;
366        use core::fmt;
367
368        use serde::de::{self, SeqAccess};
369        use serde::{Deserialize, Deserializer, Serializer};
370
371        use crate::FeeRate;
372
373        pub fn serialize<S: Serializer>(f: &[FeeRate], s: S) -> Result<S::Ok, S::Error> {
374            s.collect_seq(f.iter().map(|rate| rate.to_sat_per_vb_ceil()))
375        }
376
377        // Errors on overflow.
378        pub fn deserialize<'d, D: Deserializer<'d>>(d: D) -> Result<Vec<FeeRate>, D::Error> {
379            struct VisitVec;
380
381            impl<'de> de::Visitor<'de> for VisitVec {
382                type Value = Vec<FeeRate>;
383
384                fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
385                    write!(f, "a sequence of u64")
386                }
387
388                fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
389                where
390                    A: SeqAccess<'de>,
391                {
392                    #[derive(Deserialize)]
393                    #[serde(transparent)]
394                    struct Wrapper(#[serde(with = "super")] FeeRate);
395
396                    let mut out = Vec::with_capacity(seq.size_hint().unwrap_or(0));
397                    while let Some(wrapped) = seq.next_element::<Wrapper>()? {
398                        out.push(wrapped.0);
399                    }
400                    Ok(out)
401                }
402            }
403
404            d.deserialize_seq(VisitVec)
405        }
406    }
407}
408
409/// Overflow occurred while deserializing fee rate per virtual byte.
410#[derive(Debug, Clone, PartialEq, Eq)]
411#[non_exhaustive]
412pub struct OverflowError;
413
414impl From<Infallible> for OverflowError {
415    fn from(never: Infallible) -> Self { match never {} }
416}
417
418impl fmt::Display for OverflowError {
419    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
420        write!(f, "overflow occurred while deserializing fee rate per virtual byte")
421    }
422}
423
424#[cfg(feature = "std")]
425impl std::error::Error for OverflowError {
426    #[inline]
427    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
428        let Self {} = self;
429        None
430    }
431}