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")]
240 fn make_owned_in_place(&mut self) {
241 use alloc::borrow::ToOwned as _;
242 use alloc::boxed::Box;
243
244 match self {
245 Self::BorrowedLiteral(literal) => {
246 *self = Self::OwnedLiteral(literal.to_owned().into_boxed_str());
247 }
248 Self::BorrowedCompound(compound) => {
249 *self = Self::OwnedCompound(
250 compound
251 .iter()
252 .cloned()
253 .map(|item| item.into_owned())
254 .collect(),
255 );
256 }
257 Self::BorrowedOptional { format, item } => {
258 *self = Self::OwnedOptional {
259 format: *format,
260 item: Box::new(item.clone().into_owned()),
261 };
262 }
263 Self::BorrowedFirst(items) => {
264 *self = Self::OwnedFirst(
265 items
266 .iter()
267 .cloned()
268 .map(|item| item.into_owned())
269 .collect(),
270 );
271 }
272 Self::OwnedCompound(compound) => {
273 for item in compound {
274 item.make_owned_in_place();
275 }
276 }
277 Self::OwnedOptional { format: _, item } => {
278 item.make_owned_in_place();
279 }
280 Self::OwnedFirst(items) => {
281 for item in items {
282 item.make_owned_in_place();
283 }
284 }
285 FormatDescriptionV3Inner::Day(_)
286 | FormatDescriptionV3Inner::MonthShort(_)
287 | FormatDescriptionV3Inner::MonthLong(_)
288 | FormatDescriptionV3Inner::MonthNumerical(_)
289 | FormatDescriptionV3Inner::Ordinal(_)
290 | FormatDescriptionV3Inner::WeekdayShort(_)
291 | FormatDescriptionV3Inner::WeekdayLong(_)
292 | FormatDescriptionV3Inner::WeekdaySunday(_)
293 | FormatDescriptionV3Inner::WeekdayMonday(_)
294 | FormatDescriptionV3Inner::WeekNumberIso(_)
295 | FormatDescriptionV3Inner::WeekNumberSunday(_)
296 | FormatDescriptionV3Inner::WeekNumberMonday(_)
297 | FormatDescriptionV3Inner::CalendarYearFullExtendedRange(_)
298 | FormatDescriptionV3Inner::CalendarYearFullStandardRange(_)
299 | FormatDescriptionV3Inner::IsoYearFullExtendedRange(_)
300 | FormatDescriptionV3Inner::IsoYearFullStandardRange(_)
301 | FormatDescriptionV3Inner::CalendarYearCenturyExtendedRange(_)
302 | FormatDescriptionV3Inner::CalendarYearCenturyStandardRange(_)
303 | FormatDescriptionV3Inner::IsoYearCenturyExtendedRange(_)
304 | FormatDescriptionV3Inner::IsoYearCenturyStandardRange(_)
305 | FormatDescriptionV3Inner::CalendarYearLastTwo(_)
306 | FormatDescriptionV3Inner::IsoYearLastTwo(_)
307 | FormatDescriptionV3Inner::Hour12(_)
308 | FormatDescriptionV3Inner::Hour24(_)
309 | FormatDescriptionV3Inner::Minute(_)
310 | FormatDescriptionV3Inner::Period(_)
311 | FormatDescriptionV3Inner::Second(_)
312 | FormatDescriptionV3Inner::Subsecond(_)
313 | FormatDescriptionV3Inner::OffsetHour(_)
314 | FormatDescriptionV3Inner::OffsetMinute(_)
315 | FormatDescriptionV3Inner::OffsetSecond(_)
316 | FormatDescriptionV3Inner::Ignore(_)
317 | FormatDescriptionV3Inner::UnixTimestampSecond(_)
318 | FormatDescriptionV3Inner::UnixTimestampMillisecond(_)
319 | FormatDescriptionV3Inner::UnixTimestampMicrosecond(_)
320 | FormatDescriptionV3Inner::UnixTimestampNanosecond(_)
321 | FormatDescriptionV3Inner::End(_)
322 | FormatDescriptionV3Inner::OwnedLiteral(_) => {
323 }
325 }
326 }
327
328 #[cfg(feature = "alloc")]
331 pub(super) fn into_owned(mut self) -> FormatDescriptionV3Inner<'static> {
332 self.make_owned_in_place();
333
334 unsafe {
338 core::mem::transmute::<FormatDescriptionV3Inner<'a>, FormatDescriptionV3Inner<'static>>(
339 self,
340 )
341 }
342 }
343
344 #[inline]
346 pub const fn into_opaque(self) -> FormatDescriptionV3<'a> {
347 FormatDescriptionV3 {
348 #[cfg(feature = "formatting")]
349 max_bytes_needed: self.max_bytes_needed(),
350 inner: self,
351 }
352 }
353
354 #[cfg(feature = "formatting")]
357 const fn max_bytes_needed(&self) -> usize {
358 match self {
359 Self::Day(_) => 2,
360 Self::MonthShort(_) => 3,
361 Self::MonthLong(_) => 9,
362 Self::MonthNumerical(_) => 2,
363 Self::Ordinal(_) => 3,
364 Self::WeekdayShort(_) => 3,
365 Self::WeekdayLong(_) => 9,
366 Self::WeekdaySunday(_) | Self::WeekdayMonday(_) => 1,
367 Self::WeekNumberIso(_) | Self::WeekNumberSunday(_) | Self::WeekNumberMonday(_) => 2,
368 Self::CalendarYearFullExtendedRange(_) => 7,
369 Self::CalendarYearFullStandardRange(_) => 5,
370 Self::IsoYearFullExtendedRange(_) => 7,
371 Self::IsoYearFullStandardRange(_) => 5,
372 Self::CalendarYearCenturyExtendedRange(_) => 5,
373 Self::CalendarYearCenturyStandardRange(_) => 3,
374 Self::IsoYearCenturyExtendedRange(_) => 5,
375 Self::IsoYearCenturyStandardRange(_) => 3,
376 Self::CalendarYearLastTwo(_) => 2,
377 Self::IsoYearLastTwo(_) => 2,
378 Self::Hour12(_) | Self::Hour24(_) => 2,
379 Self::Minute(_) | Self::Period(_) | Self::Second(_) => 2,
380 Self::Subsecond(modifier) => match modifier.digits {
381 modifier::SubsecondDigits::One => 1,
382 modifier::SubsecondDigits::Two => 2,
383 modifier::SubsecondDigits::Three => 3,
384 modifier::SubsecondDigits::Four => 4,
385 modifier::SubsecondDigits::Five => 5,
386 modifier::SubsecondDigits::Six => 6,
387 modifier::SubsecondDigits::Seven => 7,
388 modifier::SubsecondDigits::Eight => 8,
389 modifier::SubsecondDigits::Nine => 9,
390 modifier::SubsecondDigits::OneOrMore => 9,
391 },
392 Self::OffsetHour(_) => 3,
393 Self::OffsetMinute(_) | Self::OffsetSecond(_) => 2,
394 #[cfg(feature = "large-dates")]
395 Self::UnixTimestampSecond(_) => 15,
396 #[cfg(not(feature = "large-dates"))]
397 Self::UnixTimestampSecond(_) => 13,
398 #[cfg(feature = "large-dates")]
399 Self::UnixTimestampMillisecond(_) => 18,
400 #[cfg(not(feature = "large-dates"))]
401 Self::UnixTimestampMillisecond(_) => 16,
402 #[cfg(feature = "large-dates")]
403 Self::UnixTimestampMicrosecond(_) => 21,
404 #[cfg(not(feature = "large-dates"))]
405 Self::UnixTimestampMicrosecond(_) => 19,
406 #[cfg(feature = "large-dates")]
407 Self::UnixTimestampNanosecond(_) => 24,
408 #[cfg(not(feature = "large-dates"))]
409 Self::UnixTimestampNanosecond(_) => 22,
410 Self::Ignore(_) | Self::End(_) => 0,
411 FormatDescriptionV3Inner::BorrowedLiteral(s) => s.len(),
412 FormatDescriptionV3Inner::BorrowedCompound(items) => {
413 let mut max_bytes_needed = 0;
414 let mut idx = 0;
415 while idx < items.len() {
416 max_bytes_needed += items[idx].max_bytes_needed();
417 idx += 1;
418 }
419 max_bytes_needed
420 }
421 FormatDescriptionV3Inner::BorrowedOptional { format, item } => {
422 if *format {
423 item.max_bytes_needed()
424 } else {
425 0
426 }
427 }
428 FormatDescriptionV3Inner::BorrowedFirst(items) => {
429 if items.is_empty() {
430 0
431 } else {
432 items[0].max_bytes_needed()
433 }
434 }
435 FormatDescriptionV3Inner::OwnedLiteral(s) => s.len(),
436 FormatDescriptionV3Inner::OwnedCompound(items) => {
437 let mut max_bytes_needed = 0;
438 let mut idx = 0;
439 while idx < items.len() {
440 max_bytes_needed += items[idx].max_bytes_needed();
441 idx += 1;
442 }
443 max_bytes_needed
444 }
445 FormatDescriptionV3Inner::OwnedOptional { format, item } => {
446 if *format {
447 item.max_bytes_needed()
448 } else {
449 0
450 }
451 }
452 FormatDescriptionV3Inner::OwnedFirst(items) => {
453 if items.is_empty() {
454 0
455 } else {
456 items[0].max_bytes_needed()
457 }
458 }
459 }
460 }
461}
462
463#[non_exhaustive]
466#[derive(Debug, Clone, Copy)]
467pub enum Component {
468 Day(modifier::Day),
470 MonthShort(modifier::MonthShort),
472 MonthLong(modifier::MonthLong),
474 MonthNumerical(modifier::MonthNumerical),
476 Ordinal(modifier::Ordinal),
478 WeekdayShort(modifier::WeekdayShort),
480 WeekdayLong(modifier::WeekdayLong),
482 WeekdaySunday(modifier::WeekdaySunday),
484 WeekdayMonday(modifier::WeekdayMonday),
486 WeekNumberIso(modifier::WeekNumberIso),
489 WeekNumberSunday(modifier::WeekNumberSunday),
491 WeekNumberMonday(modifier::WeekNumberMonday),
493 CalendarYearFullExtendedRange(modifier::CalendarYearFullExtendedRange),
495 CalendarYearFullStandardRange(modifier::CalendarYearFullStandardRange),
497 IsoYearFullExtendedRange(modifier::IsoYearFullExtendedRange),
499 IsoYearFullStandardRange(modifier::IsoYearFullStandardRange),
501 CalendarYearCenturyExtendedRange(modifier::CalendarYearCenturyExtendedRange),
503 CalendarYearCenturyStandardRange(modifier::CalendarYearCenturyStandardRange),
505 IsoYearCenturyExtendedRange(modifier::IsoYearCenturyExtendedRange),
507 IsoYearCenturyStandardRange(modifier::IsoYearCenturyStandardRange),
509 CalendarYearLastTwo(modifier::CalendarYearLastTwo),
511 IsoYearLastTwo(modifier::IsoYearLastTwo),
513 Hour12(modifier::Hour12),
515 Hour24(modifier::Hour24),
517 Minute(modifier::Minute),
519 Period(modifier::Period),
521 Second(modifier::Second),
523 Subsecond(modifier::Subsecond),
525 OffsetHour(modifier::OffsetHour),
527 OffsetMinute(modifier::OffsetMinute),
529 OffsetSecond(modifier::OffsetSecond),
531 Ignore(modifier::Ignore),
533 UnixTimestampSecond(modifier::UnixTimestampSecond),
535 UnixTimestampMillisecond(modifier::UnixTimestampMillisecond),
537 UnixTimestampMicrosecond(modifier::UnixTimestampMicrosecond),
539 UnixTimestampNanosecond(modifier::UnixTimestampNanosecond),
541 End(modifier::End),
544}