icu4x
icu4x copied to clipboard
`DataProvider` for `ForkByKeyProvider`
Many of our APIs take ResourceProviders, but we don't currently have a way to combine two ResourceProviders into one that implements both.
Every provider is either an AnyProvider or a BufferProvider. We can currently freely combine providers given that they are in the same class. However, it would be useful if we could do it directly on ResourceProvider.
Not true. Data transformers, which are the motivation for this, aren't either, and neither is the StaticDataProvider that crabbake generates.
Data transformers and the CrabBake provider are both AnyProvider-compatible. They should use impl_dyn_provider! which adds the AnyProvider impl.
https://unicode-org.github.io/icu4x-docs/doc/icu_provider/index.html#types-of-data-providers
All nontrivial data providers can fit into one of two classes.
Type 1: Those whose data originates as structured Rust objects Type 2: Those whose data originates as unstructured [u8] buffers
Data transformers and the CrabBake provider are both AnyProvider-compatible. They should use impl_dyn_provider! which adds the AnyProvider impl.
I don't think that'd be right. If we generate a crabbake provider without a key that we need, we'd get a compile time error with ResourceProvider but a runtime error with AnyProvider.
Duplicate of #3935
Not sure it's a full duplicate; #3935 is for the specific case of provider::Baked whereas this is for the more general case of ForkByKeyProvider.
Thought: can something like this work?
struct ForkProvider<A, B> {
a: A,
b: B,
}
impl<M> DataProvider<M> for ForkProvider where A: DataProvider<M>, B: DataProvider<M> {
fn load() {
match type_id::<M> {
type_id::<Fork1> => self.a.load().upcast().downcast(),
type_id::<Fork2> => ...
type_id::<Fork3> => ...
_ => self.b.load()
}
}
}
@robertbastian noted that it only works if A and B all implement DataProvider<M> for the same types.
We could generate fake impls that always return a DataError, but that seems like a footgun.