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}