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 use icu_casemap::options::TitlecaseOptions; 6 7 #[diplomat::bridge] 8 #[diplomat::abi_rename = "icu4x_{0}_mv1"] 9 #[diplomat::attr(auto, namespace = "icu4x")] 10 pub mod ffi { 11 use alloc::boxed::Box; 12 13 #[cfg(any(feature = "compiled_data", feature = "buffer_provider"))] 14 use crate::errors::ffi::DataError; 15 use crate::locale_core::ffi::Locale; 16 #[cfg(feature = "buffer_provider")] 17 use crate::provider::ffi::DataProvider; 18 use diplomat_runtime::DiplomatOption; 19 20 use writeable::Writeable; 21 22 #[diplomat::enum_convert(icu_casemap::options::LeadingAdjustment, needs_wildcard)] 23 #[diplomat::rust_link(icu::casemap::options::LeadingAdjustment, Enum)] 24 pub enum LeadingAdjustment { 25 Auto, 26 None, 27 ToCased, 28 } 29 30 #[diplomat::enum_convert(icu_casemap::options::TrailingCase, needs_wildcard)] 31 #[diplomat::rust_link(icu::casemap::options::TrailingCase, Enum)] 32 pub enum TrailingCase { 33 Lower, 34 Unchanged, 35 } 36 37 #[diplomat::rust_link(icu::casemap::options::TitlecaseOptions, Struct)] 38 #[diplomat::attr(supports = non_exhaustive_structs, rename = "TitlecaseOptions")] 39 pub struct TitlecaseOptionsV1 { 40 pub leading_adjustment: DiplomatOption<LeadingAdjustment>, 41 pub trailing_case: DiplomatOption<TrailingCase>, 42 } 43 44 impl TitlecaseOptionsV1 { 45 #[diplomat::rust_link(icu::casemap::options::TitlecaseOptions::default, FnInStruct)] 46 #[diplomat::attr(auto, constructor)] 47 #[diplomat::attr(any(cpp, js), rename = "default_options")] default() -> TitlecaseOptionsV148 pub fn default() -> TitlecaseOptionsV1 { 49 Self { 50 leading_adjustment: None.into(), 51 trailing_case: None.into(), 52 } 53 } 54 } 55 56 #[diplomat::opaque] 57 #[diplomat::rust_link(icu::casemap::CaseMapper, Struct)] 58 #[diplomat::rust_link(icu::casemap::CaseMapperBorrowed, Struct, hidden)] 59 pub struct CaseMapper(pub icu_casemap::CaseMapper); 60 61 impl CaseMapper { 62 /// Construct a new CaseMapper instance using compiled data. 63 #[diplomat::rust_link(icu::casemap::CaseMapper::new, FnInStruct)] 64 #[diplomat::rust_link(icu::casemap::CaseMapperBorrowed::new, FnInStruct, hidden)] 65 #[diplomat::attr(auto, constructor)] 66 #[cfg(feature = "compiled_data")] create() -> Box<CaseMapper>67 pub fn create() -> Box<CaseMapper> { 68 Box::new(CaseMapper(icu_casemap::CaseMapper::new().static_to_owned())) 69 } 70 71 /// Construct a new CaseMapper instance using a particular data source. 72 #[diplomat::rust_link(icu::casemap::CaseMapper::new, FnInStruct)] 73 #[diplomat::attr(all(supports = fallible_constructors, supports = named_constructors), named_constructor = "with_provider")] 74 #[cfg(feature = "buffer_provider")] create_with_provider(provider: &DataProvider) -> Result<Box<CaseMapper>, DataError>75 pub fn create_with_provider(provider: &DataProvider) -> Result<Box<CaseMapper>, DataError> { 76 Ok(Box::new(CaseMapper( 77 icu_casemap::CaseMapper::try_new_with_buffer_provider(provider.get()?)?, 78 ))) 79 } 80 /// Returns the full lowercase mapping of the given string 81 #[diplomat::rust_link(icu::casemap::CaseMapperBorrowed::lowercase, FnInStruct)] 82 #[diplomat::rust_link( 83 icu::casemap::CaseMapperBorrowed::lowercase_to_string, 84 FnInStruct, 85 hidden 86 )] lowercase(&self, s: &str, locale: &Locale, write: &mut DiplomatWrite)87 pub fn lowercase(&self, s: &str, locale: &Locale, write: &mut DiplomatWrite) { 88 let _infallible = self 89 .0 90 .as_borrowed() 91 .lowercase(s, &locale.0.id) 92 .write_to(write); 93 } 94 95 /// Returns the full uppercase mapping of the given string 96 #[diplomat::rust_link(icu::casemap::CaseMapperBorrowed::uppercase, FnInStruct)] 97 #[diplomat::rust_link( 98 icu::casemap::CaseMapperBorrowed::uppercase_to_string, 99 FnInStruct, 100 hidden 101 )] uppercase(&self, s: &str, locale: &Locale, write: &mut DiplomatWrite)102 pub fn uppercase(&self, s: &str, locale: &Locale, write: &mut DiplomatWrite) { 103 let _infallible = self 104 .0 105 .as_borrowed() 106 .uppercase(s, &locale.0.id) 107 .write_to(write); 108 } 109 110 /// Returns the full titlecase mapping of the given string, performing head adjustment without 111 /// loading additional data. 112 /// (if head adjustment is enabled in the options) 113 /// 114 /// The `v1` refers to the version of the options struct, which may change as we add more options 115 #[diplomat::rust_link( 116 icu::casemap::CaseMapperBorrowed::titlecase_segment_with_only_case_data, 117 FnInStruct 118 )] 119 #[diplomat::rust_link( 120 icu::casemap::CaseMapperBorrowed::titlecase_segment_with_only_case_data_to_string, 121 FnInStruct, 122 hidden 123 )] 124 #[diplomat::attr(supports = non_exhaustive_structs, rename = "titlecase_segment_with_only_case_data")] titlecase_segment_with_only_case_data_v1( &self, s: &str, locale: &Locale, options: TitlecaseOptionsV1, write: &mut DiplomatWrite, )125 pub fn titlecase_segment_with_only_case_data_v1( 126 &self, 127 s: &str, 128 locale: &Locale, 129 options: TitlecaseOptionsV1, 130 write: &mut DiplomatWrite, 131 ) { 132 let _infallible = self 133 .0 134 .as_borrowed() 135 .titlecase_segment_with_only_case_data(s, &locale.0.id, options.into()) 136 .write_to(write); 137 } 138 139 /// Case-folds the characters in the given string 140 #[diplomat::rust_link(icu::casemap::CaseMapperBorrowed::fold, FnInStruct)] 141 #[diplomat::rust_link(icu::casemap::CaseMapperBorrowed::fold_string, FnInStruct, hidden)] fold(&self, s: &str, write: &mut DiplomatWrite)142 pub fn fold(&self, s: &str, write: &mut DiplomatWrite) { 143 let _infallible = self.0.as_borrowed().fold(s).write_to(write); 144 } 145 /// Case-folds the characters in the given string 146 /// using Turkic (T) mappings for dotted/dotless I. 147 #[diplomat::rust_link(icu::casemap::CaseMapperBorrowed::fold_turkic, FnInStruct)] 148 #[diplomat::rust_link( 149 icu::casemap::CaseMapperBorrowed::fold_turkic_string, 150 FnInStruct, 151 hidden 152 )] fold_turkic(&self, s: &str, write: &mut DiplomatWrite)153 pub fn fold_turkic(&self, s: &str, write: &mut DiplomatWrite) { 154 let _infallible = self.0.as_borrowed().fold_turkic(s).write_to(write); 155 } 156 157 /// Adds all simple case mappings and the full case folding for `c` to `builder`. 158 /// Also adds special case closure mappings. 159 /// 160 /// In other words, this adds all characters that this casemaps to, as 161 /// well as all characters that may casemap to this one. 162 /// 163 /// Note that since CodePointSetBuilder does not contain strings, this will 164 /// ignore string mappings. 165 /// 166 /// Identical to the similarly named method on `CaseMapCloser`, use that if you 167 /// plan on using string case closure mappings too. 168 #[cfg(feature = "properties")] 169 #[diplomat::rust_link(icu::casemap::CaseMapperBorrowed::add_case_closure_to, FnInStruct)] 170 #[diplomat::rust_link(icu::casemap::ClosureSink, Trait, hidden)] 171 #[diplomat::rust_link(icu::casemap::ClosureSink::add_char, FnInTrait, hidden)] 172 #[diplomat::rust_link(icu::casemap::ClosureSink::add_string, FnInTrait, hidden)] add_case_closure_to( &self, c: DiplomatChar, builder: &mut crate::collections_sets::ffi::CodePointSetBuilder, )173 pub fn add_case_closure_to( 174 &self, 175 c: DiplomatChar, 176 builder: &mut crate::collections_sets::ffi::CodePointSetBuilder, 177 ) { 178 if let Some(ch) = char::from_u32(c) { 179 self.0.as_borrowed().add_case_closure_to(ch, &mut builder.0) 180 } 181 } 182 183 /// Returns the simple lowercase mapping of the given character. 184 /// 185 /// This function only implements simple and common mappings. 186 /// Full mappings, which can map one char to a string, are not included. 187 /// For full mappings, use `CaseMapperBorrowed::lowercase`. 188 #[diplomat::rust_link(icu::casemap::CaseMapperBorrowed::simple_lowercase, FnInStruct)] simple_lowercase(&self, ch: DiplomatChar) -> DiplomatChar189 pub fn simple_lowercase(&self, ch: DiplomatChar) -> DiplomatChar { 190 char::from_u32(ch) 191 .map(|ch| self.0.as_borrowed().simple_lowercase(ch) as DiplomatChar) 192 .unwrap_or(ch) 193 } 194 195 /// Returns the simple uppercase mapping of the given character. 196 /// 197 /// This function only implements simple and common mappings. 198 /// Full mappings, which can map one char to a string, are not included. 199 /// For full mappings, use `CaseMapperBorrowed::uppercase`. 200 #[diplomat::rust_link(icu::casemap::CaseMapperBorrowed::simple_uppercase, FnInStruct)] simple_uppercase(&self, ch: DiplomatChar) -> DiplomatChar201 pub fn simple_uppercase(&self, ch: DiplomatChar) -> DiplomatChar { 202 char::from_u32(ch) 203 .map(|ch| self.0.as_borrowed().simple_uppercase(ch) as DiplomatChar) 204 .unwrap_or(ch) 205 } 206 207 /// Returns the simple titlecase mapping of the given character. 208 /// 209 /// This function only implements simple and common mappings. 210 /// Full mappings, which can map one char to a string, are not included. 211 /// For full mappings, use `CaseMapperBorrowed::titlecase_segment`. 212 #[diplomat::rust_link(icu::casemap::CaseMapperBorrowed::simple_titlecase, FnInStruct)] simple_titlecase(&self, ch: DiplomatChar) -> DiplomatChar213 pub fn simple_titlecase(&self, ch: DiplomatChar) -> DiplomatChar { 214 char::from_u32(ch) 215 .map(|ch| self.0.as_borrowed().simple_titlecase(ch) as DiplomatChar) 216 .unwrap_or(ch) 217 } 218 219 /// Returns the simple casefolding of the given character. 220 /// 221 /// This function only implements simple folding. 222 /// For full folding, use `CaseMapperBorrowed::fold`. 223 #[diplomat::rust_link(icu::casemap::CaseMapperBorrowed::simple_fold, FnInStruct)] simple_fold(&self, ch: DiplomatChar) -> DiplomatChar224 pub fn simple_fold(&self, ch: DiplomatChar) -> DiplomatChar { 225 char::from_u32(ch) 226 .map(|ch| self.0.as_borrowed().simple_fold(ch) as DiplomatChar) 227 .unwrap_or(ch) 228 } 229 /// Returns the simple casefolding of the given character in the Turkic locale 230 /// 231 /// This function only implements simple folding. 232 /// For full folding, use `CaseMapperBorrowed::fold_turkic`. 233 #[diplomat::rust_link(icu::casemap::CaseMapperBorrowed::simple_fold_turkic, FnInStruct)] simple_fold_turkic(&self, ch: DiplomatChar) -> DiplomatChar234 pub fn simple_fold_turkic(&self, ch: DiplomatChar) -> DiplomatChar { 235 char::from_u32(ch) 236 .map(|ch| self.0.as_borrowed().simple_fold_turkic(ch) as DiplomatChar) 237 .unwrap_or(ch) 238 } 239 } 240 241 #[diplomat::opaque] 242 #[diplomat::rust_link(icu::casemap::CaseMapCloser, Struct)] 243 #[diplomat::rust_link(icu::casemap::CaseMapCloserBorrowed, Struct, hidden)] 244 pub struct CaseMapCloser(pub icu_casemap::CaseMapCloser<icu_casemap::CaseMapper>); 245 246 impl CaseMapCloser { 247 /// Construct a new CaseMapCloser instance using compiled data. 248 #[diplomat::rust_link(icu::casemap::CaseMapCloser::new, FnInStruct)] 249 #[diplomat::rust_link(icu::casemap::CaseMapCloserBorrowed::new, FnInStruct, hidden)] 250 #[diplomat::rust_link(icu::casemap::CaseMapCloser::new_with_mapper, FnInStruct, hidden)] 251 #[diplomat::attr(supports = "fallible_constructors", constructor)] 252 #[cfg(feature = "compiled_data")] create() -> Result<Box<CaseMapCloser>, DataError>253 pub fn create() -> Result<Box<CaseMapCloser>, DataError> { 254 Ok(Box::new(CaseMapCloser( 255 icu_casemap::CaseMapCloser::new().static_to_owned(), 256 ))) 257 } 258 /// Construct a new CaseMapCloser instance using a particular data source. 259 #[diplomat::rust_link(icu::casemap::CaseMapCloser::new, FnInStruct)] 260 #[diplomat::rust_link(icu::casemap::CaseMapCloser::new_with_mapper, FnInStruct, hidden)] 261 #[diplomat::attr(all(supports = fallible_constructors, supports = named_constructors), named_constructor = "with_provider")] 262 #[cfg(feature = "buffer_provider")] create_with_provider( provider: &DataProvider, ) -> Result<Box<CaseMapCloser>, DataError>263 pub fn create_with_provider( 264 provider: &DataProvider, 265 ) -> Result<Box<CaseMapCloser>, DataError> { 266 Ok(Box::new(CaseMapCloser( 267 icu_casemap::CaseMapCloser::try_new_with_buffer_provider(provider.get()?)?, 268 ))) 269 } 270 /// Adds all simple case mappings and the full case folding for `c` to `builder`. 271 /// Also adds special case closure mappings. 272 #[cfg(feature = "properties")] 273 #[diplomat::rust_link(icu::casemap::CaseMapCloserBorrowed::add_case_closure_to, FnInStruct)] add_case_closure_to( &self, c: DiplomatChar, builder: &mut crate::collections_sets::ffi::CodePointSetBuilder, )274 pub fn add_case_closure_to( 275 &self, 276 c: DiplomatChar, 277 builder: &mut crate::collections_sets::ffi::CodePointSetBuilder, 278 ) { 279 if let Some(ch) = char::from_u32(c) { 280 self.0.as_borrowed().add_case_closure_to(ch, &mut builder.0) 281 } 282 } 283 284 /// Finds all characters and strings which may casemap to `s` as their full case folding string 285 /// and adds them to the set. 286 /// 287 /// Returns true if the string was found 288 #[cfg(feature = "properties")] 289 #[diplomat::rust_link( 290 icu::casemap::CaseMapCloserBorrowed::add_string_case_closure_to, 291 FnInStruct 292 )] add_string_case_closure_to( &self, s: &DiplomatStr, builder: &mut crate::collections_sets::ffi::CodePointSetBuilder, ) -> bool293 pub fn add_string_case_closure_to( 294 &self, 295 s: &DiplomatStr, 296 builder: &mut crate::collections_sets::ffi::CodePointSetBuilder, 297 ) -> bool { 298 let s = core::str::from_utf8(s).unwrap_or(""); 299 self.0 300 .as_borrowed() 301 .add_string_case_closure_to(s, &mut builder.0) 302 } 303 } 304 305 #[diplomat::opaque] 306 #[diplomat::rust_link(icu::casemap::TitlecaseMapper, Struct)] 307 #[diplomat::rust_link(icu::casemap::TitlecaseMapperBorrowed, Struct, hidden)] 308 pub struct TitlecaseMapper(pub icu_casemap::TitlecaseMapper<icu_casemap::CaseMapper>); 309 310 impl TitlecaseMapper { 311 /// Construct a new `TitlecaseMapper` instance using compiled data. 312 #[diplomat::rust_link(icu::casemap::TitlecaseMapper::new, FnInStruct)] 313 #[diplomat::rust_link(icu::casemap::TitlecaseMapperBorrowed::new, FnInStruct, hidden)] 314 #[diplomat::rust_link(icu::casemap::TitlecaseMapper::new_with_mapper, FnInStruct, hidden)] 315 #[diplomat::attr(supports = "fallible_constructors", constructor)] 316 #[cfg(feature = "compiled_data")] create() -> Result<Box<TitlecaseMapper>, DataError>317 pub fn create() -> Result<Box<TitlecaseMapper>, DataError> { 318 Ok(Box::new(TitlecaseMapper( 319 icu_casemap::TitlecaseMapper::new().static_to_owned(), 320 ))) 321 } 322 /// Construct a new `TitlecaseMapper` instance using a particular data source. 323 #[diplomat::rust_link(icu::casemap::TitlecaseMapper::new, FnInStruct)] 324 #[diplomat::rust_link(icu::casemap::TitlecaseMapper::new_with_mapper, FnInStruct, hidden)] 325 #[diplomat::attr(all(supports = fallible_constructors, supports = named_constructors), named_constructor = "with_provider")] 326 #[cfg(feature = "buffer_provider")] create_with_provider( provider: &DataProvider, ) -> Result<Box<TitlecaseMapper>, DataError>327 pub fn create_with_provider( 328 provider: &DataProvider, 329 ) -> Result<Box<TitlecaseMapper>, DataError> { 330 Ok(Box::new(TitlecaseMapper( 331 icu_casemap::TitlecaseMapper::try_new_with_buffer_provider(provider.get()?)?, 332 ))) 333 } 334 /// Returns the full titlecase mapping of the given string 335 /// 336 /// The `v1` refers to the version of the options struct, which may change as we add more options 337 #[diplomat::rust_link(icu::casemap::TitlecaseMapperBorrowed::titlecase_segment, FnInStruct)] 338 #[diplomat::rust_link( 339 icu::casemap::TitlecaseMapperBorrowed::titlecase_segment_to_string, 340 FnInStruct, 341 hidden 342 )] 343 #[diplomat::attr(supports = non_exhaustive_structs, rename = "titlecase_segment")] titlecase_segment_v1( &self, s: &str, locale: &Locale, options: TitlecaseOptionsV1, write: &mut DiplomatWrite, )344 pub fn titlecase_segment_v1( 345 &self, 346 s: &str, 347 locale: &Locale, 348 options: TitlecaseOptionsV1, 349 write: &mut DiplomatWrite, 350 ) { 351 let _infallible = self 352 .0 353 .as_borrowed() 354 .titlecase_segment(s, &locale.0.id, options.into()) 355 .write_to(write); 356 } 357 } 358 } 359 360 impl From<ffi::TitlecaseOptionsV1> for TitlecaseOptions { from(other: ffi::TitlecaseOptionsV1) -> Self361 fn from(other: ffi::TitlecaseOptionsV1) -> Self { 362 let mut ret = Self::default(); 363 364 ret.leading_adjustment = other.leading_adjustment.into_converted_option(); 365 366 ret.trailing_case = other.trailing_case.into_converted_option(); 367 368 ret 369 } 370 } 371