icu_provider/
buf.rs

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
7use 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)]
15pub struct BufferMarker;
16
17impl 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
87pub 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
96impl<'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
107impl<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
118impl<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")]
130impl<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]
145pub 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
154impl 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}