SwiftHTML & CSSSolidityDesenvolvimento de JogosSolana/Rust
19.11.2024

Aula 072: Serialização Avançada com Borsh e Outros Formatos

A serialização é um conceito fundamental na programação, permitindo-nos converter estruturas de dados complexas em formatos que podem ser facilmente armazenados e transmitidos. No contexto do desenvolvimento em Rust e Solana, a serialização se torna ainda mais crucial devido à natureza das aplicações blockchain, onde a integridade e eficiência dos dados são primordiais. Nesta aula, vamos explorar técnicas avançadas de serialização, enfocando Borsh, um formato de serialização binária amplamente utilizado no ecossistema Solana, além de outros formatos populares em Rust.

O que é Borsh?

Borsh (Binary Object Representation Serializer for Hashing) é um formato de serialização projetado para ser eficiente, compacto e fácil de usar com Rust. Ele é utilizado principalmente para serialização e desserialização rápida e segura de estruturas de dados, especialmente em aplicações blockchain onde o desempenho é crítico.

Começando com Borsh

Para começar, vamos adicionar a dependência necessária ao nosso Cargo.toml:

[dependencies]
borsh = "0.10"

Definindo Estruturas de Dados

Vamos definir uma estrutura simples em Rust que iremos serializar e desserializar utilizando Borsh.

use borsh::{BorshDeserialize, BorshSerialize};

#[derive(BorshSerialize, BorshDeserialize, Debug)]
struct Usuario {
    nome_de_usuario: String,
    idade: u32,
}

fn main() {
    // Cria uma nova instância de Usuario
    let usuario = Usuario {
        nome_de_usuario: String::from("alice"),
        idade: 30,
    };

    // Serializa a instância de Usuario
    let usuario_serializado = usuario.try_to_vec().expect("Falha ao serializar");

    // Imprime os bytes do usuário serializado
    println!("Usuário Serializado: {:?}", &usuario_serializado);

    // Desserializa a instância de Usuario
    let usuario_desserializado: Usuario = Usuario::try_from_slice(&usuario_serializado).expect("Falha ao desserializar");

    // Imprime o usuário desserializado
    println!("Usuário Desserializado: {:?}", usuario_desserializado);
}

Explicação

  1. Estrutura de Dados: Definimos uma struct Usuario com dois campos: nome_de_usuario e idade. Derivamos os traits Borsh BorshSerialize e BorshDeserialize para nossa struct, permitindo que a serialização e desserialização sejam feitas de maneira fácil.
  2. Serialização: Criamos uma instância de Usuario e chamamos try_to_vec() para convertê-la em um vetor de bytes.
  3. Desserialização: Usamos try_from_slice() para converter o vetor de bytes de volta em uma instância de Usuario.

Usando Borsh com Enums

Borsh também suporta a serialização de enums, o que pode ser muito útil em situações onde você precisa representar diferentes tipos de estado.

Aqui está um exemplo usando um enum:

#[derive(BorshSerialize, BorshDeserialize, Debug)]
enum Status {
    Ativo,
    Inativo,
    Banido,
}

#[derive(BorshSerialize, BorshDeserialize, Debug)]
struct Conta {
    nome_de_usuario: String,
    status: Status,
}

fn main() {
    let conta = Conta {
        nome_de_usuario: String::from("bob"),
        status: Status::Ativo,
    };

    let conta_serializada = conta.try_to_vec().expect("Falha ao serializar");
    println!("Conta Serializada: {:?}", &conta_serializada);

    let conta_desserializada: Conta = Conta::try_from_slice(&conta_serializada).expect("Falha ao desserializar");
    println!("Conta Desserializada: {:?}", conta_desserializada);
}

Neste exemplo, o enum Status nos permite representar diferentes estados que uma conta pode ter. Os processos de serialização e desserialização permanecem os mesmos que com structs.

Outros Formatos de Serialização

Embora o Borsh seja altamente eficiente para aplicações blockchain, você pode encontrar situações em projetos Rust onde outros formatos de serialização são apropriados, como JSON ou MessagePack.

Usando Serde com JSON

Para serializar em JSON, podemos usar a biblioteca Serde, que fornece uma estrutura poderosa para serializar e desserializar dados.

Primeiro, adicione as dependências necessárias:

[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"

Aqui está como você pode usar Serde com JSON:

use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize, Debug)]
struct Produto {
    nome: String,
    preco: f64,
}

fn main() {
    let produto = Produto {
        nome: String::from("Laptop"),
        preco: 999.99,
    };

    // Serializa a instância de Produto para JSON
    let produto_json = serde_json::to_string(&produto).expect("Falha ao serializar para JSON");
    println!("Produto Serializado para JSON: {}", produto_json);

    // Desserializa o JSON de volta para Produto
    let produto_desserializado: Produto = serde_json::from_str(&produto_json).expect("Falha ao desserializar do JSON");
    println!("Produto Desserializado: {:?}", produto_desserializado);
}

Conclusão

Nesta aula, exploramos técnicas avançadas de serialização utilizando Borsh, um formato binário altamente eficiente utilizado extensivamente no ecossistema Solana. Também analisamos como usar Serde para serialização em JSON. Compreender esses métodos de serialização permitirá que você gerencie dados de forma eficaz em suas aplicações Rust, especialmente ao lidar com tecnologias blockchain. Lembre-se de escolher o formato de serialização que melhor se adapta ao seu caso de uso!

Did you like this article? Rate it from 1 to 5:

Thank you for voting!