use crate::decode::basic::LittleEndianBasicDecoder;
use crate::decode::{
BadSequenceHeaderSnafu, BasicDecode, DecodeFrom, ReadHeaderTagSnafu, ReadLengthSnafu,
ReadTagSnafu, Result,
};
use crate::Decode;
use byteordered::byteorder::{ByteOrder, LittleEndian};
use dicom_core::dictionary::{DataDictionary, DataDictionaryEntry};
use dicom_core::header::{DataElementHeader, Length, SequenceItemHeader};
use dicom_core::{Tag, VR};
use dicom_dictionary_std::StandardDataDictionary;
use snafu::ResultExt;
use std::fmt;
use std::io::Read;
pub type StandardImplicitVRLittleEndianDecoder =
ImplicitVRLittleEndianDecoder<StandardDataDictionary>;
pub struct ImplicitVRLittleEndianDecoder<D> {
dict: D,
basic: LittleEndianBasicDecoder,
}
impl<D> fmt::Debug for ImplicitVRLittleEndianDecoder<D> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("ImplicitVRLittleEndianDecoder")
.field("dict", &"«omitted»")
.field("basic", &self.basic)
.finish()
}
}
impl ImplicitVRLittleEndianDecoder<StandardDataDictionary> {
pub fn with_std_dict() -> Self {
ImplicitVRLittleEndianDecoder {
dict: StandardDataDictionary,
basic: LittleEndianBasicDecoder,
}
}
pub fn new() -> Self {
Self::with_std_dict()
}
}
impl Default for ImplicitVRLittleEndianDecoder<StandardDataDictionary> {
fn default() -> Self {
ImplicitVRLittleEndianDecoder::with_std_dict()
}
}
impl<D> ImplicitVRLittleEndianDecoder<D>
where
D: DataDictionary,
{
pub fn with_dict(dictionary: D) -> Self {
ImplicitVRLittleEndianDecoder {
dict: dictionary,
basic: LittleEndianBasicDecoder,
}
}
}
impl<D> Decode for ImplicitVRLittleEndianDecoder<D>
where
D: DataDictionary,
{
fn decode_header<S>(&self, mut source: &mut S) -> Result<(DataElementHeader, usize)>
where
S: ?Sized + Read,
{
let tag = self
.basic
.decode_tag(&mut source)
.context(ReadHeaderTagSnafu)?;
let mut buf = [0u8; 4];
source.read_exact(&mut buf).context(ReadLengthSnafu)?;
let len = LittleEndian::read_u32(&buf);
let vr = if tag == Tag(0x7FE0, 0x0010) || (tag.0 >> 8 == 0x60 && tag.1 == 0x3000) {
VR::OW
} else {
self.dict
.by_tag(tag)
.map(|entry| entry.vr().relaxed())
.unwrap_or(VR::UN)
};
Ok((DataElementHeader::new(tag, vr, Length(len)), 8))
}
fn decode_item_header<S>(&self, mut source: &mut S) -> Result<SequenceItemHeader>
where
S: ?Sized + Read,
{
let mut buf = [0u8; 4];
let tag = self
.basic
.decode_tag(&mut source)
.context(ReadHeaderTagSnafu)?;
source.read_exact(&mut buf).context(ReadLengthSnafu)?;
let len = LittleEndian::read_u32(&buf);
SequenceItemHeader::new(tag, Length(len)).context(BadSequenceHeaderSnafu)
}
#[inline]
fn decode_tag<S>(&self, source: &mut S) -> Result<Tag>
where
S: ?Sized + Read,
{
self.basic.decode_tag(source).context(ReadTagSnafu)
}
}
impl<S: ?Sized, D> DecodeFrom<S> for ImplicitVRLittleEndianDecoder<D>
where
S: Read,
D: DataDictionary,
{
#[inline]
fn decode_header(&self, source: &mut S) -> Result<(DataElementHeader, usize)> {
Decode::decode_header(self, source)
}
#[inline]
fn decode_item_header(&self, source: &mut S) -> Result<SequenceItemHeader> {
Decode::decode_item_header(self, source)
}
#[inline]
fn decode_tag(&self, source: &mut S) -> Result<Tag> {
Decode::decode_tag(self, source)
}
}
#[cfg(test)]
mod tests {
use super::ImplicitVRLittleEndianDecoder;
use crate::decode::Decode;
use dicom_core::dictionary::stub::StubDataDictionary;
use dicom_core::header::{HasLength, Header, Length, VR};
use dicom_core::Tag;
use std::io::{Cursor, Read, Seek, SeekFrom};
const RAW: &'static [u8; 62] = &[
0x02, 0x00, 0x02, 0x00, 0x1a, 0x00, 0x00, 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, 0x14, 0x00, 0x00, 0x00, 0x31, 0x2e, 0x32,
0x2e, 0x38, 0x34, 0x30, 0x2e, 0x31, 0x30, 0x30, 0x30, 0x38, 0x2e, 0x31, 0x2e, 0x32, 0x2e,
0x31, 0x00,
];
const DICT: &'static StubDataDictionary = &StubDataDictionary;
#[test]
fn implicit_vr_le() {
let reader = ImplicitVRLittleEndianDecoder::with_dict(DICT);
let mut cursor = Cursor::new(RAW.as_ref());
{
let (elem, bytes_read) = reader
.decode_header(&mut cursor)
.expect("should find an element");
assert_eq!(elem.tag(), Tag(0x0002, 0x0002));
assert_eq!(elem.vr(), VR::UN);
assert_eq!(elem.length(), Length(26));
assert_eq!(bytes_read, 8);
let mut buffer: Vec<u8> = Vec::with_capacity(13);
buffer.resize(13, 0);
cursor
.read_exact(buffer.as_mut_slice())
.expect("should read it fine");
assert_eq!(buffer.as_slice(), b"1.2.840.10008".as_ref());
}
assert_eq!(cursor.seek(SeekFrom::Current(0)).unwrap(), 21);
assert_eq!(cursor.seek(SeekFrom::Current(13)).unwrap(), 34);
{
let (elem, _bytes_read) = reader
.decode_header(&mut cursor)
.expect("should find an element");
assert_eq!(elem.tag(), Tag(0x0002, 0x0010));
assert_eq!(elem.vr(), VR::UN);
assert_eq!(elem.length(), Length(20));
let mut buffer: Vec<u8> = Vec::with_capacity(20);
buffer.resize(20, 0);
cursor
.read_exact(buffer.as_mut_slice())
.expect("should read it fine");
assert_eq!(buffer.as_slice(), b"1.2.840.10008.1.2.1\0".as_ref());
}
}
#[test]
fn implicit_vr_le_with_standard_dictionary() {
let reader = ImplicitVRLittleEndianDecoder::with_std_dict();
let mut cursor = Cursor::new(RAW.as_ref());
{
let (elem, _bytes_read) = reader
.decode_header(&mut cursor)
.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!(cursor.seek(SeekFrom::Current(0)).unwrap(), 8);
assert_eq!(
cursor
.seek(SeekFrom::Current(elem.length().0 as i64))
.unwrap(),
34
);
}
{
let (elem, _bytes_read) = reader
.decode_header(&mut cursor)
.expect("should find an element");
assert_eq!(elem.tag(), Tag(2, 16));
assert_eq!(elem.vr(), VR::UI);
assert_eq!(elem.length(), Length(20));
let mut buffer: Vec<u8> = Vec::with_capacity(20);
buffer.resize(20, 0);
cursor
.read_exact(buffer.as_mut_slice())
.expect("should read it fine");
assert_eq!(buffer.as_slice(), b"1.2.840.10008.1.2.1\0".as_ref());
}
}
const RAW_SEQUENCE_ITEMS: &'static [u8] = &[
0x08, 0x00, 0x3F, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0x00, 0xE0, 0xFF, 0xFF, 0xFF,
0xFF, 0xFE, 0xFF, 0x0D, 0xE0, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xDD, 0xE0, 0x00, 0x00,
0x00, 0x00,
];
#[test]
fn decode_items() {
let dec = ImplicitVRLittleEndianDecoder::default();
let mut cursor = Cursor::new(RAW_SEQUENCE_ITEMS);
{
let (elem, bytes_read) = dec
.decode_header(&mut cursor)
.expect("should find an element header");
assert_eq!(elem.tag(), Tag(8, 0x103F));
assert_eq!(elem.vr(), VR::SQ);
assert!(elem.length().is_undefined());
assert_eq!(bytes_read, 8);
}
assert_eq!(cursor.seek(SeekFrom::Current(0)).unwrap(), 8);
{
let elem = dec
.decode_item_header(&mut cursor)
.expect("should find an item header");
assert!(elem.is_item());
assert_eq!(elem.tag(), Tag(0xFFFE, 0xE000));
assert!(elem.length().is_undefined());
}
assert_eq!(cursor.seek(SeekFrom::Current(0)).unwrap(), 16);
{
let elem = dec
.decode_item_header(&mut cursor)
.expect("should find an item header");
assert!(elem.is_item_delimiter());
assert_eq!(elem.tag(), Tag(0xFFFE, 0xE00D));
assert_eq!(elem.length(), Length(0));
}
assert_eq!(cursor.seek(SeekFrom::Current(0)).unwrap(), 24);
{
let elem = dec
.decode_item_header(&mut cursor)
.expect("should find an item header");
assert!(elem.is_sequence_delimiter());
assert_eq!(elem.tag(), Tag(0xFFFE, 0xE0DD));
assert_eq!(elem.length(), Length(0));
}
}
}