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