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}