1use crate::ValidationError;
2use subtle::ConstantTimeEq;
3use zeroize::Zeroize;
4
5#[derive(Clone, Copy, Eq)]
7pub struct Digest([u8; Self::LEN]);
8
9impl Digest {
10 pub const LEN: usize = 32;
12
13 #[must_use]
15 pub const fn new(bytes: [u8; Self::LEN]) -> Self {
16 Self(bytes)
17 }
18
19 #[must_use]
21 pub const fn as_bytes(&self) -> &[u8; Self::LEN] {
22 &self.0
23 }
24
25 #[must_use]
27 pub fn is_zero(&self) -> bool {
28 bool::from(self.0.ct_eq(&[0u8; Self::LEN]))
29 }
30
31 #[must_use]
35 pub fn ct_eq(&self, other: &Self) -> bool {
36 bool::from(self.0.ct_eq(&other.0))
37 }
38}
39
40impl PartialEq for Digest {
41 fn eq(&self, other: &Self) -> bool {
42 self.ct_eq(other)
43 }
44}
45
46impl core::hash::Hash for Digest {
47 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
48 core::hash::Hash::hash(&self.0, state);
49 }
50}
51
52impl core::fmt::Debug for Digest {
53 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
54 formatter.write_str("Digest(..)")
55 }
56}
57
58#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
60pub struct EventId(Digest);
61
62impl EventId {
63 pub fn new(digest: Digest) -> Result<Self, ValidationError> {
65 if digest.is_zero() {
66 Err(ValidationError::ZeroValue)
67 } else {
68 Ok(Self(digest))
69 }
70 }
71
72 #[must_use]
74 pub const fn digest(&self) -> Digest {
75 self.0
76 }
77}
78
79#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
81pub struct CapabilityRef(Digest);
82
83impl CapabilityRef {
84 pub fn new(digest: Digest) -> Result<Self, ValidationError> {
86 if digest.is_zero() {
87 Err(ValidationError::ZeroValue)
88 } else {
89 Ok(Self(digest))
90 }
91 }
92
93 #[must_use]
95 pub const fn digest(&self) -> Digest {
96 self.0
97 }
98}
99
100#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
102pub struct PolicyEpoch(Digest);
103
104impl PolicyEpoch {
105 pub fn new(digest: Digest) -> Result<Self, ValidationError> {
107 if digest.is_zero() {
108 Err(ValidationError::ZeroValue)
109 } else {
110 Ok(Self(digest))
111 }
112 }
113
114 #[must_use]
116 pub const fn digest(&self) -> Digest {
117 self.0
118 }
119}
120
121#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
123pub struct OperationSequence(u64);
124
125impl OperationSequence {
126 pub const fn new(value: u64) -> Result<Self, ValidationError> {
128 if value == 0 {
129 Err(ValidationError::ZeroValue)
130 } else {
131 Ok(Self(value))
132 }
133 }
134
135 #[must_use]
137 pub const fn get(self) -> u64 {
138 self.0
139 }
140
141 pub const fn next(self) -> Result<Self, ValidationError> {
143 match self.0.checked_add(1) {
144 Some(value) => Ok(Self(value)),
145 None => Err(ValidationError::TooLarge),
146 }
147 }
148
149 #[must_use]
151 pub const fn immediately_follows(self, previous: Self) -> bool {
152 match previous.0.checked_add(1) {
153 Some(expected) => self.0 == expected,
154 None => false,
155 }
156 }
157}
158
159#[derive(Eq)]
164pub struct Nonce([u8; Self::LEN]);
165
166impl Nonce {
167 pub const LEN: usize = 16;
169
170 pub fn new(bytes: [u8; Self::LEN]) -> Result<Self, ValidationError> {
172 if bool::from(bytes.ct_eq(&[0u8; Self::LEN])) {
173 Err(ValidationError::ZeroValue)
174 } else {
175 Ok(Self(bytes))
176 }
177 }
178
179 #[must_use]
181 pub const fn as_bytes(&self) -> &[u8; Self::LEN] {
182 &self.0
183 }
184
185 #[must_use]
187 pub fn ct_eq(&self, other: &Self) -> bool {
188 bool::from(self.0.ct_eq(&other.0))
189 }
190}
191
192impl PartialEq for Nonce {
193 fn eq(&self, other: &Self) -> bool {
194 self.ct_eq(other)
195 }
196}
197
198impl core::hash::Hash for Nonce {
199 fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
206 core::hash::Hash::hash(&self.0, state);
207 }
208}
209
210impl Drop for Nonce {
211 fn drop(&mut self) {
212 self.0.zeroize();
213 }
214}
215
216impl core::fmt::Debug for Nonce {
217 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
218 formatter.write_str("Nonce(..)")
219 }
220}