• 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 #[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     use alloc::sync::Arc;
11     use core::fmt::Write;
12     use icu_calendar::Iso;
13 
14     use crate::calendar::ffi::Calendar;
15     use crate::errors::ffi::{CalendarError, CalendarParseError};
16 
17     use tinystr::TinyAsciiStr;
18 
19     #[cfg(feature = "calendar")]
20     use crate::week::ffi::WeekCalculator;
21 
22     #[diplomat::enum_convert(icu_calendar::types::Weekday)]
23     pub enum Weekday {
24         Monday = 1,
25         Tuesday,
26         Wednesday,
27         Thursday,
28         Friday,
29         Saturday,
30         Sunday,
31     }
32     #[diplomat::opaque]
33     #[diplomat::transparent_convert]
34     /// An ICU4X Date object capable of containing a ISO-8601 date
35     #[diplomat::rust_link(icu::calendar::Date, Struct)]
36     pub struct IsoDate(pub icu_calendar::Date<icu_calendar::Iso>);
37 
38     impl IsoDate {
39         /// Creates a new [`IsoDate`] from the specified date and time.
40         #[diplomat::rust_link(icu::calendar::Date::try_new_iso, FnInStruct)]
41         #[diplomat::attr(supports = fallible_constructors, constructor)]
create(year: i32, month: u8, day: u8) -> Result<Box<IsoDate>, CalendarError>42         pub fn create(year: i32, month: u8, day: u8) -> Result<Box<IsoDate>, CalendarError> {
43             Ok(Box::new(IsoDate(icu_calendar::Date::try_new_iso(
44                 year, month, day,
45             )?)))
46         }
47 
48         /// Creates a new [`IsoDate`] from an IXDTF string.
49         #[diplomat::rust_link(icu::calendar::Date::try_iso_from_str, FnInStruct)]
50         #[diplomat::rust_link(icu::calendar::Date::try_iso_from_utf8, FnInStruct, hidden)]
51         #[diplomat::rust_link(icu::calendar::Date::from_str, FnInStruct, hidden)]
52         #[diplomat::attr(all(supports = fallible_constructors, supports = named_constructors), named_constructor)]
from_string(v: &DiplomatStr) -> Result<Box<IsoDate>, CalendarParseError>53         pub fn from_string(v: &DiplomatStr) -> Result<Box<IsoDate>, CalendarParseError> {
54             Ok(Box::new(IsoDate(icu_calendar::Date::try_from_utf8(
55                 v, Iso,
56             )?)))
57         }
58 
59         /// Convert this date to one in a different calendar
60         #[diplomat::rust_link(icu::calendar::Date::to_calendar, FnInStruct)]
to_calendar(&self, calendar: &Calendar) -> Box<Date>61         pub fn to_calendar(&self, calendar: &Calendar) -> Box<Date> {
62             Box::new(Date(self.0.to_calendar(calendar.0.clone())))
63         }
64 
65         #[diplomat::rust_link(icu::calendar::Date::to_any, FnInStruct)]
to_any(&self) -> Box<Date>66         pub fn to_any(&self) -> Box<Date> {
67             Box::new(Date(self.0.to_any().wrap_calendar_in_arc()))
68         }
69 
70         /// Returns the 1-indexed day in the year for this date
71         #[diplomat::rust_link(icu::calendar::Date::day_of_year_info, FnInStruct)]
72         #[diplomat::attr(auto, getter)]
day_of_year(&self) -> u1673         pub fn day_of_year(&self) -> u16 {
74             self.0.day_of_year_info().day_of_year
75         }
76 
77         /// Returns the 1-indexed day in the month for this date
78         #[diplomat::rust_link(icu::calendar::Date::day_of_month, FnInStruct)]
79         #[diplomat::attr(auto, getter)]
day_of_month(&self) -> u880         pub fn day_of_month(&self) -> u8 {
81             self.0.day_of_month().0
82         }
83 
84         /// Returns the day in the week for this day
85         #[diplomat::rust_link(icu::calendar::Date::day_of_week, FnInStruct)]
86         #[diplomat::attr(auto, getter)]
day_of_week(&self) -> Weekday87         pub fn day_of_week(&self) -> Weekday {
88             self.0.day_of_week().into()
89         }
90 
91         /// Returns the week number in this month, 1-indexed, based on what
92         /// is considered the first day of the week (often a locale preference).
93         ///
94         /// `first_weekday` can be obtained via `first_weekday()` on [`WeekCalculator`]
95         #[diplomat::rust_link(icu::calendar::Date::week_of_month, FnInStruct)]
96         #[diplomat::rust_link(
97             icu::calendar::week::WeekCalculator::week_of_month,
98             FnInStruct,
99             hidden
100         )]
week_of_month(&self, first_weekday: Weekday) -> u8101         pub fn week_of_month(&self, first_weekday: Weekday) -> u8 {
102             self.0.week_of_month(first_weekday.into()).0
103         }
104 
105         /// Returns the week number in this year, using week data
106         #[diplomat::rust_link(icu::calendar::Date::week_of_year, FnInStruct)]
107         #[diplomat::rust_link(
108             icu::calendar::week::WeekCalculator::week_of_year,
109             FnInStruct,
110             hidden
111         )]
112         #[cfg(feature = "calendar")]
week_of_year(&self, calculator: &WeekCalculator) -> crate::week::ffi::WeekOf113         pub fn week_of_year(&self, calculator: &WeekCalculator) -> crate::week::ffi::WeekOf {
114             self.0.week_of_year(&calculator.0).into()
115         }
116 
117         /// Returns 1-indexed number of the month of this date in its year
118         #[diplomat::rust_link(icu::calendar::types::MonthInfo::ordinal, StructField)]
119         #[diplomat::rust_link(icu::calendar::Date::month, FnInStruct, compact)]
120         #[diplomat::attr(auto, getter)]
month(&self) -> u8121         pub fn month(&self) -> u8 {
122             self.0.month().ordinal
123         }
124 
125         /// Returns the year number in the current era for this date
126         ///
127         /// For calendars without an era, returns the extended year
128         #[diplomat::rust_link(icu::calendar::Date::year, FnInStruct)]
129         #[diplomat::attr(auto, getter)]
year(&self) -> i32130         pub fn year(&self) -> i32 {
131             self.0.year().extended_year
132         }
133 
134         /// Returns if the year is a leap year for this date
135         #[diplomat::rust_link(icu::calendar::Date::is_in_leap_year, FnInStruct)]
136         #[diplomat::attr(auto, getter)]
is_in_leap_year(&self) -> bool137         pub fn is_in_leap_year(&self) -> bool {
138             self.0.is_in_leap_year()
139         }
140 
141         /// Returns the number of months in the year represented by this date
142         #[diplomat::rust_link(icu::calendar::Date::months_in_year, FnInStruct)]
143         #[diplomat::attr(auto, getter)]
months_in_year(&self) -> u8144         pub fn months_in_year(&self) -> u8 {
145             self.0.months_in_year()
146         }
147 
148         /// Returns the number of days in the month represented by this date
149         #[diplomat::rust_link(icu::calendar::Date::days_in_month, FnInStruct)]
150         #[diplomat::attr(auto, getter)]
days_in_month(&self) -> u8151         pub fn days_in_month(&self) -> u8 {
152             self.0.days_in_month()
153         }
154 
155         /// Returns the number of days in the year represented by this date
156         #[diplomat::rust_link(icu::calendar::Date::days_in_year, FnInStruct)]
157         #[diplomat::attr(auto, getter)]
days_in_year(&self) -> u16158         pub fn days_in_year(&self) -> u16 {
159             self.0.days_in_year()
160         }
161     }
162 
163     #[diplomat::opaque]
164     #[diplomat::transparent_convert]
165     /// An ICU4X Date object capable of containing a date and time for any calendar.
166     #[diplomat::rust_link(icu::calendar::Date, Struct)]
167     pub struct Date(pub icu_calendar::Date<Arc<icu_calendar::AnyCalendar>>);
168 
169     impl Date {
170         /// Creates a new [`Date`] representing the ISO date and time
171         /// given but in a given calendar
172         #[diplomat::rust_link(icu::calendar::Date::new_from_iso, FnInStruct)]
173         #[diplomat::attr(all(supports = fallible_constructors, supports = named_constructors), named_constructor)]
174         #[diplomat::demo(default_constructor)]
from_iso_in_calendar( year: i32, month: u8, day: u8, calendar: &Calendar, ) -> Result<Box<Date>, CalendarError>175         pub fn from_iso_in_calendar(
176             year: i32,
177             month: u8,
178             day: u8,
179             calendar: &Calendar,
180         ) -> Result<Box<Date>, CalendarError> {
181             let cal = calendar.0.clone();
182             Ok(Box::new(Date(
183                 icu_calendar::Date::try_new_iso(year, month, day)?.to_calendar(cal),
184             )))
185         }
186 
187         /// Creates a new [`Date`] from the given codes, which are interpreted in the given calendar system
188         ///
189         /// An empty era code will treat the year as an extended year
190         #[diplomat::rust_link(icu::calendar::Date::try_new_from_codes, FnInStruct)]
191         #[diplomat::attr(all(supports = fallible_constructors, supports = named_constructors), named_constructor)]
from_codes_in_calendar( era_code: &DiplomatStr, year: i32, month_code: &DiplomatStr, day: u8, calendar: &Calendar, ) -> Result<Box<Date>, CalendarError>192         pub fn from_codes_in_calendar(
193             era_code: &DiplomatStr,
194             year: i32,
195             month_code: &DiplomatStr,
196             day: u8,
197             calendar: &Calendar,
198         ) -> Result<Box<Date>, CalendarError> {
199             let era = if era_code.is_empty() {
200                 Some(icu_calendar::types::Era(
201                     TinyAsciiStr::try_from_utf8(era_code).map_err(|_| CalendarError::UnknownEra)?,
202                 ))
203             } else {
204                 None
205             };
206             let month = icu_calendar::types::MonthCode(
207                 TinyAsciiStr::try_from_utf8(month_code)
208                     .map_err(|_| CalendarError::UnknownMonthCode)?,
209             );
210             let cal = calendar.0.clone();
211             Ok(Box::new(Date(icu_calendar::Date::try_new_from_codes(
212                 era, year, month, day, cal,
213             )?)))
214         }
215 
216         /// Creates a new [`Date`] from an IXDTF string.
217         #[diplomat::rust_link(icu::calendar::Date::try_from_str, FnInStruct)]
218         #[diplomat::rust_link(icu::calendar::Date::try_from_utf8, FnInStruct, hidden)]
219         #[diplomat::rust_link(icu::calendar::Date::from_str, FnInStruct, hidden)]
220         #[diplomat::attr(all(supports = fallible_constructors, supports = named_constructors), named_constructor)]
from_string( v: &DiplomatStr, calendar: &Calendar, ) -> Result<Box<Date>, CalendarParseError>221         pub fn from_string(
222             v: &DiplomatStr,
223             calendar: &Calendar,
224         ) -> Result<Box<Date>, CalendarParseError> {
225             Ok(Box::new(Date(icu_calendar::Date::try_from_utf8(
226                 v,
227                 calendar.0.clone(),
228             )?)))
229         }
230 
231         /// Convert this date to one in a different calendar
232         #[diplomat::rust_link(icu::calendar::Date::to_calendar, FnInStruct)]
233         #[diplomat::rust_link(icu::calendar::AnyCalendar::convert_any_date, FnInEnum, hidden)]
to_calendar(&self, calendar: &Calendar) -> Box<Date>234         pub fn to_calendar(&self, calendar: &Calendar) -> Box<Date> {
235             Box::new(Date(self.0.to_calendar(calendar.0.clone())))
236         }
237 
238         /// Converts this date to ISO
239         #[diplomat::rust_link(icu::calendar::Date::to_iso, FnInStruct)]
to_iso(&self) -> Box<IsoDate>240         pub fn to_iso(&self) -> Box<IsoDate> {
241             Box::new(IsoDate(self.0.to_iso()))
242         }
243 
244         /// Returns the 1-indexed day in the year for this date
245         #[diplomat::rust_link(icu::calendar::Date::day_of_year_info, FnInStruct)]
246         #[diplomat::attr(auto, getter)]
day_of_year(&self) -> u16247         pub fn day_of_year(&self) -> u16 {
248             self.0.day_of_year_info().day_of_year
249         }
250 
251         /// Returns the 1-indexed day in the month for this date
252         #[diplomat::rust_link(icu::calendar::Date::day_of_month, FnInStruct)]
253         #[diplomat::attr(auto, getter)]
day_of_month(&self) -> u8254         pub fn day_of_month(&self) -> u8 {
255             self.0.day_of_month().0
256         }
257 
258         /// Returns the day in the week for this day
259         #[diplomat::rust_link(icu::calendar::Date::day_of_week, FnInStruct)]
260         #[diplomat::attr(auto, getter)]
day_of_week(&self) -> Weekday261         pub fn day_of_week(&self) -> Weekday {
262             self.0.day_of_week().into()
263         }
264 
265         /// Returns the week number in this month, 1-indexed, based on what
266         /// is considered the first day of the week (often a locale preference).
267         ///
268         /// `first_weekday` can be obtained via `first_weekday()` on [`WeekCalculator`]
269         #[diplomat::rust_link(icu::calendar::Date::week_of_month, FnInStruct)]
270         #[diplomat::rust_link(
271             icu::calendar::week::WeekCalculator::week_of_month,
272             FnInStruct,
273             hidden
274         )]
week_of_month(&self, first_weekday: Weekday) -> u8275         pub fn week_of_month(&self, first_weekday: Weekday) -> u8 {
276             self.0.week_of_month(first_weekday.into()).0
277         }
278 
279         /// Returns the week number in this year, using week data
280         #[diplomat::rust_link(icu::calendar::Date::week_of_year, FnInStruct)]
281         #[diplomat::rust_link(
282             icu::calendar::week::WeekCalculator::week_of_year,
283             FnInStruct,
284             hidden
285         )]
286         #[cfg(feature = "calendar")]
week_of_year(&self, calculator: &WeekCalculator) -> crate::week::ffi::WeekOf287         pub fn week_of_year(&self, calculator: &WeekCalculator) -> crate::week::ffi::WeekOf {
288             self.0.week_of_year(&calculator.0).into()
289         }
290 
291         /// Returns 1-indexed number of the month of this date in its year
292         ///
293         /// Note that for lunar calendars this may not lead to the same month
294         /// having the same ordinal month across years; use month_code if you care
295         /// about month identity.
296         #[diplomat::rust_link(icu::calendar::Date::month, FnInStruct)]
297         #[diplomat::rust_link(icu::calendar::types::MonthInfo::ordinal, StructField)]
298         #[diplomat::attr(auto, getter)]
ordinal_month(&self) -> u8299         pub fn ordinal_month(&self) -> u8 {
300             self.0.month().ordinal
301         }
302 
303         /// Returns the month code for this date. Typically something
304         /// like "M01", "M02", but can be more complicated for lunar calendars.
305         #[diplomat::rust_link(icu::calendar::types::MonthInfo::standard_code, StructField)]
306         #[diplomat::rust_link(icu::calendar::Date::month, FnInStruct, compact)]
307         #[diplomat::rust_link(icu::calendar::types::MonthInfo, Struct, hidden)]
308         #[diplomat::rust_link(
309             icu::calendar::types::MonthInfo::formatting_code,
310             StructField,
311             hidden
312         )]
313         #[diplomat::rust_link(icu::calendar::types::MonthInfo, Struct, hidden)]
314         #[diplomat::attr(auto, getter)]
month_code(&self, write: &mut diplomat_runtime::DiplomatWrite)315         pub fn month_code(&self, write: &mut diplomat_runtime::DiplomatWrite) {
316             let code = self.0.month().standard_code;
317             let _infallible = write.write_str(&code.0);
318         }
319 
320         /// Returns the month number of this month.
321         #[diplomat::rust_link(icu::calendar::types::MonthInfo::month_number, FnInStruct)]
322         #[diplomat::attr(auto, getter)]
month_number(&self) -> u8323         pub fn month_number(&self) -> u8 {
324             self.0.month().month_number()
325         }
326 
327         /// Returns whether the month is a leap month.
328         #[diplomat::rust_link(icu::calendar::types::MonthInfo::is_leap, FnInStruct)]
329         #[diplomat::attr(auto, getter)]
month_is_leap(&self) -> bool330         pub fn month_is_leap(&self) -> bool {
331             self.0.month().is_leap()
332         }
333 
334         /// Returns the year number in the current era for this date
335         ///
336         /// For calendars without an era, returns the extended year
337         #[diplomat::rust_link(icu::calendar::types::YearInfo::era_year_or_extended, FnInStruct)]
338         #[diplomat::rust_link(icu::calendar::types::EraYear::era_year, StructField, compact)]
339         #[diplomat::rust_link(icu::calendar::types::YearInfo::era_year, FnInStruct, hidden)]
340         #[diplomat::rust_link(icu::calendar::Date::year, FnInStruct, compact)]
341         #[diplomat::rust_link(icu::calendar::types::EraYear, Struct, hidden)]
342         #[diplomat::rust_link(icu::calendar::types::YearKind, Enum, hidden)]
343         #[diplomat::rust_link(icu::calendar::types::YearInfo, Struct, hidden)]
344         #[diplomat::attr(auto, getter)]
year_in_era(&self) -> i32345         pub fn year_in_era(&self) -> i32 {
346             self.0.year().era_year_or_extended()
347         }
348 
349         /// Returns the extended year in the Date
350         #[diplomat::rust_link(icu::calendar::types::YearInfo::extended_year, StructField)]
351         #[diplomat::rust_link(icu::calendar::types::YearInfo, StructField, hidden)]
352         #[diplomat::attr(auto, getter)]
extended_year(&self) -> i32353         pub fn extended_year(&self) -> i32 {
354             self.0.year().extended_year
355         }
356 
357         /// Returns the era for this date, or an empty string
358         #[diplomat::rust_link(icu::calendar::types::EraYear::standard_era, StructField)]
359         #[diplomat::rust_link(icu::calendar::types::YearInfo::standard_era, FnInStruct, hidden)]
360         #[diplomat::rust_link(icu::calendar::Date::year, FnInStruct, compact)]
361         #[diplomat::rust_link(icu::calendar::types::EraYear, Struct, hidden)]
362         #[diplomat::rust_link(icu::calendar::types::YearKind, Enum, hidden)]
363         #[diplomat::rust_link(icu::calendar::types::YearInfo, Struct, hidden)]
364         #[diplomat::rust_link(icu::calendar::types::EraYear::formatting_era, StructField, hidden)]
365         #[diplomat::rust_link(icu::calendar::types::YearInfo::formatting_era, FnInStruct, hidden)]
366         #[diplomat::attr(auto, getter)]
era(&self, write: &mut diplomat_runtime::DiplomatWrite)367         pub fn era(&self, write: &mut diplomat_runtime::DiplomatWrite) {
368             if let Some(era) = self.0.year().standard_era() {
369                 let _infallible = write.write_str(&era.0);
370             }
371         }
372 
373         /// Returns the number of months in the year represented by this date
374         #[diplomat::rust_link(icu::calendar::Date::months_in_year, FnInStruct)]
375         #[diplomat::attr(auto, getter)]
months_in_year(&self) -> u8376         pub fn months_in_year(&self) -> u8 {
377             self.0.months_in_year()
378         }
379 
380         /// Returns the number of days in the month represented by this date
381         #[diplomat::rust_link(icu::calendar::Date::days_in_month, FnInStruct)]
382         #[diplomat::attr(auto, getter)]
days_in_month(&self) -> u8383         pub fn days_in_month(&self) -> u8 {
384             self.0.days_in_month()
385         }
386 
387         /// Returns the number of days in the year represented by this date
388         #[diplomat::rust_link(icu::calendar::Date::days_in_year, FnInStruct)]
389         #[diplomat::attr(auto, getter)]
days_in_year(&self) -> u16390         pub fn days_in_year(&self) -> u16 {
391             self.0.days_in_year()
392         }
393 
394         /// Returns the [`Calendar`] object backing this date
395         #[diplomat::rust_link(icu::calendar::Date::calendar, FnInStruct)]
396         #[diplomat::rust_link(icu::calendar::Date::calendar_wrapper, FnInStruct, hidden)]
397         #[diplomat::attr(auto, getter)]
calendar(&self) -> Box<Calendar>398         pub fn calendar(&self) -> Box<Calendar> {
399             Box::new(Calendar(self.0.calendar_wrapper().clone()))
400         }
401     }
402 }
403