dicom_parser/dataset/
mod.rs

1//! Interpretation of DICOM data sets as streams of tokens.
2use 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    /// Could not read item value
21    ReadItemValue { source: decode::Error },
22    /// Could not read element value
23    ReadElementValue { source: decode::Error },
24    /// Could not skip the bytes of a value
25    SkipValue { source: decode::Error },
26    /// Unexpected token type for operation
27    UnexpectedTokenType,
28    /// Unexpected undefined value length
29    UndefinedLength,
30}
31
32pub type Result<T, E = Error> = std::result::Result<T, E>;
33
34/// A token of a DICOM data set stream. This is part of the interpretation of a
35/// data set as a stream of symbols, which may either represent data headers or
36/// actual value data.
37#[derive(Debug, Clone)]
38pub enum DataToken {
39    /// A data header of a primitive value.
40    ElementHeader(DataElementHeader),
41    /// The beginning of a sequence element.
42    SequenceStart { tag: Tag, len: Length },
43    /// The beginning of an encapsulated pixel data element.
44    PixelSequenceStart,
45    /// The ending delimiter of a sequence or encapsulated pixel data.
46    SequenceEnd,
47    /// The beginning of a new item in the sequence.
48    ItemStart { len: Length },
49    /// The ending delimiter of an item.
50    ItemEnd,
51    /// A primitive data element value.
52    PrimitiveValue(PrimitiveValue),
53    /// An owned piece of raw data representing an item's value.
54    ///
55    /// This variant is used to represent
56    /// the value of an encoded fragment.
57    /// It should not be used to represent nested data sets.
58    ItemValue(Vec<u8>),
59    /// An owned sequence of unsigned 32 bit integers
60    /// representing a pixel data offset table.
61    ///
62    /// This variant is used to represent
63    /// the byte offsets to the first byte of the Item tag of the first fragment
64    /// for each frame in the sequence of items,
65    /// as per PS 3.5, Section A.4.
66    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
78/// This implementation treats undefined lengths as equal.
79impl 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    /// Check whether this token represents the start of a sequence
134    /// of nested data sets.
135    pub fn is_sequence_start(&self) -> bool {
136        matches!(self, DataToken::SequenceStart { .. })
137    }
138
139    /// Check whether this token represents the end of a sequence
140    /// or the end of an encapsulated element.
141    pub fn is_sequence_end(&self) -> bool {
142        matches!(self, DataToken::SequenceEnd)
143    }
144}
145
146/// A lazy data token for reading a data set
147/// without requiring values to be fully read in memory.
148/// This is part of the interpretation of a
149/// data set as a stream of symbols,
150/// which may either represent data headers
151/// or actual value data.
152///
153/// The parameter type `D` represents
154/// the original type of the stateful decoder,
155/// and through which the values can be retrieved.
156#[derive(Debug)]
157#[non_exhaustive]
158pub enum LazyDataToken<D> {
159    /// A data header of a primitive value.
160    ElementHeader(DataElementHeader),
161    /// The beginning of a sequence element.
162    SequenceStart { tag: Tag, len: Length },
163    /// The beginning of an encapsulated pixel data element.
164    PixelSequenceStart,
165    /// The ending delimiter of a sequence or encapsulated pixel data.
166    SequenceEnd,
167    /// The beginning of a new item in the sequence.
168    ItemStart { len: Length },
169    /// The ending delimiter of an item.
170    ItemEnd,
171    /// An element value yet to be fetched
172    LazyValue {
173        /// the header of the respective value
174        header: DataElementHeader,
175        /// the stateful decoder for fetching the bytes of the value
176        decoder: D,
177    },
178    /// An item value yet to be fetched
179    LazyItemValue {
180        /// the full length of the value, always well defined
181        len: u32,
182        /// the stateful decoder for fetching the bytes of the value
183        decoder: D,
184    },
185}
186
187impl<D> LazyDataToken<D> {
188    /// Check whether this token represents the start of a sequence
189    /// of nested data sets.
190    pub fn is_sequence_start(&self) -> bool {
191        matches!(self, LazyDataToken::SequenceStart { .. })
192    }
193
194    /// Check whether this token represents the end of a sequence
195    /// or the end of an encapsulated element.
196    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(()), // do nothing
213        }
214    }
215    /// Construct the data token into memory,
216    /// consuming the reader if necessary.
217    ///
218    /// If the token represents a lazy element value,
219    /// the inner decoder is read with string preservation.
220    pub fn into_owned(self) -> Result<DataToken> {
221        self.into_owned_with_strategy(ValueReadStrategy::Preserved)
222    }
223
224    /// Construct the data token into memory,
225    /// consuming the reader if necessary.
226    ///
227    /// If the token represents a lazy element value,
228    /// the inner decoder is read
229    /// with the given value reading strategy.
230    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                // use the stateful decoder to eagerly read the value
243                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    /// Retrieve a primitive element value from the token,
267    /// consuming the reader with the given reading strategy.
268    ///
269    /// The operation fails if the token does not represent an element value.
270    pub fn into_value_with_strategy(self, strategy: ValueReadStrategy) -> Result<PrimitiveValue> {
271        match self {
272            LazyDataToken::LazyValue {
273                header,
274                mut decoder,
275            } => {
276                // use the stateful decoder to eagerly read the value
277                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    /// Retrieve a primitive element value from the token,
294    /// consuming the reader with the default reading strategy.
295    ///
296    /// The operation fails if the token does not represent an element value.
297    pub fn into_value(self) -> Result<PrimitiveValue> {
298        self.into_value_with_strategy(ValueReadStrategy::Preserved)
299    }
300
301    /// Read the bytes of a value into the given writer,
302    /// consuming the reader.
303    ///
304    /// This operation will not interpret the value,
305    /// like in the `Bytes` value reading strategy.
306    /// It works for both data elements and non-dataset items.
307    ///
308    /// The operation fails if
309    /// the token does not represent an element or item value.
310    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    /// Convert this token into a structured representation,
331    /// for diagnostics and error reporting purposes.
332    pub fn into_repr(self) -> LazyDataTokenRepr {
333        LazyDataTokenRepr::from(self)
334    }
335
336    /// Create a structured representation of this token,
337    /// for diagnostics and error reporting purposes.
338    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/// A structured description of a lazy data token,
386/// for diagnostics and error reporting purposes.
387#[derive(Debug, Clone, PartialEq)]
388pub enum LazyDataTokenRepr {
389    /// A data header of a primitive value.
390    ElementHeader(DataElementHeader),
391    /// The beginning of a sequence element.
392    SequenceStart { tag: Tag, len: Length },
393    /// The beginning of an encapsulated pixel data element.
394    PixelSequenceStart,
395    /// The ending delimiter of a sequence or encapsulated pixel data.
396    SequenceEnd,
397    /// The beginning of a new item in the sequence.
398    ItemStart { len: Length },
399    /// The ending delimiter of an item.
400    ItemEnd,
401    /// An element value yet to be fetched
402    LazyValue {
403        /// the header of the respective value
404        header: DataElementHeader,
405    },
406    /// An item value yet to be fetched
407    LazyItemValue {
408        /// the full length of the value, always well defined
409        len: u32,
410    },
411}
412
413/// The type of delimiter: sequence or item.
414#[derive(Debug, Copy, Clone, Eq, PartialEq)]
415pub enum SeqTokenType {
416    Sequence,
417    Item,
418}
419
420/// Options for token generation
421#[derive(Debug, Copy, Clone, Default, Eq, PartialEq)]
422#[non_exhaustive]
423pub struct IntoTokensOptions {
424    /// Whether to ignore all sequence lengths in the DICOM data set,
425    /// resulting in sequences with undefined length.
426    ///
427    /// Set this to `true` when the sequence lengths in bytes might no longer be valid,
428    /// such as when changing the character set,
429    /// and as such data set sequence lengths should be replaced with undefined.
430    /// When set to `false`,
431    /// whether to retain or replace these lengths
432    /// is left at the implementation's discretion.
433    /// either be recalculated or marked as undefined.
434    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
445/// A trait for converting structured DICOM data into a stream of data tokens.
446pub trait IntoTokens {
447    /// The iterator type through which tokens are obtained.
448    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
466/// Token generator from a DICOM data element.
467pub enum DataElementTokens<I, P>
468where
469    I: IntoTokens,
470{
471    /// initial state, at the beginning of the element
472    Start(
473        // Option is used for easy taking from a &mut,
474        // should always be Some in practice
475        Option<DataElement<I, P>>,
476        IntoTokensOptions,
477    ),
478    /// the header of a plain primitive element was read
479    Header(
480        // Option is used for easy taking from a &mut,
481        // should always be Some in practice
482        Option<DataElement<I, P>>,
483    ),
484    /// reading tokens from items
485    Items(
486        FlattenTokens<
487            <dicom_core::value::C<AsItem<I>> as IntoIterator>::IntoIter,
488            ItemTokens<I::Iter>,
489        >,
490    ),
491    /// the header of encapsulated pixel data was read, will read
492    /// the offset table next
493    PixelData(
494        /// Pixel fragments
495        ///
496        /// Option is used for easy taking from a &mut,
497        /// should always be Some in practice
498        Option<dicom_core::value::C<P>>,
499        /// Frame offset table
500        OffsetTableItemTokens<dicom_core::value::C<u32>>,
501    ),
502    /// the header and offset of encapsulated pixel data was read,
503    /// fragments come next
504    PixelDataFragments(
505        FlattenTokens<
506            <dicom_core::value::C<ItemValue<P>> as IntoIterator>::IntoIter,
507            ItemValueTokens<P>,
508        >,
509    ),
510    /// no more elements
511    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                // data element header token
527
528                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                        // retrieve sequence value, begin item sequence
537                        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                                    // begin pixel sequence
566                                    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                        // return primitive value, done
589                        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                    // bypass manual state transition
597                    return Some(token);
598                } else {
599                    // sequence end token, end
600                    (Some(DataToken::SequenceEnd), DataElementTokens::End)
601                }
602            }
603            DataElementTokens::PixelData(fragments, tokens) => {
604                if let Some(token) = tokens.next() {
605                    // bypass manual state transition
606                    return Some(token);
607                }
608                // pixel data fragments next
609                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                // recursive call to ensure the retrieval of a data token
614                return self.next();
615            }
616            DataElementTokens::PixelDataFragments(tokens) => {
617                if let Some(token) = tokens.next() {
618                    // bypass manual state transition
619                    return Some(token);
620                } else {
621                    // sequence end token, end
622                    (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        //Avoid
643        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/// Flatten a sequence of elements into their respective
652/// token sequence in order.
653#[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        // ensure a token sequence
670        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        // retrieve the next token
680        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// A stream of tokens from a DICOM item.
731#[derive(Debug)]
732pub enum ItemTokens<T> {
733    /// Just started, an item header token will come next
734    Start {
735        len: Length,
736        object_tokens: Option<T>,
737    },
738    /// Will return tokens from the inner object, then an end of item token
739    /// when it ends
740    Object { object_tokens: T },
741    /// Just ended, no more tokens
742    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/// A newtype for interpreting the given data as an item.
797/// When converting a value of this type into tokens, the inner value's tokens
798/// will be surrounded by an item start and an item delimiter.
799#[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/// A newtype for wrapping a piece of raw data into an item.
824/// When converting a value of this type into tokens, the algorithm
825/// will create an item start with an explicit length, followed by
826/// an item value token, then an item delimiter.
827#[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    /// Just started, an item header token will come next. Takes a bool to configure if inner
848    /// lengths can be trusted to be valid
849    Start(Option<P>, bool),
850    /// Will return a token of the value
851    Value(P),
852    /// Will return an end of item token
853    Done,
854    /// Just ended, no more tokens
855    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/// A newtype for wrapping a sequence of `u32`s into an offset table item.
905/// When converting a value of this type into tokens,
906/// the algorithm will create an item start with an explicit length,
907/// followed by an item value token,
908/// then an item delimiter.
909#[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        //There are no sequences here that might need to be invalidated
924        OffsetTableItemTokens::new(self.0)
925    }
926}
927
928#[derive(Debug)]
929pub enum OffsetTableItemTokens<P> {
930    /// Just started, an item header token will come next
931    Start(Option<P>),
932    /// Will return a token of the actual offset table
933    Value(P),
934    /// Will return an end of item token
935    Done,
936    /// Just ended, no more tokens
937    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    /// A simple object representing a DICOM data set,
1002    /// used merely for testing purposes.
1003    #[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}