Skip to main content

zenjxl_decoder/api/
input.rs

1// Copyright (c) the JPEG XL Project Authors. All rights reserved.
2//
3// Use of this source code is governed by a BSD-style
4// license that can be found in the LICENSE file.
5
6use std::io::{BufRead, BufReader, Error, IoSliceMut, Read, Seek, SeekFrom};
7
8pub trait JxlBitstreamInput {
9    /// Returns an estimate bound of the total number of bytes that can be read via `read`.
10    /// Returning a too-low estimate here can impede parallelism. Returning a too-high
11    /// estimate can increase memory usage.
12    fn available_bytes(&mut self) -> Result<usize, Error>;
13
14    /// Fills in `bufs` with more bytes, returning the number of bytes written.
15    /// Buffers are filled in order and to completion.
16    fn read(&mut self, bufs: &mut [IoSliceMut]) -> Result<usize, Error>;
17
18    /// Skips up to `bytes` bytes of input. The provided implementation just uses `read`, but in
19    /// some cases this can be implemented faster.
20    /// Returns the number of bytes that were skipped. If this returns 0, it is assumed that no
21    /// more input is available.
22    fn skip(&mut self, bytes: usize) -> Result<usize, Error> {
23        let mut bytes = bytes;
24        const BUF_SIZE: usize = 1024;
25        let mut skip_buf = [0; BUF_SIZE];
26        let mut skipped = 0;
27        while bytes > 0 {
28            let num = bytes.min(BUF_SIZE);
29            self.read(&mut [IoSliceMut::new(&mut skip_buf[..num])])?;
30            bytes -= num;
31            skipped += num;
32        }
33        Ok(skipped)
34    }
35
36    /// Un-consumes read bytes. This will only be called at the end of a file stream,
37    /// to un-read potentially over-read bytes. If ensuring that data is not read past
38    /// the file end is not required, this method can safely be implemented as a no-op.
39    /// The provided implementation does nothing.
40    fn unconsume(&mut self, _count: usize) -> Result<(), Error> {
41        Ok(())
42    }
43}
44
45impl JxlBitstreamInput for &[u8] {
46    fn available_bytes(&mut self) -> Result<usize, Error> {
47        Ok(self.len())
48    }
49
50    fn read(&mut self, bufs: &mut [IoSliceMut]) -> Result<usize, Error> {
51        self.read_vectored(bufs)
52    }
53
54    fn skip(&mut self, bytes: usize) -> Result<usize, Error> {
55        let num = bytes.min(self.len());
56        self.consume(num);
57        Ok(num)
58    }
59}
60
61impl<R: Read + Seek> JxlBitstreamInput for BufReader<R> {
62    fn available_bytes(&mut self) -> Result<usize, Error> {
63        let pos = self.stream_position()?;
64        let end = self.seek(SeekFrom::End(0))?;
65        self.seek(SeekFrom::Start(pos))?;
66        Ok(end.saturating_sub(pos) as usize)
67    }
68
69    fn read(&mut self, bufs: &mut [IoSliceMut]) -> Result<usize, Error> {
70        self.read_vectored(bufs)
71    }
72
73    fn skip(&mut self, bytes: usize) -> Result<usize, Error> {
74        let cur = self.stream_position()?;
75        self.seek(SeekFrom::Current(bytes as i64))
76            .map(|x| x.saturating_sub(cur) as usize)
77    }
78
79    fn unconsume(&mut self, count: usize) -> Result<(), Error> {
80        self.seek_relative(-(count as i64))
81    }
82}