OpenMS
Loading...
Searching...
No Matches
ZstdCompression Class Reference

Compresses and uncompresses byte buffers using Zstandard (zstd), optionally combined with the byte-shuffling and dictionary transforms defined for mzML. More...

#include <OpenMS/FORMAT/ZstdCompression.h>

Public Types

enum class  ByteTransform { NONE , BYTE_SHUFFLE , DICTIONARY }
 Transform applied to the (little-endian) array bytes prior to zstd compression. More...
 

Static Public Member Functions

static void compressData (const void *raw_data, size_t in_length, std::string &compressed_data, int level=DEFAULT_LEVEL)
 Compress the in_length bytes pointed to by raw_data into compressed_data using zstd.
 
static void uncompressData (const void *compressed_data, size_t nr_bytes, std::string &out, size_t expected_size=0)
 Uncompress the zstd-compressed compressed_data.
 
static void byteShuffle (const void *data, size_t nr_bytes, size_t element_size, std::string &out)
 Byte-shuffle an array of element_size byte elements.
 
static void byteUnshuffle (const void *data, size_t nr_bytes, size_t element_size, std::string &out)
 Reverse the byte shuffling done by byteShuffle().
 
static void dictionaryEncode (const void *data, size_t nr_bytes, size_t element_size, std::string &out)
 Dictionary-encode an array of little-endian element_size byte elements (values and indices byte-shuffled).
 
static void dictionaryDecode (const void *data, size_t nr_bytes, size_t element_size, std::string &out, size_t array_length=0)
 Decode a buffer created by dictionaryEncode() back into an array of little-endian element_size byte elements.
 
static void encode (const void *data, size_t nr_bytes, ByteTransform transform, size_t element_size, std::string &out, int level=DEFAULT_LEVEL)
 Apply transform to an array of little-endian element_size byte elements and compress the result with zstd.
 
static void decode (const void *data, size_t nr_bytes, ByteTransform transform, size_t element_size, std::string &out, size_t array_length=0)
 Uncompress zstd data and reverse transform, yielding an array of little-endian element_size byte elements.
 

Static Public Attributes

