1use serde::{Deserialize, Serialize};
9
10#[derive(
14 Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Derivative, Serialize, Deserialize,
15)]
16#[cfg_attr(any(test, feature = "arbitrary"), derive(proptest_derive::Arbitrary))]
17#[derivative(Debug = "transparent")]
18pub struct Commitment(u16);
19
20impl Commitment {
21 pub fn increment(&mut self) {
23 self.0
24 .checked_add(1)
25 .expect("block index should never overflow");
26 }
27
28 pub const MAX: Self = Self(u16::MAX);
30}
31
32impl From<u16> for Commitment {
33 fn from(index: u16) -> Self {
34 Self(index)
35 }
36}
37
38impl From<Commitment> for u16 {
39 fn from(commitment: Commitment) -> Self {
40 commitment.0
41 }
42}
43
44#[derive(
48 Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Derivative, Serialize, Deserialize,
49)]
50#[derivative(Debug = "transparent")]
51#[cfg_attr(any(test, feature = "arbitrary"), derive(proptest_derive::Arbitrary))]
52pub struct Block(u16);
53
54impl From<u16> for Block {
55 fn from(index: u16) -> Self {
56 Self(index)
57 }
58}
59
60impl From<Block> for u16 {
61 fn from(block: Block) -> Self {
62 block.0
63 }
64}
65
66impl Block {
67 pub fn increment(&mut self) {
69 self.0
70 .checked_add(1)
71 .expect("block index should never overflow");
72 }
73
74 pub const MAX: Self = Self(u16::MAX);
76}
77
78#[derive(
82 Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Derivative, Serialize, Deserialize,
83)]
84#[cfg_attr(any(test, feature = "arbitrary"), derive(proptest_derive::Arbitrary))]
85#[derivative(Debug = "transparent")]
86pub struct Epoch(u16);
87
88impl From<u16> for Epoch {
89 fn from(index: u16) -> Self {
90 Self(index)
91 }
92}
93
94impl From<Epoch> for u16 {
95 fn from(epoch: Epoch) -> Self {
96 epoch.0
97 }
98}
99
100impl Epoch {
101 pub fn increment(&mut self) {
103 self.0
104 .checked_add(1)
105 .expect("block index should never overflow");
106 }
107
108 pub const MAX: Self = Self(u16::MAX);
110}
111
112pub mod within {
114 use super::*;
115
116 #[derive(
118 Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Serialize, Deserialize,
119 )]
120 #[cfg_attr(any(test, feature = "arbitrary"), derive(proptest_derive::Arbitrary))]
121 pub struct Block {
122 pub commitment: super::Commitment,
124 }
125
126 impl Block {
127 pub const MAX: Self = Self {
129 commitment: Commitment::MAX,
130 };
131 }
132
133 impl From<Block> for u16 {
134 fn from(
135 Block {
136 commitment: Commitment(item),
137 }: Block,
138 ) -> Self {
139 item
140 }
141 }
142
143 impl From<u16> for Block {
144 fn from(position: u16) -> Self {
145 Self {
146 commitment: Commitment(position),
147 }
148 }
149 }
150
151 impl From<Block> for u64 {
152 fn from(block: Block) -> Self {
153 u16::from(block) as u64
154 }
155 }
156
157 #[derive(
159 Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Serialize, Deserialize,
160 )]
161 #[cfg_attr(any(test, feature = "arbitrary"), derive(proptest_derive::Arbitrary))]
162 pub struct Epoch {
163 pub block: super::Block,
165 pub commitment: super::Commitment,
167 }
168
169 impl Epoch {
170 pub const MAX: Self = Self {
172 block: super::Block::MAX,
173 commitment: Commitment::MAX,
174 };
175 }
176
177 impl From<Epoch> for u32 {
178 fn from(
179 Epoch {
180 block: super::Block(block),
181 commitment: Commitment(item),
182 }: Epoch,
183 ) -> Self {
184 ((block as u32) << 16) | item as u32
185 }
186 }
187
188 impl From<u32> for Epoch {
189 fn from(position: u32) -> Self {
190 let block = (position >> 16) as u16;
191 let commitment = position as u16;
192 Self {
193 block: super::Block(block),
194 commitment: Commitment(commitment),
195 }
196 }
197 }
198
199 impl From<Epoch> for u64 {
200 fn from(epoch: Epoch) -> Self {
201 u32::from(epoch) as u64
202 }
203 }
204
205 #[derive(
207 Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Serialize, Deserialize,
208 )]
209 #[cfg_attr(any(test, feature = "arbitrary"), derive(proptest_derive::Arbitrary))]
210 pub struct Tree {
211 pub epoch: super::Epoch,
213 pub block: super::Block,
215 pub commitment: super::Commitment,
217 }
218
219 impl Tree {
220 pub const MAX: Self = Self {
222 epoch: super::Epoch::MAX,
223 block: super::Block::MAX,
224 commitment: Commitment::MAX,
225 };
226 }
227
228 impl From<Tree> for u64 {
229 fn from(
230 Tree {
231 epoch: super::Epoch(epoch),
232 block: super::Block(block),
233 commitment: super::Commitment(item),
234 }: Tree,
235 ) -> Self {
236 ((epoch as u64) << 32) | ((block as u64) << 16) | item as u64
237 }
238 }
239
240 impl From<u64> for Tree {
241 fn from(position: u64) -> Self {
242 let epoch = (position >> 32) as u16;
243 let block = (position >> 16) as u16;
244 let commitment = position as u16;
245 Self {
246 epoch: super::Epoch(epoch),
247 block: super::Block(block),
248 commitment: super::Commitment(commitment),
249 }
250 }
251 }
252}
253
254#[cfg(test)]
255mod test {
256 use super::*;
257 use proptest::prelude::*;
258
259 proptest! {
260 #[test]
261 fn u64_convert_eternity_inverse(e in 0u16..u16::MAX, b in 0u16..u16::MAX, c in 0u16..u16::MAX) {
262 let tree = within::Tree { epoch: e.into(), block: b.into(), commitment: c.into() };
263 let position: u64 = tree.into();
264 let back_again = position.into();
265 assert_eq!(tree, back_again);
266 }
267
268 #[test]
269 fn u32_convert_epoch_inverse(b in 0u16..u16::MAX, c in 0u16..u16::MAX) {
270 let epoch = within::Epoch { block: b.into(), commitment: c.into() };
271 let position: u32 = epoch.into();
272 let back_again = position.into();
273 assert_eq!(epoch, back_again);
274 }
275
276 #[test]
277 fn u16_convert_block_inverse(c in 0u16..u16::MAX) {
278 let block = within::Block { commitment: c.into() };
279 let position: u16 = block.into();
280 let back_again = position.into();
281 assert_eq!(block, back_again);
282 }
283 }
284}