lindera_binding_core/
error.rs1use std::fmt;
11
12use lindera::error::{LinderaError, LinderaErrorKind};
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
20pub enum ErrorKind {
21 InvalidArgument,
23 Dictionary,
25 Build,
27 Io,
29 Parse,
31 Validation,
33 Runtime,
35}
36
37impl ErrorKind {
38 pub fn as_str(&self) -> &'static str {
41 match self {
42 ErrorKind::InvalidArgument => "invalid_argument",
43 ErrorKind::Dictionary => "dictionary",
44 ErrorKind::Build => "build",
45 ErrorKind::Io => "io",
46 ErrorKind::Parse => "parse",
47 ErrorKind::Validation => "validation",
48 ErrorKind::Runtime => "runtime",
49 }
50 }
51}
52
53impl fmt::Display for ErrorKind {
54 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56 f.write_str(self.as_str())
57 }
58}
59
60#[derive(Debug, Clone, PartialEq, Eq)]
66pub struct CoreError {
67 kind: ErrorKind,
69 message: String,
71}
72
73impl CoreError {
74 pub fn new(kind: ErrorKind, message: impl Into<String>) -> Self {
76 Self {
77 kind,
78 message: message.into(),
79 }
80 }
81
82 pub fn invalid_argument(message: impl Into<String>) -> Self {
84 Self::new(ErrorKind::InvalidArgument, message)
85 }
86
87 pub fn dictionary(message: impl Into<String>) -> Self {
89 Self::new(ErrorKind::Dictionary, message)
90 }
91
92 pub fn build(message: impl Into<String>) -> Self {
94 Self::new(ErrorKind::Build, message)
95 }
96
97 pub fn validation(message: impl Into<String>) -> Self {
99 Self::new(ErrorKind::Validation, message)
100 }
101
102 pub fn runtime(message: impl Into<String>) -> Self {
104 Self::new(ErrorKind::Runtime, message)
105 }
106
107 pub fn kind(&self) -> ErrorKind {
109 self.kind
110 }
111
112 pub fn message(&self) -> &str {
114 &self.message
115 }
116}
117
118impl fmt::Display for CoreError {
119 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
121 f.write_str(&self.message)
122 }
123}
124
125impl std::error::Error for CoreError {}
126
127impl From<LinderaError> for CoreError {
128 fn from(err: LinderaError) -> Self {
131 let kind = match err.kind() {
132 LinderaErrorKind::Args | LinderaErrorKind::Mode => ErrorKind::InvalidArgument,
133 LinderaErrorKind::Dictionary | LinderaErrorKind::NotFound => ErrorKind::Dictionary,
134 LinderaErrorKind::Build => ErrorKind::Build,
135 LinderaErrorKind::Io => ErrorKind::Io,
136 LinderaErrorKind::Content
137 | LinderaErrorKind::Decode
138 | LinderaErrorKind::Deserialize
139 | LinderaErrorKind::Serialize
140 | LinderaErrorKind::Parse => ErrorKind::Parse,
141 LinderaErrorKind::FeatureDisabled => ErrorKind::Runtime,
142 };
143 CoreError::new(kind, err.to_string())
144 }
145}
146
147pub type CoreResult<T> = Result<T, CoreError>;
149
150#[cfg(test)]
151mod tests {
152 use super::*;
153
154 #[test]
155 fn new_exposes_kind_and_message() {
156 let err = CoreError::new(ErrorKind::Build, "boom");
157 assert_eq!(err.kind(), ErrorKind::Build);
158 assert_eq!(err.message(), "boom");
159 assert_eq!(err.to_string(), "boom");
160 }
161
162 #[test]
163 fn convenience_constructors_set_kind() {
164 assert_eq!(
165 CoreError::invalid_argument("x").kind(),
166 ErrorKind::InvalidArgument
167 );
168 assert_eq!(CoreError::dictionary("x").kind(), ErrorKind::Dictionary);
169 assert_eq!(CoreError::validation("x").kind(), ErrorKind::Validation);
170 assert_eq!(CoreError::runtime("x").kind(), ErrorKind::Runtime);
171 }
172
173 #[test]
174 fn kind_as_str_is_stable() {
175 assert_eq!(ErrorKind::InvalidArgument.as_str(), "invalid_argument");
176 assert_eq!(ErrorKind::Dictionary.to_string(), "dictionary");
177 }
178
179 #[test]
180 fn from_lindera_error_maps_kind() {
181 let parse = LinderaErrorKind::Parse.with_error(std::io::Error::other("bad"));
182 assert_eq!(CoreError::from(parse).kind(), ErrorKind::Parse);
183
184 let args = LinderaErrorKind::Args.with_error(std::io::Error::other("bad arg"));
185 assert_eq!(CoreError::from(args).kind(), ErrorKind::InvalidArgument);
186
187 let notfound = LinderaErrorKind::NotFound.with_error(std::io::Error::other("missing"));
188 assert_eq!(CoreError::from(notfound).kind(), ErrorKind::Dictionary);
189 }
190}