100 Exercises To Learn Rust - 5.8 Error enums 풀기

문제

// TODO: title error와 description error에 대응하는 두 개의 배리언트를 사용합니다.
// 각각의 배리언트는 무엇이 잘못되었는지 설명하는 문자열을 포함해야 합니다.
// `Ticket::new`의 구현 또한 업데이트해야 할 것입니다.
enum TicketNewError { }


// TODO: `easy_ticket`은 title이 잘못되면 panic을 일으켜야 하고,
// `TicketNewError` 열거형에서 관련된 배리언트에 저장된 에러 메시지를 사용합니다.
// description이 잘못되면 "Description not provided"라는 기본 description을 사용합니다.

fn easy_ticket(title: String, description: String, status: Status) -> Ticket {
    todo!()
}

#[derive(Debug, PartialEq)]
struct Ticket {
    title: String,
    description: String,
    status: Status,
}

#[derive(Debug, PartialEq, Clone)]
enum Status {
    ToDo,
    InProgress { assigned_to: String },
    Done,
}

impl Ticket {
    pub fn new(
        title: String,
        description: String,
        status: Status,
    ) -> Result<Ticket, TicketNewError> {
        if title.is_empty() {
            return Err("Title cannot be empty".to_string());
        }
        if title.len() > 50 {
            return Err("Title cannot be longer than 50 bytes".to_string());
        }
        if description.is_empty() {
            return Err("Description cannot be empty".to_string());
        }
        if description.len() > 500 {
            return Err("Description cannot be longer than 500 bytes".to_string());
        }

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

 

 

풀이

#[derive(Debug)]
enum TicketNewError {
    TitleError(String),
    DescriptionError(String),
}


// TODO: `easy_ticket`은 title이 잘못되면 panic을 일으켜야 하고,
// `TicketNewError` 열거형에서 관련된 배리언트에 저장된 에러 메시지를 사용합니다.
// description이 잘못되면 "Description not provided"라는 기본 description을 사용합니다.
fn easy_ticket(title: String, description: String, status: Status) -> Ticket {
    match Ticket::new(title.clone(), description, status.clone()) {
        Ok(ticket) => ticket,
        Err(TicketNewError::TitleError(err)) => {
            panic!("{}", err);
        }
        Err(TicketNewError::DescriptionError(_)) => {
            Ticket::new(title, "Description not provided".into(), status).unwrap()
        }

    }
}

 

title에 대응하는 TitleError(String), escription에 대응하는 DescriptionError(String) 배리언트를 정의한다.

 

easy_ticket()match를 통해서 정상적인 경우인 Ok(ticket),

제목 에러가 발생하는 경우인 Err(TicketNewError::TitleError(err)),

설명 에러가 발생하는 경우인 Err(TicketNewError::DescriptionError(_))를 모두 처리한다.

 

match하는 대상은 Ticket 타입 자체다. 설명 에러가 발생할 경우 기본 설명을 사용하는 티켓을 새로 만들도록 했으므로, 값이 이동되지 않도록 titlestatusclone()을 사용한다.

 

제목 에러가 발생하는 경우에는 new()에서 구현한 에러 메시지를 사용해야 하므로, TitleError(err)로 에러 메시지를 err에 바인딩한 후 사용한다.

설명 에러가 발생하는 경우에는 새로운 Ticket을 만들고, unwrap()으로 꺼낸 Description을 에러 메시지로 사용하게 되므로 바인딩할 값이 없다. 그러므로 _로 자리만 표시한다.