dicom_encoding/decode/
explicit_le.rs

1//! Explicit VR Little Endian syntax transfer implementation
2
3use crate::decode::basic::LittleEndianBasicDecoder;
4use crate::decode::{
5    BadSequenceHeaderSnafu, BasicDecode, Decode, DecodeFrom, ReadHeaderTagSnafu,
6    ReadItemHeaderSnafu, ReadItemLengthSnafu, ReadLengthSnafu, ReadReservedSnafu, ReadTagSnafu,
7    ReadVrSnafu, Result,
8};
9use byteordered::byteorder::{ByteOrder, LittleEndian};
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 Little Endian transfer syntax.
16#[derive(Debug, Default, Clone)]
17pub struct ExplicitVRLittleEndianDecoder {
18    basic: LittleEndianBasicDecoder,
19}
20
21impl Decode for ExplicitVRLittleEndianDecoder {
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 = LittleEndian::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        let bytes_read;
47
48        // retrieve data length
49        let len = match vr {
50            VR::OB
51            | VR::OD
52            | VR::OF
53            | VR::OL
54            | VR::OW
55            | VR::SQ
56            | VR::UC
57            | VR::UR
58            | VR::UT
59            | VR::UN => {
60                // read 2 reserved bytes, then 4 bytes for data length
61                source
62                    .read_exact(&mut buf[0..2])
63                    .context(ReadReservedSnafu)?;
64                source.read_exact(&mut buf).context(ReadLengthSnafu)?;
65                bytes_read = 12;
66                LittleEndian::read_u32(&buf)
67            }
68            _ => {
69                // read 2 bytes for the data length
70                source.read_exact(&mut buf[0..2]).context(ReadLengthSnafu)?;
71                bytes_read = 8;
72                u32::from(LittleEndian::read_u16(&buf[0..2]))
73            }
74        };
75
76        Ok((
77            DataElementHeader::new((group, element), vr, Length(len)),
78            bytes_read,
79        ))
80    }
81
82    fn decode_item_header<S>(&self, source: &mut S) -> Result<SequenceItemHeader>
83    where
84        S: ?Sized + Read,
85    {
86        let mut buf = [0u8; 8];
87        source.read_exact(&mut buf).context(ReadItemHeaderSnafu)?;
88        // retrieve tag
89        let group = LittleEndian::read_u16(&buf[0..2]);
90        let element = LittleEndian::read_u16(&buf[2..4]);
91        let len = LittleEndian::read_u32(&buf[4..8]);
92
93        SequenceItemHeader::new((group, element), Length(len)).context(BadSequenceHeaderSnafu)
94    }
95
96    fn decode_tag<S>(&self, source: &mut S) -> Result<Tag>
97    where
98        S: ?Sized + Read,
99    {
100        let mut buf = [0u8; 4];
101        source.read_exact(&mut buf).context(ReadTagSnafu)?;
102        Ok(Tag(
103            LittleEndian::read_u16(&buf[0..2]),
104            LittleEndian::read_u16(&buf[2..4]),
105        ))
106    }
107}
108
109impl<S: ?Sized> DecodeFrom<S> for ExplicitVRLittleEndianDecoder
110where
111    S: Read,
112{
113    #[inline]
114    fn decode_header(&self, source: &mut S) -> Result<(DataElementHeader, usize)> {
115        Decode::decode_header(self, source)
116    }
117
118    #[inline]
119    fn decode_item_header(&self, source: &mut S) -> Result<SequenceItemHeader> {
120        Decode::decode_item_header(self, source)
121    }
122
123    #[inline]
124    fn decode_tag(&self, source: &mut S) -> Result<Tag> {
125        Decode::decode_tag(self, source)
126    }
127}
128
129#[cfg(test)]
130mod tests {
131    use super::ExplicitVRLittleEndianDecoder;
132    use crate::decode::Decode;
133    use dicom_core::header::{HasLength, Header, Length};
134    use dicom_core::{Tag, VR};
135    use std::io::{Cursor, Read, Seek, SeekFrom};
136
137    // manually crafting some DICOM data elements
138    //  Tag: (0002,0002) Media Storage SOP Class UID
139    //  VR: UI
140    //  Length: 26
141    //  Value: "1.2.840.10008.5.1.4.1.1.1\0"
142    // --
143    //  Tag: (0002,0010) Transfer Syntax UID
144    //  VR: UI
145    //  Length: 20
146    //  Value: "1.2.840.10008.1.2.1\0" == ExplicitVRLittleEndian
147    // --
148    const RAW: &'static [u8; 62] = &[
149        0x02, 0x00, 0x02, 0x00, 0x55, 0x49, 0x1a, 0x00, 0x31, 0x2e, 0x32, 0x2e, 0x38, 0x34, 0x30,
150        0x2e, 0x31, 0x30, 0x30, 0x30, 0x38, 0x2e, 0x35, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e,
151        0x31, 0x2e, 0x31, 0x00, 0x02, 0x00, 0x10, 0x00, 0x55, 0x49, 0x14, 0x00, 0x31, 0x2e, 0x32,
152        0x2e, 0x38, 0x34, 0x30, 0x2e, 0x31, 0x30, 0x30, 0x30, 0x38, 0x2e, 0x31, 0x2e, 0x32, 0x2e,
153        0x31, 0x00,
154    ];
155
156    #[test]
157    fn decode_data_elements() {
158        let dec = ExplicitVRLittleEndianDecoder::default();
159        let mut cursor = Cursor::new(RAW.as_ref());
160        {
161            // read first element
162            let (elem, bytes_read) = dec
163                .decode_header(&mut cursor)
164                .expect("should find an element");
165            assert_eq!(elem.tag(), Tag(2, 2));
166            assert_eq!(elem.vr(), VR::UI);
167            assert_eq!(elem.length(), Length(26));
168            assert_eq!(bytes_read, 8);
169            // read only half of the value data
170            let mut buffer = [0; 13];
171            cursor.read_exact(&mut buffer).expect("should read it fine");
172            assert_eq!(&buffer, b"1.2.840.10008".as_ref());
173        }
174        // cursor should now be @ #21 (there is no automatic skipping)
175        assert_eq!(cursor.seek(SeekFrom::Current(0)).unwrap(), 21);
176        // cursor should now be @ #34 after skipping
177        assert_eq!(cursor.seek(SeekFrom::Current(13)).unwrap(), 34);
178        {
179            // read second element
180            let (elem, _bytes_read) = dec
181                .decode_header(&mut cursor)
182                .expect("should find an element");
183            assert_eq!(elem.tag(), Tag(2, 16));
184            assert_eq!(elem.vr(), VR::UI);
185            assert_eq!(elem.length(), Length(20));
186            // read all data
187            let mut buffer = [0; 20];
188            cursor.read_exact(&mut buffer).expect("should read it fine");
189            assert_eq!(&buffer, b"1.2.840.10008.1.2.1\0".as_ref());
190        }
191    }
192
193    // manually crafting some DICOM sequence/item delimiters
194    //  Tag: (0008,103F) Series Description Code Sequence
195    //  VR: SQ
196    //  Reserved bytes: 0x0000
197    //  Length: 0xFFFF_FFFF
198    // --
199    //  Tag: (FFFE,E000) Item
200    //  Length: 0xFFFF_FFFF (unspecified)
201    // --
202    //  Tag: (FFFE,E00D) Item Delimitation Item
203    //  Length: 0
204    // --
205    //  Tag: (FFFE,E0DD) Sequence Delimitation Item
206    //  Length: 0
207    // --
208    const RAW_SEQUENCE_ITEMS: &'static [u8] = &[
209        0x08, 0x00, 0x3F, 0x10, b'S', b'Q', 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0x00,
210        0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0x0D, 0xE0, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF,
211        0xDD, 0xE0, 0x00, 0x00, 0x00, 0x00,
212    ];
213
214    #[test]
215    fn decode_items() {
216        let dec = ExplicitVRLittleEndianDecoder::default();
217        let mut cursor = Cursor::new(RAW_SEQUENCE_ITEMS);
218        {
219            // read first element
220            let (elem, bytes_read) = dec
221                .decode_header(&mut cursor)
222                .expect("should find an element header");
223            assert_eq!(elem.tag(), Tag(8, 0x103F));
224            assert_eq!(elem.vr(), VR::SQ);
225            assert!(elem.length().is_undefined());
226            assert_eq!(bytes_read, 12);
227        }
228        // cursor should now be @ #12
229        assert_eq!(cursor.seek(SeekFrom::Current(0)).unwrap(), 12);
230        {
231            let elem = dec
232                .decode_item_header(&mut cursor)
233                .expect("should find an item header");
234            assert!(elem.is_item());
235            assert_eq!(elem.tag(), Tag(0xFFFE, 0xE000));
236            assert!(elem.length().is_undefined());
237        }
238        // cursor should now be @ #20
239        assert_eq!(cursor.seek(SeekFrom::Current(0)).unwrap(), 20);
240        {
241            let elem = dec
242                .decode_item_header(&mut cursor)
243                .expect("should find an item header");
244            assert!(elem.is_item_delimiter());
245            assert_eq!(elem.tag(), Tag(0xFFFE, 0xE00D));
246            assert_eq!(elem.length(), Length(0));
247        }
248        // cursor should now be @ #28
249        assert_eq!(cursor.seek(SeekFrom::Current(0)).unwrap(), 28);
250        {
251            let elem = dec
252                .decode_item_header(&mut cursor)
253                .expect("should find an item header");
254            assert!(elem.is_sequence_delimiter());
255            assert_eq!(elem.tag(), Tag(0xFFFE, 0xE0DD));
256            assert_eq!(elem.length(), Length(0));
257        }
258    }
259}