pub mod explicit_be;
pub mod explicit_le;
pub mod implicit_le;
use crate::decode::basic::BasicDecoder;
use crate::decode::Decode;
use crate::encode::Encode;
use std::io::{Read, Write};
pub use byteordered::Endianness;
pub type DynDecoder = Box<dyn Decode<Source = dyn Read>>;
pub type DynEncoder = Box<dyn Encode<Writer = dyn Write>>;
#[derive(Debug)]
pub struct TransferSyntax<A = DynDataRWAdapter> {
uid: &'static str,
name: &'static str,
byte_order: Endianness,
explicit_vr: bool,
codec: Codec<A>,
}
inventory::collect!(TransferSyntax);
#[macro_export]
macro_rules! submit_transfer_syntax {
($ts: expr) => {
inventory::submit! {
($ts).erased()
}
};
}
#[derive(Debug, Clone, PartialEq)]
pub enum Codec<A> {
None,
Unsupported,
EncapsulatedPixelData,
PixelData(A),
Dataset(A),
}
pub type AdapterFreeTransferSyntax = TransferSyntax<NeverAdapter>;
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<A> TransferSyntax<A> {
pub const fn new(
uid: &'static str,
name: &'static str,
byte_order: Endianness,
explicit_vr: bool,
codec: Codec<A>,
) -> 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<A> {
&self.codec
}
pub fn fully_supported(&self) -> bool {
match self.codec {
Codec::None | Codec::Dataset(_) | Codec::PixelData(_) => true,
_ => false,
}
}
pub fn unsupported(&self) -> bool {
match self.codec {
Codec::Unsupported => true,
_ => false,
}
}
pub fn unsupported_pixel_encapsulation(&self) -> bool {
match self.codec {
Codec::Unsupported | Codec::EncapsulatedPixelData => true,
_ => false,
}
}
pub fn get_decoder(&self) -> Option<DynDecoder> {
match (self.byte_order, self.explicit_vr) {
(Endianness::Little, false) => Some(Box::new(
implicit_le::ImplicitVRLittleEndianDecoder::default(),
)),
(Endianness::Little, true) => Some(Box::new(
explicit_le::ExplicitVRLittleEndianDecoder::default(),
)),
(Endianness::Big, true) => {
Some(Box::new(explicit_be::ExplicitVRBigEndianDecoder::default()))
}
_ => None,
}
}
pub fn get_encoder(&self) -> Option<DynEncoder> {
match (self.byte_order, self.explicit_vr) {
(Endianness::Little, false) => Some(Box::new(
implicit_le::ImplicitVRLittleEndianEncoder::default(),
)),
(Endianness::Little, true) => Some(Box::new(
explicit_le::ExplicitVRLittleEndianEncoder::default(),
)),
(Endianness::Big, true) => {
Some(Box::new(explicit_be::ExplicitVRBigEndianEncoder::default()))
}
_ => None,
}
}
pub fn get_basic_decoder(&self) -> BasicDecoder {
BasicDecoder::from(self.endianness())
}
pub fn erased(self) -> TransferSyntax
where
A: Send + Sync + 'static,
A: DataRWAdapter<
Box<dyn Read>,
Box<dyn Write>,
Reader = Box<dyn Read>,
Writer = Box<dyn Write>,
>,
{
let codec = match self.codec {
Codec::Dataset(a) => Codec::Dataset(Box::new(a) as DynDataRWAdapter),
Codec::PixelData(a) => Codec::PixelData(Box::new(a) as DynDataRWAdapter),
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,
}
}
}