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 #[diplomat::bridge] 6 #[diplomat::abi_rename = "icu4x_{0}_mv1"] 7 #[diplomat::attr(auto, namespace = "icu4x")] 8 pub mod ffi { 9 use alloc::boxed::Box; 10 11 #[cfg(feature = "buffer_provider")] 12 use crate::errors::ffi::DataError; 13 #[cfg(feature = "buffer_provider")] 14 use crate::provider::ffi::DataProvider; 15 16 #[diplomat::opaque] 17 /// An ICU4X Units Converter Factory object, capable of creating converters a [`UnitsConverter`] 18 /// for converting between two [`MeasureUnit`]s. 19 /// 20 /// Also, it can parse the CLDR unit identifier (e.g. `meter-per-square-second`) and get the [`MeasureUnit`]. 21 #[diplomat::rust_link(icu::experimental::units::converter_factory::ConverterFactory, Struct)] 22 pub struct UnitsConverterFactory( 23 pub icu_experimental::units::converter_factory::ConverterFactory, 24 ); 25 26 impl UnitsConverterFactory { 27 /// Construct a new [`UnitsConverterFactory`] instance using compiled data. 28 #[diplomat::rust_link( 29 icu::experimental::units::converter_factory::ConverterFactory::new, 30 FnInStruct 31 )] 32 #[diplomat::attr(auto, constructor)] 33 #[cfg(feature = "compiled_data")] create() -> Box<UnitsConverterFactory>34 pub fn create() -> Box<UnitsConverterFactory> { 35 Box::new(UnitsConverterFactory( 36 icu_experimental::units::converter_factory::ConverterFactory::new(), 37 )) 38 } 39 /// Construct a new [`UnitsConverterFactory`] instance using a particular data source. 40 #[diplomat::rust_link( 41 icu::experimental::units::converter_factory::ConverterFactory::new, 42 FnInStruct 43 )] 44 #[diplomat::attr(all(supports = fallible_constructors, supports = named_constructors), named_constructor = "with_provider")] 45 #[cfg(feature = "buffer_provider")] create_with_provider( provider: &DataProvider, ) -> Result<Box<UnitsConverterFactory>, DataError>46 pub fn create_with_provider( 47 provider: &DataProvider, 48 ) -> Result<Box<UnitsConverterFactory>, DataError> { 49 Ok(Box::new(UnitsConverterFactory(icu_experimental::units::converter_factory::ConverterFactory::try_new_with_buffer_provider(provider.get()?)?))) 50 } 51 /// Creates a new [`UnitsConverter`] from the input and output [`MeasureUnit`]s. 52 /// Returns nothing if the conversion between the two units is not possible. 53 /// For example, conversion between `meter` and `second` is not possible. 54 #[diplomat::rust_link( 55 icu::experimental::units::converter_factory::ConverterFactory::converter, 56 FnInStruct 57 )] converter( &self, from: &MeasureUnit, to: &MeasureUnit, ) -> Option<Box<UnitsConverter>>58 pub fn converter( 59 &self, 60 from: &MeasureUnit, 61 to: &MeasureUnit, 62 ) -> Option<Box<UnitsConverter>> { 63 self.0 64 .converter(&from.0, &to.0) 65 .map(UnitsConverter) 66 .map(Box::new) 67 } 68 69 /// Creates a parser to parse the CLDR unit identifier (e.g. `meter-per-square-second`) and get the [`MeasureUnit`]. 70 #[diplomat::rust_link( 71 icu::experimental::units::converter_factory::ConverterFactory::parser, 72 FnInStruct 73 )] parser<'a>(&'a self) -> Box<MeasureUnitParser<'a>>74 pub fn parser<'a>(&'a self) -> Box<MeasureUnitParser<'a>> { 75 MeasureUnitParser(self.0.parser()).into() 76 } 77 } 78 79 #[diplomat::opaque] 80 /// An ICU4X Measurement Unit parser object which is capable of parsing the CLDR unit identifier 81 /// (e.g. `meter-per-square-second`) and get the [`MeasureUnit`]. 82 #[diplomat::rust_link(icu::experimental::measure::parser::MeasureUnitParser, Struct)] 83 pub struct MeasureUnitParser<'a>(pub icu_experimental::measure::parser::MeasureUnitParser<'a>); 84 85 impl<'a> MeasureUnitParser<'a> { 86 /// Parses the CLDR unit identifier (e.g. `meter-per-square-second`) and returns the corresponding [`MeasureUnit`], 87 /// if the identifier is valid. 88 #[diplomat::rust_link( 89 icu::experimental::measure::parser::MeasureUnitParser::parse, 90 FnInStruct 91 )] parse(&self, unit_id: &DiplomatStr) -> Option<Box<MeasureUnit>>92 pub fn parse(&self, unit_id: &DiplomatStr) -> Option<Box<MeasureUnit>> { 93 self.0 94 .try_from_utf8(unit_id) 95 .ok() 96 .map(MeasureUnit) 97 .map(Box::new) 98 } 99 } 100 101 #[diplomat::opaque] 102 /// An ICU4X Measurement Unit object which represents a single unit of measurement 103 /// such as `meter`, `second`, `kilometer-per-hour`, `square-meter`, etc. 104 /// 105 /// You can create an instance of this object using [`MeasureUnitParser`] by calling the `parse_measure_unit` method. 106 #[diplomat::rust_link(icu::experimental::measure::measureunit::MeasureUnit, Struct)] 107 pub struct MeasureUnit(pub icu_experimental::measure::measureunit::MeasureUnit); 108 109 #[diplomat::opaque] 110 /// An ICU4X Units Converter object, capable of converting between two [`MeasureUnit`]s. 111 /// 112 /// You can create an instance of this object using [`UnitsConverterFactory`] by calling the `converter` method. 113 #[diplomat::rust_link(icu::experimental::units::converter::UnitsConverter, Struct)] 114 pub struct UnitsConverter(pub icu_experimental::units::converter::UnitsConverter<f64>); 115 impl UnitsConverter { 116 /// Converts the input value from the input unit to the output unit (that have been used to create this converter). 117 /// NOTE: 118 /// The conversion using floating-point operations is not as accurate as the conversion using ratios. 119 #[diplomat::rust_link( 120 icu::experimental::units::converter::UnitsConverter::convert, 121 FnInStruct 122 )] 123 #[diplomat::attr(supports = method_overloading, rename = "convert")] 124 #[diplomat::attr(js, rename = "convert_number")] convert_double(&self, value: f64) -> f64125 pub fn convert_double(&self, value: f64) -> f64 { 126 self.0.convert(&value) 127 } 128 129 /// Clones the current [`UnitsConverter`] object. 130 #[diplomat::rust_link( 131 icu::experimental::units::converter::UnitsConverter::clone, 132 FnInStruct 133 )] clone(&self) -> Box<Self>134 pub fn clone(&self) -> Box<Self> { 135 Box::new(UnitsConverter(self.0.clone())) 136 } 137 } 138 } 139