Skip to main content

lzma_sdk_sys/
lib.rs

1#![doc = include_str!("../README.MD")]
2#![no_std]
3#![allow(warnings)]
4
5#[cfg(feature = "std")]
6extern crate std;
7
8use core::ffi::c_void;
9
10extern crate alloc;
11extern crate core;
12
13#[cfg(not(feature = "generate-bindings"))]
14include!("bindings.rs");
15
16#[cfg(feature = "generate-bindings")]
17include!(concat!(env!("OUT_DIR"), "/bindings.rs"));
18
19// Provide a default allocator implementation for lzma encoder.
20pub struct Allocator {
21    alloc: ISzAlloc,
22}
23
24impl Default for Allocator {
25    fn default() -> Self {
26        Self {
27            alloc: ISzAlloc {
28                Alloc: Some(sz_alloc),
29                Free: Some(sz_free),
30            },
31        }
32    }
33}
34
35impl AsRef<ISzAlloc> for Allocator {
36    fn as_ref(&self) -> &ISzAlloc {
37        &self.alloc
38    }
39}
40
41unsafe extern "C" fn sz_alloc(_p: ISzAllocPtr, size: usize) -> *mut c_void {
42    libc::malloc(size)
43}
44
45unsafe extern "C" fn sz_free(_p: ISzAllocPtr, address: *mut c_void) {
46    libc::free(address)
47}
48
49#[cfg(feature = "test-build-size")]
50#[no_mangle]
51pub unsafe extern "C" fn LzmaDecode_Out(
52    dest: *mut Byte,
53    destLen: *mut SizeT,
54    src: *const Byte,
55    srcLen: *mut SizeT,
56    propData: *const Byte,
57    propSize: ::core::ffi::c_uint,
58    finishMode: ELzmaFinishMode,
59    status: *mut ELzmaStatus,
60    alloc: ISzAllocPtr,
61) -> SRes {
62    LzmaDecode(
63        dest, destLen, src, srcLen, propData, propSize, finishMode, status, alloc,
64    )
65}
66
67#[cfg(feature = "test-build-size")]
68#[no_mangle]
69pub unsafe extern "C" fn LzmaEncode_Out(
70    dest: *mut Byte,
71    destLen: *mut SizeT,
72    src: *const Byte,
73    srcLen: SizeT,
74    props: *const CLzmaEncProps,
75    propsEncoded: *mut Byte,
76    propsSize: *mut SizeT,
77    writeEndMark: ::core::ffi::c_int,
78    progress: ICompressProgressPtr,
79    alloc: ISzAllocPtr,
80    allocBig: ISzAllocPtr,
81) -> SRes {
82    LzmaEncode(
83        dest,
84        destLen,
85        src,
86        srcLen,
87        props,
88        propsEncoded,
89        propsSize,
90        writeEndMark,
91        progress,
92        alloc,
93        allocBig,
94    )
95}
96
97#[cfg(test)]
98mod tests {
99    use super::*;
100    use alloc::vec;
101    use std::ptr;
102
103    #[test]
104    fn test_lzma_round_trip() {
105        let input = b"Hello LZMA compression!";
106        let mut props = [0u8; LZMA_PROPS_SIZE as usize];
107        let mut props_size = LZMA_PROPS_SIZE as SizeT;
108
109        // Encode
110        let mut compressed = vec![0u8; input.len() * 2];
111        let mut compressed_size = compressed.len() as SizeT;
112
113        let alloc = Allocator::default();
114
115        unsafe {
116            let enc = LzmaEnc_Create(alloc.as_ref() as *const _);
117            assert!(!enc.is_null());
118
119            let mut enc_props = CLzmaEncProps::default();
120            LzmaEncProps_Init(&mut enc_props);
121
122            let res = LzmaEnc_SetProps(enc, &enc_props);
123            assert_eq!(res, SZ_OK as i32);
124
125            let res = LzmaEncode(
126                compressed.as_mut_ptr() as *mut Byte,
127                &mut compressed_size,
128                input.as_ptr() as *const Byte,
129                input.len() as SizeT,
130                &enc_props,
131                props.as_mut_ptr() as *mut Byte,
132                &mut props_size,
133                0,
134                ptr::null_mut(),
135                alloc.as_ref(),
136                alloc.as_ref(),
137            );
138            assert_eq!(res, SZ_OK as i32);
139
140            LzmaEnc_Destroy(enc, alloc.as_ref(), alloc.as_ref());
141
142            // Trim compressed buffer to actual size
143            compressed.truncate(compressed_size as usize);
144
145            // Decode
146            // The LZMA format requires the decompressed size for decoding
147            let mut dest = vec![0u8; input.len()];
148            let mut dest_size = dest.capacity() as SizeT;
149            let mut source_len: SizeT = compressed.len();
150            let mut status: ELzmaStatus = ELzmaStatus::LZMA_STATUS_NOT_SPECIFIED;
151
152            let res = LzmaDecode(
153                dest.as_mut_ptr() as *mut Byte,
154                &mut dest_size,
155                compressed.as_ptr() as *const Byte,
156                &mut source_len,
157                props.as_ptr() as *const Byte,
158                props_size as u32,
159                ELzmaFinishMode::LZMA_FINISH_END,
160                &mut status,
161                alloc.as_ref(),
162            );
163            assert_eq!(res, SZ_OK as i32);
164
165            // Verify the round-trip
166            assert_eq!(dest_size as usize, input.len());
167            assert_eq!(&dest[..dest_size as usize], input);
168        }
169    }
170}