Introdução
Uma struct agrupa campos que sempre pertencem juntos. Um enum representa um valor que pode ser uma entre várias alternativas, e cada alternativa pode carregar dados diferentes. A expressão match do Rust trata essas alternativas de forma explícita.
Você completará um enum de mensagens, extrairá coordenadas de uma variante por desestruturação e ampliará o modelo com uma nova variante. O compilador mostrará deliberadamente por que todas as variantes possíveis precisam ser cobertas antes que o processador de mensagens possa ser executado.
Defina variantes que carregam dados
Nesta etapa, você definirá três formatos alternativos para um único tipo Message.
Entre no projeto preparado e abra o código-fonte:
cd /home/labex/project/message-processor
nano src/main.rs
Uma declaração de enum lista variantes entre chaves. O código constrói uma variante usando o nome do enum, :: e o nome da variante. Variantes diferentes do mesmo enum podem carregar tipos de dados diferentes.
Substitua o comentário da Etapa 1 por:
Text(String),
Move { x: i32, y: i32 },
Stop,
Text(String) carrega um valor sem nome, um formato que o Rust chama de variante semelhante a tupla. Move { x, y } carrega campos nomeados, por isso é chamada de variante semelhante a struct. Stop não carrega dados adicionais e é chamada de variante unitária. É mais importante lembrar “um valor sem nome, campos nomeados ou nenhum dado” do que memorizar imediatamente os nomes formais. Apesar dos formatos diferentes, todo valor construído tem o tipo único Message.
Salve com Ctrl+O, pressione Enter e saia com Ctrl+X. Verifique e execute o processador preparado:
cargo check
cargo run --quiet
A saída deve ser:
Text: Maintenance at 9
Move received
Stop requested
O match preparado seleciona um braço para cada variante. Todo braço tem o formato padrão => comportamento, e vírgulas separam os braços curtos. O padrão Text(text) dá um nome à string carregada. O braço Move também dá nomes a x e y e, em seguida, agrupa temporariamente esses valores como (x, y). Aqui, os parênteses criam uma tupla de dois valores usada apenas como estrutura provisória já preparada; tuplas não são um objetivo de aprendizagem deste Lab. O nome _coordinates começa com _, indicando ao Rust que deixar esse valor temporário sem uso é intencional. Isso mantém a primeira execução sem avisos. Na próxima etapa, você substituirá essa estrutura provisória e usará as duas coordenadas na saída visível.
Use os dados desestruturados da variante
Nesta etapa, você alterará o braço Move do match para que as coordenadas extraídas pelo padrão apareçam na saída.
Os padrões podem decompor a variante que correspondem. Em uma variante semelhante a struct, escrever os nomes dos campos cria bindings que a expressão do braço pode usar.
Abra o código-fonte:
nano src/main.rs
Substitua o braço Move completo por:
Message::Move { x, y } => println!("Move to ({x}, {y})"),
Quando uma mensagem Move chega, o padrão associa os campos armazenados aos nomes locais x e y. A expressão de impressão usa esses nomes; não é necessário acessar campos separadamente nem fazer conversão de tipo.
Salve e saia; depois, execute:
cargo run --quiet
A linha do meio agora deve ser:
Move to (3, -2)
O valor negativo de y comprova que o braço usou os dados carregados pela variante real, em vez de imprimir coordenadas fixas.
Amplie um match exaustivo
Nesta etapa, você adicionará uma mensagem Pause, observará a verificação de exaustividade do compilador e, em seguida, tratará a nova alternativa.
Um match deve cobrir todos os valores possíveis do enum. Essa regra significa que adicionar uma variante identifica cada match que precisa decidir o que fazer com o novo caso.
Abra o arquivo e adicione esta variante imediatamente abaixo de Stop:
nano src/main.rs
Pause(u32),
Salve e saia; depois, verifique o programa. A falha é esperada:
cargo check
Encontre a parte estável do diagnóstico:
error[E0004]: non-exhaustive patterns: `Message::Pause(_)` not covered
O compilador aponta para match message porque o enum agora pode conter um valor Pause, mas nenhum braço explica o que fazer com ele.
Abra o código-fonte novamente. Adicione este braço abaixo do braço Stop:
Message::Pause(seconds) => println!("Pause for {seconds} seconds"),
Depois, remova o // inicial da linha preparada process(Message::Pause(5)); em main. O padrão dá ao valor u32 carregado o nome local seconds.
Salve e saia; depois, verifique e execute:
cargo check
cargo run --quiet
A saída completa deve ser:
Text: Maintenance at 9
Move to (3, -2)
Stop requested
Pause for 5 seconds
A verificação bem-sucedida comprova que o match voltou a ser exaustivo, e a quarta linha comprova que o novo braço desestruturou a duração de Pause.
Resumo
Você definiu variantes de enum unitárias, semelhantes a tuplas e semelhantes a structs; desestruturou dados carregados usando padrões de match; e usou o erro do compilador E0004 para ampliar um match de forma exaustiva depois de adicionar uma nova alternativa.


