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: &[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: &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![0; 13];
197            cursor
198                .read_exact(buffer.as_mut_slice())
199                .expect("should read it fine");
200            assert_eq!(buffer.as_slice(), b"1.2.840.10008".as_ref());
201        }
202        // cursor should now be @ #21 (there is no automatic skipping)
203        assert_eq!(cursor.stream_position().unwrap(), 21);
204        // cursor should now be @ #34 after skipping
205        assert_eq!(cursor.seek(SeekFrom::Current(13)).unwrap(), 34);
206        {
207            // read second element
208            let (elem, _bytes_read) = reader
209                .decode_header(&mut cursor)
210                .expect("should find an element");
211            assert_eq!(elem.tag(), Tag(0x0002, 0x0010));
212            assert_eq!(elem.vr(), VR::UN);
213            assert_eq!(elem.length(), Length(20));
214            // read all data
215            let mut buffer: Vec<u8> = vec![0; 20];
216            cursor
217                .read_exact(buffer.as_mut_slice())
218                .expect("should read it fine");
219            assert_eq!(buffer.as_slice(), b"1.2.840.10008.1.2.1\0".as_ref());
220        }
221    }
222
223    #[test]
224    fn implicit_vr_le_with_standard_dictionary() {
225        let reader = ImplicitVRLittleEndianDecoder::with_std_dict();
226        let mut cursor = Cursor::new(RAW.as_ref());
227        {
228            // read first element
229            let (elem, _bytes_read) = reader
230                .decode_header(&mut cursor)
231                .expect("should find an element");
232            assert_eq!(elem.tag(), Tag(2, 2));
233            assert_eq!(elem.vr(), VR::UI);
234            assert_eq!(elem.length(), Length(26));
235            // cursor should be @ #8
236            assert_eq!(cursor.stream_position().unwrap(), 8);
237            // don't read any data, just skip
238            // cursor should be @ #34 after skipping
239            assert_eq!(
240                cursor
241                    .seek(SeekFrom::Current(elem.length().0 as i64))
242                    .unwrap(),
243                34
244            );
245        }
246        {
247            // read second element
248            let (elem, _bytes_read) = reader
249                .decode_header(&mut cursor)
250                .expect("should find an element");
251            assert_eq!(elem.tag(), Tag(2, 16));
252            assert_eq!(elem.vr(), VR::UI);
253            assert_eq!(elem.length(), Length(20));
254            // read all data
255            let mut buffer: Vec<u8> = vec![0; 20];
256            cursor
257                .read_exact(buffer.as_mut_slice())
258                .expect("should read it fine");
259            assert_eq!(buffer.as_slice(), b"1.2.840.10008.1.2.1\0".as_ref());
260        }
261    }
262
263    // manually crafting some DICOM sequence/item delimiters
264    //  Tag: (0008,103F) Series Description Code Sequence
265    //  Implicit VR: SQ
266    //  Reserved bytes: 0x0000
267    //  Length: 0xFFFF_FFFF
268    // --
269    //  Tag: (FFFE,E000) Item
270    //  Length: 0xFFFF_FFFF (unspecified)
271    // --
272    //  Tag: (FFFE,E00D) Item Delimitation Item
273    //  Length: 0
274    // --
275    //  Tag: (FFFE,E0DD) Sequence Delimitation Item
276    //  Length: 0
277    // --
278    const RAW_SEQUENCE_ITEMS: &[u8] = &[
279        0x08, 0x00, 0x3F, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0x00, 0xE0, 0xFF, 0xFF, 0xFF,
280        0xFF, 0xFE, 0xFF, 0x0D, 0xE0, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF, 0xDD, 0xE0, 0x00, 0x00,
281        0x00, 0x00,
282    ];
283
284    #[test]
285    fn decode_items() {
286        let dec = ImplicitVRLittleEndianDecoder::default();
287        let mut cursor = Cursor::new(RAW_SEQUENCE_ITEMS);
288        {
289            // read first element
290            let (elem, bytes_read) = dec
291                .decode_header(&mut cursor)
292                .expect("should find an element header");
293            assert_eq!(elem.tag(), Tag(8, 0x103F));
294            assert_eq!(elem.vr(), VR::SQ);
295            assert!(elem.length().is_undefined());
296            assert_eq!(bytes_read, 8);
297        }
298        // cursor should now be @ #8
299        assert_eq!(cursor.stream_position().unwrap(), 8);
300        {
301            let elem = dec
302                .decode_item_header(&mut cursor)
303                .expect("should find an item header");
304            assert!(elem.is_item());
305            assert_eq!(elem.tag(), Tag(0xFFFE, 0xE000));
306            assert!(elem.length().is_undefined());
307        }
308        // cursor should now be @ #16
309        assert_eq!(cursor.stream_position().unwrap(), 16);
310        {
311            let elem = dec
312                .decode_item_header(&mut cursor)
313                .expect("should find an item header");
314            assert!(elem.is_item_delimiter());
315            assert_eq!(elem.tag(), Tag(0xFFFE, 0xE00D));
316            assert_eq!(elem.length(), Length(0));
317        }
318        // cursor should now be @ #24
319        assert_eq!(cursor.stream_position().unwrap(), 24);
320        {
321            let elem = dec
322                .decode_item_header(&mut cursor)
323                .expect("should find an item header");
324            assert!(elem.is_sequence_delimiter());
325            assert_eq!(elem.tag(), Tag(0xFFFE, 0xE0DD));
326            assert_eq!(elem.length(), Length(0));
327        }
328    }
329}