Source code

Revision control

Copy as Markdown

Other Tools

// 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
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 = "experimental_components")]
use icu_experimental::units::ConversionError;
#[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;
#[diplomat::bridge]
pub mod ffi {
use alloc::boxed::Box;
#[derive(Debug, 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::datetime::MismatchedCalendarError, Struct, hidden)]
#[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)]
#[diplomat::rust_link(icu_experimental::units::ConversionError, 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,
/// Input expected to be UTF-8 was ill-formed
Utf8Error = 0x03,
// 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,
// dead
// 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,
// Units errors
#[cfg(feature = "experimental_components")]
InvalidCldrUnitIdentifierError = 0x0C_00,
}
}
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)
}
}
impl From<core::str::Utf8Error> for ICU4XError {
fn from(_: core::str::Utf8Error) -> Self {
ICU4XError::Utf8Error
}
}
#[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,
ParserError::DuplicatedExtension => ICU4XError::LocaleParserExtensionError,
_ => 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)
}
}
#[cfg(feature = "experimental_components")]
impl From<ConversionError> for ICU4XError {
fn from(value: ConversionError) -> Self {
match value {
ConversionError::InvalidUnit => ICU4XError::InvalidCldrUnitIdentifierError,
_ => ICU4XError::UnknownError,
}
}
}