Skip to content

Commit

Permalink
DataError::allow_identifier_not_found helper (#5697)
Browse files Browse the repository at this point in the history
  • Loading branch information
robertbastian authored Oct 17, 2024
1 parent fc2c660 commit 4925a48
Show file tree
Hide file tree
Showing 11 changed files with 86 additions and 120 deletions.
39 changes: 15 additions & 24 deletions components/datetime/src/raw/neo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -353,20 +353,16 @@ impl TimePatternSelectionData {
// or if loading the explicit hour cycle fails, then load with the default hour cycle.
let mut maybe_payload = None;
if let Some(hour_cycle) = options.hour_cycle {
maybe_payload = match provider.load_bound(DataRequest {
id: DataIdentifierBorrowed::for_marker_attributes_and_locale(
components.with_hour_cycle(hour_cycle.into()).id_str(),
locale,
),
..Default::default()
}) {
Ok(response) => Some(response.payload),
Err(DataError {
kind: DataErrorKind::IdentifierNotFound,
..
}) => None,
Err(e) => return Err(e),
};
maybe_payload = provider
.load_bound(DataRequest {
id: DataIdentifierBorrowed::for_marker_attributes_and_locale(
components.with_hour_cycle(hour_cycle.into()).id_str(),
locale,
),
..Default::default()
})
.allow_identifier_not_found()?
.map(|r| r.payload);
}
let payload = match maybe_payload {
Some(payload) => payload,
Expand Down Expand Up @@ -523,21 +519,16 @@ impl DateTimeZonePatternSelectionData {
// TODO(#5387): load the patterns for custom hour cycles here
if let (Some(attributes), None) = (components.id_str(), options.hour_cycle) {
// Try loading an overlap pattern.
match OverlapPatternSelectionData::try_new_with_skeleton(
if let Some(overlap) = OverlapPatternSelectionData::try_new_with_skeleton(
// Note: overlap patterns are stored in the date provider
date_provider,
locale,
attributes,
options,
) {
Ok(overlap) => return Ok(Self::Overlap(overlap)),
Err(DataError {
kind: DataErrorKind::IdentifierNotFound,
..
}) => {
// fall through
}
Err(e) => return Err(e),
)
.allow_identifier_not_found()?
{
return Ok(Self::Overlap(overlap));
}
}
let date = DatePatternSelectionData::try_new_with_skeleton(
Expand Down
28 changes: 12 additions & 16 deletions components/segmenter/src/complex/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -332,22 +332,18 @@ fn try_load<M: DataMarker, P: DataProvider<M> + ?Sized>(
provider: &P,
model: &'static DataMarkerAttributes,
) -> Result<Option<DataPayload<M>>, DataError> {
match provider.load(DataRequest {
id: DataIdentifierBorrowed::for_marker_attributes(model),
metadata: {
let mut m = DataRequestMetadata::default();
m.silent = true;
m.attributes_prefix_match = true;
m
},
}) {
Ok(response) => Ok(Some(response.payload)),
Err(DataError {
kind: DataErrorKind::IdentifierNotFound,
..
}) => Ok(None),
Err(e) => Err(e),
}
provider
.load(DataRequest {
id: DataIdentifierBorrowed::for_marker_attributes(model),
metadata: {
let mut m = DataRequestMetadata::default();
m.silent = true;
m.attributes_prefix_match = true;
m
},
})
.allow_identifier_not_found()
.map(|r| r.map(|r| r.payload))
}

/// Return UTF-16 segment offset array using dictionary or lstm segmenter.
Expand Down
12 changes: 4 additions & 8 deletions components/segmenter/src/sentence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,14 +194,10 @@ impl SentenceSegmenter {
metadata
},
};
match provider.load(req) {
Ok(response) => Some(response.payload),
Err(DataError {
kind: DataErrorKind::IdentifierNotFound,
..
}) => None,
Err(e) => return Err(e),
}
provider
.load(req)
.allow_identifier_not_found()?
.map(|r| r.payload)
} else {
None
};
Expand Down
36 changes: 12 additions & 24 deletions components/segmenter/src/word.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,14 +290,10 @@ impl WordSegmenter {
metadata
},
};
match provider.load(req) {
Ok(response) => Some(response.payload),
Err(DataError {
kind: DataErrorKind::IdentifierNotFound,
..
}) => None,
Err(e) => return Err(e),
}
provider
.load(req)
.allow_identifier_not_found()?
.map(|r| r.payload)
} else {
None
},
Expand Down Expand Up @@ -416,14 +412,10 @@ impl WordSegmenter {
metadata
},
};
match provider.load(req) {
Ok(response) => Some(response.payload),
Err(DataError {
kind: DataErrorKind::IdentifierNotFound,
..
}) => None,
Err(e) => return Err(e),
}
provider
.load(req)
.allow_identifier_not_found()?
.map(|r| r.payload)
} else {
None
},
Expand Down Expand Up @@ -534,14 +526,10 @@ impl WordSegmenter {
metadata
},
};
match provider.load(req) {
Ok(response) => Some(response.payload),
Err(DataError {
kind: DataErrorKind::IdentifierNotFound,
..
}) => None,
Err(e) => return Err(e),
}
provider
.load(req)
.allow_identifier_not_found()?
.map(|r| r.payload)
} else {
None
},
Expand Down
35 changes: 18 additions & 17 deletions provider/adapters/src/fallback/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

