]>
Commit | Line | Data |
---|---|---|
487cf647 FG |
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 | //! Data provider always serving the same struct. | |
6 | ||
7 | use icu_provider::prelude::*; | |
8 | use yoke::trait_hack::YokeTraitHack; | |
9 | use yoke::Yokeable; | |
10 | use zerofrom::ZeroFrom; | |
11 | ||
12 | /// A data provider that returns clones of a fixed type-erased payload. | |
13 | /// | |
14 | /// [`AnyPayloadProvider`] implements [`AnyProvider`], so it can be used in | |
15 | /// `*_with_any_provider` constructors across ICU4X. | |
16 | /// | |
17 | /// # Examples | |
18 | /// | |
19 | /// ``` | |
20 | /// use icu_provider::hello_world::*; | |
21 | /// use icu_provider::prelude::*; | |
22 | /// use icu_provider_adapters::any_payload::AnyPayloadProvider; | |
23 | /// use std::borrow::Cow; | |
24 | /// use writeable::assert_writeable_eq; | |
25 | /// | |
26 | /// let provider = | |
27 | /// AnyPayloadProvider::from_static::<HelloWorldV1Marker>(&HelloWorldV1 { | |
28 | /// message: Cow::Borrowed("custom hello world"), | |
29 | /// }); | |
30 | /// | |
31 | /// // Check that it works: | |
32 | /// let formatter = HelloWorldFormatter::try_new_with_any_provider( | |
33 | /// &provider, | |
34 | /// &icu_locid::Locale::UND.into(), | |
35 | /// ) | |
36 | /// .expect("key matches"); | |
37 | /// assert_writeable_eq!(formatter.format(), "custom hello world"); | |
38 | /// | |
39 | /// // Requests for invalid keys get MissingDataKey | |
40 | /// assert!(matches!( | |
41 | /// provider.load_any(icu_provider::data_key!("foo@1"), Default::default()), | |
42 | /// Err(DataError { | |
43 | /// kind: DataErrorKind::MissingDataKey, | |
44 | /// .. | |
45 | /// }) | |
46 | /// )) | |
47 | /// ``` | |
49aad941 | 48 | #[derive(Debug)] |
487cf647 FG |
49 | #[allow(clippy::exhaustive_structs)] // this type is stable |
50 | pub struct AnyPayloadProvider { | |
51 | /// The [`DataKey`] for which to provide data. All others will receive a | |
52 | /// [`DataErrorKind::MissingDataKey`]. | |
53 | key: DataKey, | |
54 | /// The [`AnyPayload`] to return on matching requests. | |
55 | data: AnyPayload, | |
56 | } | |
57 | ||
58 | impl AnyPayloadProvider { | |
59 | /// Creates an `AnyPayloadProvider` with an owned (allocated) payload of the given data. | |
49aad941 | 60 | pub fn from_owned<M: KeyedDataMarker>(data: M::Yokeable) -> Self |
487cf647 FG |
61 | where |
62 | M::Yokeable: icu_provider::MaybeSendSync, | |
63 | { | |
64 | Self::from_payload::<M>(DataPayload::from_owned(data)) | |
65 | } | |
66 | ||
67 | /// Creates an `AnyPayloadProvider` with a statically borrowed payload of the given data. | |
68 | pub fn from_static<M: KeyedDataMarker>(data: &'static M::Yokeable) -> Self { | |
69 | AnyPayloadProvider { | |
70 | key: M::KEY, | |
71 | data: AnyPayload::from_static_ref(data), | |
72 | } | |
73 | } | |
74 | ||
75 | /// Creates an `AnyPayloadProvider` from an existing [`DataPayload`]. | |
49aad941 | 76 | pub fn from_payload<M: KeyedDataMarker>(payload: DataPayload<M>) -> Self |
487cf647 FG |
77 | where |
78 | M::Yokeable: icu_provider::MaybeSendSync, | |
79 | { | |
80 | AnyPayloadProvider { | |
81 | key: M::KEY, | |
82 | data: payload.wrap_into_any_payload(), | |
83 | } | |
84 | } | |
85 | ||
86 | /// Creates an `AnyPayloadProvider` from an existing [`AnyPayload`]. | |
49aad941 | 87 | pub fn from_any_payload<M: KeyedDataMarker>(payload: AnyPayload) -> Self { |
487cf647 FG |
88 | AnyPayloadProvider { |
89 | key: M::KEY, | |
90 | data: payload, | |
91 | } | |
92 | } | |
93 | ||
94 | /// Creates an `AnyPayloadProvider` with the default (allocated) version of the data struct. | |
49aad941 | 95 | pub fn new_default<M: KeyedDataMarker>() -> Self |
487cf647 FG |
96 | where |
97 | M::Yokeable: Default, | |
98 | M::Yokeable: icu_provider::MaybeSendSync, | |
99 | { | |
100 | Self::from_owned::<M>(M::Yokeable::default()) | |
101 | } | |
102 | } | |
103 | ||
104 | impl AnyProvider for AnyPayloadProvider { | |
105 | fn load_any(&self, key: DataKey, _: DataRequest) -> Result<AnyResponse, DataError> { | |
106 | key.match_key(self.key)?; | |
107 | Ok(AnyResponse { | |
108 | metadata: DataResponseMetadata::default(), | |
109 | payload: Some(self.data.clone()), | |
110 | }) | |
111 | } | |
112 | } | |
113 | ||
114 | impl<M> DataProvider<M> for AnyPayloadProvider | |
115 | where | |
49aad941 | 116 | M: KeyedDataMarker, |
487cf647 FG |
117 | for<'a> YokeTraitHack<<M::Yokeable as Yokeable<'a>>::Output>: Clone, |
118 | M::Yokeable: ZeroFrom<'static, M::Yokeable>, | |
119 | M::Yokeable: icu_provider::MaybeSendSync, | |
120 | { | |
121 | fn load(&self, req: DataRequest) -> Result<DataResponse<M>, DataError> { | |
122 | self.as_downcasting().load(req) | |
123 | } | |
124 | } |