1 // Copyright 2024 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 use super::types::*;
16 
17 use std::ffi::CStr;
18 use std::os::raw::c_char;
19 use std::os::raw::c_void;
20 
21 use crate::decoder::GenericIO;
22 use crate::internal_utils::io::DecoderFileIO;
23 use crate::internal_utils::io::DecoderRawIO;
24 use crate::*;
25 
26 #[repr(C)]
27 #[derive(Clone)]
28 pub struct avifROData {
29     pub data: *const u8,
30     pub size: usize,
31 }
32 
33 impl Default for avifROData {
default() -> Self34     fn default() -> Self {
35         avifROData {
36             data: std::ptr::null(),
37             size: 0,
38         }
39     }
40 }
41 
42 #[repr(C)]
43 #[derive(Clone, Debug)]
44 pub struct avifRWData {
45     pub data: *mut u8,
46     pub size: usize,
47 }
48 
49 impl Default for avifRWData {
default() -> Self50     fn default() -> Self {
51         avifRWData {
52             data: std::ptr::null_mut(),
53             size: 0,
54         }
55     }
56 }
57 
58 impl From<&Vec<u8>> for avifRWData {
from(v: &Vec<u8>) -> Self59     fn from(v: &Vec<u8>) -> Self {
60         avifRWData {
61             data: v.as_ptr() as *mut u8,
62             size: v.len(),
63         }
64     }
65 }
66 
67 #[no_mangle]
crabby_avifRWDataRealloc( raw: *mut avifRWData, newSize: usize, ) -> avifResult68 pub unsafe extern "C" fn crabby_avifRWDataRealloc(
69     raw: *mut avifRWData,
70     newSize: usize,
71 ) -> avifResult {
72     unsafe {
73         if (*raw).size == newSize {
74             return avifResult::Ok;
75         }
76         // Ok to use size as capacity here since we use reserve_exact.
77         let mut newData: Vec<u8> = Vec::new();
78         if newData.try_reserve_exact(newSize).is_err() {
79             return avifResult::OutOfMemory;
80         }
81         if !(*raw).data.is_null() {
82             let oldData = Box::from_raw(std::slice::from_raw_parts_mut((*raw).data, (*raw).size));
83             let sizeToCopy = std::cmp::min(newSize, oldData.len());
84             newData.extend_from_slice(&oldData[..sizeToCopy]);
85         }
86         newData.resize(newSize, 0);
87         let mut b = newData.into_boxed_slice();
88         (*raw).data = b.as_mut_ptr();
89         std::mem::forget(b);
90         (*raw).size = newSize;
91         avifResult::Ok
92     }
93 }
94 
95 #[no_mangle]
crabby_avifRWDataSet( raw: *mut avifRWData, data: *const u8, size: usize, ) -> avifResult96 pub unsafe extern "C" fn crabby_avifRWDataSet(
97     raw: *mut avifRWData,
98     data: *const u8,
99     size: usize,
100 ) -> avifResult {
101     unsafe {
102         if size != 0 {
103             let res = crabby_avifRWDataRealloc(raw, size);
104             if res != avifResult::Ok {
105                 return res;
106             }
107             std::ptr::copy_nonoverlapping(data, (*raw).data, size);
108         } else {
109             crabby_avifRWDataFree(raw);
110         }
111         avifResult::Ok
112     }
113 }
114 
115 #[no_mangle]
crabby_avifRWDataFree(raw: *mut avifRWData)116 pub unsafe extern "C" fn crabby_avifRWDataFree(raw: *mut avifRWData) {
117     unsafe {
118         if (*raw).data.is_null() {
119             return;
120         }
121         let _ = Box::from_raw(std::slice::from_raw_parts_mut((*raw).data, (*raw).size));
122     }
123 }
124 
125 pub type avifIODestroyFunc = unsafe extern "C" fn(io: *mut avifIO);
126 pub type avifIOReadFunc = unsafe extern "C" fn(
127     io: *mut avifIO,
128     readFlags: u32,
129     offset: u64,
130     size: usize,
131     out: *mut avifROData,
132 ) -> avifResult;
133 pub type avifIOWriteFunc = unsafe extern "C" fn(
134     io: *mut avifIO,
135     writeFlags: u32,
136     offset: u64,
137     data: *const u8,
138     size: usize,
139 ) -> avifResult;
140 
141 #[repr(C)]
142 #[derive(Clone, Copy)]
143 pub struct avifIO {
144     destroy: avifIODestroyFunc,
145     read: avifIOReadFunc,
146     write: avifIOWriteFunc,
147     sizeHint: u64,
148     persistent: avifBool,
149     data: *mut c_void,
150 }
151 
152 pub struct avifIOWrapper {
153     data: avifROData,
154     io: avifIO,
155 }
156 
157 impl avifIOWrapper {
create(io: avifIO) -> Self158     pub fn create(io: avifIO) -> Self {
159         Self {
160             io,
161             data: Default::default(),
162         }
163     }
164 }
165 
166 impl crate::decoder::IO for avifIOWrapper {
read(&mut self, offset: u64, size: usize) -> AvifResult<&[u8]>167     fn read(&mut self, offset: u64, size: usize) -> AvifResult<&[u8]> {
168         let res = unsafe {
169             (self.io.read)(
170                 &mut self.io as *mut avifIO,
171                 0,
172                 offset,
173                 size,
174                 &mut self.data as *mut avifROData,
175             )
176         };
177         if res != avifResult::Ok {
178             let err: AvifError = res.into();
179             return Err(err);
180         }
181         if self.data.size == 0 {
182             Ok(&[])
183         } else if self.data.data.is_null() {
184             Err(AvifError::UnknownError(
185                 "data pointer was null but size was not zero".into(),
186             ))
187         } else {
188             Ok(unsafe { std::slice::from_raw_parts(self.data.data, self.data.size) })
189         }
190     }
size_hint(&self) -> u64191     fn size_hint(&self) -> u64 {
192         self.io.sizeHint
193     }
persistent(&self) -> bool194     fn persistent(&self) -> bool {
195         self.io.persistent != 0
196     }
197 }
198 
199 pub struct avifCIOWrapper {
200     io: GenericIO,
201     buf: Vec<u8>,
202 }
203 
204 #[no_mangle]
cioDestroy(_io: *mut avifIO)205 unsafe extern "C" fn cioDestroy(_io: *mut avifIO) {}
206 
207 #[no_mangle]
cioRead( io: *mut avifIO, _readFlags: u32, offset: u64, size: usize, out: *mut avifROData, ) -> avifResult208 unsafe extern "C" fn cioRead(
209     io: *mut avifIO,
210     _readFlags: u32,
211     offset: u64,
212     size: usize,
213     out: *mut avifROData,
214 ) -> avifResult {
215     unsafe {
216         if io.is_null() {
217             return avifResult::IoError;
218         }
219         let cio = (*io).data as *mut avifCIOWrapper;
220         match (*cio).io.read(offset, size) {
221             Ok(data) => {
222                 (*cio).buf.clear();
223                 if (*cio).buf.try_reserve_exact(data.len()).is_err() {
224                     return avifResult::OutOfMemory;
225                 }
226                 (*cio).buf.extend_from_slice(data);
227             }
228             Err(_) => return avifResult::IoError,
229         }
230         (*out).data = (*cio).buf.as_ptr();
231         (*out).size = (*cio).buf.len();
232         avifResult::Ok
233     }
234 }
235 
236 #[no_mangle]
cioWrite( _io: *mut avifIO, _writeFlags: u32, _offset: u64, _data: *const u8, _size: usize, ) -> avifResult237 unsafe extern "C" fn cioWrite(
238     _io: *mut avifIO,
239     _writeFlags: u32,
240     _offset: u64,
241     _data: *const u8,
242     _size: usize,
243 ) -> avifResult {
244     avifResult::Ok
245 }
246 
247 #[no_mangle]
crabby_avifIOCreateMemoryReader( data: *const u8, size: usize, ) -> *mut avifIO248 pub unsafe extern "C" fn crabby_avifIOCreateMemoryReader(
249     data: *const u8,
250     size: usize,
251 ) -> *mut avifIO {
252     let cio = Box::new(avifCIOWrapper {
253         io: Box::new(unsafe { DecoderRawIO::create(data, size) }),
254         buf: Vec::new(),
255     });
256     let io = Box::new(avifIO {
257         destroy: cioDestroy,
258         read: cioRead,
259         write: cioWrite,
260         sizeHint: size as u64,
261         persistent: 0,
262         data: Box::into_raw(cio) as *mut c_void,
263     });
264     Box::into_raw(io)
265 }
266 
267 #[no_mangle]
crabby_avifIOCreateFileReader(filename: *const c_char) -> *mut avifIO268 pub unsafe extern "C" fn crabby_avifIOCreateFileReader(filename: *const c_char) -> *mut avifIO {
269     let filename = unsafe { String::from(CStr::from_ptr(filename).to_str().unwrap_or("")) };
270     let file_io = match DecoderFileIO::create(&filename) {
271         Ok(x) => x,
272         Err(_) => return std::ptr::null_mut(),
273     };
274     let cio = Box::new(avifCIOWrapper {
275         io: Box::new(file_io),
276         buf: Vec::new(),
277     });
278     let io = Box::new(avifIO {
279         destroy: cioDestroy,
280         read: cioRead,
281         write: cioWrite,
282         sizeHint: cio.io.size_hint(),
283         persistent: 0,
284         data: Box::into_raw(cio) as *mut c_void,
285     });
286     Box::into_raw(io)
287 }
288 
289 #[no_mangle]
crabby_avifIODestroy(io: *mut avifIO)290 pub unsafe extern "C" fn crabby_avifIODestroy(io: *mut avifIO) {
291     unsafe {
292         let _ = Box::from_raw((*io).data as *mut avifCIOWrapper);
293         let _ = Box::from_raw(io);
294     }
295 }
296