bitcoin_units/locktime/
relative.rs1use core::fmt;
6
7#[cfg(feature = "serde")]
8use serde::{Deserialize, Serialize};
9
10#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
12#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
13pub struct Height(u16);
14
15impl Height {
16 pub const ZERO: Self = Height(0);
18
19 pub const MIN: Self = Self::ZERO;
21
22 pub const MAX: Self = Height(u16::MAX);
24
25 #[inline]
27 pub const fn from_height(blocks: u16) -> Self { Height(blocks) }
28
29 #[inline]
31 pub const fn value(self) -> u16 { self.0 }
32
33 #[inline]
36 pub const fn to_consensus_u32(&self) -> u32 {
37 self.0 as u32 }
39}
40
41impl From<u16> for Height {
42 #[inline]
43 fn from(value: u16) -> Self { Height(value) }
44}
45
46crate::impl_parse_str_from_int_infallible!(Height, u16, from);
47
48impl fmt::Display for Height {
49 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
50}
51
52#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
56#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
57pub struct Time(u16);
58
59impl Time {
60 pub const ZERO: Self = Time(0);
62
63 pub const MIN: Self = Time::ZERO;
65
66 pub const MAX: Self = Time(u16::MAX);
68
69 #[inline]
73 pub const fn from_512_second_intervals(intervals: u16) -> Self { Time(intervals) }
74
75 #[inline]
82 #[rustfmt::skip] pub const fn from_seconds_floor(seconds: u32) -> Result<Self, TimeOverflowError> {
84 let interval = seconds / 512;
85 if interval <= u16::MAX as u32 { Ok(Time::from_512_second_intervals(interval as u16)) } else {
88 Err(TimeOverflowError { seconds })
89 }
90 }
91
92 #[inline]
99 #[rustfmt::skip] pub const fn from_seconds_ceil(seconds: u32) -> Result<Self, TimeOverflowError> {
101 if seconds <= u16::MAX as u32 * 512 {
102 let interval = (seconds + 511) / 512;
103 Ok(Time::from_512_second_intervals(interval as u16)) } else {
105 Err(TimeOverflowError { seconds })
106 }
107 }
108
109 #[inline]
111 pub const fn value(self) -> u16 { self.0 }
112
113 #[inline]
116 pub const fn to_consensus_u32(&self) -> u32 {
117 (1u32 << 22) | self.0 as u32 }
119}
120
121crate::impl_parse_str_from_int_infallible!(Time, u16, from_512_second_intervals);
122
123impl fmt::Display for Time {
124 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
125}
126
127#[derive(Debug, Clone, PartialEq, Eq)]
129pub struct TimeOverflowError {
130 pub(crate) seconds: u32,
133}
134
135impl TimeOverflowError {
136 pub fn new(seconds: u32) -> Self {
142 assert!(u16::try_from((seconds + 511) / 512).is_err());
143 Self { seconds }
144 }
145}
146
147impl fmt::Display for TimeOverflowError {
148 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
149 write!(
150 f,
151 "{} seconds is too large to be encoded to a 16 bit 512 second interval",
152 self.seconds
153 )
154 }
155}
156
157#[cfg(feature = "std")]
158impl std::error::Error for TimeOverflowError {}
159
160#[cfg(test)]
161mod tests {
162 use super::*;
163
164 const MAXIMUM_ENCODABLE_SECONDS: u32 = u16::MAX as u32 * 512;
165
166 #[test]
167 fn from_seconds_ceil_success() {
168 let actual = Time::from_seconds_ceil(100).unwrap();
169 let expected = Time(1_u16);
170 assert_eq!(actual, expected);
171 }
172
173 #[test]
174 fn from_seconds_ceil_with_maximum_encodable_seconds_success() {
175 let actual = Time::from_seconds_ceil(MAXIMUM_ENCODABLE_SECONDS).unwrap();
176 let expected = Time(u16::MAX);
177 assert_eq!(actual, expected);
178 }
179
180 #[test]
181 fn from_seconds_ceil_causes_time_overflow_error() {
182 let result = Time::from_seconds_ceil(MAXIMUM_ENCODABLE_SECONDS + 1);
183 assert!(result.is_err());
184 }
185
186 #[test]
187 fn from_seconds_floor_success() {
188 let actual = Time::from_seconds_floor(100).unwrap();
189 let expected = Time(0_u16);
190 assert_eq!(actual, expected);
191 }
192
193 #[test]
194 fn from_seconds_floor_with_exact_interval() {
195 let actual = Time::from_seconds_floor(512).unwrap();
196 let expected = Time(1_u16);
197 assert_eq!(actual, expected);
198 }
199
200 #[test]
201 fn from_seconds_floor_with_maximum_encodable_seconds_success() {
202 let actual = Time::from_seconds_floor(MAXIMUM_ENCODABLE_SECONDS + 511).unwrap();
203 let expected = Time(u16::MAX);
204 assert_eq!(actual, expected);
205 }
206
207 #[test]
208 fn from_seconds_floor_causes_time_overflow_error() {
209 let result = Time::from_seconds_floor(MAXIMUM_ENCODABLE_SECONDS + 512);
210 assert!(result.is_err());
211 }
212}