• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
167     #[cfg_attr(feature = "disable_cfi", no_sanitize(cfi))]
read(&mut self, offset: u64, size: usize) -> AvifResult<&[u8]>168     fn read(&mut self, offset: u64, size: usize) -> AvifResult<&[u8]> {
169         let res = unsafe {
170             (self.io.read)(
171                 &mut self.io as *mut avifIO,
172                 0,
173                 offset,
174                 size,
175                 &mut self.data as *mut avifROData,
176             )
177         };
178         if res != avifResult::Ok {
179             let err: AvifError = res.into();
180             return Err(err);
181         }
182         if self.data.size == 0 {
183             Ok(&[])
184         } else if self.data.data.is_null() {
185             Err(AvifError::UnknownError(
186                 "data pointer was null but size was not zero".into(),
187             ))
188         } else {
189             Ok(unsafe { std::slice::from_raw_parts(self.data.data, self.data.size) })
190         }
191     }
size_hint(&self) -> u64192     fn size_hint(&self) -> u64 {
193         self.io.sizeHint
194     }
persistent(&self) -> bool195     fn persistent(&self) -> bool {
196         self.io.persistent != 0
197     }
198 }
199 
200 pub struct avifCIOWrapper {
201     io: GenericIO,
202     buf: Vec<u8>,
203 }
204 
205 #[no_mangle]
cioDestroy(_io: *mut avifIO)206 unsafe extern "C" fn cioDestroy(_io: *mut avifIO) {}
207 
208 #[no_mangle]
cioRead( io: *mut avifIO, _readFlags: u32, offset: u64, size: usize, out: *mut avifROData, ) -> avifResult209 unsafe extern "C" fn cioRead(
210     io: *mut avifIO,
211     _readFlags: u32,
212     offset: u64,
213     size: usize,
214     out: *mut avifROData,
215 ) -> avifResult {
216     unsafe {
217         if io.is_null() {
218             return avifResult::IoError;
219         }
220         let cio = (*io).data as *mut avifCIOWrapper;
221         match (*cio).io.read(offset, size) {
222             Ok(data) => {
223                 (*cio).buf.clear();
224                 if (*cio).buf.try_reserve_exact(data.len()).is_err() {
225                     return avifResult::OutOfMemory;
226                 }
227                 (*cio).buf.extend_from_slice(data);
228             }
229             Err(_) => return avifResult::IoError,
230         }
231         (*out).data = (*cio).buf.as_ptr();
232         (*out).size = (*cio).buf.len();
233         avifResult::Ok
234     }
235 }
236 
237 #[no_mangle]
cioWrite( _io: *mut avifIO, _writeFlags: u32, _offset: u64, _data: *const u8, _size: usize, ) -> avifResult238 unsafe extern "C" fn cioWrite(
239     _io: *mut avifIO,
240     _writeFlags: u32,
241     _offset: u64,
242     _data: *const u8,
243     _size: usize,
244 ) -> avifResult {
245     avifResult::Ok
246 }
247 
248 #[no_mangle]
crabby_avifIOCreateMemoryReader( data: *const u8, size: usize, ) -> *mut avifIO249 pub unsafe extern "C" fn crabby_avifIOCreateMemoryReader(
250     data: *const u8,
251     size: usize,
252 ) -> *mut avifIO {
253     let cio = Box::new(avifCIOWrapper {
254         io: Box::new(unsafe { DecoderRawIO::create(data, size) }),
255         buf: Vec::new(),
256     });
257     let io = Box::new(avifIO {
258         destroy: cioDestroy,
259         read: cioRead,
260         write: cioWrite,
261         sizeHint: size as u64,
262         persistent: 0,
263         data: Box::into_raw(cio) as *mut c_void,
264     });
265     Box::into_raw(io)
266 }
267 
268 #[no_mangle]
crabby_avifIOCreateFileReader(filename: *const c_char) -> *mut avifIO269 pub unsafe extern "C" fn crabby_avifIOCreateFileReader(filename: *const c_char) -> *mut avifIO {
270     let filename = unsafe { String::from(CStr::from_ptr(filename).to_str().unwrap_or("")) };
271     let file_io = match DecoderFileIO::create(&filename) {
272         Ok(x) => x,
273         Err(_) => return std::ptr::null_mut(),
274     };
275     let cio = Box::new(avifCIOWrapper {
276         io: Box::new(file_io),
277         buf: Vec::new(),
278     });
279     let io = Box::new(avifIO {
280         destroy: cioDestroy,
281         read: cioRead,
282         write: cioWrite,
283         sizeHint: cio.io.size_hint(),
284         persistent: 0,
285         data: Box::into_raw(cio) as *mut c_void,
286     });
287     Box::into_raw(io)
288 }
289 
290 #[no_mangle]
crabby_avifIODestroy(io: *mut avifIO)291 pub unsafe extern "C" fn crabby_avifIODestroy(io: *mut avifIO) {
292     unsafe {
293         let _ = Box::from_raw((*io).data as *mut avifCIOWrapper);
294         let _ = Box::from_raw(io);
295     }
296 }
297