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 bytes into `buf` returning how many bytes you have read or an error if one occurred
45 ///
46 /// This doesn't guarantee that buf will be filled with bytes for such a guarantee see
47 /// [`read_exact_bytes`](Self::read_exact_bytes)
48 ///
49 /// ## Arguments
50 /// - `buf`: The buffer to fill with bytes
51 ///
52 /// ## Returns
53 /// - `Ok(usize)` - Actual bytes read into the buffer
54 /// - `Err()` - The error encountered when reading bytes for which we couldn't recover
55 fn read_bytes(&mut self, buf: &mut [u8]) -> Result<usize, ZByteIoError>;
56 /// Reads data into provided buffer but does not advance read position.
57 ///
58 ///
59 fn peek_bytes(&mut self, buf: &mut [u8]) -> Result<usize, ZByteIoError>;
60 fn peek_exact_bytes(&mut self, buf: &mut [u8]) -> Result<(), ZByteIoError>;
61 /// Seek into a new position from the buffer
62 ///
63 /// This is similar to the [seek](std::io::Seek::seek) function in the [Seek](std::io::Seek) trait
64 /// but implemented to work for no-std environments
65 fn z_seek(&mut self, from: ZSeekFrom) -> Result<u64, ZByteIoError>;
66 /// Report whether we are at the end of a stream.
67 ///
68 /// ## Warning
69 /// This may cause an additional syscall e.g when we are reading from a file, we must query the file
70 /// multiple times to check if we really are at the end of the file and the user didn't sneakily
71 /// add more contents to it hence use it with care
72 ///
73 /// ## Returns
74 /// - `Ok(bool)` - The answer to whether or not we are at end of file
75 /// - `Err()` - The error that occurred when we queried the underlying reader if we were at EOF
76 fn is_eof(&mut self) -> Result<bool, ZByteIoError>;
77
78 /// Return the current position of the inner cursor.
79 ///
80 /// This can be used to check the advancement of the cursor
81 fn z_position(&mut self) -> Result<u64, ZByteIoError>;
82 /// Read all bytes remaining in this input to `sink` until we hit eof
83 ///
84 /// # Returns
85 /// - `Ok(usize)` The actual number of bytes added to the sink
86 /// - `Err()` An error that occurred when reading bytes
87 fn read_remaining(&mut self, sink: &mut alloc::vec::Vec<u8>) -> Result<usize, ZByteIoError>;
88}
89
90/// The writer trait implemented for zune-image library of encoders
91///
92/// Anything that implements this trait can be used as a sink
93/// for writing encoded images
94pub trait ZByteWriterTrait {
95 /// Write some bytes into the sink returning number of bytes written or
96 /// an error if something bad happened
97 ///
98 /// An implementation is free to write less bytes that are in buf, so the bytes written
99 /// cannot be guaranteed to be fully written
100 fn write_bytes(&mut self, buf: &[u8]) -> Result<usize, ZByteIoError>;
101 /// Write all bytes to the buffer or return an error if something occurred
102 ///
103 /// This will always write all bytes, if it can't fully write all bytes, it will
104 /// error out
105 fn write_all_bytes(&mut self, buf: &[u8]) -> Result<(), ZByteIoError>;
106 /// Write a fixed number of bytes and error out if we can't write the bytes
107 ///
108 /// This is provided to allow for optimized writes where possible. (when the compiler can const fold them)
109 fn write_const_bytes<const N: usize>(&mut self, buf: &[u8; N]) -> Result<(), ZByteIoError>;
110 /// Ensure bytes are written to the sink.
111 ///
112 /// Implementations should treat this like linux `fsync`, and should implement
113 /// whatever writer's implementation of fsync should look like
114 ///
115 /// After this, the encoder should be able to guarantee that all in-core data is synced with the
116 /// storage decive
117 fn flush_bytes(&mut self) -> Result<(), ZByteIoError>;
118
119 /// A hint to tell the implementation how big of a size we expect the image to be
120 /// An implementation like in memory `Vec` can use this to reserve additional memory to
121 /// prevent reallocation when encoding
122 ///
123 /// This is just a hint, akin to calling `Vec::reserve` and should be treated as such.
124 /// If your implementation doesn't support such, e.g file or mutable slices, it's okay to return
125 /// `Ok(())`
126 fn reserve_capacity(&mut self, size: usize) -> Result<(), ZByteIoError>;
127}