💻 Exemplos: Capítulo 10: Enums, Option, Result e Pattern Matching com match/if let
💻 Exemplos: Capítulo 10: Enums Ricos, Option, Result e Pattern Matching
Especialização em Sistemas com Rust • Demonstrações Práticas Compiláveis
🎯 Objetivo dos Exemplos
Explorar Tipos Algébricos de Dados (Algebraic Data Types) através de Enums com variantes contendo dados embutidos, eliminação de ponteiros nulos com Option<T>, tratamento de falhas com Result<T, E>, casamento de padrões exaustivo com match, e propagação de erros com o operador ?.
1. Código Fonte Completo (src/main.rs)
//! Demonstração de Enums Ricos, Option, Result e Pattern Matching Exaustivo
// Enum com variantes heterogêneas contendo diferentes estruturas de dados
#[derive(Debug)]
enum ComandoRede {
Conectar { ip: String, porta: u16 },
EnviarPacote(Vec<u8>),
AjustarTimeout(u32),
Desconectar,
}
// Enum customizado para representar códigos de erro do sistema
#[derive(Debug)]
enum ErroRede {
PortaInvalida,
PacoteVazio,
ConexaoRecusada(String),
}
/// Função que processa comandos usando match exaustivo
fn despachar_comando(cmd: &ComandoRede) {
match cmd {
ComandoRede::Conectar { ip, porta } => {
println!(" [REDE] Estabelecendo handshake com {}:{}...", ip, porta);
}
ComandoRede::EnviarPacote(bytes) => {
println!(" [REDE] Transmitindo payload binário de {} bytes...", bytes.len());
}
ComandoRede::AjustarTimeout(ms) => {
println!(" [REDE] Timeout reconfigurado para {} ms.", ms);
}
ComandoRede::Desconectar => {
println!(" [REDE] Conexão encerrada graciosamente.");
}
}
}
/// Função que valida parâmetros retornando Result<T, ErroRede>
fn validar_e_montar_conexao(ip: &str, porta: u16) -> Result<ComandoRede, ErroRede> {
if porta == 0 {
return Err(ErroRede::PortaInvalida);
}
if ip == "127.0.0.99" {
return Err(ErroRede::ConexaoRecusada(String::from("Host em quarentena")));
}
Ok(ComandoRede::Conectar {
ip: String::from(ip),
porta,
})
}
/// Função que utiliza o operador '?' para propagar falhas instantaneamente
fn inicializar_subsistema() -> Result<(), ErroRede> {
let cmd1 = validar_e_montar_conexao("10.0.0.1", 8080)?; // Se retornar Err, sai da função aqui!
despachar_comando(&cmd1);
let cmd2 = validar_e_montar_conexao("10.0.0.2", 443)?;
despachar_comando(&cmd2);
Ok(())
}
fn main() {
println!("=== PATTERN MATCHING, OPTION E RESULT ===");
// 1. Despacho polimórfico de comandos via Enum
let comandos = [
ComandoRede::Conectar { ip: String::from("192.168.1.1"), porta: 22 },
ComandoRede::EnviarPacote(vec![0xAA, 0xBB, 0xCC, 0xDD]),
ComandoRede::AjustarTimeout(3000),
ComandoRede::Desconectar,
];
println!("Executando fila de comandos de rede:");
for c in &comandos {
despachar_comando(c);
}
// 2. Manipulação de Option<T> (Eliminando Null Pointers)
let usuarios_ativos: [Option<&str>; 3] = [Some("Alice"), None, Some("Roberto")];
println!("\nProcessando usuários com Option:");
for (i, usuario) in usuarios_ativos.iter().enumerate() {
match usuario {
Some(nome) => println!(" Slot {}: Usuário autenticado '{}'", i, nome),
None => println!(" Slot {}: Vazio (Nenhum usuário conectado)", i),
}
}
// 3. Sintaxe 'if let' para quando apenas uma variante interessa
let configuracao_opcional: Option<u32> = Some(4096);
if let Some(tamanho_buffer) = configuracao_opcional {
println!("\nConfiguração detectada via 'if let': {} bytes de buffer", tamanho_buffer);
}
// 4. Executando pipeline com o operador '?'
println!("\nIniciando subsistema com validação estrita:");
match inicializar_subsistema() {
Ok(_) => println!("Subsistema de rede iniciado com 100% de sucesso!"),
Err(e) => println!("Falha crítica de inicialização: {:?}", e),
}
// 5. Testando caso de erro com Result
println!("\nTestando tentativa de conexão com porta zero:");
let conexao_invalida = validar_e_montar_conexao("192.168.1.1", 0);
match conexao_invalida {
Ok(_) => println!("Conexão aceita inesperadamente!"),
Err(e) => println!("Erro capturado com sucesso pelo sistema: {:?}", e),
}
}
2. Saída Esperada no Terminal
=== PATTERN MATCHING, OPTION E RESULT ===
Executando fila de comandos de rede:
[REDE] Estabelecendo handshake com 192.168.1.1:22...
[REDE] Transmitindo payload binário de 4 bytes...
[REDE] Timeout reconfigurado para 3000 ms.
[REDE] Conexão encerrada graciosamente.
Processando usuários com Option:
Slot 0: Usuário autenticado 'Alice'
Slot 1: Vazio (Nenhum usuário conectado)
Slot 2: Usuário autenticado 'Roberto'
Configuração detectada via 'if let': 4096 bytes de buffer
Iniciando subsistema com validação estrita:
[REDE] Estabelecendo handshake com 10.0.0.1:8080...
[REDE] Estabelecendo handshake com 10.0.0.2:443...
Subsistema de rede iniciado com 100% de sucesso!
Testando tentativa de conexão com porta zero:
Erro capturado com sucesso pelo sistema: PortaInvalida