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
144
145
146
147
148
149
150
151
152
use serde::{Deserialize, Serialize};
use std::fmt;
/// Core-owned result type for fallible primitive APIs.
pub type Result<T> = std::result::Result<T, CoreError>;
/// Structured, machine-readable errors for core primitive boundaries.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(tag = "code", rename_all = "snake_case")]
pub enum CoreError {
/// An identifier was empty or malformed after normalization.
InvalidId {
/// The value supplied by the caller or serialized input.
value: String,
/// A diagnostic explanation for humans.
reason: String,
},
/// A confidence score was NaN, infinite, or outside the valid range.
InvalidConfidence {
/// The value supplied by the caller or serialized input.
value: String,
/// A diagnostic explanation for humans.
reason: String,
},
/// A source kind was not one of the stable core categories.
InvalidSourceKind {
/// The value supplied by the caller or serialized input.
value: String,
/// A diagnostic explanation for humans.
reason: String,
},
/// A required field was absent or malformed at a primitive boundary.
MalformedField {
/// The stable lower snake case field name.
field: String,
/// A diagnostic explanation for humans.
reason: String,
},
/// A primitive parser could not convert input into the requested type.
ParseFailure {
/// The primitive type or target schema being parsed.
target: String,
/// The value supplied by the caller or serialized input.
value: String,
/// A diagnostic explanation for humans.
reason: String,
},
/// Serialized data used a version unsupported by this crate.
UnsupportedVersion {
/// The unsupported serialized version.
version: String,
/// The version or version range supported by this crate.
supported: String,
},
}
impl CoreError {
/// Returns the stable error code for bindings and tests.
pub fn code(&self) -> &'static str {
match self {
Self::InvalidId { .. } => "invalid_id",
Self::InvalidConfidence { .. } => "invalid_confidence",
Self::InvalidSourceKind { .. } => "invalid_source_kind",
Self::MalformedField { .. } => "malformed_field",
Self::ParseFailure { .. } => "parse_failure",
Self::UnsupportedVersion { .. } => "unsupported_version",
}
}
pub(crate) fn invalid_id(value: impl Into<String>, reason: impl Into<String>) -> Self {
Self::InvalidId {
value: value.into(),
reason: reason.into(),
}
}
pub(crate) fn invalid_confidence(value: f64, reason: impl Into<String>) -> Self {
Self::InvalidConfidence {
value: value.to_string(),
reason: reason.into(),
}
}
pub(crate) fn invalid_source_kind(value: impl Into<String>, reason: impl Into<String>) -> Self {
Self::InvalidSourceKind {
value: value.into(),
reason: reason.into(),
}
}
pub(crate) fn malformed_field(field: impl Into<String>, reason: impl Into<String>) -> Self {
Self::MalformedField {
field: field.into(),
reason: reason.into(),
}
}
pub(crate) fn parse_failure(
target: impl Into<String>,
value: impl Into<String>,
reason: impl Into<String>,
) -> Self {
Self::ParseFailure {
target: target.into(),
value: value.into(),
reason: reason.into(),
}
}
}
impl fmt::Display for CoreError {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::InvalidId { value, reason } => {
write!(formatter, "{}: invalid id {value:?}: {reason}", self.code())
}
Self::InvalidConfidence { value, reason } => write!(
formatter,
"{}: invalid confidence {value:?}: {reason}",
self.code()
),
Self::InvalidSourceKind { value, reason } => write!(
formatter,
"{}: invalid source kind {value:?}: {reason}",
self.code()
),
Self::MalformedField { field, reason } => {
write!(
formatter,
"{}: malformed field {field:?}: {reason}",
self.code()
)
}
Self::ParseFailure {
target,
value,
reason,
} => write!(
formatter,
"{}: could not parse {value:?} as {target}: {reason}",
self.code()
),
Self::UnsupportedVersion { version, supported } => write!(
formatter,
"{}: unsupported version {version:?}; supported {supported}",
self.code()
),
}
}
}
impl std::error::Error for CoreError {}