casemap.rs (19187B)
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::unstable::errors::ffi::DataError; 15 use crate::unstable::locale_core::ffi::Locale; 16 #[cfg(feature = "buffer_provider")] 17 use crate::unstable::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")] 48 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")] 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")] 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 )] 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 )] 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 lowercase mapping of the given string, using compiled data (avoids having to allocate a CaseMapper object) 111 #[diplomat::rust_link(icu::casemap::CaseMapperBorrowed::lowercase, FnInStruct)] 112 #[diplomat::rust_link( 113 icu::casemap::CaseMapperBorrowed::lowercase_to_string, 114 FnInStruct, 115 hidden 116 )] 117 #[cfg(feature = "compiled_data")] 118 pub fn lowercase_with_compiled_data(s: &str, locale: &Locale, write: &mut DiplomatWrite) { 119 let _infallible = icu_casemap::CaseMapper::new() 120 .lowercase(s, &locale.0.id) 121 .write_to(write); 122 } 123 124 /// Returns the full uppercase mapping of the given string, using compiled data (avoids having to allocate a CaseMapper object) 125 #[diplomat::rust_link(icu::casemap::CaseMapperBorrowed::uppercase, FnInStruct)] 126 #[diplomat::rust_link( 127 icu::casemap::CaseMapperBorrowed::uppercase_to_string, 128 FnInStruct, 129 hidden 130 )] 131 #[cfg(feature = "compiled_data")] 132 pub fn uppercase_with_compiled_data(s: &str, locale: &Locale, write: &mut DiplomatWrite) { 133 let _infallible = icu_casemap::CaseMapper::new() 134 .uppercase(s, &locale.0.id) 135 .write_to(write); 136 } 137 138 /// Returns the full titlecase mapping of the given string, performing head adjustment without 139 /// loading additional data. 140 /// (if head adjustment is enabled in the options) 141 /// 142 /// The `v1` refers to the version of the options struct, which may change as we add more options 143 #[diplomat::rust_link( 144 icu::casemap::CaseMapperBorrowed::titlecase_segment_with_only_case_data, 145 FnInStruct 146 )] 147 #[diplomat::rust_link( 148 icu::casemap::CaseMapperBorrowed::titlecase_segment_with_only_case_data_to_string, 149 FnInStruct, 150 hidden 151 )] 152 #[diplomat::attr(supports = non_exhaustive_structs, rename = "titlecase_segment_with_only_case_data")] 153 pub fn titlecase_segment_with_only_case_data_v1( 154 &self, 155 s: &str, 156 locale: &Locale, 157 options: TitlecaseOptionsV1, 158 write: &mut DiplomatWrite, 159 ) { 160 let _infallible = self 161 .0 162 .as_borrowed() 163 .titlecase_segment_with_only_case_data(s, &locale.0.id, options.into()) 164 .write_to(write); 165 } 166 167 /// Case-folds the characters in the given string 168 #[diplomat::rust_link(icu::casemap::CaseMapperBorrowed::fold, FnInStruct)] 169 #[diplomat::rust_link(icu::casemap::CaseMapperBorrowed::fold_string, FnInStruct, hidden)] 170 pub fn fold(&self, s: &str, write: &mut DiplomatWrite) { 171 let _infallible = self.0.as_borrowed().fold(s).write_to(write); 172 } 173 /// Case-folds the characters in the given string 174 /// using Turkic (T) mappings for dotted/dotless I. 175 #[diplomat::rust_link(icu::casemap::CaseMapperBorrowed::fold_turkic, FnInStruct)] 176 #[diplomat::rust_link( 177 icu::casemap::CaseMapperBorrowed::fold_turkic_string, 178 FnInStruct, 179 hidden 180 )] 181 pub fn fold_turkic(&self, s: &str, write: &mut DiplomatWrite) { 182 let _infallible = self.0.as_borrowed().fold_turkic(s).write_to(write); 183 } 184 185 /// Adds all simple case mappings and the full case folding for `c` to `builder`. 186 /// Also adds special case closure mappings. 187 /// 188 /// In other words, this adds all characters that this casemaps to, as 189 /// well as all characters that may casemap to this one. 190 /// 191 /// Note that since CodePointSetBuilder does not contain strings, this will 192 /// ignore string mappings. 193 /// 194 /// Identical to the similarly named method on `CaseMapCloser`, use that if you 195 /// plan on using string case closure mappings too. 196 #[cfg(feature = "properties")] 197 #[diplomat::rust_link(icu::casemap::CaseMapperBorrowed::add_case_closure_to, FnInStruct)] 198 #[diplomat::rust_link(icu::casemap::ClosureSink, Trait, hidden)] 199 #[diplomat::rust_link(icu::casemap::ClosureSink::add_char, FnInTrait, hidden)] 200 #[diplomat::rust_link(icu::casemap::ClosureSink::add_string, FnInTrait, hidden)] 201 pub fn add_case_closure_to( 202 &self, 203 c: DiplomatChar, 204 builder: &mut crate::unstable::collections_sets::ffi::CodePointSetBuilder, 205 ) { 206 if let Some(ch) = char::from_u32(c) { 207 self.0.as_borrowed().add_case_closure_to(ch, &mut builder.0) 208 } 209 } 210 211 /// Returns the simple lowercase mapping of the given character. 212 /// 213 /// This function only implements simple and common mappings. 214 /// Full mappings, which can map one char to a string, are not included. 215 /// For full mappings, use `CaseMapperBorrowed::lowercase`. 216 #[diplomat::rust_link(icu::casemap::CaseMapperBorrowed::simple_lowercase, FnInStruct)] 217 pub fn simple_lowercase(&self, ch: DiplomatChar) -> DiplomatChar { 218 char::from_u32(ch) 219 .map(|ch| self.0.as_borrowed().simple_lowercase(ch) as DiplomatChar) 220 .unwrap_or(ch) 221 } 222 223 /// Returns the simple uppercase mapping of the given character. 224 /// 225 /// This function only implements simple and common mappings. 226 /// Full mappings, which can map one char to a string, are not included. 227 /// For full mappings, use `CaseMapperBorrowed::uppercase`. 228 #[diplomat::rust_link(icu::casemap::CaseMapperBorrowed::simple_uppercase, FnInStruct)] 229 pub fn simple_uppercase(&self, ch: DiplomatChar) -> DiplomatChar { 230 char::from_u32(ch) 231 .map(|ch| self.0.as_borrowed().simple_uppercase(ch) as DiplomatChar) 232 .unwrap_or(ch) 233 } 234 235 /// Returns the simple titlecase mapping of the given character. 236 /// 237 /// This function only implements simple and common mappings. 238 /// Full mappings, which can map one char to a string, are not included. 239 /// For full mappings, use `CaseMapperBorrowed::titlecase_segment`. 240 #[diplomat::rust_link(icu::casemap::CaseMapperBorrowed::simple_titlecase, FnInStruct)] 241 pub fn simple_titlecase(&self, ch: DiplomatChar) -> DiplomatChar { 242 char::from_u32(ch) 243 .map(|ch| self.0.as_borrowed().simple_titlecase(ch) as DiplomatChar) 244 .unwrap_or(ch) 245 } 246 247 /// Returns the simple casefolding of the given character. 248 /// 249 /// This function only implements simple folding. 250 /// For full folding, use `CaseMapperBorrowed::fold`. 251 #[diplomat::rust_link(icu::casemap::CaseMapperBorrowed::simple_fold, FnInStruct)] 252 pub fn simple_fold(&self, ch: DiplomatChar) -> DiplomatChar { 253 char::from_u32(ch) 254 .map(|ch| self.0.as_borrowed().simple_fold(ch) as DiplomatChar) 255 .unwrap_or(ch) 256 } 257 /// Returns the simple casefolding of the given character in the Turkic locale 258 /// 259 /// This function only implements simple folding. 260 /// For full folding, use `CaseMapperBorrowed::fold_turkic`. 261 #[diplomat::rust_link(icu::casemap::CaseMapperBorrowed::simple_fold_turkic, FnInStruct)] 262 pub fn simple_fold_turkic(&self, ch: DiplomatChar) -> DiplomatChar { 263 char::from_u32(ch) 264 .map(|ch| self.0.as_borrowed().simple_fold_turkic(ch) as DiplomatChar) 265 .unwrap_or(ch) 266 } 267 } 268 269 #[diplomat::opaque] 270 #[diplomat::rust_link(icu::casemap::CaseMapCloser, Struct)] 271 #[diplomat::rust_link(icu::casemap::CaseMapCloserBorrowed, Struct, hidden)] 272 pub struct CaseMapCloser(pub icu_casemap::CaseMapCloser<icu_casemap::CaseMapper>); 273 274 impl CaseMapCloser { 275 /// Construct a new CaseMapCloser instance using compiled data. 276 #[diplomat::rust_link(icu::casemap::CaseMapCloser::new, FnInStruct)] 277 #[diplomat::rust_link(icu::casemap::CaseMapCloserBorrowed::new, FnInStruct, hidden)] 278 #[diplomat::rust_link(icu::casemap::CaseMapCloser::new_with_mapper, FnInStruct, hidden)] 279 #[diplomat::attr(supports = "fallible_constructors", constructor)] 280 #[cfg(feature = "compiled_data")] 281 pub fn create() -> Result<Box<CaseMapCloser>, DataError> { 282 Ok(Box::new(CaseMapCloser( 283 icu_casemap::CaseMapCloser::new().static_to_owned(), 284 ))) 285 } 286 /// Construct a new CaseMapCloser instance using a particular data source. 287 #[diplomat::rust_link(icu::casemap::CaseMapCloser::new, FnInStruct)] 288 #[diplomat::rust_link(icu::casemap::CaseMapCloser::new_with_mapper, FnInStruct, hidden)] 289 #[diplomat::attr(all(supports = fallible_constructors, supports = named_constructors), named_constructor = "with_provider")] 290 #[cfg(feature = "buffer_provider")] 291 pub fn create_with_provider( 292 provider: &DataProvider, 293 ) -> Result<Box<CaseMapCloser>, DataError> { 294 Ok(Box::new(CaseMapCloser( 295 icu_casemap::CaseMapCloser::try_new_with_buffer_provider(provider.get()?)?, 296 ))) 297 } 298 /// Adds all simple case mappings and the full case folding for `c` to `builder`. 299 /// Also adds special case closure mappings. 300 #[cfg(feature = "properties")] 301 #[diplomat::rust_link(icu::casemap::CaseMapCloserBorrowed::add_case_closure_to, FnInStruct)] 302 pub fn add_case_closure_to( 303 &self, 304 c: DiplomatChar, 305 builder: &mut crate::unstable::collections_sets::ffi::CodePointSetBuilder, 306 ) { 307 if let Some(ch) = char::from_u32(c) { 308 self.0.as_borrowed().add_case_closure_to(ch, &mut builder.0) 309 } 310 } 311 312 /// Finds all characters and strings which may casemap to `s` as their full case folding string 313 /// and adds them to the set. 314 /// 315 /// Returns true if the string was found 316 #[cfg(feature = "properties")] 317 #[diplomat::rust_link( 318 icu::casemap::CaseMapCloserBorrowed::add_string_case_closure_to, 319 FnInStruct 320 )] 321 pub fn add_string_case_closure_to( 322 &self, 323 s: &DiplomatStr, 324 builder: &mut crate::unstable::collections_sets::ffi::CodePointSetBuilder, 325 ) -> bool { 326 let s = core::str::from_utf8(s).unwrap_or(""); 327 self.0 328 .as_borrowed() 329 .add_string_case_closure_to(s, &mut builder.0) 330 } 331 } 332 333 #[diplomat::opaque] 334 #[diplomat::rust_link(icu::casemap::TitlecaseMapper, Struct)] 335 #[diplomat::rust_link(icu::casemap::TitlecaseMapperBorrowed, Struct, hidden)] 336 pub struct TitlecaseMapper(pub icu_casemap::TitlecaseMapper<icu_casemap::CaseMapper>); 337 338 impl TitlecaseMapper { 339 /// Construct a new `TitlecaseMapper` instance using compiled data. 340 #[diplomat::rust_link(icu::casemap::TitlecaseMapper::new, FnInStruct)] 341 #[diplomat::rust_link(icu::casemap::TitlecaseMapperBorrowed::new, FnInStruct, hidden)] 342 #[diplomat::rust_link(icu::casemap::TitlecaseMapper::new_with_mapper, FnInStruct, hidden)] 343 #[diplomat::attr(supports = "fallible_constructors", constructor)] 344 #[cfg(feature = "compiled_data")] 345 pub fn create() -> Result<Box<TitlecaseMapper>, DataError> { 346 Ok(Box::new(TitlecaseMapper( 347 icu_casemap::TitlecaseMapper::new().static_to_owned(), 348 ))) 349 } 350 /// Construct a new `TitlecaseMapper` instance using a particular data source. 351 #[diplomat::rust_link(icu::casemap::TitlecaseMapper::new, FnInStruct)] 352 #[diplomat::rust_link(icu::casemap::TitlecaseMapper::new_with_mapper, FnInStruct, hidden)] 353 #[diplomat::attr(all(supports = fallible_constructors, supports = named_constructors), named_constructor = "with_provider")] 354 #[cfg(feature = "buffer_provider")] 355 pub fn create_with_provider( 356 provider: &DataProvider, 357 ) -> Result<Box<TitlecaseMapper>, DataError> { 358 Ok(Box::new(TitlecaseMapper( 359 icu_casemap::TitlecaseMapper::try_new_with_buffer_provider(provider.get()?)?, 360 ))) 361 } 362 /// Returns the full titlecase mapping of the given string 363 /// 364 /// The `v1` refers to the version of the options struct, which may change as we add more options 365 #[diplomat::rust_link(icu::casemap::TitlecaseMapperBorrowed::titlecase_segment, FnInStruct)] 366 #[diplomat::rust_link( 367 icu::casemap::TitlecaseMapperBorrowed::titlecase_segment_to_string, 368 FnInStruct, 369 hidden 370 )] 371 #[diplomat::attr(supports = non_exhaustive_structs, rename = "titlecase_segment")] 372 pub fn titlecase_segment_v1( 373 &self, 374 s: &str, 375 locale: &Locale, 376 options: TitlecaseOptionsV1, 377 write: &mut DiplomatWrite, 378 ) { 379 let _infallible = self 380 .0 381 .as_borrowed() 382 .titlecase_segment(s, &locale.0.id, options.into()) 383 .write_to(write); 384 } 385 /// Returns the full titlecase mapping of the given string, using compiled data (avoids having to allocate a TitlecaseMapper object) 386 /// 387 /// The `v1` refers to the version of the options struct, which may change as we add more options 388 #[diplomat::rust_link(icu::casemap::TitlecaseMapperBorrowed::titlecase_segment, FnInStruct)] 389 #[diplomat::rust_link( 390 icu::casemap::TitlecaseMapperBorrowed::titlecase_segment_to_string, 391 FnInStruct, 392 hidden 393 )] 394 #[diplomat::attr(supports = non_exhaustive_structs, rename = "titlecase_segment_with_compiled_data")] 395 #[cfg(feature = "compiled_data")] 396 pub fn titlecase_segment_with_compiled_data_v1( 397 s: &str, 398 locale: &Locale, 399 options: TitlecaseOptionsV1, 400 write: &mut DiplomatWrite, 401 ) { 402 let _infallible = icu_casemap::TitlecaseMapper::new() 403 .titlecase_segment(s, &locale.0.id, options.into()) 404 .write_to(write); 405 } 406 } 407 } 408 409 impl From<ffi::TitlecaseOptionsV1> for TitlecaseOptions { 410 fn from(other: ffi::TitlecaseOptionsV1) -> Self { 411 let mut ret = Self::default(); 412 413 ret.leading_adjustment = other.leading_adjustment.into_converted_option(); 414 415 ret.trailing_case = other.trailing_case.into_converted_option(); 416 417 ret 418 } 419 }