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#[cfg(feature = "serde")]
10mod serde;
11#[cfg(feature = "serde")]
12pub 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#[non_exhaustive]
19#[derive(Debug)]
20pub struct BufferMarker;
21
22impl 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
96pub trait BufferProvider: DynamicDataProvider<BufferMarker> {}
97
98impl<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]
104pub 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
113impl BufferFormat {
114    /// Returns an error if the buffer format is not enabled.
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}