1use crate::stateful::decode::{DynStatefulDecoder, Error as DecoderError, StatefulDecode};
8use dicom_core::header::{DataElementHeader, Header, Length, SequenceItemHeader};
9use dicom_core::{PrimitiveValue, Tag, VR};
10use dicom_encoding::text::SpecificCharacterSet;
11use dicom_encoding::transfer_syntax::TransferSyntax;
12use snafu::{Backtrace, ResultExt, Snafu};
13use std::cmp::Ordering;
14use std::io::Read;
15
16use super::{DataToken, SeqTokenType};
17
18fn is_stateful_decode<T>(_: &T)
19where
20 T: StatefulDecode,
21{
22}
23
24#[derive(Debug, Snafu)]
25#[non_exhaustive]
26pub enum Error {
27 #[snafu(display("Could not create decoder"))]
28 CreateDecoder {
29 #[snafu(backtrace)]
30 source: DecoderError,
31 },
32 #[snafu(display("Could not read item header"))]
33 ReadItemHeader {
34 #[snafu(backtrace)]
35 source: DecoderError,
36 },
37 #[snafu(display("Could not read element header"))]
38 ReadHeader {
39 #[snafu(backtrace)]
40 source: DecoderError,
41 },
42 #[snafu(display("Could not read {} value bytes for element tagged {}", len, tag))]
43 ReadValue {
44 len: u32,
45 tag: Tag,
46 #[snafu(backtrace)]
47 source: DecoderError,
48 },
49 #[snafu(display("Could not read {} bytes for item value", len))]
50 ReadItemValue {
51 len: u32,
52 #[snafu(backtrace)]
53 source: DecoderError,
54 },
55 #[snafu(display(
56 "Inconsistent sequence end: expected end at {} bytes but read {}",
57 end_of_sequence,
58 bytes_read
59 ))]
60 InconsistentSequenceEnd {
61 end_of_sequence: u64,
62 bytes_read: u64,
63 backtrace: Backtrace,
64 },
65 #[snafu(display("Unexpected item tag {} while reading element header", tag))]
66 UnexpectedItemTag { tag: Tag, backtrace: Backtrace },
67 #[snafu(display(
68 "Unexpected item header outside a dataset sequence at {} bytes",
69 bytes_read
70 ))]
71 UnexpectedItemHeader {
72 bytes_read: u64,
73 backtrace: Backtrace,
74 },
75 UndefinedItemLength,
77}
78
79pub type Result<T> = std::result::Result<T, Error>;
80
81#[derive(Debug, Copy, Clone, PartialEq)]
83struct SeqToken {
84 typ: SeqTokenType,
86 len: Length,
89 pixel_data: bool,
91 base_offset: u64,
94}
95
96#[derive(Debug, Default, Copy, Clone, Eq, Hash, PartialEq)]
100pub enum ValueReadStrategy {
101 Interpreted,
111 #[default]
123 Preserved,
124 Raw,
131}
132
133#[derive(Debug, Default, Copy, Clone, Eq, Hash, PartialEq)]
135#[non_exhaustive]
136pub struct DataSetReaderOptions {
137 pub value_read: ValueReadStrategy,
139 pub base_offset: u64,
141}
142
143impl DataSetReaderOptions {
144 pub fn value_read(mut self, value_read: ValueReadStrategy) -> Self {
146 self.value_read = value_read;
147 self
148 }
149 pub fn base_offset(mut self, base_offset: u64) -> Self {
151 self.base_offset = base_offset;
152 self
153 }
154}
155
156#[derive(Debug)]
159pub struct DataSetReader<S> {
160 parser: S,
162 options: DataSetReaderOptions,
164 in_sequence: bool,
166 offset_table_next: bool,
169 delimiter_check_pending: bool,
171 seq_delimiters: Vec<SeqToken>,
173 hard_break: bool,
175 last_header: Option<DataElementHeader>,
177 peek: Option<DataToken>,
179}
180
181impl<R> DataSetReader<DynStatefulDecoder<R>> {
182 #[inline]
185 pub fn new_with_ts(source: R, ts: &TransferSyntax) -> Result<Self>
186 where
187 R: Read,
188 {
189 Self::new_with_ts_cs_options(source, ts, Default::default(), Default::default())
190 }
191
192 #[inline]
200 pub fn new_with_ts_cs(source: R, ts: &TransferSyntax, cs: SpecificCharacterSet) -> Result<Self>
201 where
202 R: Read,
203 {
204 Self::new_with_ts_cs_options(source, ts, cs, Default::default())
205 }
206
207 pub fn new_with_ts_cs_options(
209 source: R,
210 ts: &TransferSyntax,
211 cs: SpecificCharacterSet,
212 options: DataSetReaderOptions,
213 ) -> Result<Self>
214 where
215 R: Read,
216 {
217 let parser = DynStatefulDecoder::new_with(source, ts, cs, 0).context(CreateDecoderSnafu)?;
218
219 is_stateful_decode(&parser);
220
221 Ok(DataSetReader {
222 parser,
223 options,
224 seq_delimiters: Vec::new(),
225 delimiter_check_pending: false,
226 offset_table_next: false,
227 in_sequence: false,
228 hard_break: false,
229 last_header: None,
230 peek: None,
231 })
232 }
233}
234
235impl<S> DataSetReader<S> {
236 pub fn new(decoder: S, options: DataSetReaderOptions) -> Self {
238 DataSetReader {
239 parser: decoder,
240 options,
241 seq_delimiters: Vec::new(),
242 delimiter_check_pending: false,
243 offset_table_next: false,
244 in_sequence: false,
245 hard_break: false,
246 last_header: None,
247 peek: None,
248 }
249 }
250}
251
252impl<S> Iterator for DataSetReader<S>
253where
254 S: StatefulDecode,
255{
256 type Item = Result<DataToken>;
257
258 fn next(&mut self) -> Option<Self::Item> {
259 if self.hard_break {
260 return None;
261 }
262 if let Some(token) = self.peek.take() {
264 return Some(Ok(token));
265 }
266
267 if self.delimiter_check_pending {
269 match self.update_seq_delimiters() {
270 Err(e) => {
271 self.hard_break = true;
272 return Some(Err(e));
273 }
274 Ok(Some(token)) => return Some(Ok(token)),
275 Ok(None) => { }
276 }
277 }
278
279 if self.in_sequence {
280 match self.parser.decode_item_header() {
283 Ok(header) => {
284 match header {
285 SequenceItemHeader::Item { len } => {
286 self.in_sequence = false;
288
289 let last_delimiter = match self.seq_delimiters.last() {
290 Some(d) => d,
291 None => {
292 return Some(
293 UnexpectedItemHeaderSnafu {
294 bytes_read: self.parser.position(),
295 }
296 .fail(),
297 )
298 }
299 };
300 self.push_sequence_token(
301 SeqTokenType::Item,
302 len,
303 last_delimiter.pixel_data,
304 );
305 if len == Length(0) {
307 self.delimiter_check_pending = true;
308 }
309 Some(Ok(DataToken::ItemStart { len }))
310 }
311 SequenceItemHeader::ItemDelimiter => {
312 self.seq_delimiters.pop();
314 self.in_sequence = true;
315 self.delimiter_check_pending = true;
317 Some(Ok(DataToken::ItemEnd))
318 }
319 SequenceItemHeader::SequenceDelimiter => {
320 self.seq_delimiters.pop();
322 self.in_sequence = false;
323 self.delimiter_check_pending = true;
325 Some(Ok(DataToken::SequenceEnd))
326 }
327 }
328 }
329 Err(e) => {
330 self.hard_break = true;
331 Some(Err(e).context(ReadItemHeaderSnafu))
332 }
333 }
334 } else if let Some(SeqToken {
335 typ: SeqTokenType::Item,
336 pixel_data: true,
337 len,
338 ..
339 }) = self.seq_delimiters.last()
340 {
341 let len = match len.get() {
342 Some(len) => len as usize,
343 None => return Some(UndefinedItemLengthSnafu.fail()),
344 };
345
346 if self.offset_table_next {
347 let mut offset_table = Vec::with_capacity(len);
349
350 self.offset_table_next = false;
351
352 self.delimiter_check_pending = true;
354
355 Some(
356 match self.parser.read_u32_to_vec(len as u32, &mut offset_table) {
357 Ok(()) => Ok(DataToken::OffsetTable(offset_table)),
358 Err(e) => Err(e).context(ReadItemValueSnafu { len: len as u32 }),
359 },
360 )
361 } else {
362 let mut value = Vec::with_capacity(len);
364
365 self.delimiter_check_pending = true;
367 Some(
368 self.parser
369 .read_to_vec(len as u32, &mut value)
370 .map(|_| Ok(DataToken::ItemValue(value)))
371 .unwrap_or_else(|e| Err(e).context(ReadItemValueSnafu { len: len as u32 })),
372 )
373 }
374 } else if let Some(header) = self.last_header {
375 if header.is_encapsulated_pixeldata() {
376 self.push_sequence_token(SeqTokenType::Sequence, Length::UNDEFINED, true);
377 self.last_header = None;
378
379 match self.parser.decode_item_header() {
381 Ok(header) => match header {
382 SequenceItemHeader::Item { len } => {
383 self.in_sequence = false;
385 self.push_sequence_token(SeqTokenType::Item, len, true);
386 if len == Length(0) {
388 self.delimiter_check_pending = true;
389 } else {
390 self.offset_table_next = true;
391 }
392 Some(Ok(DataToken::ItemStart { len }))
393 }
394 SequenceItemHeader::SequenceDelimiter => {
395 self.seq_delimiters.pop();
397 self.in_sequence = false;
398 Some(Ok(DataToken::SequenceEnd))
399 }
400 item => {
401 self.hard_break = true;
402 Some(UnexpectedItemTagSnafu { tag: item.tag() }.fail())
403 }
404 },
405 Err(e) => {
406 self.hard_break = true;
407 Some(Err(e).context(ReadItemHeaderSnafu))
408 }
409 }
410 } else {
411 let value = match self.read_value(&header) {
413 Ok(v) => v,
414 Err(e) => {
415 self.hard_break = true;
416 self.last_header = None;
417 return Some(Err(e));
418 }
419 };
420
421 self.last_header = None;
422
423 self.delimiter_check_pending = true;
425
426 Some(Ok(DataToken::PrimitiveValue(value)))
427 }
428 } else {
429 match self.parser.decode_header() {
431 Ok(DataElementHeader {
432 tag,
433 vr: VR::SQ,
434 len,
435 }) => {
436 self.in_sequence = true;
437 self.push_sequence_token(SeqTokenType::Sequence, len, false);
438
439 if len == Length(0) {
441 self.delimiter_check_pending = true;
442 }
443
444 Some(Ok(DataToken::SequenceStart { tag, len }))
445 }
446 Ok(DataElementHeader {
447 tag: Tag(0xFFFE, 0xE00D),
448 ..
449 }) if self.seq_delimiters.is_empty() => {
450 tracing::warn!(
452 "Item delimitation item outside of a sequence in position {}",
453 self.parser.position()
454 );
455 self.next()
457 }
458 Ok(DataElementHeader {
459 tag: Tag(0xFFFE, 0xE00D),
460 ..
461 }) => {
462 self.in_sequence = true;
463 self.seq_delimiters.pop();
465 self.delimiter_check_pending = true;
467 Some(Ok(DataToken::ItemEnd))
468 }
469 Ok(header) if header.is_encapsulated_pixeldata() => {
470 self.last_header = Some(header);
475 Some(Ok(DataToken::PixelSequenceStart))
476 }
477 Ok(header) if header.len.is_undefined() => {
478 self.in_sequence = true;
482
483 let DataElementHeader { tag, len, .. } = header;
484 self.push_sequence_token(SeqTokenType::Sequence, len, false);
485
486 Some(Ok(DataToken::SequenceStart { tag, len }))
487 }
488 Ok(header) => {
489 self.last_header = Some(header);
491 Some(Ok(DataToken::ElementHeader(header)))
492 }
493 Err(DecoderError::DecodeElementHeader {
494 source: dicom_encoding::decode::Error::ReadHeaderTag { source, .. },
495 ..
496 }) if source.kind() == std::io::ErrorKind::UnexpectedEof => {
497 self.hard_break = true;
503 None
504 }
505 Err(e) => {
506 self.hard_break = true;
507 Some(Err(e).context(ReadHeaderSnafu))
508 }
509 }
510 }
511 }
512}
513
514impl<S> DataSetReader<S>
515where
516 S: StatefulDecode,
517{
518 pub fn peek(&mut self) -> Result<Option<&DataToken>> {
524 if self.peek.is_none() {
525 match self.next() {
527 None => return Ok(None),
528 Some(Err(e)) => return Err(e),
529 Some(Ok(token)) => {
530 self.peek = Some(token);
531 }
532 }
533 }
534 Ok(self.peek.as_ref())
535 }
536
537 fn update_seq_delimiters(&mut self) -> Result<Option<DataToken>> {
538 if let Some(sd) = self.seq_delimiters.last() {
539 if let Some(len) = sd.len.get() {
540 let end_of_sequence = sd.base_offset + len as u64;
541 let bytes_read = self.parser.position();
542 match end_of_sequence.cmp(&bytes_read) {
543 Ordering::Equal => {
544 let token;
546 match sd.typ {
547 SeqTokenType::Sequence => {
548 self.in_sequence = false;
549 token = DataToken::SequenceEnd;
550 }
551 SeqTokenType::Item => {
552 self.in_sequence = true;
553 token = DataToken::ItemEnd;
554 }
555 }
556 self.seq_delimiters.pop();
557 return Ok(Some(token));
558 }
559 Ordering::Less => {
560 return InconsistentSequenceEndSnafu {
561 end_of_sequence,
562 bytes_read,
563 }
564 .fail();
565 }
566 Ordering::Greater => {} }
568 }
569 }
570 self.delimiter_check_pending = false;
571 Ok(None)
572 }
573
574 #[inline]
575 fn push_sequence_token(&mut self, typ: SeqTokenType, len: Length, pixel_data: bool) {
576 self.seq_delimiters.push(SeqToken {
577 typ,
578 pixel_data,
579 len,
580 base_offset: self.parser.position(),
581 })
582 }
583
584 fn read_value(&mut self, header: &DataElementHeader) -> Result<PrimitiveValue> {
585 match self.options.value_read {
586 ValueReadStrategy::Interpreted => self.parser.read_value(header),
587 ValueReadStrategy::Preserved => self.parser.read_value_preserved(header),
588 ValueReadStrategy::Raw => self.parser.read_value_bytes(header),
589 }
590 .context(ReadValueSnafu {
591 len: header.len.0,
592 tag: header.tag,
593 })
594 }
595}
596
597#[cfg(test)]
598mod tests {
599 use super::{DataSetReader, DataToken, StatefulDecode};
600 use crate::stateful::decode::StatefulDecoder;
601 use dicom_core::header::{DataElementHeader, Length};
602 use dicom_core::value::PrimitiveValue;
603 use dicom_core::{Tag, VR};
604 use dicom_encoding::decode::basic::LittleEndianBasicDecoder;
605 use dicom_encoding::decode::{
606 explicit_le::ExplicitVRLittleEndianDecoder, implicit_le::ImplicitVRLittleEndianDecoder,
607 };
608 use dicom_encoding::text::SpecificCharacterSet;
609
610 fn validate_dataset_reader_implicit_vr<I>(data: &[u8], ground_truth: I)
611 where
612 I: IntoIterator<Item = DataToken>,
613 {
614 let mut cursor = data;
615 let parser = StatefulDecoder::new(
616 &mut cursor,
617 ImplicitVRLittleEndianDecoder::default(),
618 LittleEndianBasicDecoder::default(),
619 SpecificCharacterSet::default(),
620 );
621
622 validate_dataset_reader(data, parser, ground_truth)
623 }
624
625 fn validate_dataset_reader_explicit_vr<I>(data: &[u8], ground_truth: I)
626 where
627 I: IntoIterator<Item = DataToken>,
628 {
629 let mut cursor = data;
630 let parser = StatefulDecoder::new(
631 &mut cursor,
632 ExplicitVRLittleEndianDecoder::default(),
633 LittleEndianBasicDecoder::default(),
634 SpecificCharacterSet::default(),
635 );
636
637 validate_dataset_reader(&data, parser, ground_truth)
638 }
639
640 fn validate_dataset_reader<I, D>(data: &[u8], parser: D, ground_truth: I)
641 where
642 I: IntoIterator<Item = DataToken>,
643 D: StatefulDecode,
644 {
645 let mut dset_reader = DataSetReader::new(parser, Default::default());
646
647 let iter = (&mut dset_reader).into_iter();
648 let mut ground_truth = ground_truth.into_iter();
649
650 while let Some(gt_token) = ground_truth.next() {
651 let token = iter
652 .next()
653 .expect("expecting more tokens from reader")
654 .expect("should fetch the next token without an error");
655 eprintln!("Next token: {:2?} ; Expected: {:2?}", token, gt_token);
656 assert_eq!(
657 token, gt_token,
658 "Got token {:2?} ; but expected {:2?}",
659 token, gt_token
660 );
661 }
662
663 let extra: Vec<_> = iter.collect();
664 assert_eq!(
665 extra.len(), 0,
667 "extraneous tokens remaining: {:?}",
668 extra,
669 );
670 assert_eq!(
671 dset_reader.parser.position(),
672 data.len() as u64,
673 "Decoder position did not match end of data",
674 );
675 }
676
677 #[test]
678 fn read_sequence_explicit() {
679 #[rustfmt::skip]
680 static DATA: &[u8] = &[
681 0x18, 0x00, 0x11, 0x60, b'S', b'Q', 0x00, 0x00, 0x2e, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x00, 0xe0, 0x14, 0x00, 0x00, 0x00, 0x18, 0x00, 0x12, 0x60, b'U', b'S', 0x02, 0x00, 0x01, 0x00, 0x18, 0x00, 0x14, 0x60, b'U', b'S', 0x02, 0x00, 0x02, 0x00, 0xfe, 0xff, 0x00, 0xe0, 0x0a, 0x00, 0x00, 0x00, 0x18, 0x00, 0x12, 0x60, b'U', b'S', 0x02, 0x00, 0x04, 0x00, 0x20, 0x00, 0x00, 0x40, b'L', b'T', 0x04, 0x00, b'T', b'E', b'S', b'T', ];
701
702 let ground_truth = vec![
703 DataToken::SequenceStart {
704 tag: Tag(0x0018, 0x6011),
705 len: Length(46),
706 },
707 DataToken::ItemStart { len: Length(20) },
708 DataToken::ElementHeader(DataElementHeader {
709 tag: Tag(0x0018, 0x6012),
710 vr: VR::US,
711 len: Length(2),
712 }),
713 DataToken::PrimitiveValue(PrimitiveValue::U16([1].as_ref().into())),
714 DataToken::ElementHeader(DataElementHeader {
715 tag: Tag(0x0018, 0x6014),
716 vr: VR::US,
717 len: Length(2),
718 }),
719 DataToken::PrimitiveValue(PrimitiveValue::U16([2].as_ref().into())),
720 DataToken::ItemEnd,
721 DataToken::ItemStart { len: Length(10) },
722 DataToken::ElementHeader(DataElementHeader {
723 tag: Tag(0x0018, 0x6012),
724 vr: VR::US,
725 len: Length(2),
726 }),
727 DataToken::PrimitiveValue(PrimitiveValue::U16([4].as_ref().into())),
728 DataToken::ItemEnd,
729 DataToken::SequenceEnd,
730 DataToken::ElementHeader(DataElementHeader {
731 tag: Tag(0x0020, 0x4000),
732 vr: VR::LT,
733 len: Length(4),
734 }),
735 DataToken::PrimitiveValue(PrimitiveValue::Str("TEST".into())),
736 ];
737
738 validate_dataset_reader_explicit_vr(DATA, ground_truth);
739 }
740
741 #[test]
742 fn read_sequence_explicit_2() {
743 static DATA: &[u8] = &[
744 0x08, 0x00, 0x18, 0x22, b'S', b'Q', 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
746 0xfe, 0xff, 0x00, 0xe0, 0x2e, 0x00, 0x00, 0x00,
749 0x08, 0x00, 0x00, 0x01, b'S', b'H', 0x08, 0x00, 0x54, 0x2d, 0x44, 0x31, 0x32, 0x31, 0x33, b' ',
753 0x08, 0x00, 0x02, 0x01, b'S', b'H', 0x04, 0x00, 0x53, 0x52, 0x54, b' ',
757 0x08, 0x00, 0x04, 0x01, b'L', b'O', 0x0a, 0x00, 0x4a, 0x61, 0x77, b' ', 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e,
761 0x40, 0x00, 0x55, 0x05, b'S', b'Q', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
764 0x50, 0x20, 0x20, 0x00, b'C', b'S', 0x08, 0x00, b'I', b'D', b'E', b'N', b'T', b'I', b'T', b'Y',
767 ];
768
769 let ground_truth = vec![
770 DataToken::SequenceStart {
771 tag: Tag(0x0008, 0x2218),
772 len: Length(54),
773 },
774 DataToken::ItemStart { len: Length(46) },
775 DataToken::ElementHeader(DataElementHeader {
776 tag: Tag(0x0008, 0x0100),
777 vr: VR::SH,
778 len: Length(8),
779 }),
780 DataToken::PrimitiveValue(PrimitiveValue::Strs(
781 ["T-D1213 ".to_owned()].as_ref().into(),
782 )),
783 DataToken::ElementHeader(DataElementHeader {
784 tag: Tag(0x0008, 0x0102),
785 vr: VR::SH,
786 len: Length(4),
787 }),
788 DataToken::PrimitiveValue(PrimitiveValue::Strs(["SRT ".to_owned()].as_ref().into())),
789 DataToken::ElementHeader(DataElementHeader {
790 tag: Tag(0x0008, 0x0104),
791 vr: VR::LO,
792 len: Length(10),
793 }),
794 DataToken::PrimitiveValue(PrimitiveValue::Strs(
795 ["Jaw region".to_owned()].as_ref().into(),
796 )),
797 DataToken::ItemEnd,
798 DataToken::SequenceEnd,
799 DataToken::SequenceStart {
800 tag: Tag(0x0040, 0x0555),
801 len: Length(0),
802 },
803 DataToken::SequenceEnd,
804 DataToken::ElementHeader(DataElementHeader {
805 tag: Tag(0x2050, 0x0020),
806 vr: VR::CS,
807 len: Length(8),
808 }),
809 DataToken::PrimitiveValue(PrimitiveValue::Strs(
810 ["IDENTITY".to_owned()].as_ref().into(),
811 )),
812 ];
813
814 validate_dataset_reader_explicit_vr(DATA, ground_truth);
815 }
816
817 #[test]
818 fn read_empty_sequence_explicit() {
819 static DATA: &[u8] = &[
820 0x08, 0x00, 0x18, 0x22, b'S', b'Q', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
825 ];
826
827 let ground_truth = vec![
828 DataToken::SequenceStart {
829 tag: Tag(0x0008, 0x2218),
830 len: Length(0),
831 },
832 DataToken::SequenceEnd,
833 ];
834
835 validate_dataset_reader_explicit_vr(DATA, ground_truth);
836 }
837
838 #[test]
840 fn ignore_trailing_item_delimitation_item() {
841 static DATA: &[u8] = &[
842 0x20, 0x00, 0x00, 0x40, b'L', b'T', 0x04,
843 0x00, b'T', b'E', b'S', b'T', 0xfe, 0xff, 0x0d, 0xe0, 0x00, 0x00, 0x00, 0x00, ];
847
848 let ground_truth = vec![
849 DataToken::ElementHeader(DataElementHeader {
850 tag: Tag(0x0020, 0x4000),
851 vr: VR::LT,
852 len: Length(4),
853 }),
854 DataToken::PrimitiveValue(PrimitiveValue::Str("TEST".into())),
855 ];
857
858 validate_dataset_reader_explicit_vr(DATA, ground_truth);
859 }
860
861 #[test]
862 fn read_sequence_implicit() {
863 #[rustfmt::skip]
864 static DATA: &[u8] = &[
865 0x18, 0x00, 0x11, 0x60, b'S', b'Q', 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x18, 0x00, 0x12, 0x60, b'U', b'S', 0x02, 0x00, 0x01, 0x00, 0x18, 0x00, 0x14, 0x60, b'U', b'S', 0x02, 0x00, 0x02, 0x00, 0xfe, 0xff, 0x0d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x18, 0x00, 0x12, 0x60, b'U', b'S', 0x02, 0x00, 0x04, 0x00, 0xfe, 0xff, 0x0d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xdd, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x40, b'L', b'T', 0x04, 0x00, b'T', b'E', b'S', b'T', ];
891
892 let ground_truth = vec![
893 DataToken::SequenceStart {
894 tag: Tag(0x0018, 0x6011),
895 len: Length::UNDEFINED,
896 },
897 DataToken::ItemStart {
898 len: Length::UNDEFINED,
899 },
900 DataToken::ElementHeader(DataElementHeader {
901 tag: Tag(0x0018, 0x6012),
902 vr: VR::US,
903 len: Length(2),
904 }),
905 DataToken::PrimitiveValue(PrimitiveValue::U16([1].as_ref().into())),
906 DataToken::ElementHeader(DataElementHeader {
907 tag: Tag(0x0018, 0x6014),
908 vr: VR::US,
909 len: Length(2),
910 }),
911 DataToken::PrimitiveValue(PrimitiveValue::U16([2].as_ref().into())),
912 DataToken::ItemEnd,
913 DataToken::ItemStart {
914 len: Length::UNDEFINED,
915 },
916 DataToken::ElementHeader(DataElementHeader {
917 tag: Tag(0x0018, 0x6012),
918 vr: VR::US,
919 len: Length(2),
920 }),
921 DataToken::PrimitiveValue(PrimitiveValue::U16([4].as_ref().into())),
922 DataToken::ItemEnd,
923 DataToken::SequenceEnd,
924 DataToken::ElementHeader(DataElementHeader {
925 tag: Tag(0x0020, 0x4000),
926 vr: VR::LT,
927 len: Length(4),
928 }),
929 DataToken::PrimitiveValue(PrimitiveValue::Str("TEST".into())),
930 ];
931
932 validate_dataset_reader_explicit_vr(DATA, ground_truth);
933 }
934
935 #[test]
936 fn read_implicit_len_sequence_implicit_vr_unknown() {
937 #[rustfmt::skip]
938 static DATA: &[u8] = &[
939 0x33, 0x55, 0x33, 0x55, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0x0d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xdd, 0xe0,
949 0x00, 0x00, 0x00, 0x00, ];
952
953 let ground_truth = vec![
954 DataToken::SequenceStart {
955 tag: Tag(0x5533, 0x5533),
956 len: Length::UNDEFINED,
957 },
958 DataToken::ItemStart {
959 len: Length::UNDEFINED,
960 },
961 DataToken::ItemEnd,
962 DataToken::SequenceEnd,
963 ];
964
965 validate_dataset_reader_implicit_vr(DATA, ground_truth);
966 }
967
968 #[test]
969 fn read_encapsulated_pixeldata() {
970 #[rustfmt::skip]
971 static DATA: &[u8] = &[
972 0xe0, 0x7f, 0x10, 0x00, b'O', b'B', 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x00, 0xe0, 0x20, 0x00, 0x00, 0x00, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
984 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
985 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
986 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
987 0xfe, 0xff, 0xdd, 0xe0, 0x00, 0x00, 0x00, 0x00,
990 0xfc, 0xff, 0xfc, 0xff, b'O', b'B', 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
996 ];
997
998 let ground_truth = vec![
999 DataToken::PixelSequenceStart,
1000 DataToken::ItemStart { len: Length(0) },
1001 DataToken::ItemEnd,
1002 DataToken::ItemStart { len: Length(32) },
1003 DataToken::ItemValue(vec![0x99; 32]),
1004 DataToken::ItemEnd,
1005 DataToken::SequenceEnd,
1006 DataToken::ElementHeader(DataElementHeader::new(
1007 Tag(0xfffc, 0xfffc),
1008 VR::OB,
1009 Length(8),
1010 )),
1011 DataToken::PrimitiveValue(PrimitiveValue::U8([0x00; 8].as_ref().into())),
1012 ];
1013
1014 validate_dataset_reader_explicit_vr(DATA, ground_truth);
1015 }
1016
1017 #[test]
1018 fn read_encapsulated_pixeldata_with_offset_table() {
1019 #[rustfmt::skip]
1020 static DATA: &[u8] = &[
1021 0xe0, 0x7f, 0x10, 0x00, b'O', b'B', 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0x00, 0xe0, 0x04, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x00, 0xe0, 0x20, 0x00, 0x00, 0x00, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
1035 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
1036 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
1037 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
1038 0xfe, 0xff, 0xdd, 0xe0, 0x00, 0x00, 0x00, 0x00,
1041 0xfc, 0xff, 0xfc, 0xff, b'O', b'B', 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1047 ];
1048
1049 let ground_truth = vec![
1050 DataToken::PixelSequenceStart,
1051 DataToken::ItemStart { len: Length(4) },
1052 DataToken::OffsetTable(vec![16]),
1053 DataToken::ItemEnd,
1054 DataToken::ItemStart { len: Length(32) },
1055 DataToken::ItemValue(vec![0x99; 32]),
1056 DataToken::ItemEnd,
1057 DataToken::SequenceEnd,
1058 DataToken::ElementHeader(DataElementHeader::new(
1059 Tag(0xfffc, 0xfffc),
1060 VR::OB,
1061 Length(8),
1062 )),
1063 DataToken::PrimitiveValue(PrimitiveValue::U8([0x00; 8].as_ref().into())),
1064 ];
1065
1066 validate_dataset_reader_explicit_vr(DATA, ground_truth);
1067 }
1068
1069 #[test]
1070 fn read_dataset_in_dataset() {
1071 #[rustfmt::skip]
1072 const DATA: &'static [u8; 138] = &[
1073 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'.',
1103 b'5', b'.', b'1', b'.', b'4', b'.', b'1', b'.', b'1', b'.', b'7', b'\0',
1104 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, ];
1125
1126 let ground_truth = vec![
1127 DataToken::SequenceStart {
1128 tag: Tag(0x2001, 0x9000),
1129 len: Length::UNDEFINED,
1130 },
1131 DataToken::ItemStart { len: Length(114) },
1132 DataToken::SequenceStart {
1133 tag: Tag(0x0008, 0x1115),
1134 len: Length::UNDEFINED,
1135 },
1136 DataToken::ItemStart {
1137 len: Length::UNDEFINED,
1138 },
1139 DataToken::SequenceStart {
1140 tag: Tag(0x0008, 0x1140),
1141 len: Length::UNDEFINED,
1142 },
1143 DataToken::ItemStart {
1144 len: Length::UNDEFINED,
1145 },
1146 DataToken::ElementHeader(DataElementHeader {
1147 tag: Tag(0x0008, 0x1150),
1148 vr: VR::UI,
1149 len: Length(26),
1150 }),
1151 DataToken::PrimitiveValue(PrimitiveValue::from("1.2.840.10008.5.1.4.1.1.7\0")),
1152 DataToken::ItemEnd,
1153 DataToken::SequenceEnd,
1154 DataToken::ItemEnd,
1155 DataToken::SequenceEnd,
1156 DataToken::ElementHeader(DataElementHeader {
1157 tag: Tag(0x2050, 0x0020),
1158 vr: VR::CS,
1159 len: Length(8),
1160 }),
1161 DataToken::PrimitiveValue(PrimitiveValue::from("IDENTITY")),
1162 DataToken::ItemEnd, DataToken::SequenceEnd,
1164 ];
1165
1166 validate_dataset_reader_implicit_vr(DATA, ground_truth);
1167 }
1168
1169 #[test]
1170 fn peek_data_elements_implicit() {
1171 #[rustfmt::skip]
1172 static DATA: &[u8] = &[
1173 0x18, 0x00, 0x11, 0x60, b'S', b'Q', 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xdd, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x40, b'L', b'T', 0x04, 0x00, b'T', b'E', b'S', b'T', ];
1183
1184 let ground_truth = vec![
1185 DataToken::SequenceStart {
1186 tag: Tag(0x0018, 0x6011),
1187 len: Length::UNDEFINED,
1188 },
1189 DataToken::SequenceEnd,
1190 DataToken::ElementHeader(DataElementHeader {
1191 tag: Tag(0x0020, 0x4000),
1192 vr: VR::LT,
1193 len: Length(4),
1194 }),
1195 DataToken::PrimitiveValue(PrimitiveValue::Str("TEST".into())),
1196 ];
1197
1198 let mut cursor = DATA;
1199 let parser = StatefulDecoder::new(
1200 &mut cursor,
1201 ExplicitVRLittleEndianDecoder::default(),
1202 LittleEndianBasicDecoder::default(),
1203 SpecificCharacterSet::default(),
1204 );
1205 let mut dset_reader = DataSetReader::new(parser, Default::default());
1206
1207 let iter = (&mut dset_reader).into_iter();
1208
1209 let token = iter.peek().expect("should peek first token OK");
1211 assert_eq!(token, Some(&ground_truth[0]));
1212
1213 let token = iter.peek().expect("should peek first token again OK");
1215 assert_eq!(token, Some(&ground_truth[0]));
1216
1217 let token = iter
1219 .next()
1220 .expect("expected token")
1221 .expect("should read token peeked OK");
1222 assert_eq!(&token, &ground_truth[0]);
1223
1224 let token = iter.next().unwrap().unwrap();
1228 assert_eq!(&token, &ground_truth[1]);
1229 let token = iter.next().unwrap().unwrap();
1231 assert_eq!(&token, &ground_truth[2]);
1232
1233 let token = iter.peek().unwrap();
1235 assert_eq!(token, Some(&ground_truth[3]));
1236 let token = iter.peek().unwrap();
1238 assert_eq!(token, Some(&ground_truth[3]));
1239 let token = iter.next().unwrap().unwrap();
1241 assert_eq!(&token, &ground_truth[3]);
1242
1243 assert!(iter.peek().unwrap().is_none());
1245 }
1246
1247 #[test]
1248 fn read_pixel_sequence_bad_item_end() {
1249 #[rustfmt::skip]
1250 static DATA: &[u8] = &[
1251 0xe0, 0x7f, 0x10, 0x00, b'O', b'B', 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0d, 0xe0, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, ];
1268
1269 let mut cursor = DATA;
1270 let parser = StatefulDecoder::new(
1271 &mut cursor,
1272 ExplicitVRLittleEndianDecoder::default(),
1273 LittleEndianBasicDecoder::default(),
1274 SpecificCharacterSet::default(),
1275 );
1276 let mut dset_reader = DataSetReader::new(parser, Default::default());
1277
1278 let token_res = (&mut dset_reader)
1279 .into_iter()
1280 .collect::<Result<Vec<_>, _>>();
1281 dbg!(&token_res);
1282 assert!(token_res.is_err());
1283 }
1284}