//! A data provider wrapper that performs locale fallback.
use crate::helpers::result_is_err_missing_locale;
#[doc(no_inline)]
pub use icu_locale::LocaleFallbacker;
use icu_provider::prelude::*;
Expand Down Expand Up @@ -157,23 +156,25 @@ impl<P> LocaleFallbackProvider<P> {
),
..base_req
});
if !result_is_err_missing_locale(&result) {
return result
.map(|mut res| {
f2(&mut res).locale = Some(fallback_iterator.take());
res
})

match result.allow_identifier_not_found() {
Ok(Some(mut result)) => {
f2(&mut result).locale = Some(fallback_iterator.take());
return Ok(result);
}
Ok(None) => {
// If we just checked und, break out of the loop.
if fallback_iterator.get().is_default() {
break;
}
fallback_iterator.step();
}
Err(e) => {
// Log the original request rather than the fallback request
.map_err(|e| {
base_req.metadata.silent = base_silent;
e.with_req(marker, base_req)
});
}
// If we just checked und, break out of the loop.
if fallback_iterator.get().is_default() {
break;
}
fallback_iterator.step();
base_req.metadata.silent = base_silent;
return Err(e.with_req(marker, base_req));
}
};
}
base_req.metadata.silent = base_silent;
Err(DataErrorKind::IdentifierNotFound.with_req(marker, base_req))
Expand Down
8 changes: 1 addition & 7 deletions provider/adapters/src/fork/predicates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,12 +128,6 @@ impl ForkByErrorPredicate for IdentifierNotFoundPredicate {

#[inline]
fn test(&self, _: DataMarkerInfo, _: Option<DataRequest>, err: DataError) -> bool {
matches!(
err,
DataError {
kind: DataErrorKind::IdentifierNotFound,
..
}
)
Err::<(), _>(err).allow_identifier_not_found().is_ok()
}
}
15 changes: 0 additions & 15 deletions provider/adapters/src/helpers.rs

This file was deleted.

1 change: 0 additions & 1 deletion provider/adapters/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,3 @@ pub mod fallback;
pub mod filter;
pub mod fixed;
pub mod fork;
mod helpers;
19 changes: 19 additions & 0 deletions provider/core/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -261,3 +261,22 @@ impl From<std::io::Error> for DataError {
DataErrorKind::Io(e.kind()).into_error()
}
}

/// Extension trait for `Result<T, DataError>`.
pub trait ResultDataError<T>: Sized {
/// Propagates all errors other than [`DataErrorKind::IdentifierNotFound`], and returns `None` in that case.
fn allow_identifier_not_found(self) -> Result<Option<T>, DataError>;
}

impl<T> ResultDataError<T> for Result<T, DataError> {
fn allow_identifier_not_found(self) -> Result<Option<T>, DataError> {
match self {
Ok(t) => Ok(Some(t)),
Err(DataError {
kind: DataErrorKind::IdentifierNotFound,
..
}) => Ok(None),
Err(e) => Err(e),
}
}
}
4 changes: 2 additions & 2 deletions provider/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ pub use data_provider::{
};

mod error;
pub use error::{DataError, DataErrorKind};
pub use error::{DataError, DataErrorKind, ResultDataError};

#[cfg(feature = "macros")]
pub use icu_provider_macros::data_struct;
Expand Down Expand Up @@ -172,7 +172,7 @@ pub mod prelude {
BoundDataProvider, DataError, DataErrorKind, DataLocale, DataMarker, DataMarkerAttributes,
DataMarkerInfo, DataPayload, DataProvider, DataRequest, DataRequestMetadata, DataResponse,
DataResponseMetadata, DryDataProvider, DynamicDataMarker, DynamicDataProvider,
DynamicDryDataProvider, IterableDataProvider, IterableDynamicDataProvider,
DynamicDryDataProvider, IterableDataProvider, IterableDynamicDataProvider, ResultDataError,
};

#[doc(no_inline)]
Expand Down
9 changes: 3 additions & 6 deletions provider/export/src/export_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,19 +93,16 @@ impl ExportDriver {
),
metadata,
};
match provider.load_data(marker, req) {
Ok(data_response) => {
match provider.load_data(marker, req).allow_identifier_not_found() {
Ok(Some(data_response)) => {
if let Some(iter) = locale_iter.as_ref() {
if iter.get().is_default() && !id.locale.is_default() {
log::debug!("Falling back to und: {marker:?}/{id}");
}
}
return Some(Ok(data_response.payload));
}
Err(DataError {
kind: DataErrorKind::IdentifierNotFound,
..
}) => {
Ok(None) => {
if let Some(iter) = locale_iter.as_mut() {
if iter.get().is_default() {
log::debug!("Could not find data for: {marker:?}/{id}");
Expand Down

0 comments on commit 4925a48

Please sign in to comment.