qubit_progress/error/configuration_error.rs
1// =============================================================================
2// Copyright (c) 2025 - 2026 Haixing Hu.
3//
4// SPDX-License-Identifier: Apache-2.0
5//
6// Licensed under the Apache License, Version 2.0.
7// =============================================================================
8//! Errors found while validating fixed progress configuration.
9// qubit-style: allow source-test-pair
10
11use std::error::Error;
12use std::fmt;
13
14/// Invalid fixed metadata supplied to a progress operation.
15#[derive(Clone, Debug, Eq, PartialEq)]
16#[non_exhaustive]
17pub enum ConfigurationError {
18 /// An operation was started without metrics.
19 NoMetrics,
20 /// A metric ID is empty or whitespace only.
21 EmptyMetricId {
22 /// Zero-based metric position in the builder.
23 index: usize,
24 },
25 /// A metric name is empty or whitespace only.
26 EmptyMetricName {
27 /// ID of the malformed metric.
28 metric_id: String,
29 },
30 /// Two configured metrics have the same ID.
31 DuplicateMetricId {
32 /// Duplicated stable metric ID.
33 metric_id: String,
34 },
35 /// An operation attribute key is empty or whitespace only.
36 EmptyAttributeKey {
37 /// Malformed attribute key.
38 key: String,
39 },
40 /// A stage ID is empty or whitespace only.
41 EmptyStageId,
42 /// A stage name is empty or whitespace only.
43 EmptyStageName,
44 /// Stage position and total were not supplied together.
45 IncompleteStagePosition,
46 /// Stage position is outside its one-based total range.
47 InvalidStagePosition {
48 /// Invalid one-based position.
49 position: u64,
50 /// Declared number of stages.
51 total: u64,
52 },
53}
54
55impl fmt::Display for ConfigurationError {
56 /// Formats a concise configuration explanation.
57 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
58 match self {
59 Self::NoMetrics => formatter
60 .write_str("a progress operation requires at least one metric"),
61 Self::EmptyMetricId { index } => {
62 write!(formatter, "metric at index {index} has an empty ID")
63 }
64 Self::EmptyMetricName { metric_id } => {
65 write!(formatter, "metric {metric_id:?} has an empty name")
66 }
67 Self::DuplicateMetricId { metric_id } => {
68 write!(formatter, "metric ID {metric_id:?} is duplicated")
69 }
70 Self::EmptyAttributeKey { key } => {
71 write!(formatter, "operation attribute key {key:?} is empty")
72 }
73 Self::EmptyStageId => formatter.write_str("stage ID is empty"),
74 Self::EmptyStageName => formatter.write_str("stage name is empty"),
75 Self::IncompleteStagePosition => formatter.write_str(
76 "stage position and total must be supplied together",
77 ),
78 Self::InvalidStagePosition { position, total } => write!(
79 formatter,
80 "stage position {position} is outside 1..={total}"
81 ),
82 }
83 }
84}
85
86impl Error for ConfigurationError {}