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