dicom_core/
header.rs

1//! This modules contains an assortment of types required for interpreting DICOM data elements.
2//! It comprises a variety of basic data types, such as the DICOM attribute tag, the
3//! element header, and element composite types.
4
5use crate::value::{
6    CastValueError, ConvertValueError, DataSetSequence, DicomDate, DicomDateTime, DicomTime,
7    InMemFragment, PrimitiveValue, Value, C,
8};
9use num_traits::NumCast;
10use snafu::{ensure, Backtrace, Snafu};
11use std::borrow::Cow;
12use std::cmp::Ordering;
13use std::fmt;
14use std::str::{from_utf8, FromStr};
15
16/// Error type for issues constructing a sequence item header.
17#[derive(Debug, Snafu)]
18#[non_exhaustive]
19pub enum SequenceItemHeaderError {
20    /// Unexpected header tag.
21    /// Only Item (0xFFFE, 0xE000),
22    /// Item Delimiter (0xFFFE, 0xE00D),
23    /// or Sequence Delimiter (0xFFFE, 0xE0DD)
24    /// are admitted.
25    #[snafu(display("Unexpected tag {}", tag))]
26    UnexpectedTag { tag: Tag, backtrace: Backtrace },
27    /// Unexpected delimiter value length.
28    /// Must be zero for item delimiters.
29    #[snafu(display("Unexpected delimiter length {}", len))]
30    UnexpectedDelimiterLength { len: Length, backtrace: Backtrace },
31}
32
33type Result<T, E = SequenceItemHeaderError> = std::result::Result<T, E>;
34
35/// Trait for any DICOM entity (element or item) which may have a length.
36pub trait HasLength {
37    /// Retrieve the value data's length as specified by the data element or
38    /// item, in bytes.
39    ///
40    /// It is named `length` to make it distinct from the conventional method
41    /// signature `len(&self) -> usize` for the number of elements of a
42    /// collection.
43    ///
44    /// According to the standard, the concrete value size may be undefined,
45    /// which can be the case for sequence elements or specific primitive
46    /// values.
47    fn length(&self) -> Length;
48
49    /// Check whether the value is empty (0 length).
50    fn is_empty(&self) -> bool {
51        self.length() == Length(0)
52    }
53}
54
55/// A trait for a data type containing a DICOM header.
56#[allow(clippy::len_without_is_empty)]
57pub trait Header: HasLength {
58    /// Retrieve the element's tag as a `(group, element)` tuple.
59    fn tag(&self) -> Tag;
60
61    /// Check whether this is the header of an item.
62    fn is_item(&self) -> bool {
63        self.tag() == Tag(0xFFFE, 0xE000)
64    }
65
66    /// Check whether this is the header of an item delimiter.
67    fn is_item_delimiter(&self) -> bool {
68        self.tag() == Tag(0xFFFE, 0xE00D)
69    }
70
71    /// Check whether this is the header of a sequence delimiter.
72    fn is_sequence_delimiter(&self) -> bool {
73        self.tag() == Tag(0xFFFE, 0xE0DD)
74    }
75
76    /// Check whether this is the header of an encapsulated pixel data.
77    fn is_encapsulated_pixeldata(&self) -> bool {
78        self.tag() == Tag(0x7FE0, 0x0010) && self.length().is_undefined()
79    }
80}
81
82/// Stub type representing a non-existing DICOM object.
83///
84/// This type implements [`HasLength`], but cannot be instantiated.
85/// This makes it so that [`Value<EmptyObject>`] is sure to be either
86/// a primitive value,
87/// a pixel data fragment sequence,
88/// or a sequence with no items.
89#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq, Ord, PartialOrd)]
90pub enum EmptyObject {}
91
92impl HasLength for EmptyObject {
93    fn length(&self) -> Length {
94        unreachable!()
95    }
96}
97
98/// A data type that represents and owns a DICOM data element.
99///
100/// This type is capable of representing any data element fully in memory,
101/// whether it be a primitive value,
102/// a nested data set (where `I` is the object type for data set items),
103/// or an encapsulated pixel data sequence (each item of type `P`).
104/// The type parameter `I` should usually implement [`HasLength`],
105/// whereas `P` should usually implement `AsRef<[u8]>`.
106#[derive(Debug, PartialEq, Clone)]
107pub struct DataElement<I = EmptyObject, P = InMemFragment> {
108    header: DataElementHeader,
109    value: Value<I, P>,
110}
111
112/// A data type that represents and owns a DICOM data element
113/// containing a primitive value.
114#[derive(Debug, PartialEq, Clone)]
115pub struct PrimitiveDataElement {
116    header: DataElementHeader,
117    value: PrimitiveValue,
118}
119
120impl PrimitiveDataElement {
121    /// Main constructor for a primitive data element.
122    pub fn new(header: DataElementHeader, value: PrimitiveValue) -> Self {
123        PrimitiveDataElement { header, value }
124    }
125}
126
127impl<I, P> From<PrimitiveDataElement> for DataElement<I, P> {
128    fn from(o: PrimitiveDataElement) -> Self {
129        DataElement {
130            header: o.header,
131            value: o.value.into(),
132        }
133    }
134}
135
136/// A data type that represents a DICOM data element with
137/// a borrowed value.
138#[derive(Debug, PartialEq, Clone)]
139pub struct DataElementRef<'v, I: 'v, P: 'v> {
140    header: DataElementHeader,
141    value: &'v Value<I, P>,
142}
143
144/// A data type that represents a DICOM data element with
145/// a borrowed primitive value.
146#[derive(Debug, PartialEq, Clone)]
147pub struct PrimitiveDataElementRef<'v> {
148    header: DataElementHeader,
149    value: &'v PrimitiveValue,
150}
151
152impl<'a> PrimitiveDataElementRef<'a> {
153    /// Main constructor for a primitive data element reference.
154    pub fn new(header: DataElementHeader, value: &'a PrimitiveValue) -> Self {
155        PrimitiveDataElementRef { header, value }
156    }
157}
158impl<I, P> HasLength for DataElement<I, P> {
159    #[inline]
160    fn length(&self) -> Length {
161        self.header.length()
162    }
163}
164
165impl<I, P> Header for DataElement<I, P> {
166    #[inline]
167    fn tag(&self) -> Tag {
168        self.header.tag()
169    }
170}
171
172impl<I, P> HasLength for &DataElement<I, P> {
173    #[inline]
174    fn length(&self) -> Length {
175        (**self).length()
176    }
177}
178
179impl<'a, I, P> Header for &'a DataElement<I, P> {
180    #[inline]
181    fn tag(&self) -> Tag {
182        (**self).tag()
183    }
184}
185
186impl<'v, I, P> HasLength for DataElementRef<'v, I, P> {
187    #[inline]
188    fn length(&self) -> Length {
189        self.header.length()
190    }
191}
192
193impl<'v, I, P> Header for DataElementRef<'v, I, P> {
194    #[inline]
195    fn tag(&self) -> Tag {
196        self.header.tag()
197    }
198}
199
200impl<I, P> DataElement<I, P> {
201    /// Create an empty data element.
202    pub fn empty(tag: Tag, vr: VR) -> Self {
203        DataElement {
204            header: DataElementHeader {
205                tag,
206                vr,
207                len: Length(0),
208            },
209            value: if vr == VR::SQ {
210                DataSetSequence::empty().into()
211            } else {
212                PrimitiveValue::Empty.into()
213            },
214        }
215    }
216
217    /// Retrieve the element header.
218    pub fn header(&self) -> &DataElementHeader {
219        &self.header
220    }
221
222    /// Retrieve the value representation, which may be unknown or not
223    /// applicable.
224    pub fn vr(&self) -> VR {
225        self.header.vr()
226    }
227
228    /// Retrieve the data value.
229    pub fn value(&self) -> &Value<I, P> {
230        &self.value
231    }
232
233    /// Move the data value out of the element, discarding the rest. If the
234    /// value is a sequence, its lifetime may still be bound to its original
235    /// source.
236    pub fn into_value(self) -> Value<I, P> {
237        self.value
238    }
239
240    /// Split the constituent parts of this element into a tuple.
241    /// If the value is a sequence,
242    /// its lifetime may still be bound to the original source.
243    pub fn into_parts(self) -> (DataElementHeader, Value<I, P>) {
244        (self.header, self.value)
245    }
246
247    /// Obtain a temporary mutable reference to the value,
248    /// so that mutations can be applied within.
249    ///
250    /// Once updated, the header is automatically updated
251    /// based on this set of rules:
252    ///
253    /// - if the value is a data set sequence,
254    ///   the VR is set to `SQ` and the length is reset to undefined;
255    /// - if the value is a pixel data fragment sequence,
256    ///   the VR is set to `OB` and the lenght is reset to undefined;
257    /// - if the value is primitive,
258    ///   the length is recalculated, leaving the VR as is.
259    ///
260    /// If these rules do not result in a valid element,
261    /// consider reconstructing the data element instead.
262    pub fn update_value(&mut self, mut f: impl FnMut(&mut Value<I, P>)) {
263        f(&mut self.value);
264        match &mut self.value {
265            Value::Primitive(v) => {
266                let byte_len = v.calculate_byte_len();
267                self.header.len = Length(byte_len as u32);
268            }
269            Value::Sequence(_) => {
270                self.header.vr = VR::SQ;
271                self.header.len = Length::UNDEFINED;
272            }
273            Value::PixelSequence(_) => {
274                self.header.vr = VR::OB;
275                self.header.len = Length::UNDEFINED;
276            }
277        }
278    }
279}
280
281impl<I, P> DataElement<I, P>
282where
283    I: HasLength,
284{
285    /// Create a data element from the given parts,
286    /// where the length is inferred from the value's byte length.
287    ///
288    /// If the value is textual,
289    /// the byte length of that value encoded in UTF-8 is assumed.
290    /// If you already have a length in this context,
291    /// prefer calling `new_with_len` instead.
292    ///
293    /// This method will not check whether the value representation is
294    /// compatible with the given value.
295    pub fn new<T>(tag: Tag, vr: VR, value: T) -> Self
296    where
297        T: Into<Value<I, P>>,
298    {
299        let value = value.into();
300        DataElement {
301            header: DataElementHeader {
302                tag,
303                vr,
304                len: value.length(),
305            },
306            value,
307        }
308    }
309
310    /// Create a primitive data element from the given parts.
311    ///
312    /// This method will not check
313    /// whether the length accurately represents the given value's byte length,
314    /// nor whether the value representation is compatible with the value.
315    pub fn new_with_len<T>(tag: Tag, vr: VR, length: Length, value: T) -> Self
316    where
317        T: Into<Value<I, P>>,
318    {
319        let value = value.into();
320        DataElement {
321            header: DataElementHeader {
322                tag,
323                vr,
324                len: length,
325            },
326            value,
327        }
328    }
329
330    /// Retrieve the element's value as a single clean string,
331    /// with no trailing whitespace.
332    ///
333    /// Returns an error if the value is not primitive.
334    pub fn to_str(&self) -> Result<Cow<str>, ConvertValueError> {
335        self.value.to_str()
336    }
337
338    /// Retrieve the element's value as a single raw string,
339    /// with trailing whitespace kept.
340    ///
341    /// Returns an error if the value is not primitive.
342    pub fn to_raw_str(&self) -> Result<Cow<str>, ConvertValueError> {
343        self.value.to_raw_str()
344    }
345
346    /// Convert the full primitive value into raw bytes.
347    ///
348    /// String values already encoded with the `Str` and `Strs` variants
349    /// are provided in UTF-8.
350    ///
351    /// Returns an error if the value is not primitive.
352    pub fn to_bytes(&self) -> Result<Cow<[u8]>, ConvertValueError> {
353        self.value.to_bytes()
354    }
355
356    /// Convert the full value of the data element into a sequence of strings.
357    ///
358    /// If the value is a primitive, it will be converted into
359    /// a vector of strings as described in [`PrimitiveValue::to_multi_str`].
360    ///
361    /// Returns an error if the value is not primitive.
362    ///
363    /// [`PrimitiveValue::to_multi_str`]: ../enum.PrimitiveValue.html#to_multi_str
364    pub fn to_multi_str(&self) -> Result<Cow<[String]>, CastValueError> {
365        self.value().to_multi_str()
366    }
367
368    /// Retrieve and convert the value of the data element into an integer.
369    ///
370    /// If the value is a primitive,
371    /// it will be converted into an integer
372    /// as described in [`PrimitiveValue::to_int`].
373    ///
374    /// Returns an error if the value is not primitive.
375    ///
376    /// [`PrimitiveValue::to_int`]: ../enum.PrimitiveValue.html#to_int
377    pub fn to_int<T>(&self) -> Result<T, ConvertValueError>
378    where
379        T: Clone,
380        T: NumCast,
381        T: FromStr<Err = std::num::ParseIntError>,
382    {
383        self.value().to_int()
384    }
385
386    /// Retrieve and convert the value of the data element
387    /// into a sequence of integers.
388    ///
389    /// If the value is a primitive, it will be converted into
390    /// a vector of integers as described in [PrimitiveValue::to_multi_int].
391    ///
392    /// [PrimitiveValue::to_multi_int]: ../enum.PrimitiveValue.html#to_multi_int
393    pub fn to_multi_int<T>(&self) -> Result<Vec<T>, ConvertValueError>
394    where
395        T: Clone,
396        T: NumCast,
397        T: FromStr<Err = std::num::ParseIntError>,
398    {
399        self.value().to_multi_int()
400    }
401
402    /// Retrieve and convert the value of the data element
403    /// into a single-precision floating point number.
404    ///
405    /// If the value is a primitive, it will be converted into
406    /// a number as described in [`PrimitiveValue::to_float32`].
407    ///
408    /// Returns an error if the value is not primitive.
409    ///
410    /// [`PrimitiveValue::to_float32`]: ../enum.PrimitiveValue.html#to_float32
411    pub fn to_float32(&self) -> Result<f32, ConvertValueError> {
412        self.value().to_float32()
413    }
414
415    /// Retrieve and convert the value of the data element
416    /// into a sequence of single-precision floating point numbers.
417    ///
418    /// If the value is a primitive, it will be converted into
419    /// a vector of numbers as described in [`PrimitiveValue::to_multi_float32`].
420    ///
421    /// Returns an error if the value is not primitive.
422    ///
423    /// [`PrimitiveValue::to_multi_float32`]: ../enum.PrimitiveValue.html#to_multi_float32
424    pub fn to_multi_float32(&self) -> Result<Vec<f32>, ConvertValueError> {
425        self.value().to_multi_float32()
426    }
427
428    /// Retrieve and convert the value of the data element
429    /// into a double-precision floating point number.
430    ///
431    /// If the value is a primitive, it will be converted into
432    /// a number as described in [`PrimitiveValue::to_float64`].
433    ///
434    /// Returns an error if the value is not primitive.
435    ///
436    /// [`PrimitiveValue::to_float64`]: ../enum.PrimitiveValue.html#to_float64
437    pub fn to_float64(&self) -> Result<f64, ConvertValueError> {
438        self.value().to_float64()
439    }
440
441    /// Retrieve and convert the value of the data element
442    /// into a sequence of double-precision floating point numbers.
443    ///
444    /// If the value is a primitive, it will be converted into
445    /// a vector of numbers as described in [`PrimitiveValue::to_multi_float64`].
446    ///
447    /// Returns an error if the value is not primitive.
448    ///
449    /// [`PrimitiveValue::to_multi_float64`]: ../enum.PrimitiveValue.html#to_multi_float64
450    pub fn to_multi_float64(&self) -> Result<Vec<f64>, ConvertValueError> {
451        self.value().to_multi_float64()
452    }
453
454    /// Retrieve and convert the primitive value into a date.
455    ///
456    /// If the value is a primitive, it will be converted into
457    /// a `DicomDate` as described in [`PrimitiveValue::to_date`].
458    ///
459    /// Returns an error if the value is not primitive.
460    ///
461    pub fn to_date(&self) -> Result<DicomDate, ConvertValueError> {
462        self.value().to_date()
463    }
464
465    /// Retrieve and convert the primitive value into a sequence of dates.
466    ///
467    /// If the value is a primitive, it will be converted into
468    /// a vector of `DicomDate` as described in [`PrimitiveValue::to_multi_date`].
469    ///
470    /// Returns an error if the value is not primitive.
471    ///
472    pub fn to_multi_date(&self) -> Result<Vec<DicomDate>, ConvertValueError> {
473        self.value().to_multi_date()
474    }
475
476    /// Retrieve and convert the primitive value into a time.
477    ///
478    /// If the value is a primitive, it will be converted into
479    /// a `DicomTime` as described in [`PrimitiveValue::to_time`].
480    ///
481    /// Returns an error if the value is not primitive.
482    ///
483    pub fn to_time(&self) -> Result<DicomTime, ConvertValueError> {
484        self.value().to_time()
485    }
486
487    /// Retrieve and convert the primitive value into a sequence of times.
488    ///
489    /// If the value is a primitive, it will be converted into
490    /// a vector of `DicomTime` as described in [`PrimitiveValue::to_multi_time`].
491    ///
492    /// Returns an error if the value is not primitive.
493    ///
494    pub fn to_multi_time(&self) -> Result<Vec<DicomTime>, ConvertValueError> {
495        self.value().to_multi_time()
496    }
497
498    /// Retrieve and convert the primitive value into a date-time.
499    ///
500    /// If the value is a primitive, it will be converted into
501    /// a `DicomDateTime` as described in [`PrimitiveValue::to_datetime`].
502    ///
503    /// Returns an error if the value is not primitive.
504    ///
505    pub fn to_datetime(&self) -> Result<DicomDateTime, ConvertValueError> {
506        self.value().to_datetime()
507    }
508
509    /// Retrieve and convert the primitive value into a sequence of date-times.
510    ///
511    /// If the value is a primitive, it will be converted into
512    /// a vector of `DicomDateTime` as described in [`PrimitiveValue::to_multi_datetime`].
513    ///
514    /// Returns an error if the value is not primitive.
515    ///
516    pub fn to_multi_datetime(&self) -> Result<Vec<DicomDateTime>, ConvertValueError> {
517        self.value().to_multi_datetime()
518    }
519
520    /// Retrieve the items stored in a sequence value.
521    ///
522    /// Returns `None` if the underlying value is not a data set sequence.
523    pub fn items(&self) -> Option<&[I]> {
524        self.value().items()
525    }
526
527    /// Gets a mutable reference to the items of a sequence value.
528    ///
529    /// The header's recorded length is automatically reset to undefined,
530    /// in order to prevent inconsistencies.
531    ///
532    /// Returns `None` if the underlying value is not a data set sequence.
533    pub fn items_mut(&mut self) -> Option<&mut C<I>> {
534        self.header.len = Length::UNDEFINED;
535        self.value.items_mut()
536    }
537
538    /// Retrieve the fragments stored in a pixel data sequence value.
539    ///
540    /// Returns `None` if the value is not a pixel data sequence.
541    pub fn fragments(&self) -> Option<&[P]> {
542        self.value().fragments()
543    }
544
545    /// Obtain a mutable reference to the fragments
546    /// stored in a pixel data sequence value.
547    ///
548    /// The header's recorded length is automatically reset to undefined,
549    /// in order to prevent inconsistencies.
550    ///
551    /// Returns `None` if the value is not a pixel data sequence.
552    pub fn fragments_mut(&mut self) -> Option<&mut C<P>> {
553        self.header.len = Length::UNDEFINED;
554        self.value.fragments_mut()
555    }
556
557    /// Obtain a reference to the encapsulated pixel data's basic offset table.
558    ///
559    /// Returns `None` if the underlying value is not a pixel data sequence.
560    pub fn offset_table(&self) -> Option<&[u32]> {
561        self.value().offset_table()
562    }
563}
564
565impl<'v, I, P> DataElementRef<'v, I, P>
566where
567    I: HasLength,
568{
569    /// Create a data element from the given parts. This method will not check
570    /// whether the value representation is compatible with the value. Caution
571    /// is advised.
572    pub fn new(tag: Tag, vr: VR, value: &'v Value<I, P>) -> Self {
573        DataElementRef {
574            header: DataElementHeader {
575                tag,
576                vr,
577                len: value.length(),
578            },
579            value,
580        }
581    }
582
583    /// Retrieves the element's value representation, which can be unknown.
584    pub fn vr(&self) -> VR {
585        self.header.vr()
586    }
587
588    /// Retrieves the DICOM value.
589    pub fn value(&self) -> &Value<I, P> {
590        self.value
591    }
592}
593
594/// Macro for implementing getters to single and multi-values,
595/// by delegating to `Value`.
596///
597/// Should be placed inside `DataElement`'s impl block.
598macro_rules! impl_primitive_getters {
599    ($name_single: ident, $name_multi: ident, $variant: ident, $ret: ty) => {
600        /// Get a single value of the requested type.
601        ///
602        /// If it contains multiple values,
603        /// only the first one is returned.
604        /// An error is returned if the variant is not compatible.
605        pub fn $name_single(&self) -> Result<$ret, CastValueError> {
606            self.value().$name_single()
607        }
608
609        /// Get a sequence of values of the requested type without copying.
610        ///
611        /// An error is returned if the variant is not compatible.
612        pub fn $name_multi(&self) -> Result<&[$ret], CastValueError> {
613            self.value().$name_multi()
614        }
615    };
616}
617
618impl<I, P> DataElement<I, P> {
619    /// Get a single string value.
620    ///
621    /// If it contains multiple strings,
622    /// only the first one is returned.
623    ///
624    /// An error is returned if the variant is not compatible.
625    ///
626    /// To enable conversions of other variants to a textual representation,
627    /// see [`to_str()`] instead.
628    ///
629    /// [`to_str()`]: #method.to_str
630    pub fn string(&self) -> Result<&str, CastValueError> {
631        self.value().string()
632    }
633
634    /// Get the inner sequence of string values
635    /// if the variant is either `Str` or `Strs`.
636    ///
637    /// An error is returned if the variant is not compatible.
638    ///
639    /// To enable conversions of other variants to a textual representation,
640    /// see [`to_str()`] instead.
641    ///
642    /// [`to_str()`]: #method.to_str
643    pub fn strings(&self) -> Result<&[String], CastValueError> {
644        self.value().strings()
645    }
646
647    impl_primitive_getters!(date, dates, Date, DicomDate);
648    impl_primitive_getters!(time, times, Time, DicomTime);
649    impl_primitive_getters!(datetime, datetimes, DateTime, DicomDateTime);
650    impl_primitive_getters!(uint8, uint8_slice, U8, u8);
651    impl_primitive_getters!(uint16, uint16_slice, U16, u16);
652    impl_primitive_getters!(int16, int16_slice, I16, i16);
653    impl_primitive_getters!(uint32, uint32_slice, U32, u32);
654    impl_primitive_getters!(int32, int32_slice, I32, i32);
655    impl_primitive_getters!(int64, int64_slice, I64, i64);
656    impl_primitive_getters!(uint64, uint64_slice, U64, u64);
657    impl_primitive_getters!(float32, float32_slice, F32, f32);
658    impl_primitive_getters!(float64, float64_slice, F64, f64);
659}
660
661/// A data structure for a data element header, containing
662/// a tag, value representation and specified length.
663#[derive(Debug, PartialEq, Clone, Copy)]
664pub struct DataElementHeader {
665    /// DICOM tag
666    pub tag: Tag,
667    /// Value Representation
668    pub vr: VR,
669    /// Element length
670    pub len: Length,
671}
672
673impl HasLength for DataElementHeader {
674    #[inline]
675    fn length(&self) -> Length {
676        self.len
677    }
678}
679
680impl Header for DataElementHeader {
681    #[inline]
682    fn tag(&self) -> Tag {
683        self.tag
684    }
685}
686
687impl DataElementHeader {
688    /// Create a new data element header with the given properties.
689    /// This is just a trivial constructor.
690    #[inline]
691    pub fn new<T: Into<Tag>>(tag: T, vr: VR, len: Length) -> DataElementHeader {
692        DataElementHeader {
693            tag: tag.into(),
694            vr,
695            len,
696        }
697    }
698
699    /// Retrieve the element's value representation, which can be unknown.
700    #[inline]
701    pub fn vr(&self) -> VR {
702        self.vr
703    }
704
705    /// Check whether the header suggests the value to be a sequence value:
706    /// if the value representation is SQ or the length is undefined.
707    #[inline]
708    pub fn is_non_primitive(&self) -> bool {
709        self.vr == VR::SQ || self.length().is_undefined()
710    }
711}
712
713impl From<SequenceItemHeader> for DataElementHeader {
714    fn from(value: SequenceItemHeader) -> DataElementHeader {
715        DataElementHeader {
716            tag: value.tag(),
717            vr: VR::UN,
718            len: value.length(),
719        }
720    }
721}
722
723/// Data type for describing a sequence item data element.
724/// If the element represents an item, it will also contain
725/// the specified length.
726#[derive(Debug, PartialEq, Clone, Copy)]
727pub enum SequenceItemHeader {
728    /// The cursor contains an item.
729    Item {
730        /// the length of the item in bytes (can be 0xFFFFFFFF if undefined)
731        len: Length,
732    },
733    /// The cursor read an item delimiter.
734    /// The element ends here and should not be read any further.
735    ItemDelimiter,
736    /// The cursor read a sequence delimiter.
737    /// The element ends here and should not be read any further.
738    SequenceDelimiter,
739}
740
741impl SequenceItemHeader {
742    /// Create a sequence item header using the element's raw properties.
743    /// An error can be raised if the given properties do not relate to a
744    /// sequence item, a sequence item delimiter or a sequence delimiter.
745    pub fn new<T: Into<Tag>>(tag: T, len: Length) -> Result<SequenceItemHeader> {
746        match tag.into() {
747            Tag(0xFFFE, 0xE000) => {
748                // item
749                Ok(SequenceItemHeader::Item { len })
750            }
751            Tag(0xFFFE, 0xE00D) => {
752                // item delimiter
753                // delimiters should not have a positive length
754                if len != Length(0) {
755                    UnexpectedDelimiterLengthSnafu { len }.fail()
756                } else {
757                    Ok(SequenceItemHeader::ItemDelimiter)
758                }
759            }
760            Tag(0xFFFE, 0xE0DD) => {
761                // sequence delimiter
762                Ok(SequenceItemHeader::SequenceDelimiter)
763            }
764            tag => UnexpectedTagSnafu { tag }.fail(),
765        }
766    }
767}
768
769impl HasLength for SequenceItemHeader {
770    #[inline]
771    fn length(&self) -> Length {
772        match *self {
773            SequenceItemHeader::Item { len } => len,
774            SequenceItemHeader::ItemDelimiter | SequenceItemHeader::SequenceDelimiter => Length(0),
775        }
776    }
777}
778impl Header for SequenceItemHeader {
779    #[inline]
780    fn tag(&self) -> Tag {
781        match *self {
782            SequenceItemHeader::Item { .. } => Tag(0xFFFE, 0xE000),
783            SequenceItemHeader::ItemDelimiter => Tag(0xFFFE, 0xE00D),
784            SequenceItemHeader::SequenceDelimiter => Tag(0xFFFE, 0xE0DD),
785        }
786    }
787}
788
789/// An enum type for a DICOM value representation.
790#[derive(Debug, Eq, PartialEq, Hash, Copy, Clone, Ord, PartialOrd)]
791pub enum VR {
792    /// Application Entity
793    AE,
794    /// Age String
795    AS,
796    /// Attribute Tag
797    AT,
798    /// Code String
799    CS,
800    /// Date
801    DA,
802    /// Decimal String
803    DS,
804    /// Date Time
805    DT,
806    /// Floating Point Single
807    FL,
808    /// Floating Point Double
809    FD,
810    /// Integer String
811    IS,
812    /// Long String
813    LO,
814    /// Long Text
815    LT,
816    /// Other Byte
817    OB,
818    /// Other Double
819    OD,
820    /// Other Float
821    OF,
822    /// Other Long
823    OL,
824    /// Other Very Long
825    OV,
826    /// Other Word
827    OW,
828    /// Person Name
829    PN,
830    /// Short String
831    SH,
832    /// Signed Long
833    SL,
834    /// Sequence of Items
835    SQ,
836    /// Signed Short
837    SS,
838    /// Short Text
839    ST,
840    /// Signed Very Long
841    SV,
842    /// Time
843    TM,
844    /// Unlimited Characters
845    UC,
846    /// Unique Identifier (UID)
847    UI,
848    /// Unsigned Long
849    UL,
850    /// Unknown
851    UN,
852    /// Universal Resource Identifier or Universal Resource Locator (URI/URL)
853    UR,
854    /// Unsigned Short
855    US,
856    /// Unlimited Text
857    UT,
858    /// Unsigned Very Long
859    UV,
860}
861
862impl VR {
863    /// Obtain the value representation corresponding to the given two bytes.
864    /// Each byte should represent an alphabetic character in upper case.
865    pub fn from_binary(chars: [u8; 2]) -> Option<Self> {
866        from_utf8(chars.as_ref())
867            .ok()
868            .and_then(|s| VR::from_str(s).ok())
869    }
870
871    /// Retrieve a string representation of this VR.
872    pub fn to_string(self) -> &'static str {
873        use VR::*;
874        match self {
875            AE => "AE",
876            AS => "AS",
877            AT => "AT",
878            CS => "CS",
879            DA => "DA",
880            DS => "DS",
881            DT => "DT",
882            FL => "FL",
883            FD => "FD",
884            IS => "IS",
885            LO => "LO",
886            LT => "LT",
887            OB => "OB",
888            OD => "OD",
889            OF => "OF",
890            OL => "OL",
891            OV => "OV",
892            OW => "OW",
893            PN => "PN",
894            SH => "SH",
895            SL => "SL",
896            SQ => "SQ",
897            SS => "SS",
898            ST => "ST",
899            SV => "SV",
900            TM => "TM",
901            UC => "UC",
902            UI => "UI",
903            UL => "UL",
904            UN => "UN",
905            UR => "UR",
906            US => "US",
907            UT => "UT",
908            UV => "UV",
909        }
910    }
911
912    /// Retrieve a copy of this VR's byte representation.
913    /// The function returns two alphabetic characters in upper case.
914    pub fn to_bytes(self) -> [u8; 2] {
915        let bytes = self.to_string().as_bytes();
916        [bytes[0], bytes[1]]
917    }
918}
919
920/// Obtain the value representation corresponding to the given string.
921/// The string should hold exactly two UTF-8 encoded alphabetic characters
922/// in upper case, otherwise no match is made.
923impl FromStr for VR {
924    type Err = &'static str;
925
926    fn from_str(string: &str) -> std::result::Result<Self, Self::Err> {
927        use VR::*;
928        match string {
929            "AE" => Ok(AE),
930            "AS" => Ok(AS),
931            "AT" => Ok(AT),
932            "CS" => Ok(CS),
933            "DA" => Ok(DA),
934            "DS" => Ok(DS),
935            "DT" => Ok(DT),
936            "FL" => Ok(FL),
937            "FD" => Ok(FD),
938            "IS" => Ok(IS),
939            "LO" => Ok(LO),
940            "LT" => Ok(LT),
941            "OB" => Ok(OB),
942            "OD" => Ok(OD),
943            "OF" => Ok(OF),
944            "OL" => Ok(OL),
945            "OV" => Ok(OV),
946            "OW" => Ok(OW),
947            "PN" => Ok(PN),
948            "SH" => Ok(SH),
949            "SL" => Ok(SL),
950            "SQ" => Ok(SQ),
951            "SS" => Ok(SS),
952            "ST" => Ok(ST),
953            "SV" => Ok(SV),
954            "TM" => Ok(TM),
955            "UC" => Ok(UC),
956            "UI" => Ok(UI),
957            "UL" => Ok(UL),
958            "UN" => Ok(UN),
959            "UR" => Ok(UR),
960            "US" => Ok(US),
961            "UT" => Ok(UT),
962            "UV" => Ok(UV),
963            _ => Err("no such value representation"),
964        }
965    }
966}
967
968impl fmt::Display for VR {
969    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
970        f.write_str(VR::to_string(*self))
971    }
972}
973
974/// Idiomatic alias for a tag's group number.
975pub type GroupNumber = u16;
976/// Idiomatic alias for a tag's element number.
977pub type ElementNumber = u16;
978
979/// The data type for DICOM data element tags.
980///
981/// Tags are composed by a (group, element) pair of 16-bit unsigned integers.
982/// Aside from writing a struct expression,
983/// a `Tag` may also be built by converting a `(u16, u16)` or a `[u16; 2]`.
984///
985/// In its text form,
986/// DICOM tags are printed by [`Display`][display] in the form `(GGGG,EEEE)`,
987/// where the group and element parts are in uppercase hexadecimal.
988/// Moreover, its [`FromStr`] implementation
989/// support converting strings in the following text formats into DICOM tags:
990///
991/// - `(GGGG,EEEE)`
992/// - `GGGG,EEEE`
993/// - `GGGGEEEE`
994///
995/// [display]: std::fmt::Display
996///
997/// # Example
998///
999/// ```
1000/// # use dicom_core::Tag;
1001/// let tag: Tag = "(0010,1005)".parse()?;
1002/// assert_eq!(tag, Tag(0x0010, 0x1005));
1003/// # Ok::<_, dicom_core::header::ParseTagError>(())
1004/// ```
1005#[derive(PartialEq, Eq, Hash, PartialOrd, Ord, Clone, Copy)]
1006pub struct Tag(pub GroupNumber, pub ElementNumber);
1007
1008impl Tag {
1009    /// Getter for the tag's group value.
1010    #[inline]
1011    pub fn group(self) -> GroupNumber {
1012        self.0
1013    }
1014
1015    /// Getter for the tag's element value.
1016    #[inline]
1017    pub fn element(self) -> ElementNumber {
1018        self.1
1019    }
1020}
1021
1022impl fmt::Debug for Tag {
1023    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1024        write!(f, "Tag({:#06X?}, {:#06X?})", self.0, self.1)
1025    }
1026}
1027
1028impl fmt::Display for Tag {
1029    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1030        write!(f, "({:04X},{:04X})", self.0, self.1)
1031    }
1032}
1033
1034impl From<(u16, u16)> for Tag {
1035    #[inline]
1036    fn from(value: (u16, u16)) -> Tag {
1037        Tag(value.0, value.1)
1038    }
1039}
1040
1041impl From<[u16; 2]> for Tag {
1042    #[inline]
1043    fn from(value: [u16; 2]) -> Tag {
1044        Tag(value[0], value[1])
1045    }
1046}
1047
1048/// Could not parse DICOM tag
1049#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq, Snafu)]
1050pub enum ParseTagError {
1051    /// expected tag start '('
1052    Start,
1053    /// expected tag part separator ','
1054    Separator,
1055    /// expected tag end ')'
1056    End,
1057    /// unexpected length
1058    Length,
1059    /// Illegal character for hexadecimal number
1060    Number,
1061}
1062
1063/// This parser implementation for DICOM tags
1064/// accepts strictly one of the following formats:
1065/// - `ggggeeee`
1066/// - or `gggg,eeee`
1067/// - or `(gggg,eeee)`
1068///
1069/// where `gggg` and `eeee` are the characters representing
1070/// the group part an the element part in hexadecimal,
1071/// with four characters each.
1072/// Whitespace is not excluded automatically,
1073/// and may need to be removed before-parse
1074/// depending on the context.
1075/// Lowercase and uppercase characters are allowed.
1076impl FromStr for Tag {
1077    type Err = ParseTagError;
1078
1079    fn from_str(s: &str) -> Result<Self, Self::Err> {
1080        match s.len() {
1081            11 => {
1082                // (gggg,eeee)
1083                ensure!(s.starts_with('('), StartSnafu);
1084
1085                let (num_g, rest) = parse_tag_part(&s[1..])?;
1086
1087                ensure!(rest.starts_with(','), SeparatorSnafu);
1088
1089                let (num_e, rest) = parse_tag_part(&rest[1..])?;
1090
1091                ensure!(rest == ")", EndSnafu);
1092
1093                Ok(Tag(num_g, num_e))
1094            }
1095            9 => {
1096                // gggg,eeee
1097                let (num_g, rest) = parse_tag_part(s)?;
1098
1099                ensure!(rest.starts_with(','), SeparatorSnafu);
1100
1101                let (num_e, _) = parse_tag_part(&rest[1..])?;
1102
1103                Ok(Tag(num_g, num_e))
1104            }
1105            8 => {
1106                // ggggeeee
1107                let (g, e) = s.split_at(4);
1108                let (num_g, _) = parse_tag_part(g)?;
1109                let (num_e, _) = parse_tag_part(e)?;
1110
1111                Ok(Tag(num_g, num_e))
1112            }
1113            _ => Err(ParseTagError::Length),
1114        }
1115    }
1116}
1117
1118fn parse_tag_part(s: &str) -> Result<(u16, &str), ParseTagError> {
1119    ensure!(s.is_char_boundary(4), NumberSnafu);
1120
1121    let (num, rest) = s.split_at(4);
1122    ensure!(num.chars().all(|c| c.is_ascii_hexdigit()), NumberSnafu);
1123
1124    let num = u16::from_str_radix(num, 16).expect("failed to parse tag part");
1125    Ok((num, rest))
1126}
1127
1128/// A type for representing data set content length, in bytes.
1129/// An internal value of `0xFFFF_FFFF` represents an undefined
1130/// (unspecified) length, which would have to be determined
1131/// with a traversal based on the content's encoding.
1132///
1133/// This also means that numeric comparisons and arithmetic
1134/// do not function the same way as primitive number types:
1135///
1136/// Two length of undefined length are not equal.
1137///
1138/// ```
1139/// # use dicom_core::Length;
1140/// assert_ne!(Length::UNDEFINED, Length::UNDEFINED);
1141/// ```
1142///
1143/// Any addition or substraction with at least one undefined
1144/// length results in an undefined length.
1145///
1146/// ```
1147/// # use dicom_core::Length;
1148/// assert!((Length::defined(64) + Length::UNDEFINED).is_undefined());
1149/// assert!((Length::UNDEFINED + 8).is_undefined());
1150/// ```
1151///
1152/// Comparing between at least one undefined length is always `false`.
1153///
1154/// ```
1155/// # use dicom_core::Length;
1156/// assert!(Length::defined(16) < Length::defined(64));
1157/// assert!(!(Length::UNDEFINED < Length::defined(64)));
1158/// assert!(!(Length::UNDEFINED > Length::defined(64)));
1159///
1160/// assert!(!(Length::UNDEFINED < Length::UNDEFINED));
1161/// assert!(!(Length::UNDEFINED > Length::UNDEFINED));
1162/// assert!(!(Length::UNDEFINED <= Length::UNDEFINED));
1163/// assert!(!(Length::UNDEFINED >= Length::UNDEFINED));
1164/// ```
1165///
1166#[derive(Clone, Copy)]
1167pub struct Length(pub u32);
1168
1169const UNDEFINED_LEN: u32 = 0xFFFF_FFFF;
1170
1171impl Length {
1172    /// A length that is undefined.
1173    pub const UNDEFINED: Self = Length(UNDEFINED_LEN);
1174
1175    /// Create a new length value from its internal representation.
1176    /// This is equivalent to `Length(len)`.
1177    #[inline]
1178    pub fn new(len: u32) -> Self {
1179        Length(len)
1180    }
1181
1182    /// Create a new length value with the given number of bytes.
1183    ///
1184    /// # Panic
1185    ///
1186    /// This function will panic if `len` represents an undefined length.
1187    #[inline]
1188    pub fn defined(len: u32) -> Self {
1189        assert_ne!(len, UNDEFINED_LEN);
1190        Length(len)
1191    }
1192}
1193
1194impl From<u32> for Length {
1195    #[inline]
1196    fn from(o: u32) -> Self {
1197        Length(o)
1198    }
1199}
1200
1201impl PartialEq<Length> for Length {
1202    fn eq(&self, rhs: &Length) -> bool {
1203        match (self.0, rhs.0) {
1204            (UNDEFINED_LEN, _) | (_, UNDEFINED_LEN) => false,
1205            (l1, l2) => l1 == l2,
1206        }
1207    }
1208}
1209
1210impl PartialOrd<Length> for Length {
1211    fn partial_cmp(&self, rhs: &Length) -> Option<Ordering> {
1212        match (self.0, rhs.0) {
1213            (UNDEFINED_LEN, _) | (_, UNDEFINED_LEN) => None,
1214            (l1, l2) => Some(l1.cmp(&l2)),
1215        }
1216    }
1217}
1218
1219impl std::ops::Add<Length> for Length {
1220    type Output = Self;
1221
1222    fn add(self, rhs: Length) -> Self::Output {
1223        match (self.0, rhs.0) {
1224            (UNDEFINED_LEN, _) | (_, UNDEFINED_LEN) => Length::UNDEFINED,
1225            (l1, l2) => {
1226                let o = l1 + l2;
1227                debug_assert!(
1228                    o != UNDEFINED_LEN,
1229                    "integer overflow (0xFFFF_FFFF reserved for undefined length)"
1230                );
1231                Length(o)
1232            }
1233        }
1234    }
1235}
1236
1237impl std::ops::Add<i32> for Length {
1238    type Output = Self;
1239
1240    fn add(self, rhs: i32) -> Self::Output {
1241        match self.0 {
1242            UNDEFINED_LEN => Length::UNDEFINED,
1243            len => {
1244                let o = (len as i32 + rhs) as u32;
1245                debug_assert!(
1246                    o != UNDEFINED_LEN,
1247                    "integer overflow (0xFFFF_FFFF reserved for undefined length)"
1248                );
1249
1250                Length(o)
1251            }
1252        }
1253    }
1254}
1255
1256impl std::ops::Sub<Length> for Length {
1257    type Output = Self;
1258
1259    fn sub(self, rhs: Length) -> Self::Output {
1260        let mut o = self;
1261        o -= rhs;
1262        o
1263    }
1264}
1265
1266impl std::ops::SubAssign<Length> for Length {
1267    fn sub_assign(&mut self, rhs: Length) {
1268        match (self.0, rhs.0) {
1269            (UNDEFINED_LEN, _) | (_, UNDEFINED_LEN) => (), // no-op
1270            (_, l2) => {
1271                self.0 -= l2;
1272                debug_assert!(
1273                    self.0 != UNDEFINED_LEN,
1274                    "integer overflow (0xFFFF_FFFF reserved for undefined length)"
1275                );
1276            }
1277        }
1278    }
1279}
1280
1281impl std::ops::Sub<i32> for Length {
1282    type Output = Self;
1283
1284    fn sub(self, rhs: i32) -> Self::Output {
1285        let mut o = self;
1286        o -= rhs;
1287        o
1288    }
1289}
1290
1291impl std::ops::SubAssign<i32> for Length {
1292    fn sub_assign(&mut self, rhs: i32) {
1293        match self.0 {
1294            UNDEFINED_LEN => (), // no-op
1295            len => {
1296                self.0 = (len as i32 - rhs) as u32;
1297                debug_assert!(
1298                    self.0 != UNDEFINED_LEN,
1299                    "integer overflow (0xFFFF_FFFF reserved for undefined length)"
1300                );
1301            }
1302        }
1303    }
1304}
1305
1306impl Length {
1307    /// Check whether this length is undefined (unknown).
1308    #[inline]
1309    pub fn is_undefined(self) -> bool {
1310        self.0 == UNDEFINED_LEN
1311    }
1312
1313    /// Check whether this length is well defined (not undefined).
1314    #[inline]
1315    pub fn is_defined(self) -> bool {
1316        !self.is_undefined()
1317    }
1318
1319    /// Fetch the concrete length value, if available.
1320    /// Returns `None` if it represents an undefined length.
1321    #[inline]
1322    pub fn get(self) -> Option<u32> {
1323        match self.0 {
1324            UNDEFINED_LEN => None,
1325            v => Some(v),
1326        }
1327    }
1328
1329    /// Check whether the length is equally specified as another length.
1330    /// Unlike the implemented `PartialEq`, two undefined lengths are
1331    /// considered equivalent by this method.
1332    #[inline]
1333    pub fn inner_eq(self, other: Length) -> bool {
1334        self.0 == other.0
1335    }
1336}
1337
1338impl fmt::Debug for Length {
1339    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1340        match self.0 {
1341            UNDEFINED_LEN => f.write_str("Length(Undefined)"),
1342            l => f.debug_tuple("Length").field(&l).finish(),
1343        }
1344    }
1345}
1346
1347impl fmt::Display for Length {
1348    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1349        match self.0 {
1350            UNDEFINED_LEN => f.write_str("U/L"),
1351            l => write!(f, "{}", &l),
1352        }
1353    }
1354}
1355
1356#[cfg(test)]
1357mod tests {
1358    use super::*;
1359    use crate::{dicom_value, value::PixelFragmentSequence, DicomValue};
1360
1361    #[test]
1362    fn to_clean_string() {
1363        let p = dicom_value!(U16, [256, 0, 16]);
1364        let val = DicomValue::new(p);
1365        let element = DataElement::new(Tag(0x0028, 0x3002), VR::US, val);
1366        assert_eq!(element.to_str().unwrap(), "256\\0\\16",);
1367    }
1368
1369    #[test]
1370    fn tag_from_u16_pair() {
1371        let t = Tag::from((0x0010u16, 0x0020u16));
1372        assert_eq!(0x0010u16, t.group());
1373        assert_eq!(0x0020u16, t.element());
1374    }
1375
1376    #[test]
1377    fn tag_from_u16_array() {
1378        let t = Tag::from([0x0010u16, 0x0020u16]);
1379        assert_eq!(0x0010u16, t.group());
1380        assert_eq!(0x0020u16, t.element());
1381    }
1382
1383    /// Ensure good order between tags
1384    #[test]
1385    fn tag_ord() {
1386        assert_eq!(
1387            Tag(0x0010, 0x0020).cmp(&Tag(0x0010, 0x0020)),
1388            Ordering::Equal
1389        );
1390
1391        assert_eq!(
1392            Tag(0x0010, 0x0020).cmp(&Tag(0x0010, 0x0024)),
1393            Ordering::Less
1394        );
1395        assert_eq!(
1396            Tag(0x0010, 0x0020).cmp(&Tag(0x0020, 0x0010)),
1397            Ordering::Less
1398        );
1399        assert_eq!(
1400            Tag(0x0010, 0x0020).cmp(&Tag(0x0020, 0x0024)),
1401            Ordering::Less
1402        );
1403        assert_eq!(
1404            Tag(0x0010, 0x0000).cmp(&Tag(0x0320, 0x0010)),
1405            Ordering::Less
1406        );
1407
1408        assert_eq!(
1409            Tag(0x0010, 0x0020).cmp(&Tag(0x0010, 0x0010)),
1410            Ordering::Greater
1411        );
1412        assert_eq!(
1413            Tag(0x0012, 0x0020).cmp(&Tag(0x0010, 0x0024)),
1414            Ordering::Greater
1415        );
1416        assert_eq!(
1417            Tag(0x0012, 0x0020).cmp(&Tag(0x0010, 0x0010)),
1418            Ordering::Greater
1419        );
1420        assert_eq!(
1421            Tag(0x0012, 0x0020).cmp(&Tag(0x0012, 0x0010)),
1422            Ordering::Greater
1423        );
1424    }
1425
1426    #[test]
1427    fn get_date_value() {
1428        let data_element: DataElement<_, _> = DataElement::new(
1429            Tag(0x0010, 0x0030),
1430            VR::DA,
1431            Value::new(PrimitiveValue::from("19941012")),
1432        );
1433
1434        assert_eq!(
1435            data_element.to_date().unwrap(),
1436            DicomDate::from_ymd(1994, 10, 12).unwrap(),
1437        );
1438    }
1439
1440    #[test]
1441    fn create_data_element_from_primitive() {
1442        let data_element: DataElement<EmptyObject, [u8; 0]> = DataElement::new(
1443            Tag(0x0028, 0x3002),
1444            VR::US,
1445            crate::dicom_value!(U16, [256, 0, 16]),
1446        );
1447
1448        assert_eq!(data_element.uint16_slice().unwrap(), &[256, 0, 16]);
1449    }
1450
1451    #[test]
1452    fn parse_tag() {
1453        // without parens nor comma separator
1454        let tag: Tag = "00280004".parse().unwrap();
1455        assert_eq!(tag, Tag(0x0028, 0x0004));
1456        // lowercase
1457        let tag: Tag = "7fe00001".parse().unwrap();
1458        assert_eq!(tag, Tag(0x7FE0, 0x0001));
1459        // uppercase
1460        let tag: Tag = "7FE00001".parse().unwrap();
1461        assert_eq!(tag, Tag(0x7FE0, 0x0001));
1462
1463        // with parens, lowercase
1464        let tag: Tag = "(7fe0,0010)".parse().unwrap();
1465        assert_eq!(tag, Tag(0x7FE0, 0x0010));
1466        let tag: Tag = "(003a,001a)".parse().unwrap();
1467        assert_eq!(tag, Tag(0x003A, 0x001A));
1468
1469        // with parens, uppercase
1470        let tag: Tag = "(7FE0,0010)".parse().unwrap();
1471        assert_eq!(tag, Tag(0x7FE0, 0x0010));
1472        let tag: Tag = "(003A,001A)".parse().unwrap();
1473        assert_eq!(tag, Tag(0x003A, 0x001A));
1474
1475        // with parens, mixed case
1476        let tag: Tag = "(003a,001A)".parse().unwrap();
1477        assert_eq!(tag, Tag(0x003A, 0x001A));
1478
1479        // without parens
1480        let tag: Tag = "7fe0,0010".parse().unwrap();
1481        assert_eq!(tag, Tag(0x7FE0, 0x0010));
1482        let tag: Tag = "003a,001a".parse().unwrap();
1483        assert_eq!(tag, Tag(0x003A, 0x001A));
1484
1485        // error case: unsupported number forms
1486        let r: Result<Tag, _> = "+03a,0001".parse();
1487        assert_eq!(r, Err(ParseTagError::Number));
1488        // error case: bad start
1489        let r: Result<Tag, _> = "[baad,0123)".parse();
1490        assert_eq!(r, Err(ParseTagError::Start));
1491        // error case: bad end
1492        let r: Result<Tag, _> = "(baad,0123]".parse();
1493        assert_eq!(r, Err(ParseTagError::End));
1494        // error case: not enough characters
1495        let r: Result<Tag, _> = "(3a,1a)".parse();
1496        assert_eq!(r, Err(ParseTagError::Length));
1497        // error case: bad characters
1498        let r: Result<Tag, _> = "g00d,baad".parse();
1499        assert_eq!(r, Err(ParseTagError::Number));
1500        // error case: missing comma
1501        let r: Result<Tag, _> = "(baad&0123)".parse();
1502        assert_eq!(r, Err(ParseTagError::Separator));
1503        // error case: comma in the wrong place
1504        let r: Result<Tag, _> = "123,45678".parse();
1505        assert_eq!(r, Err(ParseTagError::Number));
1506        // error case: comma in the wrong place
1507        let r: Result<Tag, _> = "abcde,f01".parse();
1508        assert_eq!(r, Err(ParseTagError::Separator));
1509        // error case: comma instead of hex digit
1510        let r: Result<Tag, _> = "1234567,".parse();
1511        assert_eq!(r, Err(ParseTagError::Number));
1512    }
1513
1514    #[test]
1515    fn test_update_value() {
1516        // can update a string value
1517        let mut e: DataElement<EmptyObject, InMemFragment> =
1518            DataElement::new(Tag(0x0010, 0x0010), VR::PN, "Doe^John");
1519        assert_eq!(e.length(), Length(8));
1520        e.update_value(|e| {
1521            *e = "Smith^John".into();
1522        });
1523        assert_eq!(e.length(), Length(10));
1524
1525        // can update a pixel sequence
1526        let mut e: DataElement<EmptyObject, InMemFragment> = DataElement::new_with_len(
1527            Tag(0x7FE0, 0x0010),
1528            VR::OB,
1529            Length(0),
1530            PixelFragmentSequence::new_fragments(vec![]),
1531        );
1532        assert_eq!(e.length(), Length(0));
1533
1534        e.update_value(|v| {
1535            let fragments = v.fragments_mut().unwrap();
1536            fragments.push(vec![0x00; 256]);
1537            fragments.push(vec![0x55; 256]);
1538            fragments.push(vec![0xCC; 256]);
1539        });
1540
1541        assert!(e.length().is_undefined());
1542        assert_eq!(e.fragments().map(|f| f.len()), Some(3));
1543    }
1544}