- Na versão 0.15 do Zig, foi introduzida a nova interface de IO (
std.Io.Reader, std.Io.Writer)
- O objetivo era melhorar a complexidade e os problemas de performance da forma anterior de IO, mas isso acabou gerando confusão no uso real
- No uso de
tls.Client e buffers, a forma inconsistente de passar parâmetros aumenta ainda mais a confusão
- Mesmo ao implementar exemplos básicos de uso, há exigências complexas como definir vários tamanhos de buffer e campos de opções
- Pela falta de documentação oficial, exemplos de código e funções utilitárias, não é algo intuitivo para iniciantes
A nova interface de IO introduzida no Zig 0.15 e seu contexto
- Na versão 0.15 do Zig, foram introduzidos os novos tipos de IO
std.Io.Reader e std.Io.Writer
- A interface de IO anterior gerava complexidade por causa de problemas de performance, mistura de tipos e uso excessivo de
anytype
- Na nova estrutura de IO, os principais objetivos são separar claramente os tipos entre interfaces e melhorar o desempenho
Problemas práticos no uso de tls.Client e da interface de IO
- Durante a atualização de uma biblioteca SMTP existente, surgiu confusão no uso da função
tls.Client.init
- Na documentação, a função
init é descrita como recebendo ponteiros para Reader e Writer, além de um conjunto de opções como argumentos
- Em Zig,
net.Stream retorna Stream.Reader/Stream.Writer por meio dos métodos reader() e writer()
- Porém,
Stream.Reader/Stream.Writer e std.Io.Reader/std.Io.Writer não são exatamente o mesmo tipo, então é preciso converter
- Para
Reader, é necessário chamar o método interface(), enquanto para Writer é preciso usar o campo &interface, o que mostra falta de consistência
Problemas na configuração de buffers e campos de opções
stream.writer e stream.reader recebem, cada um, um buffer como argumento
- O buffer é enfatizado como um elemento essencial da nova interface de IO
- Ao chamar
tls.Client.init, são obrigatórios quatro campos de opção: ca_bundle, host, write_buffer e read_buffer
- A regra de separar o que vai nos parâmetros de opção e o que vai diretamente nos argumentos parece pouco clara
var tls_client = try std.crypto.tls.Client.init(
reader.interface(),
&writer.interface,
.{
.ca = .{.bundle = bundle},
.host = .{ .explicit = "www.openmymind.net" } ,
.read_buffer = &read_buf2,
.write_buffer = &write_buf2,
},
)
- Na prática, se os ponteiros de buffer não forem passados corretamente, o programa pode não funcionar direito, travar ou até falhar de várias formas
Problemas de intuitividade ao usar Reader
- Embora o campo
reader de tls.Client seja em si um "stream descriptografado", std.Io.Reader não possui um método read comum
- Em vez disso, ele oferece apenas métodos menos intuitivos como
peek, takeByteSigned e readSliceShort
- A API mais próxima do uso esperado parece ser a leitura de dados para um buffer por meio do método
stream
var buf: [1024]u8 = undefined;
var w: std.Io.Writer = .fixed(&buf);
const n = try tls_client.reader.stream(&w, .limited(buf.len));
Exemplo completo de código e problemas no uso real
- Mesmo para montar um exemplo mínimo totalmente funcional, há muitos detalhes para cuidar, como opções, tamanho de buffers e conversões de tipo
- A falta de testes, documentação e exemplos aumenta a dificuldade de aprendizado e a barreira de entrada
- Para quem não entende bem a consistência interna da linguagem Zig ou o design subjacente, há muitos pontos que parecem estranhos
- Mesmo dentro da biblioteca padrão, esse padrão ainda não é muito usado, então faltam materiais práticos de referência
Experiência e conclusão
- Mudanças como a renomeação de
std.fmt.printInt e alterações no design da API fazem com que o processo de migração em si não seja simples
- Foram relatadas dificuldades repetidas com
reader.interface(), a forma &writer.interface, o modo de passar opções e a necessidade de vários buffers
- Para quem não está acostumado com protocolos de rede e segurança como TLS, entender exatamente o que é exigido fica ainda mais difícil
- No geral, ainda existem muitas limitações em termos de clareza, documentação e conveniência em comparação com a abordagem anterior
Ainda não há comentários.