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