1use 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, VR};
12use snafu::ResultExt;
13use std::io::{self, Write};
14
15#[derive(Debug, Default, Clone)]
17pub struct ExplicitVRLittleEndianEncoder {
18 basic: LittleEndianBasicEncoder,
19}
20
21impl BasicEncode for ExplicitVRLittleEndianEncoder {
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 ExplicitVRLittleEndianEncoder {
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 match de.vr() {
99 VR::AE
106 | VR::AS
107 | VR::AT
108 | VR::CS
109 | VR::DA
110 | VR::DS
111 | VR::DT
112 | VR::FL
113 | VR::FD
114 | VR::IS
115 | VR::LO
116 | VR::LT
117 | VR::PN
118 | VR::SH
119 | VR::SL
120 | VR::SS
121 | VR::ST
122 | VR::TM
123 | VR::UI
124 | VR::UL
125 | VR::US => {
126 let mut buf = [0u8; 8];
127 LittleEndian::write_u16(&mut buf[0..], de.tag().group());
128 LittleEndian::write_u16(&mut buf[2..], de.tag().element());
129 let vr_bytes = de.vr().to_bytes();
130 buf[4] = vr_bytes[0];
131 buf[5] = vr_bytes[1];
132 LittleEndian::write_u16(&mut buf[6..], de.length().0 as u16);
133 to.write_all(&buf).context(WriteHeaderSnafu)?;
134 Ok(8)
135 }
136 _ => {
143 let mut buf = [0u8; 12];
144 LittleEndian::write_u16(&mut buf[0..], de.tag().group());
145 LittleEndian::write_u16(&mut buf[2..], de.tag().element());
146 let vr_bytes = de.vr().to_bytes();
147 buf[4] = vr_bytes[0];
148 buf[5] = vr_bytes[1];
149 LittleEndian::write_u32(&mut buf[8..], de.length().0);
151 to.write_all(&buf).context(WriteHeaderSnafu)?;
152 Ok(12)
153 }
154 }
155 }
156
157 fn encode_item_header<W>(&self, mut to: W, len: u32) -> Result<()>
158 where
159 W: Write,
160 {
161 let mut buf = [0u8; 8];
162 LittleEndian::write_u16(&mut buf, 0xFFFE);
163 LittleEndian::write_u16(&mut buf[2..], 0xE000);
164 LittleEndian::write_u32(&mut buf[4..], len);
165 to.write_all(&buf).context(WriteItemHeaderSnafu)
166 }
167
168 fn encode_item_delimiter<W>(&self, mut to: W) -> Result<()>
169 where
170 W: Write,
171 {
172 let mut buf = [0u8; 8];
173 LittleEndian::write_u16(&mut buf, 0xFFFE);
174 LittleEndian::write_u16(&mut buf[2..], 0xE00D);
175 to.write_all(&buf).context(WriteItemDelimiterSnafu)
176 }
177
178 fn encode_sequence_delimiter<W>(&self, mut to: W) -> Result<()>
179 where
180 W: Write,
181 {
182 let mut buf = [0u8; 8];
183 LittleEndian::write_u16(&mut buf, 0xFFFE);
184 LittleEndian::write_u16(&mut buf[2..], 0xE0DD);
185 to.write_all(&buf).context(WriteSequenceDelimiterSnafu)
186 }
187
188 fn encode_primitive<W>(&self, to: W, value: &PrimitiveValue) -> Result<usize>
189 where
190 W: Write,
191 {
192 self.basic.encode_primitive(to, value)
193 }
194
195 fn encode_offset_table<W>(&self, mut to: W, offset_table: &[u32]) -> Result<usize>
196 where
197 W: Write,
198 {
199 for v in offset_table {
200 self.basic
201 .encode_ul(&mut to, *v)
202 .context(WriteOffsetTableSnafu)?;
203 }
204 Ok(offset_table.len() * 4)
205 }
206}
207
208#[cfg(test)]
209mod tests {
210 use super::ExplicitVRLittleEndianEncoder;
211 use crate::encode::Encode;
212 use dicom_core::header::{DataElementHeader, Length};
213 use dicom_core::{Tag, VR};
214 use std::io::{Cursor, Write};
215
216 type Result = std::result::Result<(), Box<dyn std::error::Error>>;
217
218 #[rustfmt::skip]
220 const RAW: &[u8] = &[
221 0x02, 0x00, 0x02, 0x00, b'U', b'I', 0x1A, 0x00, b'1', b'.', b'2', b'.', b'8', b'4', b'0', b'.', b'1', b'0', b'0', b'0', b'8', b'.',
226 b'5', b'.', b'1', b'.', b'4', b'.', b'1', b'.', b'1', b'.', b'1',
227 0x00, 0x02, 0x00, 0x10, 0x00, b'U', b'I', 0x14, 0x00, b'1', b'.', b'2', b'.', b'8', b'4', b'0', b'.', b'1', b'0', b'0', b'0', b'8', b'.',
233 b'1', b'.', b'2', b'.', b'1',
234 0x00, 0x08, 0x00, 0x54, 0x00, b'A', b'E', 0x06, 0x00, b'T', b'I', b'T', b'L', b'E',
240 b' ', 0x10, 0x00, 0x10, 0x10, b'A', b'S', 0x02, 0x00, b'8', b'Y',
246 0x72, 0x00, 0x26, 0x00, b'A', b'T', 0x04, 0x00, 0x28, 0x00, 0x10, 0x21,
251 0x10, 0x00, 0x40, 0x00, b'C', b'S', 0x02, 0x00, b'O',
256 b' ', 0x10, 0x00, 0x30, 0x00, b'D', b'A', 0x08, 0x00, b'1', b'9', b'8', b'0', b'0', b'1', b'0', b'1',
262 0x10, 0x00, 0x20, 0x10, b'D', b'S', 0x04, 0x00, b'1', b'.', b'7', b'0',
267 0x08, 0x00, 0x15, 0x00, b'D', b'T', 0x0E, 0x00, b'2', b'0', b'0', b'5', b'1', b'2', b'3', b'1', b'2', b'3', b'5', b'9', b'6', b'0',
272 0x10, 0x00, 0x31, 0x94, b'F', b'L', 0x04, 0x00, 0xDB, 0x0F, 0x49, 0x40,
277 0x40, 0x00, 0x25, 0x92, b'F', b'D', 0x08, 0x00, 0x18, 0x2D, 0x44, 0x54, 0xFB, 0x21, 0x09, 0x40,
282 0x20, 0x00, 0x13, 0x00, b'I', b'S', 0x08, 0x00, b'1', b'2', b'3', b'4', b'5', b'6', b'7',
287 b' ', 0x10, 0x00, 0x20, 0x00, b'L', b'O', 0x0A, 0x00, b'P', b'1', b'2', b'3', b'4', b'5', b'6', b'7', b'8', b'X',
293 0x10, 0x00, 0x00, 0x40, b'L', b'T', 0x04, 0x00, b'N', b'o', b'n', b'e',
298 0x08, 0x00, 0x1B, 0x04, b'O', b'B', 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x12, 0x34,
304 0xE0, 0x7F, 0x09, 0x00, b'O', b'D', 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x18, 0x2D, 0x44, 0x54, 0xFB, 0x21, 0x09, 0x40,
310 0xE0, 0x7F, 0x08, 0x00, b'O', b'F', 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xDB, 0x0F, 0x49, 0x40,
316 0x72, 0x00, 0x75, 0x00, b'O', b'L', 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x78, 0x56, 0x34, 0x12,
322 0x72, 0x00, 0x81, 0x00, b'O', b'V', 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x80, 0x7F, 0x6E, 0x5D, 0x4C, 0x3B, 0x2A, 0x19,
328 0x72, 0x00, 0x69, 0x00, b'O', b'W', 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x34, 0x12,
334 0x10, 0x00, 0x10, 0x00, b'P', b'N', 0x08, 0x00, b'D', b'o', b'e', b'^', b'J', b'o', b'h', b'n',
339 0x40, 0x00, 0x10, 0x92, b'S', b'H', 0x04, 0x00, b'L', b'B', b'L',
344 b' ', 0x18, 0x00, 0x20, 0x60, b'S', b'L', 0x04, 0x00, 0xB2, 0x9E, 0x43, 0xFF,
350 0x28, 0x00, 0x03, 0x95, b'S', b'S', 0x04, 0x00, 0x29, 0xEE,
356 0xE1, 0x10,
358 0x40, 0x00, 0x80, 0x02, b'S', b'T', 0x0A, 0x00, b'N', b'o', b' ', b'c', b'o', b'm', b'm', b'e', b'n', b't',
363 0x72, 0x00, 0x82, 0x00, b'S', b'V', 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0xB2, 0x0C, 0xCF, 0x59, 0xB4, 0x64, 0x49, 0xFE,
369 0x4E, 0xF3, 0x30, 0xA6, 0x4B, 0x9B, 0xB6, 0x01,
371 0x10, 0x00, 0x32, 0x00, b'T', b'M', 0x06, 0x00, b'1', b'2', b'3', b'4', b'5', b'6',
376 0x08, 0x00, 0x19, 0x01, b'U', b'C', 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, b'C', b'o', b'd', b'e',
382 0x18, 0x00, 0x16, 0x60, b'U', b'L',
385 0x04, 0x00, 0x01, 0x00, 0x00, 0x00,
388 0x01, 0xC0, 0x34, 0x12, b'U', b'N', 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
394 0x08, 0x00, 0x0E, 0x01, b'U', b'R', 0x00, 0x00, 0x12, 0x00, 0x00, 0x00, b'h', b't', b't', b'p', b':', b'/', b'/', b'e', b'x', b'a', b'm', b'p', b'l', b'e',
400 b'.', b'c', b'o', b'm',
401 0x08, 0x00, 0x40, 0x00, b'U', b'S', 0x02, 0x00, 0x07, 0x87,
406 0x18, 0x00, 0x17, 0x99, b'U', b'T', 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, b'N', b'o', b' ', b't', b'e', b'x', b't',
412 b' ', 0x08, 0x00, 0x0C, 0x04, b'U', b'V', 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0xD2, 0x0A, 0x1F, 0xEB, 0x8C, 0xA9, 0x54, 0xAB,
419 ];
420
421 #[test]
422 fn encode_data_elements() {
423 let mut buf = vec![0u8; RAW.len()];
424
425 let enc = ExplicitVRLittleEndianEncoder::default();
426 let mut writer = Cursor::new(&mut buf);
427
428 let de = DataElementHeader::new(Tag(0x0002, 0x0002), VR::UI, Length(26));
430 let len = enc
431 .encode_element_header(&mut writer, de)
432 .expect("should write it fine");
433 assert_eq!(len, 8);
434 writer
435 .write_all(b"1.2.840.10008.5.1.4.1.1.1\0".as_ref())
436 .expect("should write the value fine");
437
438 let de = DataElementHeader::new(Tag(0x0002, 0x0010), VR::UI, Length(20));
440 let len = enc
441 .encode_element_header(&mut writer, de)
442 .expect("should write it fine");
443 assert_eq!(len, 8);
444 writer
445 .write_all(b"1.2.840.10008.1.2.1\0".as_ref())
446 .expect("should write the value fine");
447
448 fn write_elem(
449 enc: &ExplicitVRLittleEndianEncoder,
450 mut writer: &mut Cursor<&mut Vec<u8>>,
451 group: u16,
452 element: u16,
453 vr: VR,
454 value: &[u8],
455 ) {
456 let from = writer.position() as usize;
457 let de = DataElementHeader::new(
458 Tag(group, element),
459 vr,
460 Length(value.len() as u32),
461 );
462 let _written_len = enc
463 .encode_element_header(&mut writer, de)
464 .expect("should write it fine");
465 writer.write_all(value).expect("should write the value fine");
466 let to = writer.position() as usize;
467
468 if &writer.get_ref()[from..to] != &RAW[from..to] {
470 panic!(
471 "Failure on ({:04x},{:04x}) {:?} {:02x?}\n\
472 Expected: {:02x?}",
473 group,
474 element,
475 vr,
476 value,
477 &RAW[from..to],
478 );
479 }
480 }
481
482 write_elem(&enc, &mut writer, 0x0008, 0x0054, VR::AE, b"TITLE ");
483 write_elem(&enc, &mut writer, 0x0010, 0x1010, VR::AS, b"8Y");
484 write_elem(
485 &enc,
486 &mut writer,
487 0x0072,
488 0x0026,
489 VR::AT,
490 &[0x28, 0x00, 0x10, 0x21],
491 );
492 write_elem(&enc, &mut writer, 0x0010, 0x0040, VR::CS, b"O ");
493 write_elem(&enc, &mut writer, 0x0010, 0x0030, VR::DA, b"19800101");
494 write_elem(&enc, &mut writer, 0x0010, 0x1020, VR::DS, b"1.70");
495
496 write_elem(
497 &enc,
498 &mut writer,
499 0x0008,
500 0x0015,
501 VR::DT,
502 b"20051231235960",
503 );
504 write_elem(
505 &enc,
506 &mut writer,
507 0x0010,
508 0x9431,
509 VR::FL,
510 &[0xDB, 0x0F, 0x49, 0x40],
511 );
512 write_elem(
513 &enc,
514 &mut writer,
515 0x0040,
516 0x9225,
517 VR::FD,
518 &[0x18, 0x2D, 0x44, 0x54, 0xFB, 0x21, 0x09, 0x40],
519 );
520 write_elem(&enc, &mut writer, 0x0020, 0x0013, VR::IS, b"1234567 ");
521 write_elem(&enc, &mut writer, 0x0010, 0x0020, VR::LO, b"P12345678X");
522 write_elem(&enc, &mut writer, 0x0010, 0x4000, VR::LT, b"None");
523 write_elem(&enc, &mut writer, 0x0008, 0x041B, VR::OB, &[0x12, 0x34]);
524 write_elem(
525 &enc,
526 &mut writer,
527 0x7FE0,
528 0x0009,
529 VR::OD,
530 &[0x18, 0x2D, 0x44, 0x54, 0xFB, 0x21, 0x09, 0x40],
531 );
532 write_elem(
533 &enc,
534 &mut writer,
535 0x7FE0,
536 0x0008,
537 VR::OF,
538 &[0xDB, 0x0F, 0x49, 0x40],
539 );
540 write_elem(
541 &enc,
542 &mut writer,
543 0x0072,
544 0x0075,
545 VR::OL,
546 &[0x78, 0x56, 0x34, 0x12],
547 );
548 write_elem(
549 &enc,
550 &mut writer,
551 0x0072,
552 0x0081,
553 VR::OV,
554 &[0x80, 0x7F, 0x6E, 0x5D, 0x4C, 0x3B, 0x2A, 0x19],
555 );
556 write_elem(&enc, &mut writer, 0x0072, 0x0069, VR::OW, &[0x34, 0x12]);
557 write_elem(&enc, &mut writer, 0x0010, 0x0010, VR::PN, b"Doe^John");
558 write_elem(&enc, &mut writer, 0x0040, 0x9210, VR::SH, b"LBL ");
559 write_elem(
560 &enc,
561 &mut writer,
562 0x0018,
563 0x6020,
564 VR::SL,
565 &[0xB2, 0x9E, 0x43, 0xFF],
566 );
567 write_elem(
568 &enc,
569 &mut writer,
570 0x0028,
571 0x9503,
572 VR::SS,
573 &[0x29, 0xEE, 0xE1, 0x10],
574 );
575 write_elem(&enc, &mut writer, 0x0040, 0x0280, VR::ST, b"No comment");
576 write_elem(
577 &enc,
578 &mut writer,
579 0x0072,
580 0x0082,
581 VR::SV,
582 &[
583 0xB2, 0x0C, 0xCF, 0x59, 0xB4, 0x64, 0x49, 0xFE, 0x4E, 0xF3, 0x30, 0xA6, 0x4B, 0x9B,
584 0xB6, 0x01,
585 ],
586 );
587 write_elem(&enc, &mut writer, 0x0010, 0x0032, VR::TM, b"123456");
588 write_elem(&enc, &mut writer, 0x0008, 0x0119, VR::UC, b"Code");
589 write_elem(
590 &enc,
591 &mut writer,
592 0x0018,
593 0x6016,
594 VR::UL,
595 &[0x01, 0x00, 0x00, 0x00],
596 );
597 write_elem(
598 &enc,
599 &mut writer,
600 0xC001,
601 0x1234,
602 VR::UN,
603 &[0x1, 0x2, 0x3, 0x4, 0x5, 0x6],
604 );
605 write_elem(
606 &enc,
607 &mut writer,
608 0x0008,
609 0x010E,
610 VR::UR,
611 b"http://example.com",
612 );
613 write_elem(&enc, &mut writer, 0x0008, 0x0040, VR::US, &[0x07, 0x87]);
614 write_elem(&enc, &mut writer, 0x0018, 0x9917, VR::UT, b"No text ");
615 write_elem(
616 &enc,
617 &mut writer,
618 0x0008,
619 0x040C,
620 VR::UV,
621 &[0xD2, 0x0A, 0x1F, 0xEB, 0x8C, 0xA9, 0x54, 0xAB],
622 );
623
624 assert_eq!(&buf[..], &RAW[..]);
626 }
627
628 const RAW_SEQUENCE_ITEMS: &[u8] = &[
644 0x08, 0x00, 0x3F, 0x10, b'S', b'Q', 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0x00,
645 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0x0D, 0xE0, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xFF,
646 0xDD, 0xE0, 0x00, 0x00, 0x00, 0x00,
647 ];
648
649 #[test]
650 fn encode_items() -> Result {
651 let enc = ExplicitVRLittleEndianEncoder::default();
652 let mut out = Vec::new();
653
654 {
655 let bytes_written = enc.encode_element_header(
656 &mut out,
657 DataElementHeader::new(Tag(0x0008, 0x103F), VR::SQ, Length::UNDEFINED),
658 )?;
659 assert_eq!(bytes_written, 12);
660 }
661 assert_eq!(out.len(), 12);
662
663 enc.encode_item_header(&mut out, Length::UNDEFINED.0)?;
664 assert_eq!(out.len(), 20);
665
666 enc.encode_item_delimiter(&mut out)?;
667 assert_eq!(out.len(), 28);
668
669 enc.encode_sequence_delimiter(&mut out)?;
670
671 assert_eq!(&out[..], RAW_SEQUENCE_ITEMS);
672
673 Ok(())
674 }
675}