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 | //! Traits for data providers that produce opaque buffers. |
6 | |
7 | use crate::prelude::*; |
8 | |
9 | /// [`DataMarker`] for raw buffers. Returned by [`BufferProvider`]. |
10 | /// |
11 | /// The data is expected to be deserialized before it can be used; see |
12 | /// [`DataPayload::into_deserialized`]. |
13 | #[allow (clippy::exhaustive_structs)] // marker type |
14 | #[derive (Debug)] |
15 | pub struct BufferMarker; |
16 | |
17 | impl DataMarker for BufferMarker { |
18 | type Yokeable = &'static [u8]; |
19 | } |
20 | |
21 | /// A data provider that returns opaque bytes. |
22 | /// |
23 | /// Generally, these bytes are expected to be deserializable with Serde. To get an object |
24 | /// implementing [`DataProvider`] via Serde, use [`as_deserializing()`]. |
25 | /// |
26 | /// Passing a `BufferProvider` to a `*_with_buffer_provider` constructor requires enabling |
27 | /// the deserialization Cargo feature for the expected format(s): |
28 | /// - `deserialize_json` |
29 | /// - `deserialize_postcard_1` |
30 | /// - `deserialize_bincode_1` |
31 | /// |
32 | /// Along with [`DataProvider`], this is one of the two foundational traits in this crate. |
33 | /// |
34 | /// [`BufferProvider`] can be made into a trait object. It is used over FFI. |
35 | /// |
36 | /// # Examples |
37 | /// |
38 | /// ``` |
39 | /// # #[cfg (feature = "deserialize_json" )] { |
40 | /// use icu_locid::langid; |
41 | /// use icu_provider::hello_world::*; |
42 | /// use icu_provider::prelude::*; |
43 | /// use std::borrow::Cow; |
44 | /// |
45 | /// let buffer_provider = HelloWorldProvider.into_json_provider(); |
46 | /// |
47 | /// let req = DataRequest { |
48 | /// locale: &langid!("de" ).into(), |
49 | /// metadata: Default::default(), |
50 | /// }; |
51 | /// |
52 | /// // Deserializing manually |
53 | /// assert_eq!( |
54 | /// serde_json::from_slice::<HelloWorldV1>( |
55 | /// buffer_provider |
56 | /// .load_buffer(HelloWorldV1Marker::KEY, req) |
57 | /// .expect("load should succeed" ) |
58 | /// .take_payload() |
59 | /// .unwrap() |
60 | /// .get() |
61 | /// ) |
62 | /// .expect("should deserialize" ), |
63 | /// HelloWorldV1 { |
64 | /// message: Cow::Borrowed("Hallo Welt" ), |
65 | /// }, |
66 | /// ); |
67 | /// |
68 | /// // Deserialize automatically |
69 | /// let deserializing_provider: &dyn DataProvider<HelloWorldV1Marker> = |
70 | /// &buffer_provider.as_deserializing(); |
71 | /// |
72 | /// assert_eq!( |
73 | /// deserializing_provider |
74 | /// .load(req) |
75 | /// .expect("load should succeed" ) |
76 | /// .take_payload() |
77 | /// .unwrap() |
78 | /// .get(), |
79 | /// &HelloWorldV1 { |
80 | /// message: Cow::Borrowed("Hallo Welt" ), |
81 | /// }, |
82 | /// ); |
83 | /// # } |
84 | /// ``` |
85 | /// |
86 | /// [`as_deserializing()`]: AsDeserializingBufferProvider::as_deserializing |
87 | pub trait BufferProvider { |
88 | /// Loads a [`DataPayload`]`<`[`BufferMarker`]`>` according to the key and request. |
89 | fn load_buffer( |
90 | &self, |
91 | key: DataKey, |
92 | req: DataRequest, |
93 | ) -> Result<DataResponse<BufferMarker>, DataError>; |
94 | } |
95 | |
96 | impl<'a, T: BufferProvider + ?Sized> BufferProvider for &'a T { |
97 | #[inline ] |
98 | fn load_buffer( |
99 | &self, |
100 | key: DataKey, |
101 | req: DataRequest, |
102 | ) -> Result<DataResponse<BufferMarker>, DataError> { |
103 | (**self).load_buffer(key, req) |
104 | } |
105 | } |
106 | |
107 | impl<T: BufferProvider + ?Sized> BufferProvider for alloc::boxed::Box<T> { |
108 | #[inline ] |
109 | fn load_buffer( |
110 | &self, |
111 | key: DataKey, |
112 | req: DataRequest, |
113 | ) -> Result<DataResponse<BufferMarker>, DataError> { |
114 | (**self).load_buffer(key, req) |
115 | } |
116 | } |
117 | |
118 | impl<T: BufferProvider + ?Sized> BufferProvider for alloc::rc::Rc<T> { |
119 | #[inline ] |
120 | fn load_buffer( |
121 | &self, |
122 | key: DataKey, |
123 | req: DataRequest, |
124 | ) -> Result<DataResponse<BufferMarker>, DataError> { |
125 | (**self).load_buffer(key, req) |
126 | } |
127 | } |
128 | |
129 | #[cfg (target_has_atomic = "ptr" )] |
130 | impl<T: BufferProvider + ?Sized> BufferProvider for alloc::sync::Arc<T> { |
131 | #[inline ] |
132 | fn load_buffer( |
133 | &self, |
134 | key: DataKey, |
135 | req: DataRequest, |
136 | ) -> Result<DataResponse<BufferMarker>, DataError> { |
137 | (**self).load_buffer(key, req) |
138 | } |
139 | } |
140 | |
141 | /// An enum expressing all Serde formats known to ICU4X. |
142 | #[derive (Debug, PartialEq, Eq, Hash, Copy, Clone)] |
143 | #[cfg_attr (feature = "serde" , derive(serde::Serialize, serde::Deserialize))] |
144 | #[non_exhaustive ] |
145 | pub enum BufferFormat { |
146 | /// Serialize using JavaScript Object Notation (JSON). |
147 | Json, |
148 | /// Serialize using Bincode version 1. |
149 | Bincode1, |
150 | /// Serialize using Postcard version 1. |
151 | Postcard1, |
152 | } |
153 | |
154 | impl BufferFormat { |
155 | /// Returns an error if the buffer format is not enabled. |
156 | pub fn check_available(&self) -> Result<(), DataError> { |
157 | match self { |
158 | #[cfg (feature = "deserialize_json" )] |
159 | BufferFormat::Json => Ok(()), |
160 | |
161 | #[cfg (feature = "deserialize_bincode_1" )] |
162 | BufferFormat::Bincode1 => Ok(()), |
163 | |
164 | #[cfg (feature = "deserialize_postcard_1" )] |
165 | BufferFormat::Postcard1 => Ok(()), |
166 | |
167 | // Allowed for cases in which all features are enabled |
168 | #[allow (unreachable_patterns)] |
169 | _ => Err(DataErrorKind::UnavailableBufferFormat(*self).into_error()), |
170 | } |
171 | } |
172 | } |
173 | |