summaryrefslogtreecommitdiffstats
path: root/vendor/icu_provider/src/error.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/icu_provider/src/error.rs')
-rw-r--r--vendor/icu_provider/src/error.rs267
1 files changed, 267 insertions, 0 deletions
diff --git a/vendor/icu_provider/src/error.rs b/vendor/icu_provider/src/error.rs
new file mode 100644
index 000000000..39bd1d0bb
--- /dev/null
+++ b/vendor/icu_provider/src/error.rs
@@ -0,0 +1,267 @@
+// 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 crate::buf::BufferFormat;
+use crate::prelude::*;
+use core::fmt;
+use displaydoc::Display;
+
+/// A list specifying general categories of data provider error.
+///
+/// Errors may be caused either by a malformed request or by the data provider
+/// not being able to fulfill a well-formed request.
+#[derive(Clone, Copy, Eq, PartialEq, Display, Debug)]
+#[non_exhaustive]
+pub enum DataErrorKind {
+ /// No data for the provided resource key.
+ #[displaydoc("Missing data for key")]
+ MissingDataKey,
+
+ /// There is data for the key, but not for this particular locale.
+ #[displaydoc("Missing data for locale")]
+ MissingLocale,
+
+ /// The request should include a locale.
+ #[displaydoc("Request needs a locale")]
+ NeedsLocale,
+
+ /// The request should not contain a locale.
+ #[displaydoc("Request has an extraneous locale")]
+ ExtraneousLocale,
+
+ /// The resource was blocked by a filter. The resource may or may not be available.
+ #[displaydoc("Resource blocked by filter")]
+ FilteredResource,
+
+ /// The generic type parameter does not match the TypeId. The expected type name is stored
+ /// as context when this error is returned.
+ #[displaydoc("Mismatched types: tried to downcast with {0}, but actual type is different")]
+ MismatchedType(&'static str),
+
+ /// The payload is missing. This is usually caused by a previous error.
+ #[displaydoc("Missing payload")]
+ MissingPayload,
+
+ /// A data provider object was given to an operation in an invalid state.
+ #[displaydoc("Invalid state")]
+ InvalidState,
+
+ /// An unspecified error occurred, such as a Serde error.
+ ///
+ /// Check debug logs for potentially more information.
+ #[displaydoc("Custom")]
+ Custom,
+
+ /// An error occurred while accessing a system resource.
+ #[displaydoc("I/O error: {0:?}")]
+ #[cfg(feature = "std")]
+ Io(std::io::ErrorKind),
+
+ /// An unspecified data source containing the required data is unavailable.
+ #[displaydoc("Missing source data")]
+ #[cfg(feature = "datagen")]
+ MissingSourceData,
+
+ /// An error indicating that the desired buffer format is not available. This usually
+ /// means that a required feature was not enabled
+ #[displaydoc("Unavailable buffer format: {0:?} (does icu_provider need to be compiled with an additional feature?)")]
+ UnavailableBufferFormat(BufferFormat),
+}
+
+/// The error type for ICU4X data provider operations.
+///
+/// To create one of these, either start with a [`DataErrorKind`] or use [`DataError::custom()`].
+///
+/// # Example
+///
+/// Create a NeedsLocale error and attach a data request for context:
+///
+/// ```no_run
+/// # use icu_provider::prelude::*;
+/// let key: DataKey = unimplemented!();
+/// let req: DataRequest = unimplemented!();
+/// DataErrorKind::NeedsLocale.with_req(key, req);
+/// ```
+///
+/// Create a named custom error:
+///
+/// ```
+/// # use icu_provider::prelude::*;
+/// DataError::custom("This is an example error");
+/// ```
+#[derive(Clone, Copy, Eq, PartialEq, Debug)]
+#[non_exhaustive]
+pub struct DataError {
+ /// Broad category of the error.
+ pub kind: DataErrorKind,
+
+ /// The data key of the request, if available.
+ pub key: Option<DataKey>,
+
+ /// Additional context, if available.
+ pub str_context: Option<&'static str>,
+}
+
+impl fmt::Display for DataError {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "ICU4X data error")?;
+ if self.kind != DataErrorKind::Custom {
+ write!(f, ": {}", self.kind)?;
+ }
+ if let Some(key) = self.key {
+ write!(f, " (key: {})", key)?;
+ }
+ if let Some(str_context) = self.str_context {
+ write!(f, ": {}", str_context)?;
+ }
+ Ok(())
+ }
+}
+
+impl DataErrorKind {
+ /// Converts this DataErrorKind into a DataError.
+ ///
+ /// If possible, you should attach context using a `with_` function.
+ #[inline]
+ pub const fn into_error(self) -> DataError {
+ DataError {
+ kind: self,
+ key: None,
+ str_context: None,
+ }
+ }
+
+ /// Creates a DataError with a resource key context.
+ #[inline]
+ pub const fn with_key(self, key: DataKey) -> DataError {
+ self.into_error().with_key(key)
+ }
+
+ /// Creates a DataError with a string context.
+ #[inline]
+ pub const fn with_str_context(self, context: &'static str) -> DataError {
+ self.into_error().with_str_context(context)
+ }
+
+ /// Creates a DataError with a type name context.
+ #[inline]
+ pub fn with_type_context<T>(self) -> DataError {
+ self.into_error().with_type_context::<T>()
+ }
+
+ /// Creates a DataError with a request context.
+ #[inline]
+ pub fn with_req(self, key: DataKey, req: DataRequest) -> DataError {
+ self.into_error().with_req(key, req)
+ }
+}
+
+impl DataError {
+ /// Returns a new, empty DataError with kind Custom and a string error message.
+ #[inline]
+ pub const fn custom(str_context: &'static str) -> Self {
+ Self {
+ kind: DataErrorKind::Custom,
+ key: None,
+ str_context: Some(str_context),
+ }
+ }
+
+ /// Sets the resource key of a DataError, returning a modified error.
+ #[inline]
+ pub const fn with_key(self, key: DataKey) -> Self {
+ Self {
+ kind: self.kind,
+ key: Some(key),
+ str_context: self.str_context,
+ }
+ }
+
+ /// Sets the string context of a DataError, returning a modified error.
+ #[inline]
+ pub const fn with_str_context(self, context: &'static str) -> Self {
+ Self {
+ kind: self.kind,
+ key: self.key,
+ str_context: Some(context),
+ }
+ }
+
+ /// Sets the string context of a DataError to the given type name, returning a modified error.
+ #[inline]
+ pub fn with_type_context<T>(self) -> Self {
+ self.with_str_context(core::any::type_name::<T>())
+ }
+
+ /// Logs the data error with the given request, returning an error containing the resource key.
+ ///
+ /// If the "log_error_context" feature is enabled, this logs the whole request. Either way,
+ /// it returns an error with the resource key portion of the request as context.
+ #[cfg_attr(not(feature = "log_error_context"), allow(unused_variables))]
+ pub fn with_req(self, key: DataKey, req: DataRequest) -> Self {
+ // Don't write out a log for MissingDataKey since there is no context to add
+ #[cfg(feature = "log_error_context")]
+ if self.kind != DataErrorKind::MissingDataKey {
+ log::warn!("{} (key: {}, request: {})", self, key, req);
+ }
+ self.with_key(key)
+ }
+
+ /// Logs the data error with the given context, then return self.
+ ///
+ /// This does not modify the error, but if the "log_error_context" feature is enabled,
+ /// it will print out the context.
+ #[cfg(feature = "std")]
+ #[cfg_attr(not(feature = "log_error_context"), allow(unused_variables))]
+ pub fn with_path_context<P: AsRef<std::path::Path> + ?Sized>(self, path: &P) -> Self {
+ #[cfg(feature = "log_error_context")]
+ log::warn!("{} (path: {:?})", self, path.as_ref());
+ self
+ }
+
+ /// Logs the data error with the given context, then return self.
+ ///
+ /// This does not modify the error, but if the "log_error_context" feature is enabled,
+ /// it will print out the context.
+ #[cfg_attr(not(feature = "log_error_context"), allow(unused_variables))]
+ #[inline]
+ pub fn with_display_context<D: fmt::Display + ?Sized>(self, context: &D) -> Self {
+ #[cfg(feature = "log_error_context")]
+ log::warn!("{}: {}", self, context);
+ self
+ }
+
+ /// Logs the data error with the given context, then return self.
+ ///
+ /// This does not modify the error, but if the "log_error_context" feature is enabled,
+ /// it will print out the context.
+ #[cfg_attr(not(feature = "log_error_context"), allow(unused_variables))]
+ #[inline]
+ pub fn with_debug_context<D: fmt::Debug + ?Sized>(self, context: &D) -> Self {
+ #[cfg(feature = "log_error_context")]
+ log::warn!("{}: {:?}", self, context);
+ self
+ }
+
+ #[inline]
+ pub(crate) fn for_type<T>() -> DataError {
+ DataError {
+ kind: DataErrorKind::MismatchedType(core::any::type_name::<T>()),
+ key: None,
+ str_context: None,
+ }
+ }
+}
+
+#[cfg(feature = "std")]
+impl std::error::Error for DataError {}
+
+#[cfg(feature = "std")]
+impl From<std::io::Error> for DataError {
+ fn from(e: std::io::Error) -> Self {
+ #[cfg(feature = "log_error_context")]
+ log::warn!("I/O error: {}", e);
+ DataErrorKind::Io(e.kind()).into_error()
+ }
+}