1use std::io::{BufReader, BufWriter, Error as IoError, Read, Seek, SeekFrom, Write};
41
42#[cfg(not(feature = "std"))]
43use alloc::boxed::Box;
44
45#[cfg(feature = "file-io")]
46use std::{fs::File, path::Path};
47
48use super::event::*;
49use super::openjpeg::*;
50
51extern "C" {
52 fn memcpy(
53 _: *mut core::ffi::c_void,
54 _: *const core::ffi::c_void,
55 _: usize,
56 ) -> *mut core::ffi::c_void;
57}
58
59pub(crate) trait ReadSeek: Read + Seek {}
60
61impl<R: Read + Seek> ReadSeek for R {}
62
63pub(crate) trait WriteSeek: Write + Seek {}
64
65impl<R: Write + Seek> WriteSeek for R {}
66
67pub(crate) struct CustomStream {
68 pub m_user_data: *mut core::ffi::c_void,
69 pub m_free_user_data_fn: opj_stream_free_user_data_fn,
70 pub m_read_fn: opj_stream_read_fn,
71 pub m_write_fn: opj_stream_write_fn,
72 pub m_skip_fn: opj_stream_skip_fn,
73 pub m_seek_fn: opj_stream_seek_fn,
74 pub m_byte_offset: OPJ_OFF_T,
75}
76
77impl CustomStream {
78 pub fn set_read(&mut self, read: opj_stream_read_fn) {
79 self.m_read_fn = read;
80 }
81
82 pub fn set_write(&mut self, write: opj_stream_write_fn) {
83 self.m_write_fn = write;
84 }
85
86 pub fn set_skip(&mut self, skip: opj_stream_skip_fn) {
87 self.m_skip_fn = skip;
88 }
89
90 pub fn set_seek(&mut self, seek: opj_stream_seek_fn) {
91 self.m_seek_fn = seek;
92 }
93
94 pub fn set_user_data(
95 &mut self,
96 data: *mut core::ffi::c_void,
97 free: opj_stream_free_user_data_fn,
98 ) {
99 self.m_user_data = data;
100 self.m_free_user_data_fn = free;
101 }
102
103 pub fn has_seek(&self) -> bool {
104 self.m_seek_fn.is_some()
105 }
106}
107
108impl Drop for CustomStream {
109 fn drop(&mut self) {
110 if let Some(free) = self.m_free_user_data_fn {
111 unsafe {
112 free(self.m_user_data);
113 }
114 }
115 }
116}
117
118impl Read for CustomStream {
119 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
120 let len = buf.len();
121 let res = if let Some(read) = &self.m_read_fn {
122 unsafe {
123 read(
124 buf.as_mut_ptr() as *mut core::ffi::c_void,
125 len,
126 self.m_user_data,
127 ) as isize
128 }
129 } else {
130 return Err(IoError::other("Custom stream doesn't have a read function"));
131 };
132 if res >= 0 {
133 self.m_byte_offset += res as i64;
134 Ok(res as usize)
135 } else {
136 Err(IoError::other("read failed"))
137 }
138 }
139}
140
141impl Write for CustomStream {
142 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
143 let len = buf.len();
144 let res = if let Some(write) = &self.m_write_fn {
145 unsafe {
146 write(
147 buf.as_ptr() as *mut core::ffi::c_void,
148 len,
149 self.m_user_data,
150 ) as isize
151 }
152 } else {
153 return Err(IoError::other(
154 "Custom stream doesn't have a write function",
155 ));
156 };
157 if res >= 0 {
158 self.m_byte_offset += res as i64;
159 Ok(res as usize)
160 } else {
161 Err(IoError::other("write failed"))
162 }
163 }
164
165 fn flush(&mut self) -> std::io::Result<()> {
166 Ok(())
167 }
168}
169
170impl Seek for CustomStream {
171 fn seek(&mut self, pos: SeekFrom) -> std::io::Result<u64> {
172 log::trace!("-- CustomStream.seek({pos:?})");
173 match pos {
174 SeekFrom::Start(offset) => {
175 let res = if let Some(seek) = &self.m_seek_fn {
176 unsafe { seek(offset as i64, self.m_user_data) }
177 } else {
178 return Err(IoError::other("Custom stream doesn't have a seek function"));
179 };
180 if res != 0 {
181 self.m_byte_offset = offset as i64;
182 Ok(offset)
183 } else {
184 Err(IoError::other("seek failed"))
185 }
186 }
187 SeekFrom::Current(offset) => {
188 let res = if let Some(skip) = &self.m_skip_fn {
189 unsafe { skip(offset, self.m_user_data) }
190 } else {
191 return Err(IoError::other("Custom stream doesn't have a skip function"));
192 };
193 if res != -1 {
194 self.m_byte_offset += offset;
195 Ok(self.m_byte_offset as u64)
196 } else {
197 Err(IoError::other("skip failed"))
198 }
199 }
200 SeekFrom::End(_offset) => Err(IoError::other("Unsupported seek from end")),
201 }
202 }
203}
204
205pub(crate) enum StreamInner {
206 Reader(BufReader<Box<dyn ReadSeek>>),
207 Writer(BufWriter<Box<dyn WriteSeek>>),
208 CustomReader(BufReader<CustomStream>),
209 CustomWriter(BufWriter<CustomStream>),
210}
211
212impl StreamInner {
213 pub fn new_reader<R: Read + Seek + 'static>(capacity: usize, reader: R) -> Self {
214 Self::Reader(BufReader::with_capacity(capacity, Box::new(reader)))
215 }
216
217 pub fn new_writer<R: Write + Seek + 'static>(capacity: usize, writer: R) -> Self {
218 Self::Writer(BufWriter::with_capacity(capacity, Box::new(writer)))
219 }
220
221 pub fn new_custom_reader(capacity: usize, reader: CustomStream) -> Self {
222 Self::CustomReader(BufReader::with_capacity(capacity, reader))
223 }
224
225 pub fn new_custom_writer(capacity: usize, writer: CustomStream) -> Self {
226 Self::CustomWriter(BufWriter::with_capacity(capacity, writer))
227 }
228
229 pub fn seek_relative(&mut self, offset: i64) -> std::io::Result<()> {
230 match self {
231 StreamInner::Reader(reader) => reader.seek_relative(offset),
232 StreamInner::Writer(writer) => {
233 writer.seek(SeekFrom::Current(offset))?;
234 Ok(())
235 }
236 StreamInner::CustomReader(reader) => reader.seek_relative(offset),
237 StreamInner::CustomWriter(writer) => {
238 writer.seek(SeekFrom::Current(offset))?;
239 Ok(())
240 }
241 }
242 }
243
244 pub fn has_seek(&self) -> bool {
245 match self {
246 StreamInner::Reader(_) => true,
247 StreamInner::Writer(_) => true,
248 StreamInner::CustomReader(b) => b.get_ref().has_seek(),
249 StreamInner::CustomWriter(b) => b.get_ref().has_seek(),
250 }
251 }
252}
253
254impl Read for StreamInner {
255 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
256 match self {
257 StreamInner::Reader(reader) => reader.read(buf),
258 StreamInner::CustomReader(reader) => reader.read(buf),
259 _ => Err(IoError::other("Can't read from output stream.")),
260 }
261 }
262}
263
264impl Write for StreamInner {
265 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
266 match self {
267 StreamInner::Writer(writer) => writer.write(buf),
268 StreamInner::CustomWriter(writer) => writer.write(buf),
269 _ => Err(IoError::other("Can't write to input stream.")),
270 }
271 }
272
273 fn flush(&mut self) -> std::io::Result<()> {
274 match self {
275 StreamInner::Writer(writer) => writer.flush(),
276 StreamInner::CustomWriter(writer) => writer.flush(),
277 _ => Err(IoError::other("Can't flush input stream.")),
278 }
279 }
280}
281
282impl Seek for StreamInner {
283 fn seek(&mut self, pos: SeekFrom) -> std::io::Result<u64> {
284 match self {
285 StreamInner::Reader(reader) => reader.seek(pos),
286 StreamInner::Writer(writer) => writer.seek(pos),
287 StreamInner::CustomReader(reader) => reader.seek(pos),
288 StreamInner::CustomWriter(writer) => writer.seek(pos),
289 }
290 }
291}
292
293impl Stream {
294 #[cfg(feature = "file-io")]
295 pub fn new_file<P: AsRef<Path>>(
296 path: P,
297 buffer_size: usize,
298 is_input: bool,
299 ) -> std::io::Result<Self> {
300 if is_input {
301 let file = File::open(&path)?;
302 let m_stream_length = file.metadata().map(|m| m.len())?;
303 Ok(Self {
304 m_inner: super::stream::StreamInner::new_reader(buffer_size, file),
305 m_stream_length,
306 m_byte_offset: 0,
307 })
308 } else {
309 let file = File::create(&path)?;
310 Ok(Self {
311 m_inner: super::stream::StreamInner::new_writer(buffer_size, file),
312 m_stream_length: 0,
313 m_byte_offset: 0,
314 })
315 }
316 }
317
318 pub fn new_custom(buffer_size: usize, is_input: bool) -> Self {
319 let custom = CustomStream {
320 m_user_data: core::ptr::null_mut(),
321 m_free_user_data_fn: None,
322 m_read_fn: None,
323 m_write_fn: None,
324 m_skip_fn: None,
325 m_seek_fn: None,
326 m_byte_offset: 0,
327 };
328 let mut l_stream = Self {
329 m_inner: if is_input {
330 StreamInner::CustomReader(BufReader::with_capacity(buffer_size, custom))
331 } else {
332 StreamInner::CustomWriter(BufWriter::with_capacity(buffer_size, custom))
333 },
334 m_stream_length: Default::default(),
335 m_byte_offset: 0,
336 };
337 l_stream
338 }
339
340 pub fn is_input(&self) -> bool {
341 match self.m_inner {
342 StreamInner::Reader(_) => true,
343 StreamInner::CustomReader(_) => true,
344 StreamInner::Writer(_) => false,
345 StreamInner::CustomWriter(_) => false,
346 }
347 }
348
349 pub(crate) fn as_custom(&mut self) -> Option<&mut CustomStream> {
350 match &mut self.m_inner {
351 StreamInner::Reader(_) => None,
352 StreamInner::Writer(_) => None,
353 StreamInner::CustomReader(reader) => Some(reader.get_mut()),
354 StreamInner::CustomWriter(writer) => Some(writer.get_mut()),
355 }
356 }
357
358 pub fn set_stream_length(&mut self, len: u64) {
359 self.m_stream_length = len;
360 }
361
362 pub fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
363 let len = buf.len();
364 match self.m_inner.read_exact(buf) {
365 Ok(_) => {
366 self.m_byte_offset += len as i64;
367 Ok(len)
368 }
369 Err(_err) => {
370 match self.m_inner.read(buf) {
372 Ok(nb) => {
373 self.m_byte_offset += nb as i64;
374 Ok(nb)
375 }
376 Err(err) => {
377 log::trace!("Failed to read from stream: {err}");
378 Err(err)
379 }
380 }
381 }
382 }
383 }
384
385 pub fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
386 let len = buf.len();
387 log::trace!("-- write({len}), offset={}", self.m_byte_offset);
388 match self.m_inner.write_all(buf) {
389 Ok(_) => {
390 self.m_byte_offset += len as i64;
391 Ok(len)
392 }
393 Err(err) => {
394 log::trace!("Failed to write to stream: {err}");
395 Err(err)
396 }
397 }
398 }
399
400 pub fn flush(&mut self) -> std::io::Result<()> {
401 log::trace!("-- flush(), offset={}", self.m_byte_offset);
402 self.m_inner.flush()
403 }
404
405 pub fn tell(&self) -> i64 {
406 log::trace!("-- tell() = {}", self.m_byte_offset);
407 self.m_byte_offset
408 }
409
410 pub fn get_bytes_left(&self) -> i64 {
411 log::trace!("-- byte_left(), offset={}", self.m_byte_offset);
412 assert!(self.m_byte_offset >= 0i64);
413 assert!(self.m_stream_length >= self.m_byte_offset as OPJ_UINT64);
414 let nb = if self.m_stream_length != 0 {
415 (self.m_stream_length as OPJ_OFF_T) - self.m_byte_offset
416 } else {
417 0i64
418 };
419 log::trace!("-- get_number_byte_left() = {}", nb);
420 nb
421 }
422
423 pub fn skip(&mut self, count: i64) -> std::io::Result<i64> {
424 if count < 0 {
425 log::trace!("Can't skip with count < 0: {count}");
426 return Err(std::io::Error::other(format!(
427 "Can't skip with count < 0: {count}"
428 )));
429 }
430 if self.m_stream_length > 0 {
431 let new_offset = self.m_byte_offset + count;
432 if (new_offset as u64) > self.m_stream_length {
433 log::trace!("Skip pass the end of the stream.");
434 return Err(std::io::Error::other(format!(
435 "Skip pass the end of the stream"
436 )));
437 }
438 }
439 let res = self
440 .m_inner
441 .seek_relative(count)
442 .map(|_| (self.m_byte_offset + count) as u64);
443 match res {
444 Ok(offset) => {
445 self.m_byte_offset = offset as i64;
446 log::trace!("-- skip({count}) = {offset}");
448 Ok(count)
449 }
450 Err(err) => {
451 log::trace!("Failed to skip stream: {err}");
452 Err(err)
453 }
454 }
455 }
456
457 pub fn seek(&mut self, offset: i64) -> std::io::Result<()> {
458 let res = self.m_inner.seek_relative(offset - self.m_byte_offset);
459 match res {
460 Ok(_) => {
461 self.m_byte_offset = offset;
462 log::trace!("-- seek({offset}) = Ok");
463 Ok(())
464 }
465 Err(err) => {
466 log::trace!("Failed to seek stream: {err}");
467 Err(err)
468 }
469 }
470 }
471
472 pub fn has_seek(&self) -> bool {
473 self.m_inner.has_seek()
474 }
475}
476
477impl Read for Stream {
478 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
479 self.read(buf)
480 }
481}
482
483impl Write for Stream {
484 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
485 self.write(buf)
486 }
487
488 fn flush(&mut self) -> std::io::Result<()> {
489 self.flush()
490 }
491}
492
493pub(crate) fn opj_stream_read_data(
494 mut p_stream: *mut opj_stream_private_t,
495 mut p_buffer: *mut OPJ_BYTE,
496 mut p_size: OPJ_SIZE_T,
497 mut _p_event_mgr: &mut opj_event_mgr,
498) -> OPJ_SIZE_T {
499 let p_stream = unsafe { &mut *p_stream };
500 let buf = unsafe { core::slice::from_raw_parts_mut(p_buffer as *mut u8, p_size) };
501 match p_stream.read(buf) {
502 Ok(nb) => nb as OPJ_SIZE_T,
503 Err(err) => {
504 log::trace!("Failed to read from stream: {err}");
505 -1i32 as OPJ_SIZE_T
506 }
507 }
508}
509
510pub(crate) fn opj_stream_write_data(
511 mut p_stream: *mut opj_stream_private_t,
512 mut p_buffer: *const OPJ_BYTE,
513 mut p_size: OPJ_SIZE_T,
514 mut _p_event_mgr: &mut opj_event_mgr,
515) -> OPJ_SIZE_T {
516 let p_stream = unsafe { &mut *p_stream };
517 log::trace!("-- write({p_size}), offset={}", p_stream.m_byte_offset);
518 let buf = unsafe { core::slice::from_raw_parts(p_buffer as *const u8, p_size) };
519 match p_stream.write(buf) {
520 Ok(nb) => nb,
521 Err(err) => {
522 log::trace!("Failed to write to stream: {err}");
523 -1i32 as OPJ_SIZE_T
524 }
525 }
526}
527
528pub(crate) fn opj_stream_flush(
529 mut p_stream: *mut opj_stream_private_t,
530 mut _p_event_mgr: &mut opj_event_mgr,
531) -> OPJ_BOOL {
532 let p_stream = unsafe { &mut *p_stream };
533 return match p_stream.flush() {
534 Ok(_) => 1,
535 Err(err) => {
536 log::trace!("Failed to flush stream: {err}");
537 0
538 }
539 };
540}
541
542pub(crate) fn opj_stream_tell(mut p_stream: *mut opj_stream_private_t) -> OPJ_OFF_T {
543 let p_stream = unsafe { &mut *p_stream };
544 p_stream.tell()
545}
546
547pub(crate) fn opj_stream_get_number_byte_left(
548 mut p_stream: *mut opj_stream_private_t,
549) -> OPJ_OFF_T {
550 let p_stream = unsafe { &mut *p_stream };
551 p_stream.get_bytes_left()
552}
553
554pub(crate) fn opj_stream_skip(
555 mut p_stream: *mut opj_stream_private_t,
556 mut p_size: OPJ_OFF_T,
557 mut _p_event_mgr: &mut opj_event_mgr,
558) -> OPJ_OFF_T {
559 let p_stream = unsafe { &mut *p_stream };
560 match p_stream.skip(p_size) {
561 Ok(offset) => {
562 log::trace!("-- skip({p_size}) = {}", offset);
563 offset
564 }
565 Err(err) => {
566 log::trace!("Failed to skip stream: {err}");
567 -1i32 as _
568 }
569 }
570}
571
572pub(crate) fn opj_stream_seek(
573 mut p_stream: *mut opj_stream_private_t,
574 mut p_size: OPJ_OFF_T,
575 mut _p_event_mgr: &mut opj_event_mgr,
576) -> OPJ_BOOL {
577 let p_stream = unsafe { &mut *p_stream };
578 match p_stream.seek(p_size) {
579 Ok(_) => {
580 log::trace!("-- seek({p_size}) = {}", 1);
581 1
582 }
583 Err(err) => {
584 log::trace!("Failed to seek stream: {err}");
585 0
586 }
587 }
588}
589
590pub(crate) fn opj_stream_has_seek(mut p_stream: *const opj_stream_private_t) -> OPJ_BOOL {
591 let p_stream = unsafe { &*p_stream };
592 p_stream.has_seek() as _
593}