qubit_batch/execute/batch_outcome_build_error.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2025 - 2026 Haixing Hu.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10use thiserror::Error;
11
12/// Error returned when constructing a batch outcome with invalid counters.
13///
14/// ```rust
15/// use qubit_batch::{
16/// BatchOutcomeBuildError,
17/// BatchOutcomeBuilder,
18/// };
19///
20/// let error = BatchOutcomeBuilder::<&'static str>::builder(1)
21/// .completed_count(2)
22/// .succeeded_count(2)
23/// .build()
24/// .expect_err("completed count should not exceed declared task count");
25///
26/// assert!(matches!(
27/// error,
28/// BatchOutcomeBuildError::CompletedCountExceeded { .. }
29/// ));
30/// ```
31#[derive(Debug, Clone, Error, PartialEq, Eq)]
32pub enum BatchOutcomeBuildError {
33 /// The completed task count is greater than the declared task count.
34 #[error(
35 "completed task count must not exceed declared task count: task_count {task_count}, completed_count {completed_count}"
36 )]
37 CompletedCountExceeded {
38 /// Declared task count.
39 task_count: usize,
40 /// Number of completed tasks.
41 completed_count: usize,
42 },
43
44 /// Adding failed and panicked task counts overflowed.
45 #[error(
46 "failed and panicked task counts must not overflow: failed_count {failed_count}, panicked_count {panicked_count}"
47 )]
48 FailureCountOverflow {
49 /// Number of tasks that returned their own error.
50 failed_count: usize,
51 /// Number of tasks that panicked.
52 panicked_count: usize,
53 },
54
55 /// Adding successful and failed task counts overflowed.
56 #[error(
57 "terminal task counts must not overflow: succeeded_count {succeeded_count}, failure_count {failure_count}"
58 )]
59 TerminalCountOverflow {
60 /// Number of successful tasks.
61 succeeded_count: usize,
62 /// Number of failed or panicked tasks.
63 failure_count: usize,
64 },
65
66 /// Completed tasks do not equal successful plus failed plus panicked tasks.
67 #[error(
68 "completed task count must equal succeeded + failed + panicked counts: completed_count {completed_count}, terminal_count {terminal_count}"
69 )]
70 TerminalCountMismatch {
71 /// Number of completed tasks.
72 completed_count: usize,
73 /// Number of successful, failed, and panicked tasks combined.
74 terminal_count: usize,
75 /// Number of successful tasks.
76 succeeded_count: usize,
77 /// Number of tasks that returned their own error.
78 failed_count: usize,
79 /// Number of tasks that panicked.
80 panicked_count: usize,
81 },
82
83 /// Detailed failure records do not match the aggregate failure count.
84 #[error(
85 "failure detail count must equal failed + panicked counts: expected {expected}, actual {actual}"
86 )]
87 FailureDetailCountMismatch {
88 /// Expected number of failure details.
89 expected: usize,
90 /// Actual number of failure details.
91 actual: usize,
92 },
93
94 /// A failure detail index is outside the declared task range.
95 #[error(
96 "failure index must be less than declared task count: index {index}, task_count {task_count}"
97 )]
98 FailureIndexOutOfRange {
99 /// Out-of-range failure index.
100 index: usize,
101 /// Declared task count.
102 task_count: usize,
103 },
104
105 /// Multiple failure details refer to the same task index.
106 #[error("failure index must be unique: index {index}")]
107 DuplicateFailureIndex {
108 /// Duplicate failure index.
109 index: usize,
110 },
111
112 /// Detailed failure variants do not match failed and panicked counters.
113 #[error(
114 "failure detail variants must match failed_count and panicked_count: expected_failed {expected_failed}, actual_failed {actual_failed}, expected_panicked {expected_panicked}, actual_panicked {actual_panicked}"
115 )]
116 FailureVariantCountMismatch {
117 /// Expected number of business failure details.
118 expected_failed: usize,
119 /// Actual number of business failure details.
120 actual_failed: usize,
121 /// Expected number of panic failure details.
122 expected_panicked: usize,
123 /// Actual number of panic failure details.
124 actual_panicked: usize,
125 },
126}