paramodel_elements/error.rs
1// Copyright (c) Jonathan Shook
2// SPDX-License-Identifier: Apache-2.0
3
4//! Crate-local error type for `paramodel-elements`.
5//!
6//! Per SRD-0003 D3, each paramodel crate owns a single `Error` enum
7//! and a local `Result<T>` alias. `paramodel-elements` is now the
8//! central algebra crate (after absorbing the former `paramodel-core`),
9//! so everything below ships here: name validation, domain / parameter
10//! / attribute / element / trial construction, regex compilation, and
11//! derivation evaluation.
12
13use crate::attributes::AttributeError;
14use crate::domain::DomainError;
15use crate::expression::DerivationError;
16use crate::names::NameError;
17use crate::parameter::ParameterError;
18use crate::trial::TrialError;
19
20/// Errors produced by `paramodel-elements`.
21#[derive(Debug, thiserror::Error)]
22pub enum Error {
23 /// A validated name (parameter, element, port, …) failed its
24 /// construction check.
25 #[error(transparent)]
26 Name(#[from] NameError),
27
28 /// A domain constructor or operation was rejected.
29 #[error(transparent)]
30 Domain(#[from] DomainError),
31
32 /// An attribute layer constructor or validation was rejected.
33 #[error(transparent)]
34 Attribute(#[from] AttributeError),
35
36 /// A parameter constructor or builder setter was rejected.
37 #[error(transparent)]
38 Parameter(#[from] ParameterError),
39
40 /// A derived-parameter expression failed at bind time.
41 #[error(transparent)]
42 Derivation(#[from] DerivationError),
43
44 /// A regex pattern failed to compile.
45 #[error("invalid regex: {0}")]
46 Regex(#[from] regex::Error),
47
48 /// An element-level validation or construction was rejected.
49 #[error(transparent)]
50 Element(#[from] ElementError),
51
52 /// A trial constructor (assignments, sampling strategy, ...)
53 /// rejected its inputs.
54 #[error(transparent)]
55 Trial(#[from] TrialError),
56}
57
58/// Crate-local result alias.
59pub type Result<T, E = Error> = std::result::Result<T, E>;
60
61// ---------------------------------------------------------------------------
62// ElementError.
63// ---------------------------------------------------------------------------
64
65/// Errors from `Element` construction and validation.
66#[derive(Debug, thiserror::Error)]
67pub enum ElementError {
68 /// A name-validation error bubbled up (e.g. the `type` label value
69 /// wasn't a valid `TypeId`).
70 #[error(transparent)]
71 Name(#[from] NameError),
72
73 /// An attribute-layer namespace check failed.
74 #[error(transparent)]
75 Attribute(#[from] AttributeError),
76
77 /// The element's `labels` are missing the `type` entry required
78 /// by SRD-0007 D8.
79 #[error("element is missing the required `type` label")]
80 MissingTypeLabel,
81
82 /// The element's `type` label names a type that isn't registered.
83 #[error("unknown element type '{type_id}'")]
84 UnknownElementType {
85 /// The unregistered type id.
86 type_id: String,
87 },
88
89 /// Two `Parameter`s in `Element.parameters` share a name.
90 #[error("duplicate parameter name '{name}' in element parameters")]
91 DuplicateParameterName {
92 /// The duplicated name.
93 name: String,
94 },
95
96 /// Two `Parameter`s in `Element.result_parameters` share a name.
97 #[error("duplicate parameter name '{name}' in element result_parameters")]
98 DuplicateResultParameterName {
99 /// The duplicated name.
100 name: String,
101 },
102
103 /// A configuration key references a parameter the element doesn't
104 /// declare.
105 #[error("configuration entry references unknown parameter '{name}'")]
106 UnknownConfigurationParameter {
107 /// The offending parameter name.
108 name: String,
109 },
110
111 /// A parameter name collides with a label / tag / port on the
112 /// same element.
113 #[error("parameter name '{name}' collides with an attribute or port name")]
114 ParameterNameCollidesWithAttribute {
115 /// The offending parameter name.
116 name: String,
117 },
118
119 /// `max_concurrency` is set to zero.
120 #[error("max_concurrency must be >= 1")]
121 InvalidMaxConcurrency,
122
123 /// `max_group_concurrency` exceeds `max_concurrency`.
124 #[error("max_group_concurrency ({group}) exceeds max_concurrency ({global})")]
125 GroupConcurrencyExceedsGlobal {
126 /// The group-level cap.
127 group: u32,
128 /// The global cap it must not exceed.
129 global: u32,
130 },
131
132 /// A required label (declared by the type descriptor) is absent.
133 #[error("element is missing required label '{key}' for its type")]
134 MissingRequiredLabel {
135 /// The label key.
136 key: String,
137 },
138
139 /// A forbidden label (declared by the type descriptor) is present.
140 #[error("forbidden label '{key}' is present on this element: {reason}")]
141 ForbiddenLabelPresent {
142 /// The offending label key.
143 key: String,
144 /// Descriptor-supplied explanation.
145 reason: String,
146 },
147
148 /// A `TokenExpr` was constructed from an empty string.
149 #[error("token expression must not be empty")]
150 EmptyTokenExpr,
151}