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(&dec, &mut cursor, 0x0008, 0x0015, VR::DT, b"20051231235960");
437        test_vr(
438            &dec,
439            &mut cursor,
440            0x0010,
441            0x9431,
442            VR::FL,
443            &[0x40, 0x49, 0x0F, 0xDB],
444        );
445        test_vr(
446            &dec,
447            &mut cursor,
448            0x0040,
449            0x9225,
450            VR::FD,
451            &[0x40, 0x09, 0x21, 0xFB, 0x54, 0x44, 0x2D, 0x18],
452        );
453        test_vr(&dec, &mut cursor, 0x0020, 0x0013, VR::IS, b"1234567 ");
454        test_vr(&dec, &mut cursor, 0x0010, 0x0020, VR::LO, b"P12345678X");
455        test_vr(&dec, &mut cursor, 0x0010, 0x4000, VR::LT, b"None");
456        test_vr(&dec, &mut cursor, 0x0008, 0x041B, VR::OB, &[0x12, 0x34]);
457        test_vr(
458            &dec,
459            &mut cursor,
460            0x7FE0,
461            0x0009,
462            VR::OD,
463            &[0x40, 0x09, 0x21, 0xFB, 0x54, 0x44, 0x2D, 0x18],
464        );
465        test_vr(
466            &dec,
467            &mut cursor,
468            0x7FE0,
469            0x0008,
470            VR::OF,
471            &[0x40, 0x49, 0x0F, 0xDB],
472        );
473        test_vr(
474            &dec,
475            &mut cursor,
476            0x0072,
477            0x0075,
478            VR::OL,
479            &[0x12, 0x34, 0x56, 0x78],
480        );
481        test_vr(
482            &dec,
483            &mut cursor,
484            0x0072,
485            0x0081,
486            VR::OV,
487            &[0x19, 0x2A, 0x3B, 0x4C, 0x5D, 0x6E, 0x7F, 0x80],
488        );
489        test_vr(&dec, &mut cursor, 0x0072, 0x0069, VR::OW, &[0x12, 0x34]);
490        test_vr(&dec, &mut cursor, 0x0010, 0x0010, VR::PN, b"Doe^John");
491        test_vr(&dec, &mut cursor, 0x0040, 0x9210, VR::SH, b"LBL ");
492        test_vr(
493            &dec,
494            &mut cursor,
495            0x0018,
496            0x6020,
497            VR::SL,
498            &[0xFF, 0x43, 0x9E, 0xB2],
499        );
500        test_vr(
501            &dec,
502            &mut cursor,
503            0x0028,
504            0x9503,
505            VR::SS,
506            &[0xEE, 0x29, 0x10, 0xE1],
507        );
508        test_vr(&dec, &mut cursor, 0x0040, 0x0280, VR::ST, b"No comment");
509        test_vr(
510            &dec,
511            &mut cursor,
512            0x0072,
513            0x0082,
514            VR::SV,
515            &[
516                0xFE, 0x49, 0x64, 0xB4, 0x59, 0xCF, 0x0C, 0xB2, 0x01, 0xB6, 0x9B, 0x4B, 0xA6, 0x30,
517                0xF3, 0x4E,
518            ],
519        );
520        test_vr(&dec, &mut cursor, 0x0010, 0x0032, VR::TM, b"123456");
521        test_vr(&dec, &mut cursor, 0x0008, 0x0119, VR::UC, b"Code");
522        test_vr(
523            &dec,
524            &mut cursor,
525            0x0018,
526            0x6016,
527            VR::UL,
528            &[0x00, 0x00, 0x00, 0x01],
529        );
530        test_vr(
531            &dec,
532            &mut cursor,
533            0xC001,
534            0x1234,
535            VR::UN,
536            &[0x1, 0x2, 0x3, 0x4, 0x5, 0x6],
537        );
538        test_vr(
539            &dec,
540            &mut cursor,
541            0x0008,
542            0x010E,
543            VR::UR,
544            b"http://example.com",
545        );
546        test_vr(&dec, &mut cursor, 0x0008, 0x0040, VR::US, &[0x87, 0x07]);
547        test_vr(&dec, &mut cursor, 0x0018, 0x9917, VR::UT, b"No text ");
548        test_vr(
549            &dec,
550            &mut cursor,
551            0x0008,
552            0x040C,
553            VR::UV,
554            &[0xAB, 0x54, 0xA9, 0x8C, 0xEB, 0x1F, 0x0A, 0xD2],
555        );
556    }
557
558    // manually crafting some DICOM sequence/item delimiters
559    //  Tag: (0008,103F) Series Description Code Sequence
560    //  VR: SQ
561    //  Reserved bytes: 0x0000
562    //  Length: 0xFFFF_FFFF
563    // --
564    //  Tag: (FFFE,E000) Item
565    //  Length: 0xFFFF_FFFF (unspecified)
566    // --
567    //  Tag: (FFFE,E00D) Item Delimitation Item
568    //  Length: 0
569    // --
570    //  Tag: (FFFE,E0DD) Sequence Delimitation Item
571    //  Length: 0
572    // --
573    const RAW_SEQUENCE_ITEMS: &[u8] = &[
574        0x00, 0x08, 0x10, 0x3F, b'S', b'Q', 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xE0,
575        0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xE0, 0x0D, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE,
576        0xE0, 0xDD, 0x00, 0x00, 0x00, 0x00,
577    ];
578
579    #[test]
580    fn decode_items() {
581        let dec = ExplicitVRBigEndianDecoder::default();
582        let mut cursor = Cursor::new(RAW_SEQUENCE_ITEMS);
583        {
584            // read first element
585            let (elem, _bytes_read) = dec
586                .decode_header(&mut cursor)
587                .expect("should find an element header");
588            assert_eq!(elem.tag(), Tag(8, 0x103F));
589            assert_eq!(elem.vr(), VR::SQ);
590            assert!(elem.length().is_undefined());
591        }
592        // cursor should now be @ #12
593        assert_eq!(cursor.stream_position().unwrap(), 12);
594        {
595            let elem = dec
596                .decode_item_header(&mut cursor)
597                .expect("should find an item header");
598            assert!(elem.is_item());
599            assert_eq!(elem.tag(), Tag(0xFFFE, 0xE000));
600            assert!(elem.length().is_undefined());
601        }
602        // cursor should now be @ #20
603        assert_eq!(cursor.stream_position().unwrap(), 20);
604        {
605            let elem = dec
606                .decode_item_header(&mut cursor)
607                .expect("should find an item header");
608            assert!(elem.is_item_delimiter());
609            assert_eq!(elem.tag(), Tag(0xFFFE, 0xE00D));
610            assert_eq!(elem.length(), Length(0));
611        }
612        // cursor should now be @ #28
613        assert_eq!(cursor.stream_position().unwrap(), 28);
614        {
615            let elem = dec
616                .decode_item_header(&mut cursor)
617                .expect("should find an item header");
618            assert!(elem.is_sequence_delimiter());
619            assert_eq!(elem.tag(), Tag(0xFFFE, 0xE0DD));
620            assert_eq!(elem.length(), Length(0));
621        }
622    }
623}