Files

xz

xz (LZMA2) compression of files and text, and old .lzma files read: the smallest archives, for backups and downloads.

Version 1.0.0 · 4 functions · 2 crates

#compression#files#backups

Functions

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

xz_file(from: str, to: str, level: int) → intor an error

Compresses the file at from into to (often from + ".xz"), at level 0 (fastest) to 9 (smallest; 6 is xz's usual); the size written, in bytes.

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

Unpacks the .xz (or .lzma) file at from into to: the size written, in bytes. Stops with an error past 16 GB.

xz_text(text: str, level: int) → stror an error

text compressed with xz, as base64 (a value cannot hold bytes), at level 0 to 9.

unxz_text(b64: str) → stror an error

Base64 of xz-compressed text, back to the text; up to 64 MB of it.

Get it

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

Or with curl:

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

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

main.qwe
use xz.qweruse xz_file, unxz_file from xz      // Quillo 0.6: only these

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

[dependencies]
xz2 = { version = "0.1", features = ["static"] }base64 = "0.22"

Example

xz.qwe
// A database dump compressed with xz for a backup, and text both ways.////   quillo run xz.qwe      then open http://localhost:8080/packuse "xz.qwer"route GET /pack {    let rows = for i in range(3000) => `insert into orders (id, customer, total) values (${i}, 'customer ${i % 50}', ${i % 90}.50);`    write_file("data/dump.sql", join(rows, "\n"))    let size = xz_file("data/dump.sql", "data/dump.sql.xz", 9)?    let packed = xz_text("hello, hello, hello", 6)?    {        sql_bytes: len(read_file("data/dump.sql")),        xz_bytes: size,        unpacked_bytes: unxz_file("data/dump.sql.xz", "data/dump.copy.sql")?,        back: unxz_text(packed)?,    }}
$ quillo run xz.qwe$ curl 'localhost:8080/pack'

Source

xz.qwer
//! xz (LZMA2) compression of files and text, and old .lzma files read: the smallest archives, for backups and downloads.//! version: 1.0.0//!//! [dependencies]//! xz2 = { version = "0.1", features = ["static"] }//! base64 = "0.22"use base64::engine::general_purpose::STANDARD;use base64::Engine;use std::io::{Read, Write};use xz2::read::XzDecoder;use xz2::stream::Stream;use xz2::write::XzEncoder;const MAX_FILE: u64 = 16 * 1024 * 1024 * 1024;const MAX_TEXT: u64 = 64 * 1024 * 1024;fn preset(l: i64) -> u32 {    l.clamp(0, 9) as u32}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))}// Reads .xz and legacy .lzma alike, with a memory limit of 256 MB for the decoder.fn decoder<R: Read>(r: R) -> Result<XzDecoder<R>, String> {    let s = Stream::new_auto_decoder(256 * 1024 * 1024, xz2::stream::CONCATENATED).map_err(|e| e.to_string())?;    Ok(XzDecoder::new_stream(r, s))}/// Compresses the file at `from` into `to` (often `from` + ".xz"), at `level` 0 (fastest) to 9 (smallest; 6 is xz's usual); the size written, in bytes.pub fn xz_file(from: &str, to: &str, level: i64) -> Result<i64, String> {    let mut input = std::fs::File::open(from).map_err(|e| format!("{}: {}", from, e))?;    let mut enc = XzEncoder::new(create(to)?, preset(level));    std::io::copy(&mut input, &mut enc).map_err(|e| e.to_string())?;    enc.finish().map_err(|e| e.to_string())?;    Ok(std::fs::metadata(to).map_err(|e| e.to_string())?.len() as i64)}/// Unpacks the .xz (or .lzma) file at `from` into `to`: the size written, in bytes. Stops with an error past 16 GB.pub fn unxz_file(from: &str, to: &str) -> Result<i64, String> {    let input = std::fs::File::open(from).map_err(|e| format!("{}: {}", from, e))?;    let mut out = create(to)?;    let n = std::io::copy(&mut decoder(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));    }    Ok(n as i64)}/// `text` compressed with xz, as base64 (a value cannot hold bytes), at `level` 0 to 9.pub fn xz_text(text: &str, level: i64) -> Result<String, String> {    let mut enc = XzEncoder::new(Vec::new(), preset(level));    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 xz-compressed text, back to the text; up to 64 MB of it.pub fn unxz_text(b64: &str) -> Result<String, String> {    let bytes = STANDARD.decode(b64.trim()).map_err(|e| e.to_string())?;    let mut out = Vec::new();    decoder(&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())}
Thread
68Useful? Like it, or add to its thread below.

Thread 0 posts

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

No posts yet. The first one opens the thread.