dicom_encoding/encode/
explicit_be.rs

1//! Explicit VR Big Endian syntax transfer implementation.
2
3use crate::encode::basic::BigEndianBasicEncoder;
4use crate::encode::{
5    BasicEncode, Encode, Result, WriteHeaderSnafu, WriteItemDelimiterSnafu, WriteItemHeaderSnafu,
6    WriteOffsetTableSnafu, WriteSequenceDelimiterSnafu, WriteTagSnafu,
7};
8
9use byteordered::byteorder::{BigEndian, ByteOrder};
10use byteordered::Endianness;
11use dicom_core::header::{DataElementHeader, HasLength, Header};
12use dicom_core::{PrimitiveValue, Tag, VR};
13use snafu::ResultExt;
14use std::io::{self, Write};
15
16/// A concrete encoder for the transfer syntax ExplicitVRBigEndian
17#[derive(Debug, Default, Clone)]
18pub struct ExplicitVRBigEndianEncoder {
19    basic: BigEndianBasicEncoder,
20}
21
22impl BasicEncode for ExplicitVRBigEndianEncoder {
23    fn endianness(&self) -> Endianness {
24        Endianness::Big
25    }
26
27    fn encode_us<S>(&self, to: S, value: u16) -> io::Result<()>
28    where
29        S: Write,
30    {
31        self.basic.encode_us(to, value)
32    }
33
34    fn encode_ul<S>(&self, to: S, value: u32) -> io::Result<()>
35    where
36        S: Write,
37    {
38        self.basic.encode_ul(to, value)
39    }
40
41    fn encode_uv<S>(&self, to: S, value: u64) -> io::Result<()>
42    where
43        S: Write,
44    {
45        self.basic.encode_uv(to, value)
46    }
47
48    fn encode_ss<S>(&self, to: S, value: i16) -> io::Result<()>
49    where
50        S: Write,
51    {
52        self.basic.encode_ss(to, value)
53    }
54
55    fn encode_sl<S>(&self, to: S, value: i32) -> io::Result<()>
56    where
57        S: Write,
58    {
59        self.basic.encode_sl(to, value)
60    }
61
62    fn encode_sv<S>(&self, to: S, value: i64) -> io::Result<()>
63    where
64        S: Write,
65    {
66        self.basic.encode_sv(to, value)
67    }
68
69    fn encode_fl<S>(&self, to: S, value: f32) -> io::Result<()>
70    where
71        S: Write,
72    {
73        self.basic.encode_fl(to, value)
74    }
75
76    fn encode_fd<S>(&self, to: S, value: f64) -> io::Result<()>
77    where
78        S: Write,
79    {
80        self.basic.encode_fd(to, value)
81    }
82}
83
84impl Encode for ExplicitVRBigEndianEncoder {
85    fn encode_tag<W>(&self, mut to: W, tag: Tag) -> Result<()>
86    where
87        W: Write,
88    {
89        let mut buf = [0u8, 4];
90        BigEndian::write_u16(&mut buf[..], tag.group());
91        BigEndian::write_u16(&mut buf[2..], tag.element());
92        to.write_all(&buf).context(WriteTagSnafu)
93    }
94
95    fn encode_element_header<W>(&self, mut to: W, de: DataElementHeader) -> Result<usize>
96    where
97        W: Write,
98    {
99        match de.vr() {
100            VR::OB
101            | VR::OD
102            | VR::OF
103            | VR::OL
104            | VR::OW
105            | VR::SQ
106            | VR::UC
107            | VR::UR
108            | VR::UT
109            | VR::UN => {
110                let mut buf = [0u8; 12];
111                BigEndian::write_u16(&mut buf[0..], de.tag().group());
112                BigEndian::write_u16(&mut buf[2..], de.tag().element());
113                let vr_bytes = de.vr().to_bytes();
114                buf[4] = vr_bytes[0];
115                buf[5] = vr_bytes[1];
116                // buf[6..8] is kept zero'd
117                BigEndian::write_u32(&mut buf[8..], de.length().0);
118                to.write_all(&buf).context(WriteHeaderSnafu)?;
119
120                Ok(12)
121            }
122            _ => {
123                let mut buf = [0u8; 8];
124                BigEndian::write_u16(&mut buf[0..], de.tag().group());
125                BigEndian::write_u16(&mut buf[2..], de.tag().element());
126                let vr_bytes = de.vr().to_bytes();
127                buf[4] = vr_bytes[0];
128                buf[5] = vr_bytes[1];
129                BigEndian::write_u16(&mut buf[6..], de.length().0 as u16);
130                to.write_all(&buf).context(WriteHeaderSnafu)?;
131
132                Ok(8)
133            }
134        }
135    }
136
137    fn encode_item_header<W>(&self, mut to: W, len: u32) -> Result<()>
138    where
139        W: Write,
140    {
141        let mut buf = [0u8; 8];
142        BigEndian::write_u16(&mut buf, 0xFFFE);
143        BigEndian::write_u16(&mut buf[2..], 0xE000);
144        BigEndian::write_u32(&mut buf[4..], len);
145        to.write_all(&buf).context(WriteItemHeaderSnafu)
146    }
147
148    fn encode_item_delimiter<W>(&self, mut to: W) -> Result<()>
149    where
150        W: Write,
151    {
152        let mut buf = [0u8; 8];
153        BigEndian::write_u16(&mut buf, 0xFFFE);
154        BigEndian::write_u16(&mut buf[2..], 0xE00D);
155        // remaining bytes are already zero, so it's ready to write
156        to.write_all(&buf).context(WriteItemDelimiterSnafu)
157    }
158
159    fn encode_sequence_delimiter<W>(&self, mut to: W) -> Result<()>
160    where
161        W: Write,
162    {
163        let mut buf = [0u8; 8];
164        BigEndian::write_u16(&mut buf, 0xFFFE);
165        BigEndian::write_u16(&mut buf[2..], 0xE0DD);
166        // remaining bytes are already zero, so it's ready to write
167        to.write_all(&buf).context(WriteSequenceDelimiterSnafu)
168    }
169
170    fn encode_primitive<W>(&self, to: W, value: &PrimitiveValue) -> Result<usize>
171    where
172        W: Write,
173    {
174        self.basic.encode_primitive(to, value)
175    }
176
177    fn encode_offset_table<W>(&self, mut to: W, offset_table: &[u32]) -> Result<usize>
178    where
179        W: Write,
180    {
181        for v in offset_table {
182            self.basic
183                .encode_ul(&mut to, *v)
184                .context(WriteOffsetTableSnafu)?;
185        }
186        Ok(offset_table.len() * 4)
187    }
188}
189
190#[cfg(test)]
191mod tests {
192    use super::ExplicitVRBigEndianEncoder;
193    use crate::encode::Encode;
194    use dicom_core::header::{DataElementHeader, Length};
195    use dicom_core::{Tag, VR};
196    use std::io::{Cursor, Write};
197
198    type Result = std::result::Result<(), Box<dyn std::error::Error>>;
199
200    // manually crafting some DICOM data elements
201    //  Tag: (0002,0002) Media Storage SOP Class UID
202    //  VR: UI
203    //  Length: 26
204    //  Value: "1.2.840.10008.5.1.4.1.1.1" (with 1 padding '\0')
205    // --
206    //  Tag: (0002,0010) Transfer Syntax UID
207    //  VR: UI
208    //  Length: 20
209    //  Value: "1.2.840.10008.1.2.1" (w 1 padding '\0') == ExplicitVRLittleEndian
210    // --
211    const RAW: &'static [u8; 62] = &[
212        0x00, 0x02, 0x00, 0x02, 0x55, 0x49, 0x00, 0x1a, 0x31, 0x2e, 0x32, 0x2e, 0x38, 0x34, 0x30,
213        0x2e, 0x31, 0x30, 0x30, 0x30, 0x38, 0x2e, 0x35, 0x2e, 0x31, 0x2e, 0x34, 0x2e, 0x31, 0x2e,
214        0x31, 0x2e, 0x31, 0x00, 0x00, 0x02, 0x00, 0x10, 0x55, 0x49, 0x00, 0x14, 0x31, 0x2e, 0x32,
215        0x2e, 0x38, 0x34, 0x30, 0x2e, 0x31, 0x30, 0x30, 0x30, 0x38, 0x2e, 0x31, 0x2e, 0x32, 0x2e,
216        0x31, 0x00,
217    ];
218
219    #[test]
220    fn encode_explicit_vr_be() {
221        let mut buf = [0u8; 62];
222        {
223            let enc = ExplicitVRBigEndianEncoder::default();
224            let mut writer = Cursor::new(&mut buf[..]);
225
226            // encode first element
227            let de = DataElementHeader::new(Tag(0x0002, 0x0002), VR::UI, Length(26));
228            let len = enc
229                .encode_element_header(&mut writer, de)
230                .expect("should write it fine");
231            assert_eq!(len, 8);
232            writer
233                .write_all(b"1.2.840.10008.5.1.4.1.1.1\0".as_ref())
234                .expect("should write the value fine");
235        }
236        assert_eq!(&buf[0..8], &RAW[0..8]);
237        {
238            let enc = ExplicitVRBigEndianEncoder::default();
239            let mut writer = Cursor::new(&mut buf[34..]);
240
241            // encode second element
242            let de = DataElementHeader::new(Tag(0x0002, 0x0010), VR::UI, Length(20));
243            let len = enc
244                .encode_element_header(&mut writer, de)
245                .expect("should write it fine");
246            assert_eq!(len, 8);
247            writer
248                .write_all(b"1.2.840.10008.1.2.1\0".as_ref())
249                .expect("should write the value fine");
250        }
251        assert_eq!(&buf[34..42], &RAW[34..42]);
252
253        assert_eq!(&buf[..], &RAW[..]);
254    }
255
256    // manually crafting some DICOM sequence/item delimiters
257    //  Tag: (0008,103F) Series Description Code Sequence
258    //  VR: SQ
259    //  Reserved bytes: 0x0000
260    //  Length: 0xFFFF_FFFF
261    // --
262    //  Tag: (FFFE,E000) Item
263    //  Length: 0xFFFF_FFFF (unspecified)
264    // --
265    //  Tag: (FFFE,E00D) Item Delimitation Item
266    //  Length: 0
267    // --
268    //  Tag: (FFFE,E0DD) Sequence Delimitation Item
269    //  Length: 0
270    // --
271    const RAW_SEQUENCE_ITEMS: &'static [u8] = &[
272        0x00, 0x08, 0x10, 0x3F, b'S', b'Q', 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xE0,
273        0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xE0, 0x0D, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFE,
274        0xE0, 0xDD, 0x00, 0x00, 0x00, 0x00,
275    ];
276
277    #[test]
278    fn encode_items() -> Result {
279        let enc = ExplicitVRBigEndianEncoder::default();
280        let mut out = Vec::new();
281
282        {
283            let bytes_written = enc.encode_element_header(
284                &mut out,
285                DataElementHeader::new(Tag(0x0008, 0x103F), VR::SQ, Length::UNDEFINED),
286            )?;
287            assert_eq!(bytes_written, 12);
288        }
289        assert_eq!(out.len(), 12);
290
291        enc.encode_item_header(&mut out, Length::UNDEFINED.0)?;
292        assert_eq!(out.len(), 20);
293
294        enc.encode_item_delimiter(&mut out)?;
295        assert_eq!(out.len(), 28);
296
297        enc.encode_sequence_delimiter(&mut out)?;
298
299        assert_eq!(&out[..], RAW_SEQUENCE_ITEMS);
300
301        Ok(())
302    }
303}