diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:18:32 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:18:32 +0000 |
commit | 4547b622d8d29df964fa2914213088b148c498fc (patch) | |
tree | 9fc6b25f3c3add6b745be9a2400a6e96140046e9 /vendor/icu_provider/src/error.rs | |
parent | Releasing progress-linux version 1.66.0+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-4547b622d8d29df964fa2914213088b148c498fc.tar.xz rustc-4547b622d8d29df964fa2914213088b148c498fc.zip |
Merging upstream version 1.67.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/icu_provider/src/error.rs')
-rw-r--r-- | vendor/icu_provider/src/error.rs | 267 |
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() + } +} |