Coverage Report

Created: 2025-05-08 06:13

/rust/registry/src/index.crates.io-6f17d22bba15001f/icu_provider-1.5.0/src/buf.rs
Line
Count
Source (jump to first uncovered line)
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
/// [`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)]
15
pub struct BufferMarker;
16
17
impl 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
87
pub 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
96
impl<'a, T: BufferProvider + ?Sized> BufferProvider for &'a T {
97
    #[inline]
98
0
    fn load_buffer(
99
0
        &self,
100
0
        key: DataKey,
101
0
        req: DataRequest,
102
0
    ) -> Result<DataResponse<BufferMarker>, DataError> {
103
0
        (**self).load_buffer(key, req)
104
0
    }
105
}
106
107
impl<T: BufferProvider + ?Sized> BufferProvider for alloc::boxed::Box<T> {
108
    #[inline]
109
0
    fn load_buffer(
110
0
        &self,
111
0
        key: DataKey,
112
0
        req: DataRequest,
113
0
    ) -> Result<DataResponse<BufferMarker>, DataError> {
114
0
        (**self).load_buffer(key, req)
115
0
    }
116
}
117
118
impl<T: BufferProvider + ?Sized> BufferProvider for alloc::rc::Rc<T> {
119
    #[inline]
120
0
    fn load_buffer(
121
0
        &self,
122
0
        key: DataKey,
123
0
        req: DataRequest,
124
0
    ) -> Result<DataResponse<BufferMarker>, DataError> {
125
0
        (**self).load_buffer(key, req)
126
0
    }
127
}
128
129
#[cfg(target_has_atomic = "ptr")]
130
impl<T: BufferProvider + ?Sized> BufferProvider for alloc::sync::Arc<T> {
131
    #[inline]
132
0
    fn load_buffer(
133
0
        &self,
134
0
        key: DataKey,
135
0
        req: DataRequest,
136
0
    ) -> Result<DataResponse<BufferMarker>, DataError> {
137
0
        (**self).load_buffer(key, req)
138
0
    }
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]
145
pub 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
154
impl BufferFormat {
155
    /// Returns an error if the buffer format is not enabled.
156
0
    pub fn check_available(&self) -> Result<(), DataError> {
157
0
        match self {
158
0
            #[cfg(feature = "deserialize_json")]
159
0
            BufferFormat::Json => Ok(()),
160
0
161
0
            #[cfg(feature = "deserialize_bincode_1")]
162
0
            BufferFormat::Bincode1 => Ok(()),
163
0
164
0
            #[cfg(feature = "deserialize_postcard_1")]
165
0
            BufferFormat::Postcard1 => Ok(()),
166
0
167
0
            // Allowed for cases in which all features are enabled
168
0
            #[allow(unreachable_patterns)]
169
0
            _ => Err(DataErrorKind::UnavailableBufferFormat(*self).into_error()),
170
0
        }
171
0
    }
172
}