Skip to main content

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}