1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
// =============================================================================
// #######
// ### ### F: error.rs
// ## ## ## ## P: AppCore-Runtime
// ## ##
// C: 2026/08/30 05:00:00 by dnettoRaw
// ## ## ## ## U: 2026/08/30 05:00:00 by dnettoRaw
// ########### S: 1.0.2-rc
// =============================================================================
use std::fmt;
use thiserror::Error;
/// Stable machine-readable failure code.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum ErrorCode {
/// Source is not syntactically valid.
SchemaSyntax,
/// Source schema version is absent or unsupported.
SchemaVersion,
/// Source contains an invalid field or value.
SchemaField,
/// A typed data value or binding is invalid.
DataType,
/// Computed data contains a dependency cycle.
DataCycle,
/// An asset reference violates the resolver sandbox.
AssetSandbox,
/// An asset is missing or invalid.
AssetInvalid,
/// A required font or glyph is unavailable.
FontMissing,
/// Geometry overflowed or violates an invariant.
GeometryInvalid,
/// Layout constraints cannot be resolved.
LayoutInvalid,
/// Collision/reflow did not converge within the configured bound.
LayoutNonConvergent,
/// A patch is malformed or targets an absent node.
PatchInvalid,
/// A patch attempted to mutate a locked node.
PatchLocked,
/// The requested exporter does not support a required feature.
ExportUnsupported,
/// The output writer failed.
ExportWrite,
/// A configured resource budget was exceeded.
LimitExceeded,
/// Cooperative cancellation was requested.
Cancelled,
/// Validation or preflight rejected the requested operation.
Validation,
}
impl ErrorCode {
/// Returns the stable `FM-*` representation.
#[must_use]
pub const fn as_str(self) -> &'static str {
match self {
Self::SchemaSyntax => "FM-SCHEMA-SYNTAX",
Self::SchemaVersion => "FM-SCHEMA-VERSION",
Self::SchemaField => "FM-SCHEMA-FIELD",
Self::DataType => "FM-DATA-TYPE",
Self::DataCycle => "FM-DATA-CYCLE",
Self::AssetSandbox => "FM-ASSET-SANDBOX",
Self::AssetInvalid => "FM-ASSET-INVALID",
Self::FontMissing => "FM-FONT-MISSING",
Self::GeometryInvalid => "FM-GEOM-INVALID",
Self::LayoutInvalid => "FM-LAYOUT-INVALID",
Self::LayoutNonConvergent => "FM-LAYOUT-NON-CONVERGENT",
Self::PatchInvalid => "FM-PATCH-INVALID",
Self::PatchLocked => "FM-PATCH-LOCKED",
Self::ExportUnsupported => "FM-EXPORT-UNSUPPORTED",
Self::ExportWrite => "FM-EXPORT-WRITE",
Self::LimitExceeded => "FM-LIMIT-EXCEEDED",
Self::Cancelled => "FM-CANCELLED",
Self::Validation => "FM-VALIDATION",
}
}
}
/// Typed compiler error with stable code and bounded context.
#[derive(Debug, Error)]
#[error("{code}: {message}")]
pub struct FileMakerError {
code: CodeDisplay,
message: String,
source_path: Option<String>,
}
impl FileMakerError {
/// Creates an error while bounding user-controlled diagnostic text.
#[must_use]
pub fn new(code: ErrorCode, message: impl Into<String>) -> Self {
let mut message = message.into();
message.truncate(1_024);
Self {
code: CodeDisplay(code),
message,
source_path: None,
}
}
/// Attaches a bounded logical source path.
#[must_use]
pub fn at(mut self, source_path: impl Into<String>) -> Self {
let mut source_path = source_path.into();
source_path.truncate(512);
self.source_path = Some(source_path);
self
}
/// Returns the stable code.
#[must_use]
pub const fn code(&self) -> ErrorCode {
self.code.0
}
/// Returns the bounded human-readable diagnostic.
#[must_use]
pub fn message(&self) -> &str {
&self.message
}
/// Returns the logical input path, when available.
#[must_use]
pub fn source_path(&self) -> Option<&str> {
self.source_path.as_deref()
}
}
#[derive(Debug)]
struct CodeDisplay(ErrorCode);
impl fmt::Display for CodeDisplay {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str(self.0.as_str())
}
}
/// Result returned by `FileMaker` compiler operations.
pub type Result<T> = std::result::Result<T, FileMakerError>;