Skip to content

Commit

Permalink
Move FormatItem definition to its own module
Browse files Browse the repository at this point in the history
  • Loading branch information
jhpratt committed Nov 3, 2022
1 parent e4b40ad commit 139aba1
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 102 deletions.
105 changes: 105 additions & 0 deletions time/src/format_description/borrowed_format_item.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
//! A format item with borrowed data.

use alloc::string::String;
#[cfg(feature = "alloc")]
use core::fmt;

use crate::error;
use crate::format_description::Component;

/// A complete description of how to format and parse a type.
#[non_exhaustive]
#[cfg_attr(not(feature = "alloc"), derive(Debug))]
#[derive(Clone, PartialEq, Eq)]
pub enum BorrowedFormatItem<'a> {
/// Bytes that are formatted as-is.
///
/// **Note**: If you call the `format` method that returns a `String`, these bytes will be
/// passed through `String::from_utf8_lossy`.
Literal(&'a [u8]),
/// A minimal representation of a single non-literal item.
Component(Component),
/// A series of literals or components that collectively form a partial or complete
/// description.
Compound(&'a [Self]),
/// A `FormatItem` that may or may not be present when parsing. If parsing fails, there
/// will be no effect on the resulting `struct`.
///
/// This variant has no effect on formatting, as the value is guaranteed to be present.
Optional(&'a Self),
/// A series of `FormatItem`s where, when parsing, the first successful parse is used. When
/// formatting, the first element of the slice is used. An empty slice is a no-op when
/// formatting or parsing.
First(&'a [Self]),
}

#[cfg(feature = "alloc")]
impl fmt::Debug for BorrowedFormatItem<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
BorrowedFormatItem::Literal(literal) => f.write_str(&String::from_utf8_lossy(literal)),
BorrowedFormatItem::Component(component) => component.fmt(f),
BorrowedFormatItem::Compound(compound) => compound.fmt(f),
BorrowedFormatItem::Optional(item) => f.debug_tuple("Optional").field(item).finish(),
BorrowedFormatItem::First(items) => f.debug_tuple("First").field(items).finish(),
}
}
}

impl From<Component> for BorrowedFormatItem<'_> {
fn from(component: Component) -> Self {
Self::Component(component)
}
}

impl TryFrom<BorrowedFormatItem<'_>> for Component {
type Error = error::DifferentVariant;

fn try_from(value: BorrowedFormatItem<'_>) -> Result<Self, Self::Error> {
match value {
BorrowedFormatItem::Component(component) => Ok(component),
_ => Err(error::DifferentVariant),
}
}
}

impl<'a> From<&'a [BorrowedFormatItem<'_>]> for BorrowedFormatItem<'a> {
fn from(items: &'a [BorrowedFormatItem<'_>]) -> Self {
Self::Compound(items)
}
}

impl<'a> TryFrom<BorrowedFormatItem<'a>> for &[BorrowedFormatItem<'a>] {
type Error = error::DifferentVariant;

fn try_from(value: BorrowedFormatItem<'a>) -> Result<Self, Self::Error> {
match value {
BorrowedFormatItem::Compound(items) => Ok(items),
_ => Err(error::DifferentVariant),
}
}
}

impl PartialEq<Component> for BorrowedFormatItem<'_> {
fn eq(&self, rhs: &Component) -> bool {
matches!(self, Self::Component(component) if component == rhs)
}
}

impl PartialEq<BorrowedFormatItem<'_>> for Component {
fn eq(&self, rhs: &BorrowedFormatItem<'_>) -> bool {
rhs == self
}
}

impl PartialEq<&[Self]> for BorrowedFormatItem<'_> {
fn eq(&self, rhs: &&[Self]) -> bool {
matches!(self, Self::Compound(compound) if compound == rhs)
}
}

impl PartialEq<BorrowedFormatItem<'_>> for &[BorrowedFormatItem<'_>] {
fn eq(&self, rhs: &BorrowedFormatItem<'_>) -> bool {
rhs == self
}
}
104 changes: 2 additions & 102 deletions time/src/format_description/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,17 @@
//! [`format_description!`](crate::macros::format_description) macro, the
//! [`format_description::parse`](crate::format_description::parse()) function.

