1use crate::stateful::decode;
3use dicom_core::header::{DataElementHeader, HasLength, Length, VR};
4use dicom_core::value::{DicomValueType, PrimitiveValue};
5use dicom_core::{value::Value, DataElement, Tag};
6use snafu::{OptionExt, ResultExt, Snafu};
7use std::default::Default;
8use std::fmt;
9
10pub mod lazy_read;
11pub mod read;
12pub mod write;
13
14pub use self::read::DataSetReader;
15use self::read::ValueReadStrategy;
16pub use self::write::DataSetWriter;
17
18#[derive(Debug, Snafu)]
19pub enum Error {
20 ReadItemValue { source: decode::Error },
22 ReadElementValue { source: decode::Error },
24 SkipValue { source: decode::Error },
26 UnexpectedTokenType,
28 UndefinedLength,
30}
31
32pub type Result<T, E = Error> = std::result::Result<T, E>;
33
34#[derive(Debug, Clone)]
38pub enum DataToken {
39 ElementHeader(DataElementHeader),
41 SequenceStart { tag: Tag, len: Length },
43 PixelSequenceStart,
45 SequenceEnd,
47 ItemStart { len: Length },
49 ItemEnd,
51 PrimitiveValue(PrimitiveValue),
53 ItemValue(Vec<u8>),
59 OffsetTable(Vec<u32>),
67}
68
69impl fmt::Display for DataToken {
70 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
71 match self {
72 DataToken::PrimitiveValue(ref v) => write!(f, "PrimitiveValue({:?})", v.value_type()),
73 other => write!(f, "{:?}", other),
74 }
75 }
76}
77
78impl PartialEq<Self> for DataToken {
80 fn eq(&self, other: &Self) -> bool {
81 use DataToken::*;
82 match (self, other) {
83 (
84 ElementHeader(DataElementHeader {
85 tag: tag1,
86 vr: vr1,
87 len: len1,
88 }),
89 ElementHeader(DataElementHeader {
90 tag: tag2,
91 vr: vr2,
92 len: len2,
93 }),
94 ) => tag1 == tag2 && vr1 == vr2 && len1.inner_eq(*len2),
95 (
96 SequenceStart {
97 tag: tag1,
98 len: len1,
99 },
100 SequenceStart {
101 tag: tag2,
102 len: len2,
103 },
104 ) => tag1 == tag2 && len1.inner_eq(*len2),
105 (ItemStart { len: len1 }, ItemStart { len: len2 }) => len1.inner_eq(*len2),
106 (PrimitiveValue(v1), PrimitiveValue(v2)) => v1 == v2,
107 (ItemValue(v1), ItemValue(v2)) => v1 == v2,
108 (OffsetTable(v1), OffsetTable(v2)) => v1 == v2,
109 (ItemEnd, ItemEnd)
110 | (SequenceEnd, SequenceEnd)
111 | (PixelSequenceStart, PixelSequenceStart) => true,
112 _ => false,
113 }
114 }
115}
116
117impl From<DataElementHeader> for DataToken {
118 fn from(header: DataElementHeader) -> Self {
119 match (header.vr(), header.tag) {
120 (VR::OB, Tag(0x7fe0, 0x0010)) if header.len.is_undefined() => {
121 DataToken::PixelSequenceStart
122 }
123 (VR::SQ, _) => DataToken::SequenceStart {
124 tag: header.tag,
125 len: header.len,
126 },
127 _ => DataToken::ElementHeader(header),
128 }
129 }
130}
131
132impl DataToken {
133 pub fn is_sequence_start(&self) -> bool {
136 matches!(self, DataToken::SequenceStart { .. })
137 }
138
139 pub fn is_sequence_end(&self) -> bool {
142 matches!(self, DataToken::SequenceEnd)
143 }
144}
145
146#[derive(Debug)]
157#[non_exhaustive]
158pub enum LazyDataToken<D> {
159 ElementHeader(DataElementHeader),
161 SequenceStart { tag: Tag, len: Length },
163 PixelSequenceStart,
165 SequenceEnd,
167 ItemStart { len: Length },
169 ItemEnd,
171 LazyValue {
173 header: DataElementHeader,
175 decoder: D,
177 },
178 LazyItemValue {
180 len: u32,
182 decoder: D,
184 },
185}
186
187impl<D> LazyDataToken<D> {
188 pub fn is_sequence_start(&self) -> bool {
191 matches!(self, LazyDataToken::SequenceStart { .. })
192 }
193
194 pub fn is_sequence_end(&self) -> bool {
197 matches!(self, LazyDataToken::SequenceEnd)
198 }
199}
200
201impl<D> LazyDataToken<D>
202where
203 D: decode::StatefulDecode,
204{
205 pub fn skip(self) -> crate::stateful::decode::Result<()> {
206 match self {
207 LazyDataToken::LazyValue {
208 header,
209 mut decoder,
210 } => decoder.skip_bytes(header.len.0),
211 LazyDataToken::LazyItemValue { len, mut decoder } => decoder.skip_bytes(len),
212 _ => Ok(()), }
214 }
215 pub fn into_owned(self) -> Result<DataToken> {
221 self.into_owned_with_strategy(ValueReadStrategy::Preserved)
222 }
223
224 pub fn into_owned_with_strategy(self, strategy: ValueReadStrategy) -> Result<DataToken> {
231 match self {
232 LazyDataToken::ElementHeader(header) => Ok(DataToken::ElementHeader(header)),
233 LazyDataToken::ItemEnd => Ok(DataToken::ItemEnd),
234 LazyDataToken::ItemStart { len } => Ok(DataToken::ItemStart { len }),
235 LazyDataToken::PixelSequenceStart => Ok(DataToken::PixelSequenceStart),
236 LazyDataToken::SequenceEnd => Ok(DataToken::SequenceEnd),
237 LazyDataToken::SequenceStart { tag, len } => Ok(DataToken::SequenceStart { tag, len }),
238 LazyDataToken::LazyValue {
239 header,
240 mut decoder,
241 } => {
242 let value = match strategy {
244 ValueReadStrategy::Interpreted => {
245 decoder.read_value(&header).context(ReadElementValueSnafu)?
246 }
247 ValueReadStrategy::Preserved => decoder
248 .read_value_preserved(&header)
249 .context(ReadElementValueSnafu)?,
250 ValueReadStrategy::Raw => decoder
251 .read_value_bytes(&header)
252 .context(ReadElementValueSnafu)?,
253 };
254 Ok(DataToken::PrimitiveValue(value))
255 }
256 LazyDataToken::LazyItemValue { len, mut decoder } => {
257 let mut data = Vec::new();
258 decoder
259 .read_to_vec(len, &mut data)
260 .context(ReadItemValueSnafu)?;
261 Ok(DataToken::ItemValue(data))
262 }
263 }
264 }
265
266 pub fn into_value_with_strategy(self, strategy: ValueReadStrategy) -> Result<PrimitiveValue> {
271 match self {
272 LazyDataToken::LazyValue {
273 header,
274 mut decoder,
275 } => {
276 match strategy {
278 ValueReadStrategy::Interpreted => {
279 decoder.read_value(&header).context(ReadElementValueSnafu)
280 }
281 ValueReadStrategy::Preserved => decoder
282 .read_value_preserved(&header)
283 .context(ReadElementValueSnafu),
284 ValueReadStrategy::Raw => decoder
285 .read_value_bytes(&header)
286 .context(ReadElementValueSnafu),
287 }
288 }
289 _ => UnexpectedTokenTypeSnafu.fail(),
290 }
291 }
292
293 pub fn into_value(self) -> Result<PrimitiveValue> {
298 self.into_value_with_strategy(ValueReadStrategy::Preserved)
299 }
300
301 pub fn read_value_into<W>(self, out: W) -> Result<()>
311 where
312 W: std::io::Write,
313 {
314 match self {
315 LazyDataToken::LazyValue {
316 header,
317 mut decoder,
318 } => {
319 let len = header.len.get().context(UndefinedLengthSnafu)?;
320 decoder.read_to(len, out).context(ReadElementValueSnafu)?;
321 }
322 LazyDataToken::LazyItemValue { len, mut decoder } => {
323 decoder.read_to(len, out).context(ReadItemValueSnafu)?;
324 }
325 _other => return UnexpectedTokenTypeSnafu.fail(),
326 };
327 Ok(())
328 }
329
330 pub fn into_repr(self) -> LazyDataTokenRepr {
333 LazyDataTokenRepr::from(self)
334 }
335
336 pub fn repr(&self) -> LazyDataTokenRepr {
339 LazyDataTokenRepr::from(self)
340 }
341}
342
343impl<D> From<LazyDataToken<D>> for LazyDataTokenRepr {
344 fn from(token: LazyDataToken<D>) -> Self {
345 match token {
346 LazyDataToken::ElementHeader(h) => LazyDataTokenRepr::ElementHeader(h),
347 LazyDataToken::SequenceStart { tag, len } => {
348 LazyDataTokenRepr::SequenceStart { tag, len }
349 }
350 LazyDataToken::PixelSequenceStart => LazyDataTokenRepr::PixelSequenceStart,
351 LazyDataToken::SequenceEnd => LazyDataTokenRepr::SequenceEnd,
352 LazyDataToken::ItemStart { len } => LazyDataTokenRepr::ItemStart { len },
353 LazyDataToken::ItemEnd => LazyDataTokenRepr::ItemEnd,
354 LazyDataToken::LazyValue { header, decoder: _ } => {
355 LazyDataTokenRepr::LazyValue { header }
356 }
357 LazyDataToken::LazyItemValue { len, decoder: _ } => {
358 LazyDataTokenRepr::LazyItemValue { len }
359 }
360 }
361 }
362}
363
364impl<D> From<&LazyDataToken<D>> for LazyDataTokenRepr {
365 fn from(token: &LazyDataToken<D>) -> Self {
366 match *token {
367 LazyDataToken::ElementHeader(h) => LazyDataTokenRepr::ElementHeader(h),
368 LazyDataToken::SequenceStart { tag, len } => {
369 LazyDataTokenRepr::SequenceStart { tag, len }
370 }
371 LazyDataToken::PixelSequenceStart => LazyDataTokenRepr::PixelSequenceStart,
372 LazyDataToken::SequenceEnd => LazyDataTokenRepr::SequenceEnd,
373 LazyDataToken::ItemStart { len } => LazyDataTokenRepr::ItemStart { len },
374 LazyDataToken::ItemEnd => LazyDataTokenRepr::ItemEnd,
375 LazyDataToken::LazyValue { header, decoder: _ } => {
376 LazyDataTokenRepr::LazyValue { header }
377 }
378 LazyDataToken::LazyItemValue { len, decoder: _ } => {
379 LazyDataTokenRepr::LazyItemValue { len }
380 }
381 }
382 }
383}
384
385#[derive(Debug, Clone, PartialEq)]
388pub enum LazyDataTokenRepr {
389 ElementHeader(DataElementHeader),
391 SequenceStart { tag: Tag, len: Length },
393 PixelSequenceStart,
395 SequenceEnd,
397 ItemStart { len: Length },
399 ItemEnd,
401 LazyValue {
403 header: DataElementHeader,
405 },
406 LazyItemValue {
408 len: u32,
410 },
411}
412
413#[derive(Debug, Copy, Clone, Eq, PartialEq)]
415pub enum SeqTokenType {
416 Sequence,
417 Item,
418}
419
420#[derive(Debug, Copy, Clone, Default, Eq, PartialEq)]
422#[non_exhaustive]
423pub struct IntoTokensOptions {
424 pub force_invalidate_sq_length: bool,
435}
436
437impl IntoTokensOptions {
438 pub fn new(force_invalidate_sq_length: bool) -> Self {
439 IntoTokensOptions {
440 force_invalidate_sq_length,
441 }
442 }
443}
444
445pub trait IntoTokens {
447 type Iter: Iterator<Item = DataToken>;
449
450 fn into_tokens(self) -> Self::Iter;
451 fn into_tokens_with_options(self, options: IntoTokensOptions) -> Self::Iter;
452}
453
454impl IntoTokens for dicom_core::header::EmptyObject {
455 type Iter = std::iter::Empty<DataToken>;
456
457 fn into_tokens(self) -> Self::Iter {
458 unreachable!()
459 }
460
461 fn into_tokens_with_options(self, _options: IntoTokensOptions) -> Self::Iter {
462 unreachable!()
463 }
464}
465
466pub enum DataElementTokens<I, P>
468where
469 I: IntoTokens,
470{
471 Start(
473 Option<DataElement<I, P>>,
476 IntoTokensOptions,
477 ),
478 Header(
480 Option<DataElement<I, P>>,
483 ),
484 Items(
486 FlattenTokens<
487 <dicom_core::value::C<AsItem<I>> as IntoIterator>::IntoIter,
488 ItemTokens<I::Iter>,
489 >,
490 ),
491 PixelData(
494 Option<dicom_core::value::C<P>>,
499 OffsetTableItemTokens<dicom_core::value::C<u32>>,
501 ),
502 PixelDataFragments(
505 FlattenTokens<
506 <dicom_core::value::C<ItemValue<P>> as IntoIterator>::IntoIter,
507 ItemValueTokens<P>,
508 >,
509 ),
510 End,
512}
513
514impl<I, P> Iterator for DataElementTokens<I, P>
515where
516 I: IntoTokens,
517 I: HasLength,
518 P: AsRef<[u8]>,
519{
520 type Item = DataToken;
521
522 fn next(&mut self) -> Option<Self::Item> {
523 let (out, next_state) = match self {
524 DataElementTokens::Start(elem, options) => {
525 let elem = elem.take().unwrap();
526 let mut header = *elem.header();
529 if options.force_invalidate_sq_length && elem.vr() == VR::SQ {
530 header.len = Length::UNDEFINED;
531 }
532
533 let token = DataToken::from(header);
534 match token {
535 DataToken::SequenceStart { .. } => {
536 match elem.into_value() {
538 Value::Primitive(_) | Value::PixelSequence { .. } => unreachable!(),
539 Value::Sequence(seq) => {
540 let seq = if options.force_invalidate_sq_length {
541 seq.into_items().into_vec().into()
542 } else {
543 seq
544 };
545
546 let items: dicom_core::value::C<_> = seq
547 .into_items()
548 .into_iter()
549 .map(|o| AsItem(o.length(), o))
550 .collect();
551 (
552 Some(token),
553 DataElementTokens::Items(
554 items.into_tokens_with_options(*options),
555 ),
556 )
557 }
558 }
559 }
560 DataToken::PixelSequenceStart => {
561 match elem.into_value() {
562 Value::PixelSequence(seq) => {
563 let (offset_table, fragments) = seq.into_parts();
564 (
565 Some(DataToken::PixelSequenceStart),
567 DataElementTokens::PixelData(
568 Some(fragments),
569 OffsetTableItem(offset_table)
570 .into_tokens_with_options(*options),
571 ),
572 )
573 }
574 Value::Primitive(_) | Value::Sequence { .. } => unreachable!(),
575 }
576 }
577 _ => (
578 Some(DataToken::ElementHeader(*elem.header())),
579 DataElementTokens::Header(Some(elem)),
580 ),
581 }
582 }
583 DataElementTokens::Header(elem) => {
584 let elem = elem.take().unwrap();
585 match elem.into_value() {
586 Value::Sequence { .. } | Value::PixelSequence { .. } => unreachable!(),
587 Value::Primitive(value) => {
588 let token = DataToken::PrimitiveValue(value);
590 (Some(token), DataElementTokens::End)
591 }
592 }
593 }
594 DataElementTokens::Items(tokens) => {
595 if let Some(token) = tokens.next() {
596 return Some(token);
598 } else {
599 (Some(DataToken::SequenceEnd), DataElementTokens::End)
601 }
602 }
603 DataElementTokens::PixelData(fragments, tokens) => {
604 if let Some(token) = tokens.next() {
605 return Some(token);
607 }
608 let fragments = fragments.take().unwrap();
610 let tokens: dicom_core::value::C<_> =
611 fragments.into_iter().map(ItemValue).collect();
612 *self = DataElementTokens::PixelDataFragments(tokens.into_tokens());
613 return self.next();
615 }
616 DataElementTokens::PixelDataFragments(tokens) => {
617 if let Some(token) = tokens.next() {
618 return Some(token);
620 } else {
621 (Some(DataToken::SequenceEnd), DataElementTokens::End)
623 }
624 }
625 DataElementTokens::End => return None,
626 };
627 *self = next_state;
628
629 out
630 }
631}
632
633impl<I, P> IntoTokens for DataElement<I, P>
634where
635 I: IntoTokens,
636 I: HasLength,
637 P: AsRef<[u8]>,
638{
639 type Iter = DataElementTokens<I, P>;
640
641 fn into_tokens(self) -> Self::Iter {
642 self.into_tokens_with_options(Default::default())
644 }
645
646 fn into_tokens_with_options(self, options: IntoTokensOptions) -> Self::Iter {
647 DataElementTokens::Start(Some(self), options)
648 }
649}
650
651#[derive(Debug, PartialEq)]
654pub struct FlattenTokens<O, K> {
655 seq: O,
656 tokens: Option<K>,
657 into_token_options: IntoTokensOptions,
658}
659
660impl<O, K> Iterator for FlattenTokens<O, K>
661where
662 O: Iterator,
663 O::Item: IntoTokens<Iter = K>,
664 K: Iterator<Item = DataToken>,
665{
666 type Item = DataToken;
667
668 fn next(&mut self) -> Option<Self::Item> {
669 if self.tokens.is_none() {
671 match self.seq.next() {
672 Some(entries) => {
673 self.tokens = Some(entries.into_tokens_with_options(self.into_token_options));
674 }
675 None => return None,
676 }
677 }
678
679 match self.tokens.as_mut().map(|s| s.next()) {
681 Some(Some(token)) => Some(token),
682 Some(None) => {
683 self.tokens = None;
684 self.next()
685 }
686 None => unreachable!(),
687 }
688 }
689}
690
691impl<T> IntoTokens for Vec<T>
692where
693 T: IntoTokens,
694{
695 type Iter = FlattenTokens<<Vec<T> as IntoIterator>::IntoIter, <T as IntoTokens>::Iter>;
696
697 fn into_tokens(self) -> Self::Iter {
698 self.into_tokens_with_options(Default::default())
699 }
700
701 fn into_tokens_with_options(self, into_token_options: IntoTokensOptions) -> Self::Iter {
702 FlattenTokens {
703 seq: self.into_iter(),
704 tokens: None,
705 into_token_options,
706 }
707 }
708}
709
710impl<T> IntoTokens for dicom_core::value::C<T>
711where
712 T: IntoTokens,
713{
714 type Iter =
715 FlattenTokens<<dicom_core::value::C<T> as IntoIterator>::IntoIter, <T as IntoTokens>::Iter>;
716
717 fn into_tokens(self) -> Self::Iter {
718 self.into_tokens_with_options(Default::default())
719 }
720
721 fn into_tokens_with_options(self, into_token_options: IntoTokensOptions) -> Self::Iter {
722 FlattenTokens {
723 seq: self.into_iter(),
724 tokens: None,
725 into_token_options,
726 }
727 }
728}
729
730#[derive(Debug)]
732pub enum ItemTokens<T> {
733 Start {
735 len: Length,
736 object_tokens: Option<T>,
737 },
738 Object { object_tokens: T },
741 End,
743}
744
745impl<T> ItemTokens<T>
746where
747 T: Iterator<Item = DataToken>,
748{
749 pub fn new<O>(len: Length, object: O, options: IntoTokensOptions) -> Self
750 where
751 O: IntoTokens<Iter = T>,
752 {
753 let len = if len.0 != 0 && options.force_invalidate_sq_length {
754 Length::UNDEFINED
755 } else {
756 len
757 };
758 ItemTokens::Start {
759 len,
760 object_tokens: Some(object.into_tokens_with_options(options)),
761 }
762 }
763}
764
765impl<T> Iterator for ItemTokens<T>
766where
767 T: Iterator<Item = DataToken>,
768{
769 type Item = DataToken;
770
771 fn next(&mut self) -> Option<Self::Item> {
772 let (next_state, out) = match self {
773 ItemTokens::Start { len, object_tokens } => (
774 ItemTokens::Object {
775 object_tokens: object_tokens.take().unwrap(),
776 },
777 Some(DataToken::ItemStart { len: *len }),
778 ),
779 ItemTokens::Object { object_tokens } => {
780 if let Some(token) = object_tokens.next() {
781 return Some(token);
782 } else {
783 (ItemTokens::End, Some(DataToken::ItemEnd))
784 }
785 }
786 ItemTokens::End => {
787 return None;
788 }
789 };
790
791 *self = next_state;
792 out
793 }
794}
795
796#[derive(Debug, Clone, PartialEq)]
800pub struct AsItem<I>(Length, I);
801
802impl<I> IntoTokens for AsItem<I>
803where
804 I: IntoTokens,
805{
806 type Iter = ItemTokens<I::Iter>;
807
808 fn into_tokens(self) -> Self::Iter {
809 self.into_tokens_with_options(Default::default())
810 }
811
812 fn into_tokens_with_options(self, options: IntoTokensOptions) -> Self::Iter {
813 ItemTokens::new(self.0, self.1, options)
814 }
815}
816
817impl<I> HasLength for AsItem<I> {
818 fn length(&self) -> Length {
819 self.0
820 }
821}
822
823#[derive(Debug, Clone, PartialEq)]
828pub struct ItemValue<P>(P);
829
830impl<P> IntoTokens for ItemValue<P>
831where
832 P: AsRef<[u8]>,
833{
834 type Iter = ItemValueTokens<P>;
835
836 fn into_tokens(self) -> Self::Iter {
837 self.into_tokens_with_options(Default::default())
838 }
839
840 fn into_tokens_with_options(self, options: IntoTokensOptions) -> Self::Iter {
841 ItemValueTokens::new(self.0, options)
842 }
843}
844
845#[derive(Debug)]
846pub enum ItemValueTokens<P> {
847 Start(Option<P>, bool),
850 Value(P),
852 Done,
854 End,
856}
857
858impl<P> ItemValueTokens<P> {
859 #[inline]
860 pub fn new(value: P, into_tokens_options: IntoTokensOptions) -> Self {
861 ItemValueTokens::Start(Some(value), into_tokens_options.force_invalidate_sq_length)
862 }
863}
864
865impl<P> Iterator for ItemValueTokens<P>
866where
867 P: AsRef<[u8]>,
868{
869 type Item = DataToken;
870
871 fn next(&mut self) -> Option<Self::Item> {
872 let (out, next_state) = match self {
873 ItemValueTokens::Start(value, invalidate_len) => {
874 let value = value.take().unwrap();
875 let end_item = value.as_ref().is_empty();
876 let len = if *invalidate_len && !end_item {
877 Length::UNDEFINED
878 } else {
879 Length(value.as_ref().len() as u32)
880 };
881
882 (
883 Some(DataToken::ItemStart { len }),
884 if end_item {
885 ItemValueTokens::Done
886 } else {
887 ItemValueTokens::Value(value)
888 },
889 )
890 }
891 ItemValueTokens::Value(value) => (
892 Some(DataToken::ItemValue(value.as_ref().to_owned())),
893 ItemValueTokens::Done,
894 ),
895 ItemValueTokens::Done => (Some(DataToken::ItemEnd), ItemValueTokens::End),
896 ItemValueTokens::End => return None,
897 };
898
899 *self = next_state;
900 out
901 }
902}
903
904#[derive(Debug, Clone, PartialEq)]
910pub struct OffsetTableItem<P>(P);
911
912impl<P> IntoTokens for OffsetTableItem<P>
913where
914 P: AsRef<[u32]>,
915{
916 type Iter = OffsetTableItemTokens<P>;
917
918 fn into_tokens(self) -> Self::Iter {
919 self.into_tokens_with_options(Default::default())
920 }
921
922 fn into_tokens_with_options(self, _options: IntoTokensOptions) -> Self::Iter {
923 OffsetTableItemTokens::new(self.0)
925 }
926}
927
928#[derive(Debug)]
929pub enum OffsetTableItemTokens<P> {
930 Start(Option<P>),
932 Value(P),
934 Done,
936 End,
938}
939
940impl<P> OffsetTableItemTokens<P> {
941 #[inline]
942 pub fn new(value: P) -> Self {
943 OffsetTableItemTokens::Start(Some(value))
944 }
945}
946
947impl<P> Iterator for OffsetTableItemTokens<P>
948where
949 P: AsRef<[u32]>,
950{
951 type Item = DataToken;
952
953 fn next(&mut self) -> Option<Self::Item> {
954 let (out, next_state) = match self {
955 OffsetTableItemTokens::Start(value) => {
956 let value = value.take().unwrap();
957 let len = Length(value.as_ref().len() as u32 * 4);
958
959 (
960 Some(DataToken::ItemStart { len }),
961 if len == Length(0) {
962 OffsetTableItemTokens::Done
963 } else {
964 OffsetTableItemTokens::Value(value)
965 },
966 )
967 }
968 OffsetTableItemTokens::Value(value) => (
969 Some(DataToken::OffsetTable(value.as_ref().to_owned())),
970 OffsetTableItemTokens::Done,
971 ),
972 OffsetTableItemTokens::Done => (Some(DataToken::ItemEnd), OffsetTableItemTokens::End),
973 OffsetTableItemTokens::End => return None,
974 };
975
976 *self = next_state;
977 out
978 }
979}
980
981#[cfg(test)]
982mod tests {
983 use dicom_core::{
984 dicom_value, header::HasLength, DataElement, DataElementHeader, DicomValue, Length,
985 PrimitiveValue, Tag, VR,
986 };
987
988 use super::{DataToken, IntoTokens, IntoTokensOptions, LazyDataToken};
989 use smallvec::smallvec;
990
991 use dicom_encoding::{
992 decode::{basic::LittleEndianBasicDecoder, explicit_le::ExplicitVRLittleEndianDecoder},
993 text::SpecificCharacterSet,
994 };
995
996 use crate::stateful::decode::StatefulDecode;
997 use crate::stateful::decode::StatefulDecoder;
998
999 fn is_stateful_decode<D: StatefulDecode>(_: &D) {}
1000
1001 #[derive(Debug, Clone)]
1004 struct SimpleObject<T>(Length, dicom_core::value::C<T>);
1005
1006 impl<T> HasLength for SimpleObject<T> {
1007 fn length(&self) -> Length {
1008 self.0
1009 }
1010 }
1011
1012 impl<T> IntoTokens for SimpleObject<T>
1013 where
1014 T: IntoTokens,
1015 T: HasLength,
1016 {
1017 type Iter = super::FlattenTokens<
1018 <dicom_core::value::C<T> as IntoIterator>::IntoIter,
1019 <T as IntoTokens>::Iter,
1020 >;
1021
1022 fn into_tokens(self) -> Self::Iter {
1023 self.into_tokens_with_options(Default::default())
1024 }
1025
1026 fn into_tokens_with_options(self, into_token_options: IntoTokensOptions) -> Self::Iter {
1027 super::FlattenTokens {
1028 seq: self.1.into_iter(),
1029 tokens: None,
1030 into_token_options,
1031 }
1032 }
1033 }
1034
1035 #[test]
1036 fn basic_element_into_tokens() {
1037 let element = DataElement::new(
1038 Tag(0x0010, 0x0010),
1039 VR::PN,
1040 DicomValue::new("Doe^John".into()),
1041 );
1042
1043 let tokens: Vec<_> = element.clone().into_tokens().collect();
1044
1045 assert_eq!(
1046 &tokens,
1047 &[
1048 DataToken::ElementHeader(*element.header()),
1049 DataToken::PrimitiveValue("Doe^John".into()),
1050 ],
1051 )
1052 }
1053
1054 #[test]
1055 fn sequence_implicit_len_into_tokens() {
1056 let element = DataElement::new(
1057 Tag(0x0008, 0x2218),
1058 VR::SQ,
1059 DicomValue::new_sequence(
1060 vec![SimpleObject(
1061 Length::UNDEFINED,
1062 smallvec![
1063 DataElement::new(
1064 Tag(0x0008, 0x0100),
1065 VR::SH,
1066 DicomValue::new(dicom_value!(Strs, ["T-D1213 "])),
1067 ),
1068 DataElement::new(
1069 Tag(0x0008, 0x0102),
1070 VR::SH,
1071 DicomValue::new(dicom_value!(Strs, ["SRT "])),
1072 ),
1073 DataElement::new(
1074 Tag(0x0008, 0x0104),
1075 VR::LO,
1076 DicomValue::new(dicom_value!(Strs, ["Jaw region"])),
1077 ),
1078 ],
1079 )],
1080 Length::UNDEFINED,
1081 ),
1082 );
1083
1084 let tokens: Vec<_> = element.clone().into_tokens().collect();
1085
1086 assert_eq!(
1087 &tokens,
1088 &[
1089 DataToken::SequenceStart {
1090 tag: Tag(0x0008, 0x2218),
1091 len: Length::UNDEFINED,
1092 },
1093 DataToken::ItemStart {
1094 len: Length::UNDEFINED
1095 },
1096 DataToken::ElementHeader(DataElementHeader {
1097 tag: Tag(0x0008, 0x0100),
1098 vr: VR::SH,
1099 len: Length(8),
1100 }),
1101 DataToken::PrimitiveValue(PrimitiveValue::Strs(
1102 ["T-D1213 ".to_owned()].as_ref().into(),
1103 )),
1104 DataToken::ElementHeader(DataElementHeader {
1105 tag: Tag(0x0008, 0x0102),
1106 vr: VR::SH,
1107 len: Length(4),
1108 }),
1109 DataToken::PrimitiveValue(PrimitiveValue::Strs(
1110 ["SRT ".to_owned()].as_ref().into()
1111 )),
1112 DataToken::ElementHeader(DataElementHeader {
1113 tag: Tag(0x0008, 0x0104),
1114 vr: VR::LO,
1115 len: Length(10),
1116 }),
1117 DataToken::PrimitiveValue(PrimitiveValue::Strs(
1118 ["Jaw region".to_owned()].as_ref().into(),
1119 )),
1120 DataToken::ItemEnd,
1121 DataToken::SequenceEnd,
1122 ],
1123 )
1124 }
1125
1126 #[test]
1127 fn sequence_explicit_len_into_tokens() {
1128 let element = DataElement::new(
1129 Tag(0x0008, 0x2218),
1130 VR::SQ,
1131 DicomValue::new_sequence(
1132 vec![SimpleObject(
1133 Length(46),
1134 smallvec![
1135 DataElement::new(
1136 Tag(0x0008, 0x0100),
1137 VR::SH,
1138 DicomValue::new(dicom_value!(Strs, ["T-D1213 "])),
1139 ),
1140 DataElement::new(
1141 Tag(0x0008, 0x0102),
1142 VR::SH,
1143 DicomValue::new(dicom_value!(Strs, ["SRT "])),
1144 ),
1145 DataElement::new(
1146 Tag(0x0008, 0x0104),
1147 VR::LO,
1148 DicomValue::new(dicom_value!(Strs, ["Jaw region"])),
1149 ),
1150 ],
1151 )],
1152 Length(54),
1153 ),
1154 );
1155
1156 let tokens: Vec<_> = element.clone().into_tokens().collect();
1157
1158 assert_eq!(
1159 &tokens,
1160 &[
1161 DataToken::SequenceStart {
1162 tag: Tag(0x0008, 0x2218),
1163 len: Length(54),
1164 },
1165 DataToken::ItemStart { len: Length(46) },
1166 DataToken::ElementHeader(DataElementHeader {
1167 tag: Tag(0x0008, 0x0100),
1168 vr: VR::SH,
1169 len: Length(8),
1170 }),
1171 DataToken::PrimitiveValue(PrimitiveValue::Strs(
1172 ["T-D1213 ".to_owned()].as_ref().into(),
1173 )),
1174 DataToken::ElementHeader(DataElementHeader {
1175 tag: Tag(0x0008, 0x0102),
1176 vr: VR::SH,
1177 len: Length(4),
1178 }),
1179 DataToken::PrimitiveValue(PrimitiveValue::Strs(
1180 ["SRT ".to_owned()].as_ref().into()
1181 )),
1182 DataToken::ElementHeader(DataElementHeader {
1183 tag: Tag(0x0008, 0x0104),
1184 vr: VR::LO,
1185 len: Length(10),
1186 }),
1187 DataToken::PrimitiveValue(PrimitiveValue::Strs(
1188 ["Jaw region".to_owned()].as_ref().into(),
1189 )),
1190 DataToken::ItemEnd,
1191 DataToken::SequenceEnd,
1192 ],
1193 )
1194 }
1195
1196 #[test]
1197 fn lazy_dataset_token_value() {
1198 let data = b"1.234\0";
1199 let mut data = &data[..];
1200 let decoder = StatefulDecoder::new(
1201 &mut data,
1202 ExplicitVRLittleEndianDecoder::default(),
1203 LittleEndianBasicDecoder,
1204 SpecificCharacterSet::default(),
1205 );
1206
1207 is_stateful_decode(&decoder);
1208
1209 let token = LazyDataToken::LazyValue {
1210 header: DataElementHeader {
1211 tag: Tag(0x0020, 0x000D),
1212 vr: VR::UI,
1213 len: Length(6),
1214 },
1215 decoder,
1216 };
1217
1218 match token.into_owned().unwrap() {
1219 DataToken::PrimitiveValue(v) => {
1220 assert_eq!(v.to_raw_str(), "1.234\0",);
1221 }
1222 t => panic!("Unexpected type of token {:?}", t),
1223 }
1224 }
1225
1226 #[test]
1227 fn lazy_dataset_token_value_as_mut() {
1228 let data = b"1.234\0";
1229 let mut data = &data[..];
1230 let mut decoder = StatefulDecoder::new(
1231 &mut data,
1232 ExplicitVRLittleEndianDecoder::default(),
1233 LittleEndianBasicDecoder,
1234 SpecificCharacterSet::default(),
1235 );
1236
1237 is_stateful_decode(&decoder);
1238
1239 let token = LazyDataToken::LazyValue {
1240 header: DataElementHeader {
1241 tag: Tag(0x0020, 0x000D),
1242 vr: VR::UI,
1243 len: Length(6),
1244 },
1245 decoder: &mut decoder,
1246 };
1247
1248 match token.into_owned().unwrap() {
1249 DataToken::PrimitiveValue(v) => {
1250 assert_eq!(v.to_raw_str(), "1.234\0",);
1251 }
1252 t => panic!("Unexpected type of token {:?}", t),
1253 }
1254 assert_eq!(decoder.position(), 6);
1255 }
1256
1257 #[test]
1258 fn lazy_dataset_token_value_skip() {
1259 let data = b"1.234\0";
1260 let mut data = &data[..];
1261 let mut decoder = StatefulDecoder::new(
1262 &mut data,
1263 ExplicitVRLittleEndianDecoder::default(),
1264 LittleEndianBasicDecoder,
1265 SpecificCharacterSet::default(),
1266 );
1267
1268 is_stateful_decode(&decoder);
1269
1270 let token = LazyDataToken::LazyValue {
1271 header: DataElementHeader {
1272 tag: Tag(0x0020, 0x000D),
1273 vr: VR::UI,
1274 len: Length(6),
1275 },
1276 decoder: &mut decoder,
1277 };
1278
1279 token.skip().unwrap();
1280
1281 assert_eq!(decoder.position(), 6);
1282 }
1283}