Files

LZ4

LZ4 compression of files and text in the standard .lz4 frame format: the fastest to pack and unpack, for caches, logs and data passed between services.

Version 1.0.0 · 5 functions · 2 crates

#compression#files#logs#cache

Functions

What use lz4.qwer gives a program, with the types Quillo sees. To take only some, or under other names: use lz4_file, unlz4_file from lz4 (Quillo 0.6).

lz4_file(from: str, to: str) → intor an error

Compresses the file at from into to (often from + ".lz4"), as an LZ4 frame the lz4 command reads: the size written, in bytes.

unlz4_file(from: str, to: str) → intor an error

Unpacks the .lz4 file at from (one frame or several, as lz4 writes them) into to: the size written, in bytes. Stops with an error past 16 GB.

lz4_text(text: str) → stror an error

text compressed as an LZ4 frame, as base64 (a value cannot hold bytes).

unlz4_text(b64: str) → stror an error

Base64 of an LZ4 frame, back to the text; up to 64 MB of it.

lz4_is_frame(path: str) → boolor an error

Whether the file at path starts as an LZ4 frame does (its magic number 04 22 4D 18).

Get it

$ quillo install lz4               # lz4.qwer into this folder$ quillo install lz4 --example     # and its example, lz4.qwe

Or with curl:

$ curl -O https://quillolang.org/plugins/files/lz4.qwer$ curl -O https://quillolang.org/plugins/files/lz4.qwe

Then, in your program, all of it or only what you call:

main.qwe
use lz4.qweruse lz4_file, unlz4_file from lz4      // Quillo 0.6: only these

It uses these crates, which cargo fetches the first time the plugin is built:

[dependencies]
lz4_flex = "0.14"base64 = "0.22"

Example

lz4.qwe
// An access log packed with LZ4 before it goes to the archive, and text both ways.////   quillo run lz4.qwe      then open http://localhost:8080/packuse "lz4.qwer"route GET /pack {    let lines = for i in range(5000) => `2026-10-29T10:00:${i % 60} GET /menu 200 ${i % 7}ms`    write_file("data/lz4-access.log", join(lines, "\n"))    let size = lz4_file("data/lz4-access.log", "data/lz4-access.log.lz4")?    let packed = lz4_text("hello, hello, hello, hello")?    {        log_bytes: len(read_file("data/lz4-access.log")),        lz4_bytes: size,        is_lz4: lz4_is_frame("data/lz4-access.log.lz4")?,        log_is_lz4: lz4_is_frame("data/lz4-access.log")?,        unpacked_bytes: unlz4_file("data/lz4-access.log.lz4", "data/lz4-access.copy.log")?,        back: unlz4_text(packed)?,    }}route GET /broken = { error: unlz4_text("aGVsbG8=").error }
$ quillo run lz4.qwe$ curl 'localhost:8080/pack'

Source

lz4.qwer
//! LZ4 compression of files and text, in the standard frame format (.lz4): the fastest to pack and unpack, for caches, logs and data passed between services.//! version: 1.0.0//!//! [dependencies]//! lz4_flex = "0.14"//! base64 = "0.22"use base64::engine::general_purpose::STANDARD;use base64::Engine;use lz4_flex::frame::{FrameDecoder, FrameEncoder};use std::io::{Read, Write};const MAX_FILE: u64 = 16 * 1024 * 1024 * 1024;const MAX_TEXT: u64 = 64 * 1024 * 1024;fn create(to: &str) -> Result<std::fs::File, String> {    if let Some(dir) = std::path::Path::new(to).parent().filter(|d| !d.as_os_str().is_empty()) {        std::fs::create_dir_all(dir).map_err(|e| format!("{}: {}", dir.display(), e))?;    }    std::fs::File::create(to).map_err(|e| format!("{}: {}", to, e))}/// Compresses the file at `from` into `to` (often `from` + ".lz4"), as an LZ4 frame the `lz4` command reads: the size written, in bytes.pub fn lz4_file(from: &str, to: &str) -> Result<i64, String> {    let mut input = std::fs::File::open(from).map_err(|e| format!("{}: {}", from, e))?;    let mut enc = FrameEncoder::new(std::io::BufWriter::new(create(to)?));    std::io::copy(&mut input, &mut enc).map_err(|e| e.to_string())?;    enc.finish().map_err(|e| e.to_string())?.flush().map_err(|e| e.to_string())?;    Ok(std::fs::metadata(to).map_err(|e| e.to_string())?.len() as i64)}/// Unpacks the .lz4 file at `from` (one frame or several, as `lz4` writes them) into `to`: the size written, in bytes. Stops with an error past 16 GB.pub fn unlz4_file(from: &str, to: &str) -> Result<i64, String> {    let input = std::fs::File::open(from).map_err(|e| format!("{}: {}", from, e))?;    let mut out = std::io::BufWriter::new(create(to)?);    let n = std::io::copy(&mut FrameDecoder::new(std::io::BufReader::new(input)).take(MAX_FILE + 1), &mut out).map_err(|e| format!("{}: {}", from, e))?;    if n > MAX_FILE {        return Err(format!("{}: more than 16 GB unpacked", from));    }    out.flush().map_err(|e| e.to_string())?;    Ok(n as i64)}/// `text` compressed as an LZ4 frame, as base64 (a value cannot hold bytes).pub fn lz4_text(text: &str) -> Result<String, String> {    let mut enc = FrameEncoder::new(Vec::new());    enc.write_all(text.as_bytes()).map_err(|e| e.to_string())?;    Ok(STANDARD.encode(enc.finish().map_err(|e| e.to_string())?))}/// Base64 of an LZ4 frame, back to the text; up to 64 MB of it.pub fn unlz4_text(b64: &str) -> Result<String, String> {    let bytes = STANDARD.decode(b64.trim()).map_err(|e| e.to_string())?;    let mut out = Vec::new();    FrameDecoder::new(&bytes[..]).take(MAX_TEXT + 1).read_to_end(&mut out).map_err(|e| e.to_string())?;    if out.len() as u64 > MAX_TEXT {        return Err("more than 64 MB of text".into());    }    String::from_utf8(out).map_err(|_| "the data is not UTF-8 text".to_string())}/// Whether the file at `path` starts as an LZ4 frame does (its magic number 04 22 4D 18).pub fn lz4_is_frame(path: &str) -> Result<bool, String> {    let mut f = std::fs::File::open(path).map_err(|e| format!("{}: {}", path, e))?;    let mut magic = [0u8; 4];    Ok(f.read_exact(&mut magic).is_ok() && magic == [0x04, 0x22, 0x4d, 0x18])}
Thread
67Useful? Like it, or add to its thread below.

Thread 0 posts

On LZ4: questions, tips, corrections, and code that uses it.

No posts yet. The first one opens the thread.