std.zstd implementiert Zstandard (RFC 8878) vollständig in Lyx — keine externen Abhängigkeiten. Der Dekompressionspfad unterstützt den vollständigen Zstd-Frame-Aufbau mit FSE-codierten Sequenzen und Huffman-codierten Literalen; der Kompressor arbeitet im Store-Modus (gültige RFC-8878-Frames, keine LZ77-Reduktion).
→ Standard Library · std.zlib · std.brotli · Archiv-Übersicht
Wann Zstd? Zstd ist das Kompressionsformat der modernen Server-Infrastruktur: Linux-Kernel-Module, Docker-Image-Layers, Kafka-Nachrichten, npm-Pakete und .tar.zst-Archive nutzen Zstd. std.zstd ist der richtige Einstiegspunkt wenn Zstd-komprimierte Daten dekomprimiert werden müssen — z.B. Streams aus Kafka, Backup-Dateien oder Systemarchive. Für das Erzeugen komprimierter Inhalte ist der Store-Kompressor ein gültiger Platzhalter; echte Kompression folgt in einer späteren Version.
| Konstante | Wert | Bedeutung |
|---|---|---|
ZSTD_OK | 0 | Kein Fehler |
ZSTD_ERR | -1 | Allgemeiner Fehler (kein Zstd-Frame, korrupter Stream, nicht unterstütztes Feature) |
ZSTD_OVERFLOW | -2 | Ausgabepuffer zu klein |
| Funktion | Rückgabe | Beschreibung |
|---|---|---|
ZstdDecompress(src, srcLen, dst, dstMax) | int64 Bytes oder ZSTD_ERR / ZSTD_OVERFLOW | Dekomprimiert einen Zstd-Frame vollständig |
ZstdCompress(src, srcLen, dst, dstMax) | int64 Bytes oder ZSTD_ERR / ZSTD_OVERFLOW | Erzeugt einen gültigen Zstd-Frame (Store-Modus) |
Beide Funktionen arbeiten ohne interne Allokation des Ausgabepuffers — der Aufrufer stellt dst und dstMax bereit.
Dekomprimiert einen vollständigen Zstd-Frame (RFC 8878). Unterstützt:
Wenn der Frame-Header eine bekannte unkomprimierte Größe enthält und diese dstMax übersteigt, gibt die Funktion sofort ZSTD_OVERFLOW zurück — ohne den gesamten Stream zu durchlaufen.
import std.zstd;
import std.alloc;
import std.io;
fn ZstdBeispiel(komprimiert: int64, kompLen: int64): void {
// Zstd-Frame enthält die unkomprimierte Größe im Header (wenn gesetzt).
// Ohne Vorabwissen großzügig schätzen.
var dstMax: int64 := kompLen * 20;
if dstMax < 65536 then { dstMax := 65536; }
var dst: int64 := alloc(dstMax + 1);
var n: int64 := ZstdDecompress(komprimiert, kompLen, dst, dstMax);
if n == ZSTD_ERR then {
PrintLn("Kein gültiger Zstd-Frame oder nicht unterstütztes Feature"c);
free(dst, dstMax + 1);
return;
}
if n == ZSTD_OVERFLOW then {
PrintLn("Ausgabepuffer zu klein — größeren Puffer verwenden"c);
free(dst, dstMax + 1);
return;
}
poke8(dst + n, 0);
Print("Dekomprimiert: "c); PrintLn(IntToStr(n)c);
free(dst, dstMax + 1);
}
| Einschränkung | Details |
|---|---|
| Treeless-Literalblöcke | Huffman-Typ 3 (Wiederverwendung des Baums aus dem Vorblock) wird nicht unterstützt — gibt ZSTD_ERR zurück |
| Wörterbücher (Dictionary) | Dictionary-ID wird gelesen und übersprungen; der Inhalt wird nicht angewandt |
| Skippable Frames | Magic 0x184D2A5x wird nicht erkannt — gibt ZSTD_ERR zurück |
| Multi-Frame-Streams | Nur ein Frame pro Aufruf; verkettete Frames werden nicht durchlaufen |
In der Praxis erzeugen Standard-Werkzeuge (zstd, tar –zstd, Kafka-Codec) selten Treeless-Blöcke für einzelne unkomprimierte Streams. Multi-Frame-Ausgabe tritt bei sehr großen Dateien auf, die mit –long komprimiert wurden.
Erzeugt einen RFC-8878-konformen Zstd-Frame im Store-Modus: Alle Daten werden in Raw-Blöcken unkomprimiert eingebettet. Der Output ist ein vollständiger, gültiger Zstd-Frame — der Dekompressionspfad aller RFC-konformen Zstd-Implementierungen kann ihn lesen. Er ist nicht kleiner als die Eingabe.
Frame-Aufbau:
28 B5 2F FD)Puffergröße (Worst Case):
benötigt = srcLen + 13 + ceil(srcLen / 131072) × 3
Für Eingaben ≤ 128 KB genügt dstMax = srcLen + 16. Leere Eingabe erzeugt 16 Bytes (Frame-Header + ein leerer letzter Block).
ZstdCompress prüft den Puffer vorab und gibt ZSTD_OVERFLOW zurück bevor Daten geschrieben werden.
import std.zstd;
import std.alloc;
fn ZstdStoreRoundtrip(): void {
var original: pchar := "Hallo Zstd!"c;
var srcLen: int64 := 11;
// Komprimieren (Store-Modus)
var cBuf: int64 := alloc(srcLen + 16);
var cLen: int64 := ZstdCompress(original as int64, srcLen, cBuf, srcLen + 16);
if cLen == ZSTD_ERR then { PrintLn("Fehler"c); return; }
Print("Frame-Größe: "c); PrintLn(IntToStr(cLen)c);
// Dekomprimieren
var dBuf: int64 := alloc(srcLen + 1);
var dLen: int64 := ZstdDecompress(cBuf, cLen, dBuf, srcLen + 1);
poke8(dBuf + dLen, 0);
PrintLn(dBuf as pchar); // → "Hallo Zstd!"
free(cBuf, srcLen + 16);
free(dBuf, srcLen + 1);
}
Zstd-Frames enthalten im Header die unkomprimierte Größe (wenn der Kompressor sie gesetzt hat). Für gängige Werkzeuge trifft das in der Regel zu.
1. Content Size aus Frame-Header lesen (empfohlen, wenn möglich):
Die ersten 13 Bytes eines Zstd-Frames lassen sich manuell lesen:
Bytes 0–3: Magic (28 B5 2F FD)
Byte 4: Frame Header Descriptor (FHD)
bit[7:6] = FCS (Frame Content Size Feld-Größe): 0=1B, 1=2B, 2=4B, 3=8B
bit[5] = SSF (Single Segment Flag)
bit[1:0] = DID (Dictionary ID size): 0=0B, 1=1B, 2=2B, 3=4B
Ab Byte 5: optionaler Window Descriptor (wenn SSF=0), DID-Feld, Content Size
Für die meisten Standard-Streams (zstd-Werkzeug, kein Dictionary) ist FHD 0xE0 → SSF=1, FCS=3 → 8-Byte Content Size direkt ab Byte 5 im LE64-Format.
2. Konservativer Faktor (unbekannte Größe):
var dstMax: int64 := srcLen * 20;
if dstMax < 65536 then { dstMax := 65536; }
var dst: int64 := alloc(dstMax + 1);
var n: int64 := ZstdDecompress(src, srcLen, dst, dstMax);
if n == ZSTD_OVERFLOW then {
// Puffer war zu klein — größer versuchen
}
| Merkmal | std.zstd | std.brotli | std.zlib |
|---|---|---|---|
| Standard | RFC 8878 | RFC 7932 | RFC 1950 / 1951 |
| HTTP-Encoding | zstd (aufkommend) | br (HTTP/2, HTTP/3) | gzip / deflate (universell) |
| Typischer Einsatz | Server-Infrastruktur, Backups, Kafka, Docker | Web-Assets, HTTP-Responses | ZIP-Inhalte, .tar.gz, HTTP |
| Kompressor | Store-Modus (kein LZ77) | Store-Modus (kein LZ77) | vollständig (LZ77 + Huffman) |
| Dekompressionstempo | sehr schnell (typisch schnellster) | vergleichbar | gut |
| Dekompressionspfad | vollständig (RFC 8878, keine Wörterbücher) | vollständig (RFC 7932, kein §8-Static-Dict) | vollständig |
| Einsatz in std.zip | nein | nein | ja (Methode 8) |
| Frame enthält unkomprimierte Größe | ja (meist) | nein | nein |
Für HTTP-Responses (serverseitig) ist std.zlib mit GZIP aktuell die beste Wahl. std.zstd ist bevorzugt für Infrastruktur-nahe Systeme (Kafka-Dekodierung, Backup-Restore, .zst-Dateien).
Beide Funktionen allokieren keinen Ausgabepuffer — der Aufrufer ist vollständig verantwortlich:
| Puffer | Wer allokiert | Wer gibt frei |
|---|---|---|
src (Eingabe) | Aufrufer | Aufrufer |
dst (Ausgabe) | Aufrufer (mindestens dstMax Bytes) | Aufrufer |
| Interne Arbeitspuffer | ZstdDecompress / ZstdCompress | automatisch beim Return |
ZstdDecompress allokiert intern FSE-Tabellen, Huffman-Bäume und Lese-Kontexte — diese werden vollständig freigegeben bevor die Funktion zurückkehrt.
Letzte Aktualisierung: 2026-06-13