• 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 //! Traits for data providers that produce opaque buffers.
6 
7 use crate::prelude::*;
8 
9 #[cfg(feature = "serde")]
10 mod serde;
11 #[cfg(feature = "serde")]
12 pub use self::serde::*;
13 
14 /// [`DynamicDataMarker`] for raw buffers. Returned by [`BufferProvider`].
15 ///
16 /// The data is expected to be deserialized before it can be used; see
17 /// [`DataPayload::into_deserialized`].
18 #[allow(clippy::exhaustive_structs)] // marker type
19 #[derive(Debug)]
20 pub struct BufferMarker;
21 
22 impl DynamicDataMarker for BufferMarker {
23     type DataStruct = &'static [u8];
24 }
25 
26 /// A data provider that returns opaque bytes.
27 ///
28 /// Generally, these bytes are expected to be deserializable with Serde. To get an object
29 /// implementing [`DataProvider`] via Serde, use [`as_deserializing()`].
30 ///
31 /// Passing a  `BufferProvider` to a `*_with_buffer_provider` constructor requires enabling
32 /// the deserialization Cargo feature for the expected format(s):
33 /// - `deserialize_json`
34 /// - `deserialize_postcard_1`
35 /// - `deserialize_bincode_1`
36 ///
37 /// Along with [`DataProvider`], this is one of the two foundational traits in this crate.
38 ///
39 /// [`BufferProvider`] can be made into a trait object. It is used over FFI.
40 ///
41 /// # Examples
42 ///
43 /// ```
44 /// # #[cfg(feature = "deserialize_json")] {
45 /// use icu_locale_core::langid;
46 /// use icu_provider::hello_world::*;
47 /// use icu_provider::prelude::*;
48 /// use std::borrow::Cow;
49 ///
50 /// let buffer_provider = HelloWorldProvider.into_json_provider();
51 ///
52 /// // Deserializing manually
53 /// assert_eq!(
54 ///     serde_json::from_slice::<HelloWorld>(
55 ///         buffer_provider
56 ///             .load_data(
57 ///                 HelloWorldV1::INFO,
58 ///                 DataRequest {
59 ///                     id: DataIdentifierBorrowed::for_locale(
60 ///                         &langid!("de").into()
61 ///                     ),
62 ///                     ..Default::default()
63 ///                 }
64 ///             )
65 ///             .expect("load should succeed")
66 ///             .payload
67 ///             .get()
68 ///     )
69 ///     .expect("should deserialize"),
70 ///     HelloWorld {
71 ///         message: Cow::Borrowed("Hallo Welt"),
72 ///     },
73 /// );
74 ///
75 /// // Deserialize automatically
76 /// let deserializing_provider: &dyn DataProvider<HelloWorldV1> =
77 ///     &buffer_provider.as_deserializing();
78 ///
79 /// assert_eq!(
80 ///     deserializing_provider
81 ///         .load(DataRequest {
82 ///             id: DataIdentifierBorrowed::for_locale(&langid!("de").into()),
83 ///             ..Default::default()
84 ///         })
85 ///         .expect("load should succeed")
86 ///         .payload
87 ///         .get(),
88 ///     &HelloWorld {
89 ///         message: Cow::Borrowed("Hallo Welt"),
90 ///     },
91 /// );
92 /// # }
93 /// ```
94 ///
95 /// [`as_deserializing()`]: AsDeserializingBufferProvider::as_deserializing
96 pub trait BufferProvider: DynamicDataProvider<BufferMarker> {}
97 
98 impl<P: DynamicDataProvider<BufferMarker> + ?Sized> BufferProvider for P {}
99 
100 /// An enum expressing all Serde formats known to ICU4X.
101 #[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)]
102 #[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))]
103 #[non_exhaustive]
104 pub enum BufferFormat {
105     /// Serialize using JavaScript Object Notation (JSON), using the [`serde_json`] crate.
106     Json,
107     /// Serialize using the [`bincode`] crate, version 1.
108     Bincode1,
109     /// Serialize using the [`postcard`] crate, version 1.
110     Postcard1,
111 }
112 
113 impl BufferFormat {
114     /// Returns an error if the buffer format is not enabled.
check_available(&self) -> Result<(), DataError>115     pub fn check_available(&self) -> Result<(), DataError> {
116         match self {
117             #[cfg(feature = "deserialize_json")]
118             BufferFormat::Json => Ok(()),
119             #[cfg(not(feature = "deserialize_json"))]
120             BufferFormat::Json => Err(DataErrorKind::Deserialize.with_str_context("deserializing `BufferFormat::Json` requires the `deserialize_json` Cargo feature")),
121 
122             #[cfg(feature = "deserialize_bincode_1")]
123             BufferFormat::Bincode1 => Ok(()),
124             #[cfg(not(feature = "deserialize_bincode_1"))]
125             BufferFormat::Bincode1 => Err(DataErrorKind::Deserialize.with_str_context("deserializing `BufferFormat::Bincode1` requires the `deserialize_bincode_1` Cargo feature")),
126 
127             #[cfg(feature = "deserialize_postcard_1")]
128             BufferFormat::Postcard1 => Ok(()),
129             #[cfg(not(feature = "deserialize_postcard_1"))]
130             BufferFormat::Postcard1 => Err(DataErrorKind::Deserialize.with_str_context("deserializing `BufferFormat::Postcard1` requires the `deserialize_postcard_1` Cargo feature")),
131         }
132     }
133 }
134