Skip to main content

dicom_encoding/decode/
explicit_be.rs

1//! Explicit VR Big Endian syntax transfer implementation.
2
3use crate::decode::basic::BigEndianBasicDecoder;
4use crate::decode::{
5    BadSequenceHeaderSnafu, BasicDecode, Decode, DecodeFrom, ReadHeaderTagSnafu,
6    ReadItemHeaderSnafu, ReadItemLengthSnafu, ReadLengthSnafu, ReadReservedSnafu, ReadTagSnafu,
7    ReadVrSnafu, Result,
8};
9use byteordered::byteorder::{BigEndian, ByteOrder};
10use dicom_core::header::{DataElementHeader, Length, SequenceItemHeader};
11use dicom_core::{Tag, VR};
12use snafu::ResultExt;
13use std::io::Read;
14
15/// A data element decoder for the Explicit VR Big Endian transfer syntax.
16#[derive(Debug, Default, Clone)]
17pub struct ExplicitVRBigEndianDecoder {
18    basic: BigEndianBasicDecoder,
19}
20
21impl Decode for ExplicitVRBigEndianDecoder {
22    fn decode_header<S>(&self, mut source: &mut S) -> Result<(DataElementHeader, usize)>
23    where
24        S: ?Sized + Read,
25    {
26        // retrieve tag
27        let Tag(group, element) = self
28            .basic
29            .decode_tag(&mut source)
30            .context(ReadHeaderTagSnafu)?;
31
32        let mut buf = [0u8; 4];
33        if group == 0xFFFE {
34            // item delimiters do not have VR or reserved field
35            source.read_exact(&mut buf).context(ReadItemLengthSnafu)?;
36            let len = BigEndian::read_u32(&buf);
37            return Ok((
38                DataElementHeader::new((group, element), VR::UN, Length(len)),
39                8, // tag + len
40            ));
41        }
42
43        // retrieve explicit VR
44        source.read_exact(&mut buf[0..2]).context(ReadVrSnafu)?;
45        let vr = VR::from_binary([buf[0], buf[1]]).unwrap_or(VR::UN);
46
47        let bytes_read;
48
49        // retrieve data length
50        let len = match vr {
51            // PS3.5 7.1.2:
52            // for VRs of AE, AS, AT, CS, DA, DS, DT, FL, FD, IS, LO, LT, PN,
53            // SH, SL, SS, ST, TM, UI, UL and US the Value Length Field is the
54            // 16-bit unsigned integer following the two byte VR Field (Table
55            // 7.1-2). The value of the Value Length Field shall equal the
56            // length of the Value Field.
57            VR::AE
58            | VR::AS
59            | VR::AT
60            | VR::CS
61            | VR::DA
62            | VR::DS
63            | VR::DT
64            | VR::FL
65            | VR::FD
66            | VR::IS
67            | VR::LO
68            | VR::LT
69            | VR::PN
70            | VR::SH
71            | VR::SL
72            | VR::SS
73            | VR::ST
74            | VR::TM
75            | VR::UI
76            | VR::UL
77            | VR::US => {
78                // read 2 bytes for the data length
79                source
80                    .read_exact(&mut buf[0..2])
81                    .context(ReadItemLengthSnafu)?;
82                bytes_read = 8;
83                u32::from(BigEndian::read_u16(&buf[0..2]))
84            }
85            // PS3.5 7.1.2:
86            // for all other VRs the 16 bits following the two byte VR Field
87            // are reserved for use by later versions of the DICOM Standard.
88            // These reserved bytes shall be set to 0000H and shall not be
89            // used or decoded (Table 7.1-1). The Value Length Field is a
90            // 32-bit unsigned integer.
91            _ => {
92                // read 2 reserved bytes, then 4 bytes for data length
93                source
94                    .read_exact(&mut buf[0..2])
95                    .context(ReadReservedSnafu)?;
96                source.read_exact(&mut buf).context(ReadLengthSnafu)?;
97                bytes_read = 12;
98                BigEndian::read_u32(&buf)
99            }
100        };
101
102        Ok((
103            DataElementHeader::new((group, element), vr, Length(len)),
104            bytes_read,
105        ))
106    }
107
108    fn decode_item_header<S>(&self, source: &mut S) -> Result<SequenceItemHeader>
109    where
110        S: ?Sized + Read,
111    {
112        let mut buf = [0u8; 8];
113        source.read_exact(&mut buf).context(ReadItemHeaderSnafu)?;
114        // retrieve tag
115        let group = BigEndian::read_u16(&buf[0..2]);
116        let element = BigEndian::read_u16(&buf[2..4]);
117        let len = BigEndian::read_u32(&buf[4..8]);
118
119        SequenceItemHeader::new((group, element), Length(len)).context(BadSequenceHeaderSnafu)
120    }
121
122    fn decode_tag<S>(&self, source: &mut S) -> Result<Tag>
123    where
124        S: ?Sized + Read,
125    {
126        let mut buf = [0u8; 4];
127        source.read_exact(&mut buf).context(ReadTagSnafu)?;
128        Ok(Tag(
129            BigEndian::read_u16(&buf[0..2]),
130            BigEndian::read_u16(&buf[2..4]),
131        ))
132    }
133}
134
135impl<S: ?Sized> DecodeFrom<S> for ExplicitVRBigEndianDecoder
136where
137    S: Read,
138{
139    #[inline]
140    fn decode_header(&self, source: &mut S) -> Result<(DataElementHeader, usize)> {
141        Decode::decode_header(self, source)
142    }
143
144    #[inline]
145    fn decode_item_header(&self, source: &mut S) -> Result<SequenceItemHeader> {
146        Decode::decode_item_header(self, source)
147    }
148
149    #[inline]
150    fn decode_tag(&self, source: &mut S) -> Result<Tag> {
151        Decode::decode_tag(self, source)
152    }
153}
154
155#[cfg(test)]
156mod tests {
157    use super::ExplicitVRBigEndianDecoder;
158    use crate::decode::Decode;
159    use dicom_core::header::{HasLength, Header, Length};
160    use dicom_core::{Tag, VR};
161    use std::io::{Cursor, Seek, SeekFrom};
162
163    // manually crafting some DICOM data elements
164    #[rustfmt::skip]
165    const RAW: &[u8] = &[
166        0x00, 0x02, 0x00, 0x02,     // (0002,0002) (BE) Media Storage SOP Class UID
167            b'U', b'I',             // VR: UI (UID)
168            0x00, 0x1A,             // Length: 26 bytes (BE)
169                // UID: 1.2.840.10008.5.1.4.1.1.1
170                b'1', b'.', b'2', b'.', b'8', b'4', b'0', b'.', b'1', b'0', b'0', b'0', b'8', b'.',
171                b'5', b'.', b'1', b'.', b'4', b'.', b'1', b'.', b'1', b'.', b'1',
172                0x00,               // Padding to make length even
173        0x00, 0x02, 0x00, 0x10,     // (0002,0010) (BE) Transfer Syntax UID
174            b'U', b'I',             // VR: UI (UID)
175            0x00, 0x14,             // Length: 20 bytes (BE)
176                // UID: 1.2.840.10008.1.2.1 (ExplicitVRLittleEndian)
177                b'1', b'.', b'2', b'.', b'8', b'4', b'0', b'.', b'1', b'0', b'0', b'0', b'8', b'.',
178                b'1', b'.', b'2', b'.', b'1',
179                0x00,               // Padding to make length even
180        0x00, 0x08, 0x00, 0x54,     // (0008,0054) (BE) Retrieve AE Title
181            b'A', b'E',             // VR: AE (Application Entity)
182            0x00, 0x06,             // Length: 6 bytes (BE)
183                // String "TITLE"
184                b'T', b'I', b'T', b'L', b'E',
185                b' ',               // Padding to make length even
186        0x00, 0x10, 0x10, 0x10,     // (0010,1010) (BE) Patient's Age
187            b'A', b'S',             // VR: AS (Age String)
188            0x00, 0x02,             // Length: 2 bytes (BE)
189                // String "8Y"
190                b'8', b'Y',
191        0x00, 0x72, 0x00, 0x26,     // (0072,0026) (BE) Selector Attribute
192            b'A', b'T',             // VR: AT (Attribute Tag)
193            0x00, 0x04,             // Length: 4 bytes (BE)
194                // Tag: (0028,2110) (BE) Lossy Image Compression
195                0x00, 0x28, 0x21, 0x10,
196        0x00, 0x10, 0x00, 0x40,     // (0010,0040) (BE) Patient Sex
197            b'C', b'S',             // VR: CS (Code String)
198            0x00, 0x02,             // Length: 2 bytes (BE)
199                // Text: "O"
200                b'O',
201                b' ',               // Padding to make length even
202        0x00, 0x10, 0x00, 0x30,     // (0010,0030) (BE) Patient's Birth Date
203            b'D', b'A',             // VR: DA (Date)
204            0x00, 0x08,             // Length: 8 bytes (BE)
205                // String "19800101"
206                b'1', b'9', b'8', b'0', b'0', b'1', b'0', b'1',
207        0x00, 0x10, 0x10, 0x20,     // (0010,1020) (BE) Patient's size
208            b'D', b'S',             // VR: DS (Decimal String)
209            0x00, 0x04,             // Length: 4 bytes (BE)
210                // String: "1.70"
211                b'1', b'.', b'7', b'0',
212        0x00, 0x08, 0x00, 0x15,     // (0008,0015) (BE) Instance coercion datetime
213            b'D', b'T',             // VR: DT (Date Time)
214            0x00, 0x0E,             // Length: 14 bytes (BE)
215                // String "20051231235960"
216                b'2', b'0', b'0', b'5', b'1', b'2', b'3', b'1', b'2', b'3', b'5', b'9', b'6', b'0',
217        0x00, 0x10, 0x94, 0x31,     // (0010,9431) (BE) Examined Body Thickness
218            b'F', b'L',             // VR: FL (Floating-point IEEE-754)
219            0x00, 0x04,             // Length: 4 bytes (BE)
220                // Value: 3.1415927 (BE)
221                0x40, 0x49, 0x0F, 0xDB,
222        0x00, 0x40, 0x92, 0x25,     // (0040,9225) (BE) Real World Value Slope
223            b'F', b'D',             // VR: FD (Double-precision floating-point IEEE-754)
224            0x00, 0x08,             // Length: 8 bytes (BE)
225                // Value: 3.141592653589793 (BE)
226                0x40, 0x09, 0x21, 0xFB, 0x54, 0x44, 0x2D, 0x18,
227        0x00, 0x20, 0x00, 0x13,     // (0020,0013) (BE) Instance Number
228            b'I', b'S',             // VR: IS (Integer String)
229            0x00, 0x08,             // Length: 8 bytes (BE)
230                // String: "1234567"
231                b'1', b'2', b'3', b'4', b'5', b'6', b'7',
232                b' ',               // Padding to make length even
233        0x00, 0x10, 0x00, 0x20,     // (0010,0020) (BE) Patient ID
234            b'L', b'O',             // VR: LO (Long string)
235            0x00, 0x0A,             // Length: 10 bytes (BE)
236                // String "P12345678X"
237                b'P', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'X',
238        0x00, 0x10, 0x40, 0x00,     // (0010,4000) (BE) Patient Comments
239            b'L', b'T',             // VR: LT (Long Text)
240            0x00, 0x04,             // Length: 4 bytes (BE)
241                // String "None"
242                b'N', b'o', b'n', b'e',
243        0x00, 0x08, 0x04, 0x1B,     // (0008,041B) (BE) RecordKey
244            b'O', b'B',             // VR: OB (Other Byte)
245            0x00, 0x00,             // Reserved, always 0
246            0x00, 0x00, 0x00, 0x02, // Length: 2 bytes (BE)
247                // Value: [0x12, 0x34]
248                0x12, 0x34,
249        0x7F, 0xE0, 0x00, 0x09,     // (7FE0,0009) (BE) Double Float Pixel Data
250            b'O', b'D',             // VR: OD (Other Double)
251            0x00, 0x00,             // Reserved, always 0
252            0x00, 0x00, 0x00, 0x08, // Length: 8 bytes (BE)
253                // Value: [3.141592653589793] (BE)
254                0x40, 0x09, 0x21, 0xFB, 0x54, 0x44, 0x2D, 0x18,
255        0x7F, 0xE0, 0x00, 0x08,     // (7FE0,0008) (BE) Float Pixel Data
256            b'O', b'F',             // VR: OF (Other Float)
257            0x00, 0x00,             // Reserved, always 0
258            0x00, 0x00, 0x00, 0x04, // Length: 4 bytes (BE)
259                // Value: [3.1415927] (BE)
260                0x40, 0x49, 0x0F, 0xDB,
261        0x00, 0x72, 0x00, 0x75,     // (0072,0075) (BE) Selector OL Value
262            b'O', b'L',             // VR: OL (Other Long)
263            0x00, 0x00,             // Reserved, always 0
264            0x00, 0x00, 0x00, 0x04, // Length: 4 bytes (BE)
265                // Value: [0x12345678] (BE)
266                0x12, 0x34, 0x56, 0x78,
267        0x00, 0x72, 0x00, 0x81,     // (0072,0081) (BE) Selector OV Value
268            b'O', b'V',             // VR: OV (Other Very long)
269            0x00, 0x00,             // Reserved, always 0
270            0x00, 0x00, 0x00, 0x08, // Length: 8 bytes (BE)
271                // Value: [0x192A3B4C5D6E7F80] (BE)
272                0x19, 0x2A, 0x3B, 0x4C, 0x5D, 0x6E, 0x7F, 0x80,
273        0x00, 0x72, 0x00, 0x69,     // (0072,0069) (BE) Selector OW Value
274            b'O', b'W',             // VR: OW (Other Word)
275            0x00, 0x00,             // Reserved, always 0
276            0x00, 0x00, 0x00, 0x02, // Length: 2 bytes (BE)
277                // Value: [0x1234] (BE)
278                0x12, 0x34,
279        0x00, 0x10, 0x00, 0x10,     // (0010,0010) (BE) Patient Name
280            b'P', b'N',             // VR: PN (Person Name)
281            0x00, 0x08,             // Length: 8 bytes (BE)
282                // String: "Doe^John"
283                b'D', b'o', b'e', b'^', b'J', b'o', b'h', b'n',
284        0x00, 0x40, 0x92, 0x10,     // (0040,9210) (BE) LUT Label
285            b'S', b'H',             // VR: SH (Short string)
286            0x00, 0x04,             // Length: 4 bytes (BE)
287                // String: "LBL"
288                b'L', b'B', b'L',
289                b' ',               // Padding to make length even
290        0x00, 0x18, 0x60, 0x20,     // (0018,6020) (BE) Reference Pixel X0
291            b'S', b'L',             // VR: SL (Signed Long)
292            0x00, 0x04,             // Length: 4 bytes (BE)
293                // Value: -12345678 (BE)
294                0xFF, 0x43, 0x9E, 0xB2,
295        // Sequences (VR: SQ) tested elsewhere
296        0x00, 0x28, 0x95, 0x03,     // (0028,9503) (BE) Vertices of the Region (VM 2-2n)
297            b'S', b'S',             // VR: SS (Signed Short)
298            0x00, 0x04,             // Length: 4 bytes (2 * 2) (BE)
299                // Value: -4567 (BE)
300                0xEE, 0x29,
301                // Value: 4321 (BE)
302                0x10, 0xE1,
303        0x00, 0x40, 0x02, 0x80,     // (0040,0280) (BE) Comments on the Performed Procedure Step
304            b'S', b'T',             // VR: ST (Short Text)
305            0x00, 0x0A,             // Length: 10 bytes (BE)
306                // String: "No comment"
307                b'N', b'o', b' ', b'c', b'o', b'm', b'm', b'e', b'n', b't',
308        0x00, 0x72, 0x00, 0x82,     // (0072,0082) (BE) SelectorSVValue (VM: 1-n)
309            b'S', b'V',             // VR: SV (Signed Very long)
310            0x00, 0x00,             // Reserved, always 0
311            0x00, 0x00, 0x00, 0x10, // Length: 16 bytes (2 * 8) (BE)
312                // Value: -123456789012345678 (BE)
313                0xFE, 0x49, 0x64, 0xB4, 0x59, 0xCF, 0x0C, 0xB2,
314                // Value: 123456789012345678 (BE)
315                0x01, 0xB6, 0x9B, 0x4B, 0xA6, 0x30, 0xF3, 0x4E,
316        0x00, 0x10, 0x00, 0x32,     // (0010,0032) (BE) Patient's Birth Time
317            b'T', b'M',             // VR: TM (Time)
318            0x00, 0x06,             // Length: 6 bytes (BE)
319                // String: "123456"
320                b'1', b'2', b'3', b'4', b'5', b'6',
321        0x00, 0x08, 0x01, 0x19,     // (0008,0119) (BE) Long Code Value
322            b'U', b'C',             // VR: UC (Unlimited Characters)
323            0x00, 0x00,             // Reserved, always 0
324            0x00, 0x00, 0x00, 0x04, // Length: 4 bytes (BE)
325                // String: "Code"
326                b'C', b'o', b'd', b'e',
327        // UI already tested above
328        0x00, 0x18, 0x60, 0x16,     // (0018,6016) (BE) Region Flags
329            b'U', b'L',
330            0x00, 0x04,             // Length: 4 bytes (BE)
331                // Value: 1 (BE)
332                0x00, 0x00, 0x00, 0x01,
333        0xC0, 0x01, 0x12, 0x34,     // (C001,1234) (BE) (Private data element)
334            b'U', b'N',             // VR: UN (Unknown)
335            0x00, 0x00,             // Reserved, always 0
336            0x00, 0x00, 0x00, 0x06, // Length: 6 bytes (BE)
337                // Value: [0x01, 0x02, 0x03, 0x04, 0x05, 0x06]
338                0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
339        0x00, 0x08, 0x01, 0x0E,     // (0008,010E) (BE) Coding Scheme URL
340            b'U', b'R',             // VR: UR (Universal Resource Locator, URL)
341            0x00, 0x00,             // Reserved, always 0
342            0x00, 0x00, 0x00, 0x12, // Length: 18 bytes (BE)
343                // String: "http://example.com"
344                b'h', b't', b't', b'p', b':', b'/', b'/', b'e', b'x', b'a', b'm', b'p', b'l', b'e',
345                b'.', b'c', b'o', b'm',
346        0x00, 0x08, 0x00, 0x40,     // (0008,0040) (BE) Data Set Type
347            b'U', b'S',             // VR: US (Unsigned Short)
348            0x00, 0x02,             // Length: 2 bytes (BE)
349                // Value: 34567 (BE)
350                0x87, 0x07,
351        0x00, 0x18, 0x99, 0x17,     // (0018,9917) (BE) Instruction Description
352            b'U', b'T',             // VR: UT (Unlimited Text)
353            0x00, 0x00,             // Reserved, always 0
354            0x00, 0x00, 0x00, 0x08, // Length: 8 bytes (BE)
355                // String: "No text"
356                b'N', b'o', b' ', b't', b'e', b'x', b't',
357                b' ',               // Padding to make length even
358        0x00, 0x08, 0x04, 0x0C,     // (0008,040C) (BE) File Offset in Container
359            b'U', b'V',             // VR: UV (Unsigned Very long)
360            0x00, 0x00,             // Reserved, always 0
361            0x00, 0x00, 0x00, 0x08, // Length: 8 bytes (BE)
362                // Value: 12345678901234567890 (BE)
363                0xAB, 0x54, 0xA9, 0x8C, 0xEB, 0x1F, 0x0A, 0xD2,
364    ];
365
366    #[test]
367    fn decode_explicit_vr_be() {
368        let dec = ExplicitVRBigEndianDecoder::default();
369        let mut cursor = Cursor::new(RAW.as_ref());
370
371        fn read_n<'a>(cursor: &mut Cursor<&'a [u8]>, n: usize) -> &'a [u8] {
372            let pos = cursor.position() as usize;
373            let slice = &cursor.get_ref()[pos..pos + n]; // panic if too short
374            cursor.set_position((pos + n) as u64);
375            slice
376        }
377
378        fn test_vr(
379            dec: &ExplicitVRBigEndianDecoder,
380            cursor: &mut Cursor<&[u8]>,
381            group: u16,
382            element: u16,
383            vr: VR,
384            value: &[u8],
385        ) {
386            let (elem, _bytes_read) = dec.decode_header(cursor).expect("should find an element");
387            assert_eq!(elem.tag(), Tag(group, element));
388            assert_eq!(elem.vr(), vr);
389            assert_eq!(elem.length(), Length(value.len() as u32));
390            let buffer = read_n(cursor, value.len());
391            assert_eq!(&buffer, &value);
392        }
393
394        // read first element
395        let (elem, bytes_read) = dec
396            .decode_header(&mut cursor)
397            .expect("should find an element");
398        assert_eq!(elem.tag(), Tag(0x0002, 0x0002));
399        assert_eq!(elem.vr(), VR::UI);
400        assert_eq!(elem.length(), Length(26));
401        assert_eq!(bytes_read, 8);
402        // read only half of the value data
403        let buffer = read_n(&mut cursor, 13);
404        assert_eq!(&buffer, b"1.2.840.10008");
405
406        // cursor should now be @ #21 (there is no automatic skipping)
407        assert_eq!(cursor.stream_position().unwrap(), 21);
408        // cursor should now be @ #34 after skipping
409        assert_eq!(cursor.seek(SeekFrom::Current(13)).unwrap(), 34);
410
411        // read second element
412        let (elem, _bytes_read) = dec
413            .decode_header(&mut cursor)
414            .expect("should find an element");
415        assert_eq!(elem.tag(), Tag(2, 16));
416        assert_eq!(elem.vr(), VR::UI);
417        assert_eq!(elem.length(), Length(20));
418        // read all data
419        let buffer = read_n(&mut cursor, 20);
420        assert_eq!(&buffer, b"1.2.840.10008.1.2.1\0");
421
422        // read various VRs
423        test_vr(&dec, &mut cursor, 0x0008, 0x0054, VR::AE, b"TITLE ");
424        test_vr(&dec, &mut cursor, 0x0010, 0x1010, VR::AS, b"8Y");
425        test_vr(
426            &dec,
427            &mut cursor,
428            0x0072,
429            0x0026,
430            VR::AT,
431            &[0x00, 0x28, 0x21, 0x10],
432        );
433        test_vr(&dec, &mut cursor, 0x0010, 0x0040, VR::CS, b"O ");
434        test_vr(&dec, &mut cursor, 0x0010, 0x0030, VR::DA, b"19800101");
435        test_vr(&dec, &mut cursor, 0x0010, 0x1020, VR::DS, b"1.70");
436        test_vr(
437            &dec,
438            &mut cursor,
439            0x0008,
440            0x0015,
441            VR::DT,
442            b"20051231235960",
443        );
444        test_vr(
445            &dec,
446            &mut cursor,
447            0x0010,
448            0x9431,
449            VR::FL,
450            &[0x40, 0x49, 0x0F, 0xDB],
451        );
452        test_vr(
453            &dec,
454            &mut cursor,
455            0x0040,
456            0x9225,
457            VR::FD,
458            &[0x40, 0x09, 0x21, 0xFB, 0x54, 0x44, 0x2D, 0x18],
459        );
460        test_vr(&dec, &mut cursor, 0x0020, 0x0013, VR::IS, b"1234567 ");
461        test_vr(&dec, &mut cursor, 0x0010, 0x0020, VR::LO, b"P12345678X");
462        test_vr(&dec, &mut cursor, 0x0010, 0x4000, VR::LT, b"None");
463        test_vr(&dec, &mut cursor, 0x0008, 0x041B, VR::OB, &[0x12, 0x34]);
464        test_vr(
465            &dec,
466            &mut cursor,
467            0x7FE0,
468            0x0009,
469            VR::OD,
470            &[0x40, 0x09, 0x21, 0xFB, 0x54, 0x44, 0x2D, 0x18],
471        );
472        test_vr(
473            &dec,
474            &mut cursor,
475            0x7FE0,
476            0x0008,
477            VR::OF,
478            &[0x40, 0x49, 0x0F, 0xDB],
479        );
480        test_vr(
481            &dec,
482            &mut cursor,
483            0x0072,
484            0x0075,
485            VR::OL,
486            &[0x12, 0x34, 0x56, 0x78],
487        );
488        test_vr(
489            &dec,
490            &mut cursor,
491            0x0072,
492            0x0081,
493            VR::OV,
494            &[0x19, 0x2A, 0x3B, 0x4C, 0x5D, 0x6E, 0x7F, 0x80],
495        );
496        test_vr(&dec, &mut cursor, 0x0072, 0x0069, VR::OW, &[0x12, 0x34]);
497        test_vr(&dec, &mut cursor, 0x0010, 0x0010, VR::PN, b"Doe^John");
498        test_vr(&dec, &mut cursor, 0x0040, 0x9210, VR::SH, b"LBL ");
499        test_vr(
500            &dec,
501            &mut cursor,
502            0x0018,
503            0x6020,
504            VR::SL,
505            &[0xFF, 0x43, 0x9E, 0xB2],
506        );
507        test_vr(
508            &dec,
509            &mut cursor,
510            0x0028,
511            0x9503,
512            VR::SS,
513            &[0xEE, 0x29, 0x10, 0xE1],
514        );
515        test_vr(&dec, &mut cursor, 0x0040, 0x0280, VR::ST, b"No comment");
516        test_vr(
517            &dec,
518            &mut cursor,
519            0x0072,
520            0x0082,
521            VR::SV,
522            &[
523                0xFE, 0x49, 0x64, 0xB4, 0x59, 0xCF, 0x0C, 0xB2, 0x01, 0xB6, 0x9B, 0x4B, 0xA6, 0x30,
524                0xF3, 0x4E,
525            ],
526        );
527        test_vr(&dec, &mut cursor, 0x0010, 0x0032, VR::TM, b"123456");
528        test_vr(&dec, &mut cursor, 0x0008, 0x0119, VR::UC, b"Code");
529        test_vr(
530            &dec,
531            &mut cursor,
532            0x0018,
533            0x6016,
534            VR::UL,
535            &[0x00, 0x00, 0x00, 0x01],
536        );
537        test_vr(
538            &dec,
539            &mut cursor,
540            0xC001,
541            0x1234,
542            VR::UN,
543            &[0x1, 0x2, 0x3, 0x4, 0x5, 0x6],
544        );
545        test_vr(
546            &dec,
547            &mut cursor,
548            0x0008,
549            0x010E,
550            VR::UR,
551            b"http://example.com",
552        );
553        test_vr(&dec, &mut cursor, 0x0008, 0x0040, VR::US, &[0x87, 0x07]);
554        test_vr(&dec, &mut cursor, 0x0018, 0x9917, VR::UT, b"No text ");
555        test_vr(
556            &dec,
557            &mut cursor,
558            0x0008,
559            0x040C,
560            VR::UV,
561            &[0xAB, 0x54, 0xA9, 0x8C, 0xEB, 0x1F, 0x0A, 0xD2],
562        );
563    }
564
565    // manually crafting some DICOM sequence/item delimiters
566    //  Tag: (0008,103F) Series Description Code Sequence
567    //  VR: SQ
568    //  Reserved bytes: 0x0000
569    //  Length: 0xFFFF_FFFF
570    // --
571    //  Tag: (FFFE,E000) Item
572    //  Length: 0xFFFF_FFFF (unspecified)
573    // --
574    //  Tag: (FFFE,E00D) Item Delimitation Item
575    //  Length: 0
576    // --
577    //  Tag: (FFFE,E0DD) Sequence Delimitation Item
578    //  Length: 0
579    // --
580    const RAW_SEQUENCE_ITEMS: &[u8] = &[
581        0x00, 0x08, 0x10, 0x3F, b'S', b'Q', 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xE0,
582        0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xE0, 0x0D, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE,
583        0xE0, 0xDD, 0x00, 0x00, 0x00, 0x00,
584    ];
585
586    #[test]
587    fn decode_items() {
588        let dec = ExplicitVRBigEndianDecoder::default();
589        let mut cursor = Cursor::new(RAW_SEQUENCE_ITEMS);
590        {
591            // read first element
592            let (elem, _bytes_read) = dec
593                .decode_header(&mut cursor)
594                .expect("should find an element header");
595            assert_eq!(elem.tag(), Tag(8, 0x103F));
596            assert_eq!(elem.vr(), VR::SQ);
597            assert!(elem.length().is_undefined());
598        }
599        // cursor should now be @ #12
600        assert_eq!(cursor.stream_position().unwrap(), 12);
601        {
602            let elem = dec
603                .decode_item_header(&mut cursor)
604                .expect("should find an item header");
605            assert!(elem.is_item());
606            assert_eq!(elem.tag(), Tag(0xFFFE, 0xE000));
607            assert!(elem.length().is_undefined());
608        }
609        // cursor should now be @ #20
610        assert_eq!(cursor.stream_position().unwrap(), 20);
611        {
612            let elem = dec
613                .decode_item_header(&mut cursor)
614                .expect("should find an item header");
615            assert!(elem.is_item_delimiter());
616            assert_eq!(elem.tag(), Tag(0xFFFE, 0xE00D));
617            assert_eq!(elem.length(), Length(0));
618        }
619        // cursor should now be @ #28
620        assert_eq!(cursor.stream_position().unwrap(), 28);
621        {
622            let elem = dec
623                .decode_item_header(&mut cursor)
624                .expect("should find an item header");
625            assert!(elem.is_sequence_delimiter());
626            assert_eq!(elem.tag(), Tag(0xFFFE, 0xE0DD));
627            assert_eq!(elem.length(), Length(0));
628        }
629    }
630}