use crate::error::{Error, InvalidValueReadError, Result};
use crate::parser::{DicomParser, DynamicDicomParser, Parse};
use crate::util::{ReadSeek, SeekInterval};
use dicom_core::dictionary::DataDictionary;
use dicom_core::header::{DataElementHeader, Header, Length, SequenceItemHeader};
use dicom_core::value::{DicomValueType, PrimitiveValue};
use dicom_core::{Tag, VR};
use dicom_dictionary_std::StandardDataDictionary;
use dicom_encoding::text::SpecificCharacterSet;
use dicom_encoding::transfer_syntax::TransferSyntax;
use std::fmt;
use std::io::{Read, Seek, SeekFrom};
use std::iter::Iterator;
use std::marker::PhantomData;
use std::ops::DerefMut;
#[derive(Debug)]
pub struct DataSetReader<S, P, D> {
source: S,
parser: P,
dict: D,
depth: u32,
in_sequence: bool,
hard_break: bool,
last_header: Option<DataElementHeader>,
}
fn is_parse<S: ?Sized, P>(_: &P)
where
S: Read,
P: Parse<S>,
{
}
impl<'s, S: 's> DataSetReader<S, DynamicDicomParser, StandardDataDictionary> {
pub fn new_with(source: S, ts: &TransferSyntax, cs: SpecificCharacterSet) -> Result<Self> {
let parser = DynamicDicomParser::new_with(ts, cs)?;
is_parse(&parser);
Ok(DataSetReader {
source,
parser,
dict: StandardDataDictionary,
depth: 0,
in_sequence: false,
hard_break: false,
last_header: None,
})
}
}
impl<'s, S: 's, D> DataSetReader<S, DynamicDicomParser, D> {
pub fn new_with_dictionary(
source: S,
dict: D,
ts: &TransferSyntax,
cs: SpecificCharacterSet,
) -> Result<Self> {
let parser = DynamicDicomParser::new_with(ts, cs)?;
is_parse(&parser);
Ok(DataSetReader {
source,
parser,
dict,
depth: 0,
in_sequence: false,
hard_break: false,
last_header: None,
})
}
}
impl<S, P> DataSetReader<S, P, StandardDataDictionary>
where
S: Read,
P: Parse<dyn Read>,
{
pub fn new(source: S, parser: P) -> Self {
DataSetReader {
source,
parser,
dict: StandardDataDictionary,
depth: 0,
in_sequence: false,
hard_break: false,
last_header: None,
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum DataToken {
ElementHeader(DataElementHeader),
SequenceStart { tag: Tag, len: Length },
SequenceEnd,
ItemStart { len: Length },
ItemEnd,
PrimitiveValue(PrimitiveValue),
}
impl fmt::Display for DataToken {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&DataToken::PrimitiveValue(ref v) => write!(f, "PrimitiveValue({:?})", v.value_type()),
other => write!(f, "{:?}", other),
}
}
}
impl<'s, S: 's, P, D> Iterator for DataSetReader<S, P, D>
where
S: Read,
P: Parse<dyn Read + 's>,
D: DataDictionary,
{
type Item = Result<DataToken>;
fn next(&mut self) -> Option<Self::Item> {
if self.hard_break {
return None;
}
if self.in_sequence {
match self.parser.decode_item_header(&mut self.source) {
Ok(header) => match header {
SequenceItemHeader::Item { len } => {
self.in_sequence = false;
Some(Ok(DataToken::ItemStart { len }))
}
SequenceItemHeader::ItemDelimiter => {
self.in_sequence = true;
Some(Ok(DataToken::ItemEnd))
}
SequenceItemHeader::SequenceDelimiter => {
self.depth -= 1;
self.in_sequence = false;
Some(Ok(DataToken::SequenceEnd))
}
},
Err(e) => {
self.hard_break = true;
Some(Err(e))
}
}
} else if self.last_header.is_some() {
let header = self.last_header.unwrap();
let v = match self.parser.read_value(&mut self.source, &header) {
Ok(v) => v,
Err(e) => {
self.hard_break = true;
self.last_header = None;
return Some(Err(e));
}
};
if let Some(DataElementHeader {
tag: Tag(0x0008, 0x0005),
..
}) = self.last_header
{
if let Some(charset) = v.string().and_then(SpecificCharacterSet::from_code) {
if let Err(e) = self.parser.set_character_set(charset) {
self.hard_break = true;
self.last_header = None;
return Some(Err(e));
}
}
}
self.last_header = None;
Some(Ok(DataToken::PrimitiveValue(v)))
} else {
match self.parser.decode_header(&mut self.source) {
Ok(DataElementHeader {
tag,
vr: VR::SQ,
len,
}) => {
self.in_sequence = true;
self.depth += 1;
Some(Ok(DataToken::SequenceStart { tag, len }))
}
Ok(DataElementHeader {
tag: Tag(0xFFFE, 0xE00D),
..
}) => {
self.in_sequence = true;
Some(Ok(DataToken::ItemEnd))
}
Ok(header) => {
self.last_header = Some(header);
Some(Ok(DataToken::ElementHeader(header)))
}
Err(Error::Io(ref e)) if e.kind() == ::std::io::ErrorKind::UnexpectedEof => {
self.hard_break = true;
None
}
Err(e) => {
self.hard_break = true;
Some(Err(e))
}
}
}
}
}
#[derive(Debug)]
pub struct LazyDataSetReader<S, DS, P> {
source: S,
parser: P,
depth: u32,
in_sequence: bool,
hard_break: bool,
phantom: PhantomData<DS>,
}
impl<'s> LazyDataSetReader<&'s mut dyn ReadSeek, &'s mut dyn Read, DynamicDicomParser> {
pub fn new_with(
source: &'s mut dyn ReadSeek,
ts: &TransferSyntax,
cs: SpecificCharacterSet,
) -> Result<Self> {
let parser = DicomParser::new_with(ts, cs)?;
Ok(LazyDataSetReader {
source,
parser,
depth: 0,
in_sequence: false,
hard_break: false,
phantom: PhantomData,
})
}
}
impl<S, DS, P> LazyDataSetReader<S, DS, P>
where
S: ReadSeek,
{
pub fn new(source: S, parser: P) -> LazyDataSetReader<S, DS, P> {
LazyDataSetReader {
source,
parser,
depth: 0,
in_sequence: false,
hard_break: false,
phantom: PhantomData,
}
}
fn get_position(&mut self) -> Result<u64>
where
S: Seek,
{
self.source.seek(SeekFrom::Current(0)).map_err(Error::from)
}
fn create_element_marker(&mut self, header: DataElementHeader) -> Result<DicomElementMarker> {
match self.get_position() {
Ok(pos) => Ok(DicomElementMarker { header, pos }),
Err(e) => {
self.hard_break = true;
Err(e)
}
}
}
fn create_item_marker(&mut self, header: SequenceItemHeader) -> Result<DicomElementMarker> {
match self.get_position() {
Ok(pos) => Ok(DicomElementMarker {
header: From::from(header),
pos,
}),
Err(e) => {
self.hard_break = true;
Err(e)
}
}
}
}
impl<S, P> Iterator for LazyDataSetReader<S, (), P>
where
S: ReadSeek,
P: Parse<S>,
{
type Item = Result<DicomElementMarker>;
fn next(&mut self) -> Option<Self::Item> {
if self.hard_break {
return None;
}
if self.in_sequence {
match self.parser.decode_item_header(&mut self.source) {
Ok(header) => match header {
header @ SequenceItemHeader::Item { .. } => {
self.in_sequence = false;
Some(self.create_item_marker(header))
}
SequenceItemHeader::ItemDelimiter => {
self.in_sequence = true;
Some(self.create_item_marker(header))
}
SequenceItemHeader::SequenceDelimiter => {
self.depth -= 1;
self.in_sequence = false;
Some(self.create_item_marker(header))
}
},
Err(e) => {
self.hard_break = true;
Some(Err(e))
}
}
} else {
match self.parser.decode_header(&mut self.source) {
Ok(
header @ DataElementHeader {
tag: Tag(0x0008, 0x0005),
..
},
) => {
let marker = self.create_element_marker(header);
Some(marker)
}
Ok(header) => {
if header.vr() == VR::SQ {
self.in_sequence = true;
self.depth += 1;
}
Some(self.create_element_marker(header))
}
Err(e) => {
self.hard_break = true;
Some(Err(e))
}
}
}
}
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub struct DicomElementMarker {
pub header: DataElementHeader,
pub pos: u64,
}
impl DicomElementMarker {
pub fn get_data_stream<S: ?Sized, B: DerefMut<Target = S>>(
&self,
source: B,
) -> Result<SeekInterval<S, B>>
where
S: ReadSeek,
{
let len = u64::from(
self.header
.len()
.get()
.ok_or(InvalidValueReadError::UnresolvedValueLength)?,
);
let interval = SeekInterval::new_at(source, self.pos..len)?;
Ok(interval)
}
pub fn move_to_start<S: ?Sized, B: DerefMut<Target = S>>(&self, mut source: B) -> Result<()>
where
S: Seek,
{
source.seek(SeekFrom::Start(self.pos))?;
Ok(())
}
pub fn vr(&self) -> VR {
self.header.vr()
}
}
impl Header for DicomElementMarker {
fn tag(&self) -> Tag {
self.header.tag()
}
fn len(&self) -> Length {
self.header.len()
}
}