dicom_encoding/decode/
implicit_le.rs

1//! Implicit VR Big Endian syntax transfer implementation
2
3use crate::decode::basic::LittleEndianBasicDecoder;
4use crate::decode::{
5    BadSequenceHeaderSnafu, BasicDecode, DecodeFrom, ReadHeaderTagSnafu, ReadLengthSnafu,
6    ReadTagSnafu, Result,
7};
8use crate::Decode;
9use byteordered::byteorder::{ByteOrder, LittleEndian};
10use dicom_core::dictionary::{DataDictionary, DataDictionaryEntry};
11use dicom_core::header::{DataElementHeader, Length, SequenceItemHeader};
12use dicom_core::{Tag, VR};
13use dicom_dictionary_std::StandardDataDictionary;
14use snafu::ResultExt;
15use std::fmt;
16use std::io::Read;
17
18/// An ImplicitVRLittleEndianDecoder which uses the standard data dictionary.
19pub type StandardImplicitVRLittleEndianDecoder =
20    ImplicitVRLittleEndianDecoder<StandardDataDictionary>;
21
22/// A data element decoder for the Explicit VR Little Endian transfer syntax.
23/// This type contains a reference to an attribute dictionary for resolving
24/// value representations.
25pub struct ImplicitVRLittleEndianDecoder<D> {
26    dict: D,
27    basic: LittleEndianBasicDecoder,
28}
29
30impl<D> fmt::Debug for ImplicitVRLittleEndianDecoder<D> {
31    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
32        f.debug_struct("ImplicitVRLittleEndianDecoder")
33            .field("dict", &"«omitted»")
34            .field("basic", &self.basic)
35            .finish()
36    }
37}
38
39impl ImplicitVRLittleEndianDecoder<StandardDataDictionary> {
40    /// Retrieve this decoder using the standard data dictionary.
41    pub fn with_std_dict() -> Self {
42        ImplicitVRLittleEndianDecoder {
43            dict: StandardDataDictionary,
44            basic: LittleEndianBasicDecoder,
45        }
46    }
47
48    /// Retrieve this decoder using the standard data dictionary.
49    pub fn new() -> Self {
50        Self::with_std_dict()
51    }
52}
53
54impl Default for ImplicitVRLittleEndianDecoder<StandardDataDictionary> {
55    fn default() -> Self {
56        ImplicitVRLittleEndianDecoder::with_std_dict()
57    }
58}
59
60impl<D> ImplicitVRLittleEndianDecoder<D>
61where
62    D: DataDictionary,
63{
64    /// Retrieve this decoder using a custom data dictionary.
65    pub fn with_dict(dictionary: D) -> Self {
66        ImplicitVRLittleEndianDecoder {
67            dict: dictionary,
68            basic: LittleEndianBasicDecoder,
69        }
70    }
71}
72
73impl<D> Decode for ImplicitVRLittleEndianDecoder<D>
74where
75    D: DataDictionary,
76{
77    fn decode_header<S>(&self, mut source: &mut S) -> Result<(DataElementHeader, usize)>
78    where
79        S: ?Sized + Read,
80    {
81        // retrieve tag
82        let tag = self
83            .basic
84            .decode_tag(&mut source)
85            .context(ReadHeaderTagSnafu)?;
86
87        let mut buf = [0u8; 4];
88        source.read_exact(&mut buf).context(ReadLengthSnafu)?;
89        let len = LittleEndian::read_u32(&buf);
90
91        // VR resolution is done with the help of the data dictionary.
92        // In Implicit VR Little Endian,
93        // the VR of OW must be used for Pixel Data (7FE0,0010)
94        // and Overlay Data (60xx, 3000).
95        // This edge case is addressed manually here.
96        let vr = if tag == Tag(0x7FE0, 0x0010) || (tag.0 >> 8 == 0x60 && tag.1 == 0x3000) {
97            VR::OW
98        } else {
99            self.dict
100                .by_tag(tag)
101                .map(|entry| entry.vr().relaxed())
102                .unwrap_or(VR::UN)
103        };
104        Ok((DataElementHeader::new(tag, vr, Length(len)), 8))
105    }
106
107    fn decode_item_header<S>(&self, mut source: &mut S) -> Result<SequenceItemHeader>
108    where
109        S: ?Sized + Read,
110    {
111        let mut buf = [0u8; 4];
112
113        // retrieve tag
114        let tag = self
115            .basic
116            .decode_tag(&mut source)
117            .context(ReadHeaderTagSnafu)?;
118
119        source.read_exact(&mut buf).context(ReadLengthSnafu)?;
120        let len = LittleEndian::read_u32(&buf);
121        SequenceItemHeader::new(tag, Length(len)).context(BadSequenceHeaderSnafu)
122    }
123
124    #[inline]
125    fn decode_tag<S>(&self, source: &mut S) -> Result<Tag>
126    where
127        S: ?Sized + Read,
128    {
129        self.basic.decode_tag(source).context(ReadTagSnafu)
130    }
131}
132
133impl<S: ?Sized, D> DecodeFrom<S> for ImplicitVRLittleEndianDecoder<D>
134where
135    S: Read,
136    D: DataDictionary,
137{
138    #[inline]
139    fn decode_header(&self, source: &mut S) -> Result<(DataElementHeader, usize)> {
140        Decode::decode_header(self, source)
141    }
142
143    #[inline]
144    fn decode_item_header(&self, source: &mut S) -> Result<SequenceItemHeader> {
145        Decode::decode_item_header(self, source)
146    }
147
148    #[inline]
149    fn decode_tag(&self, source: &mut S) -> Result<Tag> {
150        Decode::decode_tag(self, source)
151    }
152}
153
154#[cfg(test)]
155mod tests {
156    use super::ImplicitVRLittleEndianDecoder;
157    use crate::decode::Decode;
158    use dicom_core::dictionary::stub::StubDataDictionary;
159    use dicom_core::header::{HasLength, Header, Length, VR};
160    use dicom_core::Tag;
161    use std::io::{Cursor, Read, Seek, SeekFrom};
162
163    // manually crafting some DICOM data elements
164    //   Tag: (0002,0002) Media Storage SOP Class UID
165    //   Length: 26
166    //   Value: "1.2.840.10008.5.1.4.1.1.1" (with 1 padding '\0')
167    // --
168    //   Tag: (0002,0010) Transfer Syntax UID
169    //   Length: 20
170    //   Value: "1.2.840.10008.1.2.1" (w 1 padding '\0') == ExplicitVRLittleEndian
171    // --
172    const RAW: &'static [u8; 62] = &[
173        0x02, 0x00, 0x02, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x31, 0x2e, 0x32, 0x2e, 0x38, 0x34, 0x30,
174        0x2e, 0x31, 0x30, 0x30, 0x30, 0x38, 0x2e, 0x35, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e,
175        0x31, 0x2e, 0x31, 0x00, 0x02, 0x00, 0x10, 0x00, 0x14, 0x00, 0x00, 0x00, 0x31, 0x2e, 0x32,
176        0x2e, 0x38, 0x34, 0x30, 0x2e, 0x31, 0x30, 0x30, 0x30, 0x38, 0x2e, 0x31, 0x2e, 0x32, 0x2e,
177        0x31, 0x00,
178    ];
179
180    const DICT: &'static StubDataDictionary = &StubDataDictionary;
181
182    #[test]
183    fn implicit_vr_le() {
184        let reader = ImplicitVRLittleEndianDecoder::with_dict(DICT);
185        let mut cursor = Cursor::new(RAW.as_ref());
186        {
187            // read first element
188            let (elem, bytes_read) = reader
189                .decode_header(&mut cursor)
190                .expect("should find an element");
191            assert_eq!(elem.tag(), Tag(0x0002, 0x0002));
192            assert_eq!(elem.vr(), VR::UN);
193            assert_eq!(elem.length(), Length(26));
194            assert_eq!(bytes_read, 8);
195            // read only half of the data
196            let mut buffer: Vec<u8> = Vec::with_capacity(13);
197            buffer.resize(13, 0);
198            cursor
199                .read_exact(buffer.as_mut_slice())
200                .expect("should read it fine");
201            assert_eq!(buffer.as_slice(), b"1.2.840.10008".as_ref());
202        }
203        // cursor should now be @ #21 (there is no automatic skipping)
204        assert_eq!(cursor.seek(SeekFrom::Current(0)).unwrap(), 21);
205        // cursor should now be @ #34 after skipping
206        assert_eq!(cursor.seek(SeekFrom::Current(13)).unwrap(), 34);
207        {
208            // read second element
209            let (elem, _bytes_read) = reader
210                .decode_header(&mut cursor)
211                .expect("should find an element");
212            assert_eq!(elem.tag(), Tag(0x0002, 0x0010));
213            assert_eq!(elem.vr(), VR::UN);
214            assert_eq!(elem.length(), Length(20));
215            // read all data
216            let mut buffer: Vec<u8> = Vec::with_capacity(20);
217            buffer.resize(20, 0);
218            cursor
219                .read_exact(buffer.as_mut_slice())
220                .expect("should read it fine");
221            assert_eq!(buffer.as_slice(), b"1.2.840.10008.1.2.1\0".as_ref());
222        }
223    }
224
225    #[test]
226    fn implicit_vr_le_with_standard_dictionary() {
227        let reader = ImplicitVRLittleEndianDecoder::with_std_dict();
228        let mut cursor = Cursor::new(RAW.as_ref());
229        {
230            // read first element
231            let (elem, _bytes_read) = reader
232                .decode_header(&mut cursor)
233                .expect("should find an element");
234            assert_eq!(elem.tag(), Tag(2, 2));
235            assert_eq!(elem.vr(), VR::UI);
236            assert_eq!(elem.length(), Length(26));
237            // cursor should be @ #8
238            assert_eq!(cursor.seek(SeekFrom::Current(0)).unwrap(), 8);
239            // don't read any data, just skip
240            // cursor should be @ #34 after skipping
241            assert_eq!(
242                cursor
243                    .seek(SeekFrom::Current(elem.length().0 as i64))
244                    .unwrap(),
245                34
246            );
247        }
248        {
249            // read second element
250            let (elem, _bytes_read) = reader
251                .decode_header(&mut cursor)
252                .expect("should find an element");
253            assert_eq!(elem.tag(), Tag(2, 16));
254            assert_eq!(elem.vr(), VR::UI);
255            assert_eq!(elem.length(), Length(20));
256            // read all data
257            let mut buffer: Vec<u8> = Vec::with_capacity(20);
258            buffer.resize(20, 0);
259            cursor
260                .read_exact(buffer.as_mut_slice())
261                .expect("should read it fine");
262            assert_eq!(buffer.as_slice(), b"1.2.840.10008.1.2.1\0".as_ref());
263        }
264    }
265
266    // manually crafting some DICOM sequence/item delimiters
267    //  Tag: (0008,103F) Series Description Code Sequence
268    //  Implicit VR: SQ
269    //  Reserved bytes: 0x0000
270    //  Length: 0xFFFF_FFFF
271    // --
272    //  Tag: (FFFE,E000) Item
273    //  Length: 0xFFFF_FFFF (unspecified)
274    // --
275    //  Tag: (FFFE,E00D) Item Delimitation Item
276    //  Length: 0
277    // --
278    //  Tag: (FFFE,E0DD) Sequence Delimitation Item
279    //  Length: 0
280    // --
281    const RAW_SEQUENCE_ITEMS: &'static [u8] = &[
282        0x08, 0x00, 0x3F, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0x00, 0xE0, 0xFF, 0xFF, 0xFF,
283        0xFF, 0xFE, 0xFF, 0x0D, 0xE0, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xDD, 0xE0, 0x00, 0x00,
284        0x00, 0x00,
285    ];
286
287    #[test]
288    fn decode_items() {
289        let dec = ImplicitVRLittleEndianDecoder::default();
290        let mut cursor = Cursor::new(RAW_SEQUENCE_ITEMS);
291        {
292            // read first element
293            let (elem, bytes_read) = dec
294                .decode_header(&mut cursor)
295                .expect("should find an element header");
296            assert_eq!(elem.tag(), Tag(8, 0x103F));
297            assert_eq!(elem.vr(), VR::SQ);
298            assert!(elem.length().is_undefined());
299            assert_eq!(bytes_read, 8);
300        }
301        // cursor should now be @ #8
302        assert_eq!(cursor.seek(SeekFrom::Current(0)).unwrap(), 8);
303        {
304            let elem = dec
305                .decode_item_header(&mut cursor)
306                .expect("should find an item header");
307            assert!(elem.is_item());
308            assert_eq!(elem.tag(), Tag(0xFFFE, 0xE000));
309            assert!(elem.length().is_undefined());
310        }
311        // cursor should now be @ #16
312        assert_eq!(cursor.seek(SeekFrom::Current(0)).unwrap(), 16);
313        {
314            let elem = dec
315                .decode_item_header(&mut cursor)
316                .expect("should find an item header");
317            assert!(elem.is_item_delimiter());
318            assert_eq!(elem.tag(), Tag(0xFFFE, 0xE00D));
319            assert_eq!(elem.length(), Length(0));
320        }
321        // cursor should now be @ #24
322        assert_eq!(cursor.seek(SeekFrom::Current(0)).unwrap(), 24);
323        {
324            let elem = dec
325                .decode_item_header(&mut cursor)
326                .expect("should find an item header");
327            assert!(elem.is_sequence_delimiter());
328            assert_eq!(elem.tag(), Tag(0xFFFE, 0xE0DD));
329            assert_eq!(elem.length(), Length(0));
330        }
331    }
332}