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.into_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 pub(super) fn into_owned(self) -> FormatDescriptionV3Inner<'static> {
242 use alloc::borrow::ToOwned as _;
243 use alloc::boxed::Box;
244
245 match self {
246 Self::BorrowedLiteral(literal) => {
247 FormatDescriptionV3Inner::OwnedLiteral(literal.to_owned().into_boxed_str())
248 }
249 Self::BorrowedCompound(compound) => {
250 let owned = compound
251 .iter()
252 .map(|item| item.clone().into_owned())
253 .collect();
254 FormatDescriptionV3Inner::OwnedCompound(owned)
255 }
256 Self::BorrowedOptional { format, item } => FormatDescriptionV3Inner::OwnedOptional {
257 format,
258 item: Box::new(item.clone().into_owned()),
259 },
260 Self::BorrowedFirst(items) => {
261 let owned = items.iter().map(|item| item.clone().into_owned()).collect();
262 FormatDescriptionV3Inner::OwnedFirst(owned)
263 }
264 Self::OwnedCompound(mut compound) => {
265 let len = compound.len();
266 let compound_ptr = compound.as_mut_ptr();
267 for idx in 0..len {
268 unsafe {
272 let loc = compound_ptr.add(idx);
273 let item = loc.read();
274 loc.write(item.into_owned());
275 }
276 }
277 FormatDescriptionV3Inner::OwnedCompound(unsafe {
280 core::mem::transmute::<
281 Box<[FormatDescriptionV3Inner<'a>]>,
282 Box<[FormatDescriptionV3Inner<'static>]>,
283 >(compound)
284 })
285 }
286 Self::OwnedOptional { format, mut item } => {
287 let ptr = &raw mut *item;
288 unsafe {
291 let item = ptr.read();
292 ptr.write(item.into_owned());
293 }
294 FormatDescriptionV3Inner::OwnedOptional {
295 format,
296 item: unsafe {
299 core::mem::transmute::<
300 Box<FormatDescriptionV3Inner<'a>>,
301 Box<FormatDescriptionV3Inner<'static>>,
302 >(item)
303 },
304 }
305 }
306 Self::OwnedFirst(mut items) => {
307 let len = items.len();
308 let ptr = items.as_mut_ptr();
309 for idx in 0..len {
310 unsafe {
314 let loc = ptr.add(idx);
315 let item = loc.read();
316 loc.write(item.into_owned());
317 }
318 }
319 FormatDescriptionV3Inner::OwnedFirst(unsafe {
322 core::mem::transmute::<
323 Box<[FormatDescriptionV3Inner<'a>]>,
324 Box<[FormatDescriptionV3Inner<'static>]>,
325 >(items)
326 })
327 }
328 FormatDescriptionV3Inner::Day(_)
329 | FormatDescriptionV3Inner::MonthShort(_)
330 | FormatDescriptionV3Inner::MonthLong(_)
331 | FormatDescriptionV3Inner::MonthNumerical(_)
332 | FormatDescriptionV3Inner::Ordinal(_)
333 | FormatDescriptionV3Inner::WeekdayShort(_)
334 | FormatDescriptionV3Inner::WeekdayLong(_)
335 | FormatDescriptionV3Inner::WeekdaySunday(_)
336 | FormatDescriptionV3Inner::WeekdayMonday(_)
337 | FormatDescriptionV3Inner::WeekNumberIso(_)
338 | FormatDescriptionV3Inner::WeekNumberSunday(_)
339 | FormatDescriptionV3Inner::WeekNumberMonday(_)
340 | FormatDescriptionV3Inner::CalendarYearFullExtendedRange(_)
341 | FormatDescriptionV3Inner::CalendarYearFullStandardRange(_)
342 | FormatDescriptionV3Inner::IsoYearFullExtendedRange(_)
343 | FormatDescriptionV3Inner::IsoYearFullStandardRange(_)
344 | FormatDescriptionV3Inner::CalendarYearCenturyExtendedRange(_)
345 | FormatDescriptionV3Inner::CalendarYearCenturyStandardRange(_)
346 | FormatDescriptionV3Inner::IsoYearCenturyExtendedRange(_)
347 | FormatDescriptionV3Inner::IsoYearCenturyStandardRange(_)
348 | FormatDescriptionV3Inner::CalendarYearLastTwo(_)
349 | FormatDescriptionV3Inner::IsoYearLastTwo(_)
350 | FormatDescriptionV3Inner::Hour12(_)
351 | FormatDescriptionV3Inner::Hour24(_)
352 | FormatDescriptionV3Inner::Minute(_)
353 | FormatDescriptionV3Inner::Period(_)
354 | FormatDescriptionV3Inner::Second(_)
355 | FormatDescriptionV3Inner::Subsecond(_)
356 | FormatDescriptionV3Inner::OffsetHour(_)
357 | FormatDescriptionV3Inner::OffsetMinute(_)
358 | FormatDescriptionV3Inner::OffsetSecond(_)
359 | FormatDescriptionV3Inner::Ignore(_)
360 | FormatDescriptionV3Inner::UnixTimestampSecond(_)
361 | FormatDescriptionV3Inner::UnixTimestampMillisecond(_)
362 | FormatDescriptionV3Inner::UnixTimestampMicrosecond(_)
363 | FormatDescriptionV3Inner::UnixTimestampNanosecond(_)
364 | FormatDescriptionV3Inner::End(_)
365 | FormatDescriptionV3Inner::OwnedLiteral(_) => {
366 unsafe {
369 core::mem::transmute::<
370 FormatDescriptionV3Inner<'a>,
371 FormatDescriptionV3Inner<'static>,
372 >(self)
373 }
374 }
375 }
376 }
377
378 #[inline]
380 pub const fn into_opaque(self) -> FormatDescriptionV3<'a> {
381 FormatDescriptionV3 {
382 #[cfg(feature = "formatting")]
383 max_bytes_needed: self.max_bytes_needed(),
384 inner: self,
385 }
386 }
387
388 #[cfg(feature = "formatting")]
391 const fn max_bytes_needed(&self) -> usize {
392 match self {
393 Self::Day(_) => 2,
394 Self::MonthShort(_) => 3,
395 Self::MonthLong(_) => 9,
396 Self::MonthNumerical(_) => 2,
397 Self::Ordinal(_) => 3,
398 Self::WeekdayShort(_) => 3,
399 Self::WeekdayLong(_) => 9,
400 Self::WeekdaySunday(_) | Self::WeekdayMonday(_) => 1,
401 Self::WeekNumberIso(_) | Self::WeekNumberSunday(_) | Self::WeekNumberMonday(_) => 2,
402 Self::CalendarYearFullExtendedRange(_) => 7,
403 Self::CalendarYearFullStandardRange(_) => 5,
404 Self::IsoYearFullExtendedRange(_) => 7,
405 Self::IsoYearFullStandardRange(_) => 5,
406 Self::CalendarYearCenturyExtendedRange(_) => 5,
407 Self::CalendarYearCenturyStandardRange(_) => 3,
408 Self::IsoYearCenturyExtendedRange(_) => 5,
409 Self::IsoYearCenturyStandardRange(_) => 3,
410 Self::CalendarYearLastTwo(_) => 2,
411 Self::IsoYearLastTwo(_) => 2,
412 Self::Hour12(_) | Self::Hour24(_) => 2,
413 Self::Minute(_) | Self::Period(_) | Self::Second(_) => 2,
414 Self::Subsecond(modifier) => match modifier.digits {
415 modifier::SubsecondDigits::One => 1,
416 modifier::SubsecondDigits::Two => 2,
417 modifier::SubsecondDigits::Three => 3,
418 modifier::SubsecondDigits::Four => 4,
419 modifier::SubsecondDigits::Five => 5,
420 modifier::SubsecondDigits::Six => 6,
421 modifier::SubsecondDigits::Seven => 7,
422 modifier::SubsecondDigits::Eight => 8,
423 modifier::SubsecondDigits::Nine => 9,
424 modifier::SubsecondDigits::OneOrMore => 9,
425 },
426 Self::OffsetHour(_) => 3,
427 Self::OffsetMinute(_) | Self::OffsetSecond(_) => 2,
428 #[cfg(feature = "large-dates")]
429 Self::UnixTimestampSecond(_) => 15,
430 #[cfg(not(feature = "large-dates"))]
431 Self::UnixTimestampSecond(_) => 13,
432 #[cfg(feature = "large-dates")]
433 Self::UnixTimestampMillisecond(_) => 18,
434 #[cfg(not(feature = "large-dates"))]
435 Self::UnixTimestampMillisecond(_) => 16,
436 #[cfg(feature = "large-dates")]
437 Self::UnixTimestampMicrosecond(_) => 21,
438 #[cfg(not(feature = "large-dates"))]
439 Self::UnixTimestampMicrosecond(_) => 19,
440 #[cfg(feature = "large-dates")]
441 Self::UnixTimestampNanosecond(_) => 24,
442 #[cfg(not(feature = "large-dates"))]
443 Self::UnixTimestampNanosecond(_) => 22,
444 Self::Ignore(_) | Self::End(_) => 0,
445 FormatDescriptionV3Inner::BorrowedLiteral(s) => s.len(),
446 FormatDescriptionV3Inner::BorrowedCompound(items) => {
447 let mut max_bytes_needed = 0;
448 let mut idx = 0;
449 while idx < items.len() {
450 max_bytes_needed += items[idx].max_bytes_needed();
451 idx += 1;
452 }
453 max_bytes_needed
454 }
455 FormatDescriptionV3Inner::BorrowedOptional { format, item } => {
456 if *format {
457 item.max_bytes_needed()
458 } else {
459 0
460 }
461 }
462 FormatDescriptionV3Inner::BorrowedFirst(items) => {
463 if items.is_empty() {
464 0
465 } else {
466 items[0].max_bytes_needed()
467 }
468 }
469 FormatDescriptionV3Inner::OwnedLiteral(s) => s.len(),
470 FormatDescriptionV3Inner::OwnedCompound(items) => {
471 let mut max_bytes_needed = 0;
472 let mut idx = 0;
473 while idx < items.len() {
474 max_bytes_needed += items[idx].max_bytes_needed();
475 idx += 1;
476 }
477 max_bytes_needed
478 }
479 FormatDescriptionV3Inner::OwnedOptional { format, item } => {
480 if *format {
481 item.max_bytes_needed()
482 } else {
483 0
484 }
485 }
486 FormatDescriptionV3Inner::OwnedFirst(items) => {
487 if items.is_empty() {
488 0
489 } else {
490 items[0].max_bytes_needed()
491 }
492 }
493 }
494 }
495}
496
497#[non_exhaustive]
500#[derive(Debug, Clone, Copy)]
501pub enum Component {
502 Day(modifier::Day),
504 MonthShort(modifier::MonthShort),
506 MonthLong(modifier::MonthLong),
508 MonthNumerical(modifier::MonthNumerical),
510 Ordinal(modifier::Ordinal),
512 WeekdayShort(modifier::WeekdayShort),
514 WeekdayLong(modifier::WeekdayLong),
516 WeekdaySunday(modifier::WeekdaySunday),
518 WeekdayMonday(modifier::WeekdayMonday),
520 WeekNumberIso(modifier::WeekNumberIso),
523 WeekNumberSunday(modifier::WeekNumberSunday),
525 WeekNumberMonday(modifier::WeekNumberMonday),
527 CalendarYearFullExtendedRange(modifier::CalendarYearFullExtendedRange),
529 CalendarYearFullStandardRange(modifier::CalendarYearFullStandardRange),
531 IsoYearFullExtendedRange(modifier::IsoYearFullExtendedRange),
533 IsoYearFullStandardRange(modifier::IsoYearFullStandardRange),
535 CalendarYearCenturyExtendedRange(modifier::CalendarYearCenturyExtendedRange),
537 CalendarYearCenturyStandardRange(modifier::CalendarYearCenturyStandardRange),
539 IsoYearCenturyExtendedRange(modifier::IsoYearCenturyExtendedRange),
541 IsoYearCenturyStandardRange(modifier::IsoYearCenturyStandardRange),
543 CalendarYearLastTwo(modifier::CalendarYearLastTwo),
545 IsoYearLastTwo(modifier::IsoYearLastTwo),
547 Hour12(modifier::Hour12),
549 Hour24(modifier::Hour24),
551 Minute(modifier::Minute),
553 Period(modifier::Period),
555 Second(modifier::Second),
557 Subsecond(modifier::Subsecond),
559 OffsetHour(modifier::OffsetHour),
561 OffsetMinute(modifier::OffsetMinute),
563 OffsetSecond(modifier::OffsetSecond),
565 Ignore(modifier::Ignore),
567 UnixTimestampSecond(modifier::UnixTimestampSecond),
569 UnixTimestampMillisecond(modifier::UnixTimestampMillisecond),
571 UnixTimestampMicrosecond(modifier::UnixTimestampMicrosecond),
573 UnixTimestampNanosecond(modifier::UnixTimestampNanosecond),
575 End(modifier::End),
578}