static constexpr int DEFAULT_LEVEL = 3
 Default zstd compression level (identical to zstd's own default)
 

Detailed Description

Compresses and uncompresses byte buffers using Zstandard (zstd), optionally combined with the byte-shuffling and dictionary transforms defined for mzML.

Static utility class implementing the zstd based binary data array compression methods recommended by the mzML specification (PSI-MS CV terms MS:1003780 to MS:1003785):

  • zstd compression (MS:1003780): the little-endian bytes of the array are compressed with zstd.
  • byte-shuffled zstd compression (MS:1003781): the bytes of the array elements are transposed ("shuffled") so that the i-th byte of every element is stored contiguously, followed by zstd compression. This usually compresses sorted data (e.g. m/z arrays) much better.
  • dictionary-encoded zstd compression (MS:1003782): the array is replaced by a sorted dictionary of its distinct values and an array of indices into that dictionary. Values and indices are byte-shuffled separately, then everything is compressed with zstd. This is well suited for arrays with many repeated values (e.g. ion mobility, charge states).
  • The MS-Numpress variants (MS:1003783 to MS:1003785) apply plain zstd compression to the output of the respective MS-Numpress encoder.

The layout of a dictionary-encoded buffer is: an unsigned 64 bit little-endian integer holding the byte offset of the index array, an unsigned 64 bit little-endian integer holding the number of distinct values n, the byte-shuffled sorted distinct values, and finally the byte-shuffled indices. The indices use the smallest unsigned integer type able to address all values (8 bit if n < 2^8, 16 bit if n < 2^16, 32 bit if n < 2^32, otherwise 64 bit). Since implementations disagree on the index width at these boundaries (e.g. 8 bit indices for exactly 256 values), the decoder derives the width from the size of the index region if the number of array elements is known (see dictionaryDecode()).

All array transforms operate on raw byte buffers holding a contiguous array of fixed-size elements in little-endian byte order (the byte order mandated by mzML). The data is treated as raw bytes and may contain embedded zeros.

See also
https://github.com/mobiusklein/mzd.cpp for the reference implementation.

Member Enumeration Documentation

◆ ByteTransform

enum class ByteTransform
strong

Transform applied to the (little-endian) array bytes prior to zstd compression.

Enumerator
NONE 

no transform, plain zstd compression (MS:1003780)

BYTE_SHUFFLE 

byte shuffling followed by zstd compression (MS:1003781)

DICTIONARY 

byte-shuffled dictionary encoding followed by zstd compression (MS:1003782)

Member Function Documentation

◆ byteShuffle()

static void byteShuffle ( const void *  data,
size_t  nr_bytes,
size_t  element_size,
std::string &  out 
)
static

Byte-shuffle an array of element_size byte elements.

The i-th byte of the j-th element is moved to position i * n + j (with n being the number of elements).

Parameters
[in]dataPointer to the array bytes.
[in]nr_bytesLength of data in bytes; must be a multiple of element_size.
[in]element_sizeSize of a single array element in bytes.
[out]outReceives the shuffled bytes; any previous contents are replaced.
Exceptions
Exception::InvalidValueif element_size is zero.
Exception::ConversionErrorif nr_bytes is not a multiple of element_size.

◆ byteUnshuffle()

static void byteUnshuffle ( const void *  data,
size_t  nr_bytes,
size_t  element_size,
std::string &  out 
)
static

Reverse the byte shuffling done by byteShuffle().

Parameters
[in]dataPointer to the shuffled bytes.
[in]nr_bytesLength of data in bytes; must be a multiple of element_size.
[in]element_sizeSize of a single array element in bytes.
[out]outReceives the restored array bytes; any previous contents are replaced.
Exceptions
Exception::InvalidValueif element_size is zero.
Exception::ConversionErrorif nr_bytes is not a multiple of element_size.

◆ compressData()

static void compressData ( const void *  raw_data,
size_t  in_length,
std::string &  compressed_data,
int  level = DEFAULT_LEVEL 
)
static

Compress the in_length bytes pointed to by raw_data into compressed_data using zstd.

A single zstd frame is written which records the uncompressed size in its header.

Parameters
[in]raw_dataPointer to the bytes to compress.
[in]in_lengthLength of raw_data in bytes.
[out]compressed_dataReceives the compressed payload; any previous contents are replaced.
[in]levelThe zstd compression level.
Exceptions
Exception::ConversionErrorif zstd reports a failure during compression.

◆ decode()

static void decode ( const void *  data,
size_t  nr_bytes,
ByteTransform  transform,
size_t  element_size,
std::string &  out,
size_t  array_length = 0 
)
static

Uncompress zstd data and reverse transform, yielding an array of little-endian element_size byte elements.

An empty input yields an empty output.

Parameters
[in]dataPointer to the compressed bytes.
[in]nr_bytesLength of data in bytes.
[in]transformThe transform that was applied before compression.
[in]element_sizeSize of a single array element in bytes (for ByteTransform::NONE only used together with array_length).
[out]outReceives the decoded array bytes; any previous contents are replaced.
[in]array_lengthNumber of elements of the array (0 if unknown). Limits the initial allocation for the decompressed data (see uncompressData()) and is passed on to dictionaryDecode().
Exceptions
Exception::InvalidValueif element_size is invalid for transform.
Exception::ConversionErrorif the data is malformed.

◆ dictionaryDecode()

static void dictionaryDecode ( const void *  data,
size_t  nr_bytes,
size_t  element_size,
std::string &  out,
size_t  array_length = 0 
)
static

Decode a buffer created by dictionaryEncode() back into an array of little-endian element_size byte elements.

An empty input yields an empty output.

If array_length is given, the index width is taken from the size of the index region divided by array_length, provided that this is 1, 2, 4 or 8 bytes and adjacent to the width defined by the specification. This accepts buffers written with the diverging boundary conventions of other implementations (e.g. 8 bit indices for 256 values or 16 bit indices for 255 values). Otherwise, the width defined by the specification is used.

Parameters
[in]dataPointer to the dictionary-encoded bytes.
[in]nr_bytesLength of data in bytes.
[in]element_sizeSize of a single array element in bytes (1, 2, 4 or 8).
[out]outReceives the decoded array bytes; any previous contents are replaced.
[in]array_lengthNumber of elements of the encoded array, e.g. the mzML arrayLength (0 if unknown).
Exceptions
Exception::InvalidValueif element_size is not 1, 2, 4 or 8.
Exception::ConversionErrorif the buffer is malformed or its values do not have element_size bytes.

◆ dictionaryEncode()

static void dictionaryEncode ( const void *  data,
size_t  nr_bytes,
size_t  element_size,
std::string &  out 
)
static

Dictionary-encode an array of little-endian element_size byte elements (values and indices byte-shuffled).

See the class documentation for the layout of the resulting buffer.

Parameters
[in]dataPointer to the array bytes (little-endian elements).
[in]nr_bytesLength of data in bytes; must be a multiple of element_size.
[in]element_sizeSize of a single array element in bytes (1, 2, 4 or 8).
[out]outReceives the dictionary-encoded bytes; any previous contents are replaced.
Exceptions
Exception::InvalidValueif element_size is not 1, 2, 4 or 8.
Exception::ConversionErrorif nr_bytes is not a multiple of element_size.

◆ encode()

static void encode ( const void *  data,
size_t  nr_bytes,
ByteTransform  transform,
size_t  element_size,
std::string &  out,
int  level = DEFAULT_LEVEL 
)
static

Apply transform to an array of little-endian element_size byte elements and compress the result with zstd.

An empty input yields an empty output.

Parameters
[in]dataPointer to the array bytes (little-endian elements).
[in]nr_bytesLength of data in bytes; must be a multiple of element_size.
[in]transformThe transform applied before compression.
[in]element_sizeSize of a single array element in bytes (ignored for ByteTransform::NONE).
[out]outReceives the compressed bytes; any previous contents are replaced.
[in]levelThe zstd compression level.
Exceptions
Exception::InvalidValueif element_size is invalid for transform.
Exception::ConversionErrorif the input size does not match element_size or compression fails.

◆ uncompressData()

static void uncompressData ( const void *  compressed_data,
size_t  nr_bytes,
std::string &  out,
size_t  expected_size = 0 
)
static

Uncompress the zstd-compressed compressed_data.

Multiple concatenated frames and frames without a recorded content size are supported. An empty input yields an empty output.

The output buffer is initially sized from the content size recorded in the frame header, capped at expected_size (or, if that is 0, at a small multiple of nr_bytes), and grows as needed. The expected size therefore only affects the initial allocation, not the result.

Parameters
[in]compressed_dataPointer to the zstd-compressed bytes.
[in]nr_bytesLength of compressed_data in bytes.
[out]outReceives the decompressed bytes; any previous contents are replaced.
[in]expected_sizeExpected size of the decompressed data in bytes (0 if unknown).
Exceptions
Exception::ConversionErrorif the data is not valid zstd data or is truncated.

Member Data Documentation

◆ DEFAULT_LEVEL

constexpr int DEFAULT_LEVEL = 3
staticconstexpr

Default zstd compression level (identical to zstd's own default)