openjp2/
stream.rs

1/*
2 * The copyright in this software is being made available under the 2-clauses
3 * BSD License, included below. This software may be subject to other third
4 * party and contributor rights, including patent rights, and no such rights
5 * are granted under this license.
6 *
7 * Copyright (c) 2002-2014, Universite catholique de Louvain (UCL), Belgium
8 * Copyright (c) 2002-2014, Professor Benoit Macq
9 * Copyright (c) 2001-2003, David Janssens
10 * Copyright (c) 2002-2003, Yannick Verschueren
11 * Copyright (c) 2003-2007, Francois-Olivier Devaux
12 * Copyright (c) 2003-2014, Antonin Descampe
13 * Copyright (c) 2005, Herve Drolon, FreeImage Team
14 * Copyright (c) 2008, 2011-2012, Centre National d'Etudes Spatiales (CNES), FR
15 * Copyright (c) 2012, CS Systemes d'Information, France
16 * All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
20 * are met:
21 * 1. Redistributions of source code must retain the above copyright
22 *    notice, this list of conditions and the following disclaimer.
23 * 2. Redistributions in binary form must reproduce the above copyright
24 *    notice, this list of conditions and the following disclaimer in the
25 *    documentation and/or other materials provided with the distribution.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
28 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
31 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 */
39
40use 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        // Maybe EOF, do a partial read.
371        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        // TODO: return number of bytes skipped.
447        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}