• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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