ckb_occupied_capacity_core/
units.rs

1use serde::{Deserialize, Serialize};
2
3/// CKB capacity.
4///
5/// It is encoded as the amount of `Shannons` internally.
6#[derive(
7    Debug, Clone, Copy, Default, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize,
8)]
9pub struct Capacity(u64);
10
11/// Represents the ratio `numerator / denominator`, where `numerator` and `denominator` are both
12/// unsigned 64-bit integers.
13#[derive(Clone, PartialEq, Debug, Eq, Copy, Deserialize, Serialize)]
14pub struct Ratio {
15    /// Numerator.
16    numer: u64,
17    /// Denominator.
18    denom: u64,
19}
20
21impl Ratio {
22    /// Creates a ratio numer / denom.
23    pub const fn new(numer: u64, denom: u64) -> Self {
24        Self { numer, denom }
25    }
26
27    /// The numerator in ratio numerator / denominator.
28    pub fn numer(&self) -> u64 {
29        self.numer
30    }
31
32    /// The denominator in ratio numerator / denominator.
33    pub fn denom(&self) -> u64 {
34        self.denom
35    }
36}
37
38/// Conversion into `Capacity`.
39pub trait IntoCapacity {
40    /// Converts `self` into `Capacity`.
41    fn into_capacity(self) -> Capacity;
42}
43
44impl IntoCapacity for Capacity {
45    fn into_capacity(self) -> Capacity {
46        self
47    }
48}
49
50impl IntoCapacity for u64 {
51    fn into_capacity(self) -> Capacity {
52        Capacity::shannons(self)
53    }
54}
55
56impl IntoCapacity for u32 {
57    fn into_capacity(self) -> Capacity {
58        Capacity::shannons(u64::from(self))
59    }
60}
61
62impl IntoCapacity for u16 {
63    fn into_capacity(self) -> Capacity {
64        Capacity::shannons(u64::from(self))
65    }
66}
67
68impl IntoCapacity for u8 {
69    fn into_capacity(self) -> Capacity {
70        Capacity::shannons(u64::from(self))
71    }
72}
73
74// A `Byte` contains how many `Shannons`.
75const BYTE_SHANNONS: u64 = 100_000_000;
76
77/// Numeric errors.
78#[derive(Debug, Clone, PartialEq, Eq)]
79pub enum Error {
80    /// Numeric overflow.
81    Overflow,
82}
83
84impl ::std::fmt::Display for Error {
85    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
86        write!(f, "OccupiedCapacity: overflow")
87    }
88}
89
90impl ::std::error::Error for Error {}
91
92/// Numeric operation result.
93pub type Result<T> = ::std::result::Result<T, Error>;
94
95impl Capacity {
96    /// Capacity of zero Shannons.
97    pub const fn zero() -> Self {
98        Capacity(0)
99    }
100
101    /// Capacity of one Shannon.
102    pub const fn one() -> Self {
103        Capacity(1)
104    }
105
106    /// Views the capacity as Shannons.
107    pub const fn shannons(val: u64) -> Self {
108        Capacity(val)
109    }
110
111    /// Views the capacity as CKBytes.
112    pub fn bytes(val: usize) -> Result<Self> {
113        (val as u64)
114            .checked_mul(BYTE_SHANNONS)
115            .map(Capacity::shannons)
116            .ok_or(Error::Overflow)
117    }
118
119    /// Views the capacity as Shannons.
120    pub fn as_u64(self) -> u64 {
121        self.0
122    }
123
124    /// Adds self and rhs and checks overflow error.
125    pub fn safe_add<C: IntoCapacity>(self, rhs: C) -> Result<Self> {
126        self.0
127            .checked_add(rhs.into_capacity().0)
128            .map(Capacity::shannons)
129            .ok_or(Error::Overflow)
130    }
131
132    /// Subtracts self and rhs and checks overflow error.
133    pub fn safe_sub<C: IntoCapacity>(self, rhs: C) -> Result<Self> {
134        self.0
135            .checked_sub(rhs.into_capacity().0)
136            .map(Capacity::shannons)
137            .ok_or(Error::Overflow)
138    }
139
140    /// Multiplies self and rhs and checks overflow error.
141    pub fn safe_mul<C: IntoCapacity>(self, rhs: C) -> Result<Self> {
142        self.0
143            .checked_mul(rhs.into_capacity().0)
144            .map(Capacity::shannons)
145            .ok_or(Error::Overflow)
146    }
147
148    /// Multiplies self with a ratio and checks overflow error.
149    pub fn safe_mul_ratio(self, ratio: Ratio) -> Result<Self> {
150        self.0
151            .checked_mul(ratio.numer())
152            .and_then(|ret| ret.checked_div(ratio.denom()))
153            .map(Capacity::shannons)
154            .ok_or(Error::Overflow)
155    }
156}
157
158impl ::std::str::FromStr for Capacity {
159    type Err = ::std::num::ParseIntError;
160
161    fn from_str(s: &str) -> ::std::result::Result<Self, Self::Err> {
162        Ok(Capacity(s.parse::<u64>()?))
163    }
164}
165
166impl ::std::fmt::Display for Capacity {
167    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
168        self.0.fmt(f)
169    }
170}
171
172impl ::std::fmt::LowerHex for Capacity {
173    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
174        self.0.fmt(f)
175    }
176}