bitcoin_units/locktime/
relative.rs1use core::fmt;
6
7#[cfg(feature = "arbitrary")]
8use arbitrary::{Arbitrary, Unstructured};
9#[cfg(feature = "serde")]
10use serde::{Deserialize, Serialize};
11
12#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
14#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
15pub struct Height(u16);
16
17impl Height {
18 pub const ZERO: Self = Height(0);
20
21 pub const MIN: Self = Self::ZERO;
23
24 pub const MAX: Self = Height(u16::MAX);
26
27 #[inline]
29 pub const fn from_height(blocks: u16) -> Self { Height(blocks) }
30
31 #[inline]
33 pub fn value(self) -> u16 { self.0 }
34
35 #[inline]
38 pub fn to_consensus_u32(&self) -> u32 { self.0.into() }
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 let interval = (seconds + 511) / 512;
102 if interval <= u16::MAX as u32 { Ok(Time::from_512_second_intervals(interval as u16)) } else {
105 Err(TimeOverflowError { seconds })
106 }
107 }
108
109 #[inline]
111 pub fn value(self) -> u16 { self.0 }
112
113 #[inline]
116 pub fn to_consensus_u32(&self) -> u32 { (1u32 << 22) | u32::from(self.0) }
117}
118
119crate::impl_parse_str_from_int_infallible!(Time, u16, from_512_second_intervals);
120
121impl fmt::Display for Time {
122 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) }
123}
124
125#[derive(Debug, Clone, PartialEq, Eq)]
127pub struct TimeOverflowError {
128 pub(crate) seconds: u32,
131}
132
133impl TimeOverflowError {
134 pub fn new(seconds: u32) -> Self {
140 assert!(u16::try_from((seconds + 511) / 512).is_err());
141 Self { seconds }
142 }
143}
144
145impl fmt::Display for TimeOverflowError {
146 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
147 write!(
148 f,
149 "{} seconds is too large to be encoded to a 16 bit 512 second interval",
150 self.seconds
151 )
152 }
153}
154
155#[cfg(feature = "std")]
156impl std::error::Error for TimeOverflowError {}
157
158#[cfg(feature = "arbitrary")]
159impl<'a> Arbitrary<'a> for Height {
160 fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
161 let choice = u.int_in_range(0..=2)?;
162
163 match choice {
164 0 => Ok(Height::MIN),
165 1 => Ok(Height::MAX),
166 _ => Ok(Height::from_height(u16::arbitrary(u)?)),
167 }
168 }
169}
170
171#[cfg(feature = "arbitrary")]
172impl<'a> Arbitrary<'a> for Time {
173 fn arbitrary(u: &mut Unstructured<'a>) -> arbitrary::Result<Self> {
174 let choice = u.int_in_range(0..=2)?;
175
176 match choice {
177 0 => Ok(Time::MIN),
178 1 => Ok(Time::MAX),
179 _ => Ok(Time::from_512_second_intervals(u16::arbitrary(u)?)),
180 }
181 }
182}