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