provider.rs (7178B)
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 #[diplomat::bridge] 6 #[diplomat::abi_rename = "icu4x_{0}_mv1"] 7 #[diplomat::attr(auto, namespace = "icu4x")] 8 #[cfg(feature = "buffer_provider")] 9 pub mod ffi { 10 use alloc::boxed::Box; 11 use icu_provider::buf::BufferProvider; 12 13 use crate::unstable::errors::ffi::DataError; 14 15 #[diplomat::opaque] 16 /// An ICU4X data provider, capable of loading ICU4X data keys from some source. 17 /// 18 /// Currently the only source supported is loading from "blob" formatted data from a bytes buffer or the file system. 19 /// 20 /// If you wish to use ICU4X's builtin "compiled data", use the version of the constructors that do not have `_with_provider` 21 /// in their names. 22 #[diplomat::rust_link(icu_provider, Mod)] 23 pub struct DataProvider(Option<Box<dyn BufferProvider + 'static>>); 24 25 impl DataProvider { 26 // These will be unused if almost *all* components are turned off, which is tedious and unproductive to gate for 27 #[allow(unused)] 28 pub(crate) fn get( 29 &self, 30 ) -> Result<&(dyn icu_provider::buf::BufferProvider + 'static), icu_provider::DataError> 31 { 32 match &self.0 { 33 None => Err(icu_provider::DataError::custom( 34 "This provider has been destroyed", 35 ))?, 36 Some(ref buffer_provider) => Ok(buffer_provider), 37 } 38 } 39 40 // These will be unused if almost *all* components are turned off, which is tedious and unproductive to gate for 41 #[allow(unused)] 42 pub(crate) fn get_unstable( 43 &self, 44 ) -> Result< 45 icu_provider::buf::DeserializingBufferProvider< 46 (dyn icu_provider::buf::BufferProvider + 'static), 47 >, 48 icu_provider::DataError, 49 > { 50 self.get() 51 .map(icu_provider::buf::AsDeserializingBufferProvider::as_deserializing) 52 } 53 54 /// Constructs an `FsDataProvider` and returns it as an [`DataProvider`]. 55 /// Requires the `provider_fs` Cargo feature. 56 /// Not supported in WASM. 57 #[diplomat::rust_link(icu_provider_fs::FsDataProvider, Struct)] 58 #[cfg(all( 59 feature = "provider_fs", 60 not(any(target_arch = "wasm32", target_os = "none")) 61 ))] 62 #[diplomat::attr(any(dart, js), disable)] 63 #[diplomat::attr(all(supports = fallible_constructors, supports = named_constructors), named_constructor)] 64 pub fn from_fs(path: &DiplomatStr) -> Result<Box<DataProvider>, DataError> { 65 Ok(Box::new(DataProvider(Some(Box::new( 66 icu_provider_fs::FsDataProvider::try_new( 67 // In the future we can start using OsString APIs to support non-utf8 paths 68 core::str::from_utf8(path) 69 .map_err(|_| DataError::Io)? 70 .into(), 71 )?, 72 ))))) 73 } 74 75 /// Constructs a `BlobDataProvider` and returns it as an [`DataProvider`]. 76 #[diplomat::rust_link(icu_provider_blob::BlobDataProvider, Struct)] 77 #[diplomat::attr(all(supports = fallible_constructors, supports = named_constructors), named_constructor)] 78 #[diplomat::attr(not(supports = static_slices), disable)] 79 pub fn from_byte_slice( 80 blob: &'static [DiplomatByte], 81 ) -> Result<Box<DataProvider>, DataError> { 82 Ok(Box::new(DataProvider(Some(Box::new( 83 icu_provider_blob::BlobDataProvider::try_new_from_static_blob(blob)?, 84 ))))) 85 } 86 87 /// Creates a provider that tries the current provider and then, if the current provider 88 /// doesn't support the data key, another provider `other`. 89 /// 90 /// This takes ownership of the `other` provider, leaving an empty provider in its place. 91 #[diplomat::rust_link(icu_provider_adapters::fork::ForkByMarkerProvider, Typedef)] 92 #[diplomat::rust_link( 93 icu_provider_adapters::fork::ForkByMarkerProvider::new, 94 FnInTypedef, 95 hidden 96 )] 97 #[diplomat::rust_link( 98 icu_provider_adapters::fork::ForkByMarkerProvider::new_with_predicate, 99 FnInTypedef, 100 hidden 101 )] 102 #[diplomat::rust_link( 103 icu_provider_adapters::fork::predicates::MarkerNotFoundPredicate, 104 Struct, 105 hidden 106 )] 107 pub fn fork_by_marker(&mut self, other: &mut DataProvider) -> Result<(), DataError> { 108 *self = match (core::mem::take(&mut self.0), core::mem::take(&mut other.0)) { 109 (None, _) | (_, None) => Err(icu_provider::DataError::custom( 110 "This provider has been destroyed", 111 ))?, 112 (Some(a), Some(b)) => DataProvider(Some(Box::new( 113 icu_provider_adapters::fork::ForkByMarkerProvider::new(a, b), 114 ))), 115 }; 116 Ok(()) 117 } 118 119 /// Same as `fork_by_key` but forks by locale instead of key. 120 #[diplomat::rust_link( 121 icu_provider_adapters::fork::predicates::IdentifierNotFoundPredicate, 122 Struct 123 )] 124 pub fn fork_by_locale(&mut self, other: &mut DataProvider) -> Result<(), DataError> { 125 *self = match (core::mem::take(&mut self.0), core::mem::take(&mut other.0)) { 126 (None, _) | (_, None) => Err(icu_provider::DataError::custom( 127 "This provider has been destroyed", 128 ))?, 129 (Some(a), Some(b)) => DataProvider(Some(Box::new( 130 icu_provider_adapters::fork::ForkByErrorProvider::new_with_predicate( 131 a, 132 b, 133 icu_provider_adapters::fork::predicates::IdentifierNotFoundPredicate, 134 ), 135 ))), 136 }; 137 Ok(()) 138 } 139 140 #[diplomat::rust_link( 141 icu_provider_adapters::fallback::LocaleFallbackProvider::new, 142 FnInStruct 143 )] 144 #[diplomat::rust_link( 145 icu_provider_adapters::fallback::LocaleFallbackProvider, 146 Struct, 147 compact 148 )] 149 #[allow(unused_variables)] // feature-gated 150 #[cfg(feature = "locale")] 151 pub fn enable_locale_fallback_with( 152 &mut self, 153 fallbacker: &crate::unstable::fallbacker::ffi::LocaleFallbacker, 154 ) -> Result<(), DataError> { 155 *self = match core::mem::take(&mut self.0) { 156 None => Err(icu_provider::DataError::custom( 157 "This provider has been destroyed", 158 ))?, 159 Some(inner) => DataProvider(Some(Box::new( 160 icu_provider_adapters::fallback::LocaleFallbackProvider::new( 161 inner, 162 fallbacker.0.clone(), 163 ), 164 ))), 165 }; 166 Ok(()) 167 } 168 } 169 }