use crate::adapters::{DynPixelRWAdapter, NeverPixelAdapter, PixelRWAdapter};
use crate::decode::{
basic::BasicDecoder, explicit_be::ExplicitVRBigEndianDecoder,
explicit_le::ExplicitVRLittleEndianDecoder, implicit_le::ImplicitVRLittleEndianDecoder,
DecodeFrom,
};
use crate::encode::{
explicit_be::ExplicitVRBigEndianEncoder, explicit_le::ExplicitVRLittleEndianEncoder,
implicit_le::ImplicitVRLittleEndianEncoder, EncodeTo, EncoderFor,
};
use std::io::{Read, Write};
pub use byteordered::Endianness;
pub type DynDecoder<S> = Box<dyn DecodeFrom<S>>;
pub type DynEncoder<'w, W> = Box<dyn EncodeTo<W> + 'w>;
#[derive(Debug)]
pub struct TransferSyntax<D = DynDataRWAdapter, P = DynPixelRWAdapter> {
uid: &'static str,
name: &'static str,
byte_order: Endianness,
explicit_vr: bool,
codec: Codec<D, P>,
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct TransferSyntaxFactory(pub fn() -> TransferSyntax);
#[cfg(feature = "inventory-registry")]
inventory::collect!(TransferSyntaxFactory);
pub trait TransferSyntaxIndex {
fn get(&self, uid: &str) -> Option<&TransferSyntax>;
}
impl<T: ?Sized> TransferSyntaxIndex for &T
where
T: TransferSyntaxIndex,
{
fn get(&self, uid: &str) -> Option<&TransferSyntax> {
(**self).get(uid)
}
}
#[cfg(feature = "inventory-registry")]
#[macro_export]
macro_rules! submit_transfer_syntax {
($ts: expr) => {
inventory::submit! {
$crate::transfer_syntax::TransferSyntaxFactory(|| ($ts).erased())
}
};
}
#[cfg(not(feature = "inventory-registry"))]
#[macro_export]
macro_rules! submit_transfer_syntax {
($ts: expr) => {
};
}
#[derive(Debug, Clone, PartialEq)]
pub enum Codec<D, P> {
None,
Unsupported,
EncapsulatedPixelData,
PixelData(P),
Dataset(D),
}
pub type AdapterFreeTransferSyntax = TransferSyntax<NeverAdapter, NeverPixelAdapter>;
pub trait DataRWAdapter<R, W> {
type Reader: Read;
type Writer: Write;
fn adapt_reader(&self, reader: R) -> Self::Reader
where
R: Read;
fn adapt_writer(&self, writer: W) -> Self::Writer
where
W: Write;
}
pub type DynDataRWAdapter = Box<
dyn DataRWAdapter<
Box<dyn Read>,
Box<dyn Write>,
Reader = Box<dyn Read>,
Writer = Box<dyn Write>,
> + Send
+ Sync,
>;
impl<'a, T, R, W> DataRWAdapter<R, W> for &'a T
where
T: DataRWAdapter<R, W>,
R: Read,
W: Write,
{
type Reader = <T as DataRWAdapter<R, W>>::Reader;
type Writer = <T as DataRWAdapter<R, W>>::Writer;
fn adapt_reader(&self, reader: R) -> Self::Reader
where
R: Read,
{
(**self).adapt_reader(reader)
}
fn adapt_writer(&self, writer: W) -> Self::Writer
where
W: Write,
{
(**self).adapt_writer(writer)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum NeverAdapter {}
impl<R, W> DataRWAdapter<R, W> for NeverAdapter {
type Reader = Box<dyn Read>;
type Writer = Box<dyn Write>;
fn adapt_reader(&self, _reader: R) -> Self::Reader
where
R: Read,
{
unreachable!()
}
fn adapt_writer(&self, _writer: W) -> Self::Writer
where
W: Write,
{
unreachable!()
}
}
impl<D, P> TransferSyntax<D, P> {
pub const fn new(
uid: &'static str,
name: &'static str,
byte_order: Endianness,
explicit_vr: bool,
codec: Codec<D, P>,
) -> Self {
TransferSyntax {
uid,
name,
byte_order,
explicit_vr,
codec,
}
}
pub const fn uid(&self) -> &'static str {
self.uid
}
pub const fn name(&self) -> &'static str {
self.name
}
pub const fn endianness(&self) -> Endianness {
self.byte_order
}
pub fn codec(&self) -> &Codec<D, P> {
&self.codec
}
pub fn fully_supported(&self) -> bool {
matches!(
self.codec,
Codec::None | Codec::Dataset(_) | Codec::PixelData(_),
)
}
pub fn is_codec_free(&self) -> bool {
matches!(self.codec, Codec::None)
}
pub fn unsupported(&self) -> bool {
matches!(self.codec, Codec::Unsupported)
}
pub fn unsupported_pixel_encapsulation(&self) -> bool {
matches!(
self.codec,
Codec::Unsupported | Codec::EncapsulatedPixelData
)
}
pub fn decoder<'s>(&self) -> Option<DynDecoder<dyn Read + 's>> {
self.decoder_for()
}
pub fn decoder_for<S>(&self) -> Option<DynDecoder<S>>
where
Self: Sized,
S: ?Sized + Read,
{
match (self.byte_order, self.explicit_vr) {
(Endianness::Little, false) => Some(Box::new(ImplicitVRLittleEndianDecoder::default())),
(Endianness::Little, true) => Some(Box::new(ExplicitVRLittleEndianDecoder::default())),
(Endianness::Big, true) => Some(Box::new(ExplicitVRBigEndianDecoder::default())),
_ => None,
}
}
pub fn encoder<'w>(&self) -> Option<DynEncoder<'w, dyn Write + 'w>> {
self.encoder_for()
}
pub fn encoder_for<'w, W: 'w>(&self) -> Option<DynEncoder<'w, W>>
where
Self: Sized,
W: ?Sized + Write,
{
match (self.byte_order, self.explicit_vr) {
(Endianness::Little, false) => Some(Box::new(EncoderFor::new(
ImplicitVRLittleEndianEncoder::default(),
))),
(Endianness::Little, true) => Some(Box::new(EncoderFor::new(
ExplicitVRLittleEndianEncoder::default(),
))),
(Endianness::Big, true) => Some(Box::new(EncoderFor::new(
ExplicitVRBigEndianEncoder::default(),
))),
_ => None,
}
}
pub fn basic_decoder(&self) -> BasicDecoder {
BasicDecoder::from(self.endianness())
}
pub fn erased(self) -> TransferSyntax
where
D: Send + Sync + 'static,
D: DataRWAdapter<
Box<dyn Read>,
Box<dyn Write>,
Reader = Box<dyn Read>,
Writer = Box<dyn Write>,
>,
P: Send + Sync + 'static,
P: PixelRWAdapter,
{
let codec = match self.codec {
Codec::Dataset(d) => Codec::Dataset(Box::new(d) as DynDataRWAdapter),
Codec::PixelData(p) => Codec::PixelData(Box::new(p) as DynPixelRWAdapter),
Codec::EncapsulatedPixelData => Codec::EncapsulatedPixelData,
Codec::Unsupported => Codec::Unsupported,
Codec::None => Codec::None,
};
TransferSyntax {
uid: self.uid,
name: self.name,
byte_order: self.byte_order,
explicit_vr: self.explicit_vr,
codec,
}
}
}