fm_plugin/ffi/
binary_data.rs

1use super::*;
2use std::convert::TryFrom;
3use std::fmt;
4use std::mem::ManuallyDrop;
5
6#[repr(C)]
7#[derive(Debug, Copy, Clone)]
8pub struct fmx_BinaryData {
9    _address: u8,
10}
11
12#[cfg_attr(target_os = "macos", link(kind = "framework", name = "FMWrapper"))]
13#[cfg_attr(target_os = "windows", link(kind = "static", name = "FMWrapper"))]
14#[cfg_attr(target_os = "linux", link(kind = "dylib", name = "FMWrapper"))]
15extern "C" {
16    fn FM_BinaryData_Constructor1(_x: *mut fmx__fmxcpt) -> *mut fmx_BinaryData;
17    fn FM_BinaryData_Constructor2(
18        sourceData: *const fmx_BinaryData,
19        _x: *mut fmx__fmxcpt,
20    ) -> *mut fmx_BinaryData;
21
22    fn FM_BinaryData_Constructor3(
23        name: *const fmx_Text,
24        amount: u32,
25        buffer: *mut i8,
26        _x: *mut fmx__fmxcpt,
27    ) -> *mut fmx_BinaryData;
28
29    #[allow(dead_code)]
30    fn FM_BinaryData_Constructor4(
31        name: *const fmx_Text,
32        context: *mut u32,
33        _x: *mut fmx__fmxcpt,
34    ) -> *mut fmx_BinaryData;
35
36    #[allow(dead_code)]
37    fn FM_BinaryData_operatorAS(
38        _self: *mut fmx_BinaryData,
39        source: *const fmx_BinaryData,
40        _x: *mut fmx__fmxcpt,
41    ) -> *mut fmx_BinaryData;
42
43    fn FM_BinaryData_operatorEQ(
44        _self: *const fmx_BinaryData,
45        compareData: *const fmx_BinaryData,
46        _x: *mut fmx__fmxcpt,
47    ) -> bool;
48
49    fn FM_BinaryData_operatorNE(
50        _self: *const fmx_BinaryData,
51        compareData: *const fmx_BinaryData,
52        _x: *mut fmx__fmxcpt,
53    ) -> bool;
54
55    fn FM_BinaryData_GetCount(_self: *const fmx_BinaryData, _x: *mut fmx__fmxcpt) -> i32;
56
57    fn FM_BinaryData_GetIndex(
58        _self: *const fmx_BinaryData,
59        dataType: *const fmx_QuadChar,
60        _x: *mut fmx__fmxcpt,
61    ) -> i32;
62
63    fn FM_BinaryData_GetTotalSize(_self: *const fmx_BinaryData, _x: *mut fmx__fmxcpt) -> u32;
64
65    fn FM_BinaryData_GetType(
66        _self: *const fmx_BinaryData,
67        index: i32,
68        dataType: *mut fmx_QuadChar,
69        _x: *mut fmx__fmxcpt,
70    );
71
72    fn FM_BinaryData_GetSize(_self: *const fmx_BinaryData, index: i32, _x: *mut fmx__fmxcpt)
73        -> u32;
74
75    fn FM_BinaryData_GetData(
76        _self: *const fmx_BinaryData,
77        index: i32,
78        offset: u32,
79        amount: u32,
80        buffer: *mut i8,
81        _x: *mut fmx__fmxcpt,
82    ) -> FMError;
83
84    fn FM_BinaryData_Add(
85        _self: *mut fmx_BinaryData,
86        dataType: *const fmx_QuadChar,
87        amount: u32,
88        buffer: *mut i8,
89        _x: *mut fmx__fmxcpt,
90    ) -> FMError;
91
92    fn FM_BinaryData_Remove(
93        _self: *mut fmx_BinaryData,
94        dataType: *const fmx_QuadChar,
95        _x: *mut fmx__fmxcpt,
96    ) -> bool;
97
98    fn FM_BinaryData_RemoveAll(_self: *mut fmx_BinaryData, _x: *mut fmx__fmxcpt);
99    fn FM_BinaryData_Delete(_self: *mut fmx_BinaryData, _x: *mut fmx__fmxcpt);
100
101    fn FM_BinaryData_GetFNAMData(
102        _self: *const fmx_BinaryData,
103        filepathlist: *mut fmx_Text,
104        _x: *mut fmx__fmxcpt,
105    ) -> FMError;
106
107    fn FM_BinaryData_AddFNAMData(
108        _self: *mut fmx_BinaryData,
109        filepathlist: *const fmx_Text,
110        _x: *mut fmx__fmxcpt,
111    ) -> FMError;
112
113    fn FM_BinaryData_GetSIZEData(
114        _self: *const fmx_BinaryData,
115        width: *mut i16,
116        height: *mut i16,
117        _x: *mut fmx__fmxcpt,
118    ) -> FMError;
119
120    fn FM_BinaryData_AddSIZEData(
121        _self: *mut fmx_BinaryData,
122        width: i16,
123        height: i16,
124        _x: *mut fmx__fmxcpt,
125    ) -> FMError;
126
127    fn FM_BinaryData_AddBegin(
128        _self: *mut fmx_BinaryData,
129        dataType: *const fmx_QuadChar,
130        context: *mut u32,
131        _x: *mut fmx__fmxcpt,
132    ) -> FMError;
133
134    fn FM_BinaryData_AddAppend(
135        _self: *mut fmx_BinaryData,
136        context: u32,
137        amount: u32,
138        buffer: *mut i8,
139        _x: *mut fmx__fmxcpt,
140    ) -> FMError;
141
142    fn FM_BinaryData_AddFinish(
143        _self: *mut fmx_BinaryData,
144        context: u32,
145        _x: *mut fmx__fmxcpt,
146    ) -> FMError;
147}
148
149#[derive(Eq)]
150pub struct BinaryData {
151    pub(crate) ptr: *mut fmx_BinaryData,
152    drop: bool,
153}
154
155impl BinaryData {
156    pub fn new() -> Self {
157        let mut _x = fmx__fmxcpt::new();
158        let ptr = unsafe { FM_BinaryData_Constructor1(&mut _x) };
159        _x.check();
160        Self { ptr, drop: true }
161    }
162
163    pub fn to_owned(&self) -> Self {
164        let mut _x = fmx__fmxcpt::new();
165        let ptr = unsafe { FM_BinaryData_Constructor2(self.ptr, &mut _x) };
166        _x.check();
167        Self { ptr, drop: true }
168    }
169
170    pub fn from_buffer<T: ToText>(name: T, buffer: Vec<u8>) -> Self {
171        let mut _x = fmx__fmxcpt::new();
172        let name = name.to_text();
173        let buffer_size = buffer.len() as u32;
174        let mut buffer = ManuallyDrop::new(buffer);
175        let buffer_ptr = buffer.as_mut_ptr();
176
177        let ptr = unsafe {
178            FM_BinaryData_Constructor3(name.ptr, buffer_size as u32, buffer_ptr as *mut i8, &mut _x)
179        };
180        unsafe { ManuallyDrop::drop(&mut buffer) };
181        _x.check();
182        Self { ptr, drop: true }
183    }
184
185    pub fn from_ptr(ptr: *const fmx_BinaryData) -> Self {
186        Self {
187            ptr: ptr as *mut fmx_BinaryData,
188            drop: false,
189        }
190    }
191
192    pub fn get_stream_count(&self) -> i32 {
193        let mut _x = fmx__fmxcpt::new();
194        let count = unsafe { FM_BinaryData_GetCount(self.ptr, &mut _x) };
195        _x.check();
196        count
197    }
198
199    pub fn get_stream_index(&self, stream_type: BinaryStreamType) -> i32 {
200        let mut _x = fmx__fmxcpt::new();
201        let quad = QuadChar::from(stream_type);
202        let index = unsafe { FM_BinaryData_GetIndex(self.ptr, quad.ptr, &mut _x) };
203        _x.check();
204        index
205    }
206
207    pub fn total_size(&self) -> u32 {
208        let mut _x = fmx__fmxcpt::new();
209        let size = unsafe { FM_BinaryData_GetTotalSize(self.ptr, &mut _x) };
210        _x.check();
211        size
212    }
213
214    pub fn get_size(&self, index: i32) -> u32 {
215        let mut _x = fmx__fmxcpt::new();
216        let size = unsafe { FM_BinaryData_GetSize(self.ptr, index, &mut _x) };
217        _x.check();
218        size
219    }
220
221    pub fn get_data(&self, index: i32, offset: u32, amount: usize) -> Vec<u8> {
222        let buffer = Vec::with_capacity(amount);
223        let mut buffer = ManuallyDrop::new(buffer);
224        let ptr = buffer.as_mut_ptr();
225
226        let mut _x = fmx__fmxcpt::new();
227        let error =
228            unsafe { FM_BinaryData_GetData(self.ptr, index, offset, amount as u32, ptr, &mut _x) };
229        _x.check();
230        if error != FMError::NoError {
231            panic!();
232        }
233        unsafe { Vec::from_raw_parts(ptr as *mut u8, amount, amount) }
234    }
235
236    pub fn get_type(&self, index: i32) -> BinaryStreamType {
237        let mut _x = fmx__fmxcpt::new();
238        let quad = QuadChar::empty();
239        unsafe { FM_BinaryData_GetType(self.ptr, index, quad.ptr, &mut _x) };
240        _x.check();
241        BinaryStreamType::from(quad)
242    }
243
244    pub fn add_stream(&self, stream_type: BinaryStreamType, buffer: &mut Vec<u8>) {
245        let mut _x = fmx__fmxcpt::new();
246        let quad = QuadChar::from(stream_type);
247        let size = buffer.len() as u32;
248        let mut buffer = ManuallyDrop::new(buffer);
249        let buffer_ptr = buffer.as_mut_ptr();
250        let error =
251            unsafe { FM_BinaryData_Add(self.ptr, quad.ptr, size, buffer_ptr as *mut i8, &mut _x) };
252        unsafe { ManuallyDrop::drop(&mut buffer) };
253        _x.check();
254        if error != FMError::NoError {
255            panic!();
256        }
257    }
258
259    pub fn remove_stream(&self, stream_type: BinaryStreamType) {
260        let mut _x = fmx__fmxcpt::new();
261        let quad = QuadChar::from(stream_type);
262        let success = unsafe { FM_BinaryData_Remove(self.ptr, quad.ptr, &mut _x) };
263        _x.check();
264        if !success {
265            panic!();
266        }
267    }
268
269    pub fn remove_all(&self) {
270        let mut _x = fmx__fmxcpt::new();
271        unsafe { FM_BinaryData_RemoveAll(self.ptr, &mut _x) };
272        _x.check();
273    }
274
275    pub fn start_stream(&self, stream_type: BinaryStreamType) -> u32 {
276        let mut _x = fmx__fmxcpt::new();
277        let quad = QuadChar::from(stream_type);
278        let mut context = 0;
279        let error = unsafe { FM_BinaryData_AddBegin(self.ptr, quad.ptr, &mut context, &mut _x) };
280        _x.check();
281        if error != FMError::NoError {
282            panic!();
283        }
284        context
285    }
286
287    pub fn append_stream(&self, stream_id: u32, buffer: &mut Vec<u8>) {
288        let mut _x = fmx__fmxcpt::new();
289        let size = buffer.len() as u32;
290        let mut buffer = ManuallyDrop::new(buffer);
291        let buffer_ptr = buffer.as_mut_ptr();
292        let error = unsafe {
293            FM_BinaryData_AddAppend(self.ptr, stream_id, size, buffer_ptr as *mut i8, &mut _x)
294        };
295        unsafe { ManuallyDrop::drop(&mut buffer) };
296        _x.check();
297        if error != FMError::NoError {
298            panic!();
299        }
300    }
301
302    pub fn end_stream(&self, stream_id: u32) {
303        let mut _x = fmx__fmxcpt::new();
304        let error = unsafe { FM_BinaryData_AddFinish(self.ptr, stream_id, &mut _x) };
305        _x.check();
306        if error != FMError::NoError {
307            panic!();
308        }
309    }
310
311    pub fn get_file_names(&self) -> Text {
312        let mut _x = fmx__fmxcpt::new();
313        let file_paths = Text::new();
314        let error = unsafe { FM_BinaryData_GetFNAMData(self.ptr, file_paths.ptr, &mut _x) };
315        _x.check();
316        if error != FMError::NoError {
317            panic!();
318        }
319        file_paths
320    }
321
322    pub fn add_file_paths<T: ToText>(&self, file_paths: T) {
323        let mut _x = fmx__fmxcpt::new();
324        let f_paths = file_paths.to_text();
325        let error = unsafe { FM_BinaryData_AddFNAMData(self.ptr, f_paths.ptr, &mut _x) };
326        _x.check();
327        if error != FMError::NoError {
328            panic!();
329        }
330    }
331
332    pub fn get_dimensions(&self) -> (i16, i16) {
333        let mut _x = fmx__fmxcpt::new();
334        let mut height = 0;
335        let mut width = 0;
336        let error =
337            unsafe { FM_BinaryData_GetSIZEData(self.ptr, &mut width, &mut height, &mut _x) };
338        _x.check();
339        if error != FMError::NoError {
340            panic!();
341        }
342        (width, height)
343    }
344
345    pub fn set_dimensions(&self, height: i16, width: i16) {
346        let mut _x = fmx__fmxcpt::new();
347        let error = unsafe { FM_BinaryData_AddSIZEData(self.ptr, width, height, &mut _x) };
348        _x.check();
349        if error != FMError::NoError {
350            panic!();
351        }
352    }
353}
354
355impl Drop for BinaryData {
356    fn drop(&mut self) {
357        if self.drop {
358            let mut _x = fmx__fmxcpt::new();
359            unsafe { FM_BinaryData_Delete(self.ptr, &mut _x) };
360            _x.check();
361        }
362    }
363}
364
365impl Default for BinaryData {
366    fn default() -> Self {
367        Self::new()
368    }
369}
370
371#[derive(Debug, PartialEq)]
372pub enum BinaryStreamType {
373    FNAM,
374    JPEG,
375    GIF,
376    EPS,
377    META,
378    PNG,
379    BMP,
380    PDF,
381    FILE,
382    ZLIB,
383    FORK,
384    SND,
385    MAIN,
386    SIZE,
387    Other(String),
388}
389
390impl From<BinaryStreamType> for QuadChar {
391    fn from(stream_type: BinaryStreamType) -> QuadChar {
392        use BinaryStreamType::*;
393        match stream_type {
394            FNAM => QuadChar::new(b"FNAM"),
395            JPEG => QuadChar::new(b"JPEG"),
396            GIF => QuadChar::new(b"GIFf"),
397            EPS => QuadChar::new(b"EPSf"),
398            META => QuadChar::new(b"META"),
399            PNG => QuadChar::new(b"PNGf"),
400            BMP => QuadChar::new(b"BMPf"),
401            PDF => QuadChar::new(b"PDF "),
402            SIZE => QuadChar::new(b"SIZE"),
403            FILE => QuadChar::new(b"FILE"),
404            ZLIB => QuadChar::new(b"ZLIB"),
405            FORK => QuadChar::new(b"FORK"),
406            SND => QuadChar::new(b"snd "),
407            MAIN => QuadChar::new(b"MAIN"),
408            Other(txt) => {
409                let slice = txt.as_bytes();
410                let bytes = <&[u8; 4]>::try_from(&slice[..4]).unwrap();
411                QuadChar::new(bytes)
412            }
413        }
414    }
415}
416
417impl From<QuadChar> for BinaryStreamType {
418    fn from(quad: QuadChar) -> BinaryStreamType {
419        let txt = quad.to_string();
420        use BinaryStreamType::*;
421        match txt.as_ref() {
422            "FNAM" => FNAM,
423            "JPEG" => JPEG,
424            "GIFf" => GIF,
425            "EPSf" => EPS,
426            "META" => META,
427            "PNGf" => PNG,
428            "BMPf" => BMP,
429            "PDF " => PDF,
430            "SIZE" => SIZE,
431            "FILE" => FILE,
432            "ZLIB" => ZLIB,
433            "FORK" => FORK,
434            "snd " => SND,
435            "MAIN" => MAIN,
436            t => Other(t.to_string()),
437        }
438    }
439}
440
441impl PartialEq for BinaryData {
442    fn eq(&self, other: &BinaryData) -> bool {
443        let mut _x = fmx__fmxcpt::new();
444        let result = unsafe { FM_BinaryData_operatorEQ(self.ptr, other.ptr, &mut _x) };
445        _x.check();
446        result
447    }
448
449    #[allow(clippy::partialeq_ne_impl)]
450    fn ne(&self, other: &BinaryData) -> bool {
451        let mut _x = fmx__fmxcpt::new();
452        let result = unsafe { FM_BinaryData_operatorNE(self.ptr, other.ptr, &mut _x) };
453        _x.check();
454        result
455    }
456}
457
458impl fmt::Display for BinaryStreamType {
459    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
460        write!(f, "{:?}", self)
461    }
462}
463
464impl ToText for BinaryStreamType {
465    fn to_text(self) -> Text {
466        self.to_string().to_text()
467    }
468}