dicom_encoding/encode/
implicit_le.rs

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