1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
use std::path::PathBuf;
use std::{error::Error, fmt::Debug};
use super::DataBlock;
use crate::FileInfo;
/// A type that decodes a file in a read stream.
pub trait Decoder: Sized + 'static {
/// The data type of a single sample. (i.e. `f32`)
type T: Copy + Clone + Default + Send;
/// Any additional options for opening a file with this decoder.
type AdditionalOpts: Send + Default + Debug;
/// Any additional information on the file.
type FileParams: Clone + Send;
/// The error type while opening the file.
type OpenError: Error + Send;
/// The error type when a fatal error occurs.
type FatalError: Error + Send;
/// The default number of frames in a prefetch block.
const DEFAULT_BLOCK_SIZE: usize;
/// The default number of prefetch blocks in a cache block. This will cause a cache to be
/// used whenever the stream is seeked to a frame in the range:
///
/// `[cache_start, cache_start + (num_cache_blocks * block_size))`
///
/// If this is 0, then the cache is only used when seeked to exactly `cache_start`.
const DEFAULT_NUM_CACHE_BLOCKS: usize;
/// The number of prefetch blocks to store ahead of the cache block. This must be
/// sufficiently large to ensure enough to time to fill the buffer in the worst
/// case latency scenerio.
const DEFAULT_NUM_LOOK_AHEAD_BLOCKS: usize;
/// Open the file and start reading from `start_frame`.
///
/// Please note this algorithm depends on knowing the exact number of frames in a file.
/// Do **not** return an approximate length in the returned `FileInfo`.
fn new(
file: PathBuf,
start_frame: usize,
block_size: usize,
additional_opts: Self::AdditionalOpts,
) -> Result<(Self, FileInfo<Self::FileParams>), Self::OpenError>;
/// Seek to a frame in the file. If a frame lies outside of the end of the file,
/// set the read position the end of the file instead of returning an error.
fn seek(&mut self, frame: usize) -> Result<(), Self::FatalError>;
/// Decode data into the `data_block` starting from the read position. This is streaming,
/// meaning the next call to `decode()` should pick up where the previous left off.
///
/// If the end of the file is reached, fill data up to the end of the file, then set the
/// read position to the last frame in the file and do nothing.
///
/// ## Unsafe
/// This is marked as "unsafe" because a `data_block` may be uninitialized, causing
/// undefined behavior if data is not filled into the block. It is your responsibility to
/// always fill the block (unless the end of the file is reached, in which case the server
/// will tell the client to not read data past that frame).
unsafe fn decode(
&mut self,
data_block: &mut DataBlock<Self::T>,
) -> Result<(), Self::FatalError>;
/// Return the current read position.
fn current_frame(&self) -> usize;
}