1 //! Error that occurred at some stage of parsing 2 3 use core::convert::TryFrom; 4 use core::fmt; 5 6 use crate::error::{self, ParseFromDescription, TryFromParsed}; 7 8 /// An error that occurred at some stage of parsing. 9 #[cfg_attr(__time_03_docs, doc(cfg(feature = "parsing")))] 10 #[allow(variant_size_differences)] 11 #[non_exhaustive] 12 #[derive(Debug, Clone, Copy, PartialEq, Eq)] 13 pub enum Parse { 14 #[allow(clippy::missing_docs_in_private_items)] 15 TryFromParsed(TryFromParsed), 16 #[allow(clippy::missing_docs_in_private_items)] 17 ParseFromDescription(ParseFromDescription), 18 /// The input should have ended, but there were characters remaining. 19 #[non_exhaustive] 20 UnexpectedTrailingCharacters, 21 } 22 23 impl fmt::Display for Parse { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result24 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 25 match self { 26 Self::TryFromParsed(err) => err.fmt(f), 27 Self::ParseFromDescription(err) => err.fmt(f), 28 Self::UnexpectedTrailingCharacters => f.write_str("unexpected trailing characters"), 29 } 30 } 31 } 32 33 #[cfg(feature = "std")] 34 impl std::error::Error for Parse { source(&self) -> Option<&(dyn std::error::Error + 'static)>35 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { 36 match self { 37 Self::TryFromParsed(err) => Some(err), 38 Self::ParseFromDescription(err) => Some(err), 39 Self::UnexpectedTrailingCharacters => None, 40 } 41 } 42 } 43 44 #[cfg_attr(__time_03_docs, doc(cfg(feature = "parsing")))] 45 impl From<TryFromParsed> for Parse { from(err: TryFromParsed) -> Self46 fn from(err: TryFromParsed) -> Self { 47 Self::TryFromParsed(err) 48 } 49 } 50 51 #[cfg_attr(__time_03_docs, doc(cfg(feature = "parsing")))] 52 impl TryFrom<Parse> for TryFromParsed { 53 type Error = error::DifferentVariant; 54 try_from(err: Parse) -> Result<Self, Self::Error>55 fn try_from(err: Parse) -> Result<Self, Self::Error> { 56 match err { 57 Parse::TryFromParsed(err) => Ok(err), 58 _ => Err(error::DifferentVariant), 59 } 60 } 61 } 62 63 #[cfg_attr(__time_03_docs, doc(cfg(feature = "parsing")))] 64 impl From<ParseFromDescription> for Parse { from(err: ParseFromDescription) -> Self65 fn from(err: ParseFromDescription) -> Self { 66 Self::ParseFromDescription(err) 67 } 68 } 69 70 #[cfg_attr(__time_03_docs, doc(cfg(feature = "parsing")))] 71 impl TryFrom<Parse> for ParseFromDescription { 72 type Error = error::DifferentVariant; 73 try_from(err: Parse) -> Result<Self, Self::Error>74 fn try_from(err: Parse) -> Result<Self, Self::Error> { 75 match err { 76 Parse::ParseFromDescription(err) => Ok(err), 77 _ => Err(error::DifferentVariant), 78 } 79 } 80 } 81 82 #[cfg_attr(__time_03_docs, doc(cfg(feature = "parsing")))] 83 impl From<Parse> for crate::Error { from(err: Parse) -> Self84 fn from(err: Parse) -> Self { 85 match err { 86 Parse::TryFromParsed(err) => Self::TryFromParsed(err), 87 Parse::ParseFromDescription(err) => Self::ParseFromDescription(err), 88 Parse::UnexpectedTrailingCharacters => Self::UnexpectedTrailingCharacters, 89 } 90 } 91 } 92 93 #[cfg_attr(__time_03_docs, doc(cfg(feature = "parsing")))] 94 impl TryFrom<crate::Error> for Parse { 95 type Error = error::DifferentVariant; 96 try_from(err: crate::Error) -> Result<Self, Self::Error>97 fn try_from(err: crate::Error) -> Result<Self, Self::Error> { 98 match err { 99 crate::Error::ParseFromDescription(err) => Ok(Self::ParseFromDescription(err)), 100 crate::Error::UnexpectedTrailingCharacters => Ok(Self::UnexpectedTrailingCharacters), 101 crate::Error::TryFromParsed(err) => Ok(Self::TryFromParsed(err)), 102 _ => Err(error::DifferentVariant), 103 } 104 } 105 } 106 107 #[cfg(feature = "serde-human-readable")] 108 impl Parse { 109 /// Obtain an error type for the deserializer. to_invalid_serde_value<'a, D: serde::Deserializer<'a>>(self) -> D::Error110 pub(crate) fn to_invalid_serde_value<'a, D: serde::Deserializer<'a>>(self) -> D::Error { 111 #[cfg(not(feature = "std"))] 112 use alloc::format; 113 114 use serde::de::Error; 115 116 match self { 117 Self::TryFromParsed(TryFromParsed::InsufficientInformation) => unreachable!( 118 "The deserializing format contains all information needed to construct a `Time`." 119 ), 120 Self::TryFromParsed(TryFromParsed::ComponentRange(err)) => { 121 err.to_invalid_serde_value::<D>() 122 } 123 Self::ParseFromDescription(ParseFromDescription::InvalidLiteral) => { 124 D::Error::invalid_value(serde::de::Unexpected::Other("literal"), &"valid format") 125 } 126 Self::ParseFromDescription(ParseFromDescription::InvalidComponent(component)) => { 127 D::Error::invalid_value( 128 serde::de::Unexpected::Other(component), 129 &&*format!("valid {}", component), 130 ) 131 } 132 Self::UnexpectedTrailingCharacters => D::Error::invalid_value( 133 serde::de::Unexpected::Other("literal"), 134 &"no extraneous characters", 135 ), 136 } 137 } 138 } 139