🦀

thiserror を使って、ソースコードの行数を削減した

2025/02/28に公開

概要

std::error::Error を使用して実装していたエラーの型を、
thiserror クレートを使用して実装するように変更した。

その結果、ソースコードを約半分に削減することできた。

削減したソースコード

自作の正規表現コマンドで使用している ParseError を一例に、
std::error::Errorthiserror のそれぞれのソースコードを記載する。

他のエラーも含めた、変更時の commit は以下。

https://github.com/shu-kitamura/regular-expression/commit/d8b2535f1e2c90171c43ce6fa849de7069a8433a

std::error::Error を使用した実装

enum で ParseError を定義し、Display, Error トレイトを実装している。
特に表示用の Display トレイトがソースコードを長くしている。

#[derive(Debug, PartialEq)]
pub enum ParseError {
    InvalidEscape(usize, char), // 誤ったエスケープシーケンスが入力された場合
    InvalidRightParen(usize),   // ')' に対応する '(' が存在しない場合
    NoPrev(usize),              // '+', '*', '?', '|' の前に式がない場合
    NoRightParen,               // ')' が存在しない場合
    Empty,
}

/// ParseErrorを表示するため、Displayトレイトを実装
impl Display for ParseError {
    fn fmt (&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            ParseError::InvalidEscape(pos, c) => {
                write!(f, "ParseError: invalid escape : position = {pos}, character = '{c}'")
            }
            ParseError::InvalidRightParen(pos) => {
                write!(f, "ParseError: invalid right parenthesis : position = {pos}")
            }
            ParseError::NoPrev(pos) => {
                write!(f, "ParseError: no prevous expression : position = {pos}")
            }
            ParseError::NoRightParen => {
                write!(f, "ParseError: No right parenthesis")
            }
            ParseError::Empty => {
                write!(f, "ParseError: empty expression")
            }
        }
    }
}

/// エラー用にErrorトレイトを実装
impl Error for ParseError {}

thiserror を使用した実装

thiserror を使用した場合、以下のようになる。
表示用のエラーメッセージを attribute を設定でき、ソースコードの量も減っている。

#[derive(Debug, Error, PartialEq)]
pub enum CompileError {
    #[error("ParseError: invalid escape : position = {0}, character = '{1}'")]
    InvalidEscape(usize, char),
    #[error("ParseError: invalid right parenthesis : position = {0}")]
    InvalidRightParen(usize),
    #[error("ParseError: no previous expression : position = {0}")]
    NoPrev(usize),
    #[error("ParseError: No right parenthesis")]
    NoRightParen,
    #[error("ParseError: empty expression")]
    Empty,
}

Discussion