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:

§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();