collator.rs (11376B)
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_collator::options::{CollatorOptions, ResolvedCollatorOptions}; 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(feature = "buffer_provider")] 14 use crate::unstable::provider::ffi::DataProvider; 15 #[cfg(any(feature = "compiled_data", feature = "buffer_provider"))] 16 use crate::unstable::{errors::ffi::DataError, locale_core::ffi::Locale}; 17 use diplomat_runtime::DiplomatOption; 18 19 #[diplomat::opaque] 20 #[diplomat::rust_link(icu::collator::Collator, Struct)] 21 #[diplomat::rust_link(icu::collator::CollatorBorrowed, Struct, hidden)] 22 pub struct Collator(pub icu_collator::Collator); 23 24 #[diplomat::rust_link(icu::collator::options::CollatorOptions, Struct)] 25 #[diplomat::rust_link(icu::collator::options::CollatorOptions::default, FnInStruct, hidden)] 26 #[diplomat::attr(supports = non_exhaustive_structs, rename = "CollatorOptions")] 27 pub struct CollatorOptionsV1 { 28 pub strength: DiplomatOption<CollatorStrength>, 29 pub alternate_handling: DiplomatOption<CollatorAlternateHandling>, 30 pub max_variable: DiplomatOption<CollatorMaxVariable>, 31 pub case_level: DiplomatOption<CollatorCaseLevel>, 32 } 33 34 // Note the flipped order of the words `Collator` and `Resolved`, because 35 // in FFI `Collator` is part of the `Collator` prefix, but in Rust, 36 // `ResolvedCollatorOptions` makes more sense as English. 37 #[diplomat::rust_link(icu::collator::options::ResolvedCollatorOptions, Struct)] 38 #[diplomat::out] 39 #[diplomat::attr(supports = non_exhaustive_structs, rename = "CollatorResolvedOptions")] 40 pub struct CollatorResolvedOptionsV1 { 41 pub strength: CollatorStrength, 42 pub alternate_handling: CollatorAlternateHandling, 43 pub case_first: CollatorCaseFirst, 44 pub max_variable: CollatorMaxVariable, 45 pub case_level: CollatorCaseLevel, 46 pub numeric: CollatorNumericOrdering, 47 } 48 49 #[diplomat::rust_link(icu::collator::options::Strength, Enum)] 50 #[derive(Eq, PartialEq, Debug, PartialOrd, Ord)] 51 #[diplomat::enum_convert(icu_collator::options::Strength, needs_wildcard)] 52 pub enum CollatorStrength { 53 Primary = 0, 54 Secondary = 1, 55 Tertiary = 2, 56 Quaternary = 3, 57 Identical = 4, 58 } 59 60 #[diplomat::rust_link(icu::collator::options::AlternateHandling, Enum)] 61 #[derive(Eq, PartialEq, Debug, PartialOrd, Ord)] 62 #[diplomat::enum_convert(icu_collator::options::AlternateHandling, needs_wildcard)] 63 pub enum CollatorAlternateHandling { 64 NonIgnorable = 0, 65 Shifted = 1, 66 } 67 68 #[diplomat::rust_link(icu::collator::preferences::CollationCaseFirst, Enum)] 69 #[derive(Eq, PartialEq, Debug, PartialOrd, Ord)] 70 pub enum CollatorCaseFirst { 71 Off = 0, 72 Lower = 1, 73 Upper = 2, 74 } 75 76 #[diplomat::rust_link(icu::collator::options::MaxVariable, Enum)] 77 #[derive(Eq, PartialEq, Debug, PartialOrd, Ord)] 78 #[diplomat::enum_convert(icu_collator::options::MaxVariable, needs_wildcard)] 79 pub enum CollatorMaxVariable { 80 Space = 0, 81 Punctuation = 1, 82 Symbol = 2, 83 Currency = 3, 84 } 85 86 #[diplomat::rust_link(icu::collator::options::CaseLevel, Enum)] 87 #[derive(Eq, PartialEq, Debug, PartialOrd, Ord)] 88 #[diplomat::enum_convert(icu_collator::options::CaseLevel, needs_wildcard)] 89 pub enum CollatorCaseLevel { 90 Off = 0, 91 On = 1, 92 } 93 94 #[diplomat::rust_link(icu::collator::preferences::CollationNumericOrdering, Enum)] 95 #[derive(Eq, PartialEq, Debug, PartialOrd, Ord)] 96 pub enum CollatorNumericOrdering { 97 Off = 0, 98 On = 1, 99 } 100 101 impl Collator { 102 /// Construct a new Collator instance using compiled data. 103 #[diplomat::rust_link(icu::collator::Collator::try_new, FnInStruct)] 104 #[diplomat::rust_link(icu::collator::CollatorBorrowed::try_new, FnInStruct, hidden)] 105 #[diplomat::rust_link(icu::collator::CollatorPreferences, Struct, hidden)] 106 #[diplomat::rust_link(icu::collator::CollatorPreferences::extend, FnInStruct, hidden)] 107 #[diplomat::attr(all(supports = fallible_constructors, supports = named_constructors), named_constructor = "with_provider")] 108 #[diplomat::attr(supports = non_exhaustive_structs, rename = "create")] 109 #[cfg(feature = "compiled_data")] 110 pub fn create_v1( 111 locale: &Locale, 112 options: CollatorOptionsV1, 113 ) -> Result<Box<Collator>, DataError> { 114 Ok(Box::new(Collator( 115 icu_collator::Collator::try_new((&locale.0).into(), options.into())? 116 .static_to_owned(), 117 ))) 118 } 119 120 /// Construct a new Collator instance using a particular data source. 121 #[diplomat::rust_link(icu::collator::Collator::try_new, FnInStruct)] 122 #[diplomat::rust_link(icu::collator::CollatorBorrowed::try_new, FnInStruct, hidden)] 123 #[diplomat::rust_link(icu::collator::CollatorPreferences, Struct, hidden)] 124 #[diplomat::attr(supports = fallible_constructors, constructor)] 125 #[diplomat::attr(supports = non_exhaustive_structs, rename = "create_with_provider")] 126 #[cfg(feature = "buffer_provider")] 127 pub fn create_v1_with_provider( 128 provider: &DataProvider, 129 locale: &Locale, 130 options: CollatorOptionsV1, 131 ) -> Result<Box<Collator>, DataError> { 132 let options = options.into(); 133 Ok(Box::new(Collator( 134 icu_collator::Collator::try_new_with_buffer_provider( 135 provider.get()?, 136 (&locale.0).into(), 137 options, 138 )?, 139 ))) 140 } 141 /// Compare two strings. 142 /// 143 /// Ill-formed input is treated as if errors had been replaced with REPLACEMENT CHARACTERs according 144 /// to the WHATWG Encoding Standard. 145 #[diplomat::rust_link(icu::collator::CollatorBorrowed::compare_utf8, FnInStruct)] 146 #[diplomat::rust_link(icu::collator::CollatorBorrowed::compare, FnInStruct, hidden)] 147 #[diplomat::attr(not(supports = utf8_strings), disable)] 148 #[diplomat::attr(supports = utf8_strings, rename = "compare")] 149 pub fn compare_utf8(&self, left: &DiplomatStr, right: &DiplomatStr) -> core::cmp::Ordering { 150 self.0.as_borrowed().compare_utf8(left, right) 151 } 152 153 /// Compare two strings. 154 /// 155 /// Ill-formed input is treated as if errors had been replaced with REPLACEMENT CHARACTERs according 156 /// to the WHATWG Encoding Standard. 157 #[diplomat::rust_link(icu::collator::CollatorBorrowed::compare_utf16, FnInStruct)] 158 #[diplomat::attr(not(supports = utf8_strings), rename = "compare")] 159 #[diplomat::attr(supports = utf8_strings, rename = "compare16")] 160 pub fn compare_utf16( 161 &self, 162 left: &DiplomatStr16, 163 right: &DiplomatStr16, 164 ) -> core::cmp::Ordering { 165 self.0.as_borrowed().compare_utf16(left, right) 166 } 167 168 /// The resolved options showing how the default options, the requested options, 169 /// and the options from locale data were combined. None of the struct fields 170 /// will have `Auto` as the value. 171 #[diplomat::rust_link(icu::collator::CollatorBorrowed::resolved_options, FnInStruct)] 172 #[diplomat::attr(auto, getter)] 173 #[diplomat::attr(supports = non_exhaustive_structs, rename = "resolved_options")] 174 pub fn resolved_options_v1(&self) -> CollatorResolvedOptionsV1 { 175 self.0.as_borrowed().resolved_options().into() 176 } 177 } 178 } 179 180 impl From<ffi::CollatorOptionsV1> for CollatorOptions { 181 fn from(options: ffi::CollatorOptionsV1) -> CollatorOptions { 182 let mut result = CollatorOptions::default(); 183 result.strength = options.strength.into_converted_option(); 184 result.alternate_handling = options.alternate_handling.into_converted_option(); 185 result.max_variable = options.max_variable.into_converted_option(); 186 result.case_level = options.case_level.into_converted_option(); 187 188 result 189 } 190 } 191 192 impl From<ResolvedCollatorOptions> for ffi::CollatorResolvedOptionsV1 { 193 fn from(options: ResolvedCollatorOptions) -> ffi::CollatorResolvedOptionsV1 { 194 Self { 195 strength: options.strength.into(), 196 alternate_handling: options.alternate_handling.into(), 197 case_first: options.case_first.into(), 198 max_variable: options.max_variable.into(), 199 case_level: options.case_level.into(), 200 numeric: options.numeric.into(), 201 } 202 } 203 } 204 205 impl From<icu_collator::preferences::CollationCaseFirst> for ffi::CollatorCaseFirst { 206 fn from(other: icu_collator::preferences::CollationCaseFirst) -> Self { 207 match other { 208 icu_collator::preferences::CollationCaseFirst::Upper => ffi::CollatorCaseFirst::Upper, 209 icu_collator::preferences::CollationCaseFirst::Lower => ffi::CollatorCaseFirst::Lower, 210 icu_collator::preferences::CollationCaseFirst::False => ffi::CollatorCaseFirst::Off, 211 _ => { 212 debug_assert!( 213 false, 214 "unknown variant for icu_collator::preferences::CollationCaseFirst" 215 ); 216 ffi::CollatorCaseFirst::Off 217 } 218 } 219 } 220 } 221 impl From<ffi::CollatorCaseFirst> for icu_collator::preferences::CollationCaseFirst { 222 fn from(this: ffi::CollatorCaseFirst) -> Self { 223 match this { 224 ffi::CollatorCaseFirst::Off => icu_collator::preferences::CollationCaseFirst::False, 225 ffi::CollatorCaseFirst::Lower => icu_collator::preferences::CollationCaseFirst::Lower, 226 ffi::CollatorCaseFirst::Upper => icu_collator::preferences::CollationCaseFirst::Upper, 227 } 228 } 229 } 230 231 impl From<icu_collator::preferences::CollationNumericOrdering> for ffi::CollatorNumericOrdering { 232 fn from(other: icu_collator::preferences::CollationNumericOrdering) -> Self { 233 match other { 234 icu_collator::preferences::CollationNumericOrdering::True => { 235 ffi::CollatorNumericOrdering::On 236 } 237 icu_collator::preferences::CollationNumericOrdering::False => { 238 ffi::CollatorNumericOrdering::Off 239 } 240 _ => { 241 debug_assert!( 242 false, 243 "unknown variant for icu_collator::preferences::CollationNumericOrdering" 244 ); 245 ffi::CollatorNumericOrdering::Off 246 } 247 } 248 } 249 } 250 impl From<ffi::CollatorNumericOrdering> for icu_collator::preferences::CollationNumericOrdering { 251 fn from(this: ffi::CollatorNumericOrdering) -> Self { 252 match this { 253 ffi::CollatorNumericOrdering::Off => { 254 icu_collator::preferences::CollationNumericOrdering::False 255 } 256 ffi::CollatorNumericOrdering::On => { 257 icu_collator::preferences::CollationNumericOrdering::True 258 } 259 } 260 } 261 }