• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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