zune_core/bytestream/
traits.rs

1/*
2 * Copyright (c) 2023.
3 *
4 * This software is free software;
5 *
6 * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license
7 */
8//! Traits for reading and writing images in zune
9//!
10//!
11//! This exposes the traits and implementations for readers
12//! and writers in the zune family of decoders and encoders.
13
14use crate::bytestream::reader::{ZByteIoError, ZSeekFrom};
15
16/// The de-facto Input trait implemented for readers.
17///
18/// This provides the basic functions needed to quick and sometimes
19/// heap free I/O for the zune image decoders with easy support for extending it
20/// to multiple implementations.
21///
22/// # Considerations
23///
24/// If you have an in memory buffer, prefer [`ZCursor`](crate::bytestream::ZCursor) over [`Cursor`](std::io::Cursor).
25/// We implement this trait for two types, `ZCursor`, and any thing that implements `BufRead`+`Seek`, `Cursor` falls in the latter
26/// and since Rust doesn't have specialization for traits, we can only implement it once. This means functions like
27/// [`read_byte_no_error`](crate::bytestream::ZByteReaderTrait::read_byte_no_error) are slower than they should be for `Cursor`.
28///
29pub trait ZByteReaderTrait {
30    /// Read a single byte from the decoder and return
31    /// `0` if we can't read the byte, e.g because of EOF
32    ///
33    /// The implementation should try to be as fast as possible as this is called
34    /// from some hot loops where it may become the bottleneck
35    fn read_byte_no_error(&mut self) -> u8;
36    /// Read exact bytes required to fill `buf` or return an error if that isn't possible
37    ///
38    /// ## Arguments
39    ///  - `buf`: Buffer to fill with bytes from the underlying reader
40    ///  ## Errors
41    /// In case of an error, the implementation should not increment the internal position
42    fn read_exact_bytes(&mut self, buf: &mut [u8]) -> Result<(), ZByteIoError>;
43
44    /// Read exact bytes required to fill `buf` or return an error if that isn't possible
45    ///
46    /// This is the same as [`read_exact_bytes`](Self::read_exact_bytes) but implemented as a separate
47    /// method to allow some implementations to optimize it to cost fewer instructions
48    ///
49    /// ## Arguments
50    ///  - `buf`: Buffer to fill with bytes from the underlying reader
51    ///  ## Errors
52    /// In case of an error, the implementation should not increment the internal position
53    fn read_const_bytes<const N: usize>(&mut self, buf: &mut [u8; N]) -> Result<(), ZByteIoError>;
54
55    /// Read exact bytes required to fill `buf` or ignore buf entirely if you can't fill it
56    /// due to an error like the inability to fill the buffer completely
57    /// ## Arguments
58    ///  - `buf`: Buffer to fill with bytes from the underlying reader
59    /// ## Errors
60    /// In case of an error, the implementation should not increment the internal position
61    fn read_const_bytes_no_error<const N: usize>(&mut self, buf: &mut [u8; N]);
62
63    /// Read bytes into `buf` returning how many bytes you have read or an error if one occurred
64    ///
65    /// This doesn't guarantee that buf will be filled with bytes for such a guarantee see
66    /// [`read_exact_bytes`](Self::read_exact_bytes)
67    ///
68    /// ## Arguments
69    /// - `buf`: The buffer to fill with bytes
70    ///
71    /// ## Returns
72    ///  - `Ok(usize)` - Actual bytes read into the buffer
73    ///  - `Err()` - The error encountered when reading bytes for which we couldn't recover
74    fn read_bytes(&mut self, buf: &mut [u8]) -> Result<usize, ZByteIoError>;
75    /// Reads data into provided buffer but does not advance read position.
76    ///
77    ///
78    fn peek_bytes(&mut self, buf: &mut [u8]) -> Result<usize, ZByteIoError>;
79    fn peek_exact_bytes(&mut self, buf: &mut [u8]) -> Result<(), ZByteIoError>;
80    /// Seek into a new position from the buffer
81    ///
82    /// This is similar to the [seek](std::io::Seek::seek) function in the [Seek](std::io::Seek) trait
83    /// but implemented to work for no-std environments
84    fn z_seek(&mut self, from: ZSeekFrom) -> Result<u64, ZByteIoError>;
85    /// Report whether we are at the end of a stream.
86    ///
87    /// ## Warning
88    /// This may cause an additional syscall e.g when we are reading from a file, we must query the file
89    /// multiple times to check if we really are at the end of the file and the user didn't sneakily
90    /// add more contents to it hence use it with care
91    ///
92    /// ## Returns
93    /// - `Ok(bool)` - The answer to whether or not we are at end of file
94    /// - `Err()` - The error that occurred when we queried the underlying reader if we were at EOF
95    fn is_eof(&mut self) -> Result<bool, ZByteIoError>;
96
97    /// Return the current position of the inner cursor.
98    ///
99    /// This can be used to check the advancement of the cursor
100    fn z_position(&mut self) -> Result<u64, ZByteIoError>;
101    /// Read all bytes remaining in this input to `sink` until we hit eof
102    ///
103    /// # Returns
104    /// - `Ok(usize)` The actual number of bytes added to the sink
105    /// - `Err()` An error that occurred when reading bytes
106    fn read_remaining(&mut self, sink: &mut alloc::vec::Vec<u8>) -> Result<usize, ZByteIoError>;
107}
108
109/// The writer trait implemented for zune-image library of encoders
110///
111/// Anything that implements this trait can be used as a sink
112/// for writing encoded images
113pub trait ZByteWriterTrait {
114    /// Write some bytes into the sink returning number of bytes written or
115    /// an error if something bad happened
116    ///
117    /// An implementation is free to write less bytes that are in buf, so the bytes written
118    /// cannot be guaranteed to be fully written
119    fn write_bytes(&mut self, buf: &[u8]) -> Result<usize, ZByteIoError>;
120    /// Write all bytes to the buffer or return an error if something occurred
121    ///
122    /// This will always write all bytes, if it can't fully write all bytes, it will
123    /// error out
124    fn write_all_bytes(&mut self, buf: &[u8]) -> Result<(), ZByteIoError>;
125    /// Write a fixed number of bytes and error out if we can't write the bytes
126    ///
127    /// This is provided to allow for optimized writes where possible. (when the compiler can const fold them)
128    fn write_const_bytes<const N: usize>(&mut self, buf: &[u8; N]) -> Result<(), ZByteIoError>;
129    /// Ensure bytes are written to the sink.
130    ///
131    /// Implementations should treat this like linux `fsync`, and should implement
132    /// whatever writer's implementation of fsync should look like
133    ///
134    /// After this, the encoder should be able to guarantee that all in-core data is synced with the
135    /// storage decive
136    fn flush_bytes(&mut self) -> Result<(), ZByteIoError>;
137
138    /// A hint to tell the implementation how big of a size we expect the image to be
139    /// An implementation like in memory `Vec` can use this to reserve additional memory to
140    /// prevent reallocation when encoding
141    ///
142    /// This is just a hint, akin to calling `Vec::reserve` and should be treated as such.
143    /// If your implementation doesn't support such, e.g file or mutable slices, it's okay to return
144    /// `Ok(())`
145    fn reserve_capacity(&mut self, size: usize) -> Result<(), ZByteIoError>;
146}