use byteordered::Endianness;
use dicom_core::value::serialize::{encode_date, encode_datetime, encode_time};
use dicom_core::{DataElementHeader, PrimitiveValue, Tag};
use snafu::{Backtrace, ResultExt, Snafu};
use std::fmt;
use std::io::{self, Write};
use std::marker::PhantomData;
pub mod basic;
pub mod explicit_be;
pub mod explicit_le;
pub mod implicit_le;
#[derive(Debug, Snafu)]
#[non_exhaustive]
pub enum Error {
#[snafu(display("Failed to write Date value"))]
WriteDate {
backtrace: Backtrace,
source: io::Error,
},
#[snafu(display("Failed to write Time value"))]
WriteTime {
backtrace: Backtrace,
source: io::Error,
},
#[snafu(display("Failed to write DateTime value"))]
WriteDateTime {
backtrace: Backtrace,
source: io::Error,
},
#[snafu(display("Failed to write tag"))]
WriteTag {
backtrace: Backtrace,
source: io::Error,
},
#[snafu(display("Failed to write tag group"))]
WriteTagGroup {
backtrace: Backtrace,
source: io::Error,
},
#[snafu(display("Failed to write tag element"))]
WriteTagElement {
backtrace: Backtrace,
source: io::Error,
},
#[snafu(display("Failed to write item header"))]
WriteItemHeader {
backtrace: Backtrace,
source: io::Error,
},
#[snafu(display("Failed to write element header"))]
WriteHeader {
backtrace: Backtrace,
source: io::Error,
},
#[snafu(display("Failed to write item delimiter"))]
WriteItemDelimiter {
backtrace: Backtrace,
source: io::Error,
},
#[snafu(display("Failed to write sequence delimiter"))]
WriteSequenceDelimiter {
backtrace: Backtrace,
source: io::Error,
},
#[snafu(display("Failed to write {} value", typ))]
WriteBinary {
typ: &'static str,
backtrace: Backtrace,
source: io::Error,
},
#[snafu(display("Failed to write string value"))]
WriteString {
backtrace: Backtrace,
source: io::Error,
},
#[snafu(display("Failed to write bytes"))]
WriteBytes {
backtrace: Backtrace,
source: io::Error,
},
#[snafu(display("Failed to write pixel data offset table"))]
WriteOffsetTable {
backtrace: Backtrace,
source: io::Error,
},
}
pub type Result<T, E = Error> = std::result::Result<T, E>;
pub trait BasicEncode {
fn endianness(&self) -> Endianness;
fn encode_us<W>(&self, to: W, value: u16) -> io::Result<()>
where
W: Write;
fn encode_ul<W>(&self, to: W, value: u32) -> io::Result<()>
where
W: Write;
fn encode_uv<W>(&self, to: W, value: u64) -> io::Result<()>
where
W: Write;
fn encode_ss<W>(&self, to: W, value: i16) -> io::Result<()>
where
W: Write;
fn encode_sl<W>(&self, to: W, value: i32) -> io::Result<()>
where
W: Write;
fn encode_sv<W>(&self, to: W, value: i64) -> io::Result<()>
where
W: Write;
fn encode_fl<W>(&self, to: W, value: f32) -> io::Result<()>
where
W: Write;
fn encode_fd<W>(&self, to: W, value: f64) -> io::Result<()>
where
W: Write;
#[inline]
fn with_encoder<T, F1, F2>(&self, f_le: F1, f_be: F2) -> T
where
F1: FnOnce(basic::LittleEndianBasicEncoder) -> T,
F2: FnOnce(basic::BigEndianBasicEncoder) -> T,
{
match self.endianness() {
Endianness::Little => f_le(basic::LittleEndianBasicEncoder),
Endianness::Big => f_be(basic::BigEndianBasicEncoder),
}
}
fn encode_primitive<W>(&self, mut to: W, value: &PrimitiveValue) -> Result<usize>
where
W: Write,
{
use PrimitiveValue::*;
match value {
Empty => Ok(0), Date(date) => {
encode_collection_delimited(&mut to, date, |to, date| encode_date(to, *date))
.context(WriteDateSnafu)
}
Time(time) => {
encode_collection_delimited(&mut to, time, |to, time| encode_time(to, *time))
.context(WriteTimeSnafu)
}
DateTime(datetime) => encode_collection_delimited(&mut to, datetime, |to, datetime| {
encode_datetime(to, *datetime)
})
.context(WriteDateTimeSnafu),
Str(s) => {
write!(to, "{}", s).context(WriteStringSnafu)?;
Ok(s.len())
}
Strs(s) => encode_collection_delimited(&mut to, s, |to, s| {
write!(to, "{}", s)?;
Ok(s.len())
})
.context(WriteStringSnafu),
F32(values) => {
for v in values {
self.encode_fl(&mut to, *v)
.context(WriteBinarySnafu { typ: "F32" })?;
}
Ok(values.len() * 4)
}
F64(values) => {
for v in values {
self.encode_fd(&mut to, *v)
.context(WriteBinarySnafu { typ: "F64" })?;
}
Ok(values.len() * 8)
}
U64(values) => {
for v in values {
self.encode_uv(&mut to, *v)
.context(WriteBinarySnafu { typ: "U64" })?;
}
Ok(values.len() * 8)
}
I64(values) => {
for v in values {
self.encode_sv(&mut to, *v)
.context(WriteBinarySnafu { typ: "I64" })?;
}
Ok(values.len() * 8)
}
U32(values) => {
for v in values {
self.encode_ul(&mut to, *v)
.context(WriteBinarySnafu { typ: "U32" })?;
}
Ok(values.len() * 4)
}
I32(values) => {
for v in values {
self.encode_sl(&mut to, *v)
.context(WriteBinarySnafu { typ: "I32" })?;
}
Ok(values.len() * 4)
}
U16(values) => {
for v in values {
self.encode_us(&mut to, *v)
.context(WriteBinarySnafu { typ: "U16" })?;
}
Ok(values.len() * 2)
}
I16(values) => {
for v in values {
self.encode_ss(&mut to, *v)
.context(WriteBinarySnafu { typ: "I16" })?;
}
Ok(values.len() * 2)
}
U8(values) => {
to.write_all(values).context(WriteBytesSnafu)?;
Ok(values.len())
}
Tags(tags) => {
for tag in tags {
self.encode_us(&mut to, tag.0).context(WriteTagGroupSnafu)?;
self.encode_us(&mut to, tag.1)
.context(WriteTagElementSnafu)?;
}
Ok(tags.len() * 4)
}
}
}
}
fn encode_collection_delimited<W, T, F>(
to: &mut W,
col: &[T],
mut encode_element_fn: F,
) -> io::Result<usize>
where
W: ?Sized + Write,
F: FnMut(&mut W, &T) -> io::Result<usize>,
{
let mut acc = 0;
for (i, v) in col.iter().enumerate() {
acc += encode_element_fn(to, v)?;
if i < col.len() - 1 {
to.write_all(b"\\")?;
acc += 1;
}
}
Ok(acc)
}
pub trait Encode {
fn encode_tag<W>(&self, to: W, tag: Tag) -> Result<()>
where
W: Write;
fn encode_element_header<W>(&self, to: W, de: DataElementHeader) -> Result<usize>
where
W: Write;
fn encode_item_header<W>(&self, to: W, len: u32) -> Result<()>
where
W: Write;
fn encode_item_delimiter<W>(&self, mut to: W) -> Result<()>
where
W: Write,
{
self.encode_tag(&mut to, Tag(0xFFFE, 0xE00D))?;
to.write_all(&[0u8; 4]).context(WriteItemDelimiterSnafu)?;
Ok(())
}
fn encode_sequence_delimiter<W>(&self, mut to: W) -> Result<()>
where
W: Write,
{
self.encode_tag(&mut to, Tag(0xFFFE, 0xE0DD))?;
to.write_all(&[0u8; 4])
.context(WriteSequenceDelimiterSnafu)?;
Ok(())
}
fn encode_primitive<W>(&self, to: W, value: &PrimitiveValue) -> Result<usize>
where
W: Write;
fn encode_offset_table<W>(&self, to: W, offset_table: &[u32]) -> Result<usize>
where
W: Write;
}
impl<T: ?Sized> Encode for &T
where
T: Encode,
{
fn encode_tag<W>(&self, to: W, tag: Tag) -> Result<()>
where
W: Write,
{
(**self).encode_tag(to, tag)
}
fn encode_element_header<W>(&self, to: W, de: DataElementHeader) -> Result<usize>
where
W: Write,
{
(**self).encode_element_header(to, de)
}
fn encode_item_header<W>(&self, to: W, len: u32) -> Result<()>
where
W: Write,
{
(**self).encode_item_header(to, len)
}
fn encode_item_delimiter<W>(&self, to: W) -> Result<()>
where
W: Write,
{
(**self).encode_item_delimiter(to)
}
fn encode_sequence_delimiter<W>(&self, to: W) -> Result<()>
where
W: Write,
{
(**self).encode_sequence_delimiter(to)
}
fn encode_primitive<W>(&self, to: W, value: &PrimitiveValue) -> Result<usize>
where
W: Write,
{
(**self).encode_primitive(to, value)
}
fn encode_offset_table<W>(&self, to: W, offset_table: &[u32]) -> Result<usize>
where
W: Write,
{
(**self).encode_offset_table(to, offset_table)
}
}
impl<T: ?Sized> Encode for Box<T>
where
T: Encode,
{
fn encode_tag<W>(&self, to: W, tag: Tag) -> Result<()>
where
W: Write,
{
(**self).encode_tag(to, tag)
}
fn encode_element_header<W>(&self, to: W, de: DataElementHeader) -> Result<usize>
where
W: Write,
{
(**self).encode_element_header(to, de)
}
fn encode_item_header<W>(&self, to: W, len: u32) -> Result<()>
where
W: Write,
{
(**self).encode_item_header(to, len)
}
fn encode_item_delimiter<W>(&self, to: W) -> Result<()>
where
W: Write,
{
(**self).encode_item_delimiter(to)
}
fn encode_sequence_delimiter<W>(&self, to: W) -> Result<()>
where
W: Write,
{
(**self).encode_sequence_delimiter(to)
}
fn encode_primitive<W>(&self, to: W, value: &PrimitiveValue) -> Result<usize>
where
W: Write,
{
(**self).encode_primitive(to, value)
}
fn encode_offset_table<W>(&self, to: W, offset_table: &[u32]) -> Result<usize>
where
W: Write,
{
(**self).encode_offset_table(to, offset_table)
}
}
pub trait EncodeTo<W: ?Sized> {
fn encode_tag(&self, to: &mut W, tag: Tag) -> Result<()>
where
W: Write;
fn encode_element_header(&self, to: &mut W, de: DataElementHeader) -> Result<usize>
where
W: Write;
fn encode_item_header(&self, to: &mut W, len: u32) -> Result<()>
where
W: Write;
fn encode_item_delimiter(&self, to: &mut W) -> Result<()>
where
W: Write;
fn encode_sequence_delimiter(&self, to: &mut W) -> Result<()>
where
W: Write;
fn encode_primitive(&self, to: &mut W, value: &PrimitiveValue) -> Result<usize>
where
W: Write;
fn encode_offset_table(&self, to: &mut W, offset_table: &[u32]) -> Result<usize>
where
W: Write;
}
impl<T, W: ?Sized> EncodeTo<W> for &T
where
T: EncodeTo<W>,
{
fn encode_tag(&self, to: &mut W, tag: Tag) -> Result<()>
where
W: Write,
{
(**self).encode_tag(to, tag)
}
fn encode_element_header(&self, to: &mut W, de: DataElementHeader) -> Result<usize>
where
W: Write,
{
(**self).encode_element_header(to, de)
}
fn encode_item_header(&self, to: &mut W, len: u32) -> Result<()>
where
W: Write,
{
(**self).encode_item_header(to, len)
}
fn encode_item_delimiter(&self, to: &mut W) -> Result<()>
where
W: Write,
{
(**self).encode_item_delimiter(to)
}
fn encode_sequence_delimiter(&self, to: &mut W) -> Result<()>
where
W: Write,
{
(**self).encode_sequence_delimiter(to)
}
fn encode_primitive(&self, to: &mut W, value: &PrimitiveValue) -> Result<usize>
where
W: Write,
{
(**self).encode_primitive(to, value)
}
fn encode_offset_table(&self, to: &mut W, offset_table: &[u32]) -> Result<usize>
where
W: Write,
{
(**self).encode_offset_table(to, offset_table)
}
}
impl<T: ?Sized, W: ?Sized> EncodeTo<W> for Box<T>
where
T: EncodeTo<W>,
{
fn encode_tag(&self, to: &mut W, tag: Tag) -> Result<()>
where
W: Write,
{
(**self).encode_tag(to, tag)
}
fn encode_element_header(&self, to: &mut W, de: DataElementHeader) -> Result<usize>
where
W: Write,
{
(**self).encode_element_header(to, de)
}
fn encode_item_header(&self, to: &mut W, len: u32) -> Result<()>
where
W: Write,
{
(**self).encode_item_header(to, len)
}
fn encode_item_delimiter(&self, to: &mut W) -> Result<()>
where
W: Write,
{
(**self).encode_item_delimiter(to)
}
fn encode_sequence_delimiter(&self, to: &mut W) -> Result<()>
where
W: Write,
{
(**self).encode_sequence_delimiter(to)
}
fn encode_primitive(&self, to: &mut W, value: &PrimitiveValue) -> Result<usize>
where
W: Write,
{
(**self).encode_primitive(to, value)
}
fn encode_offset_table(&self, to: &mut W, offset_table: &[u32]) -> Result<usize>
where
W: Write,
{
(**self).encode_offset_table(to, offset_table)
}
}
pub struct EncoderFor<T, W: ?Sized> {
inner: T,
phantom: PhantomData<W>,
}
impl<T, W: ?Sized> EncoderFor<T, W> {
pub fn new(encoder: T) -> Self {
EncoderFor {
inner: encoder,
phantom: PhantomData,
}
}
}
impl<T: fmt::Debug, W: ?Sized> fmt::Debug for EncoderFor<T, W> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("ImplicitVRLittleEndianEncoder")
.field("inner", &self.inner)
.field("phantom", &self.phantom)
.finish()
}
}
impl<T, W: ?Sized> Default for EncoderFor<T, W>
where
T: Default,
{
fn default() -> Self {
EncoderFor {
inner: T::default(),
phantom: PhantomData,
}
}
}
impl<T, W: ?Sized> BasicEncode for EncoderFor<T, W>
where
T: BasicEncode,
W: Write,
{
fn endianness(&self) -> Endianness {
self.inner.endianness()
}
fn encode_us<S>(&self, to: S, value: u16) -> io::Result<()>
where
S: Write,
{
self.inner.encode_us(to, value)
}
fn encode_ul<S>(&self, to: S, value: u32) -> io::Result<()>
where
S: Write,
{
self.inner.encode_ul(to, value)
}
fn encode_uv<S>(&self, to: S, value: u64) -> io::Result<()>
where
S: Write,
{
self.inner.encode_uv(to, value)
}
fn encode_ss<S>(&self, to: S, value: i16) -> io::Result<()>
where
S: Write,
{
self.inner.encode_ss(to, value)
}
fn encode_sl<S>(&self, to: S, value: i32) -> io::Result<()>
where
S: Write,
{
self.inner.encode_sl(to, value)
}
fn encode_sv<S>(&self, to: S, value: i64) -> io::Result<()>
where
S: Write,
{
self.inner.encode_sv(to, value)
}
fn encode_fl<S>(&self, to: S, value: f32) -> io::Result<()>
where
S: Write,
{
self.inner.encode_fl(to, value)
}
fn encode_fd<S>(&self, to: S, value: f64) -> io::Result<()>
where
S: Write,
{
self.inner.encode_fd(to, value)
}
}
impl<T, W: ?Sized> EncodeTo<W> for EncoderFor<T, W>
where
T: Encode,
W: Write,
{
fn encode_tag(&self, to: &mut W, tag: Tag) -> Result<()> {
self.inner.encode_tag(to, tag)
}
fn encode_element_header(&self, to: &mut W, de: DataElementHeader) -> Result<usize> {
self.inner.encode_element_header(to, de)
}
fn encode_item_header(&self, to: &mut W, len: u32) -> Result<()> {
self.inner.encode_item_header(to, len)
}
fn encode_item_delimiter(&self, to: &mut W) -> Result<()> {
self.inner.encode_item_delimiter(to)
}
fn encode_sequence_delimiter(&self, to: &mut W) -> Result<()> {
self.inner.encode_sequence_delimiter(to)
}
fn encode_primitive(&self, to: &mut W, value: &PrimitiveValue) -> Result<usize> {
self.inner.encode_primitive(to, value)
}
fn encode_offset_table(&self, to: &mut W, offset_table: &[u32]) -> Result<usize> {
self.inner.encode_offset_table(to, offset_table)
}
}
#[cfg(test)]
mod tests {
use super::*;
fn is_encode<T: Encode>(_encoder: &T) {}
fn is_encode_to<W: ?Sized, T: EncodeTo<W>>(_encoder: &T) {}
#[allow(unused)]
fn boxed_encode_is_encode<T>(encoder: T)
where
T: Encode,
T: Copy,
{
is_encode(&encoder);
is_encode_to::<dyn Write, _>(&EncoderFor::new(encoder));
let boxed = Box::new(encoder);
is_encode(&boxed);
is_encode_to::<dyn Write, _>(&EncoderFor::new(boxed));
}
}