time/format_description/
owned_format_item.rs

1//! A format item with owned data.
2
3use alloc::boxed::Box;
4use alloc::string::String;
5use alloc::vec::Vec;
6use core::fmt;
7
8use crate::error;
9use crate::format_description::{BorrowedFormatItem, Component};
10
11/// A complete description of how to format and parse a type.
12#[non_exhaustive]
13#[derive(Clone, PartialEq, Eq)]
14pub enum OwnedFormatItem {
15    /// Bytes that are formatted as-is.
16    ///
17    /// **Note**: These bytes **should** be UTF-8, but are not required to be. The value is passed
18    /// through `String::from_utf8_lossy` when necessary.
19    Literal(Box<[u8]>),
20    /// A minimal representation of a single non-literal item.
21    Component(Component),
22    /// A series of literals or components that collectively form a partial or complete
23    /// description.
24    Compound(Box<[Self]>),
25    /// A `FormatItem` that may or may not be present when parsing. If parsing fails, there
26    /// will be no effect on the resulting `struct`.
27    ///
28    /// This variant has no effect on formatting, as the value is guaranteed to be present.
29    Optional(Box<Self>),
30    /// A series of `FormatItem`s where, when parsing, the first successful parse is used. When
31    /// formatting, the first element of the [`Vec`] is used. An empty [`Vec`] is a no-op when
32    /// formatting or parsing.
33    First(Box<[Self]>),
34}
35
36impl fmt::Debug for OwnedFormatItem {
37    #[inline]
38    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39        match self {
40            Self::Literal(literal) => f.write_str(&String::from_utf8_lossy(literal)),
41            Self::Component(component) => component.fmt(f),
42            Self::Compound(compound) => compound.fmt(f),
43            Self::Optional(item) => f.debug_tuple("Optional").field(item).finish(),
44            Self::First(items) => f.debug_tuple("First").field(items).finish(),
45        }
46    }
47}
48
49impl From<BorrowedFormatItem<'_>> for OwnedFormatItem {
50    #[inline]
51    fn from(item: BorrowedFormatItem<'_>) -> Self {
52        (&item).into()
53    }
54}
55
56impl From<&BorrowedFormatItem<'_>> for OwnedFormatItem {
57    #[inline]
58    fn from(item: &BorrowedFormatItem<'_>) -> Self {
59        match item {
60            BorrowedFormatItem::Literal(literal) => {
61                Self::Literal(literal.to_vec().into_boxed_slice())
62            }
63            BorrowedFormatItem::Component(component) => Self::Component(*component),
64            BorrowedFormatItem::Compound(compound) => Self::Compound(
65                compound
66                    .iter()
67                    .cloned()
68                    .map(Into::into)
69                    .collect::<Vec<_>>()
70                    .into_boxed_slice(),
71            ),
72            BorrowedFormatItem::Optional(item) => Self::Optional(Box::new((*item).into())),
73            BorrowedFormatItem::First(items) => Self::First(
74                items
75                    .iter()
76                    .cloned()
77                    .map(Into::into)
78                    .collect::<Vec<_>>()
79                    .into_boxed_slice(),
80            ),
81        }
82    }
83}
84
85impl From<Vec<BorrowedFormatItem<'_>>> for OwnedFormatItem {
86    #[inline]
87    fn from(items: Vec<BorrowedFormatItem<'_>>) -> Self {
88        items.as_slice().into()
89    }
90}
91
92impl<'a, T> From<&T> for OwnedFormatItem
93where
94    T: AsRef<[BorrowedFormatItem<'a>]> + ?Sized,
95{
96    #[inline]
97    fn from(items: &T) -> Self {
98        Self::Compound(
99            items
100                .as_ref()
101                .iter()
102                .cloned()
103                .map(Into::into)
104                .collect::<Vec<_>>()
105                .into_boxed_slice(),
106        )
107    }
108}
109
110impl From<Component> for OwnedFormatItem {
111    #[inline]
112    fn from(component: Component) -> Self {
113        Self::Component(component)
114    }
115}
116
117impl TryFrom<OwnedFormatItem> for Component {
118    type Error = error::DifferentVariant;
119
120    #[inline]
121    fn try_from(value: OwnedFormatItem) -> Result<Self, Self::Error> {
122        match value {
123            OwnedFormatItem::Component(component) => Ok(component),
124            _ => Err(error::DifferentVariant),
125        }
126    }
127}
128
129impl From<Vec<Self>> for OwnedFormatItem {
130    #[inline]
131    fn from(items: Vec<Self>) -> Self {
132        Self::Compound(items.into_boxed_slice())
133    }
134}
135
136impl TryFrom<OwnedFormatItem> for Vec<OwnedFormatItem> {
137    type Error = error::DifferentVariant;
138
139    #[inline]
140    fn try_from(value: OwnedFormatItem) -> Result<Self, Self::Error> {
141        match value {
142            OwnedFormatItem::Compound(items) => Ok(items.into_vec()),
143            _ => Err(error::DifferentVariant),
144        }
145    }
146}
147
148impl PartialEq<Component> for OwnedFormatItem {
149    #[inline]
150    fn eq(&self, rhs: &Component) -> bool {
151        matches!(self, Self::Component(component) if component == rhs)
152    }
153}
154
155impl PartialEq<OwnedFormatItem> for Component {
156    #[inline]
157    fn eq(&self, rhs: &OwnedFormatItem) -> bool {
158        rhs == self
159    }
160}
161
162impl PartialEq<&[Self]> for OwnedFormatItem {
163    #[inline]
164    fn eq(&self, rhs: &&[Self]) -> bool {
165        matches!(self, Self::Compound(compound) if &&**compound == rhs)
166    }
167}
168
169impl PartialEq<OwnedFormatItem> for &[OwnedFormatItem] {
170    #[inline]
171    fn eq(&self, rhs: &OwnedFormatItem) -> bool {
172        rhs == self
173    }
174}