use crate::{
block::{chunk::TileCoordinates, lines::LineRef, UncompressedBlock},
error::{Result, UnitResult},
image::{
read::layers::{ChannelsReader, ReadChannels},
*,
},
math::Vec2,
meta::{
attribute::{ChannelDescription, Text},
header::Header,
},
};
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct ReadAnyChannels<ReadSamples> {
pub read_samples: ReadSamples,
}
pub trait ReadSamples {
type Reader: SamplesReader;
fn create_sample_reader(
&self,
header: &Header,
channel: &ChannelDescription,
) -> Result<Self::Reader>;
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct AnyChannelsReader<SamplesReader> {
sample_channels_reader: SmallVec<[AnyChannelReader<SamplesReader>; 4]>,
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct AnyChannelReader<SamplesReader> {
samples: SamplesReader,
name: Text,
sampling_rate: Vec2<usize>,
quantize_linearly: bool,
}
pub trait SamplesReader {
type Samples;
fn filter_block(&self, tile: TileCoordinates) -> bool;
fn read_line(&mut self, line: LineRef<'_>) -> UnitResult;
fn into_samples(self) -> Self::Samples;
}
impl<'s, S: 's + ReadSamples> ReadChannels<'s> for ReadAnyChannels<S> {
type Reader = AnyChannelsReader<S::Reader>;
fn create_channels_reader(&self, header: &Header) -> Result<Self::Reader> {
let samples: Result<_> = header
.channels
.list
.iter()
.map(|channel: &ChannelDescription| {
Ok(AnyChannelReader {
samples: self.read_samples.create_sample_reader(header, channel)?,
name: channel.name.clone(),
sampling_rate: channel.sampling,
quantize_linearly: channel.quantize_linearly,
})
})
.collect();
Ok(AnyChannelsReader {
sample_channels_reader: samples?,
})
}
}
impl<S: SamplesReader> ChannelsReader for AnyChannelsReader<S> {
type Channels = AnyChannels<S::Samples>;
fn filter_block(&self, tile: TileCoordinates) -> bool {
self.sample_channels_reader.iter().any(|channel| channel.samples.filter_block(tile))
}
fn read_block(&mut self, header: &Header, decompressed: UncompressedBlock) -> UnitResult {
for line in decompressed.lines(&header.channels) {
self.sample_channels_reader[line.location.channel].samples.read_line(line)?;
}
Ok(())
}
fn into_channels(self) -> Self::Channels {
AnyChannels {
list: self
.sample_channels_reader
.into_iter()
.map(|channel| AnyChannel {
sample_data: channel.samples.into_samples(),
name: channel.name,
quantize_linearly: channel.quantize_linearly,
sampling: channel.sampling_rate,
})
.collect(),
}
}
}