#![warn(missing_docs)]
use crate::codec::header::Magic;
use crate::{DeltaT, Event, PlaneSize, SourceCamera, TimeMode};
use bitstream_io::{BigEndian, BitReader};
use enum_dispatch::enum_dispatch;
use std::io;
use std::io::{Read, Seek, Sink, Write};
#[enum_dispatch(WriteCompression<W>)]
pub enum WriteCompressionEnum<W: Write> {
#[cfg(feature = "compression")]
CompressedOutput(CompressedOutput<W>),
RawOutput(RawOutput<W>),
RawOutputInterleaved(RawOutputInterleaved<W>),
EmptyOutput(EmptyOutput<Sink>),
}
#[derive(Default, Clone, Copy, PartialEq)]
pub enum EncoderType {
Compressed,
Raw,
RawInterleaved,
#[default]
Empty,
}
#[enum_dispatch(ReadCompression<R>)]
enum ReadCompressionEnum<R: Read + Seek> {
#[cfg(feature = "compression")]
CompressedInput(CompressedInput<R>),
RawInput(RawInput<R>),
}
#[cfg(feature = "compression")]
pub mod compressed;
pub mod decoder;
pub mod empty;
pub mod encoder;
mod header;
pub mod raw;
pub const LATEST_CODEC_VERSION: u8 = 2;
#[allow(missing_docs)]
#[derive(Copy, Clone)]
pub struct CodecMetadata {
pub codec_version: u8,
pub header_size: usize,
pub time_mode: TimeMode,
pub plane: PlaneSize,
pub tps: DeltaT,
pub ref_interval: DeltaT,
pub delta_t_max: DeltaT,
pub event_size: u8,
pub source_camera: SourceCamera,
}
impl Default for CodecMetadata {
fn default() -> Self {
CodecMetadata {
codec_version: LATEST_CODEC_VERSION,
header_size: 24,
time_mode: Default::default(),
plane: Default::default(),
tps: 2550,
ref_interval: 255,
delta_t_max: 255,
event_size: 9,
source_camera: Default::default(),
}
}
}
#[enum_dispatch]
pub trait WriteCompression<W: Write> {
fn magic(&self) -> Magic;
fn meta(&self) -> &CodecMetadata;
fn meta_mut(&mut self) -> &mut CodecMetadata;
fn write_bytes(&mut self, bytes: &[u8]) -> Result<(), std::io::Error>;
fn byte_align(&mut self) -> io::Result<()>;
fn into_writer(&mut self) -> Option<W>;
fn flush_writer(&mut self) -> io::Result<()>;
fn ingest_event(&mut self, event: Event) -> Result<(), CodecError>;
#[cfg(feature = "compression")]
fn ingest_event_debug(&mut self, event: Event) -> Result<Option<Adu>, CodecError>;
}
#[enum_dispatch]
pub trait ReadCompression<R: Read> {
fn magic(&self) -> Magic;
fn meta(&self) -> &CodecMetadata;
fn meta_mut(&mut self) -> &mut CodecMetadata;
fn read_bytes(
&mut self,
bytes: &mut [u8],
reader: &mut BitReader<R, BigEndian>,
) -> io::Result<()>;
fn digest_event(&mut self, reader: &mut BitReader<R, BigEndian>) -> Result<Event, CodecError>;
#[cfg(feature = "compression")]
fn digest_event_debug(
&mut self,
reader: &mut BitReader<R, BigEndian>,
) -> Result<(Option<Adu>, Event), CodecError>;
fn set_input_stream_position(
&mut self,
reader: &mut BitReader<R, BigEndian>,
position: u64,
) -> Result<(), CodecError>;
}
#[cfg(feature = "compression")]
use crate::codec::compressed::adu::frame::Adu;
#[cfg(feature = "compression")]
use crate::codec::compressed::stream::{CompressedInput, CompressedOutput};
use crate::codec::empty::stream::EmptyOutput;
use crate::codec::raw::stream::{RawInput, RawOutput, RawOutputInterleaved};
use thiserror::Error;
#[allow(missing_docs)]
#[derive(Error, Debug)]
pub enum CodecError {
#[error("stream has not been initialized")]
UnitializedStream,
#[error("Reached end of file when expected")]
Eof,
#[error("Could not deserialize data. EOF reached at unexpected time.")]
Deserialize,
#[error("File formatted incorrectly")]
BadFile,
#[error("File is of unexpected type (compressed or raw)")]
WrongMagic,
#[error("Attempted to seek to a bad position in the stream")]
Seek,
#[error("Unsupported codec version (expected {LATEST_CODEC_VERSION} or lower, found {0})")]
UnsupportedVersion(u8),
#[error("Malformed encoder")]
MalformedEncoder,
#[error("Bincode error")]
BincodeError(#[from] bincode::Error),
#[error("IO error")]
IoError(#[from] io::Error),
#[error("Plane error")]
PlaneError(#[from] crate::PlaneError),
#[cfg(feature = "compression")]
#[error("Blocking error")]
BlockError(#[from] crate::codec::compressed::blocks::block::BlockError),
#[cfg(feature = "compression")]
#[error("Arithmetic coding error")]
ArithmeticCodingError(#[from] arithmetic_coding::Error),
}