diff options
Diffstat (limited to 'third_party/rust/icu_provider/src/buf.rs')
-rw-r--r-- | third_party/rust/icu_provider/src/buf.rs | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/third_party/rust/icu_provider/src/buf.rs b/third_party/rust/icu_provider/src/buf.rs new file mode 100644 index 0000000000..0a0ad6eb30 --- /dev/null +++ b/third_party/rust/icu_provider/src/buf.rs @@ -0,0 +1,168 @@ +// This file is part of ICU4X. For terms of use, please see the file +// called LICENSE at the top level of the ICU4X source tree +// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ). + +//! Traits for data providers that produce opaque buffers. + +use crate::prelude::*; + +/// [`DataMarker`] for raw buffers. Returned by [`BufferProvider`]. +/// +/// The data is expected to be deserialized before it can be used; see +/// [`DataPayload::into_deserialized`]. +#[allow(clippy::exhaustive_structs)] // marker type +#[derive(Debug)] +pub struct BufferMarker; + +impl DataMarker for BufferMarker { + type Yokeable = &'static [u8]; +} + +/// A data provider that returns opaque bytes. +/// +/// Generally, these bytes are expected to be deserializable with Serde. To get an object +/// implementing [`DataProvider`] via Serde, use [`as_deserializing()`]. +/// +/// Passing a `BufferProvider` to a `*_with_buffer_provider` constructor requires enabling +/// the deserialization Cargo feature for the expected format(s): +/// - `deserialize_json` +/// - `deserialize_postcard_1` +/// - `deserialize_bincode_1` +/// +/// Along with [`DataProvider`], this is one of the two foundational traits in this crate. +/// +/// [`BufferProvider`] can be made into a trait object. It is used over FFI. +/// +/// # Examples +/// +/// ``` +/// # #[cfg(feature = "deserialize_json")] { +/// use icu_locid::locale; +/// use icu_provider::hello_world::*; +/// use icu_provider::prelude::*; +/// use std::borrow::Cow; +/// +/// let buffer_provider = HelloWorldProvider.into_json_provider(); +/// +/// let req = DataRequest { +/// locale: &locale!("de").into(), +/// metadata: Default::default(), +/// }; +/// +/// // Deserializing manually +/// assert_eq!( +/// serde_json::from_slice::<HelloWorldV1>( +/// buffer_provider +/// .load_buffer(HelloWorldV1Marker::KEY, req) +/// .expect("load should succeed") +/// .take_payload() +/// .unwrap() +/// .get() +/// ) +/// .expect("should deserialize"), +/// HelloWorldV1 { +/// message: Cow::Borrowed("Hallo Welt"), +/// }, +/// ); +/// +/// // Deserialize automatically +/// let deserializing_provider: &dyn DataProvider<HelloWorldV1Marker> = +/// &buffer_provider.as_deserializing(); +/// +/// assert_eq!( +/// deserializing_provider +/// .load(req) +/// .expect("load should succeed") +/// .take_payload() +/// .unwrap() +/// .get(), +/// &HelloWorldV1 { +/// message: Cow::Borrowed("Hallo Welt"), +/// }, +/// ); +/// # } +/// ``` +/// +/// [`as_deserializing()`]: AsDeserializingBufferProvider::as_deserializing +pub trait BufferProvider { + /// Loads a [`DataPayload`]`<`[`BufferMarker`]`>` according to the key and request. + fn load_buffer( + &self, + key: DataKey, + req: DataRequest, + ) -> Result<DataResponse<BufferMarker>, DataError>; +} + +impl<'a, T: BufferProvider + ?Sized> BufferProvider for &'a T { + fn load_buffer( + &self, + key: DataKey, + req: DataRequest, + ) -> Result<DataResponse<BufferMarker>, DataError> { + (**self).load_buffer(key, req) + } +} + +impl<T: BufferProvider + ?Sized> BufferProvider for alloc::boxed::Box<T> { + fn load_buffer( + &self, + key: DataKey, + req: DataRequest, + ) -> Result<DataResponse<BufferMarker>, DataError> { + (**self).load_buffer(key, req) + } +} + +impl<T: BufferProvider + ?Sized> BufferProvider for alloc::rc::Rc<T> { + fn load_buffer( + &self, + key: DataKey, + req: DataRequest, + ) -> Result<DataResponse<BufferMarker>, DataError> { + (**self).load_buffer(key, req) + } +} + +#[cfg(target_has_atomic = "ptr")] +impl<T: BufferProvider + ?Sized> BufferProvider for alloc::sync::Arc<T> { + fn load_buffer( + &self, + key: DataKey, + req: DataRequest, + ) -> Result<DataResponse<BufferMarker>, DataError> { + (**self).load_buffer(key, req) + } +} + +/// An enum expressing all Serde formats known to ICU4X. +#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[non_exhaustive] +pub enum BufferFormat { + /// Serialize using JavaScript Object Notation (JSON). + Json, + /// Serialize using Bincode version 1. + Bincode1, + /// Serialize using Postcard version 1. + Postcard1, +} + +impl BufferFormat { + /// Returns an error if the buffer format is not enabled. + pub fn check_available(&self) -> Result<(), DataError> { + match self { + #[cfg(feature = "deserialize_json")] + BufferFormat::Json => Ok(()), + + #[cfg(feature = "deserialize_bincode_1")] + BufferFormat::Bincode1 => Ok(()), + + #[cfg(feature = "deserialize_postcard_1")] + BufferFormat::Postcard1 => Ok(()), + + // Allowed for cases in which all features are enabled + #[allow(unreachable_patterns)] + _ => Err(DataErrorKind::UnavailableBufferFormat(*self).into_error()), + } + } +} |