1#[cfg(feature = "alloc")]
7use alloc::boxed::Box;
8use core::fmt;
9
10use crate::format_description::modifier;
11
12#[derive(Clone)]
19pub struct FormatDescriptionV3<'a> {
20 pub(crate) inner: FormatDescriptionV3Inner<'a>,
22 #[cfg(feature = "formatting")]
25 pub(crate) max_bytes_needed: usize,
26}
27
28impl fmt::Debug for FormatDescriptionV3<'_> {
29 #[inline]
30 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31 self.inner.fmt(f)
32 }
33}
34
35impl FormatDescriptionV3<'_> {
36 #[cfg(feature = "alloc")]
39 #[inline]
40 pub fn to_owned(self) -> FormatDescriptionV3<'static> {
41 FormatDescriptionV3 {
42 inner: self.inner.to_owned(),
43 #[cfg(feature = "formatting")]
44 max_bytes_needed: self.max_bytes_needed,
45 }
46 }
47}
48
49#[non_exhaustive]
52#[derive(Clone)]
53pub enum FormatDescriptionV3Inner<'a> {
54 Day(modifier::Day),
56 MonthShort(modifier::MonthShort),
58 MonthLong(modifier::MonthLong),
60 MonthNumerical(modifier::MonthNumerical),
62 Ordinal(modifier::Ordinal),
64 WeekdayShort(modifier::WeekdayShort),
66 WeekdayLong(modifier::WeekdayLong),
68 WeekdaySunday(modifier::WeekdaySunday),
70 WeekdayMonday(modifier::WeekdayMonday),
72 WeekNumberIso(modifier::WeekNumberIso),
75 WeekNumberSunday(modifier::WeekNumberSunday),
77 WeekNumberMonday(modifier::WeekNumberMonday),
79 CalendarYearFullExtendedRange(modifier::CalendarYearFullExtendedRange),
81 CalendarYearFullStandardRange(modifier::CalendarYearFullStandardRange),
83 IsoYearFullExtendedRange(modifier::IsoYearFullExtendedRange),
85 IsoYearFullStandardRange(modifier::IsoYearFullStandardRange),
87 CalendarYearCenturyExtendedRange(modifier::CalendarYearCenturyExtendedRange),
89 CalendarYearCenturyStandardRange(modifier::CalendarYearCenturyStandardRange),
91 IsoYearCenturyExtendedRange(modifier::IsoYearCenturyExtendedRange),
93 IsoYearCenturyStandardRange(modifier::IsoYearCenturyStandardRange),
95 CalendarYearLastTwo(modifier::CalendarYearLastTwo),
97 IsoYearLastTwo(modifier::IsoYearLastTwo),
99 Hour12(modifier::Hour12),
101 Hour24(modifier::Hour24),
103 Minute(modifier::Minute),
105 Period(modifier::Period),
107 Second(modifier::Second),
109 Subsecond(modifier::Subsecond),
111 OffsetHour(modifier::OffsetHour),
113 OffsetMinute(modifier::OffsetMinute),
115 OffsetSecond(modifier::OffsetSecond),
117 Ignore(modifier::Ignore),
119 UnixTimestampSecond(modifier::UnixTimestampSecond),
121 UnixTimestampMillisecond(modifier::UnixTimestampMillisecond),
123 UnixTimestampMicrosecond(modifier::UnixTimestampMicrosecond),
125 UnixTimestampNanosecond(modifier::UnixTimestampNanosecond),
127 End(modifier::End),
130 BorrowedLiteral(&'a str),
132 BorrowedCompound(&'a [Self]),
134 BorrowedOptional {
137 format: bool,
139 item: &'a Self,
141 },
142 BorrowedFirst(&'a [Self]),
145 #[cfg(feature = "alloc")]
147 OwnedLiteral(Box<str>),
148 #[cfg(feature = "alloc")]
150 OwnedCompound(Box<[Self]>),
151 #[cfg(feature = "alloc")]
154 OwnedOptional {
155 format: bool,
157 item: Box<Self>,
159 },
160 #[cfg(feature = "alloc")]
163 OwnedFirst(Box<[Self]>),
164}
165
166impl fmt::Debug for FormatDescriptionV3Inner<'_> {
167 #[inline]
168 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
169 match self {
170 Self::Day(modifier) => modifier.fmt(f),
171 Self::MonthShort(modifier) => modifier.fmt(f),
172 Self::MonthLong(modifier) => modifier.fmt(f),
173 Self::MonthNumerical(modifier) => modifier.fmt(f),
174 Self::Ordinal(modifier) => modifier.fmt(f),
175 Self::WeekdayShort(modifier) => modifier.fmt(f),
176 Self::WeekdayLong(modifier) => modifier.fmt(f),
177 Self::WeekdaySunday(modifier) => modifier.fmt(f),
178 Self::WeekdayMonday(modifier) => modifier.fmt(f),
179 Self::WeekNumberIso(modifier) => modifier.fmt(f),
180 Self::WeekNumberSunday(modifier) => modifier.fmt(f),
181 Self::WeekNumberMonday(modifier) => modifier.fmt(f),
182 Self::CalendarYearFullExtendedRange(modifier) => modifier.fmt(f),
183 Self::CalendarYearFullStandardRange(modifier) => modifier.fmt(f),
184 Self::IsoYearFullExtendedRange(modifier) => modifier.fmt(f),
185 Self::IsoYearFullStandardRange(modifier) => modifier.fmt(f),
186 Self::CalendarYearCenturyExtendedRange(modifier) => modifier.fmt(f),
187 Self::CalendarYearCenturyStandardRange(modifier) => modifier.fmt(f),
188 Self::IsoYearCenturyExtendedRange(modifier) => modifier.fmt(f),
189 Self::IsoYearCenturyStandardRange(modifier) => modifier.fmt(f),
190 Self::CalendarYearLastTwo(modifier) => modifier.fmt(f),
191 Self::IsoYearLastTwo(modifier) => modifier.fmt(f),
192 Self::Hour12(modifier) => modifier.fmt(f),
193 Self::Hour24(modifier) => modifier.fmt(f),
194 Self::Minute(modifier) => modifier.fmt(f),
195 Self::Period(modifier) => modifier.fmt(f),
196 Self::Second(modifier) => modifier.fmt(f),
197 Self::Subsecond(modifier) => modifier.fmt(f),
198 Self::OffsetHour(modifier) => modifier.fmt(f),
199 Self::OffsetMinute(modifier) => modifier.fmt(f),
200 Self::OffsetSecond(modifier) => modifier.fmt(f),
201 Self::Ignore(modifier) => modifier.fmt(f),
202 Self::UnixTimestampSecond(modifier) => modifier.fmt(f),
203 Self::UnixTimestampMillisecond(modifier) => modifier.fmt(f),
204 Self::UnixTimestampMicrosecond(modifier) => modifier.fmt(f),
205 Self::UnixTimestampNanosecond(modifier) => modifier.fmt(f),
206 Self::End(modifier) => modifier.fmt(f),
207 Self::BorrowedLiteral(literal) => f.debug_tuple("Literal").field(literal).finish(),
208 Self::BorrowedCompound(compound) => f.debug_tuple("Compound").field(compound).finish(),
209 Self::BorrowedOptional {
210 format: should_format,
211 item,
212 } => f
213 .debug_struct("Optional")
214 .field("should_format", should_format)
215 .field("item", item)
216 .finish(),
217 Self::BorrowedFirst(items) => f.debug_tuple("First").field(items).finish(),
218 #[cfg(feature = "alloc")]
219 Self::OwnedLiteral(literal) => f.debug_tuple("Literal").field(literal).finish(),
220 #[cfg(feature = "alloc")]
221 Self::OwnedCompound(compound) => f.debug_tuple("Compound").field(compound).finish(),
222 #[cfg(feature = "alloc")]
223 Self::OwnedOptional {
224 format: should_format,
225 item,
226 } => f
227 .debug_struct("Optional")
228 .field("should_format", should_format)
229 .field("item", item)
230 .finish(),
231 #[cfg(feature = "alloc")]
232 Self::OwnedFirst(items) => f.debug_tuple("First").field(items).finish(),
233 }
234 }
235}
236
237impl<'a> FormatDescriptionV3Inner<'a> {
238 #[cfg(feature = "alloc")]
241 fn to_owned(&self) -> FormatDescriptionV3Inner<'static> {
242 use alloc::borrow::ToOwned as _;
243 use alloc::boxed::Box;
244 use alloc::vec::Vec;
245
246 match self {
247 Self::Day(day) => FormatDescriptionV3Inner::Day(*day),
248 Self::MonthShort(month_short) => FormatDescriptionV3Inner::MonthShort(*month_short),
249 Self::MonthLong(month_long) => FormatDescriptionV3Inner::MonthLong(*month_long),
250 Self::MonthNumerical(month_numerical) => {
251 FormatDescriptionV3Inner::MonthNumerical(*month_numerical)
252 }
253 Self::Ordinal(ordinal) => FormatDescriptionV3Inner::Ordinal(*ordinal),
254 Self::WeekdayShort(weekday_short) => {
255 FormatDescriptionV3Inner::WeekdayShort(*weekday_short)
256 }
257 Self::WeekdayLong(weekday_long) => FormatDescriptionV3Inner::WeekdayLong(*weekday_long),
258 Self::WeekdaySunday(weekday_sunday) => {
259 FormatDescriptionV3Inner::WeekdaySunday(*weekday_sunday)
260 }
261 Self::WeekdayMonday(weekday_monday) => {
262 FormatDescriptionV3Inner::WeekdayMonday(*weekday_monday)
263 }
264 Self::WeekNumberIso(week_number_iso) => {
265 FormatDescriptionV3Inner::WeekNumberIso(*week_number_iso)
266 }
267 Self::WeekNumberSunday(week_number_sunday) => {
268 FormatDescriptionV3Inner::WeekNumberSunday(*week_number_sunday)
269 }
270 Self::WeekNumberMonday(week_number_monday) => {
271 FormatDescriptionV3Inner::WeekNumberMonday(*week_number_monday)
272 }
273 Self::CalendarYearFullExtendedRange(calendar_year_full_extended_range) => {
274 FormatDescriptionV3Inner::CalendarYearFullExtendedRange(
275 *calendar_year_full_extended_range,
276 )
277 }
278 Self::CalendarYearFullStandardRange(calendar_year_full_standard_range) => {
279 FormatDescriptionV3Inner::CalendarYearFullStandardRange(
280 *calendar_year_full_standard_range,
281 )
282 }
283 Self::IsoYearFullExtendedRange(iso_year_full_extended_range) => {
284 FormatDescriptionV3Inner::IsoYearFullExtendedRange(*iso_year_full_extended_range)
285 }
286 Self::IsoYearFullStandardRange(iso_year_full_standard_range) => {
287 FormatDescriptionV3Inner::IsoYearFullStandardRange(*iso_year_full_standard_range)
288 }
289 Self::CalendarYearCenturyExtendedRange(calendar_year_century_extended_range) => {
290 FormatDescriptionV3Inner::CalendarYearCenturyExtendedRange(
291 *calendar_year_century_extended_range,
292 )
293 }
294 Self::CalendarYearCenturyStandardRange(calendar_year_century_standard_range) => {
295 FormatDescriptionV3Inner::CalendarYearCenturyStandardRange(
296 *calendar_year_century_standard_range,
297 )
298 }
299 Self::IsoYearCenturyExtendedRange(iso_year_century_extended_range) => {
300 FormatDescriptionV3Inner::IsoYearCenturyExtendedRange(
301 *iso_year_century_extended_range,
302 )
303 }
304 Self::IsoYearCenturyStandardRange(iso_year_century_standard_range) => {
305 FormatDescriptionV3Inner::IsoYearCenturyStandardRange(
306 *iso_year_century_standard_range,
307 )
308 }
309 Self::CalendarYearLastTwo(calendar_year_last_two) => {
310 FormatDescriptionV3Inner::CalendarYearLastTwo(*calendar_year_last_two)
311 }
312 Self::IsoYearLastTwo(iso_year_last_two) => {
313 FormatDescriptionV3Inner::IsoYearLastTwo(*iso_year_last_two)
314 }
315 Self::Hour12(hour12) => FormatDescriptionV3Inner::Hour12(*hour12),
316 Self::Hour24(hour24) => FormatDescriptionV3Inner::Hour24(*hour24),
317 Self::Minute(minute) => FormatDescriptionV3Inner::Minute(*minute),
318 Self::Period(period) => FormatDescriptionV3Inner::Period(*period),
319 Self::Second(second) => FormatDescriptionV3Inner::Second(*second),
320 Self::Subsecond(subsecond) => FormatDescriptionV3Inner::Subsecond(*subsecond),
321 Self::OffsetHour(offset_hour) => FormatDescriptionV3Inner::OffsetHour(*offset_hour),
322 Self::OffsetMinute(offset_minute) => {
323 FormatDescriptionV3Inner::OffsetMinute(*offset_minute)
324 }
325 Self::OffsetSecond(offset_second) => {
326 FormatDescriptionV3Inner::OffsetSecond(*offset_second)
327 }
328 Self::Ignore(ignore) => FormatDescriptionV3Inner::Ignore(*ignore),
329 Self::UnixTimestampSecond(unix_timestamp_second) => {
330 FormatDescriptionV3Inner::UnixTimestampSecond(*unix_timestamp_second)
331 }
332 Self::UnixTimestampMillisecond(unix_timestamp_millisecond) => {
333 FormatDescriptionV3Inner::UnixTimestampMillisecond(*unix_timestamp_millisecond)
334 }
335 Self::UnixTimestampMicrosecond(unix_timestamp_microsecond) => {
336 FormatDescriptionV3Inner::UnixTimestampMicrosecond(*unix_timestamp_microsecond)
337 }
338 Self::UnixTimestampNanosecond(unix_timestamp_nanosecond) => {
339 FormatDescriptionV3Inner::UnixTimestampNanosecond(*unix_timestamp_nanosecond)
340 }
341 Self::End(end) => FormatDescriptionV3Inner::End(*end),
342 Self::BorrowedLiteral(literal) => {
343 FormatDescriptionV3Inner::OwnedLiteral((*literal).to_owned().into_boxed_str())
344 }
345 Self::BorrowedCompound(compound) => FormatDescriptionV3Inner::OwnedCompound(
346 compound
347 .iter()
348 .map(|v| v.to_owned())
349 .collect::<Vec<_>>()
350 .into_boxed_slice(),
351 ),
352 Self::BorrowedOptional { format, item } => FormatDescriptionV3Inner::OwnedOptional {
353 format: *format,
354 item: Box::new((*item).to_owned()),
355 },
356 Self::BorrowedFirst(items) => FormatDescriptionV3Inner::OwnedFirst(
357 items
358 .iter()
359 .map(|v| v.to_owned())
360 .collect::<Vec<_>>()
361 .into_boxed_slice(),
362 ),
363 Self::OwnedLiteral(literal) => FormatDescriptionV3Inner::OwnedLiteral(literal.clone()),
364 Self::OwnedCompound(compound) => FormatDescriptionV3Inner::OwnedCompound(
365 compound
366 .into_iter()
367 .map(|v| v.to_owned())
368 .collect::<Vec<_>>()
369 .into_boxed_slice(),
370 ),
371 Self::OwnedOptional { format, item } => FormatDescriptionV3Inner::OwnedOptional {
372 format: *format,
373 item: Box::new((**item).to_owned()),
374 },
375 Self::OwnedFirst(items) => FormatDescriptionV3Inner::OwnedFirst(
376 items
377 .into_iter()
378 .map(|v| v.to_owned())
379 .collect::<Vec<_>>()
380 .into_boxed_slice(),
381 ),
382 }
383 }
384
385 #[inline]
387 pub const fn into_opaque(self) -> FormatDescriptionV3<'a> {
388 FormatDescriptionV3 {
389 #[cfg(feature = "formatting")]
390 max_bytes_needed: self.max_bytes_needed(),
391 inner: self,
392 }
393 }
394
395 #[cfg(feature = "formatting")]
398 const fn max_bytes_needed(&self) -> usize {
399 match self {
400 Self::Day(_) => 2,
401 Self::MonthShort(_) => 3,
402 Self::MonthLong(_) => 9,
403 Self::MonthNumerical(_) => 2,
404 Self::Ordinal(_) => 3,
405 Self::WeekdayShort(_) => 3,
406 Self::WeekdayLong(_) => 9,
407 Self::WeekdaySunday(_) | Self::WeekdayMonday(_) => 1,
408 Self::WeekNumberIso(_) | Self::WeekNumberSunday(_) | Self::WeekNumberMonday(_) => 2,
409 Self::CalendarYearFullExtendedRange(_) => 7,
410 Self::CalendarYearFullStandardRange(_) => 5,
411 Self::IsoYearFullExtendedRange(_) => 7,
412 Self::IsoYearFullStandardRange(_) => 5,
413 Self::CalendarYearCenturyExtendedRange(_) => 5,
414 Self::CalendarYearCenturyStandardRange(_) => 3,
415 Self::IsoYearCenturyExtendedRange(_) => 5,
416 Self::IsoYearCenturyStandardRange(_) => 3,
417 Self::CalendarYearLastTwo(_) => 2,
418 Self::IsoYearLastTwo(_) => 2,
419 Self::Hour12(_) | Self::Hour24(_) => 2,
420 Self::Minute(_) | Self::Period(_) | Self::Second(_) => 2,
421 Self::Subsecond(modifier) => match modifier.digits {
422 modifier::SubsecondDigits::One => 1,
423 modifier::SubsecondDigits::Two => 2,
424 modifier::SubsecondDigits::Three => 3,
425 modifier::SubsecondDigits::Four => 4,
426 modifier::SubsecondDigits::Five => 5,
427 modifier::SubsecondDigits::Six => 6,
428 modifier::SubsecondDigits::Seven => 7,
429 modifier::SubsecondDigits::Eight => 8,
430 modifier::SubsecondDigits::Nine => 9,
431 modifier::SubsecondDigits::OneOrMore => 9,
432 },
433 Self::OffsetHour(_) => 3,
434 Self::OffsetMinute(_) | Self::OffsetSecond(_) => 2,
435 #[cfg(feature = "large-dates")]
436 Self::UnixTimestampSecond(_) => 15,
437 #[cfg(not(feature = "large-dates"))]
438 Self::UnixTimestampSecond(_) => 13,
439 #[cfg(feature = "large-dates")]
440 Self::UnixTimestampMillisecond(_) => 18,
441 #[cfg(not(feature = "large-dates"))]
442 Self::UnixTimestampMillisecond(_) => 16,
443 #[cfg(feature = "large-dates")]
444 Self::UnixTimestampMicrosecond(_) => 21,
445 #[cfg(not(feature = "large-dates"))]
446 Self::UnixTimestampMicrosecond(_) => 19,
447 #[cfg(feature = "large-dates")]
448 Self::UnixTimestampNanosecond(_) => 24,
449 #[cfg(not(feature = "large-dates"))]
450 Self::UnixTimestampNanosecond(_) => 22,
451 Self::Ignore(_) | Self::End(_) => 0,
452 FormatDescriptionV3Inner::BorrowedLiteral(s) => s.len(),
453 FormatDescriptionV3Inner::BorrowedCompound(items) => {
454 let mut max_bytes_needed = 0;
455 let mut idx = 0;
456 while idx < items.len() {
457 max_bytes_needed += items[idx].max_bytes_needed();
458 idx += 1;
459 }
460 max_bytes_needed
461 }
462 FormatDescriptionV3Inner::BorrowedOptional { format, item } => {
463 if *format {
464 item.max_bytes_needed()
465 } else {
466 0
467 }
468 }
469 FormatDescriptionV3Inner::BorrowedFirst(items) => {
470 if items.is_empty() {
471 0
472 } else {
473 items[0].max_bytes_needed()
474 }
475 }
476 FormatDescriptionV3Inner::OwnedLiteral(s) => s.len(),
477 FormatDescriptionV3Inner::OwnedCompound(items) => {
478 let mut max_bytes_needed = 0;
479 let mut idx = 0;
480 while idx < items.len() {
481 max_bytes_needed += items[idx].max_bytes_needed();
482 idx += 1;
483 }
484 max_bytes_needed
485 }
486 FormatDescriptionV3Inner::OwnedOptional { format, item } => {
487 if *format {
488 item.max_bytes_needed()
489 } else {
490 0
491 }
492 }
493 FormatDescriptionV3Inner::OwnedFirst(items) => {
494 if items.is_empty() {
495 0
496 } else {
497 items[0].max_bytes_needed()
498 }
499 }
500 }
501 }
502}
503
504#[non_exhaustive]
507#[derive(Debug, Clone, Copy)]
508pub enum Component {
509 Day(modifier::Day),
511 MonthShort(modifier::MonthShort),
513 MonthLong(modifier::MonthLong),
515 MonthNumerical(modifier::MonthNumerical),
517 Ordinal(modifier::Ordinal),
519 WeekdayShort(modifier::WeekdayShort),
521 WeekdayLong(modifier::WeekdayLong),
523 WeekdaySunday(modifier::WeekdaySunday),
525 WeekdayMonday(modifier::WeekdayMonday),
527 WeekNumberIso(modifier::WeekNumberIso),
530 WeekNumberSunday(modifier::WeekNumberSunday),
532 WeekNumberMonday(modifier::WeekNumberMonday),
534 CalendarYearFullExtendedRange(modifier::CalendarYearFullExtendedRange),
536 CalendarYearFullStandardRange(modifier::CalendarYearFullStandardRange),
538 IsoYearFullExtendedRange(modifier::IsoYearFullExtendedRange),
540 IsoYearFullStandardRange(modifier::IsoYearFullStandardRange),
542 CalendarYearCenturyExtendedRange(modifier::CalendarYearCenturyExtendedRange),
544 CalendarYearCenturyStandardRange(modifier::CalendarYearCenturyStandardRange),
546 IsoYearCenturyExtendedRange(modifier::IsoYearCenturyExtendedRange),
548 IsoYearCenturyStandardRange(modifier::IsoYearCenturyStandardRange),
550 CalendarYearLastTwo(modifier::CalendarYearLastTwo),
552 IsoYearLastTwo(modifier::IsoYearLastTwo),
554 Hour12(modifier::Hour12),
556 Hour24(modifier::Hour24),
558 Minute(modifier::Minute),
560 Period(modifier::Period),
562 Second(modifier::Second),
564 Subsecond(modifier::Subsecond),
566 OffsetHour(modifier::OffsetHour),
568 OffsetMinute(modifier::OffsetMinute),
570 OffsetSecond(modifier::OffsetSecond),
572 Ignore(modifier::Ignore),
574 UnixTimestampSecond(modifier::UnixTimestampSecond),
576 UnixTimestampMillisecond(modifier::UnixTimestampMillisecond),
578 UnixTimestampMicrosecond(modifier::UnixTimestampMicrosecond),
580 UnixTimestampNanosecond(modifier::UnixTimestampNanosecond),
582 End(modifier::End),
585}