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 //! Provides the [`DeserializingBufferProvider`] wrapper, which deserializes data using Serde.
6 //!
7 //! Providers that produce opaque buffers that need to be deserialized into concrete data structs,
8 //! such as `FsDataProvider`, should implement [`BufferProvider`]. These can be converted into
9 //! [`DeserializingBufferProvider`] using the [`as_deserializing`](AsDeserializingBufferProvider::as_deserializing)
10 //! convenience method.
11 //!
12 //! [`BufferProvider`]: crate::buf::BufferProvider
13
14 use crate::buf::BufferFormat;
15 use crate::buf::BufferProvider;
16 use crate::data_provider::DynamicDryDataProvider;
17 use crate::prelude::*;
18 use crate::DryDataProvider;
19 use serde::de::Deserialize;
20 use yoke::Yokeable;
21
22 /// A [`BufferProvider`] that deserializes its data using Serde.
23 #[derive(Debug)]
24 pub struct DeserializingBufferProvider<'a, P: ?Sized>(&'a P);
25
26 /// Blanket-implemented trait adding the [`Self::as_deserializing()`] function.
27 pub trait AsDeserializingBufferProvider {
28 /// Wrap this [`BufferProvider`] in a [`DeserializingBufferProvider`].
29 ///
30 /// This requires enabling the deserialization Cargo feature
31 /// for the expected format(s):
32 ///
33 /// - `deserialize_json`
34 /// - `deserialize_postcard_1`
35 /// - `deserialize_bincode_1`
as_deserializing(&self) -> DeserializingBufferProvider<Self>36 fn as_deserializing(&self) -> DeserializingBufferProvider<Self>;
37 }
38
39 impl<P> AsDeserializingBufferProvider for P
40 where
41 P: BufferProvider + ?Sized,
42 {
43 /// Wrap this [`BufferProvider`] in a [`DeserializingBufferProvider`].
44 ///
45 /// This requires enabling the deserialization Cargo feature
46 /// for the expected format(s):
47 ///
48 /// - `deserialize_json`
49 /// - `deserialize_postcard_1`
50 /// - `deserialize_bincode_1`
as_deserializing(&self) -> DeserializingBufferProvider<Self>51 fn as_deserializing(&self) -> DeserializingBufferProvider<Self> {
52 DeserializingBufferProvider(self)
53 }
54 }
55
deserialize_impl<'data, M>( #[allow(unused_variables)] bytes: &'data [u8], buffer_format: BufferFormat, ) -> Result<<M::DataStruct as Yokeable<'data>>::Output, DataError> where M: DynamicDataMarker, for<'de> <M::DataStruct as Yokeable<'de>>::Output: Deserialize<'de>,56 fn deserialize_impl<'data, M>(
57 // Allow `bytes` to be unused in case all buffer formats are disabled
58 #[allow(unused_variables)] bytes: &'data [u8],
59 buffer_format: BufferFormat,
60 ) -> Result<<M::DataStruct as Yokeable<'data>>::Output, DataError>
61 where
62 M: DynamicDataMarker,
63 for<'de> <M::DataStruct as Yokeable<'de>>::Output: Deserialize<'de>,
64 {
65 match buffer_format {
66 #[cfg(feature = "deserialize_json")]
67 BufferFormat::Json => {
68 let mut d = serde_json::Deserializer::from_slice(bytes);
69 Ok(Deserialize::deserialize(&mut d)?)
70 }
71
72 #[cfg(feature = "deserialize_bincode_1")]
73 BufferFormat::Bincode1 => {
74 use bincode::Options;
75 let options = bincode::DefaultOptions::new()
76 .with_fixint_encoding()
77 .allow_trailing_bytes();
78 let mut d = bincode::de::Deserializer::from_slice(bytes, options);
79 Ok(Deserialize::deserialize(&mut d)?)
80 }
81
82 #[cfg(feature = "deserialize_postcard_1")]
83 BufferFormat::Postcard1 => {
84 let mut d = postcard::Deserializer::from_bytes(bytes);
85 Ok(Deserialize::deserialize(&mut d)?)
86 }
87
88 // Allowed for cases in which all features are enabled
89 #[allow(unreachable_patterns)]
90 _ => {
91 buffer_format.check_available()?;
92 unreachable!()
93 }
94 }
95 }
96
97 impl DataPayload<BufferMarker> {
98 /// Deserialize a [`DataPayload`]`<`[`BufferMarker`]`>` into a [`DataPayload`] of a
99 /// specific concrete type.
100 ///
101 /// This requires enabling the deserialization Cargo feature
102 /// for the expected format(s):
103 ///
104 /// - `deserialize_json`
105 /// - `deserialize_postcard_1`
106 /// - `deserialize_bincode_1`
107 ///
108 /// This function takes the buffer format as an argument. When a buffer payload is returned
109 /// from a data provider, the buffer format is stored in the [`DataResponseMetadata`].
110 ///
111 /// # Examples
112 ///
113 /// Requires the `deserialize_json` Cargo feature:
114 ///
115 /// ```
116 /// use icu_provider::buf::BufferFormat;
117 /// use icu_provider::hello_world::*;
118 /// use icu_provider::prelude::*;
119 ///
120 /// let buffer: &[u8] = br#"{"message":"Hallo Welt"}"#;
121 ///
122 /// let buffer_payload = DataPayload::from_owned(buffer);
123 /// let payload: DataPayload<HelloWorldV1> = buffer_payload
124 /// .into_deserialized(BufferFormat::Json)
125 /// .expect("Deserialization successful");
126 ///
127 /// assert_eq!(payload.get().message, "Hallo Welt");
128 /// ```
into_deserialized<M>( self, buffer_format: BufferFormat, ) -> Result<DataPayload<M>, DataError> where M: DynamicDataMarker, for<'de> <M::DataStruct as Yokeable<'de>>::Output: Deserialize<'de>,129 pub fn into_deserialized<M>(
130 self,
131 buffer_format: BufferFormat,
132 ) -> Result<DataPayload<M>, DataError>
133 where
134 M: DynamicDataMarker,
135 for<'de> <M::DataStruct as Yokeable<'de>>::Output: Deserialize<'de>,
136 {
137 self.try_map_project(|bytes, _| deserialize_impl::<M>(bytes, buffer_format))
138 }
139 }
140
141 impl<P, M> DynamicDataProvider<M> for DeserializingBufferProvider<'_, P>
142 where
143 M: DynamicDataMarker,
144 P: BufferProvider + ?Sized,
145 for<'de> <M::DataStruct as Yokeable<'de>>::Output: Deserialize<'de>,
146 {
147 /// Converts a buffer into a concrete type by deserializing from a supported buffer format.
148 ///
149 /// This requires enabling the deserialization Cargo feature
150 /// for the expected format(s):
151 ///
152 /// - `deserialize_json`
153 /// - `deserialize_postcard_1`
154 /// - `deserialize_bincode_1`
load_data( &self, marker: DataMarkerInfo, req: DataRequest, ) -> Result<DataResponse<M>, DataError>155 fn load_data(
156 &self,
157 marker: DataMarkerInfo,
158 req: DataRequest,
159 ) -> Result<DataResponse<M>, DataError> {
160 let buffer_response = self.0.load_data(marker, req)?;
161 let buffer_format = buffer_response.metadata.buffer_format.ok_or_else(|| {
162 DataErrorKind::Deserialize
163 .with_str_context("BufferProvider didn't set BufferFormat")
164 .with_req(marker, req)
165 })?;
166 Ok(DataResponse {
167 metadata: buffer_response.metadata,
168 payload: buffer_response
169 .payload
170 .into_deserialized(buffer_format)
171 .map_err(|e| e.with_req(marker, req))?,
172 })
173 }
174 }
175
176 impl<P, M> DynamicDryDataProvider<M> for DeserializingBufferProvider<'_, P>
177 where
178 M: DynamicDataMarker,
179 P: DynamicDryDataProvider<BufferMarker> + ?Sized,
180 for<'de> <M::DataStruct as Yokeable<'de>>::Output: serde::de::Deserialize<'de>,
181 {
dry_load_data( &self, marker: DataMarkerInfo, req: DataRequest, ) -> Result<DataResponseMetadata, DataError>182 fn dry_load_data(
183 &self,
184 marker: DataMarkerInfo,
185 req: DataRequest,
186 ) -> Result<DataResponseMetadata, DataError> {
187 self.0.dry_load_data(marker, req)
188 }
189 }
190
191 impl<P, M> DataProvider<M> for DeserializingBufferProvider<'_, P>
192 where
193 M: DataMarker,
194 P: DynamicDataProvider<BufferMarker> + ?Sized,
195 for<'de> <M::DataStruct as Yokeable<'de>>::Output: Deserialize<'de>,
196 {
197 /// Converts a buffer into a concrete type by deserializing from a supported buffer format.
198 ///
199 /// This requires enabling the deserialization Cargo feature
200 /// for the expected format(s):
201 ///
202 /// - `deserialize_json`
203 /// - `deserialize_postcard_1`
204 /// - `deserialize_bincode_1`
load(&self, req: DataRequest) -> Result<DataResponse<M>, DataError>205 fn load(&self, req: DataRequest) -> Result<DataResponse<M>, DataError> {
206 self.load_data(M::INFO, req)
207 }
208 }
209
210 impl<P, M> DryDataProvider<M> for DeserializingBufferProvider<'_, P>
211 where
212 M: DataMarker,
213 P: DynamicDryDataProvider<BufferMarker> + ?Sized,
214 for<'de> <M::DataStruct as Yokeable<'de>>::Output: Deserialize<'de>,
215 {
dry_load(&self, req: DataRequest) -> Result<DataResponseMetadata, DataError>216 fn dry_load(&self, req: DataRequest) -> Result<DataResponseMetadata, DataError> {
217 self.0.dry_load_data(M::INFO, req)
218 }
219 }
220
221 #[cfg(feature = "deserialize_json")]
222 impl From<serde_json::error::Error> for crate::DataError {
from(e: serde_json::error::Error) -> Self223 fn from(e: serde_json::error::Error) -> Self {
224 DataErrorKind::Deserialize
225 .with_str_context("serde_json")
226 .with_display_context(&e)
227 }
228 }
229
230 #[cfg(feature = "deserialize_bincode_1")]
231 impl From<bincode::Error> for crate::DataError {
from(e: bincode::Error) -> Self232 fn from(e: bincode::Error) -> Self {
233 DataErrorKind::Deserialize
234 .with_str_context("bincode")
235 .with_display_context(&e)
236 }
237 }
238
239 #[cfg(feature = "deserialize_postcard_1")]
240 impl From<postcard::Error> for crate::DataError {
from(e: postcard::Error) -> Self241 fn from(e: postcard::Error) -> Self {
242 DataErrorKind::Deserialize
243 .with_str_context("postcard")
244 .with_display_context(&e)
245 }
246 }
247