1use ffi::IsoWeekOfYear;
6
7#[diplomat::bridge]
8#[diplomat::abi_rename = "icu4x_{0}_mv1"]
9pub mod ffi {
10 use alloc::boxed::Box;
11 use alloc::sync::Arc;
12 use core::fmt::Write;
13 #[cfg(feature = "unstable")]
14 use diplomat_runtime::DiplomatOption;
15 use icu_calendar::Iso;
16
17 use crate::unstable::calendar::ffi::Calendar;
18 #[cfg(feature = "unstable")]
19 use crate::unstable::errors::ffi::CalendarDateFromFieldsError;
20 use crate::unstable::errors::ffi::{CalendarError, Rfc9557ParseError};
21
22 use tinystr::TinyAsciiStr;
23
24 #[diplomat::enum_convert(icu_calendar::types::Weekday)]
25 #[diplomat::rust_link(icu::calendar::types::Weekday, Enum)]
26 #[non_exhaustive]
27 pub enum Weekday {
28 Monday = 1,
29 Tuesday,
30 Wednesday,
31 Thursday,
32 Friday,
33 Saturday,
34 Sunday,
35 }
36 #[diplomat::opaque]
37 #[diplomat::transparent_convert]
38 #[diplomat::rust_link(icu::calendar::Date, Struct)]
40 pub struct IsoDate(pub icu_calendar::Date<icu_calendar::Iso>);
41
42 impl IsoDate {
43 #[diplomat::rust_link(icu::calendar::Date::try_new_iso, FnInStruct)]
45 #[diplomat::attr(supports = fallible_constructors, constructor)]
46 pub fn create(year: i32, month: u8, day: u8) -> Result<Box<IsoDate>, CalendarError> {
47 Ok(Box::new(IsoDate(icu_calendar::Date::try_new_iso(
48 year, month, day,
49 )?)))
50 }
51
52 #[diplomat::rust_link(icu::calendar::Date::from_rata_die, FnInStruct)]
54 #[diplomat::attr(all(supports = named_constructors), named_constructor)]
55 #[diplomat::demo(default_constructor)]
56 #[diplomat::attr(demo_gen, disable)] pub fn from_rata_die(rd: i64) -> Box<IsoDate> {
58 Box::new(IsoDate(icu_calendar::Date::from_rata_die(
59 icu_calendar::types::RataDie::new(rd),
60 Iso,
61 )))
62 }
63
64 #[diplomat::rust_link(icu::calendar::Date::try_from_str, FnInStruct)]
66 #[diplomat::rust_link(icu::calendar::Date::try_from_utf8, FnInStruct, hidden)]
67 #[diplomat::rust_link(icu::calendar::Date::from_str, FnInStruct, hidden)]
68 #[diplomat::attr(all(supports = fallible_constructors, supports = named_constructors), named_constructor)]
69 #[diplomat::attr(demo_gen, disable)] pub fn from_string(v: &DiplomatStr) -> Result<Box<IsoDate>, Rfc9557ParseError> {
71 Ok(Box::new(IsoDate(icu_calendar::Date::try_from_utf8(
72 v, Iso,
73 )?)))
74 }
75
76 #[diplomat::rust_link(icu::calendar::Date::to_calendar, FnInStruct)]
78 #[diplomat::attr(demo_gen, disable)] pub fn to_calendar(&self, calendar: &Calendar) -> Box<Date> {
80 Box::new(Date(self.0.to_calendar(calendar.0.clone())))
81 }
82
83 #[diplomat::rust_link(icu::calendar::Date::to_any, FnInStruct)]
84 #[diplomat::attr(demo_gen, disable)] pub fn to_any(&self) -> Box<Date> {
86 Box::new(Date(self.0.to_any().into_atomic_ref_counted()))
87 }
88
89 #[diplomat::rust_link(icu::calendar::Date::to_rata_die, FnInStruct)]
91 #[diplomat::attr(auto, getter = "rata_die")]
92 #[diplomat::attr(demo_gen, disable)] pub fn to_rata_die(&self) -> i64 {
94 self.0.to_rata_die().to_i64_date()
95 }
96
97 #[diplomat::rust_link(icu::calendar::Date::day_of_year, FnInStruct)]
99 #[diplomat::attr(auto, getter)]
100 #[diplomat::attr(demo_gen, disable)] pub fn day_of_year(&self) -> u16 {
102 self.0.day_of_year().0
103 }
104
105 #[diplomat::rust_link(icu::calendar::Date::day_of_month, FnInStruct)]
107 #[diplomat::attr(auto, getter)]
108 #[diplomat::attr(demo_gen, disable)] pub fn day_of_month(&self) -> u8 {
110 self.0.day_of_month().0
111 }
112
113 #[diplomat::rust_link(icu::calendar::Date::day_of_week, FnInStruct)]
115 #[diplomat::attr(auto, getter)]
116 #[diplomat::attr(demo_gen, disable)] pub fn day_of_week(&self) -> Weekday {
118 self.0.day_of_week().into()
119 }
120
121 #[diplomat::rust_link(icu::calendar::Date::week_of_year, FnInStruct)]
123 #[cfg(feature = "calendar")]
124 #[diplomat::attr(demo_gen, disable)] pub fn week_of_year(&self) -> IsoWeekOfYear {
126 self.0.week_of_year().into()
127 }
128
129 #[diplomat::rust_link(icu::calendar::types::MonthInfo::ordinal, StructField)]
131 #[diplomat::rust_link(icu::calendar::Date::month, FnInStruct, compact)]
132 #[diplomat::attr(auto, getter)]
133 #[diplomat::attr(demo_gen, disable)] pub fn month(&self) -> u8 {
135 self.0.month().ordinal
136 }
137
138 #[diplomat::rust_link(icu::calendar::Date::year, FnInStruct)]
142 #[diplomat::attr(auto, getter)]
143 #[diplomat::attr(demo_gen, disable)] pub fn year(&self) -> i32 {
145 self.0.extended_year()
146 }
147
148 #[diplomat::rust_link(icu::calendar::Date::is_in_leap_year, FnInStruct)]
150 #[diplomat::attr(auto, getter)]
151 #[diplomat::attr(demo_gen, disable)] pub fn is_in_leap_year(&self) -> bool {
153 self.0.is_in_leap_year()
154 }
155
156 #[diplomat::rust_link(icu::calendar::Date::months_in_year, FnInStruct)]
158 #[diplomat::attr(auto, getter)]
159 #[diplomat::attr(demo_gen, disable)] pub fn months_in_year(&self) -> u8 {
161 self.0.months_in_year()
162 }
163
164 #[diplomat::rust_link(icu::calendar::Date::days_in_month, FnInStruct)]
166 #[diplomat::attr(auto, getter)]
167 #[diplomat::attr(demo_gen, disable)] pub fn days_in_month(&self) -> u8 {
169 self.0.days_in_month()
170 }
171
172 #[diplomat::rust_link(icu::calendar::Date::days_in_year, FnInStruct)]
174 #[diplomat::attr(auto, getter)]
175 #[diplomat::attr(demo_gen, disable)] pub fn days_in_year(&self) -> u16 {
177 self.0.days_in_year()
178 }
179 }
180
181 #[diplomat::rust_link(icu::calendar::options::DateFromFieldsOptions, Struct)]
183 #[cfg(feature = "unstable")]
184 pub struct DateFromFieldsOptions {
185 pub overflow: DiplomatOption<DateOverflow>,
186 pub missing_fields_strategy: DiplomatOption<DateMissingFieldsStrategy>,
187 }
188
189 #[diplomat::rust_link(icu::calendar::types::DateFields, Struct)]
191 #[cfg(feature = "unstable")]
192 pub struct DateFields<'a> {
193 pub era: DiplomatOption<&'a DiplomatStr>,
194 pub era_year: DiplomatOption<i32>,
195 pub extended_year: DiplomatOption<i32>,
196 pub month_code: DiplomatOption<&'a DiplomatStr>,
197 pub ordinal_month: DiplomatOption<u8>,
198 pub day: DiplomatOption<u8>,
199 }
200
201 #[diplomat::enum_convert(icu_calendar::options::Overflow, needs_wildcard)]
203 #[diplomat::rust_link(icu::calendar::options::Overflow, Enum)]
204 #[non_exhaustive]
205 #[cfg(feature = "unstable")]
206 pub enum DateOverflow {
207 Constrain,
208 Reject,
209 }
210
211 #[diplomat::enum_convert(icu_calendar::options::MissingFieldsStrategy, needs_wildcard)]
213 #[diplomat::rust_link(icu::calendar::options::MissingFieldsStrategy, Enum)]
214 #[non_exhaustive]
215 #[cfg(feature = "unstable")]
216 pub enum DateMissingFieldsStrategy {
217 Reject,
218 Ecma,
219 }
220
221 #[diplomat::opaque]
222 #[diplomat::transparent_convert]
223 #[diplomat::rust_link(icu::calendar::Date, Struct)]
225 pub struct Date(pub icu_calendar::Date<Arc<icu_calendar::AnyCalendar>>);
226
227 impl Date {
228 #[diplomat::rust_link(icu::calendar::Date::new_from_iso, FnInStruct)]
231 #[diplomat::attr(all(supports = fallible_constructors, supports = named_constructors), named_constructor)]
232 #[diplomat::demo(default_constructor)]
233 pub fn from_iso_in_calendar(
234 iso_year: i32,
235 iso_month: u8,
236 iso_day: u8,
237 calendar: &Calendar,
238 ) -> Result<Box<Date>, CalendarError> {
239 let cal = calendar.0.clone();
240 Ok(Box::new(Date(
241 icu_calendar::Date::try_new_iso(iso_year, iso_month, iso_day)?.to_calendar(cal),
242 )))
243 }
244
245 #[diplomat::rust_link(icu::calendar::Date::try_from_fields, FnInStruct)]
249 #[diplomat::attr(all(supports = fallible_constructors, supports = named_constructors), named_constructor)]
250 #[cfg(feature = "unstable")]
251 pub fn from_fields_in_calendar(
252 fields: DateFields,
253 options: DateFromFieldsOptions,
254 calendar: &Calendar,
255 ) -> Result<Box<Date>, CalendarDateFromFieldsError> {
256 let cal = calendar.0.clone();
257 Ok(Box::new(Date(icu_calendar::Date::try_from_fields(
258 fields.into(),
259 options.into(),
260 cal,
261 )?)))
262 }
263
264 #[diplomat::rust_link(icu::calendar::Date::try_new_from_codes, FnInStruct)]
268 #[diplomat::attr(all(supports = fallible_constructors, supports = named_constructors), named_constructor)]
269 pub fn from_codes_in_calendar(
270 era_code: &DiplomatStr,
271 year: i32,
272 month_code: &DiplomatStr,
273 day: u8,
274 calendar: &Calendar,
275 ) -> Result<Box<Date>, CalendarError> {
276 let era = if !era_code.is_empty() {
277 Some(core::str::from_utf8(era_code).map_err(|_| CalendarError::UnknownEra)?)
278 } else {
279 None
280 };
281 let month = icu_calendar::types::MonthCode(
282 TinyAsciiStr::try_from_utf8(month_code)
283 .map_err(|_| CalendarError::UnknownMonthCode)?,
284 );
285 let cal = calendar.0.clone();
286 Ok(Box::new(Date(icu_calendar::Date::try_new_from_codes(
287 era, year, month, day, cal,
288 )?)))
289 }
290
291 #[diplomat::rust_link(icu::calendar::Date::from_rata_die, FnInStruct)]
293 #[diplomat::attr(all(supports = named_constructors), named_constructor)]
294 #[diplomat::demo(default_constructor)]
295 pub fn from_rata_die(rd: i64, calendar: &Calendar) -> Result<Box<Date>, CalendarError> {
296 let cal = calendar.0.clone();
297 Ok(Box::new(Date(icu_calendar::Date::from_rata_die(
298 icu_calendar::types::RataDie::new(rd),
299 cal,
300 ))))
301 }
302
303 #[diplomat::rust_link(icu::calendar::Date::try_from_str, FnInStruct)]
305 #[diplomat::rust_link(icu::calendar::Date::try_from_utf8, FnInStruct, hidden)]
306 #[diplomat::rust_link(icu::calendar::Date::from_str, FnInStruct, hidden)]
307 #[diplomat::attr(all(supports = fallible_constructors, supports = named_constructors), named_constructor)]
308 pub fn from_string(
309 v: &DiplomatStr,
310 calendar: &Calendar,
311 ) -> Result<Box<Date>, Rfc9557ParseError> {
312 Ok(Box::new(Date(icu_calendar::Date::try_from_utf8(
313 v,
314 calendar.0.clone(),
315 )?)))
316 }
317
318 #[diplomat::rust_link(icu::calendar::Date::to_calendar, FnInStruct)]
320 #[diplomat::rust_link(icu::calendar::Date::convert_any, FnInStruct, hidden)]
321 pub fn to_calendar(&self, calendar: &Calendar) -> Box<Date> {
322 Box::new(Date(self.0.to_calendar(calendar.0.clone())))
323 }
324
325 #[diplomat::rust_link(icu::calendar::Date::to_iso, FnInStruct)]
327 pub fn to_iso(&self) -> Box<IsoDate> {
328 Box::new(IsoDate(self.0.to_iso()))
329 }
330
331 #[diplomat::rust_link(icu::calendar::Date::to_rata_die, FnInStruct)]
333 #[diplomat::attr(auto, getter = "rata_die")]
334 pub fn to_rata_die(&self) -> i64 {
335 self.0.to_rata_die().to_i64_date()
336 }
337
338 #[diplomat::rust_link(icu::calendar::Date::day_of_year, FnInStruct)]
340 #[diplomat::attr(auto, getter)]
341 pub fn day_of_year(&self) -> u16 {
342 self.0.day_of_year().0
343 }
344
345 #[diplomat::rust_link(icu::calendar::Date::day_of_month, FnInStruct)]
347 #[diplomat::attr(auto, getter)]
348 pub fn day_of_month(&self) -> u8 {
349 self.0.day_of_month().0
350 }
351
352 #[diplomat::rust_link(icu::calendar::Date::day_of_week, FnInStruct)]
354 #[diplomat::attr(auto, getter)]
355 pub fn day_of_week(&self) -> Weekday {
356 self.0.day_of_week().into()
357 }
358
359 #[diplomat::rust_link(icu::calendar::Date::month, FnInStruct)]
365 #[diplomat::rust_link(icu::calendar::types::MonthInfo::ordinal, StructField)]
366 #[diplomat::attr(auto, getter)]
367 pub fn ordinal_month(&self) -> u8 {
368 self.0.month().ordinal
369 }
370
371 #[diplomat::rust_link(icu::calendar::types::MonthInfo::standard_code, StructField)]
374 #[diplomat::rust_link(icu::calendar::Date::month, FnInStruct, compact)]
375 #[diplomat::rust_link(icu::calendar::types::MonthInfo, Struct, hidden)]
376 #[diplomat::rust_link(
377 icu::calendar::types::MonthInfo::formatting_code,
378 StructField,
379 hidden
380 )]
381 #[diplomat::rust_link(icu::calendar::types::MonthInfo, Struct, hidden)]
382 #[diplomat::attr(auto, getter)]
383 pub fn month_code(&self, write: &mut diplomat_runtime::DiplomatWrite) {
384 let code = self.0.month().standard_code;
385 let _infallible = write.write_str(&code.0);
386 }
387
388 #[diplomat::rust_link(icu::calendar::types::MonthInfo::month_number, FnInStruct)]
390 #[diplomat::attr(auto, getter)]
391 pub fn month_number(&self) -> u8 {
392 self.0.month().month_number()
393 }
394
395 #[diplomat::rust_link(icu::calendar::types::MonthInfo::is_leap, FnInStruct)]
397 #[diplomat::attr(auto, getter)]
398 pub fn month_is_leap(&self) -> bool {
399 self.0.month().is_leap()
400 }
401
402 #[diplomat::rust_link(icu::calendar::types::YearInfo::era_year_or_related_iso, FnInEnum)]
406 #[diplomat::rust_link(icu::calendar::types::EraYear::year, StructField, compact)]
407 #[diplomat::rust_link(icu::calendar::types::CyclicYear::related_iso, StructField, compact)]
408 #[diplomat::rust_link(icu::calendar::Date::year, FnInStruct, compact)]
409 #[diplomat::rust_link(icu::calendar::Date::era_year, FnInStruct, hidden)]
410 #[diplomat::rust_link(icu::calendar::Date::cyclic_year, FnInStruct, hidden)]
411 #[diplomat::rust_link(icu::calendar::types::YearInfo, Enum, hidden)]
412 #[diplomat::rust_link(icu::calendar::types::YearInfo::era, FnInEnum, hidden)]
413 #[diplomat::rust_link(icu::calendar::types::YearInfo::cyclic, FnInEnum, hidden)]
414 #[diplomat::rust_link(icu::calendar::types::EraYear, Struct, hidden)]
415 #[diplomat::rust_link(icu::calendar::types::CyclicYear, Struct, hidden)]
416 #[diplomat::attr(auto, getter)]
417 pub fn era_year_or_related_iso(&self) -> i32 {
418 self.0.year().era_year_or_related_iso()
419 }
420
421 #[diplomat::rust_link(icu::calendar::Date::extended_year, FnInStruct)]
427 #[diplomat::rust_link(icu::calendar::types::YearInfo::extended_year, FnInEnum, hidden)]
428 #[diplomat::attr(auto, getter)]
429 pub fn extended_year(&self) -> i32 {
430 self.0.extended_year()
431 }
432
433 #[diplomat::rust_link(icu::calendar::types::EraYear::era, StructField)]
435 #[diplomat::rust_link(icu::calendar::Date::year, FnInStruct, compact)]
436 #[diplomat::attr(auto, getter)]
437 pub fn era(&self, write: &mut diplomat_runtime::DiplomatWrite) {
438 if let Some(era) = self.0.year().era() {
439 let _infallible = write.write_str(&era.era);
440 }
441 }
442
443 #[diplomat::rust_link(icu::calendar::Date::months_in_year, FnInStruct)]
445 #[diplomat::attr(auto, getter)]
446 pub fn months_in_year(&self) -> u8 {
447 self.0.months_in_year()
448 }
449
450 #[diplomat::rust_link(icu::calendar::Date::days_in_month, FnInStruct)]
452 #[diplomat::attr(auto, getter)]
453 pub fn days_in_month(&self) -> u8 {
454 self.0.days_in_month()
455 }
456
457 #[diplomat::rust_link(icu::calendar::Date::days_in_year, FnInStruct)]
459 #[diplomat::attr(auto, getter)]
460 pub fn days_in_year(&self) -> u16 {
461 self.0.days_in_year()
462 }
463
464 #[diplomat::rust_link(icu::calendar::Date::calendar, FnInStruct)]
466 #[diplomat::rust_link(icu::calendar::Date::calendar_wrapper, FnInStruct, hidden)]
467 #[diplomat::attr(auto, getter)]
468 pub fn calendar(&self) -> Box<Calendar> {
469 Box::new(Calendar(self.0.calendar_wrapper().clone()))
470 }
471 }
472
473 #[diplomat::rust_link(icu::calendar::types::IsoWeekOfYear, Struct)]
474 pub struct IsoWeekOfYear {
475 pub week_number: u8,
476 pub iso_year: i32,
477 }
478}
479
480impl From<icu_calendar::types::IsoWeekOfYear> for IsoWeekOfYear {
481 fn from(
482 icu_calendar::types::IsoWeekOfYear {
483 week_number,
484 iso_year,
485 }: icu_calendar::types::IsoWeekOfYear,
486 ) -> Self {
487 Self {
488 week_number,
489 iso_year,
490 }
491 }
492}
493
494#[cfg(feature = "unstable")]
495impl From<ffi::DateFromFieldsOptions> for icu_calendar::options::DateFromFieldsOptions {
496 fn from(other: ffi::DateFromFieldsOptions) -> Self {
497 let mut options = Self::default();
498
499 options.overflow = other.overflow.into_converted_option();
500 options.missing_fields_strategy = other.missing_fields_strategy.into_converted_option();
501
502 options
503 }
504}
505
506#[cfg(feature = "unstable")]
507impl<'a> From<ffi::DateFields<'a>> for icu_calendar::types::DateFields<'a> {
508 fn from(other: ffi::DateFields<'a>) -> Self {
509 let mut fields = Self::default();
510 fields.era = other.era.into_option();
511 fields.era_year = other.era_year.into();
512 fields.extended_year = other.extended_year.into();
513 fields.month_code = other.month_code.into_option();
514 fields.ordinal_month = other.ordinal_month.into();
515 fields.day = other.day.into();
516
517 fields
518 }
519}