#![cfg(all(feature = "compression", feature = "decompression"))]
#[rustfmt::skip]
mod readme_1 {
use mopenzl::{Compressor, Decompressor, EncoderConfig, Level};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let input = "openzl ".repeat(1000);
let config = EncoderConfig::default().with_level(Level::try_from(6)?);
let mut encoder = Compressor::new(config)?;
let frame = encoder.compress(input.as_bytes())?;
println!("{} -> {} bytes", input.len(), frame.len());
let restored = Decompressor::default().decompress(&frame)?;
assert_eq!(restored, input.as_bytes());
Ok(())
}
#[test]
fn runs() {
main().unwrap();
}
}
#[rustfmt::skip]
mod readme_2 {
use mopenzl::{Compressor, Decompressor, EncoderConfig, Level};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut encoder = Compressor::new(EncoderConfig::default().with_level(Level::try_from(3)?))?;
let mut decoder = Decompressor::default();
let mut frame = Vec::new();
for input in [b"first payload".as_slice(), b"second payload".as_slice()] {
frame.clear(); let written = encoder.compress_into(input, &mut frame)?;
assert_eq!(written, 0..frame.len());
assert_eq!(decoder.decompress(&frame)?, input);
}
Ok(())
}
#[test]
fn runs() {
main().unwrap();
}
}
#[cfg(not(feature = "no_std"))]
#[rustfmt::skip]
mod readme_3 {
use mopenzl::{ChunkSize, Chunking, Compressor, Decompressor, EncoderConfig, InputSize};
use std::io::{Read, Write};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let payload = b"streamed payload ".repeat(10_000);
let config = EncoderConfig::default().with_chunking(Chunking::Fixed(ChunkSize::MIN));
let mut encoder = Compressor::new(config)?;
let mut writer = encoder.writer(Vec::new(), InputSize::Exact(payload.len() as u64).into());
writer.write_all(&payload)?;
let frame = writer
.finish()
.map_err(mopenzl::io::FinishError::into_error)?;
let mut reader = encoder.reader(&payload[..], InputSize::Exact(payload.len() as u64).into());
let mut from_reader = Vec::new();
reader.read_to_end(&mut from_reader)?;
assert_eq!(from_reader, frame);
let mut decoder = Decompressor::default();
let mut restored = Vec::new();
decoder.reader(&frame[..]).read_to_end(&mut restored)?;
assert_eq!(restored, payload);
let mut writer = decoder.writer(Vec::new());
writer.write_all(&frame)?;
let restored = writer
.finish()
.map_err(mopenzl::io::FinishError::into_error)?;
assert_eq!(restored, payload);
Ok(())
}
#[test]
fn runs() {
main().unwrap();
}
}
#[cfg(feature = "all-codecs")]
#[rustfmt::skip]
mod readme_4 {
use mopenzl::graph::{CompressorGraph, StandardGraph};
use mopenzl::input::{Input, Numbers};
use mopenzl::{Compressor, DataType, Decompressor, EncoderConfig};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let values: Vec<u8> = (0..10_000u32)
.flat_map(|i| (1_700_000_000 + i * 3).to_le_bytes())
.collect();
let numbers = Numbers::try_from((&values[..], 4))?;
let mut compressor = Compressor::builder(EncoderConfig::default())
.with_graph(CompressorGraph::standard(StandardGraph::SelectNumeric))
.build()?;
let frame = compressor.compress_inputs(&[Input::from(numbers)])?;
println!("{} -> {} bytes", values.len(), frame.len());
let outputs = Decompressor::default().decompress_typed(&frame)?;
assert_eq!(outputs[0].data_type(), DataType::Numeric);
assert_eq!(outputs[0].width(), 4);
assert_eq!(outputs[0].content(), values);
Ok(())
}
#[test]
fn runs() {
main().unwrap();
}
}
#[cfg(feature = "all-codecs")]
#[rustfmt::skip]
mod readme_5 {
use mopenzl::graph::{GraphBuilder, StandardGraph, StandardNode};
use mopenzl::{Compressor, Decompressor, EncoderConfig};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut builder = GraphBuilder::new();
let start = builder.pipeline(
&[
StandardNode::ConvertSerialToNumLe32.into(),
StandardNode::DeltaInt.into(),
],
StandardGraph::FieldLz,
)?;
let graph = builder.build(start)?;
let input: Vec<u8> = (0..4096u32).flat_map(|i| (i * 7).to_le_bytes()).collect();
let mut compressor = Compressor::builder(EncoderConfig::default())
.with_graph(graph)
.build()?;
let frame = compressor.compress(&input)?;
assert_eq!(Decompressor::default().decompress(&frame)?, input);
Ok(())
}
#[test]
fn runs() {
main().unwrap();
}
}
#[cfg(feature = "zstd")]
#[rustfmt::skip]
mod readme_6 {
use mopenzl::dict::{BundleStore, Dict, DictBundle};
use mopenzl::graph::{GraphBuilder, NodeParams, StandardGraph, StandardNode};
use mopenzl::{Compressor, Decompressor, EncoderConfig};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let record = |i: usize| {
let users = ["alice", "bob", "carol", "dave", "erin"];
let cities = ["Oslo", "Lima", "Kyiv", "Pune"];
format!(
r#"{{"user":"{}","city":"{}","plan":"{}","seen":{},"flags":["beta","email"],"locale":"en-GB"}}"#,
users[i % 5],
cities[i % 4],
if i.is_multiple_of(2) { "pro" } else { "free" },
i * 7
)
};
let history = (0..40).map(record).collect::<Vec<_>>().join("\n");
let dict = Dict::zstd(history.as_bytes(), 3)?;
let bundle = DictBundle::try_from(vec![dict.clone()])?;
let mut builder = GraphBuilder::new();
let node = builder.parameterize_node_with(
StandardNode::Zstd,
NodeParams::default().with_dictionary(dict.id()),
)?;
builder.load_dictionaries(&bundle)?;
let start = builder.static_graph(node, &[StandardGraph::Store.into()])?;
let graph = builder.build(start)?;
let mut compressor = Compressor::builder(EncoderConfig::default())
.with_graph(graph)
.build()?;
let payload = record(1234).into_bytes();
let frame = compressor.compress(&payload)?;
let plain = Compressor::default().compress(&payload)?;
println!(
"{} bytes -> {} with the dictionary, {} without",
payload.len(),
frame.len(),
plain.len()
);
let mut store = BundleStore::default();
store.insert(&bundle)?;
let mut decoder = Decompressor::builder(Default::default())
.with_dictionaries(store)
.build();
assert_eq!(decoder.decompress(&frame)?, payload);
Ok(())
}
#[test]
fn runs() {
main().unwrap();
}
}
#[rustfmt::skip]
mod docs_readme_1 {
use mopenzl::{DecodeError, DecodeLimits, DecoderConfig, Decompressor, FrameMode};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let limits = DecodeLimits::default()
.with_max_input_bytes(Some(1 << 20))
.with_max_output_bytes(Some(8 << 20));
let config = DecoderConfig::default()
.with_frame_mode(FrameMode::Concatenated)
.with_limits(limits);
let mut decoder = Decompressor::new(config);
let mut encoder = mopenzl::Compressor::default();
let mut frames = encoder.compress(b"first frame, ")?;
frames.extend(encoder.compress(b"second frame")?);
assert_eq!(decoder.decompress(&frames)?, b"first frame, second frame");
assert!(decoder.decompress(b"not a frame").is_err());
let big = encoder.compress(&vec![7u8; 16 << 20])?;
assert!(matches!(
decoder.decompress(&big),
Err(DecodeError::OutputLimitExceeded { .. })
));
let _ = DecoderConfig::from(limits);
Ok(())
}
#[test]
fn runs() {
main().unwrap();
}
}
#[rustfmt::skip]
mod docs_readme_2 {
use mopenzl::graph::Comment;
use mopenzl::{Compressor, DataType, Decompressor};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut encoder = Compressor::default();
encoder.set_comment(Some(Comment::try_from(&b"nightly export"[..])?))?;
let frame = encoder.compress(b"payload")?;
let info = Decompressor::default().frame_info(&frame)?;
assert_eq!(info.comment(), Some(&b"nightly export"[..]));
assert_eq!(info.outputs()[0].data_type(), DataType::Serial);
assert_eq!(info.decompressed_size(), 7);
assert!(info.bundle_id().is_none());
Ok(())
}
#[test]
fn runs() {
main().unwrap();
}
}
#[cfg(feature = "zstd")]
#[rustfmt::skip]
mod docs_readme_3 {
use mopenzl::graph::Comment;
use mopenzl::{Compressor, Decompressor, EncoderConfig, FormatVersion, Level};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let config = EncoderConfig::default()
.with_level(Level::try_from(19)?)
.with_format_version(FormatVersion::try_from(24)?)
.with_content_checksum(false)
.with_min_stream_size(32)
.with_store_on_expansion(true);
let mut encoder = Compressor::new(config)?;
encoder.set_comment(Some(Comment::try_from(&b"produced by the docs"[..])?))?;
let frame = encoder.compress(&b"configured payload ".repeat(100))?;
assert_eq!(
Decompressor::default().decompress(&frame)?,
b"configured payload ".repeat(100)
);
let mut old = Compressor::new(config.with_format_version(FormatVersion::try_from(21)?))?;
assert!(
old.set_comment(Some(Comment::try_from(&b"too old"[..])?))
.is_err()
);
Ok(())
}
#[test]
fn runs() {
main().unwrap();
}
}
#[rustfmt::skip]
mod docs_readme_4 {
use mopenzl::{Compressor, Decompressor, EncodeError};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let input = b"data to compress";
let mut encoder = Compressor::default();
let bound = Compressor::max_compressed_size(input.len())?;
let mut output = vec![0; bound];
let written = encoder.compress_to_slice(input, &mut output)?;
output.truncate(written);
assert_eq!(output, encoder.compress(input)?);
let mut cramped = [0u8; 4];
assert!(matches!(
encoder.compress_to_slice(input, &mut cramped),
Err(EncodeError::OutputTooSmall { provided: 4 })
));
let mut restored = [0u8; 64];
let n = Decompressor::default().decompress_to_slice(&output, &mut restored)?;
assert_eq!(&restored[..n], input);
Ok(())
}
#[test]
fn runs() {
main().unwrap();
}
}
#[rustfmt::skip]
mod docs_readme_5 {
use mopenzl::{Compressor, Decompressor};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let input = b"uninitialized destination ".repeat(50);
let mut encoder = Compressor::default();
let mut frame: Vec<u8> = Vec::with_capacity(Compressor::max_compressed_size(input.len())?);
let written = encoder.compress_to_uninit(&input, frame.spare_capacity_mut())?;
unsafe { frame.set_len(written) };
assert_eq!(frame, encoder.compress(&input)?);
let mut restored: Vec<u8> = Vec::with_capacity(input.len());
let n = Decompressor::default().decompress_to_uninit(&frame, restored.spare_capacity_mut())?;
unsafe { restored.set_len(n) };
assert_eq!(restored, input);
Ok(())
}
#[test]
fn runs() {
main().unwrap();
}
}
#[rustfmt::skip]
mod docs_readme_6 {
use mopenzl::{Compressor, EncoderConfig, RetentionPolicy};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut encoder = Compressor::builder(EncoderConfig::default())
.with_retention(RetentionPolicy::Bounded { max_bytes: 1 << 20 })
.build()?;
encoder.compress(&b"warm the tables up ".repeat(1000))?;
println!("retained {} bytes", encoder.retained_bytes());
encoder.trim(RetentionPolicy::ReleaseAll);
assert_eq!(encoder.retained_bytes(), 0);
Ok(())
}
#[test]
fn runs() {
main().unwrap();
}
}
#[rustfmt::skip]
mod docs_readme_7 {
use mopenzl::{
ChunkSize, Chunking, Compressor, DecodeOperation, DecoderStatus, Decompressor, EncoderConfig,
EncoderStatus, InputSize, Operation,
};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let payload = b"incremental payload ".repeat(5_000);
let config = EncoderConfig::default().with_chunking(Chunking::Fixed(ChunkSize::MIN));
let mut encoder = Compressor::new(config)?;
let expected = encoder.compress(&payload)?;
let mut session = encoder.start(InputSize::Exact(payload.len() as u64).into());
let mut frame = Vec::new();
let mut buffer = [0u8; 1024];
let mut rest = &payload[..];
loop {
let take = rest.len().min(4096);
let operation = if take == rest.len() {
Operation::End
} else {
Operation::Continue
};
let progress = session.process(&rest[..take], &mut buffer, operation)?;
frame.extend_from_slice(&buffer[..progress.produced]);
rest = &rest[progress.consumed..];
if progress.status == EncoderStatus::Finished {
break;
}
}
assert_eq!(frame, expected);
let mut decoder = Decompressor::default();
let mut session = decoder.start();
let mut restored = Vec::new();
let mut position = 0;
loop {
let end = (position + 1000).min(frame.len());
let operation = if end == frame.len() {
DecodeOperation::Finish
} else {
DecodeOperation::Process
};
let progress = session.process(&frame[position..end], &mut buffer, operation)?;
restored.extend_from_slice(&buffer[..progress.produced]);
position += progress.consumed;
if progress.status == DecoderStatus::Finished {
break;
}
}
assert_eq!(restored, payload);
Ok(())
}
#[test]
fn runs() {
main().unwrap();
}
}
#[cfg(feature = "all-codecs")]
#[rustfmt::skip]
mod docs_codecs_1 {
use mopenzl::graph::params::{divide_by, zstd};
use mopenzl::graph::{GraphBuilder, LocalParams, StandardGraph, StandardNode};
use mopenzl::input::{Input, Numbers};
use mopenzl::{Compressor, Decompressor, EncoderConfig};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut builder = GraphBuilder::new();
let divide = builder.parameterize_node(
StandardNode::DivideBy,
LocalParams::default().with_bytes(divide_by::DIVIDE_BY, 1000u64.to_le_bytes().to_vec()),
)?;
let zstd19 = builder.parameterize_node(
StandardNode::Zstd,
LocalParams::default().with_int(zstd::COMPRESSION_LEVEL, 19),
)?;
let to_bytes = builder.static_graph(zstd19, &[StandardGraph::Store.into()])?;
let start = builder.pipeline(
&[divide, StandardNode::ConvertNumToSerialLe.into()],
to_bytes,
)?;
let graph = builder.build(start)?;
let values: Vec<u8> = (0..4096u32)
.flat_map(|i| (i * 1000).to_le_bytes())
.collect();
let numbers = Numbers::try_from((&values[..], 4))?;
let mut compressor = Compressor::builder(EncoderConfig::default())
.with_graph(graph)
.build()?;
let frame = compressor.compress_inputs(&[Input::from(numbers)])?;
let outputs = Decompressor::default().decompress_typed(&frame)?;
assert_eq!(outputs[0].content(), values);
Ok(())
}
#[test]
fn runs() {
main().unwrap();
}
}
#[cfg(feature = "zstd")]
#[rustfmt::skip]
mod docs_dictionaries_1 {
use mopenzl::dict::{Dict, DictBundle, DictCodec};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let users = Dict::zstd(&br#"{"user":"alice","plan":"pro"}"#.repeat(8), 3)?;
let events = Dict::new(DictCodec::ZSTD, b"raw dictionary content".to_vec())?;
let bundle = DictBundle::try_from(vec![users.clone(), events.clone()])?;
let reversed = DictBundle::try_from(vec![events, users.clone()])?;
assert_ne!(bundle.id(), reversed.id());
let fat = Vec::from(&bundle);
assert_eq!(DictBundle::try_from(&fat[..])?, bundle);
assert_eq!(bundle.dicts()[0].id(), users.id());
println!("bundle {}", bundle.id()); Ok(())
}
#[test]
fn runs() {
main().unwrap();
}
}
#[cfg(feature = "zstd")]
#[rustfmt::skip]
mod docs_dictionaries_2 {
use mopenzl::dict::{BundleStore, Dict, DictBundle};
use mopenzl::graph::{GraphBuilder, NodeParams, StandardGraph, StandardNode};
use mopenzl::{Compressor, Decompressor, EncoderConfig};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let record = |i: usize| {
let users = ["alice", "bob", "carol", "dave", "erin"];
let cities = ["Oslo", "Lima", "Kyiv", "Pune"];
format!(
r#"{{"user":"{}","city":"{}","plan":"{}","seen":{},"flags":["beta","email"],"locale":"en-GB"}}"#,
users[i % 5],
cities[i % 4],
if i.is_multiple_of(2) { "pro" } else { "free" },
i * 7
)
};
let history = (0..40).map(record).collect::<Vec<_>>().join("\n");
let dict = Dict::zstd(history.as_bytes(), 3)?;
let bundle = DictBundle::try_from(vec![dict.clone()])?;
let mut builder = GraphBuilder::new();
let node = builder.parameterize_node_with(
StandardNode::Zstd,
NodeParams::default().with_dictionary(dict.id()),
)?;
builder.load_dictionaries(&bundle)?;
let start = builder.static_graph(node, &[StandardGraph::Store.into()])?;
let graph = builder.build(start)?;
let record = record(1234).into_bytes();
let mut with_dict = Compressor::builder(EncoderConfig::default())
.with_graph(graph)
.build()?;
let small = with_dict.compress(&record)?;
let plain = Compressor::default().compress(&record)?;
println!(
"with dictionary {} bytes, without {}",
small.len(),
plain.len()
);
let mut store = BundleStore::default();
store.insert(&bundle)?;
let mut decoder = Decompressor::builder(Default::default())
.with_dictionaries(store)
.build();
assert_eq!(decoder.decompress(&small)?, record);
Ok(())
}
#[test]
fn runs() {
main().unwrap();
}
}
#[cfg(feature = "zstd")]
#[rustfmt::skip]
mod docs_dictionaries_3 {
use mopenzl::dict::{BundleStore, Dict, DictBundle};
use mopenzl::graph::{GraphBuilder, GraphError, NodeParams, StandardGraph, StandardNode};
use mopenzl::{Compressor, DecodeError, Decompressor, EncoderConfig};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let dict = Dict::zstd(&b"some shared history ".repeat(10), 3)?;
let bundle = DictBundle::try_from(vec![dict.clone()])?;
let mut early = GraphBuilder::new();
assert!(matches!(
early.load_dictionaries(&bundle),
Err(GraphError::Dictionary(_))
));
let mut unloaded = GraphBuilder::new();
let node = unloaded.parameterize_node_with(
StandardNode::Zstd,
NodeParams::default().with_dictionary(dict.id()),
)?;
let start = unloaded.static_graph(node, &[StandardGraph::Store.into()])?;
assert!(matches!(
unloaded.build(start),
Err(GraphError::DictionaryNotFound(_))
));
let mut builder = GraphBuilder::new();
let node = builder.parameterize_node_with(
StandardNode::Zstd,
NodeParams::default().with_dictionary(dict.id()),
)?;
builder.load_dictionaries(&bundle)?;
assert_eq!(
builder.load_dictionaries(&bundle),
Err(GraphError::BundleAlreadyLoaded)
);
let start = builder.static_graph(node, &[StandardGraph::Store.into()])?;
let graph = builder.build(start)?;
let frame = Compressor::builder(EncoderConfig::default())
.with_graph(graph)
.build()?
.compress(b"some shared history, again")?;
assert!(matches!(
Decompressor::default().decompress(&frame),
Err(DecodeError::MissingBundle { bundle: id }) if id == bundle.id()
));
let mut store = BundleStore::default();
store.insert(&bundle)?;
let mut decoder = Decompressor::builder(Default::default())
.with_dictionaries(store)
.build();
assert_eq!(decoder.decompress(&frame)?, b"some shared history, again");
Ok(())
}
#[test]
fn runs() {
main().unwrap();
}
}
#[cfg(feature = "all-codecs")]
#[rustfmt::skip]
mod docs_graphs_1 {
use mopenzl::graph::{CompressorGraph, StandardGraph};
use mopenzl::input::{Input, Records, Strings};
use mopenzl::{Compressor, DataType, Decompressor, EncoderConfig};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let text = b"alpha beta gamma delta alpha beta gamma delta ".repeat(20);
let lens: Vec<u32> = vec![46; 20];
let records: Vec<u8> = (0..4000u32)
.flat_map(|i| [(i % 7) as u8, 1, 2, 3])
.collect();
let inputs = [
Input::from(&text[..]),
Input::from(Records::try_from((&records[..], 4))?),
Input::from(Strings::try_from((&text[..], &lens[..]))?),
];
let mut compressor = Compressor::builder(EncoderConfig::default())
.with_graph(CompressorGraph::standard(StandardGraph::CompressGeneric))
.build()?;
let frame = compressor.compress_inputs(&inputs)?;
let outputs = Decompressor::default().decompress_typed(&frame)?;
let types: Vec<DataType> = outputs.iter().map(|o| o.data_type()).collect();
assert_eq!(
types,
[DataType::Serial, DataType::Struct, DataType::String]
);
assert_eq!(outputs[0].content(), text);
assert_eq!(outputs[1].width(), 4);
assert_eq!(outputs[2].string_lens(), lens);
Ok(())
}
#[test]
fn runs() {
main().unwrap();
}
}
#[cfg(feature = "all-codecs")]
#[rustfmt::skip]
mod docs_graphs_2 {
use mopenzl::graph::{GraphBuilder, StandardGraph, StandardNode};
use mopenzl::input::{Input, Numbers};
use mopenzl::{Compressor, Decompressor, EncoderConfig};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut builder = GraphBuilder::new();
let packed = builder.pipeline(
&[
StandardNode::DeltaInt.into(),
StandardNode::Zigzag.into(),
StandardNode::BitpackInt.into(),
],
StandardGraph::Store,
)?;
let graph = builder.build(packed)?;
let values: Vec<u8> = (0..2000u32)
.flat_map(|i| (500 + i % 17).to_le_bytes())
.collect();
let numbers = Numbers::try_from((&values[..], 4))?;
let mut compressor = Compressor::builder(EncoderConfig::default())
.with_graph(graph)
.build()?;
let frame = compressor.compress_inputs(&[Input::from(numbers)])?;
assert!(frame.len() < values.len() / 2);
let outputs = Decompressor::default().decompress_typed(&frame)?;
assert_eq!(outputs[0].content(), values);
Ok(())
}
#[test]
fn runs() {
main().unwrap();
}
}
#[cfg(feature = "all-codecs")]
#[rustfmt::skip]
mod docs_graphs_3 {
use mopenzl::graph::params::zstd;
use mopenzl::graph::{GraphBuilder, GraphParams, LocalParams, StandardGraph, StandardNode};
use mopenzl::{Compressor, Decompressor, EncoderConfig};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut builder = GraphBuilder::new();
let zstd19 = builder.parameterize_node(
StandardNode::Zstd,
LocalParams::default().with_int(zstd::COMPRESSION_LEVEL, 19),
)?;
let strong = builder.static_graph(zstd19, &[StandardGraph::Store.into()])?;
let race = builder.parameterize_graph(
StandardGraph::BruteForce,
GraphParams::default()
.with_graphs([
strong,
StandardGraph::Lz4.into(),
StandardGraph::Store.into(),
])
.with_name("zstd19-or-lz4"),
)?;
let graph = builder.build(race)?;
let input = b"parameters replace, they do not merge ".repeat(500);
let mut compressor = Compressor::builder(EncoderConfig::default())
.with_graph(graph)
.build()?;
let frame = compressor.compress(&input)?;
assert!(frame.len() < input.len() / 10);
assert_eq!(Decompressor::default().decompress(&frame)?, input);
Ok(())
}
#[test]
fn runs() {
main().unwrap();
}
}
#[cfg(feature = "all-codecs")]
#[rustfmt::skip]
mod docs_graphs_4 {
use mopenzl::graph::{
GraphBuilder, GraphId, InputView, Selector, SelectorContext, StandardGraph, TypeSet,
};
use mopenzl::{Compressor, DataType, Decompressor, EncoderConfig};
struct Smallest;
impl Selector for Smallest {
fn select(
&self,
cx: &mut SelectorContext<'_>,
input: InputView<'_>,
successors: &[GraphId],
) -> GraphId {
let mut best = successors[0];
let mut best_size = usize::MAX;
for &graph in successors {
let size = cx.try_graph(&input, graph).unwrap_or(usize::MAX);
if size < best_size {
(best, best_size) = (graph, size);
}
}
best
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut builder = GraphBuilder::new();
let selector = builder.selector(
"smallest",
Smallest,
TypeSet::from(DataType::Serial),
&[
StandardGraph::Zstd.into(),
StandardGraph::Lz4.into(),
StandardGraph::Store.into(),
],
)?;
let graph = builder.build(selector)?;
let input = b"selectors measure instead of guessing ".repeat(300);
let mut compressor = Compressor::builder(EncoderConfig::default())
.with_graph(graph)
.build()?;
let frame = compressor.compress(&input)?;
assert_eq!(Decompressor::default().decompress(&frame)?, input);
Ok(())
}
#[test]
fn runs() {
main().unwrap();
}
}
#[cfg(feature = "all-codecs")]
#[rustfmt::skip]
mod docs_graphs_5 {
use mopenzl::graph::{
Edge, FunctionGraph, GraphBuilder, GraphContext, GraphError, StandardGraph, StandardNode,
};
use mopenzl::input::{Input, Strings};
use mopenzl::{Compressor, DataType, Decompressor, EncoderConfig};
struct SplitStrings;
impl FunctionGraph for SplitStrings {
fn compress(&self, cx: &mut GraphContext<'_>, inputs: &[Edge]) -> Result<(), GraphError> {
let parts = cx.run_node(StandardNode::SeparateStringComponents, inputs)?;
let graphs = cx.custom_graphs();
cx.set_destination(&parts[0..1], graphs[0])?; cx.set_destination(&parts[1..2], graphs[1])?; Ok(())
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut builder = GraphBuilder::new();
let function = builder.function_graph(
"split_strings",
SplitStrings,
&[DataType::String.into()],
false,
&[
StandardGraph::Zstd.into(),
StandardGraph::NumericCompress.into(),
],
&[],
)?;
let graph = builder.build(function)?;
let text = b"red green blue red green blue ".repeat(100);
let lens: Vec<u32> = [3, 5, 4, 3, 5, 4]
.iter()
.cycle()
.take(600)
.copied()
.collect();
let content_len: u32 = lens.iter().sum();
let strings = Strings::try_from((&text[..content_len as usize], &lens[..]))?;
let mut compressor = Compressor::builder(EncoderConfig::default())
.with_graph(graph)
.build()?;
let frame = compressor.compress_inputs(&[Input::from(strings)])?;
let outputs = Decompressor::default().decompress_typed(&frame)?;
assert_eq!(outputs[0].string_lens(), lens);
assert_eq!(outputs[0].content(), &text[..content_len as usize]);
Ok(())
}
#[test]
fn runs() {
main().unwrap();
}
}
#[cfg(feature = "all-codecs")]
#[rustfmt::skip]
mod docs_graphs_6 {
use mopenzl::graph::{GraphBuilder, GraphError, Segmenter, SegmenterContext, StandardGraph};
use mopenzl::{Compressor, DataType, Decompressor, EncoderConfig};
struct Thirds;
impl Segmenter for Thirds {
fn segment(&self, cx: &mut SegmenterContext<'_>) -> Result<(), GraphError> {
let total = cx.remaining()[0];
let successor = cx.custom_graphs()[0];
let third = total.div_ceil(3).max(1);
let mut left = total;
while left > 0 {
let take = third.min(left);
cx.process_chunk(&[take], successor)?;
left -= take;
}
if total == 0 {
cx.process_chunk(&[0], successor)?;
}
Ok(())
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut builder = GraphBuilder::new();
let thirds = builder.segmenter(
"thirds",
Thirds,
&[DataType::Serial.into()],
&[StandardGraph::CompressGeneric.into()],
)?;
let graph = builder.build(thirds)?;
let input = b"three chunks, three independent graphs ".repeat(400);
let mut compressor = Compressor::builder(EncoderConfig::default())
.with_graph(graph)
.build()?;
let frame = compressor.compress(&input)?;
assert_eq!(Decompressor::default().decompress(&frame)?, input);
Ok(())
}
#[test]
fn runs() {
main().unwrap();
}
}
#[cfg(feature = "all-codecs")]
#[rustfmt::skip]
mod docs_graphs_7 {
use mopenzl::graph::GraphBuilder;
use mopenzl::{ChunkSize, Compressor, Decompressor, EncoderConfig};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut builder = GraphBuilder::new();
let segmenter = builder.num_from_serial_segmenter(8, ChunkSize::try_from(64 << 10)?, None)?;
let graph = builder.build(segmenter)?;
let input: Vec<u8> = (0..40_000u64)
.flat_map(|i| (i * 1000).to_le_bytes())
.collect();
let mut compressor = Compressor::builder(EncoderConfig::default())
.with_graph(graph)
.build()?;
let frame = compressor.compress(&input)?;
assert_eq!(Decompressor::default().decompress(&frame)?, input);
Ok(())
}
#[test]
fn runs() {
main().unwrap();
}
}
#[cfg(feature = "all-codecs")]
#[rustfmt::skip]
mod docs_graphs_8 {
use mopenzl::graph::{CompressorGraph, StandardGraph};
use mopenzl::{Compressor, Decompressor, EncoderConfig};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let not_constant = b"this is certainly not one repeated byte".repeat(10);
let graph = CompressorGraph::standard(StandardGraph::Constant);
let mut strict = Compressor::builder(EncoderConfig::default())
.with_graph(graph.clone())
.build()?;
assert!(strict.compress(¬_constant).is_err());
let config = EncoderConfig::default().with_permissive(true);
let mut permissive = Compressor::builder(config).with_graph(graph).build()?;
let frame = permissive.compress(¬_constant)?;
assert_eq!(Decompressor::default().decompress(&frame)?, not_constant);
Ok(())
}
#[test]
fn runs() {
main().unwrap();
}
}
#[cfg(feature = "all-codecs")]
#[rustfmt::skip]
mod docs_structured_data_1 {
use mopenzl::graph::{CompressorGraph, StandardGraph};
use mopenzl::input::{Input, Numbers};
use mopenzl::{Compressor, EncoderConfig, Level};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let values: Vec<u8> = (0..20_000u64)
.flat_map(|i| (1_000_000 + i * 16 + (i * 2654435761) % 5).to_le_bytes())
.collect();
let input = Input::from(Numbers::try_from((&values[..], 8))?);
for (name, graph, level) in [
("zstd", StandardGraph::Zstd, 6),
("field_lz", StandardGraph::FieldLz, 6),
("select_numeric, level 6", StandardGraph::SelectNumeric, 6),
("select_numeric, level 10", StandardGraph::SelectNumeric, 10),
] {
let config = EncoderConfig::default().with_level(Level::try_from(level)?);
let mut compressor = Compressor::builder(config)
.with_graph(CompressorGraph::standard(graph))
.build()?;
let frame = if graph == StandardGraph::Zstd {
compressor.compress(&values)?
} else {
compressor.compress_inputs(&[input])?
};
println!("{name}: {} -> {} bytes", values.len(), frame.len());
}
Ok(())
}
#[test]
fn runs() {
main().unwrap();
}
}
#[cfg(feature = "all-codecs")]
#[rustfmt::skip]
mod docs_structured_data_2 {
use mopenzl::graph::{
Edge, FunctionGraph, GraphBuilder, GraphContext, GraphError, StandardGraph, StandardNode,
};
use mopenzl::input::{Input, Records};
use mopenzl::{Compressor, DataType, Decompressor, EncoderConfig};
struct Columns;
impl FunctionGraph for Columns {
fn compress(&self, cx: &mut GraphContext<'_>, inputs: &[Edge]) -> Result<(), GraphError> {
let columns = cx.run_node(StandardNode::TransposeSplit, inputs)?;
let successor = cx.custom_graphs()[0];
for column in columns {
cx.set_destination(&[column], successor)?;
}
Ok(())
}
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut bytes = Vec::new();
for i in 0..5_000u32 {
bytes.extend_from_slice(&i.to_le_bytes());
bytes.extend_from_slice(&(i % 3).to_le_bytes());
bytes.extend_from_slice(&[0xAB; 8]);
}
let records = Records::try_from((&bytes[..], 16))?;
let mut builder = GraphBuilder::new();
let columns = builder.function_graph(
"columns",
Columns,
&[DataType::Struct.into()],
false,
&[StandardGraph::Zstd.into()],
&[],
)?;
let graph = builder.build(columns)?;
let mut compressor = Compressor::builder(EncoderConfig::default())
.with_graph(graph)
.build()?;
let frame = compressor.compress_inputs(&[Input::from(records)])?;
println!("{} -> {} bytes", bytes.len(), frame.len());
let outputs = Decompressor::default().decompress_typed(&frame)?;
assert_eq!(outputs[0].data_type(), DataType::Struct);
assert_eq!(outputs[0].width(), 16);
assert_eq!(outputs[0].content(), bytes);
Ok(())
}
#[test]
fn runs() {
main().unwrap();
}
}
#[cfg(feature = "all-codecs")]
#[rustfmt::skip]
mod docs_structured_data_3 {
use mopenzl::graph::{GraphBuilder, GraphParams, StandardGraph};
use mopenzl::input::{Input, Strings};
use mopenzl::{Compressor, DataType, Decompressor, EncoderConfig};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let column: Vec<String> = (0..3_000u32)
.map(|i| (10_000 + i * 7).to_string())
.collect();
let content: Vec<u8> = column.concat().into_bytes();
let lens: Vec<u32> = column.iter().map(|s| s.len() as u32).collect();
let strings = Strings::try_from((&content[..], &lens[..]))?;
let mut builder = GraphBuilder::new();
let parse = builder.parameterize_graph(
StandardGraph::TryParseInt,
GraphParams::default().with_graphs([
StandardGraph::NumericCompress.into(),
StandardGraph::StringCompress.into(),
StandardGraph::NumericCompress.into(),
]),
)?;
let mut compressor = Compressor::builder(EncoderConfig::default())
.with_graph(builder.build(parse)?)
.build()?;
let frame = compressor.compress_inputs(&[Input::from(strings)])?;
println!("{} -> {} bytes", content.len(), frame.len());
let outputs = Decompressor::default().decompress_typed(&frame)?;
assert_eq!(outputs[0].data_type(), DataType::String);
assert_eq!(outputs[0].string_lens(), lens);
assert_eq!(outputs[0].content(), content);
Ok(())
}
#[test]
fn runs() {
main().unwrap();
}
}
#[cfg(feature = "all-codecs")]
#[rustfmt::skip]
mod docs_structured_data_4 {
use mopenzl::graph::{CLUSTERING_TAG_METADATA_ID, ClusteringConfig, GraphBuilder, StandardGraph};
use mopenzl::input::{Input, Numbers};
use mopenzl::{Compressor, DataType, Decompressor, EncoderConfig};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let latency: Vec<u8> = (0..4000u32)
.flat_map(|i| (20 + i % 9).to_le_bytes())
.collect();
let latency_p99: Vec<u8> = (0..4000u32)
.flat_map(|i| (90 + i % 13).to_le_bytes())
.collect();
let ids: Vec<u8> = (0..4000u32)
.flat_map(|i| (1_000_000 + i).to_le_bytes())
.collect();
let tags = [
[(CLUSTERING_TAG_METADATA_ID, 1)],
[(CLUSTERING_TAG_METADATA_ID, 2)],
[(CLUSTERING_TAG_METADATA_ID, 3)],
];
let inputs = [
Input::from(Numbers::try_from((&latency[..], 4))?).with_metadata(&tags[0]),
Input::from(Numbers::try_from((&latency_p99[..], 4))?).with_metadata(&tags[1]),
Input::from(Numbers::try_from((&ids[..], 4))?).with_metadata(&tags[2]),
];
let config = ClusteringConfig::default()
.with_cluster(DataType::Numeric, 4, 0, 2, [1, 2])
.with_type_default(DataType::Numeric, 4, 1, 2);
let mut builder = GraphBuilder::new();
let clustering = builder.clustering(
&config,
&[
StandardGraph::SelectNumeric.into(),
StandardGraph::FieldLz.into(),
],
)?;
let graph = builder.build(clustering)?;
let mut compressor = Compressor::builder(EncoderConfig::default())
.with_graph(graph)
.build()?;
let frame = compressor.compress_inputs(&inputs)?;
let outputs = Decompressor::default().decompress_typed(&frame)?;
assert_eq!(outputs.len(), 3);
assert_eq!(outputs[0].content(), latency);
assert_eq!(outputs[1].content(), latency_p99);
assert_eq!(outputs[2].content(), ids);
Ok(())
}
#[test]
fn runs() {
main().unwrap();
}
}
#[cfg(feature = "all-codecs")]
#[rustfmt::skip]
mod docs_structured_data_5 {
use mopenzl::graph::{GbtModel, GbtNode, GraphBuilder, MlSelectorConfig, StandardGraph};
use mopenzl::input::{Input, Numbers};
use mopenzl::{Compressor, Decompressor, EncoderConfig};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let tree = vec![
GbtNode::split(0, 64.0, 1, 2, 1),
GbtNode::leaf(-1.0),
GbtNode::leaf(1.0),
];
let model = GbtModel {
forests: vec![vec![tree]],
successors: 2,
features: vec!["nbElts".to_string()],
};
let config = MlSelectorConfig::try_from(&model)?;
let mut builder = GraphBuilder::new();
let selector = builder.ml_selector(
&config,
&[StandardGraph::Store.into(), StandardGraph::FieldLz.into()],
)?;
let graph = builder.build(selector)?;
let mut compressor = Compressor::builder(EncoderConfig::default())
.with_graph(graph)
.build()?;
let mut decoder = Decompressor::default();
for count in [16u32, 4096] {
let values: Vec<u8> = (0..count).flat_map(|i| (i % 5).to_le_bytes()).collect();
let numbers = Numbers::try_from((&values[..], 4))?;
let frame = compressor.compress_inputs(&[Input::from(numbers)])?;
println!("{count} values -> {} bytes", frame.len());
assert_eq!(decoder.decompress_typed(&frame)?[0].content(), values);
}
Ok(())
}
#[test]
fn runs() {
main().unwrap();
}
}
#[cfg(feature = "all-codecs")]
#[rustfmt::skip]
mod docs_structured_data_6 {
use mopenzl::graph::{GraphBuilder, StandardGraph};
use mopenzl::{Compressor, Decompressor, EncoderConfig};
fn head(major: u8, n: usize) -> Vec<u8> {
assert!(n < 24);
vec![major << 5 | n as u8]
}
fn text(s: &str) -> Vec<u8> {
[head(3, s.len()), s.as_bytes().to_vec()].concat()
}
fn map1(key: &str, value: Vec<u8>) -> Vec<u8> {
[head(5, 1), text(key), value].concat()
}
fn array(items: &[Vec<u8>]) -> Vec<u8> {
[head(4, items.len()), items.concat()].concat()
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let records = 1000u32;
let var_d0 = map1("var", text("d0"));
let assign = map1("assign", array(&[var_d0.clone(), map1("dest", vec![0xF6])]));
let count = map1(
"int",
[vec![0x19], (records as u16).to_be_bytes().to_vec()].concat(),
);
let field = map1("send", array(&[map1("atom", text("u4l")), var_d0]));
let consume = map1("consume", map1("array", array(&[field, count])));
let description = map1("exprs", array(&[assign, consume]));
let mut builder = GraphBuilder::new();
let sddl = builder.sddl(&description, StandardGraph::CompressGeneric)?;
let graph = builder.build(sddl)?;
let mut compressor = Compressor::builder(EncoderConfig::default())
.with_graph(graph)
.build()?;
let data: Vec<u8> = (0..records).flat_map(|i| (i * 3).to_le_bytes()).collect();
let frame = compressor.compress(&data)?;
assert_eq!(Decompressor::default().decompress(&frame)?, data);
let words: [u32; 4] = [0x0001_0003, 4000, 0x000C_0001, 0x0005_0001];
let bytecode: Vec<u8> = words.iter().flat_map(|word| word.to_le_bytes()).collect();
let mut builder = GraphBuilder::new();
let sddl2 = builder.sddl2(&bytecode, 0, None)?;
let graph = builder.build(sddl2)?;
let mut compressor = Compressor::builder(EncoderConfig::default())
.with_graph(graph)
.build()?;
let frame = compressor.compress(&data)?;
assert_eq!(Decompressor::default().decompress(&frame)?, data);
Ok(())
}
#[test]
fn runs() {
main().unwrap();
}
}
#[test]
fn docs_examples_are_current() {
let source = include_str!("docs_examples.rs");
let squash = |text: &str| -> String {
text.lines()
.map(str::trim)
.filter(|l| !l.is_empty())
.collect::<Vec<_>>()
.join("\n")
};
let source = squash(source);
for (name, text) in [
("README.md", include_str!("../README.md")),
("docs/README.md", include_str!("../docs/README.md")),
(
"docs/benchmarking.md",
include_str!("../docs/benchmarking.md"),
),
("docs/codecs.md", include_str!("../docs/codecs.md")),
(
"docs/development.md",
include_str!("../docs/development.md"),
),
(
"docs/dictionaries.md",
include_str!("../docs/dictionaries.md"),
),
("docs/graphs.md", include_str!("../docs/graphs.md")),
(
"docs/structured-data.md",
include_str!("../docs/structured-data.md"),
),
] {
for block in text.split("```rust\n").skip(1) {
let code = squash(block.split("```").next().unwrap_or_default());
assert!(source.contains(&code), "{name}: stale example:\n{code}");
}
}
}