【time-rs】解释://! Error that occurred at some stage of parsing(error/parse.rs)

这段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,
    },
}

属性说明:

  1. #[non_exhaustive]

    • 表示枚举未来可能添加新变体
    • 强制用户代码使用穷尽匹配,保持向后兼容
  2. #[allow(variant_size_differences)]

    • 允许变体大小不同(因为包含 Infallible 类型)
    • reason 属性说明:仅在某些平台上触发
  3. #[derive(...)]

    • 实现了 DebugCloneCopyPartialEqEq 等常见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 的转换

向上转换:Parsecrate::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::ErrorParse

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 具体层 格式解析错误

这种设计提供了灵活的错误处理机制,既支持通用的错误处理,也支持精确的错误类型匹配。

相关推荐
程序员大辉9 小时前
Rust使用IDE,除了vscode还有RustRover非商业用户可以免费使用
ide·vscode·rust
盒马盒马1 天前
Rust:内部可变性 & 型变
开发语言·后端·rust
云水木石1 天前
Rust 语言开发的 Linux 桌面来了
linux·运维·开发语言·后端·rust
Source.Liu1 天前
【time-rs】解释://! Invalid format description(error/invalid_format_description.rs)
rust·time
fegggye1 天前
创建一个rust写的python库[signatures和错误处理]
开发语言·python·rust
Source.Liu1 天前
【time-rs】解释://! Indeterminate offset(error/indeterminate_offset.rs)
rust·time
福大大架构师每日一题1 天前
rust 1.92.0 更新详解:语言特性增强、编译器优化与全新稳定API
java·javascript·rust
分布式存储与RustFS1 天前
MinIO替代方案精选:RustFS深度评测与选型指南
人工智能·rust·开源项目·对象存储·minio·企业存储·rustfs
JPX-NO1 天前
使用cargo-generate自定义创建项目模板
rust·mvc