macro_rules! impl_dynamic_data_provider { ($provider:ty, $arms:tt, $one:path, $($rest:path),+) => { ... }; ($provider:ty, { $($ident:ident = $marker:path => $struct_m:ty),+, $(_ => $struct_d:ty,)?}, $dyn_m:ty) => { ... }; ($provider:ty, [ $($(#[$cfg:meta])? $struct_m:ty),+, ], $dyn_m:path) => { ... }; }
Expand description
Implements DynamicDataProvider
for a marker type S
on a type that already implements
DynamicDataProvider
or DataProvider
for one or more M
, where M
is a concrete type
that is convertible to S
via UpcastDataPayload
.
Use this macro to add support to your data provider for:
AnyPayload
if your provider can return typed objects asAny
.
§Wrapping DataProvider
If your type implements DataProvider
, pass a list of markers as the second argument.
This results in a DynamicDataProvider
that delegates to a specific marker if the marker
matches or else returns DataErrorKind::MarkerNotFound
.
use icu_provider::prelude::*;
use icu_provider::hello_world::*;
use icu_provider::marker::NeverMarker;
use icu_locale_core::langid;
// Implement DynamicDataProvider<AnyMarker> on HelloWorldProvider: DataProvider<HelloWorldV1Marker>
icu_provider::dynutil::impl_dynamic_data_provider!(HelloWorldProvider, [HelloWorldV1Marker,], AnyMarker);
// Successful because the marker matches:
HelloWorldProvider.load_data(HelloWorldV1Marker::INFO, DataRequest {
id: DataIdentifierBorrowed::for_locale(&langid!("de").into()),
..Default::default()
}).unwrap();
// MissingDataMarker error as the marker does not match:
assert_eq!(
HelloWorldProvider.load_data(DummyMarker::INFO, DataRequest {
id: DataIdentifierBorrowed::for_locale(&langid!("de").into()),
..Default::default()
}).unwrap_err().kind,
DataErrorKind::MarkerNotFound,
);
§Wrapping DynamicDataProvider
It is also possible to wrap a DynamicDataProvider
to create another DynamicDataProvider
. To do this,
pass a match-like statement for markers as the second argument:
use icu_provider::prelude::*;
use icu_provider::hello_world::*;
use icu_provider::any::*;
use icu_locale_core::langid;
// Implement DataProvider<AnyMarker> on HelloWorldProvider: DynamicDataProvider<HelloWorldV1Marker>
icu_provider::dynutil::impl_dynamic_data_provider!(HelloWorldProvider, {
// Match HelloWorldV1Marker::INFO and delegate to DynamicDataProvider<HelloWorldV1Marker>.
HW = HelloWorldV1Marker::INFO => HelloWorldV1Marker,
// Send the wildcard match also to DynamicDataProvider<HelloWorldV1Marker>.
_ => HelloWorldV1Marker,
}, AnyMarker);
// Successful because the marker matches:
HelloWorldProvider.as_any_provider().load_any(HelloWorldV1Marker::INFO, DataRequest {
id: DataIdentifierBorrowed::for_locale(&langid!("de").into()),
..Default::default()
}).unwrap();
// Because of the wildcard, any marker actually works:
struct DummyMarker;
impl DynamicDataMarker for DummyMarker {
type DataStruct = <HelloWorldV1Marker as DynamicDataMarker>::DataStruct;
}
impl DataMarker for DummyMarker {
const INFO: DataMarkerInfo = DataMarkerInfo::from_path(icu_provider::marker::data_marker_path!("dummy@1"));
}
HelloWorldProvider.as_any_provider().load_any(DummyMarker::INFO, DataRequest {
id: DataIdentifierBorrowed::for_locale(&langid!("de").into()),
..Default::default()
}).unwrap();