mod borrowed_format_item;
mod component;
pub mod modifier;
#[cfg(feature = "alloc")]
mod parse;

#[cfg(feature = "alloc")]
use alloc::string::String;
#[cfg(feature = "alloc")]
use core::fmt;
pub use borrowed_format_item::BorrowedFormatItem as FormatItem;

pub use self::component::Component;
#[cfg(feature = "alloc")]
pub use self::parse::parse;
use crate::error;

/// Well-known formats, typically standards.
pub mod well_known {
Expand All @@ -31,100 +28,3 @@ pub mod well_known {
pub use rfc2822::Rfc2822;
pub use rfc3339::Rfc3339;
}

/// A complete description of how to format and parse a type.
#[non_exhaustive]
#[cfg_attr(not(feature = "alloc"), derive(Debug))]
#[derive(Clone, PartialEq, Eq)]
pub enum FormatItem<'a> {
/// Bytes that are formatted as-is.
///
/// **Note**: If you call the `format` method that returns a `String`, these bytes will be
/// passed through `String::from_utf8_lossy`.
Literal(&'a [u8]),
/// A minimal representation of a single non-literal item.
Component(Component),
/// A series of literals or components that collectively form a partial or complete
/// description.
Compound(&'a [Self]),
/// A `FormatItem` that may or may not be present when parsing. If parsing fails, there will be
/// no effect on the resulting `struct`.
///
/// This variant has no effect on formatting, as the value is guaranteed to be present.
Optional(&'a Self),
/// A series of `FormatItem`s where, when parsing, the first successful parse is used. When
/// formatting, the first element of the slice is used. An empty slice is a no-op when
/// formatting or parsing.
First(&'a [Self]),
}

#[cfg(feature = "alloc")]
impl fmt::Debug for FormatItem<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
FormatItem::Literal(literal) => f.write_str(&String::from_utf8_lossy(literal)),
FormatItem::Component(component) => component.fmt(f),
FormatItem::Compound(compound) => compound.fmt(f),
FormatItem::Optional(item) => f.debug_tuple("Optional").field(item).finish(),
FormatItem::First(items) => f.debug_tuple("First").field(items).finish(),
}
}
}

impl From<Component> for FormatItem<'_> {
fn from(component: Component) -> Self {
Self::Component(component)
}
}

impl TryFrom<FormatItem<'_>> for Component {
type Error = error::DifferentVariant;

fn try_from(value: FormatItem<'_>) -> Result<Self, Self::Error> {
match value {
FormatItem::Component(component) => Ok(component),
_ => Err(error::DifferentVariant),
}
}
}

impl<'a> From<&'a [FormatItem<'_>]> for FormatItem<'a> {
fn from(items: &'a [FormatItem<'_>]) -> FormatItem<'a> {
FormatItem::Compound(items)
}
}

impl<'a> TryFrom<FormatItem<'a>> for &[FormatItem<'a>] {
type Error = error::DifferentVariant;

fn try_from(value: FormatItem<'a>) -> Result<Self, Self::Error> {
match value {
FormatItem::Compound(items) => Ok(items),
_ => Err(error::DifferentVariant),
}
}
}

impl PartialEq<Component> for FormatItem<'_> {
fn eq(&self, rhs: &Component) -> bool {
matches!(self, FormatItem::Component(component) if component == rhs)
}
}

impl PartialEq<FormatItem<'_>> for Component {
fn eq(&self, rhs: &FormatItem<'_>) -> bool {
rhs == self
}
}

impl PartialEq<&[FormatItem<'_>]> for FormatItem<'_> {
fn eq(&self, rhs: &&[FormatItem<'_>]) -> bool {
matches!(self, FormatItem::Compound(compound) if compound == rhs)
}
}

impl PartialEq<FormatItem<'_>> for &[FormatItem<'_>] {
fn eq(&self, rhs: &FormatItem<'_>) -> bool {
rhs == self
}
}

0 comments on commit 139aba1

Please sign in to comment.