time/format_description/
borrowed_format_item.rs

1//! A format item with borrowed data.
2
3#[cfg(feature = "alloc")]
4use alloc::string::String;
5#[cfg(feature = "alloc")]
6use core::fmt;
7
8/// A complete description of how to format and parse a type.
9///
10/// This alias exists for backwards-compatibility. It is recommended to use `BorrowedFormatItem`
11/// for clarity, as it is more explicit that the data is borrowed rather than owned.
12#[cfg(doc)]
13#[deprecated(
14    since = "0.3.35",
15    note = "use `BorrowedFormatItem` instead for clarity"
16)]
17pub type FormatItem<'a> = BorrowedFormatItem<'a>;
18
19#[cfg(not(doc))]
20pub use self::BorrowedFormatItem as FormatItem;
21use crate::error;
22use crate::format_description::Component;
23
24/// A complete description of how to format and parse a type.
25#[non_exhaustive]
26#[cfg_attr(not(feature = "alloc"), derive(Debug))]
27#[derive(Clone, PartialEq, Eq)]
28pub enum BorrowedFormatItem<'a> {
29    /// Bytes that are formatted as-is.
30    ///
31    /// **Note**: These bytes **should** be UTF-8, but are not required to be. The value is passed
32    /// through `String::from_utf8_lossy` when necessary.
33    Literal(&'a [u8]),
34    /// A minimal representation of a single non-literal item.
35    Component(Component),
36    /// A series of literals or components that collectively form a partial or complete
37    /// description.
38    Compound(&'a [Self]),
39    /// A `FormatItem` that may or may not be present when parsing. If parsing fails, there
40    /// will be no effect on the resulting `struct`.
41    ///
42    /// This variant has no effect on formatting, as the value is guaranteed to be present.
43    Optional(&'a Self),
44    /// A series of `FormatItem`s where, when parsing, the first successful parse is used. When
45    /// formatting, the first element of the slice is used.  An empty slice is a no-op when
46    /// formatting or parsing.
47    First(&'a [Self]),
48}
49
50#[cfg(feature = "alloc")]
51impl fmt::Debug for BorrowedFormatItem<'_> {
52    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53        match self {
54            Self::Literal(literal) => f.write_str(&String::from_utf8_lossy(literal)),
55            Self::Component(component) => component.fmt(f),
56            Self::Compound(compound) => compound.fmt(f),
57            Self::Optional(item) => f.debug_tuple("Optional").field(item).finish(),
58            Self::First(items) => f.debug_tuple("First").field(items).finish(),
59        }
60    }
61}
62
63impl From<Component> for BorrowedFormatItem<'_> {
64    fn from(component: Component) -> Self {
65        Self::Component(component)
66    }
67}
68
69impl TryFrom<BorrowedFormatItem<'_>> for Component {
70    type Error = error::DifferentVariant;
71
72    fn try_from(value: BorrowedFormatItem<'_>) -> Result<Self, Self::Error> {
73        match value {
74            BorrowedFormatItem::Component(component) => Ok(component),
75            _ => Err(error::DifferentVariant),
76        }
77    }
78}
79
80impl<'a> From<&'a [BorrowedFormatItem<'_>]> for BorrowedFormatItem<'a> {
81    fn from(items: &'a [BorrowedFormatItem<'_>]) -> Self {
82        Self::Compound(items)
83    }
84}
85
86impl<'a> TryFrom<BorrowedFormatItem<'a>> for &[BorrowedFormatItem<'a>] {
87    type Error = error::DifferentVariant;
88
89    fn try_from(value: BorrowedFormatItem<'a>) -> Result<Self, Self::Error> {
90        match value {
91            BorrowedFormatItem::Compound(items) => Ok(items),
92            _ => Err(error::DifferentVariant),
93        }
94    }
95}
96
97impl PartialEq<Component> for BorrowedFormatItem<'_> {
98    fn eq(&self, rhs: &Component) -> bool {
99        matches!(self, Self::Component(component) if component == rhs)
100    }
101}
102
103impl PartialEq<BorrowedFormatItem<'_>> for Component {
104    fn eq(&self, rhs: &BorrowedFormatItem<'_>) -> bool {
105        rhs == self
106    }
107}
108
109impl PartialEq<&[Self]> for BorrowedFormatItem<'_> {
110    fn eq(&self, rhs: &&[Self]) -> bool {
111        matches!(self, Self::Compound(compound) if compound == rhs)
112    }
113}
114
115impl PartialEq<BorrowedFormatItem<'_>> for &[BorrowedFormatItem<'_>] {
116    fn eq(&self, rhs: &BorrowedFormatItem<'_>) -> bool {
117        rhs == self
118    }
119}