use crate::util::n_times;
use dicom_core::dictionary::VirtualVr;
use dicom_core::header::{DataElementHeader, HasLength, Length, SequenceItemHeader, Tag, VR};
use dicom_core::value::deserialize::{
parse_date_partial, parse_datetime_partial, parse_time_partial,
};
use dicom_core::value::PrimitiveValue;
use dicom_dictionary_std::StandardDataDictionary;
use dicom_encoding::decode::basic::{BasicDecoder, LittleEndianBasicDecoder};
use dicom_encoding::decode::explicit_le::ExplicitVRLittleEndianDecoder;
use dicom_encoding::decode::{BasicDecode, DecodeFrom};
use dicom_encoding::text::{
validate_da, validate_dt, validate_tm, DefaultCharacterSetCodec, SpecificCharacterSet,
TextCodec, TextValidationOutcome,
};
use dicom_encoding::transfer_syntax::{DynDecoder, TransferSyntax};
use smallvec::smallvec;
use snafu::{Backtrace, OptionExt, ResultExt, Snafu};
use std::io::Read;
use std::{fmt::Debug, io::Seek, io::SeekFrom};
#[derive(Debug, Snafu)]
#[non_exhaustive]
pub enum Error {
#[snafu(display("Decoding in transfer syntax {} is unsupported", ts))]
UnsupportedTransferSyntax {
ts: &'static str,
backtrace: Backtrace,
},
#[snafu(display("Unsupported character set {:?}", charset))]
UnsupportedCharacterSet {
charset: SpecificCharacterSet,
backtrace: Backtrace,
},
#[snafu(display("Attempted to read non-primitive value at position {}", position))]
NonPrimitiveType { position: u64, backtrace: Backtrace },
#[snafu(display(
"Undefined value length of element tagged {} at position {}",
tag,
position
))]
UndefinedValueLength {
tag: Tag,
position: u64,
backtrace: Backtrace,
},
#[snafu(display("Could not decode element header at position {}", position))]
DecodeElementHeader {
position: u64,
#[snafu(backtrace)]
source: dicom_encoding::decode::Error,
},
#[snafu(display("Could not decode element header at position {}", position))]
DecodeItemHeader {
position: u64,
#[snafu(backtrace)]
source: dicom_encoding::decode::Error,
},
#[snafu(display("Could not decode text at position {}", position))]
DecodeText {
position: u64,
#[snafu(backtrace)]
source: dicom_encoding::text::DecodeTextError,
},
#[snafu(display("Could not read value from source at position {}", position))]
ReadValueData {
position: u64,
source: std::io::Error,
backtrace: Backtrace,
},
#[snafu(display(
"Could not move source cursor from position {} to {}",
position,
new_position
))]
SeekReader {
position: u64,
new_position: u64,
source: std::io::Error,
backtrace: Backtrace,
},
#[snafu(display("Failed value deserialization at position {}", position))]
DeserializeValue {
position: u64,
source: dicom_core::value::deserialize::Error,
},
#[snafu(display("Invalid integer value at position {}", position))]
ReadInt {
position: u64,
source: std::num::ParseIntError,
},
#[snafu(display("Invalid float value at position {}", position))]
ReadFloat {
position: u64,
source: std::num::ParseFloatError,
},
#[snafu(display("Invalid Date value element `{}` at position {}", string, position))]
InvalidDateValue {
position: u64,
string: String,
backtrace: Backtrace,
},
#[snafu(display("Invalid Time value element `{}` at position {}", string, position))]
InvalidTimeValue {
position: u64,
string: String,
backtrace: Backtrace,
},
#[snafu(display("Invalid DateTime value element `{}` at position {}", string, position))]
InvalidDateTimeValue {
position: u64,
string: String,
backtrace: Backtrace,
},
}
pub type Result<T, E = Error> = std::result::Result<T, E>;
pub trait StatefulDecode {
type Reader: Read;
fn decode_header(&mut self) -> Result<DataElementHeader>;
fn decode_item_header(&mut self) -> Result<SequenceItemHeader>;
fn read_value(&mut self, header: &DataElementHeader) -> Result<PrimitiveValue>;
fn read_value_preserved(&mut self, header: &DataElementHeader) -> Result<PrimitiveValue>;
fn read_value_bytes(&mut self, header: &DataElementHeader) -> Result<PrimitiveValue>;
fn read_to_vec(&mut self, length: u32, vec: &mut Vec<u8>) -> Result<()>;
fn read_u32_to_vec(&mut self, length: u32, vec: &mut Vec<u32>) -> Result<()>;
fn read_to<W>(&mut self, length: u32, out: W) -> Result<()>
where
Self: Sized,
W: std::io::Write;
fn skip_bytes(&mut self, length: u32) -> Result<()>;
fn seek(&mut self, position: u64) -> Result<()>
where
Self::Reader: Seek;
fn position(&self) -> u64;
}
pub type DynStatefulDecoder<S> = StatefulDecoder<DynDecoder<S>, S>;
const PARSER_BUFFER_CAPACITY: usize = 2048;
#[derive(Debug)]
pub struct StatefulDecoder<D, S, BD = BasicDecoder, TC = SpecificCharacterSet> {
from: S,
decoder: D,
basic: BD,
text: TC,
buffer: Vec<u8>,
position: u64,
signed_pixeldata: Option<bool>,
}
impl<S> StatefulDecoder<DynDecoder<S>, S> {
pub fn new_with(
from: S,
ts: &TransferSyntax,
charset: SpecificCharacterSet,
position: u64,
) -> Result<Self>
where
S: Read,
{
let basic = ts.basic_decoder();
let decoder = ts
.decoder_for::<S>()
.context(UnsupportedTransferSyntaxSnafu { ts: ts.name() })?;
Ok(StatefulDecoder::new_with_position(
from, decoder, basic, charset, position,
))
}
pub fn new_with_ts(from: S, ts: &TransferSyntax, position: u64) -> Result<Self>
where
S: Read,
{
Self::new_with(from, ts, SpecificCharacterSet::default(), position)
}
}
pub type FileHeaderParser<S> = StatefulDecoder<
ExplicitVRLittleEndianDecoder,
S,
LittleEndianBasicDecoder,
DefaultCharacterSetCodec,
>;
impl<S> FileHeaderParser<S>
where
S: Read,
{
pub fn file_header_parser(from: S) -> Self {
Self {
from,
basic: LittleEndianBasicDecoder,
decoder: ExplicitVRLittleEndianDecoder::default(),
text: DefaultCharacterSetCodec,
buffer: Vec::with_capacity(PARSER_BUFFER_CAPACITY),
position: 0,
signed_pixeldata: None,
}
}
}
impl<D, S, BD, TC> StatefulDecoder<D, S, BD, TC>
where
BD: BasicDecode,
TC: TextCodec,
{
#[inline]
pub fn new(from: S, decoder: D, basic: BD, text: TC) -> StatefulDecoder<D, S, BD, TC> {
Self::new_with_position(from, decoder, basic, text, 0)
}
#[inline]
pub fn new_with_position(from: S, decoder: D, basic: BD, text: TC, position: u64) -> Self {
Self {
from,
basic,
decoder,
text,
buffer: Vec::with_capacity(PARSER_BUFFER_CAPACITY),
position,
signed_pixeldata: None,
}
}
}
impl<D, S, BD, TC> StatefulDecoder<D, S, BD, TC>
where
S: Seek,
BD: BasicDecode,
TC: TextCodec,
{
pub fn new_positioned(
mut from: S,
decoder: D,
basic: BD,
text: TC,
) -> Result<Self, std::io::Error> {
let position = from.stream_position()?;
Ok(Self::new_with_position(
from, decoder, basic, text, position,
))
}
}
impl<D, S, BD, TC> StatefulDecoder<D, S, BD, TC>
where
D: DecodeFrom<S>,
BD: BasicDecode,
S: Read,
TC: TextCodec,
{
fn require_known_length(&self, header: &DataElementHeader) -> Result<usize> {
header
.length()
.get()
.map(|len| len as usize)
.context(UndefinedValueLengthSnafu {
position: self.position,
tag: header.tag,
})
}
fn read_value_tag(&mut self, header: &DataElementHeader) -> Result<PrimitiveValue> {
let len = self.require_known_length(header)?;
let ntags = len >> 2;
let parts: Result<_> = n_times(ntags)
.map(|_| {
self.basic
.decode_tag(&mut self.from)
.context(ReadValueDataSnafu {
position: self.position,
})
})
.collect();
self.position += len as u64;
Ok(PrimitiveValue::Tags(parts?))
}
fn read_value_ob(&mut self, header: &DataElementHeader) -> Result<PrimitiveValue> {
let len = self.require_known_length(header)?;
let mut buf = smallvec![0u8; len];
self.from.read_exact(&mut buf).context(ReadValueDataSnafu {
position: self.position,
})?;
self.position += len as u64;
Ok(PrimitiveValue::U8(buf))
}
fn read_value_strs(&mut self, header: &DataElementHeader) -> Result<PrimitiveValue> {
let len = self.require_known_length(header)?;
self.buffer.resize_with(len, Default::default);
self.from
.read_exact(&mut self.buffer)
.context(ReadValueDataSnafu {
position: self.position,
})?;
let parts: Result<_> = match header.vr() {
VR::AE | VR::CS | VR::AS => self
.buffer
.split(|v| *v == b'\\')
.map(|slice| {
DefaultCharacterSetCodec
.decode(slice)
.context(DecodeTextSnafu {
position: self.position,
})
})
.collect(),
_ => self
.buffer
.split(|v| *v == b'\\')
.map(|slice| {
self.text.decode(slice).context(DecodeTextSnafu {
position: self.position,
})
})
.collect(),
};
self.position += len as u64;
Ok(PrimitiveValue::Strs(parts?))
}
fn read_value_str(&mut self, header: &DataElementHeader) -> Result<PrimitiveValue> {
let len = self.require_known_length(header)?;
self.buffer.resize_with(len, Default::default);
self.from
.read_exact(&mut self.buffer)
.context(ReadValueDataSnafu {
position: self.position,
})?;
self.position += len as u64;
Ok(PrimitiveValue::Str(
self.text
.decode(&self.buffer[..])
.context(DecodeTextSnafu {
position: self.position,
})?,
))
}
fn read_value_ss(&mut self, header: &DataElementHeader) -> Result<PrimitiveValue> {
let len = self.require_known_length(header)?;
let n = len >> 1;
let mut vec = smallvec![0; n];
self.basic
.decode_ss_into(&mut self.from, &mut vec[..])
.context(ReadValueDataSnafu {
position: self.position,
})?;
self.position += len as u64;
Ok(PrimitiveValue::I16(vec))
}
fn read_value_fl(&mut self, header: &DataElementHeader) -> Result<PrimitiveValue> {
let len = self.require_known_length(header)?;
let n = len >> 2;
let mut vec = smallvec![0.; n];
self.basic
.decode_fl_into(&mut self.from, &mut vec[..])
.context(ReadValueDataSnafu {
position: self.position,
})?;
self.position += len as u64;
Ok(PrimitiveValue::F32(vec))
}
fn read_value_da(&mut self, header: &DataElementHeader) -> Result<PrimitiveValue> {
let len = self.require_known_length(header)?;
self.buffer.resize_with(len, Default::default);
self.from
.read_exact(&mut self.buffer)
.context(ReadValueDataSnafu {
position: self.position,
})?;
let buf = trim_trail_empty_bytes(&self.buffer);
if buf.is_empty() {
return Ok(PrimitiveValue::Empty);
}
if validate_da(buf) != TextValidationOutcome::Ok {
let lossy_str = DefaultCharacterSetCodec
.decode(buf)
.unwrap_or_else(|_| "[byte stream]".to_string());
return InvalidDateValueSnafu {
position: self.position,
string: lossy_str,
}
.fail();
}
let vec: Result<_> = buf
.split(|b| *b == b'\\')
.map(|part| {
parse_date_partial(part)
.map(|t| t.0)
.context(DeserializeValueSnafu {
position: self.position,
})
})
.collect();
self.position += len as u64;
Ok(PrimitiveValue::Date(vec?))
}
fn read_value_ds(&mut self, header: &DataElementHeader) -> Result<PrimitiveValue> {
let len = self.require_known_length(header)?;
self.buffer.resize_with(len, Default::default);
self.from
.read_exact(&mut self.buffer)
.context(ReadValueDataSnafu {
position: self.position,
})?;
let buf = trim_trail_empty_bytes(&self.buffer);
if buf.is_empty() {
return Ok(PrimitiveValue::Empty);
}
let parts: Result<_> = buf
.split(|b| *b == b'\\')
.map(|slice| {
let codec = DefaultCharacterSetCodec;
let txt = codec.decode(slice).context(DecodeTextSnafu {
position: self.position,
})?;
let txt = txt.trim();
txt.parse::<f64>().context(ReadFloatSnafu {
position: self.position,
})
})
.collect();
self.position += len as u64;
Ok(PrimitiveValue::F64(parts?))
}
fn read_value_dt(&mut self, header: &DataElementHeader) -> Result<PrimitiveValue> {
let len = self.require_known_length(header)?;
self.buffer.resize_with(len, Default::default);
self.from
.read_exact(&mut self.buffer)
.context(ReadValueDataSnafu {
position: self.position,
})?;
let buf = trim_trail_empty_bytes(&self.buffer);
if buf.is_empty() {
return Ok(PrimitiveValue::Empty);
}
if validate_dt(buf) != TextValidationOutcome::Ok {
let lossy_str = DefaultCharacterSetCodec
.decode(buf)
.unwrap_or_else(|_| "[byte stream]".to_string());
return InvalidDateTimeValueSnafu {
position: self.position,
string: lossy_str,
}
.fail();
}
let vec: Result<_> = buf
.split(|b| *b == b'\\')
.map(|part| {
parse_datetime_partial(part).context(DeserializeValueSnafu {
position: self.position,
})
})
.collect();
self.position += len as u64;
Ok(PrimitiveValue::DateTime(vec?))
}
fn read_value_is(&mut self, header: &DataElementHeader) -> Result<PrimitiveValue> {
let len = self.require_known_length(header)?;
self.buffer.resize_with(len, Default::default);
self.from
.read_exact(&mut self.buffer)
.context(ReadValueDataSnafu {
position: self.position,
})?;
let buf = trim_trail_empty_bytes(&self.buffer);
if buf.is_empty() {
return Ok(PrimitiveValue::Empty);
}
let parts: Result<_> = buf
.split(|v| *v == b'\\')
.map(|slice| {
let codec = DefaultCharacterSetCodec;
let txt = codec.decode(slice).context(DecodeTextSnafu {
position: self.position,
})?;
let txt = txt.trim();
txt.parse::<i32>().context(ReadIntSnafu {
position: self.position,
})
})
.collect();
self.position += len as u64;
Ok(PrimitiveValue::I32(parts?))
}
fn read_value_tm(&mut self, header: &DataElementHeader) -> Result<PrimitiveValue> {
let len = self.require_known_length(header)?;
self.buffer.resize_with(len, Default::default);
self.from
.read_exact(&mut self.buffer)
.context(ReadValueDataSnafu {
position: self.position,
})?;
let buf = trim_trail_empty_bytes(&self.buffer);
if buf.is_empty() {
return Ok(PrimitiveValue::Empty);
}
if validate_tm(buf) != TextValidationOutcome::Ok {
let lossy_str = DefaultCharacterSetCodec
.decode(buf)
.unwrap_or_else(|_| "[byte stream]".to_string());
return InvalidTimeValueSnafu {
position: self.position,
string: lossy_str,
}
.fail();
}
let vec: std::result::Result<_, _> = buf
.split(|b| *b == b'\\')
.map(|part| {
parse_time_partial(part)
.map(|t| t.0)
.context(DeserializeValueSnafu {
position: self.position,
})
})
.collect();
self.position += len as u64;
Ok(PrimitiveValue::Time(vec?))
}
fn read_value_od(&mut self, header: &DataElementHeader) -> Result<PrimitiveValue> {
let len = self.require_known_length(header)?;
let n = len >> 3;
let mut vec = smallvec![0.; n];
self.basic
.decode_fd_into(&mut self.from, &mut vec[..])
.context(ReadValueDataSnafu {
position: self.position,
})?;
self.position += len as u64;
Ok(PrimitiveValue::F64(vec))
}
fn read_value_ul(&mut self, header: &DataElementHeader) -> Result<PrimitiveValue> {
let len = self.require_known_length(header)?;
let n = len >> 2;
let mut vec = smallvec![0u32; n];
self.basic
.decode_ul_into(&mut self.from, &mut vec[..])
.context(ReadValueDataSnafu {
position: self.position,
})?;
self.position += len as u64;
Ok(PrimitiveValue::U32(vec))
}
fn read_u32(&mut self, n: usize, vec: &mut Vec<u32>) -> Result<()> {
let base = vec.len();
vec.resize(base + n, 0);
self.basic
.decode_ul_into(&mut self.from, &mut vec[base..])
.context(ReadValueDataSnafu {
position: self.position,
})?;
self.position += n as u64 * 4;
Ok(())
}
fn read_value_us(&mut self, header: &DataElementHeader) -> Result<PrimitiveValue> {
let len = self.require_known_length(header)?;
let n = len >> 1;
let mut vec = smallvec![0; n];
self.basic
.decode_us_into(&mut self.from, &mut vec[..])
.context(ReadValueDataSnafu {
position: self.position,
})?;
self.position += len as u64;
if header.tag == Tag(0x0028, 0x0103) {
self.signed_pixeldata = vec.first().map(|rep| *rep != 0);
}
Ok(PrimitiveValue::U16(vec))
}
fn read_value_uv(&mut self, header: &DataElementHeader) -> Result<PrimitiveValue> {
let len = self.require_known_length(header)?;
let n = len >> 3;
let mut vec = smallvec![0; n];
self.basic
.decode_uv_into(&mut self.from, &mut vec[..])
.context(ReadValueDataSnafu {
position: self.position,
})?;
self.position += len as u64;
Ok(PrimitiveValue::U64(vec))
}
fn read_value_sl(&mut self, header: &DataElementHeader) -> Result<PrimitiveValue> {
let len = self.require_known_length(header)?;
let n = len >> 2;
let mut vec = smallvec![0; n];
self.basic
.decode_sl_into(&mut self.from, &mut vec[..])
.context(ReadValueDataSnafu {
position: self.position,
})?;
self.position += len as u64;
Ok(PrimitiveValue::I32(vec))
}
fn read_value_sv(&mut self, header: &DataElementHeader) -> Result<PrimitiveValue> {
let len = self.require_known_length(header)?;
let n = len >> 3;
let mut vec = smallvec![0; n];
self.basic
.decode_sv_into(&mut self.from, &mut vec[..])
.context(ReadValueDataSnafu {
position: self.position,
})?;
self.position += len as u64;
Ok(PrimitiveValue::I64(vec))
}
}
impl<S, D, BD> StatefulDecoder<D, S, BD>
where
D: DecodeFrom<S>,
BD: BasicDecode,
S: Read,
{
fn set_character_set(&mut self, charset: SpecificCharacterSet) -> Result<()> {
self.text = charset;
Ok(())
}
fn read_value_cs(&mut self, header: &DataElementHeader) -> Result<PrimitiveValue> {
let out = self.read_value_strs(header)?;
let parts = match &out {
PrimitiveValue::Strs(parts) => parts,
_ => unreachable!(),
};
if header.tag == Tag(0x0008, 0x0005) {
if let Some(charset) = parts.first().map(|x| x.as_ref()).and_then(|name| {
SpecificCharacterSet::from_code(name).or_else(|| {
tracing::warn!("Unsupported character set `{}`, ignoring", name);
None
})
}) {
self.set_character_set(charset)?;
}
}
Ok(out)
}
}
impl<D> StatefulDecode for &'_ mut D
where
D: StatefulDecode,
{
type Reader = D::Reader;
fn decode_header(&mut self) -> Result<DataElementHeader> {
(**self).decode_header()
}
fn decode_item_header(&mut self) -> Result<SequenceItemHeader> {
(**self).decode_item_header()
}
fn read_value(&mut self, header: &DataElementHeader) -> Result<PrimitiveValue> {
(**self).read_value(header)
}
fn read_value_preserved(&mut self, header: &DataElementHeader) -> Result<PrimitiveValue> {
(**self).read_value_preserved(header)
}
fn read_value_bytes(&mut self, header: &DataElementHeader) -> Result<PrimitiveValue> {
(**self).read_value_bytes(header)
}
fn read_to_vec(&mut self, length: u32, vec: &mut Vec<u8>) -> Result<()> {
(**self).read_to_vec(length, vec)
}
fn read_u32_to_vec(&mut self, length: u32, vec: &mut Vec<u32>) -> Result<()> {
(**self).read_u32_to_vec(length, vec)
}
fn read_to<W>(&mut self, length: u32, out: W) -> Result<()>
where
Self: Sized,
W: std::io::Write,
{
(**self).read_to(length, out)
}
fn skip_bytes(&mut self, length: u32) -> Result<()> {
(**self).skip_bytes(length)
}
fn position(&self) -> u64 {
(**self).position()
}
fn seek(&mut self, position: u64) -> Result<()>
where
Self::Reader: Seek,
{
(**self).seek(position)
}
}
impl<D, S, BD> StatefulDecode for StatefulDecoder<D, S, BD>
where
D: DecodeFrom<S>,
BD: BasicDecode,
S: Read,
{
type Reader = S;
fn decode_header(&mut self) -> Result<DataElementHeader> {
let mut header = self
.decoder
.decode_header(&mut self.from)
.context(DecodeElementHeaderSnafu {
position: self.position,
})
.map(|(header, bytes_read)| {
self.position += bytes_read as u64;
header
})
.map_err(From::from)?;
if let Some(vr) = self.determine_vr_based_on_pixel_representation(header.tag) {
header.vr = vr;
}
Ok(header)
}
fn decode_item_header(&mut self) -> Result<SequenceItemHeader> {
self.decoder
.decode_item_header(&mut self.from)
.context(DecodeItemHeaderSnafu {
position: self.position,
})
.map(|header| {
self.position += 8;
header
})
.map_err(From::from)
}
fn read_value(&mut self, header: &DataElementHeader) -> Result<PrimitiveValue> {
if header.length() == Length(0) {
return Ok(PrimitiveValue::Empty);
}
match header.vr() {
VR::SQ => {
NonPrimitiveTypeSnafu {
position: self.position,
}
.fail()
}
VR::AT => self.read_value_tag(header),
VR::AE | VR::AS | VR::PN | VR::SH | VR::LO | VR::UC | VR::UI => {
self.read_value_strs(header)
}
VR::CS => self.read_value_cs(header),
VR::UT | VR::ST | VR::UR | VR::LT => self.read_value_str(header),
VR::UN | VR::OB => self.read_value_ob(header),
VR::US | VR::OW => self.read_value_us(header),
VR::SS => self.read_value_ss(header),
VR::DA => self.read_value_da(header),
VR::DT => self.read_value_dt(header),
VR::TM => self.read_value_tm(header),
VR::DS => self.read_value_ds(header),
VR::FD | VR::OD => self.read_value_od(header),
VR::FL | VR::OF => self.read_value_fl(header),
VR::IS => self.read_value_is(header),
VR::SL => self.read_value_sl(header),
VR::SV => self.read_value_sv(header),
VR::OL | VR::UL => self.read_value_ul(header),
VR::OV | VR::UV => self.read_value_uv(header),
}
}
fn read_value_preserved(&mut self, header: &DataElementHeader) -> Result<PrimitiveValue> {
if header.length() == Length(0) {
return Ok(PrimitiveValue::Empty);
}
match header.vr() {
VR::SQ => {
NonPrimitiveTypeSnafu {
position: self.position,
}
.fail()
}
VR::AT => self.read_value_tag(header),
VR::AE
| VR::AS
| VR::PN
| VR::SH
| VR::LO
| VR::UC
| VR::UI
| VR::IS
| VR::DS
| VR::DA
| VR::TM
| VR::DT => self.read_value_strs(header),
VR::CS => self.read_value_cs(header),
VR::UT | VR::ST | VR::UR | VR::LT => self.read_value_str(header),
VR::UN | VR::OB => self.read_value_ob(header),
VR::US | VR::OW => self.read_value_us(header),
VR::SS => self.read_value_ss(header),
VR::FD | VR::OD => self.read_value_od(header),
VR::FL | VR::OF => self.read_value_fl(header),
VR::SL => self.read_value_sl(header),
VR::OL | VR::UL => self.read_value_ul(header),
VR::SV => self.read_value_sv(header),
VR::OV | VR::UV => self.read_value_uv(header),
}
}
fn read_value_bytes(&mut self, header: &DataElementHeader) -> Result<PrimitiveValue> {
if header.length() == Length(0) {
return Ok(PrimitiveValue::Empty);
}
match header.vr() {
VR::SQ => {
NonPrimitiveTypeSnafu {
position: self.position,
}
.fail()
}
_ => self.read_value_ob(header),
}
}
fn position(&self) -> u64 {
self.position
}
fn read_to_vec(&mut self, length: u32, vec: &mut Vec<u8>) -> Result<()> {
self.read_to(length, vec)
}
fn read_u32_to_vec(&mut self, length: u32, vec: &mut Vec<u32>) -> Result<()> {
self.read_u32((length >> 2) as usize, vec)
}
fn read_to<W>(&mut self, length: u32, mut out: W) -> Result<()>
where
Self: Sized,
W: std::io::Write,
{
let length = u64::from(length);
std::io::copy(&mut self.from.by_ref().take(length), &mut out).context(
ReadValueDataSnafu {
position: self.position,
},
)?;
self.position += length;
Ok(())
}
fn skip_bytes(&mut self, length: u32) -> Result<()> {
std::io::copy(
&mut self.from.by_ref().take(u64::from(length)),
&mut std::io::sink(),
)
.context(ReadValueDataSnafu {
position: self.position,
})?;
self.position += u64::from(length);
Ok(())
}
fn seek(&mut self, position: u64) -> Result<()>
where
Self::Reader: Seek,
{
self.from
.seek(SeekFrom::Start(position))
.context(SeekReaderSnafu {
position: self.position,
new_position: position,
})
.map(|_| ())
}
}
impl<D, S, BD> StatefulDecoder<D, S, BD>
where
D: DecodeFrom<S>,
BD: BasicDecode,
S: Read,
{
fn determine_vr_based_on_pixel_representation(&self, tag: Tag) -> Option<VR> {
use dicom_core::dictionary::DataDictionary;
if self.signed_pixeldata == Some(true)
&& StandardDataDictionary.by_tag(tag).map(|e| e.vr) == Some(VirtualVr::Xs)
{
Some(VR::SS)
} else {
None
}
}
}
fn trim_trail_empty_bytes(mut x: &[u8]) -> &[u8] {
while x.last() == Some(&b' ') || x.last() == Some(&b'\0') {
x = &x[..x.len() - 1];
}
x
}
#[cfg(test)]
mod tests {
use super::{StatefulDecode, StatefulDecoder};
use dicom_core::header::{DataElementHeader, HasLength, Header, Length, SequenceItemHeader};
use dicom_core::{Tag, VR};
use dicom_encoding::decode::basic::LittleEndianBasicDecoder;
use dicom_encoding::decode::{
explicit_le::ExplicitVRLittleEndianDecoder, implicit_le::ImplicitVRLittleEndianDecoder,
};
use dicom_encoding::text::{SpecificCharacterSet, TextCodec};
use std::io::{Cursor, Seek, SeekFrom};
const RAW: &'static [u8; 62] = &[
0x02, 0x00, 0x02, 0x00, 0x55, 0x49, 0x1a, 0x00, 0x31, 0x2e, 0x32, 0x2e, 0x38, 0x34, 0x30,
0x2e, 0x31, 0x30, 0x30, 0x30, 0x38, 0x2e, 0x35, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e,
0x31, 0x2e, 0x31, 0x00, 0x02, 0x00, 0x10, 0x00, 0x55, 0x49, 0x14, 0x00, 0x31, 0x2e, 0x32,
0x2e, 0x38, 0x34, 0x30, 0x2e, 0x31, 0x30, 0x30, 0x30, 0x38, 0x2e, 0x31, 0x2e, 0x32, 0x2e,
0x31, 0x00,
];
fn is_stateful_decoder<T>(_: &T)
where
T: StatefulDecode,
{
}
#[test]
fn decode_data_elements() {
let mut cursor = Cursor::new(&RAW[..]);
let mut decoder = StatefulDecoder::new(
&mut cursor,
ExplicitVRLittleEndianDecoder::default(),
LittleEndianBasicDecoder,
SpecificCharacterSet::default(),
);
is_stateful_decoder(&decoder);
{
let elem = decoder.decode_header().expect("should find an element");
assert_eq!(elem.tag(), Tag(2, 2));
assert_eq!(elem.vr(), VR::UI);
assert_eq!(elem.length(), Length(26));
assert_eq!(decoder.position(), 8);
let value = decoder
.read_value(&elem)
.expect("value after element header");
assert_eq!(value.multiplicity(), 1);
assert_eq!(value.string(), Ok("1.2.840.10008.5.1.4.1.1.1\0"));
assert_eq!(decoder.position(), 8 + 26);
}
{
let elem = decoder.decode_header().expect("should find an element");
assert_eq!(elem.tag(), Tag(2, 16));
assert_eq!(elem.vr(), VR::UI);
assert_eq!(elem.length(), Length(20));
assert_eq!(decoder.position(), 8 + 26 + 8);
let value = decoder
.read_value(&elem)
.expect("value after element header");
assert_eq!(value.multiplicity(), 1);
assert_eq!(value.string(), Ok("1.2.840.10008.1.2.1\0"));
assert_eq!(decoder.position(), 8 + 26 + 8 + 20);
decoder.seek(8 + 26 + 8).unwrap();
let value = decoder
.read_value(&elem)
.expect("value after element header");
assert_eq!(value.multiplicity(), 1);
assert_eq!(value.string(), Ok("1.2.840.10008.1.2.1\0"));
assert_eq!(decoder.position(), 8 + 26 + 8 + 20 + 20);
}
}
#[test]
fn update_character_set() {
const RAW: &'static [u8; 18] = &[
0x08, 0x00, 0x05, 0x00, b'C', b'S', 0x0a, 0x00, b'I', b'S', b'O', b'_', b'I', b'R', b' ', b'1', b'9', b'2',
];
let mut cursor = &RAW[..];
let mut decoder = StatefulDecoder::new(
&mut cursor,
ExplicitVRLittleEndianDecoder::default(),
LittleEndianBasicDecoder,
SpecificCharacterSet::default(),
);
is_stateful_decoder(&decoder);
let header = decoder
.decode_header()
.expect("should find an element header");
assert_eq!(
header,
DataElementHeader {
tag: Tag(0x0008, 0x0005),
vr: VR::CS,
len: Length(10),
}
);
let value = decoder
.read_value_preserved(&header)
.expect("should read a value");
assert_eq!(value.string(), Ok("ISO_IR 192"));
assert_eq!(decoder.text.name(), "ISO_IR 192",);
}
#[test]
fn decode_data_elements_with_position() {
let data = {
let mut x = vec![0; 128];
x.extend(RAW);
x
};
let mut cursor = Cursor::new(&data[..]);
cursor.seek(SeekFrom::Start(128)).unwrap();
let mut decoder = StatefulDecoder::new_with_position(
&mut cursor,
ExplicitVRLittleEndianDecoder::default(),
LittleEndianBasicDecoder,
SpecificCharacterSet::default(),
128,
);
is_stateful_decoder(&decoder);
{
let elem = decoder.decode_header().expect("should find an element");
assert_eq!(elem.tag(), Tag(2, 2));
assert_eq!(elem.vr(), VR::UI);
assert_eq!(elem.length(), Length(26));
assert_eq!(decoder.position(), 128 + 8);
let value = decoder
.read_value(&elem)
.expect("value after element header");
assert_eq!(value.multiplicity(), 1);
assert_eq!(value.string(), Ok("1.2.840.10008.5.1.4.1.1.1\0"));
assert_eq!(decoder.position(), 128 + 8 + 26);
}
{
let elem = decoder.decode_header().expect("should find an element");
assert_eq!(elem.tag(), Tag(2, 16));
assert_eq!(elem.vr(), VR::UI);
assert_eq!(elem.length(), Length(20));
assert_eq!(decoder.position(), 128 + 8 + 26 + 8);
let value = decoder
.read_value(&elem)
.expect("value after element header");
assert_eq!(value.multiplicity(), 1);
assert_eq!(value.string(), Ok("1.2.840.10008.1.2.1\0"));
assert_eq!(decoder.position(), 128 + 8 + 26 + 8 + 20);
decoder.seek(128 + 8 + 26 + 8).unwrap();
let value = decoder
.read_value(&elem)
.expect("value after element header");
assert_eq!(value.multiplicity(), 1);
assert_eq!(value.string(), Ok("1.2.840.10008.1.2.1\0"));
assert_eq!(decoder.position(), 128 + 8 + 26 + 8 + 20 + 20);
}
}
#[test]
fn decode_nested_datasets() {
const RAW: &'static [u8; 138] = &[
0x01, 0x20, 0x00, 0x90, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0x00, 0xE0, 0x72, 0x00, 0x00, 0x00, 0x08, 0x00, 0x15, 0x11, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x08, 0x00, 0x40, 0x11, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0x00, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0x08, 0x00, 0x50, 0x11, 0x1a, 0x00, 0x00, 0x00, b'1', b'.', b'2', b'.', b'8', b'4', b'0', b'.', b'1', b'0', b'0', b'0', b'8', b'.',
b'5', b'.', b'1', b'.', b'4', b'.', b'1', b'.', b'1', b'.', b'7', b'\0',
0xFE, 0xFF, 0x0D, 0xE0, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xDD, 0xE0, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0x0D, 0xE0, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xDD, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x50, 0x20, 0x20, 0x00, 0x08, 0x00, 0x00, 0x00, b'I', b'D', b'E', b'N', b'T', b'I', b'T', b'Y', 0xFE, 0xFF, 0xDD, 0xE0, 0x00, 0x00, 0x00, 0x00, ];
let mut cursor = &RAW[..];
let mut decoder = StatefulDecoder::new(
&mut cursor,
ImplicitVRLittleEndianDecoder::default(),
LittleEndianBasicDecoder,
SpecificCharacterSet::default(),
);
is_stateful_decoder(&decoder);
let header = decoder
.decode_header()
.expect("should find an element header");
assert_eq!(header.tag(), Tag(0x2001, 0x9000));
assert_eq!(header.vr(), VR::UN);
assert!(header.length().is_undefined());
assert_eq!(decoder.position(), 8);
let item_header = decoder
.decode_item_header()
.expect("should find an item header");
assert_eq!(item_header, SequenceItemHeader::Item { len: Length(114) });
assert_eq!(decoder.position(), 16);
let header = decoder
.decode_header()
.expect("should find an element header");
assert_eq!(header.tag(), Tag(0x0008, 0x1115));
assert_eq!(header.vr(), VR::SQ);
assert!(header.length().is_undefined());
assert_eq!(decoder.position(), 24);
let item_header = decoder
.decode_item_header()
.expect("should find an item header (ReferencedSeriesSequence)");
assert!(matches!(
item_header,
SequenceItemHeader::Item {
len,
} if len.is_undefined()
));
assert_eq!(decoder.position(), 32);
let header = decoder
.decode_header()
.expect("should find an element header");
assert_eq!(header.tag(), Tag(0x0008, 0x1140));
assert_eq!(header.vr(), VR::SQ);
assert!(header.length().is_undefined());
assert_eq!(decoder.position(), 40);
let item_header = decoder
.decode_item_header()
.expect("should find an item header (ReferencedImageSequence)");
assert!(matches!(
item_header,
SequenceItemHeader::Item {
len,
} if len.is_undefined()
));
assert_eq!(decoder.position(), 48);
let header = decoder
.decode_header()
.expect("should find an element header");
assert_eq!(header.tag(), Tag(0x0008, 0x1150));
assert_eq!(header.vr(), VR::UI);
assert_eq!(header.length(), Length(26));
assert_eq!(decoder.position(), 56);
let value = decoder
.read_value(&header)
.expect("should find a value after element header");
assert_eq!(value.to_str(), "1.2.840.10008.5.1.4.1.1.7");
assert_eq!(decoder.position(), 82);
let item_header = decoder
.decode_item_header()
.expect("should find item delimiter");
assert_eq!(item_header, SequenceItemHeader::ItemDelimiter);
assert_eq!(decoder.position(), 90);
let item_header = decoder
.decode_item_header()
.expect("should find sequence delimiter");
assert_eq!(item_header, SequenceItemHeader::SequenceDelimiter);
assert_eq!(decoder.position(), 98);
let item_header = decoder
.decode_item_header()
.expect("should find item delimiter");
assert_eq!(item_header, SequenceItemHeader::ItemDelimiter);
assert_eq!(decoder.position(), 106);
let item_header = decoder
.decode_item_header()
.expect("should find sequence delimiter");
assert_eq!(item_header, SequenceItemHeader::SequenceDelimiter);
assert_eq!(decoder.position(), 114);
let header = decoder
.decode_header()
.expect("should find an element header");
assert_eq!(header.tag(), Tag(0x2050, 0x0020));
assert_eq!(header.vr(), VR::CS);
assert_eq!(header.length(), Length(8));
assert_eq!(decoder.position(), 122);
let value = decoder
.read_value(&header)
.expect("value after element header");
assert_eq!(value.multiplicity(), 1);
assert_eq!(value.to_str(), "IDENTITY");
assert_eq!(decoder.position(), 130);
let item_header = decoder
.decode_item_header()
.expect("should find an item header");
assert_eq!(item_header, SequenceItemHeader::SequenceDelimiter);
assert_eq!(decoder.position(), 138);
}
#[test]
fn decode_and_use_pixel_representation() {
const RAW: &'static [u8; 20] = &[
0x28, 0x00, 0x03, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x28, 0x00, 0x20, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, ];
let mut cursor = &RAW[..];
let mut decoder = StatefulDecoder::new(
&mut cursor,
ImplicitVRLittleEndianDecoder::default(),
LittleEndianBasicDecoder,
SpecificCharacterSet::default(),
);
is_stateful_decoder(&decoder);
let header_1 = decoder
.decode_header()
.expect("should find an element header");
assert_eq!(
header_1,
DataElementHeader {
tag: Tag(0x0028, 0x0103),
vr: VR::US,
len: Length(2),
}
);
decoder
.read_value(&header_1)
.expect("Can read Pixel Representation");
let header_2 = decoder
.decode_header()
.expect("should find an element header");
assert_eq!(
header_2,
DataElementHeader {
tag: Tag(0x0028, 0x0120),
vr: VR::SS,
len: Length(2),
}
);
}
}