diff options
Diffstat (limited to 'intl/icu_capi/src/errors.rs')
-rw-r--r-- | intl/icu_capi/src/errors.rs | 407 |
1 files changed, 407 insertions, 0 deletions
diff --git a/intl/icu_capi/src/errors.rs b/intl/icu_capi/src/errors.rs new file mode 100644 index 0000000000..bf17a650f3 --- /dev/null +++ b/intl/icu_capi/src/errors.rs @@ -0,0 +1,407 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +use self::ffi::ICU4XError; +use core::fmt; +#[cfg(feature = "icu_decimal")] +use fixed_decimal::FixedDecimalError; +#[cfg(any( + feature = "icu_datetime", + feature = "icu_timezone", + feature = "icu_calendar" +))] +use icu_calendar::CalendarError; +#[cfg(feature = "icu_collator")] +use icu_collator::CollatorError; +#[cfg(feature = "icu_datetime")] +use icu_datetime::DateTimeError; +#[cfg(any(feature = "icu_decimal", feature = "icu_datetime"))] +use icu_decimal::DecimalError; +#[cfg(feature = "icu_list")] +use icu_list::ListError; +use icu_locid::ParserError; +#[cfg(feature = "icu_locid_transform")] +use icu_locid_transform::LocaleTransformError; +#[cfg(feature = "icu_normalizer")] +use icu_normalizer::NormalizerError; +#[cfg(any(feature = "icu_plurals", feature = "icu_datetime"))] +use icu_plurals::PluralsError; +#[cfg(feature = "icu_properties")] +use icu_properties::PropertiesError; +use icu_provider::{DataError, DataErrorKind}; +#[cfg(feature = "icu_segmenter")] +use icu_segmenter::SegmenterError; +#[cfg(any(feature = "icu_timezone", feature = "icu_datetime"))] +use icu_timezone::TimeZoneError; +use tinystr::TinyStrError; + +#[diplomat::bridge] +pub mod ffi { + use alloc::boxed::Box; + + #[derive(Debug, Copy, Clone, PartialEq, Eq)] + #[repr(C)] + /// A common enum for errors that ICU4X may return, organized by API + /// + /// The error names are stable and can be checked against as strings in the JS API + #[diplomat::rust_link(fixed_decimal::FixedDecimalError, Enum, compact)] + #[diplomat::rust_link(icu::calendar::CalendarError, Enum, compact)] + #[diplomat::rust_link(icu::collator::CollatorError, Enum, compact)] + #[diplomat::rust_link(icu::datetime::DateTimeError, Enum, compact)] + #[diplomat::rust_link(icu::decimal::DecimalError, Enum, compact)] + #[diplomat::rust_link(icu::list::ListError, Enum, compact)] + #[diplomat::rust_link(icu::locid::ParserError, Enum, compact)] + #[diplomat::rust_link(icu::locid_transform::LocaleTransformError, Enum, compact)] + #[diplomat::rust_link(icu::normalizer::NormalizerError, Enum, compact)] + #[diplomat::rust_link(icu::plurals::PluralsError, Enum, compact)] + #[diplomat::rust_link(icu::properties::PropertiesError, Enum, compact)] + #[diplomat::rust_link(icu::provider::DataError, Struct, compact)] + #[diplomat::rust_link(icu::provider::DataErrorKind, Enum, compact)] + #[diplomat::rust_link(icu::segmenter::SegmenterError, Enum, compact)] + #[diplomat::rust_link(icu::timezone::TimeZoneError, Enum, compact)] + pub enum ICU4XError { + // general errors + /// The error is not currently categorized as ICU4XError. + /// Please file a bug + UnknownError = 0x00, + /// An error arising from writing to a string + /// Typically found when not enough space is allocated + /// Most APIs that return a string may return this error + WriteableError = 0x01, + // Some input was out of bounds + OutOfBoundsError = 0x02, + + // general data errors + // See DataError + DataMissingDataKeyError = 0x1_00, + DataMissingVariantError = 0x1_01, + DataMissingLocaleError = 0x1_02, + DataNeedsVariantError = 0x1_03, + DataNeedsLocaleError = 0x1_04, + DataExtraneousLocaleError = 0x1_05, + DataFilteredResourceError = 0x1_06, + DataMismatchedTypeError = 0x1_07, + DataMissingPayloadError = 0x1_08, + DataInvalidStateError = 0x1_09, + DataCustomError = 0x1_0A, + DataIoError = 0x1_0B, + DataUnavailableBufferFormatError = 0x1_0C, + DataMismatchedAnyBufferError = 0x1_0D, + + // locale errors + /// The subtag being requested was not set + LocaleUndefinedSubtagError = 0x2_00, + /// The locale or subtag string failed to parse + LocaleParserLanguageError = 0x2_01, + LocaleParserSubtagError = 0x2_02, + LocaleParserExtensionError = 0x2_03, + + // data struct errors + /// Attempted to construct an invalid data struct + DataStructValidityError = 0x3_00, + + // property errors + PropertyUnknownScriptIdError = 0x4_00, + PropertyUnknownGeneralCategoryGroupError = 0x4_01, + PropertyUnexpectedPropertyNameError = 0x4_02, + + // fixed_decimal errors + FixedDecimalLimitError = 0x5_00, + FixedDecimalSyntaxError = 0x5_01, + + // plural errors + PluralsParserError = 0x6_00, + + // datetime errors + CalendarParseError = 0x7_00, + CalendarOverflowError = 0x7_01, + CalendarUnderflowError = 0x7_02, + CalendarOutOfRangeError = 0x7_03, + CalendarUnknownEraError = 0x7_04, + CalendarUnknownMonthCodeError = 0x7_05, + CalendarMissingInputError = 0x7_06, + CalendarUnknownKindError = 0x7_07, + CalendarMissingError = 0x7_08, + + // datetime format errors + DateTimePatternError = 0x8_00, + DateTimeMissingInputFieldError = 0x8_01, + DateTimeSkeletonError = 0x8_02, + DateTimeUnsupportedFieldError = 0x8_03, + DateTimeUnsupportedOptionsError = 0x8_04, + DateTimeMissingWeekdaySymbolError = 0x8_05, + DateTimeMissingMonthSymbolError = 0x8_06, + DateTimeFixedDecimalError = 0x8_07, + DateTimeMismatchedCalendarError = 0x8_08, + + // tinystr errors + TinyStrTooLargeError = 0x9_00, + TinyStrContainsNullError = 0x9_01, + TinyStrNonAsciiError = 0x9_02, + + // timezone errors + TimeZoneOffsetOutOfBoundsError = 0xA_00, + TimeZoneInvalidOffsetError = 0xA_01, + TimeZoneMissingInputError = 0xA_02, + TimeZoneInvalidIdError = 0xA_03, + + // normalizer errors + NormalizerFutureExtensionError = 0xB_00, + NormalizerValidationError = 0xB_01, + } +} + +impl ICU4XError { + #[cfg(feature = "logging")] + #[inline] + pub(crate) fn log_original<T: core::fmt::Display + ?Sized>(self, e: &T) -> Self { + use core::any; + log::warn!( + "Returning ICU4XError::{:?} based on original {}: {}", + self, + any::type_name::<T>(), + e + ); + self + } + + #[cfg(not(feature = "logging"))] + #[inline] + pub(crate) fn log_original<T: core::fmt::Display + ?Sized>(self, _e: &T) -> Self { + self + } +} + +impl From<fmt::Error> for ICU4XError { + fn from(e: fmt::Error) -> Self { + ICU4XError::WriteableError.log_original(&e) + } +} + +impl From<DataError> for ICU4XError { + fn from(e: DataError) -> Self { + match e.kind { + DataErrorKind::MissingDataKey => ICU4XError::DataMissingDataKeyError, + DataErrorKind::MissingLocale => ICU4XError::DataMissingLocaleError, + DataErrorKind::NeedsLocale => ICU4XError::DataNeedsLocaleError, + DataErrorKind::ExtraneousLocale => ICU4XError::DataExtraneousLocaleError, + DataErrorKind::FilteredResource => ICU4XError::DataFilteredResourceError, + DataErrorKind::MismatchedType(..) => ICU4XError::DataMismatchedTypeError, + DataErrorKind::MissingPayload => ICU4XError::DataMissingPayloadError, + DataErrorKind::InvalidState => ICU4XError::DataInvalidStateError, + DataErrorKind::Custom => ICU4XError::DataCustomError, + #[cfg(all( + feature = "provider_fs", + not(any(target_arch = "wasm32", target_os = "none")) + ))] + DataErrorKind::Io(..) => ICU4XError::DataIoError, + // datagen only + // DataErrorKind::MissingSourceData(..) => .., + DataErrorKind::UnavailableBufferFormat(..) => { + ICU4XError::DataUnavailableBufferFormatError + } + _ => ICU4XError::UnknownError, + } + .log_original(&e) + } +} + +#[cfg(feature = "icu_collator")] +impl From<CollatorError> for ICU4XError { + fn from(e: CollatorError) -> Self { + match e { + CollatorError::NotFound => ICU4XError::DataMissingPayloadError, + CollatorError::MalformedData => ICU4XError::DataInvalidStateError, + CollatorError::Data(_) => ICU4XError::DataIoError, + _ => ICU4XError::DataIoError, + } + .log_original(&e) + } +} + +#[cfg(feature = "icu_properties")] +impl From<PropertiesError> for ICU4XError { + fn from(e: PropertiesError) -> Self { + match e { + PropertiesError::PropDataLoad(e) => e.into(), + PropertiesError::UnknownScriptId(..) => ICU4XError::PropertyUnknownScriptIdError, + PropertiesError::UnknownGeneralCategoryGroup(..) => { + ICU4XError::PropertyUnknownGeneralCategoryGroupError + } + PropertiesError::UnexpectedPropertyName => { + ICU4XError::PropertyUnexpectedPropertyNameError + } + _ => ICU4XError::UnknownError, + } + .log_original(&e) + } +} + +#[cfg(any( + feature = "icu_datetime", + feature = "icu_timezone", + feature = "icu_calendar" +))] +impl From<CalendarError> for ICU4XError { + fn from(e: CalendarError) -> Self { + match e { + CalendarError::Parse => ICU4XError::CalendarParseError, + CalendarError::Overflow { field: _, max: _ } => ICU4XError::CalendarOverflowError, + CalendarError::Underflow { field: _, min: _ } => ICU4XError::CalendarUnderflowError, + CalendarError::OutOfRange => ICU4XError::CalendarOutOfRangeError, + CalendarError::UnknownEra(..) => ICU4XError::CalendarUnknownEraError, + CalendarError::UnknownMonthCode(..) => ICU4XError::CalendarUnknownMonthCodeError, + CalendarError::MissingInput(_) => ICU4XError::CalendarMissingInputError, + CalendarError::UnknownAnyCalendarKind(_) => ICU4XError::CalendarUnknownKindError, + CalendarError::MissingCalendar => ICU4XError::CalendarMissingError, + CalendarError::Data(e) => e.into(), + _ => ICU4XError::UnknownError, + } + .log_original(&e) + } +} + +#[cfg(feature = "icu_datetime")] +impl From<DateTimeError> for ICU4XError { + fn from(e: DateTimeError) -> Self { + match e { + DateTimeError::Pattern(_) => ICU4XError::DateTimePatternError, + DateTimeError::Format(err) => err.into(), + DateTimeError::Data(err) => err.into(), + DateTimeError::MissingInputField(_) => ICU4XError::DateTimeMissingInputFieldError, + // TODO(#1324): Add back skeleton errors + // DateTimeFormatterError::Skeleton(_) => ICU4XError::DateTimeFormatSkeletonError, + DateTimeError::UnsupportedField(_) => ICU4XError::DateTimeUnsupportedFieldError, + DateTimeError::UnsupportedOptions => ICU4XError::DateTimeUnsupportedOptionsError, + DateTimeError::PluralRules(err) => err.into(), + DateTimeError::DateTimeInput(err) => err.into(), + DateTimeError::MissingWeekdaySymbol(_) => ICU4XError::DateTimeMissingWeekdaySymbolError, + DateTimeError::MissingMonthSymbol(_) => ICU4XError::DateTimeMissingMonthSymbolError, + DateTimeError::FixedDecimal => ICU4XError::DateTimeFixedDecimalError, + DateTimeError::FixedDecimalFormatter(err) => err.into(), + DateTimeError::MismatchedAnyCalendar(_, _) => { + ICU4XError::DateTimeMismatchedCalendarError + } + _ => ICU4XError::UnknownError, + } + .log_original(&e) + } +} + +#[cfg(feature = "icu_decimal")] +impl From<FixedDecimalError> for ICU4XError { + fn from(e: FixedDecimalError) -> Self { + match e { + FixedDecimalError::Limit => ICU4XError::FixedDecimalLimitError, + FixedDecimalError::Syntax => ICU4XError::FixedDecimalSyntaxError, + _ => ICU4XError::UnknownError, + } + .log_original(&e) + } +} + +#[cfg(any(feature = "icu_plurals", feature = "icu_datetime"))] +impl From<PluralsError> for ICU4XError { + fn from(e: PluralsError) -> Self { + match e { + PluralsError::Data(e) => e.into(), + _ => ICU4XError::UnknownError, + } + .log_original(&e) + } +} + +#[cfg(any(feature = "icu_decimal", feature = "icu_datetime"))] +impl From<DecimalError> for ICU4XError { + fn from(e: DecimalError) -> Self { + match e { + DecimalError::Data(e) => e.into(), + _ => ICU4XError::UnknownError, + } + .log_original(&e) + } +} + +#[cfg(feature = "icu_locid_transform")] +impl From<LocaleTransformError> for ICU4XError { + fn from(e: LocaleTransformError) -> Self { + match e { + LocaleTransformError::Data(e) => e.into(), + _ => ICU4XError::UnknownError, + } + .log_original(&e) + } +} + +#[cfg(feature = "icu_segmenter")] +impl From<SegmenterError> for ICU4XError { + fn from(e: SegmenterError) -> Self { + match e { + SegmenterError::Data(e) => e.into(), + _ => ICU4XError::UnknownError, + } + .log_original(&e) + } +} + +#[cfg(feature = "icu_list")] +impl From<ListError> for ICU4XError { + fn from(e: ListError) -> Self { + match e { + ListError::Data(e) => e.into(), + _ => ICU4XError::UnknownError, + } + .log_original(&e) + } +} + +impl From<ParserError> for ICU4XError { + fn from(e: ParserError) -> Self { + match e { + ParserError::InvalidLanguage => ICU4XError::LocaleParserLanguageError, + ParserError::InvalidSubtag => ICU4XError::LocaleParserSubtagError, + ParserError::InvalidExtension => ICU4XError::LocaleParserExtensionError, + _ => ICU4XError::UnknownError, + } + .log_original(&e) + } +} + +impl From<TinyStrError> for ICU4XError { + fn from(e: TinyStrError) -> Self { + match e { + TinyStrError::TooLarge { .. } => ICU4XError::TinyStrTooLargeError, + TinyStrError::ContainsNull => ICU4XError::TinyStrContainsNullError, + TinyStrError::NonAscii => ICU4XError::TinyStrNonAsciiError, + _ => ICU4XError::UnknownError, + } + .log_original(&e) + } +} + +#[cfg(any(feature = "icu_timezone", feature = "icu_datetime"))] +impl From<TimeZoneError> for ICU4XError { + fn from(e: TimeZoneError) -> Self { + match e { + TimeZoneError::OffsetOutOfBounds => ICU4XError::TimeZoneOffsetOutOfBoundsError, + TimeZoneError::InvalidOffset => ICU4XError::TimeZoneInvalidOffsetError, + TimeZoneError::Data(err) => err.into(), + _ => ICU4XError::UnknownError, + } + .log_original(&e) + } +} + +#[cfg(feature = "icu_normalizer")] +impl From<NormalizerError> for ICU4XError { + fn from(e: NormalizerError) -> Self { + match e { + NormalizerError::FutureExtension => ICU4XError::NormalizerFutureExtensionError, + NormalizerError::ValidationError => ICU4XError::NormalizerValidationError, + NormalizerError::Data(err) => err.into(), + _ => ICU4XError::UnknownError, + } + .log_original(&e) + } +} |