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