dicom_core/value/
mod.rs

1//! This module includes a high level abstraction over a DICOM data element's value.
2
3use crate::header::{EmptyObject, HasLength, Length, Tag};
4use num_traits::NumCast;
5use smallvec::SmallVec;
6use std::{borrow::Cow, str::FromStr};
7
8pub mod deserialize;
9pub mod fragments;
10pub mod partial;
11pub mod person_name;
12mod primitive;
13pub mod range;
14pub mod serialize;
15
16pub use self::deserialize::Error as DeserializeError;
17pub use self::partial::{DicomDate, DicomDateTime, DicomTime, PreciseDateTime};
18pub use self::person_name::PersonName;
19pub use self::range::{AsRange, DateRange, DateTimeRange, TimeRange};
20
21pub use self::primitive::{
22    CastValueError, ConvertValueError, InvalidValueReadError, ModifyValueError, PrimitiveValue,
23    ValueType,
24};
25
26pub use either::Either;
27
28/// An aggregation of one or more elements in a value.
29pub type C<T> = SmallVec<[T; 2]>;
30
31/// Type alias for the in-memory pixel data fragment data.
32pub type InMemFragment = Vec<u8>;
33
34/// A trait for a value that maps to a DICOM element data value.
35pub trait DicomValueType: HasLength {
36    /// Retrieve the specific type of this value.
37    fn value_type(&self) -> ValueType;
38
39    /// Retrieve the number of elements contained in the DICOM value.
40    ///
41    /// In a sequence value, this is the number of items in the sequence.
42    /// In an encapsulated pixel data sequence, the output is always 1.
43    /// Otherwise, the output is the number of elements effectively encoded
44    /// in the value.
45    fn cardinality(&self) -> usize;
46}
47
48impl<L, R> HasLength for Either<L, R>
49where
50    L: HasLength,
51    R: HasLength,
52{
53    fn length(&self) -> Length {
54        match self {
55            Either::Left(l) => l.length(),
56            Either::Right(r) => r.length(),
57        }
58    }
59}
60
61impl<L, R> DicomValueType for Either<L, R>
62where
63    L: DicomValueType,
64    R: DicomValueType,
65{
66    fn value_type(&self) -> ValueType {
67        match self {
68            Either::Left(l) => l.value_type(),
69            Either::Right(r) => r.value_type(),
70        }
71    }
72
73    fn cardinality(&self) -> usize {
74        match self {
75            Either::Left(l) => l.cardinality(),
76            Either::Right(r) => r.cardinality(),
77        }
78    }
79}
80
81/// Representation of a full DICOM value, which may be either primitive or
82/// another DICOM object.
83///
84/// `I` is the complex type for nest data set items, which should usually
85/// implement [`HasLength`].
86/// `P` is the encapsulated pixel data provider,
87/// which should usually implement `AsRef<[u8]>`.
88#[derive(Debug, Clone, PartialEq)]
89pub enum Value<I = EmptyObject, P = InMemFragment> {
90    /// Primitive value.
91    Primitive(PrimitiveValue),
92    /// A complex sequence of items.
93    Sequence(DataSetSequence<I>),
94    /// A sequence of encapsulated pixel data fragments.
95    PixelSequence(PixelFragmentSequence<P>),
96}
97
98impl<P> Value<EmptyObject, P> {
99    /// Construct an isolated DICOM pixel sequence sequence value
100    /// from a basic offset table and a list of fragments.
101    ///
102    /// This function will define the data set sequence item type `I`
103    /// to an empty object ([`EmptyObject`]),
104    /// so that it can be used more easily in isolation.
105    /// As a consequence, it cannot be directly combined with
106    /// DICOM objects that may contain sequence values.
107    /// To let the type parameter `I` be inferred from its context,
108    /// create a [`PixelFragmentSequence`] and use `Value::from` instead.
109    ///
110    /// **Note:** This function does not validate the offset table
111    /// against the fragments.
112    pub fn new_pixel_sequence<T>(offset_table: C<u32>, fragments: T) -> Self
113    where
114        T: Into<C<P>>,
115    {
116        Value::from(PixelFragmentSequence::new(offset_table, fragments))
117    }
118}
119
120impl<I> Value<I> {
121    /// Construct an isolated DICOM data set sequence value
122    /// from a list of items and length.
123    ///
124    /// This function will define the pixel data fragment type parameter `P`
125    /// to the `Value` type's default ([`InMemFragment`]),
126    /// so that it can be used more easily.
127    /// If necessary,
128    /// it is possible to let this type parameter be inferred from its context
129    /// by creating a [`DataSetSequence`] and using `Value::from` instead.
130    #[inline]
131    pub fn new_sequence<T>(items: T, length: Length) -> Self
132    where
133        T: Into<C<I>>,
134    {
135        Self::from(DataSetSequence::new(items, length))
136    }
137}
138
139impl Value {
140    /// Construct a DICOM value from a primitive value.
141    ///
142    /// This is equivalent to `Value::from` in behavior,
143    /// except that suitable type parameters are specified
144    /// instead of inferred.
145    ///
146    /// This function will automatically define
147    /// the sequence item parameter `I`
148    /// to [`EmptyObject`]
149    /// and the pixel data fragment type parameter `P`
150    /// to the default fragment data type ([`InMemFragment`]),
151    /// so that it can be used more easily in isolation.
152    /// As a consequence, it cannot be directly combined with
153    /// DICOM objects that may contain
154    /// nested data sets or encapsulated pixel data.
155    /// To let the type parameters `I` and `P` be inferred from their context,
156    /// create a value of one of the types and use `Value::from` instead.
157    ///
158    /// - [`PrimitiveValue`]
159    /// - [`PixelFragmentSequence`]
160    /// - [`DataSetSequence`]
161    #[inline]
162    pub fn new(value: PrimitiveValue) -> Self {
163        Self::from(value)
164    }
165}
166
167impl<I, P> Value<I, P> {
168    /// Obtain the number of individual values.
169    /// In a primitive, this is the number of individual elements in the value.
170    /// In a sequence item, this is the number of items.
171    /// In a pixel sequence, this is currently set to 1
172    /// regardless of the number of compressed fragments or frames.
173    pub fn multiplicity(&self) -> u32 {
174        match self {
175            Value::Primitive(v) => v.multiplicity(),
176            Value::Sequence(v) => v.multiplicity(),
177            Value::PixelSequence(..) => 1,
178        }
179    }
180
181    /// Gets a reference to the primitive value.
182    pub fn primitive(&self) -> Option<&PrimitiveValue> {
183        match self {
184            Value::Primitive(v) => Some(v),
185            _ => None,
186        }
187    }
188
189    /// Produce a shallow clone of the value,
190    /// leaving the items and pixel data fragments as references.
191    ///
192    /// If the value is primitive,
193    /// the entire value will be copied.
194    /// Otherwise, the item or fragment sequences
195    /// will hold references to the original data.
196    pub fn shallow_clone(&self) -> Value<&I, &P> {
197        match self {
198            Value::Primitive(v) => Value::Primitive(v.clone()),
199            Value::Sequence(v) => Value::Sequence(DataSetSequence {
200                items: v.items.iter().collect(),
201                length: v.length,
202            }),
203            Value::PixelSequence(v) => Value::PixelSequence(PixelFragmentSequence {
204                offset_table: v.offset_table.iter().copied().collect(),
205                fragments: v.fragments.iter().collect(),
206            }),
207        }
208    }
209
210    /// Gets a mutable reference to the primitive value.
211    pub fn primitive_mut(&mut self) -> Option<&mut PrimitiveValue> {
212        match self {
213            Value::Primitive(v) => Some(v),
214            _ => None,
215        }
216    }
217
218    /// Gets a reference to the items of a sequence.
219    ///
220    /// Returns `None` if the value is not a data set sequence.
221    pub fn items(&self) -> Option<&[I]> {
222        match self {
223            Value::Sequence(v) => Some(v.items()),
224            _ => None,
225        }
226    }
227
228    /// Gets a mutable reference to the items of a sequence.
229    ///
230    /// Returns `None` if the value is not a data set sequence.
231    pub fn items_mut(&mut self) -> Option<&mut C<I>> {
232        match self {
233            Value::Sequence(v) => Some(v.items_mut()),
234            _ => None,
235        }
236    }
237
238    /// Gets a reference to the fragments of a pixel data sequence.
239    ///
240    /// Returns `None` if the value is not a pixel data sequence.
241    pub fn fragments(&self) -> Option<&[P]> {
242        match self {
243            Value::PixelSequence(v) => Some(v.fragments()),
244            _ => None,
245        }
246    }
247
248    /// Gets a mutable reference to the fragments of a pixel data sequence.
249    ///
250    /// Returns `None` if the value is not a pixel data sequence.
251    pub fn fragments_mut(&mut self) -> Option<&mut C<P>> {
252        match self {
253            Value::PixelSequence(v) => Some(v.fragments_mut()),
254            _ => None,
255        }
256    }
257
258    /// Retrieves the primitive value.
259    pub fn into_primitive(self) -> Option<PrimitiveValue> {
260        match self {
261            Value::Primitive(v) => Some(v),
262            _ => None,
263        }
264    }
265
266    /// Retrieves the data set items,
267    /// discarding the recorded length information.
268    ///
269    /// Returns `None` if the value is not a data set sequence.
270    pub fn into_items(self) -> Option<C<I>> {
271        match self {
272            Value::Sequence(v) => Some(v.into_items()),
273            _ => None,
274        }
275    }
276
277    /// Retrieves the pixel data fragments,
278    /// discarding the rest of the information.
279    pub fn into_fragments(self) -> Option<C<P>> {
280        match self {
281            Value::PixelSequence(v) => Some(v.into_fragments()),
282            _ => None,
283        }
284    }
285
286    /// Gets a reference to the encapsulated pixel data's offset table.
287    ///
288    /// Returns `None` if the value is not a pixel data sequence.
289    pub fn offset_table(&self) -> Option<&[u32]> {
290        match self {
291            Value::PixelSequence(v) => Some(v.offset_table()),
292            _ => None,
293        }
294    }
295
296    /// Gets a mutable reference to the encapsulated pixel data's offset table.
297    ///
298    /// Returns `None` if the value is not a pixel data sequence.
299    pub fn offset_table_mut(&mut self) -> Option<&mut C<u32>> {
300        match self {
301            Value::PixelSequence(v) => Some(v.offset_table_mut()),
302            _ => None,
303        }
304    }
305
306    /// Shorten this value by removing trailing elements
307    /// to fit the given limit.
308    ///
309    /// On primitive values,
310    /// elements are counted by the number of individual value items
311    /// (note that bytes in a [`PrimitiveValue::U8`]
312    /// are treated as individual items).
313    /// On data set sequences and pixel data fragment sequences,
314    /// this operation is applied to
315    /// the data set items (or fragments) in the sequence.
316    ///
317    /// Nothing is done if the value's cardinality
318    /// is already lower than or equal to the limit.
319    pub fn truncate(&mut self, limit: usize) {
320        match self {
321            Value::Primitive(v) => v.truncate(limit),
322            Value::Sequence(v) => v.truncate(limit),
323            Value::PixelSequence(v) => v.truncate(limit),
324        }
325    }
326}
327
328impl<I, P> From<&str> for Value<I, P> {
329    /// Converts a string into a primitive textual value.
330    fn from(value: &str) -> Self {
331        Value::Primitive(PrimitiveValue::from(value))
332    }
333}
334
335impl<I, P> From<String> for Value<I, P> {
336    /// Converts a string into a primitive textual value.
337    fn from(value: String) -> Self {
338        Value::Primitive(PrimitiveValue::from(value))
339    }
340}
341
342impl<I, P> From<DicomDate> for Value<I, P> {
343    /// Converts the DICOM date into a primitive value.
344    fn from(value: DicomDate) -> Self {
345        Value::Primitive(PrimitiveValue::from(value))
346    }
347}
348
349impl<I, P> From<DicomTime> for Value<I, P> {
350    /// Converts the DICOM time into a primitive value.
351    fn from(value: DicomTime) -> Self {
352        Value::Primitive(PrimitiveValue::from(value))
353    }
354}
355
356impl<I, P> From<DicomDateTime> for Value<I, P> {
357    /// Converts the DICOM date-time into a primitive value.
358    fn from(value: DicomDateTime) -> Self {
359        Value::Primitive(PrimitiveValue::from(value))
360    }
361}
362
363impl<I, P> HasLength for Value<I, P> {
364    fn length(&self) -> Length {
365        match self {
366            Value::Primitive(v) => v.length(),
367            Value::Sequence(v) => v.length(),
368            Value::PixelSequence(v) => v.length(),
369        }
370    }
371}
372
373impl<I, P> HasLength for &Value<I, P> {
374    fn length(&self) -> Length {
375        HasLength::length(*self)
376    }
377}
378
379impl<I, P> DicomValueType for Value<I, P> {
380    fn value_type(&self) -> ValueType {
381        match self {
382            Value::Primitive(v) => v.value_type(),
383            Value::Sequence(..) => ValueType::DataSetSequence,
384            Value::PixelSequence(..) => ValueType::PixelSequence,
385        }
386    }
387
388    fn cardinality(&self) -> usize {
389        match self {
390            Value::Primitive(v) => v.cardinality(),
391            Value::Sequence(DataSetSequence { items, .. }) => items.len(),
392            Value::PixelSequence { .. } => 1,
393        }
394    }
395}
396
397impl<I, P> DicomValueType for &Value<I, P> {
398    fn value_type(&self) -> ValueType {
399        DicomValueType::value_type(*self)
400    }
401
402    fn cardinality(&self) -> usize {
403        DicomValueType::cardinality(*self)
404    }
405}
406
407impl<I, P> Value<I, P>
408where
409    I: HasLength,
410{
411    /// Convert the full primitive value into a clean string.
412    ///
413    /// The value is converted into a strings
414    /// as described in [`PrimitiveValue::to_str`].
415    /// If the value contains multiple strings,
416    /// they are trimmed at the end and concatenated
417    /// (separated by the standard DICOM value delimiter `'\\'`)
418    /// into an owned string.
419    ///
420    /// Returns an error if the value is not primitive.
421    pub fn to_str(&self) -> Result<Cow<'_, str>, ConvertValueError> {
422        match self {
423            Value::Primitive(prim) => Ok(prim.to_str()),
424            _ => Err(ConvertValueError {
425                requested: "string",
426                original: self.value_type(),
427                cause: None,
428            }),
429        }
430    }
431
432    /// Convert the full primitive value into a single raw string,
433    /// with trailing whitespace kept.
434    ///
435    /// If the value contains multiple strings, they are concatenated
436    /// (separated by the standard DICOM value delimiter `'\\'`)
437    /// into an owned string.
438    ///
439    /// Returns an error if the value is not primitive.
440    pub fn to_raw_str(&self) -> Result<Cow<'_, str>, ConvertValueError> {
441        match self {
442            Value::Primitive(prim) => Ok(prim.to_raw_str()),
443            _ => Err(ConvertValueError {
444                requested: "string",
445                original: self.value_type(),
446                cause: None,
447            }),
448        }
449    }
450
451    /// Convert the full primitive value into a sequence of strings.
452    ///
453    /// If the value is a primitive, it will be converted into
454    /// a vector of strings as described in [`PrimitiveValue::to_multi_str`].
455    ///
456    /// Returns an error if the value is not primitive.
457    ///
458    /// [`PrimitiveValue::to_multi_str`]: ../enum.PrimitiveValue.html#to_multi_str
459    pub fn to_multi_str(&self) -> Result<Cow<'_, [String]>, CastValueError> {
460        match self {
461            Value::Primitive(prim) => Ok(prim.to_multi_str()),
462            _ => Err(CastValueError {
463                requested: "string",
464                got: self.value_type(),
465            }),
466        }
467    }
468
469    /// Convert the full primitive value into raw bytes.
470    ///
471    /// String values already encoded with the `Str` and `Strs` variants
472    /// are provided in UTF-8.
473    ///
474    /// Returns an error if the value is not primitive.
475    pub fn to_bytes(&self) -> Result<Cow<'_, [u8]>, ConvertValueError> {
476        match self {
477            Value::Primitive(prim) => Ok(prim.to_bytes()),
478            _ => Err(ConvertValueError {
479                requested: "bytes",
480                original: self.value_type(),
481                cause: None,
482            }),
483        }
484    }
485
486    /// Retrieve and convert the primitive value into an integer.
487    ///
488    /// If the value is a primitive, it will be converted into
489    /// an integer as described in [`PrimitiveValue::to_int`].
490    ///
491    /// [`PrimitiveValue::to_int`]: ../enum.PrimitiveValue.html#to_int
492    pub fn to_int<T>(&self) -> Result<T, ConvertValueError>
493    where
494        T: Clone,
495        T: NumCast,
496        T: FromStr<Err = std::num::ParseIntError>,
497    {
498        match self {
499            Value::Primitive(v) => v.to_int::<T>(),
500            _ => Err(ConvertValueError {
501                requested: "integer",
502                original: self.value_type(),
503                cause: None,
504            }),
505        }
506    }
507
508    /// Retrieve and convert the primitive value into a sequence of integers.
509    ///
510    /// If the value is a primitive, it will be converted into
511    /// a vector of integers as described in [PrimitiveValue::to_multi_int].
512    ///
513    /// [PrimitiveValue::to_multi_int]: ../enum.PrimitiveValue.html#to_multi_int
514    pub fn to_multi_int<T>(&self) -> Result<Vec<T>, ConvertValueError>
515    where
516        T: Clone,
517        T: NumCast,
518        T: FromStr<Err = std::num::ParseIntError>,
519    {
520        match self {
521            Value::Primitive(v) => v.to_multi_int::<T>(),
522            _ => Err(ConvertValueError {
523                requested: "integer",
524                original: self.value_type(),
525                cause: None,
526            }),
527        }
528    }
529
530    /// Retrieve and convert the primitive value
531    /// into a single-precision floating point number.
532    ///
533    /// If the value is a primitive, it will be converted into
534    /// a number as described in [`PrimitiveValue::to_float32`].
535    ///
536    /// [`PrimitiveValue::to_float32`]: ../enum.PrimitiveValue.html#to_float32
537    pub fn to_float32(&self) -> Result<f32, ConvertValueError> {
538        match self {
539            Value::Primitive(v) => v.to_float32(),
540            _ => Err(ConvertValueError {
541                requested: "float32",
542                original: self.value_type(),
543                cause: None,
544            }),
545        }
546    }
547
548    /// Retrieve and convert the primitive value
549    /// into a sequence of single-precision floating point numbers.
550    ///
551    /// If the value is a primitive, it will be converted into
552    /// a vector of numbers as described in [`PrimitiveValue::to_multi_float32`].
553    ///
554    /// [`PrimitiveValue::to_multi_float32`]: ../enum.PrimitiveValue.html#to_multi_float32
555    pub fn to_multi_float32(&self) -> Result<Vec<f32>, ConvertValueError> {
556        match self {
557            Value::Primitive(v) => v.to_multi_float32(),
558            _ => Err(ConvertValueError {
559                requested: "float32",
560                original: self.value_type(),
561                cause: None,
562            }),
563        }
564    }
565
566    /// Retrieve and convert the primitive value
567    /// into a double-precision floating point number.
568    ///
569    /// If the value is a primitive, it will be converted into
570    /// a number as described in [`PrimitiveValue::to_float64`].
571    ///
572    /// [`PrimitiveValue::to_float64`]: ../enum.PrimitiveValue.html#to_float64
573    pub fn to_float64(&self) -> Result<f64, ConvertValueError> {
574        match self {
575            Value::Primitive(v) => v.to_float64(),
576            _ => Err(ConvertValueError {
577                requested: "float64",
578                original: self.value_type(),
579                cause: None,
580            }),
581        }
582    }
583
584    /// Retrieve and convert the primitive value
585    /// into a sequence of double-precision floating point numbers.
586    ///
587    /// If the value is a primitive, it will be converted into
588    /// a vector of numbers as described in [`PrimitiveValue::to_multi_float64`].
589    ///
590    /// [`PrimitiveValue::to_multi_float64`]: ../enum.PrimitiveValue.html#to_multi_float64
591    pub fn to_multi_float64(&self) -> Result<Vec<f64>, ConvertValueError> {
592        match self {
593            Value::Primitive(v) => v.to_multi_float64(),
594            _ => Err(ConvertValueError {
595                requested: "float64",
596                original: self.value_type(),
597                cause: None,
598            }),
599        }
600    }
601
602    /// Retrieve and convert the primitive value into a `DicomDate`.
603    ///
604    /// If the value is a primitive, it will be converted into
605    /// a `DicomDate` as described in [`PrimitiveValue::to_date`].
606    ///
607    pub fn to_date(&self) -> Result<DicomDate, ConvertValueError> {
608        match self {
609            Value::Primitive(v) => v.to_date(),
610            _ => Err(ConvertValueError {
611                requested: "DicomDate",
612                original: self.value_type(),
613                cause: None,
614            }),
615        }
616    }
617
618    /// Retrieve and convert the primitive value into a sequence of `DicomDate`s.
619    ///
620    /// If the value is a primitive, it will be converted into
621    /// a vector of `DicomDate` as described in [`PrimitiveValue::to_multi_date`].
622    ///
623    pub fn to_multi_date(&self) -> Result<Vec<DicomDate>, ConvertValueError> {
624        match self {
625            Value::Primitive(v) => v.to_multi_date(),
626            _ => Err(ConvertValueError {
627                requested: "DicomDate",
628                original: self.value_type(),
629                cause: None,
630            }),
631        }
632    }
633
634    /// Retrieve and convert the primitive value into a `DicomTime`.
635    ///
636    /// If the value is a primitive, it will be converted into
637    /// a `DicomTime` as described in [`PrimitiveValue::to_time`].
638    ///
639    pub fn to_time(&self) -> Result<DicomTime, ConvertValueError> {
640        match self {
641            Value::Primitive(v) => v.to_time(),
642            _ => Err(ConvertValueError {
643                requested: "DicomTime",
644                original: self.value_type(),
645                cause: None,
646            }),
647        }
648    }
649
650    /// Retrieve and convert the primitive value into a sequence of `DicomTime`s.
651    ///
652    /// If the value is a primitive, it will be converted into
653    /// a vector of `DicomTime` as described in [`PrimitiveValue::to_multi_time`].
654    ///
655    pub fn to_multi_time(&self) -> Result<Vec<DicomTime>, ConvertValueError> {
656        match self {
657            Value::Primitive(v) => v.to_multi_time(),
658            _ => Err(ConvertValueError {
659                requested: "DicomTime",
660                original: self.value_type(),
661                cause: None,
662            }),
663        }
664    }
665
666    /// Retrieve and convert the primitive value into a `DicomDateTime`.
667    ///
668    /// If the value is a primitive, it will be converted into
669    /// a `DateTime` as described in [`PrimitiveValue::to_datetime`].
670    ///
671    pub fn to_datetime(&self) -> Result<DicomDateTime, ConvertValueError> {
672        match self {
673            Value::Primitive(v) => v.to_datetime(),
674            _ => Err(ConvertValueError {
675                requested: "DicomDateTime",
676                original: self.value_type(),
677                cause: None,
678            }),
679        }
680    }
681
682    /// Retrieve and convert the primitive value into a sequence of `DicomDateTime`s.
683    ///
684    /// If the value is a primitive, it will be converted into
685    /// a vector of `DicomDateTime` as described in [`PrimitiveValue::to_multi_datetime`].
686    ///
687    pub fn to_multi_datetime(&self) -> Result<Vec<DicomDateTime>, ConvertValueError> {
688        match self {
689            Value::Primitive(v) => v.to_multi_datetime(),
690            _ => Err(ConvertValueError {
691                requested: "DicomDateTime",
692                original: self.value_type(),
693                cause: None,
694            }),
695        }
696    }
697
698    /// Retrieve and convert the primitive value into a `DateRange`.
699    ///
700    /// If the value is a primitive, it will be converted into
701    /// a `DateRange` as described in [`PrimitiveValue::to_date_range`].
702    ///
703    pub fn to_date_range(&self) -> Result<DateRange, ConvertValueError> {
704        match self {
705            Value::Primitive(v) => v.to_date_range(),
706            _ => Err(ConvertValueError {
707                requested: "DateRange",
708                original: self.value_type(),
709                cause: None,
710            }),
711        }
712    }
713
714    /// Retrieve and convert the primitive value into a `TimeRange`.
715    ///
716    /// If the value is a primitive, it will be converted into
717    /// a `TimeRange` as described in [`PrimitiveValue::to_time_range`].
718    ///
719    pub fn to_time_range(&self) -> Result<TimeRange, ConvertValueError> {
720        match self {
721            Value::Primitive(v) => v.to_time_range(),
722            _ => Err(ConvertValueError {
723                requested: "TimeRange",
724                original: self.value_type(),
725                cause: None,
726            }),
727        }
728    }
729
730    /// Retrieve and convert the primitive value into a `DateTimeRange`.
731    ///
732    /// If the value is a primitive, it will be converted into
733    /// a `DateTimeRange` as described in [`PrimitiveValue::to_datetime_range`].
734    ///
735    pub fn to_datetime_range(&self) -> Result<DateTimeRange, ConvertValueError> {
736        match self {
737            Value::Primitive(v) => v.to_datetime_range(),
738            _ => Err(ConvertValueError {
739                requested: "DateTimeRange",
740                original: self.value_type(),
741                cause: None,
742            }),
743        }
744    }
745
746    /// Retrieves the primitive value as a DICOM tag.
747    pub fn to_tag(&self) -> Result<Tag, CastValueError> {
748        match self {
749            Value::Primitive(PrimitiveValue::Tags(v)) => Ok(v[0]),
750            _ => Err(CastValueError {
751                requested: "tag",
752                got: self.value_type(),
753            }),
754        }
755    }
756
757    /// Retrieves the primitive value as a [`PersonName`].
758    pub fn to_person_name(&self) -> Result<PersonName<'_>, ConvertValueError> {
759        match self {
760            Value::Primitive(v) => v.to_person_name(),
761            _ => Err(ConvertValueError {
762                requested: "PersonName",
763                original: self.value_type(),
764                cause: None,
765            }),
766        }
767    }
768}
769
770/// Macro for implementing getters to single and multi-values,
771/// by delegating to `PrimitiveValue`.
772///
773/// Should be placed inside `Value`'s impl block.
774macro_rules! impl_primitive_getters {
775    ($name_single: ident, $name_multi: ident, $variant: ident, $ret: ty) => {
776        /// Get a single value of the requested type.
777        ///
778        /// If it contains multiple values,
779        /// only the first one is returned.
780        /// An error is returned if the variant is not compatible.
781        pub fn $name_single(&self) -> Result<$ret, CastValueError> {
782            match self {
783                Value::Primitive(v) => v.$name_single(),
784                value => Err(CastValueError {
785                    requested: stringify!($name_single),
786                    got: value.value_type(),
787                }),
788            }
789        }
790
791        /// Get a sequence of values of the requested type without copying.
792        ///
793        /// An error is returned if the variant is not compatible.
794        pub fn $name_multi(&self) -> Result<&[$ret], CastValueError> {
795            match self {
796                Value::Primitive(v) => v.$name_multi(),
797                value => Err(CastValueError {
798                    requested: stringify!($name_multi),
799                    got: value.value_type(),
800                }),
801            }
802        }
803    };
804}
805
806impl<I, P> Value<I, P> {
807    /// Get a single string value.
808    ///
809    /// If it contains multiple strings,
810    /// only the first one is returned.
811    ///
812    /// An error is returned if the variant is not compatible.
813    ///
814    /// To enable conversions of other variants to a textual representation,
815    /// see [`to_str()`] instead.
816    ///
817    /// [`to_str()`]: #method.to_str
818    pub fn string(&self) -> Result<&str, CastValueError> {
819        match self {
820            Value::Primitive(v) => v.string(),
821            _ => Err(CastValueError {
822                requested: "string",
823                got: self.value_type(),
824            }),
825        }
826    }
827
828    /// Get the inner sequence of string values
829    /// if the variant is either `Str` or `Strs`.
830    ///
831    /// An error is returned if the variant is not compatible.
832    ///
833    /// To enable conversions of other variants to a textual representation,
834    /// see [`to_str()`] instead.
835    ///
836    /// [`to_str()`]: #method.to_str
837    pub fn strings(&self) -> Result<&[String], CastValueError> {
838        match self {
839            Value::Primitive(v) => v.strings(),
840            _ => Err(CastValueError {
841                requested: "strings",
842                got: self.value_type(),
843            }),
844        }
845    }
846
847    impl_primitive_getters!(tag, tags, Tags, Tag);
848    impl_primitive_getters!(date, dates, Date, DicomDate);
849    impl_primitive_getters!(time, times, Time, DicomTime);
850    impl_primitive_getters!(datetime, datetimes, DateTime, DicomDateTime);
851    impl_primitive_getters!(uint8, uint8_slice, U8, u8);
852    impl_primitive_getters!(uint16, uint16_slice, U16, u16);
853    impl_primitive_getters!(int16, int16_slice, I16, i16);
854    impl_primitive_getters!(uint32, uint32_slice, U32, u32);
855    impl_primitive_getters!(int32, int32_slice, I32, i32);
856    impl_primitive_getters!(int64, int64_slice, I64, i64);
857    impl_primitive_getters!(uint64, uint64_slice, U64, u64);
858    impl_primitive_getters!(float32, float32_slice, F32, f32);
859    impl_primitive_getters!(float64, float64_slice, F64, f64);
860}
861
862impl<I, P> From<PrimitiveValue> for Value<I, P> {
863    fn from(v: PrimitiveValue) -> Self {
864        Value::Primitive(v)
865    }
866}
867
868/// A sequence of complex data set items of type `I`.
869#[derive(Debug, Clone)]
870pub struct DataSetSequence<I> {
871    /// The item sequence.
872    items: C<I>,
873    /// The sequence length in bytes.
874    ///
875    /// The value may be [`UNDEFINED`](Length::UNDEFINED)
876    /// if the length is implicitly defined,
877    /// otherwise it should match the full byte length of all items.
878    length: Length,
879}
880
881impl<I> DataSetSequence<I> {
882    /// Construct a DICOM data sequence
883    /// using a sequence of items and a length.
884    ///
885    /// **Note:** This function does not validate the `length`
886    /// against the items.
887    /// When not sure,
888    /// `length` can be set to [`UNDEFINED`](Length::UNDEFINED)
889    /// to leave it as implicitly defined.
890    #[inline]
891    pub fn new(items: impl Into<C<I>>, length: Length) -> Self {
892        DataSetSequence {
893            items: items.into(),
894            length,
895        }
896    }
897
898    /// Construct an empty DICOM data sequence,
899    /// with the length explicitly defined to zero.
900    #[inline]
901    pub fn empty() -> Self {
902        DataSetSequence {
903            items: Default::default(),
904            length: Length(0),
905        }
906    }
907
908    /// Gets a reference to the items of a sequence.
909    #[inline]
910    pub fn items(&self) -> &[I] {
911        &self.items
912    }
913
914    /// Gets a mutable reference to the items of a sequence.
915    #[inline]
916    pub fn items_mut(&mut self) -> &mut C<I> {
917        &mut self.items
918    }
919
920    /// Obtain the number of items in the sequence.
921    #[inline]
922    pub fn multiplicity(&self) -> u32 {
923        self.items.len() as u32
924    }
925
926    /// Retrieve the sequence of items,
927    /// discarding the recorded length information.
928    #[inline]
929    pub fn into_items(self) -> C<I> {
930        self.items
931    }
932
933    /// Get the value data's length
934    /// as specified by the sequence's data element,
935    /// in bytes.
936    ///
937    /// This is equivalent to [`HasLength::length`].
938    #[inline]
939    pub fn length(&self) -> Length {
940        HasLength::length(self)
941    }
942
943    /// Shorten this sequence by removing trailing data set items
944    /// to fit the given limit.
945    #[inline]
946    pub fn truncate(&mut self, limit: usize) {
947        self.items.truncate(limit);
948    }
949}
950
951impl<I> HasLength for DataSetSequence<I> {
952    #[inline]
953    fn length(&self) -> Length {
954        self.length
955    }
956}
957
958impl<I> DicomValueType for DataSetSequence<I> {
959    #[inline]
960    fn value_type(&self) -> ValueType {
961        ValueType::DataSetSequence
962    }
963
964    #[inline]
965    fn cardinality(&self) -> usize {
966        self.items.len()
967    }
968}
969
970impl<I> From<Vec<I>> for DataSetSequence<I> {
971    /// Converts a vector of items
972    /// into a data set sequence with an undefined length.
973    #[inline]
974    fn from(items: Vec<I>) -> Self {
975        DataSetSequence {
976            items: items.into(),
977            length: Length::UNDEFINED,
978        }
979    }
980}
981
982impl<A, I> From<SmallVec<A>> for DataSetSequence<I>
983where
984    A: smallvec::Array<Item = I>,
985    C<I>: From<SmallVec<A>>,
986{
987    /// Converts a smallvec of items
988    /// into a data set sequence with an undefined length.
989    #[inline]
990    fn from(items: SmallVec<A>) -> Self {
991        DataSetSequence {
992            items: items.into(),
993            length: Length::UNDEFINED,
994        }
995    }
996}
997
998impl<I> From<[I; 1]> for DataSetSequence<I> {
999    /// Constructs a data set sequence with a single item
1000    /// and an undefined length.
1001    #[inline]
1002    fn from([item]: [I; 1]) -> Self {
1003        DataSetSequence {
1004            items: smallvec::smallvec![item],
1005            length: Length::UNDEFINED,
1006        }
1007    }
1008}
1009
1010impl<I, P> From<DataSetSequence<I>> for Value<I, P> {
1011    #[inline]
1012    fn from(value: DataSetSequence<I>) -> Self {
1013        Value::Sequence(value)
1014    }
1015}
1016
1017impl<I> PartialEq<DataSetSequence<I>> for DataSetSequence<I>
1018where
1019    I: PartialEq,
1020{
1021    /// This method tests for `self` and `other` values to be equal,
1022    /// and is used by `==`.
1023    ///
1024    /// This implementation only checks for item equality,
1025    /// disregarding the byte length.
1026    #[inline]
1027    fn eq(&self, other: &DataSetSequence<I>) -> bool {
1028        self.items() == other.items()
1029    }
1030}
1031
1032/// A sequence of pixel data fragments.
1033///
1034/// Each fragment (of data type `P`) is
1035/// an even-lengthed sequence of bytes
1036/// representing the encoded pixel data.
1037/// The first item of the sequence is interpreted as a basic offset table,
1038/// which is defined separately.
1039#[derive(Debug, Clone, PartialEq)]
1040pub struct PixelFragmentSequence<P> {
1041    /// The value contents of the basic offset table.
1042    offset_table: C<u32>,
1043    /// The sequence of pixel data fragments.
1044    fragments: C<P>,
1045}
1046
1047impl<P> PixelFragmentSequence<P> {
1048    /// Construct a DICOM pixel sequence sequence value
1049    /// from a basic offset table and a list of fragments.
1050    ///
1051    /// **Note:** This function does not validate the offset table
1052    /// against the given fragments.
1053    #[inline]
1054    pub fn new(offset_table: impl Into<C<u32>>, fragments: impl Into<C<P>>) -> Self {
1055        PixelFragmentSequence {
1056            offset_table: offset_table.into(),
1057            fragments: fragments.into(),
1058        }
1059    }
1060
1061    /// Construct a DICOM pixel sequence sequence value
1062    /// from a list of fragments,
1063    /// with an empty basic offset table.
1064    #[inline]
1065    pub fn new_fragments(fragments: impl Into<C<P>>) -> Self {
1066        PixelFragmentSequence {
1067            offset_table: Default::default(),
1068            fragments: fragments.into(),
1069        }
1070    }
1071
1072    /// Gets a reference to the pixel data fragments.
1073    ///
1074    /// This sequence does not include the offset table.
1075    #[inline]
1076    pub fn fragments(&self) -> &[P] {
1077        &self.fragments
1078    }
1079
1080    /// Gets a mutable reference to the pixel data fragments.
1081    ///
1082    /// This sequence does not include the offset table.
1083    #[inline]
1084    pub fn fragments_mut(&mut self) -> &mut C<P> {
1085        &mut self.fragments
1086    }
1087
1088    /// Retrieve the pixel data fragments,
1089    /// discarding the rest of the information.
1090    ///
1091    /// This sequence does not include the offset table.
1092    #[inline]
1093    pub fn into_fragments(self) -> C<P> {
1094        self.fragments
1095    }
1096
1097    /// Decompose the sequence into its constituent parts:
1098    /// the basic offset table and the pixel data fragments.
1099    pub fn into_parts(self) -> (C<u32>, C<P>) {
1100        (self.offset_table, self.fragments)
1101    }
1102
1103    /// Gets a reference to the encapsulated pixel data's offset table.
1104    pub fn offset_table(&self) -> &[u32] {
1105        &self.offset_table
1106    }
1107
1108    /// Gets a mutable reference to the encapsulated pixel data's offset table.
1109    pub fn offset_table_mut(&mut self) -> &mut C<u32> {
1110        &mut self.offset_table
1111    }
1112
1113    /// Get the value data's length
1114    /// as specified by the sequence's data element,
1115    /// in bytes.
1116    ///
1117    /// This is equivalent to [`HasLength::length`].
1118    #[inline]
1119    pub fn length(&self) -> Length {
1120        HasLength::length(self)
1121    }
1122
1123    /// Shorten this sequence by removing trailing fragments
1124    /// to fit the given limit.
1125    ///
1126    /// Note that this operations does not affect the basic offset table.
1127    #[inline]
1128    pub fn truncate(&mut self, limit: usize) {
1129        self.fragments.truncate(limit);
1130    }
1131}
1132
1133impl<T, F, P> From<(T, F)> for PixelFragmentSequence<P>
1134where
1135    T: Into<C<u32>>,
1136    F: Into<C<P>>,
1137{
1138    /// Construct a pixel data fragment sequence,
1139    /// interpreting the first tuple element as a basic offset table
1140    /// and the second element as the vector of fragments.
1141    ///
1142    /// **Note:** This function does not validate the offset table
1143    /// against the given fragments.
1144    fn from((offset_table, fragments): (T, F)) -> Self {
1145        PixelFragmentSequence::new(offset_table, fragments)
1146    }
1147}
1148
1149impl<I, P> From<PixelFragmentSequence<P>> for Value<I, P> {
1150    #[inline]
1151    fn from(value: PixelFragmentSequence<P>) -> Self {
1152        Value::PixelSequence(value)
1153    }
1154}
1155
1156impl<P> HasLength for PixelFragmentSequence<P> {
1157    /// In standard DICOM,
1158    /// encapsulated pixel data is always defined by
1159    /// a pixel data element with an undefined length.
1160    #[inline]
1161    fn length(&self) -> Length {
1162        Length::UNDEFINED
1163    }
1164}
1165
1166impl<P> DicomValueType for PixelFragmentSequence<P> {
1167    #[inline]
1168    fn value_type(&self) -> ValueType {
1169        ValueType::PixelSequence
1170    }
1171
1172    #[inline]
1173    fn cardinality(&self) -> usize {
1174        1
1175    }
1176}
1177
1178#[cfg(test)]
1179mod tests {
1180    use super::*;
1181    use crate::dicom_value;
1182    use smallvec::smallvec;
1183
1184    #[test]
1185    fn to_int() {
1186        let value = Value::new(dicom_value!(I32, [1, 2, 5]));
1187        assert_eq!(value.to_int::<u32>().unwrap(), 1);
1188        assert_eq!(value.to_int::<i32>().unwrap(), 1);
1189        assert_eq!(value.to_int::<u16>().unwrap(), 1);
1190        assert_eq!(value.to_int::<i16>().unwrap(), 1);
1191        assert_eq!(value.to_int::<u64>().unwrap(), 1);
1192        assert_eq!(value.to_int::<i64>().unwrap(), 1);
1193
1194        assert_eq!(value.to_multi_int::<i32>().unwrap(), vec![1, 2, 5]);
1195        assert_eq!(value.to_multi_int::<u32>().unwrap(), vec![1, 2, 5]);
1196
1197        // sequence values can't be turned to an int
1198        let value = Value::<EmptyObject, _>::new_sequence(smallvec![], Length::UNDEFINED);
1199
1200        assert!(matches!(
1201            value.to_int::<u32>(),
1202            Err(ConvertValueError {
1203                requested: "integer",
1204                original: ValueType::DataSetSequence,
1205                ..
1206            })
1207        ));
1208    }
1209
1210    #[test]
1211    fn to_float() {
1212        let value = Value::new(dicom_value!(F64, [1., 2., 5.]));
1213        assert_eq!(value.to_float32().unwrap(), 1.);
1214        assert_eq!(value.to_float64().unwrap(), 1.);
1215
1216        assert_eq!(value.to_multi_float32().unwrap(), vec![1., 2., 5.]);
1217        assert_eq!(value.to_multi_float64().unwrap(), vec![1., 2., 5.]);
1218
1219        // sequence values can't be turned to a number
1220        let value = Value::<EmptyObject, _>::new_sequence(smallvec![], Length::UNDEFINED);
1221
1222        assert!(matches!(
1223            value.to_float32(),
1224            Err(ConvertValueError {
1225                requested: "float32",
1226                original: ValueType::DataSetSequence,
1227                ..
1228            })
1229        ));
1230    }
1231
1232    #[test]
1233    fn to_date() {
1234        let expected_dates = [
1235            DicomDate::from_ymd(2021, 2, 3).unwrap(),
1236            DicomDate::from_ymd(2022, 3, 4).unwrap(),
1237            DicomDate::from_ymd(2023, 4, 5).unwrap(),
1238        ];
1239
1240        let value = Value::new(dicom_value!(Strs, ["20210203", "20220304", "20230405"]));
1241        assert_eq!(value.to_date().unwrap(), expected_dates[0],);
1242        assert_eq!(value.to_multi_date().unwrap(), &expected_dates[..]);
1243
1244        let value_pair = Value::new(dicom_value!(
1245            Date,
1246            [
1247                DicomDate::from_ymd(2021, 2, 3).unwrap(),
1248                DicomDate::from_ymd(2022, 3, 4).unwrap(),
1249            ]
1250        ));
1251
1252        assert_eq!(value_pair.to_date().unwrap(), expected_dates[0]);
1253        assert_eq!(value_pair.to_multi_date().unwrap(), &expected_dates[0..2]);
1254
1255        // cannot turn to integers
1256        assert!(matches!(
1257            value_pair.to_multi_int::<i64>(),
1258            Err(ConvertValueError {
1259                requested: "integer",
1260                original: ValueType::Date,
1261                ..
1262            })
1263        ));
1264
1265        let range_value = Value::new(dicom_value!(Str, "20210203-20220304"));
1266
1267        // can turn to range
1268        assert_eq!(
1269            range_value.to_date_range().unwrap(),
1270            DateRange::from_start_to_end(
1271                expected_dates[0].to_naive_date().unwrap(),
1272                expected_dates[1].to_naive_date().unwrap()
1273            )
1274            .unwrap()
1275        );
1276    }
1277
1278    #[test]
1279    fn getters() {
1280        assert_eq!(
1281            Value::new(dicom_value!(Strs, ["Smith^John"]))
1282                .string()
1283                .unwrap(),
1284            "Smith^John"
1285        );
1286
1287        assert_eq!(
1288            Value::new(dicom_value!(Strs, ["Smith^John"]))
1289                .strings()
1290                .unwrap(),
1291            &["Smith^John"]
1292        );
1293
1294        assert_eq!(Value::new(dicom_value!(I32, [1, 2, 5])).int32().unwrap(), 1,);
1295
1296        assert_eq!(
1297            Value::new(dicom_value!(I32, [1, 2, 5]))
1298                .int32_slice()
1299                .unwrap(),
1300            &[1, 2, 5],
1301        );
1302
1303        assert!(matches!(
1304            Value::new(dicom_value!(I32, [1, 2, 5])).uint32(),
1305            Err(CastValueError {
1306                requested: "uint32",
1307                got: ValueType::I32,
1308                ..
1309            })
1310        ));
1311
1312        assert!(matches!(
1313            Value::new(dicom_value!(I32, [1, 2, 5])).strings(),
1314            Err(CastValueError {
1315                requested: "strings",
1316                got: ValueType::I32,
1317                ..
1318            })
1319        ));
1320
1321        assert_eq!(
1322            Value::new(PrimitiveValue::Date(smallvec![DicomDate::from_ymd(
1323                2014, 10, 12
1324            )
1325            .unwrap()]))
1326            .date()
1327            .ok(),
1328            Some(DicomDate::from_ymd(2014, 10, 12).unwrap()),
1329        );
1330
1331        assert_eq!(
1332            Value::new(PrimitiveValue::Date(
1333                smallvec![DicomDate::from_ymd(2014, 10, 12).unwrap(); 5]
1334            ))
1335            .dates()
1336            .unwrap(),
1337            &[DicomDate::from_ymd(2014, 10, 12).unwrap(); 5]
1338        );
1339
1340        assert!(matches!(
1341            Value::new(PrimitiveValue::Date(smallvec![DicomDate::from_ymd(
1342                2014, 10, 12
1343            )
1344            .unwrap()]))
1345            .time(),
1346            Err(CastValueError {
1347                requested: "time",
1348                got: ValueType::Date,
1349                ..
1350            })
1351        ));
1352    }
1353
1354    #[derive(Debug, Clone, Copy, PartialEq)]
1355    struct DummyItem(u32);
1356
1357    impl HasLength for DummyItem {
1358        fn length(&self) -> Length {
1359            Length::defined(8)
1360        }
1361    }
1362
1363    #[test]
1364    fn value_eq() {
1365        // the following declarations are equivalent
1366        let v1 = Value::<_, _>::from(PixelFragmentSequence::new(
1367            smallvec![],
1368            smallvec![vec![1, 2, 5]],
1369        ));
1370        let v2 = Value::new_pixel_sequence(smallvec![], smallvec![vec![1, 2, 5]]);
1371        assert_eq!(v1, v2);
1372        assert_eq!(v2, v1);
1373
1374        // redeclare with different type parameters
1375        let v1 = Value::<DummyItem, _>::from(PixelFragmentSequence::new(
1376            smallvec![],
1377            smallvec![vec![1, 2, 5]],
1378        ));
1379
1380        // declarations are equivalent
1381        let v3 = Value::from(PrimitiveValue::from("Something"));
1382        let v4 = Value::new(dicom_value!(Str, "Something"));
1383        let v3_2: Value = "Something".into();
1384        assert_eq!(v3, v4);
1385        assert_eq!(v3, v3_2);
1386
1387        // redeclare with different type parameters
1388        let v3: Value<DummyItem, _> = PrimitiveValue::from("Something").into();
1389
1390        let v5 = Value::from(DataSetSequence::new(
1391            vec![DummyItem(0), DummyItem(1), DummyItem(2)],
1392            Length::defined(1000),
1393        ));
1394        let v6 = Value::from(DataSetSequence::new(
1395            vec![DummyItem(0), DummyItem(1), DummyItem(2)],
1396            Length::UNDEFINED,
1397        ));
1398        assert_eq!(v5, v6);
1399
1400        assert_ne!(v1, v3);
1401        assert_ne!(v3, v1);
1402        assert_ne!(v1, v6);
1403        assert_ne!(v6, v1);
1404        assert_ne!(v3, v6);
1405        assert_ne!(v6, v3);
1406    }
1407
1408    #[test]
1409    fn data_set_sequences() {
1410        let v = DataSetSequence::new(
1411            vec![DummyItem(1), DummyItem(2), DummyItem(5)],
1412            Length::defined(24),
1413        );
1414
1415        assert_eq!(v.cardinality(), 3);
1416        assert_eq!(v.value_type(), ValueType::DataSetSequence);
1417        assert_eq!(v.items(), &[DummyItem(1), DummyItem(2), DummyItem(5)]);
1418        assert_eq!(v.length(), Length(24));
1419
1420        let v = Value::<_, [u8; 0]>::from(v);
1421        assert_eq!(v.value_type(), ValueType::DataSetSequence);
1422        assert_eq!(v.cardinality(), 3);
1423        assert_eq!(
1424            v.items(),
1425            Some(&[DummyItem(1), DummyItem(2), DummyItem(5)][..])
1426        );
1427        assert_eq!(v.primitive(), None);
1428        assert_eq!(v.fragments(), None);
1429        assert_eq!(v.offset_table(), None);
1430        assert_eq!(v.length(), Length(24));
1431
1432        // can't turn sequence to string
1433        assert!(matches!(
1434            v.to_str(),
1435            Err(ConvertValueError {
1436                original: ValueType::DataSetSequence,
1437                ..
1438            })
1439        ));
1440        // can't turn sequence to bytes
1441        assert!(matches!(
1442            v.to_bytes(),
1443            Err(ConvertValueError {
1444                requested: "bytes",
1445                original: ValueType::DataSetSequence,
1446                ..
1447            })
1448        ));
1449
1450        // can turn into items
1451        let items = v.into_items().unwrap();
1452        assert_eq!(&items[..], &[DummyItem(1), DummyItem(2), DummyItem(5)][..]);
1453    }
1454
1455    #[test]
1456    fn pixel_fragment_sequences() {
1457        let v = PixelFragmentSequence::new(vec![], vec![vec![0x55; 128]]);
1458
1459        assert_eq!(v.cardinality(), 1);
1460        assert_eq!(v.value_type(), ValueType::PixelSequence);
1461        assert_eq!(v.fragments(), &[vec![0x55; 128]]);
1462        assert!(HasLength::length(&v).is_undefined());
1463
1464        let v = Value::<EmptyObject, _>::from(v);
1465        assert_eq!(v.cardinality(), 1);
1466        assert_eq!(v.value_type(), ValueType::PixelSequence);
1467        assert_eq!(v.items(), None);
1468        assert_eq!(v.primitive(), None);
1469        assert_eq!(v.fragments(), Some(&[vec![0x55; 128]][..]));
1470        assert_eq!(v.offset_table(), Some(&[][..]));
1471        assert!(HasLength::length(&v).is_undefined());
1472
1473        // can't turn sequence to string
1474        assert!(matches!(
1475            v.to_str(),
1476            Err(ConvertValueError {
1477                requested: "string",
1478                original: ValueType::PixelSequence,
1479                ..
1480            })
1481        ));
1482
1483        // can't turn sequence to bytes
1484        assert!(matches!(
1485            v.to_bytes(),
1486            Err(ConvertValueError {
1487                requested: "bytes",
1488                original: ValueType::PixelSequence,
1489                ..
1490            })
1491        ));
1492
1493        // can turn into fragments
1494        let fragments = v.into_fragments().unwrap();
1495        assert_eq!(&fragments[..], &[vec![0x55; 128]]);
1496    }
1497}