1use self::ffi::ICU4XError;
6use core::fmt;
7#[cfg(feature = "icu_decimal")]
8use fixed_decimal::FixedDecimalError;
9#[cfg(any(
10 feature = "icu_datetime",
11 feature = "icu_timezone",
12 feature = "icu_calendar"
13))]
14use icu_calendar::CalendarError;
15#[cfg(feature = "icu_collator")]
16use icu_collator::CollatorError;
17#[cfg(feature = "icu_datetime")]
18use icu_datetime::DateTimeError;
19#[cfg(any(feature = "icu_decimal", feature = "icu_datetime"))]
20use icu_decimal::DecimalError;
21#[cfg(feature = "experimental_components")]
22use icu_experimental::units::ConversionError;
23#[cfg(feature = "icu_list")]
24use icu_list::ListError;
25use icu_locid::ParserError;
26#[cfg(feature = "icu_locid_transform")]
27use icu_locid_transform::LocaleTransformError;
28#[cfg(feature = "icu_normalizer")]
29use icu_normalizer::NormalizerError;
30#[cfg(any(feature = "icu_plurals", feature = "icu_datetime"))]
31use icu_plurals::PluralsError;
32#[cfg(feature = "icu_properties")]
33use icu_properties::PropertiesError;
34use icu_provider::{DataError, DataErrorKind};
35#[cfg(feature = "icu_segmenter")]
36use icu_segmenter::SegmenterError;
37#[cfg(any(feature = "icu_timezone", feature = "icu_datetime"))]
38use icu_timezone::TimeZoneError;
39
40#[diplomat::bridge]
41pub mod ffi {
42 use alloc::boxed::Box;
43
44 #[derive(Debug, PartialEq, Eq)]
45 #[repr(C)]
46 #[diplomat::rust_link(fixed_decimal::FixedDecimalError, Enum, compact)]
50 #[diplomat::rust_link(icu::calendar::CalendarError, Enum, compact)]
51 #[diplomat::rust_link(icu::collator::CollatorError, Enum, compact)]
52 #[diplomat::rust_link(icu::datetime::DateTimeError, Enum, compact)]
53 #[diplomat::rust_link(icu::datetime::MismatchedCalendarError, Struct, hidden)]
54 #[diplomat::rust_link(icu::decimal::DecimalError, Enum, compact)]
55 #[diplomat::rust_link(icu::list::ListError, Enum, compact)]
56 #[diplomat::rust_link(icu::locid::ParserError, Enum, compact)]
57 #[diplomat::rust_link(icu::locid_transform::LocaleTransformError, Enum, compact)]
58 #[diplomat::rust_link(icu::normalizer::NormalizerError, Enum, compact)]
59 #[diplomat::rust_link(icu::plurals::PluralsError, Enum, compact)]
60 #[diplomat::rust_link(icu::properties::PropertiesError, Enum, compact)]
61 #[diplomat::rust_link(icu::provider::DataError, Struct, compact)]
62 #[diplomat::rust_link(icu::provider::DataErrorKind, Enum, compact)]
63 #[diplomat::rust_link(icu::segmenter::SegmenterError, Enum, compact)]
64 #[diplomat::rust_link(icu::timezone::TimeZoneError, Enum, compact)]
65 #[diplomat::rust_link(icu_experimental::units::ConversionError, Enum, compact)]
66 pub enum ICU4XError {
67 UnknownError = 0x00,
71 WriteableError = 0x01,
75 OutOfBoundsError = 0x02,
77 Utf8Error = 0x03,
79
80 DataMissingDataKeyError = 0x1_00,
83 DataMissingVariantError = 0x1_01,
84 DataMissingLocaleError = 0x1_02,
85 DataNeedsVariantError = 0x1_03,
86 DataNeedsLocaleError = 0x1_04,
87 DataExtraneousLocaleError = 0x1_05,
88 DataFilteredResourceError = 0x1_06,
89 DataMismatchedTypeError = 0x1_07,
90 DataMissingPayloadError = 0x1_08,
91 DataInvalidStateError = 0x1_09,
92 DataCustomError = 0x1_0A,
93 DataIoError = 0x1_0B,
94 DataUnavailableBufferFormatError = 0x1_0C,
95 DataMismatchedAnyBufferError = 0x1_0D,
96
97 LocaleUndefinedSubtagError = 0x2_00,
100 LocaleParserLanguageError = 0x2_01,
102 LocaleParserSubtagError = 0x2_02,
103 LocaleParserExtensionError = 0x2_03,
104
105 DataStructValidityError = 0x3_00,
108
109 PropertyUnknownScriptIdError = 0x4_00,
111 PropertyUnknownGeneralCategoryGroupError = 0x4_01,
112 PropertyUnexpectedPropertyNameError = 0x4_02,
113
114 FixedDecimalLimitError = 0x5_00,
116 FixedDecimalSyntaxError = 0x5_01,
117
118 PluralsParserError = 0x6_00,
120
121 CalendarParseError = 0x7_00,
123 CalendarOverflowError = 0x7_01,
124 CalendarUnderflowError = 0x7_02,
125 CalendarOutOfRangeError = 0x7_03,
126 CalendarUnknownEraError = 0x7_04,
127 CalendarUnknownMonthCodeError = 0x7_05,
128 CalendarMissingInputError = 0x7_06,
129 CalendarUnknownKindError = 0x7_07,
130 CalendarMissingError = 0x7_08,
131
132 DateTimePatternError = 0x8_00,
134 DateTimeMissingInputFieldError = 0x8_01,
135 DateTimeSkeletonError = 0x8_02,
136 DateTimeUnsupportedFieldError = 0x8_03,
137 DateTimeUnsupportedOptionsError = 0x8_04,
138 DateTimeMissingWeekdaySymbolError = 0x8_05,
139 DateTimeMissingMonthSymbolError = 0x8_06,
140 DateTimeFixedDecimalError = 0x8_07,
141 DateTimeMismatchedCalendarError = 0x8_08,
142
143 TinyStrTooLargeError = 0x9_00,
146 TinyStrContainsNullError = 0x9_01,
147 TinyStrNonAsciiError = 0x9_02,
148
149 TimeZoneOffsetOutOfBoundsError = 0xA_00,
151 TimeZoneInvalidOffsetError = 0xA_01,
152 TimeZoneMissingInputError = 0xA_02,
153 TimeZoneInvalidIdError = 0xA_03,
154
155 NormalizerFutureExtensionError = 0xB_00,
157 NormalizerValidationError = 0xB_01,
158
159 #[cfg(feature = "experimental_components")]
161 InvalidCldrUnitIdentifierError = 0x0C_00,
162 }
163}
164
165impl ICU4XError {
166 #[cfg(feature = "logging")]
167 #[inline]
168 pub(crate) fn log_original<T: core::fmt::Display + ?Sized>(self, e: &T) -> Self {
169 use core::any;
170 log::warn!(
171 "Returning ICU4XError::{:?} based on original {}: {}",
172 self,
173 any::type_name::<T>(),
174 e
175 );
176 self
177 }
178
179 #[cfg(not(feature = "logging"))]
180 #[inline]
181 pub(crate) fn log_original<T: core::fmt::Display + ?Sized>(self, _e: &T) -> Self {
182 self
183 }
184}
185
186impl From<fmt::Error> for ICU4XError {
187 fn from(e: fmt::Error) -> Self {
188 ICU4XError::WriteableError.log_original(&e)
189 }
190}
191
192impl From<DataError> for ICU4XError {
193 fn from(e: DataError) -> Self {
194 match e.kind {
195 DataErrorKind::MissingDataKey => ICU4XError::DataMissingDataKeyError,
196 DataErrorKind::MissingLocale => ICU4XError::DataMissingLocaleError,
197 DataErrorKind::NeedsLocale => ICU4XError::DataNeedsLocaleError,
198 DataErrorKind::ExtraneousLocale => ICU4XError::DataExtraneousLocaleError,
199 DataErrorKind::FilteredResource => ICU4XError::DataFilteredResourceError,
200 DataErrorKind::MismatchedType(..) => ICU4XError::DataMismatchedTypeError,
201 DataErrorKind::MissingPayload => ICU4XError::DataMissingPayloadError,
202 DataErrorKind::InvalidState => ICU4XError::DataInvalidStateError,
203 DataErrorKind::Custom => ICU4XError::DataCustomError,
204 #[cfg(all(
205 feature = "provider_fs",
206 not(any(target_arch = "wasm32", target_os = "none"))
207 ))]
208 DataErrorKind::Io(..) => ICU4XError::DataIoError,
209 DataErrorKind::UnavailableBufferFormat(..) => {
212 ICU4XError::DataUnavailableBufferFormatError
213 }
214 _ => ICU4XError::UnknownError,
215 }
216 .log_original(&e)
217 }
218}
219
220impl From<core::str::Utf8Error> for ICU4XError {
221 fn from(_: core::str::Utf8Error) -> Self {
222 ICU4XError::Utf8Error
223 }
224}
225
226#[cfg(feature = "icu_collator")]
227impl From<CollatorError> for ICU4XError {
228 fn from(e: CollatorError) -> Self {
229 match e {
230 CollatorError::NotFound => ICU4XError::DataMissingPayloadError,
231 CollatorError::MalformedData => ICU4XError::DataInvalidStateError,
232 CollatorError::Data(_) => ICU4XError::DataIoError,
233 _ => ICU4XError::DataIoError,
234 }
235 .log_original(&e)
236 }
237}
238
239#[cfg(feature = "icu_properties")]
240impl From<PropertiesError> for ICU4XError {
241 fn from(e: PropertiesError) -> Self {
242 match e {
243 PropertiesError::PropDataLoad(e) => e.into(),
244 PropertiesError::UnknownScriptId(..) => ICU4XError::PropertyUnknownScriptIdError,
245 PropertiesError::UnknownGeneralCategoryGroup(..) => {
246 ICU4XError::PropertyUnknownGeneralCategoryGroupError
247 }
248 PropertiesError::UnexpectedPropertyName => {
249 ICU4XError::PropertyUnexpectedPropertyNameError
250 }
251 _ => ICU4XError::UnknownError,
252 }
253 .log_original(&e)
254 }
255}
256
257#[cfg(any(
258 feature = "icu_datetime",
259 feature = "icu_timezone",
260 feature = "icu_calendar"
261))]
262impl From<CalendarError> for ICU4XError {
263 fn from(e: CalendarError) -> Self {
264 match e {
265 CalendarError::Parse => ICU4XError::CalendarParseError,
266 CalendarError::Overflow { field: _, max: _ } => ICU4XError::CalendarOverflowError,
267 CalendarError::Underflow { field: _, min: _ } => ICU4XError::CalendarUnderflowError,
268 CalendarError::OutOfRange => ICU4XError::CalendarOutOfRangeError,
269 CalendarError::UnknownEra(..) => ICU4XError::CalendarUnknownEraError,
270 CalendarError::UnknownMonthCode(..) => ICU4XError::CalendarUnknownMonthCodeError,
271 CalendarError::MissingInput(_) => ICU4XError::CalendarMissingInputError,
272 CalendarError::UnknownAnyCalendarKind(_) => ICU4XError::CalendarUnknownKindError,
273 CalendarError::MissingCalendar => ICU4XError::CalendarMissingError,
274 CalendarError::Data(e) => e.into(),
275 _ => ICU4XError::UnknownError,
276 }
277 .log_original(&e)
278 }
279}
280
281#[cfg(feature = "icu_datetime")]
282impl From<DateTimeError> for ICU4XError {
283 fn from(e: DateTimeError) -> Self {
284 match e {
285 DateTimeError::Pattern(_) => ICU4XError::DateTimePatternError,
286 DateTimeError::Format(err) => err.into(),
287 DateTimeError::Data(err) => err.into(),
288 DateTimeError::MissingInputField(_) => ICU4XError::DateTimeMissingInputFieldError,
289 DateTimeError::UnsupportedField(_) => ICU4XError::DateTimeUnsupportedFieldError,
292 DateTimeError::UnsupportedOptions => ICU4XError::DateTimeUnsupportedOptionsError,
293 DateTimeError::PluralRules(err) => err.into(),
294 DateTimeError::DateTimeInput(err) => err.into(),
295 DateTimeError::MissingWeekdaySymbol(_) => ICU4XError::DateTimeMissingWeekdaySymbolError,
296 DateTimeError::MissingMonthSymbol(_) => ICU4XError::DateTimeMissingMonthSymbolError,
297 DateTimeError::FixedDecimal => ICU4XError::DateTimeFixedDecimalError,
298 DateTimeError::FixedDecimalFormatter(err) => err.into(),
299 DateTimeError::MismatchedAnyCalendar(_, _) => {
300 ICU4XError::DateTimeMismatchedCalendarError
301 }
302 _ => ICU4XError::UnknownError,
303 }
304 .log_original(&e)
305 }
306}
307
308#[cfg(feature = "icu_decimal")]
309impl From<FixedDecimalError> for ICU4XError {
310 fn from(e: FixedDecimalError) -> Self {
311 match e {
312 FixedDecimalError::Limit => ICU4XError::FixedDecimalLimitError,
313 FixedDecimalError::Syntax => ICU4XError::FixedDecimalSyntaxError,
314 _ => ICU4XError::UnknownError,
315 }
316 .log_original(&e)
317 }
318}
319
320#[cfg(any(feature = "icu_plurals", feature = "icu_datetime"))]
321impl From<PluralsError> for ICU4XError {
322 fn from(e: PluralsError) -> Self {
323 match e {
324 PluralsError::Data(e) => e.into(),
325 _ => ICU4XError::UnknownError,
326 }
327 .log_original(&e)
328 }
329}
330
331#[cfg(any(feature = "icu_decimal", feature = "icu_datetime"))]
332impl From<DecimalError> for ICU4XError {
333 fn from(e: DecimalError) -> Self {
334 match e {
335 DecimalError::Data(e) => e.into(),
336 _ => ICU4XError::UnknownError,
337 }
338 .log_original(&e)
339 }
340}
341
342#[cfg(feature = "icu_locid_transform")]
343impl From<LocaleTransformError> for ICU4XError {
344 fn from(e: LocaleTransformError) -> Self {
345 match e {
346 LocaleTransformError::Data(e) => e.into(),
347 _ => ICU4XError::UnknownError,
348 }
349 .log_original(&e)
350 }
351}
352
353#[cfg(feature = "icu_segmenter")]
354impl From<SegmenterError> for ICU4XError {
355 fn from(e: SegmenterError) -> Self {
356 match e {
357 SegmenterError::Data(e) => e.into(),
358 _ => ICU4XError::UnknownError,
359 }
360 .log_original(&e)
361 }
362}
363
364#[cfg(feature = "icu_list")]
365impl From<ListError> for ICU4XError {
366 fn from(e: ListError) -> Self {
367 match e {
368 ListError::Data(e) => e.into(),
369 _ => ICU4XError::UnknownError,
370 }
371 .log_original(&e)
372 }
373}
374
375impl From<ParserError> for ICU4XError {
376 fn from(e: ParserError) -> Self {
377 match e {
378 ParserError::InvalidLanguage => ICU4XError::LocaleParserLanguageError,
379 ParserError::InvalidSubtag => ICU4XError::LocaleParserSubtagError,
380 ParserError::InvalidExtension => ICU4XError::LocaleParserExtensionError,
381 ParserError::DuplicatedExtension => ICU4XError::LocaleParserExtensionError,
382 _ => ICU4XError::UnknownError,
383 }
384 .log_original(&e)
385 }
386}
387
388#[cfg(any(feature = "icu_timezone", feature = "icu_datetime"))]
389impl From<TimeZoneError> for ICU4XError {
390 fn from(e: TimeZoneError) -> Self {
391 match e {
392 TimeZoneError::OffsetOutOfBounds => ICU4XError::TimeZoneOffsetOutOfBoundsError,
393 TimeZoneError::InvalidOffset => ICU4XError::TimeZoneInvalidOffsetError,
394 TimeZoneError::Data(err) => err.into(),
395 _ => ICU4XError::UnknownError,
396 }
397 .log_original(&e)
398 }
399}
400
401#[cfg(feature = "icu_normalizer")]
402impl From<NormalizerError> for ICU4XError {
403 fn from(e: NormalizerError) -> Self {
404 match e {
405 NormalizerError::FutureExtension => ICU4XError::NormalizerFutureExtensionError,
406 NormalizerError::ValidationError => ICU4XError::NormalizerValidationError,
407 NormalizerError::Data(err) => err.into(),
408 _ => ICU4XError::UnknownError,
409 }
410 .log_original(&e)
411 }
412}
413
414#[cfg(feature = "experimental_components")]
415impl From<ConversionError> for ICU4XError {
416 fn from(value: ConversionError) -> Self {
417 match value {
418 ConversionError::InvalidUnit => ICU4XError::InvalidCldrUnitIdentifierError,
419 _ => ICU4XError::UnknownError,
420 }
421 }
422}