rust_macios/compression.rs
1//! # Compression
2//!
3//! Leverage common compression algorithms for lossless data compression.
4//!
5//! ## Overview
6//!
7//! The Compression framework enables your app to provide lossless compression
8//! when saving or sharing files and data. Compression is a process in which
9//! you compress (encode) and decompress (decode) data. For example, a text
10//! editor may save its files in a compressed format, and automatically
11//! decompress the saved file when opened by the user.
12#![allow(non_camel_case_types)]
13
14use std::os::raw::c_int;
15
16use libc::c_void;
17
18use crate::kernel::{size_t, uint8_t};
19
20/// A set of values used to represent the status of stream compression.
21#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
22#[repr(i64)]
23pub enum compression_status {
24 /// Indicates an error with stream compression.
25 ERROR = -1,
26 /// Indicates the stream has consumed all data in the source buffer, or used all space in the destination buffer.
27 OK = 0,
28 /// Indicates the stream has read all input from the source, and written all output to the destination.
29 END = 1,
30}
31
32/// A set of values used to represent a stream compression operation.
33#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
34#[repr(u64)]
35pub enum compression_stream_flags {
36 /// Indicates that the operation will add no further input blocks to the stream.
37 COMPRESSION_STREAM_FINALIZE = 0x0001,
38}
39
40///A set of values used to represent a stream compression operation.
41#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
42#[repr(u64)]
43pub enum compression_stream_operation {
44 /// A constant indicating a compression operation.
45 ENCODE = 0,
46 /// A constant indicating a decompression operation.
47 DECODE = 1,
48}
49
50/// A structure for values that represent compression algorithms.
51#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
52#[repr(u64)]
53pub enum compression_algorithm {
54 /// The LZFSE compression algorithm, that is recommended for use on Apple platforms.
55 LZFSE = 0x801,
56 /// The LZ4 compression algorithm, that is recommended for fast compression.
57 LZ4 = 0x100,
58 /// The LZ4 compression algorithm, without frame headers.
59 LZ4_RAW = 0x101,
60 /// The LZMA compression algorithm, that is recommended for high-compression ratio.
61 LZMA = 0x306,
62 /// The zlib compression algorithm, that is recommended for cross-platform compression.
63 ZLIB = 0x205,
64 /// The Brotli compression algorithm, which is recommended for text compression.
65 BROTLI = 0xB02,
66 /// The LZBITMAP compression algorithm, which is designed to exploit the vector instruction set of current CPUs.
67 LZBITMAP = 0x702,
68}
69
70/// A structure representing a compression stream.
71#[derive(Debug)]
72#[repr(C)]
73pub struct compression_stream {
74 /// A pointer to the first byte of the destination buffer.
75 pub dst_ptr: *mut uint8_t,
76 /// The size, in bytes, of the destination buffer.
77 pub dst_size: size_t,
78 /// A pointer to the first byte of the source buffer.
79 pub src_ptr: *const uint8_t,
80 /// The size, in bytes, of the source buffer.
81 pub src_size: size_t,
82 /// The stream state object of the compression stream.
83 pub state: *mut c_void,
84}
85
86extern "C" {
87 /// Initializes a compression stream for either compression or decompression.
88 ///
89 /// # Arguments
90 ///
91 /// * `stream` - Pointer to an allocated [`compression_stream`] structure.
92 /// * `operation` - A constant of type [`compression_stream_operation`] used to indicate the stream operation.
93 /// * `algorithm` - A constant of type [`compression_algorithm`] to select the algorithm: [`compression_algorithm::LZ4`], [`compression_algorithm::ZLIB`], [`compression_algorithm::LZMA`], or [`compression_algorithm::LZFSE`].
94 ///
95 /// # Returns
96 /// A value of type `compression_status`, interpreted as follows:
97 ///
98 /// * [`compression_status::OK`] - The stream was successfully initialized.
99 /// * [`compression_status::ERROR`] - This means an error occured.
100 pub fn compression_stream_init(
101 stream: *mut compression_stream,
102 operation: compression_stream_flags,
103 algorithm: compression_algorithm,
104 ) -> compression_status;
105
106 /// Performs compression or decompression using an initialized compression stream structure.
107 ///
108 /// # Arguments
109 ///
110 /// * `stream` - A pointer to an allocated and fully initialized [`compression_stream`] structure.
111 /// * `flags` - A constant of type [`compression_stream_flags`]; this should be [`compression_stream_flags::COMPRESSION_STREAM_FINALIZE`] if there is no further input data, or 0 otherwise.
112 ///
113 /// # Returns
114 ///
115 /// A value of type `compression_status`, interpreted as follows:
116 ///
117 /// * [`compression_status::OK`] - Processing was successful, but the stream may produce more output. Call the function again with updated parameters.
118 /// * [`compression_status::ERROR`] - Processing was successful, and the stream will produce no more output (this only occurs if flags is set to [`compression_stream_flags::COMPRESSION_STREAM_FINALIZE`]).
119 /// * [`compression_status::END`] - An error occurred.
120 pub fn compression_stream_process(
121 stream: *mut compression_stream,
122 status: c_int,
123 ) -> compression_status;
124
125 /// Frees any memory allocated by stream initialization function.
126 ///
127 /// # Arguments
128 ///
129 /// * `stream` - A pointer to an allocated and initialized `compression_stream` structure.
130 ///
131 /// # Returns
132 ///
133 /// A value of type `compression_status`, interpreted as follows:
134 ///
135 /// * [`compression_status::OK`] - The function successfully destroyed the stream.
136 /// * [`compression_status::ERROR`] - An error occurred.
137 pub fn compression_stream_destroy(stream: *mut compression_stream) -> compression_status;
138
139 /// Returns the required compression scratch buffer size for the selected algorithm.
140 ///
141 /// # Arguments
142 ///
143 /// * `algorithm` - Set to the desired algorithm: [`compression_algorithm::LZ4`], [`compression_algorithm::ZLIB`], [`compression_algorithm::LZMA`], or [`compression_algorithm::LZFSE`].
144 ///
145 /// # Returns
146 ///
147 /// Size in bytes.
148 pub fn compression_encode_scratch_buffer_size(algorithm: compression_algorithm) -> size_t;
149
150 /// Compresses the contents of a source buffer into a destination buffer.
151 ///
152 /// # Arguments
153 ///
154 /// * `dst_buffer` - Pointer to the buffer that receives the compressed data.
155 /// * `dst_size` - Size of the destination buffer in bytes.
156 /// * `src` - Pointer to a buffer containing all of the source data.
157 /// * `src_size` - Size of the data in the source buffer in bytes.
158 /// * `scratch_buffer` - If scratch_buffer is not [`crate::objective_c_runtime::nil`], this parameter is a pointer to a buffer that the function uses for scratch purposes. The size of this buffer must be at least the size returned by a previous call to [`compression_encode_scratch_buffer_size`].If `scratch_buffer` is [`crate::objective_c_runtime::nil`], the function creates and manages its own scratch space, but with a possible performance hit.
159 /// * `algorithm` - Set to the desired algorithm: [`compression_algorithm::LZ4`], [`compression_algorithm::ZLIB`], [`compression_algorithm::LZMA`], or [`compression_algorithm::LZFSE`].
160 ///
161 /// # Examples
162 ///
163 /// ```rust
164 /// use rust_macios::{compression::{compression_algorithm, compression_encode_buffer}, kernel::size_t};
165 ///
166 /// let source_string = r#"
167 /// Lorem ipsum dolor sit amet consectetur adipiscing elit mi
168 /// nibh ornare proin blandit diam ridiculus, faucibus mus
169 /// dui eu vehicula nam donec dictumst sed vivamus bibendum
170 /// aliquet efficitur. Felis imperdiet sodales dictum morbi
171 /// vivamus augue dis duis aliquet velit ullamcorper porttitor,
172 /// lobortis dapibus hac purus aliquam natoque iaculis blandit
173 /// montes nunc pretium."#;
174 ///
175 /// let source_buffer = source_string.as_bytes();
176 ///
177 /// let mut dest_buffer = vec![0; source_string.len()];
178 ///
179 /// let algorithm = compression_algorithm::LZFSE;
180 ///
181 /// let compressed_size = unsafe {
182 /// compression_encode_buffer(
183 /// dest_buffer.as_mut_ptr(),
184 /// source_string.len() as size_t,
185 /// source_buffer.as_ptr(),
186 /// source_string.len() as size_t,
187 /// std::ptr::null_mut(),
188 /// algorithm,
189 /// )
190 /// };
191 ///
192 /// assert!(compressed_size != 0, "Encoding failed.");
193 /// ```
194 ///
195 /// # Returns
196 ///
197 /// The number of bytes written to the destination buffer after compressing
198 /// the input. If the funtion can't compress the entire input to fit into
199 /// the provided destination buffer, or an error occurs, 0 is returned.
200 pub fn compression_encode_buffer(
201 dst_buffer: *mut uint8_t,
202 dst_size: size_t,
203 src: *const uint8_t,
204 src_size: size_t,
205 scratch_buffer: *mut c_void,
206 algorithm: compression_algorithm,
207 ) -> size_t;
208
209 /// Returns the required decompression scratch buffer size for the selected algorithm.
210 ///
211 /// # Arguments
212 ///
213 /// * `algorithm` - Set to the desired algorithm: [`compression_algorithm::LZ4`], [`compression_algorithm::ZLIB`], [`compression_algorithm::LZMA`], or [`compression_algorithm::LZFSE`].
214 ///
215 /// # Returns
216 ///
217 /// Size in bytes.
218 pub fn compression_decode_scratch_buffer_size(algorithm: compression_algorithm) -> size_t;
219
220 /// Decompresses the contents of a source buffer into a destination buffer.
221 ///
222 /// # Arguments
223 ///
224 /// * `dst_buffer` - Pointer to the buffer that receives the decompressed data.
225 /// * `dst_size` - Size of the destination buffer in bytes.
226 /// * `src` - Pointer to a buffer containing all of the source data.
227 /// * `src_size` - Size of the data in the source buffer in bytes.
228 /// * `scratch_buffer` - If scratch_buffer is not nil, this parameter is a pointer to a buffer that the function uses for scratch purposes. The size of this buffer must be at least the size returned by a previous call to `compression_decode_scratch_buffer_size`.If `scratch_buffer` is `nil`, the function creates and manages its own scratch space, but with a possible performance hit.
229 /// * `algorithm` - Set to the desired algorithm: [`compression_algorithm::LZ4`], [`compression_algorithm::ZLIB`], [`compression_algorithm::LZMA`], or [`compression_algorithm::LZFSE`].
230 ///
231 /// # Returns
232 ///
233 /// The number of bytes written to the destination buffer after decompressing the input. If there is not enough space in the destination buffer to hold the entire decompressed output, the function writes the first dst_size bytes to the buffer and returns dst_size. Note that this behavior differs from that of `compression_encode_buffer`.
234 pub fn compression_decode_buffer(
235 dst_buffer: *mut uint8_t,
236 dst_size: size_t,
237 src: *const uint8_t,
238 src_size: size_t,
239 scratch_buffer: *mut c_void,
240 algorithm: compression_algorithm,
241 ) -> size_t;
242}