1 | // This file is part of ICU4X. For terms of use, please see the file |
2 | // called LICENSE at the top level of the ICU4X source tree |
3 | // (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). |
4 | |
5 | //! Helpers for switching between multiple providers. |
6 | |
7 | use icu_provider::prelude::*; |
8 | |
9 | #[cfg (feature = "datagen" )] |
10 | use icu_provider::datagen; |
11 | |
12 | /// A provider that is one of two types determined at runtime. |
13 | /// |
14 | /// Data provider traits implemented by both `P0` and `P1` are implemented on |
15 | /// `EitherProvider<P0, P1>`. |
16 | #[allow (clippy::exhaustive_enums)] // this is stable |
17 | #[derive (Debug)] |
18 | pub enum EitherProvider<P0, P1> { |
19 | /// A value of type `P0`. |
20 | A(P0), |
21 | /// A value of type `P1`. |
22 | B(P1), |
23 | } |
24 | |
25 | impl<P0: AnyProvider, P1: AnyProvider> AnyProvider for EitherProvider<P0, P1> { |
26 | #[inline ] |
27 | fn load_any(&self, key: DataKey, req: DataRequest) -> Result<AnyResponse, DataError> { |
28 | use EitherProvider::*; |
29 | match self { |
30 | A(p: &P0) => p.load_any(key, req), |
31 | B(p: &P1) => p.load_any(key, req), |
32 | } |
33 | } |
34 | } |
35 | |
36 | impl<P0: BufferProvider, P1: BufferProvider> BufferProvider for EitherProvider<P0, P1> { |
37 | #[inline ] |
38 | fn load_buffer( |
39 | &self, |
40 | key: DataKey, |
41 | req: DataRequest, |
42 | ) -> Result<DataResponse<BufferMarker>, DataError> { |
43 | use EitherProvider::*; |
44 | match self { |
45 | A(p: &P0) => p.load_buffer(key, req), |
46 | B(p: &P1) => p.load_buffer(key, req), |
47 | } |
48 | } |
49 | } |
50 | |
51 | impl<M: DataMarker, P0: DynamicDataProvider<M>, P1: DynamicDataProvider<M>> DynamicDataProvider<M> |
52 | for EitherProvider<P0, P1> |
53 | { |
54 | #[inline ] |
55 | fn load_data(&self, key: DataKey, req: DataRequest) -> Result<DataResponse<M>, DataError> { |
56 | use EitherProvider::*; |
57 | match self { |
58 | A(p: &P0) => p.load_data(key, req), |
59 | B(p: &P1) => p.load_data(key, req), |
60 | } |
61 | } |
62 | } |
63 | |
64 | impl<M: KeyedDataMarker, P0: DataProvider<M>, P1: DataProvider<M>> DataProvider<M> |
65 | for EitherProvider<P0, P1> |
66 | { |
67 | #[inline ] |
68 | fn load(&self, req: DataRequest) -> Result<DataResponse<M>, DataError> { |
69 | use EitherProvider::*; |
70 | match self { |
71 | A(p: &P0) => p.load(req), |
72 | B(p: &P1) => p.load(req), |
73 | } |
74 | } |
75 | } |
76 | |
77 | #[cfg (feature = "datagen" )] |
78 | impl< |
79 | M: DataMarker, |
80 | P0: datagen::IterableDynamicDataProvider<M>, |
81 | P1: datagen::IterableDynamicDataProvider<M>, |
82 | > datagen::IterableDynamicDataProvider<M> for EitherProvider<P0, P1> |
83 | { |
84 | #[inline ] |
85 | fn supported_locales_for_key( |
86 | &self, |
87 | key: DataKey, |
88 | ) -> Result<alloc::vec::Vec<DataLocale>, DataError> { |
89 | use EitherProvider::*; |
90 | match self { |
91 | A(p) => p.supported_locales_for_key(key), |
92 | B(p) => p.supported_locales_for_key(key), |
93 | } |
94 | } |
95 | } |
96 | |
97 | #[cfg (feature = "datagen" )] |
98 | impl< |
99 | M: KeyedDataMarker, |
100 | P0: datagen::IterableDataProvider<M>, |
101 | P1: datagen::IterableDataProvider<M>, |
102 | > datagen::IterableDataProvider<M> for EitherProvider<P0, P1> |
103 | { |
104 | #[inline ] |
105 | fn supported_locales(&self) -> Result<alloc::vec::Vec<DataLocale>, DataError> { |
106 | use EitherProvider::*; |
107 | match self { |
108 | A(p) => p.supported_locales(), |
109 | B(p) => p.supported_locales(), |
110 | } |
111 | } |
112 | } |
113 | |