1use std::fmt::Debug;
18use std::io::Error;
19use thiserror::Error;
20
21use crate::config::ConfigError;
22use crate::dic::build::error::DicBuildError;
23use crate::dic::character_category::Error as CharacterCategoryError;
24use crate::dic::header::HeaderError;
25use crate::dic::lexicon_set::LexiconSetError;
26use crate::plugin::PluginError;
27
28pub type SudachiResult<T> = Result<T, SudachiError>;
29
30#[derive(Error, Debug)]
32#[non_exhaustive]
33pub enum SudachiError {
34 #[error("{context}: {cause}")]
35 ErrWithContext {
36 context: String,
37 cause: Box<SudachiError>,
38 },
39
40 #[error("{context}: {cause}")]
41 Io {
42 cause: std::io::Error,
43 context: String,
44 },
45
46 #[error("Parse Int Error")]
47 ParseIntError(#[from] std::num::ParseIntError),
48
49 #[error("Invalid UTF-16: {0}")]
50 FromUtf16(#[from] std::string::FromUtf16Error),
51
52 #[error("Regex error")]
53 RegexError(#[from] fancy_regex::Error),
54
55 #[error("Error from nom {0}")]
56 NomParseError(String),
57
58 #[error("Invalid utf16 string from nom")]
59 InvalidUtf16FromNom,
60
61 #[error("Serde error: {0}")]
62 SerdeError(#[from] serde_json::Error),
63
64 #[error("Invalid character category definition: {0}")]
65 InvalidCharacterCategory(#[from] CharacterCategoryError),
66
67 #[error("Config Error: {0}")]
68 ConfigError(#[from] ConfigError),
69
70 #[error("Invalid header: {0}")]
71 InvalidHeader(#[from] HeaderError),
72
73 #[error("Lecicon error")]
74 LexiconSetError(#[from] LexiconSetError),
75
76 #[error("Plugin error")]
77 PluginError(#[from] PluginError),
78
79 #[error("End of sentence (EOS) is not connected to beginning of sentence (BOS)")]
80 EosBosDisconnect,
81
82 #[error("Invalid character category type: {0}")]
83 InvalidCharacterCategoryType(String),
84
85 #[error("Invalid data format: {1} at line {0}")]
86 InvalidDataFormat(usize, String),
87
88 #[error("Invalid grammar")]
89 InvalidDictionaryGrammar,
90
91 #[error("Invalid part of speech: {0}")]
92 InvalidPartOfSpeech(String),
93
94 #[error("Invalid range: {0}..{1}")]
95 InvalidRange(usize, usize),
96
97 #[error("No out of vocabulary plugin provided")]
98 NoOOVPluginProvided,
99
100 #[error("Input is too long, it can't be more than {1} bytes, was {0}")]
101 InputTooLong(usize, usize),
102
103 #[error(transparent)]
104 DictionaryCompilationError(#[from] DicBuildError),
105
106 #[error("MorphemeList is borrowed, make sure that all Ref<> are dropped")]
107 MorphemeListBorrowed,
108}
109
110impl From<std::io::Error> for SudachiError {
111 fn from(e: Error) -> Self {
112 SudachiError::Io {
113 cause: e,
114 context: String::from("IO Error"),
115 }
116 }
117}
118
119impl SudachiError {
120 pub fn with_context<S: Into<String>>(self, ctx: S) -> Self {
121 match self {
122 SudachiError::Io { cause, .. } => SudachiError::Io {
123 cause,
124 context: ctx.into(),
125 },
126 cause => SudachiError::ErrWithContext {
127 cause: Box::new(cause),
128 context: ctx.into(),
129 },
130 }
131 }
132}
133
134pub type SudachiNomResult<I, O> = nom::IResult<I, O, SudachiNomError<I>>;
135
136#[derive(Debug, PartialEq)]
138pub enum SudachiNomError<I> {
139 Utf16String,
141 Nom(I, nom::error::ErrorKind),
142 OutOfBounds(String, usize, usize),
143}
144
145impl<I> nom::error::ParseError<I> for SudachiNomError<I> {
146 fn from_error_kind(input: I, kind: nom::error::ErrorKind) -> Self {
147 SudachiNomError::Nom(input, kind)
148 }
149 fn append(_: I, _: nom::error::ErrorKind, other: Self) -> Self {
150 other
151 }
152}
153
154impl<I: Debug> From<nom::Err<SudachiNomError<I>>> for SudachiError {
155 fn from(err: nom::Err<SudachiNomError<I>>) -> Self {
156 if let nom::Err::Failure(SudachiNomError::Utf16String) = err {
157 return SudachiError::InvalidUtf16FromNom;
158 }
159 SudachiError::NomParseError(format!("{}", err))
160 }
161}