sudachi/dic/build/
error.rs1use crate::error::SudachiError;
18use crate::prelude::SudachiResult;
19use thiserror::Error;
20
21#[derive(Error, Debug)]
24#[error("{file}:{line}\t{cause}")]
25pub struct DicBuildError {
26 pub file: String,
27 pub line: usize,
28 pub cause: BuildFailure,
29}
30
31#[derive(Error, Debug)]
33#[non_exhaustive]
34pub enum BuildFailure {
35 #[error("The actual size {actual} was larger than expected {expected}")]
36 InvalidSize { actual: usize, expected: usize },
37
38 #[error("The actual size of {field} {actual} was larger than expected {expected}")]
39 InvalidFieldSize {
40 actual: usize,
41 expected: usize,
42 field: &'static str,
43 },
44
45 #[error(transparent)]
47 Io(#[from] std::io::Error),
48
49 #[error("Field {0} did not exist in CSV lexicon")]
50 NoRawField(&'static str),
51
52 #[error(transparent)]
53 CsvError(csv::Error),
54
55 #[error("Invalid character literal {0}")]
56 InvalidCharLiteral(String),
57
58 #[error("Invalid i16 literal {0}")]
59 InvalidI16Literal(String),
60
61 #[error("Invalid u32 literal {0}")]
62 InvalidU32Literal(String),
63
64 #[error("Invalid word id: {0}")]
65 InvalidWordId(String),
66
67 #[error("Invalid word split {0}")]
68 InvalidSplit(String),
69
70 #[error("Invalid word split format - field {field} did not exist in {original}")]
71 SplitFormatError {
72 field: &'static str,
73 original: String,
74 },
75
76 #[error("IndexForm can't be empty")]
77 EmptyIndexForm,
78
79 #[error("Maximum number of POS (2^15-1) exceeded with {0}")]
80 PosLimitExceeded(String),
81
82 #[error("Split reference {0} was incorrect")]
83 InvalidSplitWordReference(String),
84
85 #[error("Lexicon contains unresolved splits, call resolve()")]
86 UnresolvedSplits,
87
88 #[error("Connection size {0} was invalid: {1}")]
89 InvalidConnSize(&'static str, i16),
90
91 #[error("WordId table is not built, call build_word_id_table()")]
92 WordIdTableNotBuilt,
93
94 #[error("Failed to build trie")]
95 TrieBuildFailure,
96
97 #[error(
98 "Invalid string pointer during dictionary compilation: length={length}, offset={offset}, alignment={alignment}"
99 )]
100 InvalidStringPointer {
101 length: usize,
102 offset: usize,
103 alignment: usize,
104 },
105
106 #[error("Dictionary compile time must not be earlier than UNIX_EPOCH")]
107 InvalidCompileTime,
108
109 #[error("{0}")]
110 InvalidBuilderState(&'static str),
111}
112
113#[derive(Default)]
114pub(crate) struct DicCompilationCtx {
115 name: String,
116 line: usize,
117}
118
119impl DicCompilationCtx {
120 pub fn memory() -> Self {
121 DicCompilationCtx {
122 name: "<memory>".to_owned(),
123 line: 0,
124 }
125 }
126
127 #[inline]
128 pub fn err<T, E: Into<BuildFailure>>(&self, reason: E) -> SudachiResult<T> {
129 Err(self.to_sudachi_err(reason))
130 }
131
132 #[inline(always)]
133 pub fn to_sudachi_err<E: Into<BuildFailure>>(&self, reason: E) -> SudachiError {
134 match reason.into() {
135 BuildFailure::Io(e) => e.into(),
136 reason => {
137 let err = DicBuildError {
138 file: self.name.clone(),
139 line: self.line,
140 cause: reason,
141 };
142 err.into()
143 }
144 }
145 }
146
147 #[inline(never)]
148 #[cold]
149 pub fn to_sudachi_err_cold<E: Into<BuildFailure>>(&self, reason: E) -> SudachiError {
150 self.to_sudachi_err(reason)
151 }
152
153 #[inline(always)]
154 pub fn transform<T>(&self, result: DicWriteResult<T>) -> SudachiResult<T> {
155 match result {
156 Ok(v) => Ok(v),
157 Err(e) => Err(self.to_sudachi_err_cold(e)),
158 }
159 }
160
161 #[inline(always)]
162 pub fn apply<T, F: FnOnce() -> DicWriteResult<T>>(&self, f: F) -> SudachiResult<T> {
163 match f() {
164 Ok(v) => Ok(v),
165 Err(e) => Err(self.to_sudachi_err_cold(e)),
166 }
167 }
168
169 pub fn set_filename(&mut self, new_name: String) -> String {
170 std::mem::replace(&mut self.name, new_name)
171 }
172
173 pub fn add_line(&mut self, offset: usize) {
174 self.line += offset;
175 }
176
177 pub fn set_line(&mut self, line: usize) -> usize {
178 std::mem::replace(&mut self.line, line)
179 }
180}
181
182pub type DicWriteResult<T> = std::result::Result<T, BuildFailure>;