snarkvm_synthesizer/restrictions/helpers/
block_range.rs1use console::{
17 network::Network,
18 prelude::{Deserialize, Deserializer, EnumAccess, One, Result, Serialize, Serializer, VariantAccess, Visitor, de},
19 types::Field,
20};
21
22use core::{
23 fmt,
24 ops::{Range, RangeFrom, RangeInclusive, RangeTo},
25};
26
27#[derive(Debug, Clone, PartialEq, Eq)]
28pub enum BlockRange {
29 Range(Range<u32>),
30 RangeFrom(RangeFrom<u32>),
31 RangeTo(RangeTo<u32>),
32 RangeInclusive(RangeInclusive<u32>),
33 FullRange,
34}
35
36impl BlockRange {
37 pub fn contains(&self, height: u32) -> bool {
39 match self {
40 BlockRange::Range(range) => range.contains(&height),
41 BlockRange::RangeFrom(range) => range.contains(&height),
42 BlockRange::RangeTo(range) => range.contains(&height),
43 BlockRange::RangeInclusive(range) => range.contains(&height),
44 BlockRange::FullRange => true,
45 }
46 }
47}
48
49impl BlockRange {
50 pub fn to_fields<N: Network>(&self) -> Result<Vec<Field<N>>> {
52 match self {
53 BlockRange::Range(range) => {
54 Ok(vec![Field::from_u8(0), Field::from_u32(range.start), Field::from_u32(range.end)])
55 }
56 BlockRange::RangeFrom(range) => Ok(vec![Field::from_u8(1), Field::from_u32(range.start), -Field::one()]),
57 BlockRange::RangeTo(range) => Ok(vec![Field::from_u8(2), -Field::one(), Field::from_u32(range.end)]),
58 BlockRange::RangeInclusive(range) => {
59 Ok(vec![Field::from_u8(3), Field::from_u32(*range.start()), Field::from_u32(*range.end())])
60 }
61 BlockRange::FullRange => Ok(vec![Field::from_u8(4), -Field::one(), -Field::one()]),
62 }
63 }
64}
65
66impl Serialize for BlockRange {
67 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
68 where
69 S: Serializer,
70 {
71 match self {
72 BlockRange::Range(range) => {
73 serializer.serialize_newtype_variant("BlockRange", 0, "Range", &(range.start, range.end))
74 }
75 BlockRange::RangeFrom(range) => {
76 serializer.serialize_newtype_variant("BlockRange", 1, "RangeFrom", &range.start)
77 }
78 BlockRange::RangeTo(range) => serializer.serialize_newtype_variant("BlockRange", 2, "RangeTo", &range.end),
79 BlockRange::RangeInclusive(range) => {
80 serializer.serialize_newtype_variant("BlockRange", 3, "RangeInclusive", &(range.start(), range.end()))
81 }
82 BlockRange::FullRange => serializer.serialize_newtype_variant("BlockRange", 4, "FullRange", &()),
83 }
84 }
85}
86
87impl<'de> Deserialize<'de> for BlockRange {
88 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
89 where
90 D: Deserializer<'de>,
91 {
92 enum Field {
93 Range,
94 RangeFrom,
95 RangeTo,
96 RangeInclusive,
97 FullRange,
98 }
99
100 impl<'de> Deserialize<'de> for Field {
101 fn deserialize<D>(deserializer: D) -> Result<Field, D::Error>
102 where
103 D: Deserializer<'de>,
104 {
105 struct FieldVisitor;
106
107 impl Visitor<'_> for FieldVisitor {
108 type Value = Field;
109
110 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
111 formatter.write_str("`Range`, `RangeFrom`, `RangeTo`, `RangeInclusive`, or `FullRange`")
112 }
113
114 fn visit_str<E>(self, value: &str) -> Result<Field, E>
115 where
116 E: de::Error,
117 {
118 match value {
119 "Range" => Ok(Field::Range),
120 "RangeFrom" => Ok(Field::RangeFrom),
121 "RangeTo" => Ok(Field::RangeTo),
122 "RangeInclusive" => Ok(Field::RangeInclusive),
123 "FullRange" => Ok(Field::FullRange),
124 _ => Err(de::Error::unknown_field(value, FIELDS)),
125 }
126 }
127 }
128
129 deserializer.deserialize_identifier(FieldVisitor)
130 }
131 }
132
133 struct BlockRangeVisitor;
134
135 impl<'de> Visitor<'de> for BlockRangeVisitor {
136 type Value = BlockRange;
137
138 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
139 formatter.write_str("struct BlockRange")
140 }
141
142 fn visit_enum<A>(self, data: A) -> Result<BlockRange, A::Error>
143 where
144 A: EnumAccess<'de>,
145 {
146 let (field, variant) = data.variant()?;
147 match field {
148 Field::Range => {
149 let (start, end): (u32, u32) = variant.newtype_variant()?;
150 Ok(BlockRange::Range(start..end))
151 }
152 Field::RangeFrom => {
153 let start: u32 = variant.newtype_variant()?;
154 Ok(BlockRange::RangeFrom(RangeFrom { start }))
155 }
156 Field::RangeTo => {
157 let end: u32 = variant.newtype_variant()?;
158 Ok(BlockRange::RangeTo(RangeTo { end }))
159 }
160 Field::RangeInclusive => {
161 let (start, end): (u32, u32) = variant.newtype_variant()?;
162 Ok(BlockRange::RangeInclusive(RangeInclusive::new(start, end)))
163 }
164 Field::FullRange => {
165 variant.unit_variant()?;
166 Ok(BlockRange::FullRange)
167 }
168 }
169 }
170 }
171
172 const FIELDS: &[&str] = &["Range", "RangeFrom", "RangeTo", "RangeInclusive", "FullRange"];
173 deserializer.deserialize_enum("BlockRange", FIELDS, BlockRangeVisitor)
174 }
175}
176
177#[cfg(test)]
178mod tests {
179 use super::*;
180
181 type CurrentNetwork = console::network::MainnetV0;
182
183 #[test]
184 fn test_serialize_range() {
185 let range = BlockRange::Range(1..10);
186 let serialized = serde_json::to_string(&range).unwrap();
187 assert_eq!(serialized, r#"{"Range":[1,10]}"#);
188 }
189
190 #[test]
191 fn test_deserialize_range() {
192 let serialized = r#"{"Range":[1,10]}"#;
193 let deserialized: BlockRange = serde_json::from_str(serialized).unwrap();
194 assert_eq!(deserialized, BlockRange::Range(1..10));
195 }
196
197 #[test]
198 fn test_serialize_range_from() {
199 let range = BlockRange::RangeFrom(RangeFrom { start: 5 });
200 let serialized = serde_json::to_string(&range).unwrap();
201 assert_eq!(serialized, r#"{"RangeFrom":5}"#);
202 }
203
204 #[test]
205 fn test_deserialize_range_from() {
206 let serialized = r#"{"RangeFrom":5}"#;
207 let deserialized: BlockRange = serde_json::from_str(serialized).unwrap();
208 assert_eq!(deserialized, BlockRange::RangeFrom(RangeFrom { start: 5 }));
209 }
210
211 #[test]
212 fn test_serialize_range_to() {
213 let range = BlockRange::RangeTo(RangeTo { end: 8 });
214 let serialized = serde_json::to_string(&range).unwrap();
215 assert_eq!(serialized, r#"{"RangeTo":8}"#);
216 }
217
218 #[test]
219 fn test_deserialize_range_to() {
220 let serialized = r#"{"RangeTo":8}"#;
221 let deserialized: BlockRange = serde_json::from_str(serialized).unwrap();
222 assert_eq!(deserialized, BlockRange::RangeTo(RangeTo { end: 8 }));
223 }
224
225 #[test]
226 fn test_serialize_range_inclusive() {
227 let range = BlockRange::RangeInclusive(RangeInclusive::new(2, 9));
228 let serialized = serde_json::to_string(&range).unwrap();
229 assert_eq!(serialized, r#"{"RangeInclusive":[2,9]}"#);
230 }
231
232 #[test]
233 fn test_deserialize_range_inclusive() {
234 let serialized = r#"{"RangeInclusive":[2,9]}"#;
235 let deserialized: BlockRange = serde_json::from_str(serialized).unwrap();
236 assert_eq!(deserialized, BlockRange::RangeInclusive(RangeInclusive::new(2, 9)));
237 }
238
239 #[test]
240 fn test_serialize_full_range() {
241 let range = BlockRange::FullRange;
242 let serialized = serde_json::to_string(&range).unwrap();
243 assert_eq!(serialized, r#"{"FullRange":null}"#);
244 }
245
246 #[test]
247 fn test_deserialize_full_range() {
248 let serialized = r#"{"FullRange":null}"#;
249 let deserialized: BlockRange = serde_json::from_str(serialized).unwrap();
250 assert_eq!(deserialized, BlockRange::FullRange);
251 }
252
253 #[test]
254 fn test_deserialize_error() {
255 let serialized = r#"{"InvalidRange":[1,2]}"#;
256 let result: Result<BlockRange, _> = serde_json::from_str(serialized);
257 assert!(result.is_err());
258 }
259
260 #[test]
261 fn test_deserialize_missing_field() {
262 let serialized = r#"{}"#;
263 let result: Result<BlockRange, _> = serde_json::from_str(serialized);
264 assert!(result.is_err());
265 }
266
267 #[test]
268 fn test_contains() {
269 let range = BlockRange::Range(1..10);
270 assert!(range.contains(1));
271 assert!(range.contains(5));
272 assert!(range.contains(9));
273 assert!(!range.contains(10));
274
275 let range = BlockRange::RangeFrom(RangeFrom { start: 5 });
276 assert!(!range.contains(4));
277 assert!(range.contains(5));
278 assert!(range.contains(6));
279
280 let range = BlockRange::RangeTo(RangeTo { end: 8 });
281 assert!(range.contains(7));
282 assert!(!range.contains(8));
283 assert!(!range.contains(9));
284
285 let range = BlockRange::RangeInclusive(RangeInclusive::new(2, 9));
286 assert!(!range.contains(1));
287 assert!(range.contains(2));
288 assert!(range.contains(9));
289 assert!(!range.contains(10));
290
291 let range = BlockRange::FullRange;
292 assert!(range.contains(0));
293 assert!(range.contains(1));
294 assert!(range.contains(1000));
295 }
296
297 #[test]
298 fn test_to_fields() {
299 let range = BlockRange::Range(1..10);
300 let fields = range.to_fields::<CurrentNetwork>().unwrap();
301 assert_eq!(fields, vec![Field::from_u8(0), Field::from_u32(1), Field::from_u32(10)]);
302
303 let range = BlockRange::RangeFrom(RangeFrom { start: 5 });
304 let fields = range.to_fields::<CurrentNetwork>().unwrap();
305 assert_eq!(fields, vec![Field::from_u8(1), Field::from_u32(5), -Field::one()]);
306
307 let range = BlockRange::RangeTo(RangeTo { end: 8 });
308 let fields = range.to_fields::<CurrentNetwork>().unwrap();
309 assert_eq!(fields, vec![Field::from_u8(2), -Field::one(), Field::from_u32(8)]);
310
311 let range = BlockRange::RangeInclusive(RangeInclusive::new(2, 9));
312 let fields = range.to_fields::<CurrentNetwork>().unwrap();
313 assert_eq!(fields, vec![Field::from_u8(3), Field::from_u32(2), Field::from_u32(9)]);
314
315 let range = BlockRange::FullRange;
316 let fields = range.to_fields::<CurrentNetwork>().unwrap();
317 assert_eq!(fields, vec![Field::from_u8(4), -Field::one(), -Field::one()]);
318 }
319}