2 Punkte von GN⁺ 2025-08-25 | Noch keine Kommentare. | Auf WhatsApp teilen
  • Mit Zig 0.15 wurden neue IO-Schnittstellen (std.Io.Reader, std.Io.Writer) eingeführt
  • Ziel war es, die Komplexität und Performance-Probleme des bisherigen IO-Ansatzes zu verbessern, doch in der tatsächlichen Nutzung entsteht Verwirrung
  • Im Zusammenhang mit der Verwendung von tls.Client und Buffern sorgt die uneinheitliche Übergabe von Parametern für zusätzliche Verwirrung
  • Schon bei der Umsetzung einfacher Anwendungsbeispiele gibt es komplexe Anforderungen wie die Angabe verschiedener Puffergrößen und Optionsfelder
  • Wegen fehlender offizieller Dokumentation, Codebeispiele und Komfortfunktionen ist das System für Einsteiger nicht intuitiv

Die neue IO-Schnittstelle in Zig 0.15 und ihr Hintergrund

  • In Zig 0.15 wurden die neuen IO-Typen std.Io.Reader und std.Io.Writer eingeführt
  • Die frühere IO-Schnittstelle führte durch Performance-Probleme, Typvermischung und den übermäßigen Einsatz von anytype zu Komplexität
  • Hauptziele der neuen IO-Struktur sind eine klare Typtrennung zwischen den Schnittstellen und bessere Performance

Praktische Probleme bei der Nutzung von tls.Client und der IO-Schnittstelle

  • Bei der Aktualisierung einer bestehenden SMTP-Bibliothek entstand Verwirrung bei der Verwendung von tls.Client.init
  • Laut Dokumentation erwartet die init-Funktion Zeiger auf Reader und Writer sowie ein Options-Set als Argumente
  • Zigs net.Stream liefert über die Methoden reader() und writer() jeweils Stream.Reader bzw. Stream.Writer zurück
    • Stream.Reader/Stream.Writer und std.Io.Reader/std.Io.Writer sind jedoch nicht exakt derselbe Typ, daher ist eine Umwandlung nötig
    • Beim Reader muss die Methode interface() aufgerufen werden, beim Writer das Feld &interface verwendet werden, was inkonsistent wirkt

Probleme bei der Konfiguration von Buffern und Optionsfeldern

  • stream.writer und stream.reader erwarten jeweils einen Buffer als Argument
    • Buffer werden in der neuen IO-Schnittstelle als wesentlicher Bestandteil hervorgehoben
  • Beim Aufruf von tls.Client.init sind vier Optionsfelder zwingend erforderlich: ca_bundle, host, write_buffer und read_buffer
    • Die Regeln dafür, welche Werte über die Optionsparameter und welche direkt als Argumente übergeben werden, wirken unklar
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,
  },
)
  • Wenn Buffer-Zeiger in der Praxis nicht korrekt übergeben werden, funktioniert das Programm nicht richtig oder es kommt zu Hängern, Abstürzen und anderen Problemen

Mangelnde Intuitivität bei der Nutzung des Readers

  • Obwohl das Feld reader von tls.Client selbst ein „entschlüsselter Stream“ ist, besitzt std.Io.Reader in der Praxis keine gewöhnliche read-Methode
  • Stattdessen werden nur weniger intuitive Methoden wie peek, takeByteSigned oder readSliceShort angeboten
  • Die der praktischen Nutzung am nächsten kommende API ist der Weg, Daten über die Methode stream in einen Buffer einzulesen
var buf: [1024]u8 = undefined;
var w: std.Io.Writer = .fixed(&buf);
const n = try tls_client.reader.stream(&w, .limited(buf.len));

Gesamtes Codebeispiel und Probleme in der Praxis

  • Selbst für ein vollständiges, lauffähiges Minimalbeispiel muss man viele Dinge beachten: Optionen, Buffergrößen, Typumwandlungen und mehr
  • Durch fehlende Tests, Dokumentation und Beispiele steigen Lernaufwand und Einstiegshürde
  • Ohne ein gutes Verständnis der Konsistenz innerhalb der Zig-Sprache oder des zugrunde liegenden Designs gibt es viele Stellen, die seltsam wirken
  • Auch innerhalb der Standardbibliothek wird dieser Ansatz noch nicht häufig genutzt, sodass es an praxistauglichen Referenzen fehlt

Erfahrungen und Fazit

  • Durch Umbenennungen wie std.fmt.printInt und Änderungen am API-Design ist schon der Migrationsprozess selbst nicht einfach
  • Die wiederkehrenden Schwierigkeiten mit reader.interface(), &writer.interface, der Übergabe von Optionen und der Notwendigkeit mehrerer Buffer treten immer wieder auf
  • Wenn man mit Netzwerk- und Sicherheitsprotokollen wie TLS nicht vertraut ist, wirken die Anforderungen noch schwerer nachvollziehbar
  • Insgesamt gibt es gegenüber früher weiterhin deutliche Defizite bei Klarheit, Dokumentation und Bedienkomfort

Noch keine Kommentare.

Noch keine Kommentare.