1use crate::{
2 ProfileSelection, SettingDomain, SettingId, SettingScope, SettingValue, SettingValueKind,
3};
4use animsmith_core::SourceFormatV1;
5use animsmith_core::engine_contract::EngineContractError;
6use std::fmt;
7
8#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
10pub enum SettingLocation {
11 Document,
13 ClipSelector(String),
15}
16
17impl fmt::Display for SettingLocation {
18 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
19 match self {
20 Self::Document => formatter.write_str("document settings"),
21 Self::ClipSelector(selector) => write!(formatter, "clip selector {selector:?}"),
22 }
23 }
24}
25
26#[derive(Debug, Clone, PartialEq, Eq)]
28pub enum InvalidSettingReason {
29 WrongDomain {
31 expected: SettingDomain,
33 found: SettingValueKind,
35 },
36 EmptyPath,
38 PathTooLong {
40 bytes: usize,
42 limit: usize,
44 },
45 AbsolutePath,
47 EmptyPathSegment,
49 DotPathSegment,
51 ControlCharacter,
53}
54
55#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
57#[non_exhaustive]
58pub enum ResolutionError {
59 #[error("engine settings were declared without an engine profile selection")]
61 SettingsWithoutSelection,
62 #[error("unknown engine profile selection {0:?}")]
64 UnknownProfile(ProfileSelection),
65 #[error("unknown engine setting {key:?} in {location}")]
67 UnknownSetting {
68 key: String,
70 location: SettingLocation,
72 },
73 #[error(
75 "engine setting {setting:?} has {expected:?} scope but was declared in {found:?} scope"
76 )]
77 WrongScope {
78 setting: SettingId,
80 expected: SettingScope,
82 found: SettingScope,
84 location: SettingLocation,
86 },
87 #[error("engine setting {setting:?} is not applicable in {location}")]
89 NotApplicable {
90 setting: SettingId,
92 location: SettingLocation,
94 },
95 #[error("invalid value for engine setting {setting:?} in {location}: {reason:?}")]
97 InvalidSettingValue {
98 setting: SettingId,
100 location: SettingLocation,
102 reason: InvalidSettingReason,
104 },
105 #[error("missing required engine setting {setting:?} in {location}")]
107 MissingRequiredSetting {
108 setting: SettingId,
110 location: SettingLocation,
112 },
113 #[error("input format {format:?} is not accepted by engine profile {selection:?}")]
115 UnacceptedInputFormat {
116 selection: ProfileSelection,
118 format: SourceFormatV1,
120 },
121 #[error("resolved engine settings are outside the V1 contract: {0}")]
124 ResolvedSettingsContract(#[from] EngineContractError),
125}
126
127#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
129#[non_exhaustive]
130pub enum PredictionRuleError {
131 #[error("prediction provenance does not describe the supplied same-load source")]
134 SourceProvenanceMismatch,
135 #[error("prediction provenance does not match the frozen engine profile facts")]
138 FrozenProfileMismatch,
139}
140
141#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
143#[non_exhaustive]
144pub enum RegistryValidationError {
145 #[error("V1 registry contains {found} profiles rather than five")]
147 ProfileCount {
148 found: usize,
150 },
151 #[error("duplicate profile selection {selection:?}")]
153 DuplicateSelection {
154 selection: ProfileSelection,
156 },
157 #[error("duplicate fact-bundle URN {urn}")]
159 DuplicateFactBundleUrn {
160 urn: &'static str,
162 },
163 #[error("invalid fact inventory for {selection:?}")]
165 InvalidFactInventory {
166 selection: ProfileSelection,
168 },
169 #[error("invalid accepted-input fact for {selection:?}")]
171 InvalidAcceptedInputFact {
172 selection: ProfileSelection,
174 },
175 #[error("duplicate setting descriptor for {selection:?}")]
177 DuplicateSettingDescriptor {
178 selection: ProfileSelection,
180 },
181 #[error("invalid default status for {setting:?} in {selection:?}")]
183 InvalidDescriptorDefault {
184 selection: ProfileSelection,
186 setting: SettingId,
188 },
189 #[error("duplicate source id {source_id} in {selection:?}")]
191 DuplicateSourceId {
192 selection: ProfileSelection,
194 source_id: &'static str,
196 },
197 #[error("source {source_id} references unknown fact {fact:?} in {selection:?}")]
199 UnknownSourceFact {
200 selection: ProfileSelection,
202 source_id: &'static str,
204 fact: crate::FactId,
206 },
207 #[error("source {source_id} references non-known fact {fact:?} in {selection:?}")]
209 SourceReferencesNonKnownFact {
210 selection: ProfileSelection,
212 source_id: &'static str,
214 fact: crate::FactId,
216 },
217 #[error("source {source_id} references unknown setting {setting:?} in {selection:?}")]
219 UnknownSourceSetting {
220 selection: ProfileSelection,
222 source_id: &'static str,
224 setting: SettingId,
226 },
227 #[error("known fact {fact:?} has no source reference in {selection:?}")]
229 UnreferencedKnownFact {
230 selection: ProfileSelection,
232 fact: crate::FactId,
234 },
235 #[error("setting descriptor {setting:?} has no source reference in {selection:?}")]
237 UnreferencedSetting {
238 selection: ProfileSelection,
240 setting: SettingId,
242 },
243 #[error("facts identity mismatch for {selection:?}")]
245 FactsIdentityMismatch {
246 selection: ProfileSelection,
248 },
249}
250
251impl SettingValue {
252 pub(crate) const fn kind(&self) -> SettingValueKind {
253 match self {
254 SettingValue::Boolean(_) => SettingValueKind::Boolean,
255 SettingValue::BakeOrExtract(_) => SettingValueKind::BakeOrExtract,
256 SettingValue::SourceTransformPath(_) => SettingValueKind::SourceTransformPath,
257 }
258 }
259}