这段Rust代码定义了一个解析错误的通用枚举类型 Parse,用于表示在时间解析过程中可能发生的各种错误。它是时间解析库中的核心错误类型。
枚举定义
rust
#[non_exhaustive]
#[allow(variant_size_differences, reason = "only triggers on some platforms")]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Parse {
TryFromParsed(TryFromParsed),
ParseFromDescription(ParseFromDescription),
#[non_exhaustive]
#[deprecated(
since = "0.3.28",
note = "no longer output. moved to the `ParseFromDescription` variant"
)]
UnexpectedTrailingCharacters {
#[doc(hidden)]
never: Infallible,
},
}
属性说明:
-
#[non_exhaustive]:- 表示枚举未来可能添加新变体
- 强制用户代码使用穷尽匹配,保持向后兼容
-
#[allow(variant_size_differences)]:- 允许变体大小不同(因为包含
Infallible类型) reason属性说明:仅在某些平台上触发
- 允许变体大小不同(因为包含
-
#[derive(...)]:- 实现了
Debug、Clone、Copy、PartialEq、Eq等常见trait
- 实现了
变体详解
1. TryFromParsed(TryFromParsed)
- 表示在从解析结果转换到目标类型时发生的错误
- 例如:解析出的日期时间值超出目标类型的有效范围
2. ParseFromDescription(ParseFromDescription)
- 表示根据格式描述进行解析时发生的错误
- 例如:输入字符串与格式描述不匹配
3. UnexpectedTrailingCharacters(已弃用)
rust
#[deprecated(since = "0.3.28", note = "...")]
UnexpectedTrailingCharacters {
#[doc(hidden)]
never: Infallible,
}
- 已弃用:从 0.3.28 版本开始不再使用
- 迁移 :功能已移至
ParseFromDescription变体 Infallible:永不实例化的类型,确保该变体无法构造- 设计目的:保持API兼容性,同时逐步移除旧功能
Display trait 实现
rust
impl fmt::Display for Parse {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::TryFromParsed(err) => err.fmt(f),
Self::ParseFromDescription(err) => err.fmt(f),
#[allow(deprecated)]
Self::UnexpectedTrailingCharacters { never } => match *never {},
}
}
}
实现特点:
- 委托给内部错误的
Display实现 - 对于已弃用变体,使用
match *never {}保证编译通过 #[allow(deprecated)]允许使用已弃用的变体模式
Error trait 实现
rust
impl core::error::Error for Parse {
fn source(&self) -> Option<&(dyn core::error::Error + 'static)> {
match self {
Self::TryFromParsed(err) => Some(err),
Self::ParseFromDescription(err) => Some(err),
#[allow(deprecated)]
Self::UnexpectedTrailingCharacters { never } => match *never {},
}
}
}
特点:
- 实现
source()方法,提供错误的根本原因 - 支持错误链(error chain)
- 同样处理了已弃用变体
与内部错误类型的转换
从 TryFromParsed 转换到 Parse
rust
impl From<TryFromParsed> for Parse {
fn from(err: TryFromParsed) -> Self {
Self::TryFromParsed(err)
}
}
从 Parse 尝试转换到 TryFromParsed
rust
impl TryFrom<Parse> for TryFromParsed {
type Error = error::DifferentVariant;
fn try_from(err: Parse) -> Result<Self, Self::Error> {
match err {
Parse::TryFromParsed(err) => Ok(err),
_ => Err(error::DifferentVariant),
}
}
}
从 ParseFromDescription 转换到 Parse
rust
impl From<ParseFromDescription> for Parse {
fn from(err: ParseFromDescription) -> Self {
Self::ParseFromDescription(err)
}
}
从 Parse 尝试转换到 ParseFromDescription
rust
impl TryFrom<Parse> for ParseFromDescription {
type Error = error::DifferentVariant;
fn try_from(err: Parse) -> Result<Self, Self::Error> {
match err {
Parse::ParseFromDescription(err) => Ok(err),
_ => Err(error::DifferentVariant),
}
}
}
转换模式总结:
From<T>:总是成功,向上转换TryFrom<Parse>:可能失败,向下转换DifferentVariant:当错误类型不匹配时返回
与 crate::Error 的转换
向上转换:Parse → crate::Error
rust
impl From<Parse> for crate::Error {
fn from(err: Parse) -> Self {
match err {
Parse::TryFromParsed(err) => Self::TryFromParsed(err),
Parse::ParseFromDescription(err) => Self::ParseFromDescription(err),
#[allow(deprecated)]
Parse::UnexpectedTrailingCharacters { never } => match never {},
}
}
}
处理已弃用变体:
- 对于
UnexpectedTrailingCharacters,使用match never {}保证不会执行 - 确保编译通过,即使变体已弃用
向下转换:crate::Error → Parse
rust
impl TryFrom<crate::Error> for Parse {
type Error = error::DifferentVariant;
fn try_from(err: crate::Error) -> Result<Self, Self::Error> {
match err {
crate::Error::ParseFromDescription(err) => Ok(Self::ParseFromDescription(err)),
#[allow(deprecated)]
crate::Error::UnexpectedTrailingCharacters { never } => match never {},
crate::Error::TryFromParsed(err) => Ok(Self::TryFromParsed(err)),
_ => Err(error::DifferentVariant),
}
}
}
使用场景示例
解析时间字符串
rust
use time::format_description;
use time::parsing::Parse;
fn parse_datetime(input: &str) -> Result<OffsetDateTime, Parse> {
let format = format_description::parse("[year]-[month]-[day] [hour]:[minute]:[second]")?;
let parsed = PrimitiveDateTime::parse(input, &format)?;
Ok(parsed.into())
}
错误处理
rust
match parse_datetime("2023-13-01 25:00:00") {
Ok(dt) => println!("解析成功: {}", dt),
Err(Parse::ParseFromDescription(err)) => {
eprintln!("格式解析错误: {}", err);
}
Err(Parse::TryFromParsed(err)) => {
eprintln!("类型转换错误: {}", err);
}
}
设计特点
1. 分层错误处理
crate::Error
├── Parse
│ ├── TryFromParsed
│ └── ParseFromDescription
└── Other errors...
2. 向后兼容性
- 使用
#[deprecated]和Infallible平滑过渡 #[non_exhaustive]保护未来扩展
3. 类型安全
- 双向转换确保类型安全
- 使用
TryFrom进行安全的错误类型提取
4. 性能优化
#[inline]提示内联优化- 大部分类型实现
Copy,减少分配
与其他错误类型的关系
| 错误类型 | 层级 | 用途 |
|---|---|---|
crate::Error |
顶级 | 所有错误的容器 |
Parse |
中间层 | 解析相关错误 |
TryFromParsed |
具体层 | 转换错误 |
ParseFromDescription |
具体层 | 格式解析错误 |
这种设计提供了灵活的错误处理机制,既支持通用的错误处理,也支持精确的错误类型匹配。