divans/ffi/
mod.rs

1#![cfg(not(feature="safe"))]
2
3#[no_mangle]
4use core;
5use core::slice;
6use ::StaticCommand;
7use super::DivansDecompressorFactory;
8use super::interface::Decompressor;
9pub mod interface;
10pub mod alloc_util;
11use self::alloc_util::SubclassableAllocator;
12mod compressor;
13mod decompressor;
14use self::compressor::DivansCompressorState;
15use self::decompressor::DivansDecompressorState;
16use self::interface::{CAllocator, c_void, DivansOptionSelect, DivansReturnCode, DIVANS_FAILURE, DIVANS_SUCCESS, DIVANS_NEEDS_MORE_INPUT, DIVANS_NEEDS_MORE_OUTPUT};
17#[no_mangle]
18pub extern fn divans_new_compressor() -> *mut compressor::DivansCompressorState{
19    unsafe {
20        divans_new_compressor_with_custom_alloc(CAllocator{
21            alloc_func:None,
22            free_func:None,
23            opaque: core::ptr::null_mut(),
24        })
25    }
26}
27
28
29
30#[cfg(feature="no-stdlib")]
31fn divans_new_compressor_without_custom_alloc(_to_box: DivansCompressorState) -> *mut DivansCompressorState{
32    panic!("Must supply allocators if calling divans when compiled with features=no-stdlib");
33}
34#[cfg(not(feature="no-stdlib"))]
35fn divans_new_compressor_without_custom_alloc(to_box: DivansCompressorState) -> *mut DivansCompressorState{
36    alloc_util::Box::<DivansCompressorState>::into_raw(alloc_util::Box::<DivansCompressorState>::new(to_box))
37}
38#[no_mangle]
39pub unsafe extern fn divans_new_compressor_with_custom_alloc(allocators:CAllocator) -> *mut DivansCompressorState{
40    let to_box = DivansCompressorState{
41        custom_allocator:allocators.clone(),
42        compressor:compressor::CompressorState::default(),
43    };
44    if let Some(alloc_fn) = allocators.alloc_func {
45        let ptr = alloc_fn(allocators.opaque, core::mem::size_of::<DivansCompressorState>());
46        let divans_compressor_state_ptr = core::mem::transmute::<*mut c_void, *mut DivansCompressorState>(ptr);
47        core::ptr::write(divans_compressor_state_ptr, to_box);
48        divans_compressor_state_ptr
49    } else {
50        divans_new_compressor_without_custom_alloc(to_box)
51    }
52}
53
54
55
56
57#[no_mangle]
58pub unsafe extern fn divans_set_option(state_ptr: *mut DivansCompressorState,
59                                       selector: DivansOptionSelect,
60                                       value: u32) -> DivansReturnCode {
61    match state_ptr.as_mut() {
62        None => DIVANS_FAILURE,
63        Some(state_ref) => {
64            state_ref.compressor.set_option(selector, value)
65        }
66    }
67}
68     
69#[no_mangle]
70pub unsafe extern fn divans_encode(state_ptr: *mut DivansCompressorState,
71                                   input_buf_ptr: *const u8, input_size: usize, input_offset_ptr: *mut usize,
72                                   output_buf_ptr: *mut u8, output_size: usize, output_offset_ptr: *mut usize) -> DivansReturnCode {
73    let input_buf = slice::from_raw_parts(input_buf_ptr, input_size);
74    let output_buf = slice::from_raw_parts_mut(output_buf_ptr, output_size);
75    match input_offset_ptr.as_mut() {
76        None => return DIVANS_FAILURE,
77        Some(input_offset) => {
78            match output_offset_ptr.as_mut() {
79                None => return DIVANS_FAILURE,
80                Some(output_offset) => {
81                    match state_ptr.as_mut() {
82                        None => return DIVANS_FAILURE,
83                        Some(state_ref) => {
84                            return state_ref.compressor.encode(input_buf, input_offset, output_buf, output_offset, &state_ref.custom_allocator);
85                        }
86                    }
87                }
88            }
89        }
90    }
91}
92
93#[no_mangle]
94pub unsafe extern fn divans_encode_flush(state_ptr: *mut DivansCompressorState,
95                                         output_buf_ptr: *mut u8, output_size: usize, output_offset_ptr: *mut usize) -> DivansReturnCode {
96    let output_buf = slice::from_raw_parts_mut(output_buf_ptr, output_size);
97    match output_offset_ptr.as_mut() {
98        None => return DIVANS_FAILURE,
99        Some(output_offset) => {
100            match state_ptr.as_mut() {
101                None => return DIVANS_FAILURE,
102                Some(state_ref) => {
103                    return state_ref.compressor.flush(output_buf, output_offset, &state_ref.custom_allocator);
104                }
105            }
106        }
107    }
108}
109
110#[no_mangle]
111pub unsafe extern fn divans_compressor_malloc_u8(state_ptr: *mut DivansCompressorState, size: usize) -> *mut u8 {
112    if let Some(alloc_fn) = (*state_ptr).custom_allocator.alloc_func {
113            return core::mem::transmute::<*mut c_void, *mut u8>(alloc_fn((*state_ptr).custom_allocator.opaque, size));
114    } else {
115        return alloc_util::alloc_stdlib(size);
116    }
117}
118
119#[no_mangle]
120pub unsafe extern fn divans_compressor_free_u8(state_ptr: *mut DivansCompressorState, data: *mut u8, size: usize) {
121    if let Some(free_fn) = (*state_ptr).custom_allocator.free_func {
122        free_fn((*state_ptr).custom_allocator.opaque, core::mem::transmute::<*mut u8, *mut c_void>(data));
123    } else {
124        alloc_util::free_stdlib(data, size);
125    }
126}
127
128
129#[no_mangle]
130pub unsafe extern fn divans_compressor_malloc_usize(state_ptr: *mut DivansCompressorState, size: usize) -> *mut usize {
131    if let Some(alloc_fn) = (*state_ptr).custom_allocator.alloc_func {
132        return core::mem::transmute::<*mut c_void, *mut usize>(alloc_fn((*state_ptr).custom_allocator.opaque,
133                                                                         size * core::mem::size_of::<usize>()));
134    } else {
135        return alloc_util::alloc_stdlib(size);
136    }
137}
138#[no_mangle]
139pub unsafe extern fn divans_compressor_free_usize(state_ptr: *mut DivansCompressorState, data: *mut usize, size: usize) {
140    if let Some(free_fn) = (*state_ptr).custom_allocator.free_func {
141        free_fn((*state_ptr).custom_allocator.opaque, core::mem::transmute::<*mut usize, *mut c_void>(data));
142    } else {
143        alloc_util::free_stdlib(data, size);
144    }
145}
146
147
148#[cfg(not(feature="no-stdlib"))]
149unsafe fn free_compressor_no_custom_alloc(state_ptr: *mut DivansCompressorState) {
150    let _state = alloc_util::Box::from_raw(state_ptr);
151}
152
153#[cfg(feature="no-stdlib")]
154unsafe fn free_compressor_no_custom_alloc(_state_ptr: *mut DivansCompressorState) {
155    unreachable!();
156}
157
158#[no_mangle]
159pub unsafe extern fn divans_free_compressor(state_ptr: *mut DivansCompressorState) {
160    if let Some(_) = (*state_ptr).custom_allocator.alloc_func {
161        if let Some(free_fn) = (*state_ptr).custom_allocator.free_func {
162            let _to_free = core::ptr::read(state_ptr);
163            let ptr = core::mem::transmute::<*mut DivansCompressorState, *mut c_void>(state_ptr);
164            free_fn((*state_ptr).custom_allocator.opaque, ptr);
165        }
166    } else {
167        free_compressor_no_custom_alloc(state_ptr)
168    }
169}
170
171
172
173
174
175
176
177#[no_mangle]
178pub extern fn divans_new_decompressor() -> *mut DivansDecompressorState{
179    unsafe {
180        divans_new_decompressor_with_custom_alloc(CAllocator{
181            alloc_func:None,
182            free_func:None,
183            opaque: core::ptr::null_mut(),
184        }, 0, 1)
185    }
186}
187
188
189#[no_mangle]
190pub extern fn divans_new_serial_decompressor() -> *mut DivansDecompressorState{
191    unsafe {
192        divans_new_decompressor_with_custom_alloc(CAllocator{
193            alloc_func:None,
194            free_func:None,
195            opaque: core::ptr::null_mut(),
196        }, 0, 0)
197    }
198}
199
200
201#[cfg(feature="no-stdlib")]
202fn divans_new_decompressor_without_custom_alloc(_to_box: DivansDecompressorState) -> *mut DivansDecompressorState{
203    panic!("Must supply allocators if calling divans when compiled with features=no-stdlib");
204}
205
206#[cfg(not(feature="no-stdlib"))]
207fn divans_new_decompressor_without_custom_alloc(to_box: DivansDecompressorState) -> *mut DivansDecompressorState{
208    alloc_util::Box::<DivansDecompressorState>::into_raw(alloc_util::Box::<DivansDecompressorState>::new(to_box))
209}
210
211
212#[no_mangle]
213pub unsafe extern fn divans_new_decompressor_with_custom_alloc(allocators:CAllocator, skip_crc:u8, multithread: u8) -> *mut DivansDecompressorState{
214    let to_box = DivansDecompressorState{
215        custom_allocator:allocators.clone(),
216        decompressor:decompressor::DecompressorFactory::new(
217            SubclassableAllocator::<u8>::new(allocators.clone()),
218            SubclassableAllocator::<super::DefaultCDF16>::new(allocators.clone()),
219            SubclassableAllocator::<StaticCommand>::new(allocators.clone()),
220            skip_crc != 0,
221            multithread != 0,
222        ),
223    };
224    if let Some(alloc_fn) = allocators.alloc_func {
225        let ptr = alloc_fn(allocators.opaque, core::mem::size_of::<DivansDecompressorState>());
226        let divans_decompressor_state_ptr = core::mem::transmute::<*mut c_void, *mut DivansDecompressorState>(ptr);
227        core::ptr::write(divans_decompressor_state_ptr, to_box);
228        divans_decompressor_state_ptr
229    } else {
230        divans_new_decompressor_without_custom_alloc(to_box)
231    }
232}
233
234
235#[no_mangle]
236pub unsafe extern fn divans_decode(state_ptr: *mut DivansDecompressorState,
237                                   input_buf_ptr: *const u8, input_size: usize, input_offset_ptr: *mut usize,
238                                   output_buf_ptr: *mut u8, output_size: usize, output_offset_ptr: *mut usize) -> DivansReturnCode {
239    let input_buf = slice::from_raw_parts(input_buf_ptr, input_size);
240    let output_buf = slice::from_raw_parts_mut(output_buf_ptr, output_size);
241    match input_offset_ptr.as_mut() {
242        None => return DIVANS_FAILURE,
243        Some(input_offset) => {
244            match output_offset_ptr.as_mut() {
245                None => return DIVANS_FAILURE,
246                Some(output_offset) => {
247                    match state_ptr.as_mut() {
248                        None => return DIVANS_FAILURE,
249                        Some(state_ref) => {
250                            match state_ref.decompressor.decode(input_buf, input_offset, output_buf, output_offset) {
251                                ::interface::DivansResult::Success => return DIVANS_SUCCESS,
252                                ::interface::DivansResult::Failure(_) => return DIVANS_FAILURE,
253                                ::interface::DivansResult::NeedsMoreInput => return DIVANS_NEEDS_MORE_INPUT,
254                                ::interface::DivansResult::NeedsMoreOutput => return DIVANS_NEEDS_MORE_OUTPUT,
255                            }
256                        }
257                    }
258                }
259            }
260        }
261    }
262}
263
264#[cfg(not(feature="no-stdlib"))]
265unsafe fn free_decompressor_no_custom_alloc(state_ptr: *mut DivansDecompressorState) {
266    let _state = alloc_util::Box::from_raw(state_ptr);
267}
268
269#[cfg(feature="no-stdlib")]
270unsafe fn free_decompressor_no_custom_alloc(_state_ptr: *mut DivansDecompressorState) {
271    unreachable!();
272}
273
274
275#[no_mangle]
276pub unsafe extern fn divans_decompressor_malloc_u8(state_ptr: *mut DivansDecompressorState, size: usize) -> *mut u8 {
277    if let Some(alloc_fn) = (*state_ptr).custom_allocator.alloc_func {
278        return core::mem::transmute::<*mut c_void, *mut u8>(alloc_fn((*state_ptr).custom_allocator.opaque, size));
279    } else {
280        return alloc_util::alloc_stdlib(size);
281    }
282}
283
284#[no_mangle]
285pub unsafe extern fn divans_decompressor_free_u8(state_ptr: *mut DivansDecompressorState, data: *mut u8, size: usize) {
286    if let Some(free_fn) = (*state_ptr).custom_allocator.free_func {
287        free_fn((*state_ptr).custom_allocator.opaque, core::mem::transmute::<*mut u8, *mut c_void>(data));
288    } else {
289        alloc_util::free_stdlib(data, size);
290    }
291}
292
293#[no_mangle]
294pub unsafe extern fn divans_decompressor_malloc_usize(state_ptr: *mut DivansDecompressorState, size: usize) -> *mut usize {
295    if let Some(alloc_fn) = (*state_ptr).custom_allocator.alloc_func {
296        return core::mem::transmute::<*mut c_void, *mut usize>(alloc_fn((*state_ptr).custom_allocator.opaque,
297                                                                         size * core::mem::size_of::<usize>()));
298    } else {
299        return alloc_util::alloc_stdlib(size);
300    }
301}
302#[no_mangle]
303pub unsafe extern fn divans_decompressor_free_usize(state_ptr: *mut DivansDecompressorState, data: *mut usize, size: usize) {
304    if let Some(free_fn) = (*state_ptr).custom_allocator.free_func {
305        free_fn((*state_ptr).custom_allocator.opaque, core::mem::transmute::<*mut usize, *mut c_void>(data));
306    } else {
307        alloc_util::free_stdlib(data, size);
308    }
309}
310
311#[no_mangle]
312pub unsafe extern fn divans_free_decompressor(state_ptr: *mut DivansDecompressorState) {
313    if let Some(_) = (*state_ptr).custom_allocator.alloc_func {
314        if let Some(free_fn) = (*state_ptr).custom_allocator.free_func {
315            //(*state_ptr).drop();
316            let _to_free = core::ptr::read(state_ptr);
317            let ptr = core::mem::transmute::<*mut DivansDecompressorState, *mut c_void>(state_ptr);
318            free_fn((*state_ptr).custom_allocator.opaque, ptr);
319        }
320    } else {
321        free_decompressor_no_custom_alloc(state_ptr);
322    }
323}
324