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 use crate::{ 16 date::ffi::IsoDate, errors::ffi::TimeZoneInvalidOffsetError, time::ffi::Time, 17 timezone::ffi::TimeZone, 18 }; 19 20 #[diplomat::rust_link(icu::time::zone::UtcOffsetCalculator, Struct)] 21 #[diplomat::opaque] 22 pub struct UtcOffsetCalculator(pub icu_time::zone::UtcOffsetCalculator); 23 24 #[diplomat::opaque] 25 #[diplomat::rust_link(icu::time::zone::UtcOffset, Struct)] 26 pub struct UtcOffset(pub(crate) icu_time::zone::UtcOffset); 27 28 #[diplomat::out] 29 #[diplomat::rust_link(icu::time::zone::UtcOffsets, Struct)] 30 pub struct UtcOffsets { 31 pub standard: Box<UtcOffset>, 32 pub daylight: Option<Box<UtcOffset>>, 33 } 34 35 impl UtcOffset { 36 /// Creates an offset from seconds. 37 /// 38 /// Errors if the offset seconds are out of range. 39 #[diplomat::rust_link(icu::time::zone::UtcOffset::try_from_seconds, FnInStruct)] 40 #[diplomat::rust_link( 41 icu::time::zone::UtcOffset::from_seconds_unchecked, 42 FnInStruct, 43 hidden 44 )] 45 #[diplomat::attr(auto, named_constructor = "from_seconds")] from_seconds(seconds: i32) -> Result<Box<UtcOffset>, TimeZoneInvalidOffsetError>46 pub fn from_seconds(seconds: i32) -> Result<Box<UtcOffset>, TimeZoneInvalidOffsetError> { 47 Ok(Box::new(Self(icu_time::zone::UtcOffset::try_from_seconds( 48 seconds, 49 )?))) 50 } 51 52 /// Creates an offset from eighths of an hour. 53 #[diplomat::rust_link(icu::time::zone::UtcOffset, Struct, compact)] 54 #[diplomat::rust_link(icu::time::zone::UtcOffset::from_eighths_of_hour, FnInStruct)] 55 #[diplomat::attr(auto, named_constructor = "from_eights_of_hour")] from_eighths_of_hour(eighths_of_hour: i8) -> Box<Self>56 pub fn from_eighths_of_hour(eighths_of_hour: i8) -> Box<Self> { 57 Box::new(Self(icu_time::zone::UtcOffset::from_eighths_of_hour( 58 eighths_of_hour, 59 ))) 60 } 61 62 /// Creates an offset from a string. 63 #[diplomat::rust_link(icu::time::zone::UtcOffset, Struct, compact)] 64 #[diplomat::rust_link(icu::time::zone::UtcOffset::try_from_str, FnInStruct)] 65 #[diplomat::rust_link(icu::time::zone::UtcOffset::try_from_utf8, FnInStruct, hidden)] 66 #[diplomat::rust_link(icu::time::zone::UtcOffset::from_str, FnInStruct, hidden)] 67 #[diplomat::attr(auto, named_constructor = "from_string")] 68 #[diplomat::demo(default_constructor)] from_string(offset: &DiplomatStr) -> Result<Box<Self>, TimeZoneInvalidOffsetError>69 pub fn from_string(offset: &DiplomatStr) -> Result<Box<Self>, TimeZoneInvalidOffsetError> { 70 icu_time::zone::UtcOffset::try_from_utf8(offset) 71 .map_err(|_| TimeZoneInvalidOffsetError) 72 .map(Self) 73 .map(Box::new) 74 } 75 76 /// Gets the offset as eighths of an hour. 77 #[diplomat::rust_link(icu::time::zone::UtcOffset::to_eighths_of_hour, FnInStruct)] 78 #[diplomat::attr(auto, getter)] eighths_of_hour(&self) -> i879 pub fn eighths_of_hour(&self) -> i8 { 80 self.0.to_eighths_of_hour() 81 } 82 83 /// Returns the value as offset seconds. 84 #[diplomat::rust_link(icu::time::TimeZoneInfo::offset, FnInStruct)] 85 #[diplomat::rust_link(icu::time::zone::UtcOffset::to_seconds, FnInStruct)] 86 #[diplomat::rust_link(icu::time::zone::UtcOffset, Struct, compact)] 87 #[diplomat::attr(auto, getter)] seconds(&self) -> i3288 pub fn seconds(&self) -> i32 { 89 self.0.to_seconds() 90 } 91 92 /// Returns whether the offset is positive. 93 #[diplomat::rust_link(icu::time::zone::UtcOffset::is_non_negative, FnInStruct)] 94 #[diplomat::rust_link(icu::time::zone::UtcOffset, Struct, compact)] 95 #[diplomat::attr(auto, getter)] is_non_negative(&self) -> bool96 pub fn is_non_negative(&self) -> bool { 97 self.0.is_non_negative() 98 } 99 100 /// Returns whether the offset is zero. 101 #[diplomat::rust_link(icu::time::zone::UtcOffset::is_zero, FnInStruct)] 102 #[diplomat::rust_link(icu::time::zone::UtcOffset, Struct, compact)] 103 #[diplomat::attr(auto, getter)] is_zero(&self) -> bool104 pub fn is_zero(&self) -> bool { 105 self.0.is_zero() 106 } 107 108 /// Returns the hours part of the offset. 109 #[diplomat::rust_link(icu::time::zone::UtcOffset::hours_part, FnInStruct)] 110 #[diplomat::rust_link(icu::time::zone::UtcOffset, Struct, compact)] 111 #[diplomat::attr(auto, getter)] hours_part(&self) -> i32112 pub fn hours_part(&self) -> i32 { 113 self.0.hours_part() 114 } 115 116 /// Returns the minutes part of the offset. 117 #[diplomat::rust_link(icu::time::zone::UtcOffset::minutes_part, FnInStruct)] 118 #[diplomat::rust_link(icu::time::zone::UtcOffset, Struct, compact)] 119 #[diplomat::attr(auto, getter)] minutes_part(&self) -> u32120 pub fn minutes_part(&self) -> u32 { 121 self.0.minutes_part() 122 } 123 124 /// Returns the seconds part of the offset. 125 #[diplomat::rust_link(icu::time::zone::UtcOffset::seconds_part, FnInStruct)] 126 #[diplomat::rust_link(icu::time::zone::UtcOffset, Struct, compact)] 127 #[diplomat::attr(auto, getter)] seconds_part(&self) -> u32128 pub fn seconds_part(&self) -> u32 { 129 self.0.seconds_part() 130 } 131 } 132 133 impl UtcOffsetCalculator { 134 /// Construct a new [`UtcOffsetCalculator`] instance using compiled data. 135 #[diplomat::rust_link(icu::time::zone::UtcOffsetCalculator::new, FnInStruct)] 136 #[diplomat::attr(auto, constructor)] 137 #[cfg(feature = "compiled_data")] create() -> Box<UtcOffsetCalculator>138 pub fn create() -> Box<UtcOffsetCalculator> { 139 Box::new(UtcOffsetCalculator( 140 icu_time::zone::UtcOffsetCalculator::new(), 141 )) 142 } 143 /// Construct a new [`UtcOffsetCalculator`] instance using a particular data source. 144 #[diplomat::rust_link(icu::time::zone::UtcOffsetCalculator::new, FnInStruct)] 145 #[diplomat::attr(all(supports = fallible_constructors, supports = named_constructors), named_constructor = "with_provider")] 146 #[cfg(feature = "buffer_provider")] create_with_provider( provider: &DataProvider, ) -> Result<Box<UtcOffsetCalculator>, DataError>147 pub fn create_with_provider( 148 provider: &DataProvider, 149 ) -> Result<Box<UtcOffsetCalculator>, DataError> { 150 Ok(Box::new(UtcOffsetCalculator( 151 icu_time::zone::UtcOffsetCalculator::try_new_with_buffer_provider(provider.get()?)?, 152 ))) 153 } 154 155 #[diplomat::rust_link( 156 icu::time::zone::UtcOffsetCalculator::compute_offsets_from_time_zone, 157 FnInStruct 158 )] compute_offsets_from_time_zone( &self, time_zone: &TimeZone, local_date: &IsoDate, local_time: &Time, ) -> Option<UtcOffsets>159 pub fn compute_offsets_from_time_zone( 160 &self, 161 time_zone: &TimeZone, 162 local_date: &IsoDate, 163 local_time: &Time, 164 ) -> Option<UtcOffsets> { 165 let icu_time::zone::UtcOffsets { 166 standard, daylight, .. 167 } = self 168 .0 169 .compute_offsets_from_time_zone(time_zone.0, (local_date.0, local_time.0))?; 170 171 Some(UtcOffsets { 172 standard: Box::new(UtcOffset(standard)), 173 daylight: daylight.map(UtcOffset).map(Box::new), 174 }) 175 } 176 } 177 } 178