1use crate::dataset::read::OddLengthStrategy;
16use crate::stateful::decode::{
17 CharacterSetOverride, DynStatefulDecoder, Error as DecoderError, StatefulDecode,
18};
19use crate::util::ReadSeek;
20use dicom_core::header::{DataElementHeader, Header, Length, SequenceItemHeader};
21use dicom_core::{Tag, VR};
22use dicom_encoding::text::SpecificCharacterSet;
23use dicom_encoding::transfer_syntax::TransferSyntax;
24use snafu::{Backtrace, OptionExt, ResultExt, Snafu};
25use std::cmp::Ordering;
26
27use super::{DataToken, LazyDataToken, SeqTokenType};
28
29#[derive(Debug, Snafu)]
30#[non_exhaustive]
31pub enum Error {
32 #[snafu(display("Could not create decoder"))]
33 CreateDecoder {
34 #[snafu(backtrace)]
35 source: DecoderError,
36 },
37 #[snafu(display("Could not read item header at {} bytes", bytes_read))]
38 ReadItemHeader {
39 bytes_read: u64,
40 #[snafu(backtrace)]
41 source: DecoderError,
42 },
43 #[snafu(display("Could not read element header at {} bytes", bytes_read))]
44 ReadHeader {
45 bytes_read: u64,
46 #[snafu(backtrace)]
47 source: DecoderError,
48 },
49 #[snafu(display("Could not read value"))]
50 ReadValue {
51 #[snafu(backtrace)]
52 source: DecoderError,
53 },
54 #[snafu(display("Failed to get reader position"))]
55 GetPosition {
56 source: std::io::Error,
57 backtrace: Backtrace,
58 },
59 #[snafu(display(
60 "Inconsistent sequence end: expected end at {} bytes but read {}",
61 end_of_sequence,
62 bytes_read
63 ))]
64 InconsistentSequenceEnd {
65 end_of_sequence: u64,
66 bytes_read: u64,
67 backtrace: Backtrace,
68 },
69 #[snafu(display("Unexpected item delimiter at {} bytes", bytes_read))]
70 UnexpectedItemDelimiter {
71 bytes_read: u64,
72 backtrace: Backtrace,
73 },
74 #[snafu(display("Unexpected undefined value length at {} bytes", bytes_read))]
75 UndefinedLength {
76 bytes_read: u64,
77 backtrace: Backtrace,
78 },
79
80 InvalidElementLength {
82 tag: Tag,
83 len: u32,
84 bytes_read: u64,
85 backtrace: Backtrace,
86 },
87
88 InvalidItemLength {
90 len: u32,
91 bytes_read: u64,
92 backtrace: Backtrace,
93 },
94
95 #[snafu(display("Attempted to inspect a header at {} bytes", bytes_read))]
96 Peek {
97 bytes_read: u64,
98 backtrace: Backtrace,
99 },
100}
101
102pub type Result<T, E = Error> = std::result::Result<T, E>;
103
104#[derive(Debug, Copy, Clone, PartialEq)]
106struct SeqToken {
107 typ: SeqTokenType,
109 len: Length,
112 pixel_data: bool,
114 base_offset: u64,
117}
118
119#[derive(Debug)]
125pub struct LazyDataSetReader<S> {
126 parser: S,
128 options: LazyDataSetReaderOptions,
130 in_sequence: bool,
132 delimiter_check_pending: bool,
134 seq_delimiters: Vec<SeqToken>,
136 hard_break: bool,
138 last_header: Option<DataElementHeader>,
140 peek: Option<DataToken>,
142}
143
144#[derive(Debug, Default, Copy, Clone, Eq, Hash, PartialEq)]
146#[non_exhaustive]
147pub struct LazyDataSetReaderOptions {
148 pub odd_length: OddLengthStrategy,
150
151 pub charset_override: CharacterSetOverride,
153}
154
155impl<R> LazyDataSetReader<DynStatefulDecoder<R>> {
156 #[inline]
160 pub fn new_with_ts(source: R, ts: &TransferSyntax) -> Result<Self>
161 where
162 R: ReadSeek,
163 {
164 Self::new_with_ts_cs(source, ts, SpecificCharacterSet::default())
165 }
166
167 #[inline]
171 pub fn new_with_ts_cs(source: R, ts: &TransferSyntax, cs: SpecificCharacterSet) -> Result<Self>
172 where
173 R: ReadSeek,
174 {
175 Self::new_with_ts_cs_options(source, ts, cs, Default::default())
176 }
177
178 #[inline]
183 pub fn new_with_ts_options(
184 source: R,
185 ts: &TransferSyntax,
186 options: LazyDataSetReaderOptions,
187 ) -> Result<Self>
188 where
189 R: ReadSeek,
190 {
191 Self::new_with_ts_cs_options(source, ts, SpecificCharacterSet::default(), options)
192 }
193
194 pub fn new_with_ts_cs_options(
198 mut source: R,
199 ts: &TransferSyntax,
200 cs: SpecificCharacterSet,
201 options: LazyDataSetReaderOptions,
202 ) -> Result<Self>
203 where
204 R: ReadSeek,
205 {
206 let position = source.stream_position().context(GetPositionSnafu)?;
207 let parser = DynStatefulDecoder::new_with_override(
208 source,
209 ts,
210 cs,
211 options.charset_override,
212 position,
213 )
214 .context(CreateDecoderSnafu)?;
215
216 Ok(LazyDataSetReader {
217 parser,
218 options,
219 seq_delimiters: Vec::new(),
220 delimiter_check_pending: false,
221 in_sequence: false,
222 hard_break: false,
223 last_header: None,
224 peek: None,
225 })
226 }
227}
228
229impl<S> LazyDataSetReader<S>
230where
231 S: StatefulDecode,
232{
233 #[inline]
235 pub fn new(parser: S) -> Self {
236 LazyDataSetReader::new_with_options(parser, Default::default())
237 }
238
239 pub fn new_with_options(parser: S, options: LazyDataSetReaderOptions) -> Self
243 where
244 S: StatefulDecode,
245 {
246 LazyDataSetReader {
247 parser,
248 options,
249 seq_delimiters: Vec::new(),
250 delimiter_check_pending: false,
251 in_sequence: false,
252 hard_break: false,
253 last_header: None,
254 peek: None,
255 }
256 }
257}
258
259impl<S> LazyDataSetReader<S>
260where
261 S: StatefulDecode,
262{
263 fn update_seq_delimiters<'b>(&mut self) -> Result<Option<LazyDataToken<&'b mut S>>> {
264 if let Some(sd) = self.seq_delimiters.last() {
265 if let Some(len) = sd.len.get() {
266 let end_of_sequence = sd.base_offset + len as u64;
267 let bytes_read = self.parser.position();
268 match end_of_sequence.cmp(&bytes_read) {
269 Ordering::Equal => {
270 let token;
272 match sd.typ {
273 SeqTokenType::Sequence => {
274 self.in_sequence = false;
275 token = LazyDataToken::SequenceEnd;
276 }
277 SeqTokenType::Item => {
278 self.in_sequence = true;
279 token = LazyDataToken::ItemEnd;
280 }
281 }
282 self.seq_delimiters.pop();
283 return Ok(Some(token));
284 }
285 Ordering::Less => {
286 return InconsistentSequenceEndSnafu {
287 end_of_sequence,
288 bytes_read,
289 }
290 .fail();
291 }
292 Ordering::Greater => {} }
294 }
295 }
296 self.delimiter_check_pending = false;
297 Ok(None)
298 }
299
300 #[inline]
301 fn push_sequence_token(&mut self, typ: SeqTokenType, len: Length, pixel_data: bool) {
302 self.seq_delimiters.push(SeqToken {
303 typ,
304 pixel_data,
305 len,
306 base_offset: self.parser.position(),
307 })
308 }
309
310 pub fn into_decoder(self) -> S {
312 self.parser
313 }
314
315 pub fn advance(&mut self) -> Option<Result<LazyDataToken<&mut S>>> {
321 if self.hard_break {
322 return None;
323 }
324
325 if let Some(peek) = self.peek.take() {
327 let token = match peek {
328 DataToken::ElementHeader(header) => LazyDataToken::ElementHeader(header),
329 DataToken::SequenceStart { tag, len } => LazyDataToken::SequenceStart { tag, len },
330 DataToken::ItemStart { len } => LazyDataToken::ItemStart { len },
331 DataToken::ItemEnd => LazyDataToken::ItemEnd,
332 DataToken::SequenceEnd => LazyDataToken::SequenceEnd,
333 DataToken::PixelSequenceStart => LazyDataToken::PixelSequenceStart,
334 _ => unreachable!("peeked token should not be a value token"),
335 };
336 return Some(Ok(token));
337 }
338
339 let bytes_read = self.parser.position();
341
342 if self.delimiter_check_pending {
344 match self.update_seq_delimiters() {
345 Err(e) => {
346 self.hard_break = true;
347 return Some(Err(e));
348 }
349 Ok(Some(token)) => return Some(Ok(token)),
350 Ok(None) => { }
351 }
352 }
353
354 if self.in_sequence {
355 match self.parser.decode_item_header() {
358 Ok(header) => {
359 match header {
360 SequenceItemHeader::Item { len } => {
361 let Some(len) = self.sanitize_length(len) else {
363 return Some(
364 InvalidItemLengthSnafu {
365 len: len.0,
366 bytes_read: self.parser.position(),
367 }
368 .fail(),
369 );
370 };
371
372 self.in_sequence = false;
374 self.push_sequence_token(
375 SeqTokenType::Item,
376 len,
377 self.seq_delimiters.last()
378 .expect("item header should be read only inside an existing sequence")
379 .pixel_data);
380 if len == Length(0) {
382 self.delimiter_check_pending = true;
383 }
384 Some(Ok(LazyDataToken::ItemStart { len }))
385 }
386 SequenceItemHeader::ItemDelimiter => {
387 self.seq_delimiters.pop();
389 self.in_sequence = true;
390 self.delimiter_check_pending = true;
392 Some(Ok(LazyDataToken::ItemEnd))
393 }
394 SequenceItemHeader::SequenceDelimiter => {
395 self.seq_delimiters.pop();
397 self.in_sequence = false;
398 self.delimiter_check_pending = true;
400 Some(Ok(LazyDataToken::SequenceEnd))
401 }
402 }
403 }
404 Err(e) => {
405 self.hard_break = true;
406 Some(Err(e).context(ReadItemHeaderSnafu { bytes_read }))
407 }
408 }
409 } else if let Some(SeqToken {
410 typ: SeqTokenType::Item,
411 pixel_data: true,
412 len,
413 ..
414 }) = self.seq_delimiters.last()
415 {
416 let Some(len) = self.sanitize_length(*len) else {
419 return Some(
420 InvalidItemLengthSnafu {
421 len: len.0,
422 bytes_read: self.parser.position(),
423 }
424 .fail(),
425 );
426 };
427
428 let len = match len
429 .get()
430 .with_context(|| UndefinedLengthSnafu { bytes_read })
431 {
432 Ok(len) => len,
433 Err(e) => return Some(Err(e)),
434 };
435
436 self.delimiter_check_pending = true;
438 Some(Ok(LazyDataToken::LazyItemValue {
439 len,
440 decoder: &mut self.parser,
441 }))
442 } else if let Some(header) = self.last_header {
443 if header.is_encapsulated_pixeldata() {
444 self.push_sequence_token(SeqTokenType::Sequence, Length::UNDEFINED, true);
445 self.last_header = None;
446
447 match self.parser.decode_item_header() {
449 Ok(header) => match header {
450 SequenceItemHeader::Item { len } => {
451 let Some(len) = self.sanitize_length(len) else {
453 return Some(
454 InvalidItemLengthSnafu {
455 len: len.0,
456 bytes_read: self.parser.position(),
457 }
458 .fail(),
459 );
460 };
461
462 self.in_sequence = false;
464 self.push_sequence_token(SeqTokenType::Item, len, true);
465 if len == Length(0) {
467 self.delimiter_check_pending = true;
468 }
469 Some(Ok(LazyDataToken::ItemStart { len }))
470 }
471 SequenceItemHeader::SequenceDelimiter => {
472 self.seq_delimiters.pop();
474 self.in_sequence = false;
475 Some(Ok(LazyDataToken::SequenceEnd))
476 }
477 SequenceItemHeader::ItemDelimiter => {
478 self.hard_break = true;
479 Some(UnexpectedItemDelimiterSnafu { bytes_read }.fail())
480 }
481 },
482 Err(e) => {
483 self.hard_break = true;
484 Some(Err(e).context(ReadItemHeaderSnafu { bytes_read }))
485 }
486 }
487 } else {
488 self.last_header = None;
490
491 self.delimiter_check_pending = true;
493
494 Some(Ok(LazyDataToken::LazyValue {
495 header,
496 decoder: &mut self.parser,
497 }))
498 }
499 } else {
500 match self.parser.decode_header() {
502 Ok(DataElementHeader {
503 tag,
504 vr: VR::SQ,
505 len,
506 }) => {
507 let Some(len) = self.sanitize_length(len) else {
508 return Some(
509 InvalidElementLengthSnafu {
510 tag,
511 len: len.0,
512 bytes_read: self.parser.position(),
513 }
514 .fail(),
515 );
516 };
517
518 self.in_sequence = true;
519 self.push_sequence_token(SeqTokenType::Sequence, len, false);
520
521 if len == Length(0) {
523 self.delimiter_check_pending = true;
524 }
525
526 Some(Ok(LazyDataToken::SequenceStart { tag, len }))
527 }
528 Ok(DataElementHeader {
529 tag: Tag(0xFFFE, 0xE00D),
530 ..
531 }) => {
532 self.in_sequence = true;
533 self.seq_delimiters.pop();
535 self.delimiter_check_pending = true;
537 Some(Ok(LazyDataToken::ItemEnd))
538 }
539 Ok(header) if header.is_encapsulated_pixeldata() => {
540 self.last_header = Some(header);
545 Some(Ok(LazyDataToken::PixelSequenceStart))
546 }
547 Ok(header) if header.len.is_undefined() => {
548 self.in_sequence = true;
552
553 let DataElementHeader { tag, len, .. } = header;
554 self.push_sequence_token(SeqTokenType::Sequence, len, false);
555
556 Some(Ok(LazyDataToken::SequenceStart { tag, len }))
557 }
558 Ok(mut header) => {
559 let Some(len) = self.sanitize_length(header.len) else {
561 return Some(
562 InvalidElementLengthSnafu {
563 tag: header.tag,
564 len: header.len.0,
565 bytes_read: self.parser.position(),
566 }
567 .fail(),
568 );
569 };
570 header.len = len;
571
572 self.last_header = Some(header);
574 Some(Ok(LazyDataToken::ElementHeader(header)))
575 }
576 Err(DecoderError::DecodeElementHeader {
577 source: dicom_encoding::decode::Error::ReadHeaderTag { source, .. },
578 ..
579 }) if source.kind() == std::io::ErrorKind::UnexpectedEof => {
580 self.hard_break = true;
586 None
587 }
588 Err(e) => {
589 self.hard_break = true;
590 Some(Err(e).context(ReadHeaderSnafu { bytes_read }))
591 }
592 }
593 }
594 }
595
596 pub fn peek(&mut self) -> Result<Option<&DataToken>> {
606 if self.peek.is_none() {
607 match self.advance() {
609 None => return Ok(None),
610 Some(Err(e)) => return Err(e),
611 Some(Ok(token)) => match token {
612 LazyDataToken::ElementHeader(header) => {
613 self.peek = Some(DataToken::ElementHeader(header));
614 }
615 LazyDataToken::SequenceStart { tag, len } => {
616 self.peek = Some(DataToken::SequenceStart { tag, len });
617 }
618 LazyDataToken::ItemStart { len } => {
619 self.peek = Some(DataToken::ItemStart { len });
620 }
621 LazyDataToken::ItemEnd => {
622 self.peek = Some(DataToken::ItemEnd);
623 }
624 LazyDataToken::SequenceEnd => {
625 self.peek = Some(DataToken::SequenceEnd);
626 }
627 LazyDataToken::PixelSequenceStart => {
628 self.peek = Some(DataToken::PixelSequenceStart);
629 }
630 _ => {
631 self.hard_break = true;
632 return PeekSnafu {
633 bytes_read: self.parser.position(),
634 }
635 .fail();
636 }
637 },
638 }
639 }
640 Ok(self.peek.as_ref())
641 }
642
643 fn sanitize_length(&self, length: Length) -> Option<Length> {
647 if length.is_defined() && length.0 & 1 != 0 {
648 match self.options.odd_length {
649 OddLengthStrategy::Accept => Some(length),
650 OddLengthStrategy::NextEven => Some(length + 1),
651 OddLengthStrategy::Fail => None,
652 }
653 } else {
654 Some(length)
655 }
656 }
657}
658
659#[cfg(test)]
660mod tests {
661 use super::{LazyDataSetReader, StatefulDecode};
662 use crate::{
663 dataset::{
664 lazy_read::LazyDataSetReaderOptions, read::OddLengthStrategy, DataToken, LazyDataToken,
665 },
666 StatefulDecoder,
667 };
668 use dicom_core::value::PrimitiveValue;
669 use dicom_core::{
670 dicom_value,
671 header::{DataElementHeader, Length},
672 };
673 use dicom_core::{Tag, VR};
674 use dicom_encoding::decode::{
675 explicit_le::ExplicitVRLittleEndianDecoder, implicit_le::ImplicitVRLittleEndianDecoder,
676 };
677 use dicom_encoding::{decode::basic::LittleEndianBasicDecoder, text::SpecificCharacterSet};
678
679 fn validate_dataset_reader_implicit_vr<I>(data: &[u8], ground_truth: I)
680 where
681 I: IntoIterator<Item = DataToken>,
682 {
683 let mut cursor = data;
684 let parser = StatefulDecoder::new(
685 &mut cursor,
686 ImplicitVRLittleEndianDecoder::default(),
687 LittleEndianBasicDecoder,
688 SpecificCharacterSet::default(),
689 );
690
691 validate_dataset_reader(data, parser, ground_truth)
692 }
693
694 fn validate_dataset_reader_explicit_vr<I>(data: &[u8], ground_truth: I)
695 where
696 I: IntoIterator<Item = DataToken>,
697 {
698 let mut cursor = data;
699 let parser = StatefulDecoder::new(
700 &mut cursor,
701 ExplicitVRLittleEndianDecoder::default(),
702 LittleEndianBasicDecoder,
703 SpecificCharacterSet::default(),
704 );
705
706 validate_dataset_reader(data, parser, ground_truth)
707 }
708
709 fn validate_dataset_reader<I, D>(data: &[u8], parser: D, ground_truth: I)
710 where
711 I: IntoIterator<Item = DataToken>,
712 D: StatefulDecode,
713 {
714 let mut dset_reader = LazyDataSetReader::new(parser);
715
716 let mut gt_iter = ground_truth.into_iter();
717 while let Some(res) = dset_reader.advance() {
718 let gt_token = gt_iter.next().expect("ground truth is shorter");
719 let token = res.expect("should parse without an error");
720 let token = token.into_owned().unwrap();
721 assert_eq!(token, gt_token);
722 }
723
724 assert_eq!(
725 gt_iter.count(), 0, "unexpected number of tokens remaining"
728 );
729 assert_eq!(dset_reader.parser.position(), data.len() as u64);
730 }
731
732 #[test]
733 fn lazy_read_sequence_explicit() {
734 #[rustfmt::skip]
735 static DATA: &[u8] = &[
736 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', ];
756
757 let ground_truth = vec![
758 DataToken::SequenceStart {
759 tag: Tag(0x0018, 0x6011),
760 len: Length(46),
761 },
762 DataToken::ItemStart { len: Length(20) },
763 DataToken::ElementHeader(DataElementHeader {
764 tag: Tag(0x0018, 0x6012),
765 vr: VR::US,
766 len: Length(2),
767 }),
768 DataToken::PrimitiveValue(PrimitiveValue::U16([1].as_ref().into())),
769 DataToken::ElementHeader(DataElementHeader {
770 tag: Tag(0x0018, 0x6014),
771 vr: VR::US,
772 len: Length(2),
773 }),
774 DataToken::PrimitiveValue(PrimitiveValue::U16([2].as_ref().into())),
775 DataToken::ItemEnd,
776 DataToken::ItemStart { len: Length(10) },
777 DataToken::ElementHeader(DataElementHeader {
778 tag: Tag(0x0018, 0x6012),
779 vr: VR::US,
780 len: Length(2),
781 }),
782 DataToken::PrimitiveValue(PrimitiveValue::U16([4].as_ref().into())),
783 DataToken::ItemEnd,
784 DataToken::SequenceEnd,
785 DataToken::ElementHeader(DataElementHeader {
786 tag: Tag(0x0020, 0x4000),
787 vr: VR::LT,
788 len: Length(4),
789 }),
790 DataToken::PrimitiveValue(PrimitiveValue::Str("TEST".into())),
791 ];
792
793 validate_dataset_reader_explicit_vr(DATA, ground_truth);
794 }
795
796 #[test]
797 fn lazy_read_sequence_explicit_2() {
798 static DATA: &[u8] = &[
799 0x08, 0x00, 0x18, 0x22, b'S', b'Q', 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
801 0xfe, 0xff, 0x00, 0xe0, 0x2e, 0x00, 0x00, 0x00,
804 0x08, 0x00, 0x00, 0x01, b'S', b'H', 0x08, 0x00, 0x54, 0x2d, 0x44, 0x31, 0x32, 0x31, 0x33, b' ',
808 0x08, 0x00, 0x02, 0x01, b'S', b'H', 0x04, 0x00, 0x53, 0x52, 0x54, b' ',
812 0x08, 0x00, 0x04, 0x01, b'L', b'O', 0x0a, 0x00, 0x4a, 0x61, 0x77, b' ', 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e,
816 0x40, 0x00, 0x55, 0x05, b'S', b'Q', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
819 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',
822 ];
823
824 let ground_truth = vec![
825 DataToken::SequenceStart {
826 tag: Tag(0x0008, 0x2218),
827 len: Length(54),
828 },
829 DataToken::ItemStart { len: Length(46) },
830 DataToken::ElementHeader(DataElementHeader {
831 tag: Tag(0x0008, 0x0100),
832 vr: VR::SH,
833 len: Length(8),
834 }),
835 DataToken::PrimitiveValue(PrimitiveValue::Strs(
836 ["T-D1213 ".to_owned()].as_ref().into(),
837 )),
838 DataToken::ElementHeader(DataElementHeader {
839 tag: Tag(0x0008, 0x0102),
840 vr: VR::SH,
841 len: Length(4),
842 }),
843 DataToken::PrimitiveValue(PrimitiveValue::Strs(["SRT ".to_owned()].as_ref().into())),
844 DataToken::ElementHeader(DataElementHeader {
845 tag: Tag(0x0008, 0x0104),
846 vr: VR::LO,
847 len: Length(10),
848 }),
849 DataToken::PrimitiveValue(PrimitiveValue::Strs(
850 ["Jaw region".to_owned()].as_ref().into(),
851 )),
852 DataToken::ItemEnd,
853 DataToken::SequenceEnd,
854 DataToken::SequenceStart {
855 tag: Tag(0x0040, 0x0555),
856 len: Length(0),
857 },
858 DataToken::SequenceEnd,
859 DataToken::ElementHeader(DataElementHeader {
860 tag: Tag(0x2050, 0x0020),
861 vr: VR::CS,
862 len: Length(8),
863 }),
864 DataToken::PrimitiveValue(PrimitiveValue::Strs(
865 ["IDENTITY".to_owned()].as_ref().into(),
866 )),
867 ];
868
869 validate_dataset_reader_explicit_vr(DATA, ground_truth);
870 }
871
872 #[test]
873 fn lazy_read_sequence_implicit() {
874 #[rustfmt::skip]
875 static DATA: &[u8] = &[
876 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', ];
902
903 let ground_truth = vec![
904 DataToken::SequenceStart {
905 tag: Tag(0x0018, 0x6011),
906 len: Length::UNDEFINED,
907 },
908 DataToken::ItemStart {
909 len: Length::UNDEFINED,
910 },
911 DataToken::ElementHeader(DataElementHeader {
912 tag: Tag(0x0018, 0x6012),
913 vr: VR::US,
914 len: Length(2),
915 }),
916 DataToken::PrimitiveValue(PrimitiveValue::U16([1].as_ref().into())),
917 DataToken::ElementHeader(DataElementHeader {
918 tag: Tag(0x0018, 0x6014),
919 vr: VR::US,
920 len: Length(2),
921 }),
922 DataToken::PrimitiveValue(PrimitiveValue::U16([2].as_ref().into())),
923 DataToken::ItemEnd,
924 DataToken::ItemStart {
925 len: Length::UNDEFINED,
926 },
927 DataToken::ElementHeader(DataElementHeader {
928 tag: Tag(0x0018, 0x6012),
929 vr: VR::US,
930 len: Length(2),
931 }),
932 DataToken::PrimitiveValue(PrimitiveValue::U16([4].as_ref().into())),
933 DataToken::ItemEnd,
934 DataToken::SequenceEnd,
935 DataToken::ElementHeader(DataElementHeader {
936 tag: Tag(0x0020, 0x4000),
937 vr: VR::LT,
938 len: Length(4),
939 }),
940 DataToken::PrimitiveValue(PrimitiveValue::Str("TEST".into())),
941 ];
942
943 validate_dataset_reader_explicit_vr(DATA, ground_truth);
944 }
945
946 #[test]
947 fn lazy_read_dataset_in_dataset() {
948 #[rustfmt::skip]
949 const DATA: &[u8; 138] = &[
950 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'.',
980 b'5', b'.', b'1', b'.', b'4', b'.', b'1', b'.', b'1', b'.', b'7', b'\0',
981 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, ];
1002
1003 let ground_truth = vec![
1004 DataToken::SequenceStart {
1005 tag: Tag(0x2001, 0x9000),
1006 len: Length::UNDEFINED,
1007 },
1008 DataToken::ItemStart { len: Length(114) },
1009 DataToken::SequenceStart {
1010 tag: Tag(0x0008, 0x1115),
1011 len: Length::UNDEFINED,
1012 },
1013 DataToken::ItemStart {
1014 len: Length::UNDEFINED,
1015 },
1016 DataToken::SequenceStart {
1017 tag: Tag(0x0008, 0x1140),
1018 len: Length::UNDEFINED,
1019 },
1020 DataToken::ItemStart {
1021 len: Length::UNDEFINED,
1022 },
1023 DataToken::ElementHeader(DataElementHeader {
1024 tag: Tag(0x0008, 0x1150),
1025 vr: VR::UI,
1026 len: Length(26),
1027 }),
1028 DataToken::PrimitiveValue(PrimitiveValue::from("1.2.840.10008.5.1.4.1.1.7\0")),
1029 DataToken::ItemEnd,
1030 DataToken::SequenceEnd,
1031 DataToken::ItemEnd,
1032 DataToken::SequenceEnd,
1033 DataToken::ElementHeader(DataElementHeader {
1034 tag: Tag(0x2050, 0x0020),
1035 vr: VR::CS,
1036 len: Length(8),
1037 }),
1038 DataToken::PrimitiveValue(PrimitiveValue::from("IDENTITY")),
1039 DataToken::ItemEnd, DataToken::SequenceEnd,
1041 ];
1042
1043 validate_dataset_reader_implicit_vr(DATA, ground_truth);
1044 }
1045
1046 #[test]
1047 fn lazy_read_implicit_len_sequence_implicit_vr_unknown() {
1048 #[rustfmt::skip]
1049 static DATA: &[u8] = &[
1050 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,
1060 0x00, 0x00, 0x00, 0x00, ];
1063
1064 let ground_truth = vec![
1065 DataToken::SequenceStart {
1066 tag: Tag(0x5533, 0x5533),
1067 len: Length::UNDEFINED,
1068 },
1069 DataToken::ItemStart {
1070 len: Length::UNDEFINED,
1071 },
1072 DataToken::ItemEnd,
1073 DataToken::SequenceEnd,
1074 ];
1075
1076 validate_dataset_reader_implicit_vr(DATA, ground_truth);
1077 }
1078
1079 #[test]
1080 fn read_encapsulated_pixeldata() {
1081 #[rustfmt::skip]
1082 static DATA: &[u8] = &[
1083 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,
1095 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
1096 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
1097 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
1098 0xfe, 0xff, 0xdd, 0xe0, 0x00, 0x00, 0x00, 0x00,
1101 0xfc, 0xff, 0xfc, 0xff, b'O', b'B', 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1107 ];
1108
1109 let ground_truth = vec![
1110 DataToken::PixelSequenceStart,
1111 DataToken::ItemStart { len: Length(0) },
1112 DataToken::ItemEnd,
1113 DataToken::ItemStart { len: Length(32) },
1114 DataToken::ItemValue(vec![0x99; 32]),
1115 DataToken::ItemEnd,
1116 DataToken::SequenceEnd,
1117 DataToken::ElementHeader(DataElementHeader::new(
1118 Tag(0xfffc, 0xfffc),
1119 VR::OB,
1120 Length(8),
1121 )),
1122 DataToken::PrimitiveValue(PrimitiveValue::U8([0x00; 8].as_ref().into())),
1123 ];
1124
1125 validate_dataset_reader_explicit_vr(DATA, ground_truth);
1126 }
1127
1128 #[test]
1129 fn lazy_read_encapsulated_pixeldata_with_offset_table() {
1130 #[rustfmt::skip]
1131 static DATA: &[u8] = &[
1132 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,
1146 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
1147 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
1148 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99,
1149 0xfe, 0xff, 0xdd, 0xe0, 0x00, 0x00, 0x00, 0x00,
1152 0xfc, 0xff, 0xfc, 0xff, b'O', b'B', 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1158 ];
1159
1160 let ground_truth = vec![
1161 DataToken::PixelSequenceStart,
1162 DataToken::ItemStart { len: Length(4) },
1163 DataToken::ItemValue(vec![0x10, 0x00, 0x00, 0x00]),
1164 DataToken::ItemEnd,
1165 DataToken::ItemStart { len: Length(32) },
1166 DataToken::ItemValue(vec![0x99; 32]),
1167 DataToken::ItemEnd,
1168 DataToken::SequenceEnd,
1169 DataToken::ElementHeader(DataElementHeader::new(
1170 Tag(0xfffc, 0xfffc),
1171 VR::OB,
1172 Length(8),
1173 )),
1174 DataToken::PrimitiveValue(PrimitiveValue::U8([0x00; 8].as_ref().into())),
1175 ];
1176
1177 validate_dataset_reader_explicit_vr(DATA, ground_truth);
1178 }
1179
1180 #[test]
1181 fn lazy_read_sequence_explicit_2_skip_values() {
1182 static DATA: &[u8] = &[
1183 0x08, 0x00, 0x18, 0x22, b'S', b'Q', 0x00, 0x00, 0x36, 0x00, 0x00, 0x00,
1185 0xfe, 0xff, 0x00, 0xe0, 0x2e, 0x00, 0x00, 0x00,
1188 0x08, 0x00, 0x00, 0x01, b'S', b'H', 0x08, 0x00, 0x54, 0x2d, 0x44, 0x31, 0x32, 0x31, 0x33, b' ',
1192 0x08, 0x00, 0x02, 0x01, b'S', b'H', 0x04, 0x00, 0x53, 0x52, 0x54, b' ',
1196 0x08, 0x00, 0x04, 0x01, b'L', b'O', 0x0a, 0x00, 0x4a, 0x61, 0x77, b' ', 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e,
1200 0x40, 0x00, 0x55, 0x05, b'S', b'Q', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1203 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',
1206 ];
1207
1208 let ground_truth = vec![
1209 DataToken::SequenceStart {
1210 tag: Tag(0x0008, 0x2218),
1211 len: Length(54),
1212 },
1213 DataToken::ItemStart { len: Length(46) },
1214 DataToken::ElementHeader(DataElementHeader {
1215 tag: Tag(0x0008, 0x0100),
1216 vr: VR::SH,
1217 len: Length(8),
1218 }),
1219 DataToken::PrimitiveValue(PrimitiveValue::Strs(
1220 ["T-D1213 ".to_owned()].as_ref().into(),
1221 )),
1222 DataToken::ElementHeader(DataElementHeader {
1223 tag: Tag(0x0008, 0x0102),
1224 vr: VR::SH,
1225 len: Length(4),
1226 }),
1227 DataToken::PrimitiveValue(PrimitiveValue::Strs(["SRT ".to_owned()].as_ref().into())),
1228 DataToken::ElementHeader(DataElementHeader {
1229 tag: Tag(0x0008, 0x0104),
1230 vr: VR::LO,
1231 len: Length(10),
1232 }),
1233 DataToken::PrimitiveValue(PrimitiveValue::Strs(
1234 ["Jaw region".to_owned()].as_ref().into(),
1235 )),
1236 DataToken::ItemEnd,
1237 DataToken::SequenceEnd,
1238 DataToken::SequenceStart {
1239 tag: Tag(0x0040, 0x0555),
1240 len: Length(0),
1241 },
1242 DataToken::SequenceEnd,
1243 DataToken::ElementHeader(DataElementHeader {
1244 tag: Tag(0x2050, 0x0020),
1245 vr: VR::CS,
1246 len: Length(8),
1247 }),
1248 DataToken::PrimitiveValue(PrimitiveValue::Strs(
1249 ["IDENTITY".to_owned()].as_ref().into(),
1250 )),
1251 ];
1252
1253 let mut cursor = DATA;
1254 let parser = StatefulDecoder::new(
1255 &mut cursor,
1256 ExplicitVRLittleEndianDecoder::default(),
1257 LittleEndianBasicDecoder,
1258 SpecificCharacterSet::default(),
1259 );
1260
1261 let mut dset_reader = LazyDataSetReader::new(parser);
1262
1263 let mut gt_iter = ground_truth.into_iter();
1264 while let Some(res) = dset_reader.advance() {
1265 let token = res.expect("should parse without an error");
1266 let gt_token = gt_iter.next().expect("ground truth is shorter");
1267 match token {
1268 LazyDataToken::LazyValue { .. } | LazyDataToken::LazyItemValue { .. } => {
1269 token.skip().unwrap();
1270 }
1271 token => {
1272 let token = token.into_owned().unwrap();
1273 assert_eq!(token, gt_token);
1274 }
1275 }
1276 }
1277
1278 assert_eq!(
1279 gt_iter.count(), 0, "unexpected number of tokens remaining"
1282 );
1283 assert_eq!(dset_reader.parser.position(), DATA.len() as u64);
1284 }
1285
1286 #[test]
1287 fn lazy_read_value_via_into_value() {
1288 const RAW: &[u8; 62] = &[
1300 0x02, 0x00, 0x02, 0x00, 0x55, 0x49, 0x1a, 0x00, 0x31, 0x2e, 0x32, 0x2e, 0x38, 0x34,
1301 0x30, 0x2e, 0x31, 0x30, 0x30, 0x30, 0x38, 0x2e, 0x35, 0x2e, 0x31, 0x2e, 0x34, 0x2e,
1302 0x31, 0x2e, 0x31, 0x2e, 0x31, 0x00, 0x02, 0x00, 0x10, 0x00, 0x55, 0x49, 0x14, 0x00,
1303 0x31, 0x2e, 0x32, 0x2e, 0x38, 0x34, 0x30, 0x2e, 0x31, 0x30, 0x30, 0x30, 0x38, 0x2e,
1304 0x31, 0x2e, 0x32, 0x2e, 0x31, 0x00,
1305 ];
1306 let mut cursor = &RAW[..];
1307 let parser = StatefulDecoder::new(
1308 &mut cursor,
1309 ExplicitVRLittleEndianDecoder::default(),
1310 LittleEndianBasicDecoder,
1311 SpecificCharacterSet::default(),
1312 );
1313
1314 let mut dset_reader = LazyDataSetReader::new(parser);
1315
1316 let token = dset_reader
1317 .advance()
1318 .expect("Expected token 1")
1319 .expect("Failed to read token 1");
1320
1321 let header_token1 = match token {
1322 LazyDataToken::ElementHeader(header) => header,
1323 _ => {
1324 panic!("Unexpected token type (1)");
1325 }
1326 };
1327
1328 let token = dset_reader
1329 .advance()
1330 .expect("Expected token 2")
1331 .expect("Failed to read token 2");
1332
1333 match token {
1334 LazyDataToken::LazyValue { header, decoder: _ } => {
1335 assert_eq!(header_token1, header);
1336 }
1337 _ => {
1338 panic!("Unexpected token type (2)");
1339 }
1340 }
1341
1342 assert_eq!(
1344 token.into_value().unwrap(),
1345 dicom_value!(Strs, ["1.2.840.10008.5.1.4.1.1.1\0"]),
1346 );
1347
1348 let token = dset_reader
1349 .advance()
1350 .expect("Expected token 3")
1351 .expect("Failed to read token 3");
1352
1353 let header_token3 = match token {
1354 LazyDataToken::ElementHeader(header) => header,
1355 _ => {
1356 panic!("Unexpected token type (3)");
1357 }
1358 };
1359
1360 let token = dset_reader
1361 .advance()
1362 .expect("Expected token 4")
1363 .expect("Failed to read token 4");
1364
1365 match token {
1366 LazyDataToken::LazyValue { header, decoder: _ } => {
1367 assert_eq!(header_token3, header);
1368 }
1369 _ => {
1370 panic!("Unexpected token type (4)");
1371 }
1372 }
1373
1374 assert_eq!(
1376 token.into_value().unwrap(),
1377 dicom_value!(Strs, ["1.2.840.10008.1.2.1\0"]),
1378 );
1379
1380 assert!(
1381 dset_reader.advance().is_none(),
1382 "unexpected number of tokens remaining"
1383 );
1384 }
1385
1386 #[test]
1387 fn peek_data_elements() {
1388 #[rustfmt::skip]
1389 static DATA: &[u8] = &[
1390 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', ];
1402
1403 let ground_truth = vec![
1404 DataToken::SequenceStart {
1405 tag: Tag(0x0018, 0x6011),
1406 len: Length::UNDEFINED,
1407 },
1408 DataToken::SequenceEnd,
1409 DataToken::ElementHeader(DataElementHeader {
1410 tag: Tag(0x0020, 0x4000),
1411 vr: VR::LT,
1412 len: Length(4),
1413 }),
1414 DataToken::PrimitiveValue(PrimitiveValue::Str("TEST".into())),
1415 ];
1416
1417 let mut cursor = DATA;
1418 let parser = StatefulDecoder::new(
1419 &mut cursor,
1420 ExplicitVRLittleEndianDecoder::default(),
1421 LittleEndianBasicDecoder::default(),
1422 SpecificCharacterSet::default(),
1423 );
1424 let mut dset_reader = LazyDataSetReader::new(parser);
1425
1426 let token = dset_reader.peek().expect("should peek first token OK");
1428 assert_eq!(token, Some(&ground_truth[0]));
1429
1430 assert_eq!(dset_reader.parser.position(), 12);
1431
1432 let token = dset_reader
1434 .peek()
1435 .expect("should peek first token again OK");
1436 assert_eq!(token, Some(&ground_truth[0]));
1437
1438 assert_eq!(dset_reader.parser.position(), 12);
1439
1440 let token = dset_reader
1442 .advance()
1443 .expect("expected token")
1444 .expect("should read token peeked OK");
1445 assert_eq!(&token.into_owned().unwrap(), &ground_truth[0]);
1446
1447 assert_eq!(dset_reader.parser.position(), 12);
1448
1449 let token = dset_reader
1451 .advance()
1452 .expect("expected token")
1453 .expect("should read token OK");
1454 assert_eq!(&token.into_owned().unwrap(), &ground_truth[1]);
1455
1456 assert_eq!(dset_reader.parser.position(), 20);
1457
1458 let token = dset_reader.peek().expect("should peek first token OK");
1460 assert_eq!(token, Some(&ground_truth[2]));
1461
1462 assert_eq!(dset_reader.parser.position(), 28);
1463
1464 let token = dset_reader
1466 .advance()
1467 .expect("expected token")
1468 .expect("should read token OK");
1469 assert_eq!(&token.into_owned().unwrap(), &ground_truth[2]);
1470
1471 assert_eq!(dset_reader.parser.position(), 28);
1473
1474 let token = dset_reader
1476 .advance()
1477 .expect("expected token")
1478 .expect("should read token OK");
1479 assert_eq!(&token.into_owned().unwrap(), &ground_truth[3]);
1480
1481 assert!(dset_reader.peek().unwrap().is_none());
1483 }
1484
1485 #[test]
1486 fn read_odd_length_element() {
1487 #[rustfmt::skip]
1488 static DATA: &[u8] = &[
1489 0x08, 0x00, 0x16, 0x00, b'U', b'I', 0x0b, 0x00, b'1', b'.', b'2', b'.', b'8', b'4', b'0', b'.', b'1', b'0', b'0',
1493 0x00, ];
1495
1496 let ground_truth = vec![
1497 DataToken::ElementHeader(DataElementHeader {
1498 tag: Tag(0x0008, 0x0016),
1499 vr: VR::UI,
1500 len: Length(12),
1501 }),
1502 DataToken::PrimitiveValue(PrimitiveValue::from("1.2.840.100\0")),
1503 ];
1504
1505 let mut cursor = DATA;
1508 let parser = StatefulDecoder::new(
1509 &mut cursor,
1510 ExplicitVRLittleEndianDecoder::default(),
1511 LittleEndianBasicDecoder,
1512 SpecificCharacterSet::default(),
1513 );
1514 let mut dset_reader = LazyDataSetReader::new_with_options(
1515 parser,
1516 LazyDataSetReaderOptions {
1517 odd_length: OddLengthStrategy::NextEven,
1518 ..Default::default()
1519 },
1520 );
1521
1522 let token = dset_reader
1524 .advance()
1525 .expect("expected token")
1526 .expect("should read token OK");
1527
1528 assert_eq!(&token.into_owned().unwrap(), &ground_truth[0],);
1529
1530 let mut cursor = DATA;
1533 let parser = StatefulDecoder::new(
1534 &mut cursor,
1535 ExplicitVRLittleEndianDecoder::default(),
1536 LittleEndianBasicDecoder,
1537 SpecificCharacterSet::default(),
1538 );
1539 let mut dset_reader = LazyDataSetReader::new_with_options(
1540 parser,
1541 LazyDataSetReaderOptions {
1542 odd_length: OddLengthStrategy::Fail,
1543 ..Default::default()
1544 },
1545 );
1546
1547 let token = dset_reader.advance();
1548
1549 assert!(
1550 matches!(
1551 token,
1552 Some(Err(super::Error::InvalidElementLength {
1553 tag: Tag(0x0008, 0x0016),
1554 len: 11,
1555 bytes_read: 8,
1556 ..
1557 })),
1558 ),
1559 "got: {:?}",
1560 token
1561 );
1562 }
1563}