100 Exercises To Learn Rust - 5.14 source 풀기

문제

 

// TODO: Add a new error variant to `TicketNewError` for when the status string is invalid.
//   When calling `source` on an error of that variant, it should return a `ParseStatusError` rather than `None`.

#[derive(Debug, thiserror::Error)]
pub enum TicketNewError {
    #[error("Title cannot be empty")]
    TitleCannotBeEmpty ,
    #[error("Title cannot be longer than 50 bytes")]
    TitleTooLong,
    #[error("Description cannot be empty")]
    DescriptionCannotBeEmpty,
    #[error("Description cannot be longer than 500 bytes")]
    DescriptionTooLong,
}
...
impl Ticket {
    pub fn new(title: String, description: String, status: String) -> Result<Self, TicketNewError> {
        ...
        }
        ...

        // TODO: Parse the status string into a `Status` enum.

        Ok(Ticket {
            title,
            description,
            status,
        })
    }
}

풀이

 

pub enum TicketNewError {
    #[error("Title cannot be empty")]
    TitleCannotBeEmpty,
    #[error("Title cannot be longer than 50 bytes")]
    TitleTooLong,
    #[error("Description cannot be empty")]
    DescriptionCannotBeEmpty,
    #[error("Description cannot be longer than 500 bytes")]
    DescriptionTooLong,
    #[error("{0}")]
    InvalidStatusError(#[from] ParseStatusError),
}

 

status 문자열이 유효하지 않을 때를 처리하기 위한 배리언트 InvalidStatusError을 추가한다.

 

#[from] 속성을 사용하여 자동으로 다른 오류 타입을 변환하여 래핑(wrapping)한다.

즉, ParseStatusError를 TicketNewError::InvalidStatusError로 변환할 때 From<ParseStatusError> for TicketNewError 구현을 수동으로 작성할 필요가 없다.

 

let status = Status::try_from(status)?;

        // TODO: Parse the status string into a `Status` enum.
        Ok(Ticket {
            title,
            description,
            status,
        })

 

status는 새로 정의해 이전의status를 가리도록 한다. 이때 ?를 사용해 try_from 호출에서 Err(ParseStatusError)가 반환될 경우, 이를 자동으로 TicketNewError::InvalidStatusError로 변환한다.