use std::fmt;
use lindera::error::{LinderaError, LinderaErrorKind};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ErrorKind {
InvalidArgument,
Dictionary,
Build,
Io,
Parse,
Validation,
Runtime,
}
impl ErrorKind {
pub fn as_str(&self) -> &'static str {
match self {
ErrorKind::InvalidArgument => "invalid_argument",
ErrorKind::Dictionary => "dictionary",
ErrorKind::Build => "build",
ErrorKind::Io => "io",
ErrorKind::Parse => "parse",
ErrorKind::Validation => "validation",
ErrorKind::Runtime => "runtime",
}
}
}
impl fmt::Display for ErrorKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct CoreError {
kind: ErrorKind,
message: String,
}
impl CoreError {
pub fn new(kind: ErrorKind, message: impl Into<String>) -> Self {
Self {
kind,
message: message.into(),
}
}
pub fn invalid_argument(message: impl Into<String>) -> Self {
Self::new(ErrorKind::InvalidArgument, message)
}
pub fn dictionary(message: impl Into<String>) -> Self {
Self::new(ErrorKind::Dictionary, message)
}
pub fn build(message: impl Into<String>) -> Self {
Self::new(ErrorKind::Build, message)
}
pub fn validation(message: impl Into<String>) -> Self {
Self::new(ErrorKind::Validation, message)
}
pub fn runtime(message: impl Into<String>) -> Self {
Self::new(ErrorKind::Runtime, message)
}
pub fn kind(&self) -> ErrorKind {
self.kind
}
pub fn message(&self) -> &str {
&self.message
}
}
impl fmt::Display for CoreError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&self.message)
}
}
impl std::error::Error for CoreError {}
impl From<LinderaError> for CoreError {
fn from(err: LinderaError) -> Self {
let kind = match err.kind() {
LinderaErrorKind::Args | LinderaErrorKind::Mode => ErrorKind::InvalidArgument,
LinderaErrorKind::Dictionary | LinderaErrorKind::NotFound => ErrorKind::Dictionary,
LinderaErrorKind::Build => ErrorKind::Build,
LinderaErrorKind::Io => ErrorKind::Io,
LinderaErrorKind::Content
| LinderaErrorKind::Decode
| LinderaErrorKind::Deserialize
| LinderaErrorKind::Serialize
| LinderaErrorKind::Parse => ErrorKind::Parse,
LinderaErrorKind::FeatureDisabled => ErrorKind::Runtime,
};
CoreError::new(kind, err.to_string())
}
}
pub type CoreResult<T> = Result<T, CoreError>;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_exposes_kind_and_message() {
let err = CoreError::new(ErrorKind::Build, "boom");
assert_eq!(err.kind(), ErrorKind::Build);
assert_eq!(err.message(), "boom");
assert_eq!(err.to_string(), "boom");
}
#[test]
fn convenience_constructors_set_kind() {
assert_eq!(
CoreError::invalid_argument("x").kind(),
ErrorKind::InvalidArgument
);
assert_eq!(CoreError::dictionary("x").kind(), ErrorKind::Dictionary);
assert_eq!(CoreError::validation("x").kind(), ErrorKind::Validation);
assert_eq!(CoreError::runtime("x").kind(), ErrorKind::Runtime);
}
#[test]
fn kind_as_str_is_stable() {
assert_eq!(ErrorKind::InvalidArgument.as_str(), "invalid_argument");
assert_eq!(ErrorKind::Dictionary.to_string(), "dictionary");
}
#[test]
fn from_lindera_error_maps_kind() {
let parse = LinderaErrorKind::Parse.with_error(std::io::Error::other("bad"));
assert_eq!(CoreError::from(parse).kind(), ErrorKind::Parse);
let args = LinderaErrorKind::Args.with_error(std::io::Error::other("bad arg"));
assert_eq!(CoreError::from(args).kind(), ErrorKind::InvalidArgument);
let notfound = LinderaErrorKind::NotFound.with_error(std::io::Error::other("missing"));
assert_eq!(CoreError::from(notfound).kind(), ErrorKind::Dictionary);
}
}