1use std::{num::ParseIntError, str::ParseBoolError, sync::Arc};
4
5use num_bigint::{BigInt, ParseBigIntError, TryFromBigIntError};
6use thiserror::Error;
7
8#[derive(Error, Debug)]
12pub enum Error {
13 #[error("Failure while parsing field element")]
15 FieldParsingError,
16 #[error("Not enough constants")]
18 NotEnoughConstants,
19 #[error("IO cell iterator was exhausted")]
21 NotEnoughIOCells,
22 #[error("Parse failure")]
24 IntParse(#[from] ParseIntError),
25 #[error("Parse failure")]
27 BoolParse(#[from] ParseBoolError),
28 #[error("Parse failure")]
30 BigUintParse(#[from] ParseBigIntError),
31 #[error("Synthesis error")]
33 Plonk(Arc<dyn std::error::Error>),
34 #[error("Error")]
36 StrError(&'static str),
37 #[error(transparent)]
48 IntCast(#[from] std::num::TryFromIntError),
49 #[error(transparent)]
51 BigIntCast(#[from] TryFromBigIntError<BigInt>),
52 #[error("{header}Was expecting {expected} elements but got {actual}")]
54 UnexpectedElements {
55 header: String,
57 expected: usize,
59 actual: usize,
61 },
62}
63
64impl From<&'static str> for Error {
65 fn from(value: &'static str) -> Self {
66 Self::StrError(value)
67 }
68}
69
70unsafe impl Send for Error {}
71unsafe impl Sync for Error {}
72
73#[macro_export]
101macro_rules! expect_elements {
102 (($($tokens:tt)+) , $($fmt:tt)+) => {
104 $crate::__expect_elements_parse! { [] [$($tokens)+] format!($($fmt)+) }
105 };
106
107 ($($tokens:tt)+) => {
109 $crate::__expect_elements_parse! { [] [$($tokens)+] String::new() }
110 };
111}
112
113#[macro_export]
117#[doc(hidden)]
118macro_rules! __expect_elements_parse {
119 ([$($lhs:tt)+] [== $($rhs:tt)+] $msg:expr) => {
121 $crate::__expect_elements_finish! {
122 ($($lhs)*)
123 (==)
124 ($($rhs)*)
125 ($msg)
126 }
127 };
128
129 ([$($lhs:tt)+] [!= $($rhs:tt)+] $msg:expr) => {
131 $crate::__expect_elements_finish! {
132 ($($lhs)*)
133 (!=)
134 ($($rhs)*)
135 ($msg)
136 }
137 };
138
139 ([$($lhs:tt)+] [< $($rhs:tt)+] $msg:expr) => {
141 $crate::__expect_elements_finish! {
142 ($($lhs)*)
143 (<)
144 ($($rhs)*)
145 ($msg)
146 }
147 };
148
149 ([$($lhs:tt)+] [<= $($rhs:tt)+] $msg:expr) => {
151 $crate::__expect_elements_finish! {
152 ($($lhs)*)
153 (<=)
154 ($($rhs)*)
155 ($msg)
156 }
157 };
158
159 ([$($lhs:tt)+] [> $($rhs:tt)+] $msg:expr) => {
161 $crate::__expect_elements_finish! {
162 ($($lhs)*)
163 (>)
164 ($($rhs)*)
165 ($msg)
166 }
167 };
168
169 ([$($lhs:tt)+] [>= $($rhs:tt)+] $msg:expr) => {
171 $crate::__expect_elements_finish! {
172 ($($lhs)*)
173 (>=)
174 ($($rhs)*)
175 ($msg)
176 }
177 };
178
179 ([$($lhs:tt)*] [$next:tt $($rest:tt)*] $msg:expr) => {
181 $crate::__expect_elements_parse! { [$($lhs)* $next] [$($rest)*] $msg }
182 };
183
184 ([$($lhs:tt)*] [] $msg:expr) => {
186 compile_error!("expected a comparison expression such as `lhs == rhs`");
187 };
188}
189
190#[doc(hidden)]
194#[macro_export]
195macro_rules! __expect_elements_finish {
196 (($($lhs:tt)+) (==) ($($rhs:tt)+) ($msg:expr)) => {{
198 let lhs_val: usize = $($lhs)*;
199 let rhs_val: usize = $($rhs)*;
200 $crate::error::__expect_elements_impl($msg, lhs_val, rhs_val, lhs_val == rhs_val)?;
201 }};
202
203 (($($lhs:tt)+) (!=) ($($rhs:tt)+) ($msg:expr)) => {{
205 let lhs_val: usize = $($lhs)*;
206 let rhs_val: usize = $($rhs)*;
207 $crate::error::__expect_elements_impl($msg, lhs_val, rhs_val, lhs_val != rhs_val)?;
208 }};
209
210 (($($lhs:tt)+) (<) ($($rhs:tt)+) ($msg:expr)) => {{
212 let lhs_val: usize = $($lhs)*;
213 let rhs_val: usize = $($rhs)*;
214 $crate::error::__expect_elements_impl($msg, lhs_val, rhs_val, lhs_val < rhs_val)?;
215 }};
216
217 (($($lhs:tt)+) (<=) ($($rhs:tt)+) ($msg:expr)) => {{
219 let lhs_val: usize = $($lhs)*;
220 let rhs_val: usize = $($rhs)*;
221 $crate::error::__expect_elements_impl($msg, lhs_val, rhs_val, lhs_val <= rhs_val)?;
222 }};
223
224 (($($lhs:tt)+) (>) ($($rhs:tt)+) ($msg:expr)) => {{
226 let lhs_val: usize = $($lhs)*;
227 let rhs_val: usize = $($rhs)*;
228 $crate::error::__expect_elements_impl($msg, lhs_val, rhs_val, lhs_val > rhs_val)?;
229 }};
230
231 (($($lhs:tt)+) (>=) ($($rhs:tt)+) ($msg:expr)) => {{
233 let lhs_val: usize = $($lhs)*;
234 let rhs_val: usize = $($rhs)*;
235 $crate::error::__expect_elements_impl($msg, lhs_val, rhs_val, lhs_val >= rhs_val)?;
236 }};
237}
238
239#[doc(hidden)]
240#[inline]
241pub fn __expect_elements_impl(
242 header: String,
243 expected: usize,
244 actual: usize,
245 passed: bool,
246) -> Result<(), Error> {
247 if passed {
248 Ok(())
249 } else {
250 Err(Error::UnexpectedElements {
251 header,
252 expected,
253 actual,
254 })
255 }
256}
257
258#[cfg(test)]
259mod tests {
260 use super::*;
261 use rstest::rstest;
262
263 #[derive(Debug)]
264 enum Cmp {
265 Eq,
266 Ne,
267 Lt,
268 Le,
269 Gt,
270 Ge,
271 }
272
273 #[rstest]
274 #[case(Cmp::Eq, 1, 1)]
275 #[case(Cmp::Ne, 1, 2)]
276 #[case(Cmp::Lt, 1, 2)]
277 #[case(Cmp::Le, 1, 1)]
278 #[case(Cmp::Gt, 2, 1)]
279 #[case(Cmp::Ge, 1, 1)]
280 #[should_panic(expected = "unexpected elements error")]
281 #[case(Cmp::Eq, 1, 2)]
282 #[should_panic(expected = "unexpected elements error")]
283 #[case(Cmp::Ne, 1, 1)]
284 #[should_panic(expected = "unexpected elements error")]
285 #[case(Cmp::Lt, 1, 0)]
286 #[should_panic(expected = "unexpected elements error")]
287 #[case(Cmp::Le, 1, 0)]
288 #[should_panic(expected = "unexpected elements error")]
289 #[case(Cmp::Gt, 2, 3)]
290 #[should_panic(expected = "unexpected elements error")]
291 #[case(Cmp::Ge, 1, 3)]
292 fn expect_elements_test(#[case] cmp: Cmp, #[case] expected: usize, #[case] actual: usize) {
293 fn do_test(cmp: Cmp, expected: usize, actual: usize) -> Result<(), Error> {
294 match cmp {
295 Cmp::Eq => expect_elements!((expected == actual), "unexpected elements error"),
296 Cmp::Ne => expect_elements!((expected != actual), "unexpected elements error"),
297 Cmp::Lt => expect_elements!((expected < actual), "unexpected elements error"),
298 Cmp::Le => expect_elements!((expected <= actual), "unexpected elements error"),
299 Cmp::Gt => expect_elements!((expected > actual), "unexpected elements error"),
300 Cmp::Ge => expect_elements!((expected >= actual), "unexpected elements error"),
301 }
302 Ok(())
303 }
304 eprintln!("cmp = {cmp:?}, expected = {expected}, actual = {actual}");
305 do_test(cmp, expected, actual).unwrap();
306 }
307
308 #[rstest]
309 #[should_panic(expected = "unexpected elements error")]
310 #[case(Cmp::Eq)]
311 #[should_panic(expected = "unexpected elements error")]
312 #[case(Cmp::Ne)]
313 #[should_panic(expected = "unexpected elements error")]
314 #[case(Cmp::Lt)]
315 #[should_panic(expected = "unexpected elements error")]
316 #[case(Cmp::Le)]
317 #[should_panic(expected = "unexpected elements error")]
318 #[case(Cmp::Gt)]
319 #[should_panic(expected = "unexpected elements error")]
320 #[case(Cmp::Ge)]
321 fn expect_elements_complex_expr_rhs(#[case] cmp: Cmp) {
322 fn do_test(cmp: Cmp) -> Result<(), Error> {
323 let v = vec![1, 2, 3];
324 match cmp {
325 Cmp::Eq => expect_elements!((2 == v.len()), "unexpected elements error"),
326 Cmp::Ne => expect_elements!((3 != v.len()), "unexpected elements error"),
327 Cmp::Lt => expect_elements!((4 < v.len()), "unexpected elements error"),
328 Cmp::Le => expect_elements!((4 <= v.len()), "unexpected elements error"),
329 Cmp::Gt => expect_elements!((2 > v.len()), "unexpected elements error"),
330 Cmp::Ge => expect_elements!((2 >= v.len()), "unexpected elements error"),
331 };
332 Ok(())
333 }
334 do_test(cmp).unwrap();
335 }
336
337 #[rstest]
338 #[should_panic(expected = "unexpected elements error")]
339 #[case(Cmp::Eq)]
340 #[should_panic(expected = "unexpected elements error")]
341 #[case(Cmp::Ne)]
342 #[should_panic(expected = "unexpected elements error")]
343 #[case(Cmp::Lt)]
344 #[should_panic(expected = "unexpected elements error")]
345 #[case(Cmp::Le)]
346 #[should_panic(expected = "unexpected elements error")]
347 #[case(Cmp::Gt)]
348 #[should_panic(expected = "unexpected elements error")]
349 #[case(Cmp::Ge)]
350 fn expect_elements_complex_expr_lhs(#[case] cmp: Cmp) {
351 fn do_test(cmp: Cmp) -> Result<(), Error> {
352 let v = vec![1, 2, 3];
353 match cmp {
354 Cmp::Eq => expect_elements!((v.len() == 2), "unexpected elements error"),
355 Cmp::Ne => expect_elements!((v.len() != 3), "unexpected elements error"),
356 Cmp::Lt => expect_elements!((v.len() < 2), "unexpected elements error"),
357 Cmp::Le => expect_elements!((v.len() <= 2), "unexpected elements error"),
358 Cmp::Gt => expect_elements!((v.len() > 4), "unexpected elements error"),
359 Cmp::Ge => expect_elements!((v.len() >= 4), "unexpected elements error"),
360 };
361 Ok(())
362 }
363 do_test(cmp).unwrap();
364 }
365}