diff --git a/src/format/mod.rs b/src/format/mod.rs index a0d0263..caecb2b 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -200,15 +200,6 @@ pub enum Fixed { /// Same to [`TimezoneOffsetColonZ`](#variant.TimezoneOffsetColonZ) but prints no colon. /// Parsing allows an optional colon. TimezoneOffsetZ, - /// Same as [`TimezoneOffsetColonZ`](#variant.TimezoneOffsetColonZ), but - /// allows missing minutes (per [ISO 8601][iso8601]). - /// - /// # Panics - /// - /// If you try to use this for printing. - /// - /// [iso8601]: https://en.wikipedia.org/wiki/ISO_8601#Time_offsets_from_UTC - TimezoneOffsetPermissive, /// RFC 2822 date and time syntax. Commonly used for email and MIME date and time. RFC2822, /// RFC 3339 & ISO 8601 date and time syntax. @@ -222,29 +213,22 @@ pub enum Fixed { } /// An opaque type representing fixed-format item types for internal uses only. +#[derive(Debug, Clone, PartialEq, Eq)] pub struct InternalFixed { - _dummy: Void, + val: InternalInternal, } -impl Clone for InternalFixed { - fn clone(&self) -> Self { - match self._dummy {} - } -} - -impl PartialEq for InternalFixed { - fn eq(&self, _other: &InternalFixed) -> bool { - match self._dummy {} - } -} - -impl Eq for InternalFixed { -} - -impl fmt::Debug for InternalFixed { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "") - } +#[derive(Debug, Clone, PartialEq, Eq)] +enum InternalInternal { + /// Same as [`TimezoneOffsetColonZ`](#variant.TimezoneOffsetColonZ), but + /// allows missing minutes (per [ISO 8601][iso8601]). + /// + /// # Panics + /// + /// If you try to use this for printing. + /// + /// [iso8601]: https://en.wikipedia.org/wiki/ISO_8601#Time_offsets_from_UTC + TimezoneOffsetPermissive, } /// A single formatting item. This is used for both formatting and parsing. @@ -273,6 +257,7 @@ macro_rules! num { ($x:ident) => (Item::Numeric(Numeric::$x, Pad::None)) } macro_rules! num0 { ($x:ident) => (Item::Numeric(Numeric::$x, Pad::Zero)) } macro_rules! nums { ($x:ident) => (Item::Numeric(Numeric::$x, Pad::Space)) } macro_rules! fix { ($x:ident) => (Item::Fixed(Fixed::$x)) } +macro_rules! internal_fix { ($x:ident) => (Item::Fixed(Fixed::Internal(InternalFixed { val: InternalInternal::$x })))} /// An error from the `parse` function. #[derive(Debug, Clone, PartialEq, Eq, Copy)] @@ -500,7 +485,7 @@ pub fn format<'a, I>(w: &mut fmt::Formatter, date: Option<&NaiveDate>, time: Opt off.map(|&(_, off)| write_local_minus_utc(w, off, false, false)), TimezoneOffsetZ => off.map(|&(_, off)| write_local_minus_utc(w, off, true, false)), - TimezoneOffsetPermissive => + Internal(InternalFixed { val: InternalInternal::TimezoneOffsetPermissive }) => panic!("Do not try to write %#z it is undefined"), RFC2822 => // same to `%a, %e %b %Y %H:%M:%S %z` if let (Some(d), Some(t), Some(&(_, off))) = (date, time, off) { @@ -522,9 +507,6 @@ pub fn format<'a, I>(w: &mut fmt::Formatter, date: Option<&NaiveDate>, time: Opt } else { None }, - - // for the future expansion - Internal(ref int) => match int._dummy {}, }; match ret { diff --git a/src/format/parse.rs b/src/format/parse.rs index 493d5ca..c5b14a2 100644 --- a/src/format/parse.rs +++ b/src/format/parse.rs @@ -9,7 +9,7 @@ use std::usize; use Weekday; use super::scan; -use super::{Parsed, ParseResult, Item}; +use super::{Parsed, ParseResult, Item, InternalFixed, InternalInternal}; use super::{OUT_OF_RANGE, INVALID, TOO_SHORT, TOO_LONG, BAD_FORMAT}; fn set_weekday_with_num_days_from_sunday(p: &mut Parsed, v: i64) -> ParseResult<()> { @@ -328,7 +328,7 @@ pub fn parse<'a, I>(parsed: &mut Parsed, mut s: &str, items: I) -> ParseResult<( scan::colon_or_space)); try!(parsed.set_offset(i64::from(offset))); } - TimezoneOffsetPermissive => { + Internal(InternalFixed { val: InternalInternal::TimezoneOffsetPermissive }) => { let offset = try_consume!(scan::timezone_offset_permissive( s.trim_left(), scan::colon_or_space)); try!(parsed.set_offset(i64::from(offset))); @@ -336,9 +336,6 @@ pub fn parse<'a, I>(parsed: &mut Parsed, mut s: &str, items: I) -> ParseResult<( RFC2822 => try_consume!(parse_rfc2822(parsed, s)), RFC3339 => try_consume!(parse_rfc3339(parsed, s)), - - // for the future expansion - Internal(ref int) => match int._dummy {}, } } @@ -575,10 +572,10 @@ fn test_parse() { check!("zulu", [fix!(TimezoneOffsetZ), lit!("ulu")]; offset: 0); check!("+1234ulu", [fix!(TimezoneOffsetZ), lit!("ulu")]; offset: 754 * 60); check!("+12:34ulu", [fix!(TimezoneOffsetZ), lit!("ulu")]; offset: 754 * 60); - check!("Z", [fix!(TimezoneOffsetPermissive)]; offset: 0); - check!("z", [fix!(TimezoneOffsetPermissive)]; offset: 0); - check!("+12:00", [fix!(TimezoneOffsetPermissive)]; offset: 12 * 60 * 60); - check!("+12", [fix!(TimezoneOffsetPermissive)]; offset: 12 * 60 * 60); + check!("Z", [internal_fix!(TimezoneOffsetPermissive)]; offset: 0); + check!("z", [internal_fix!(TimezoneOffsetPermissive)]; offset: 0); + check!("+12:00", [internal_fix!(TimezoneOffsetPermissive)]; offset: 12 * 60 * 60); + check!("+12", [internal_fix!(TimezoneOffsetPermissive)]; offset: 12 * 60 * 60); check!("???", [fix!(TimezoneName)]; BAD_FORMAT); // not allowed // some practical examples diff --git a/src/format/strftime.rs b/src/format/strftime.rs index 54659a4..3d65019 100644 --- a/src/format/strftime.rs +++ b/src/format/strftime.rs @@ -147,7 +147,7 @@ Notes: */ -use super::{Item, Numeric, Fixed, Pad}; +use super::{Item, Numeric, Fixed, InternalFixed, InternalInternal, Pad}; /// Parsing iterator for `strftime`-like format strings. #[derive(Clone, Debug)] @@ -270,7 +270,7 @@ impl<'a> Iterator for StrftimeItems<'a> { num0!(YearMod100)], 'y' => num0!(YearMod100), 'z' => if is_alternate { - fix!(TimezoneOffsetPermissive) + internal_fix!(TimezoneOffsetPermissive) } else { fix!(TimezoneOffset) }, @@ -380,7 +380,7 @@ fn test_strftime_items() { assert_eq!(parse_and_collect("%0e"), [num0!(Day)]); assert_eq!(parse_and_collect("%_e"), [nums!(Day)]); assert_eq!(parse_and_collect("%z"), [fix!(TimezoneOffset)]); - assert_eq!(parse_and_collect("%#z"), [fix!(TimezoneOffsetPermissive)]); + assert_eq!(parse_and_collect("%#z"), [internal_fix!(TimezoneOffsetPermissive)]); assert_eq!(parse_and_collect("%#m"), [Item::Error]); }