dicom_encoding/encode/
mod.rs

1//! This module contains all DICOM data element encoding logic.
2use byteordered::Endianness;
3use dicom_core::value::serialize::{encode_date, encode_datetime, encode_time};
4use dicom_core::{DataElementHeader, PrimitiveValue, Tag};
5use snafu::{Backtrace, ResultExt, Snafu};
6use std::fmt;
7use std::io::{self, Write};
8use std::marker::PhantomData;
9
10pub mod basic;
11pub mod explicit_be;
12pub mod explicit_le;
13pub mod implicit_le;
14
15/// Module-level error type:
16/// for errors which may occur while encoding DICOM data.
17#[derive(Debug, Snafu)]
18#[non_exhaustive]
19pub enum Error {
20    #[snafu(display("Failed to write Date value"))]
21    WriteDate {
22        backtrace: Backtrace,
23        source: io::Error,
24    },
25    #[snafu(display("Failed to write Time value"))]
26    WriteTime {
27        backtrace: Backtrace,
28        source: io::Error,
29    },
30    #[snafu(display("Failed to write DateTime value"))]
31    WriteDateTime {
32        backtrace: Backtrace,
33        source: io::Error,
34    },
35    #[snafu(display("Failed to write tag"))]
36    WriteTag {
37        backtrace: Backtrace,
38        source: io::Error,
39    },
40    #[snafu(display("Failed to write tag group"))]
41    WriteTagGroup {
42        backtrace: Backtrace,
43        source: io::Error,
44    },
45    #[snafu(display("Failed to write tag element"))]
46    WriteTagElement {
47        backtrace: Backtrace,
48        source: io::Error,
49    },
50    #[snafu(display("Failed to write item header"))]
51    WriteItemHeader {
52        backtrace: Backtrace,
53        source: io::Error,
54    },
55    #[snafu(display("Failed to write element header"))]
56    WriteHeader {
57        backtrace: Backtrace,
58        source: io::Error,
59    },
60    #[snafu(display("Failed to write item delimiter"))]
61    WriteItemDelimiter {
62        backtrace: Backtrace,
63        source: io::Error,
64    },
65    #[snafu(display("Failed to write sequence delimiter"))]
66    WriteSequenceDelimiter {
67        backtrace: Backtrace,
68        source: io::Error,
69    },
70    #[snafu(display("Failed to write {} value", typ))]
71    WriteBinary {
72        typ: &'static str,
73        backtrace: Backtrace,
74        source: io::Error,
75    },
76    #[snafu(display("Failed to write string value"))]
77    WriteString {
78        backtrace: Backtrace,
79        source: io::Error,
80    },
81    #[snafu(display("Failed to write bytes"))]
82    WriteBytes {
83        backtrace: Backtrace,
84        source: io::Error,
85    },
86    #[snafu(display("Failed to write pixel data offset table"))]
87    WriteOffsetTable {
88        backtrace: Backtrace,
89        source: io::Error,
90    },
91}
92
93pub type Result<T, E = Error> = std::result::Result<T, E>;
94
95/// Type trait for an encoder of basic data properties.
96/// Unlike `Encode` (and similar to `BasicDecode`), this trait is not object
97/// safe because it's better to just provide a dynamic implementation.
98pub trait BasicEncode {
99    /// Retrieve the encoder's endianness.
100    fn endianness(&self) -> Endianness;
101
102    /// Encode an unsigned short value to the given writer.
103    fn encode_us<W>(&self, to: W, value: u16) -> io::Result<()>
104    where
105        W: Write;
106
107    /// Encode an unsigned long value to the given writer.
108    fn encode_ul<W>(&self, to: W, value: u32) -> io::Result<()>
109    where
110        W: Write;
111
112    /// Encode an unsigned very long value to the given writer.
113    fn encode_uv<W>(&self, to: W, value: u64) -> io::Result<()>
114    where
115        W: Write;
116
117    /// Encode a signed short value to the given writer.
118    fn encode_ss<W>(&self, to: W, value: i16) -> io::Result<()>
119    where
120        W: Write;
121
122    /// Encode a signed long value to the given writer.
123    fn encode_sl<W>(&self, to: W, value: i32) -> io::Result<()>
124    where
125        W: Write;
126
127    /// Encode a signed very long value to the given writer.
128    fn encode_sv<W>(&self, to: W, value: i64) -> io::Result<()>
129    where
130        W: Write;
131
132    /// Encode a single precision float value to the given writer.
133    fn encode_fl<W>(&self, to: W, value: f32) -> io::Result<()>
134    where
135        W: Write;
136
137    /// Encode a double precision float value to the given writer.
138    fn encode_fd<W>(&self, to: W, value: f64) -> io::Result<()>
139    where
140        W: Write;
141
142    /// If this encoder is in Little Endian, evaluate the first function.
143    /// Otherwise, evaluate the second one.
144    #[inline]
145    fn with_encoder<T, F1, F2>(&self, f_le: F1, f_be: F2) -> T
146    where
147        F1: FnOnce(basic::LittleEndianBasicEncoder) -> T,
148        F2: FnOnce(basic::BigEndianBasicEncoder) -> T,
149    {
150        match self.endianness() {
151            Endianness::Little => f_le(basic::LittleEndianBasicEncoder),
152            Endianness::Big => f_be(basic::BigEndianBasicEncoder),
153        }
154    }
155
156    /// Encode a primitive value to the given writer. The default implementation
157    /// delegates to the other value encoding methods.
158    fn encode_primitive<W>(&self, mut to: W, value: &PrimitiveValue) -> Result<usize>
159    where
160        W: Write,
161    {
162        use PrimitiveValue::*;
163        match value {
164            Empty => Ok(0), // no-op
165            Date(date) => {
166                encode_collection_delimited(&mut to, date, |to, date| encode_date(to, *date))
167                    .context(WriteDateSnafu)
168            }
169            Time(time) => {
170                encode_collection_delimited(&mut to, time, |to, time| encode_time(to, *time))
171                    .context(WriteTimeSnafu)
172            }
173            DateTime(datetime) => encode_collection_delimited(&mut to, datetime, |to, datetime| {
174                encode_datetime(to, *datetime)
175            })
176            .context(WriteDateTimeSnafu),
177            Str(s) => {
178                // Note: this will always print in UTF-8. Consumers should
179                // intercept string primitive values and encode them according
180                // to the expected character set.
181                write!(to, "{}", s).context(WriteStringSnafu)?;
182                Ok(s.len())
183            }
184            Strs(s) => encode_collection_delimited(&mut to, s, |to, s| {
185                // Note: this will always print in UTF-8. Consumers should
186                // intercept string primitive values and encode them according
187                // to the expected character set.
188                write!(to, "{}", s)?;
189                Ok(s.len())
190            })
191            .context(WriteStringSnafu),
192            F32(values) => {
193                for v in values {
194                    self.encode_fl(&mut to, *v)
195                        .context(WriteBinarySnafu { typ: "F32" })?;
196                }
197                Ok(values.len() * 4)
198            }
199            F64(values) => {
200                for v in values {
201                    self.encode_fd(&mut to, *v)
202                        .context(WriteBinarySnafu { typ: "F64" })?;
203                }
204                Ok(values.len() * 8)
205            }
206            U64(values) => {
207                for v in values {
208                    self.encode_uv(&mut to, *v)
209                        .context(WriteBinarySnafu { typ: "U64" })?;
210                }
211                Ok(values.len() * 8)
212            }
213            I64(values) => {
214                for v in values {
215                    self.encode_sv(&mut to, *v)
216                        .context(WriteBinarySnafu { typ: "I64" })?;
217                }
218                Ok(values.len() * 8)
219            }
220            U32(values) => {
221                for v in values {
222                    self.encode_ul(&mut to, *v)
223                        .context(WriteBinarySnafu { typ: "U32" })?;
224                }
225                Ok(values.len() * 4)
226            }
227            I32(values) => {
228                for v in values {
229                    self.encode_sl(&mut to, *v)
230                        .context(WriteBinarySnafu { typ: "I32" })?;
231                }
232                Ok(values.len() * 4)
233            }
234            U16(values) => {
235                for v in values {
236                    self.encode_us(&mut to, *v)
237                        .context(WriteBinarySnafu { typ: "U16" })?;
238                }
239                Ok(values.len() * 2)
240            }
241            I16(values) => {
242                for v in values {
243                    self.encode_ss(&mut to, *v)
244                        .context(WriteBinarySnafu { typ: "I16" })?;
245                }
246                Ok(values.len() * 2)
247            }
248            U8(values) => {
249                to.write_all(values).context(WriteBytesSnafu)?;
250                Ok(values.len())
251            }
252            Tags(tags) => {
253                for tag in tags {
254                    self.encode_us(&mut to, tag.0).context(WriteTagGroupSnafu)?;
255                    self.encode_us(&mut to, tag.1)
256                        .context(WriteTagElementSnafu)?;
257                }
258                Ok(tags.len() * 4)
259            }
260        }
261    }
262}
263
264fn encode_collection_delimited<W, T, F>(
265    to: &mut W,
266    col: &[T],
267    mut encode_element_fn: F,
268) -> io::Result<usize>
269where
270    W: ?Sized + Write,
271    F: FnMut(&mut W, &T) -> io::Result<usize>,
272{
273    let mut acc = 0;
274    for (i, v) in col.iter().enumerate() {
275        acc += encode_element_fn(to, v)?;
276        if i < col.len() - 1 {
277            to.write_all(b"\\")?;
278            acc += 1;
279        }
280    }
281    Ok(acc)
282}
283
284/// Type trait for a data element encoder.
285pub trait Encode {
286    /// Encode and write an element tag.
287    fn encode_tag<W>(&self, to: W, tag: Tag) -> Result<()>
288    where
289        W: Write;
290
291    /// Encode and write a data element header to the given destination.
292    /// Returns the number of bytes effectively written on success.
293    fn encode_element_header<W>(&self, to: W, de: DataElementHeader) -> Result<usize>
294    where
295        W: Write;
296
297    /// Encode and write a DICOM sequence item header to the given destination.
298    /* Although item element headers are always a tag and length sequence regardless of TS,
299    the encoding of the length is unknown at this level. So no default impl. */
300    fn encode_item_header<W>(&self, to: W, len: u32) -> Result<()>
301    where
302        W: Write;
303
304    /// Encode and write a DICOM sequence item delimiter to the given destination.
305    fn encode_item_delimiter<W>(&self, mut to: W) -> Result<()>
306    where
307        W: Write,
308    {
309        self.encode_tag(&mut to, Tag(0xFFFE, 0xE00D))?;
310        to.write_all(&[0u8; 4]).context(WriteItemDelimiterSnafu)?;
311        Ok(())
312    }
313
314    /// Encode and write a DICOM sequence delimiter to the given destination.
315    fn encode_sequence_delimiter<W>(&self, mut to: W) -> Result<()>
316    where
317        W: Write,
318    {
319        self.encode_tag(&mut to, Tag(0xFFFE, 0xE0DD))?;
320        to.write_all(&[0u8; 4])
321            .context(WriteSequenceDelimiterSnafu)?;
322        Ok(())
323    }
324
325    /// Encode and write a primitive DICOM value to the given destination.
326    fn encode_primitive<W>(&self, to: W, value: &PrimitiveValue) -> Result<usize>
327    where
328        W: Write;
329
330    /// Encode and write a DICOM pixel data offset table
331    /// to the given destination.
332    ///
333    /// For convenience, returns the number of bytes written on success,
334    /// equivalent to `offset_table.len() * 4`.
335    // Note that offset tables might not apply to all forms of encoding,
336    // but this method needs to exist nevertheless.
337    fn encode_offset_table<W>(&self, to: W, offset_table: &[u32]) -> Result<usize>
338    where
339        W: Write;
340}
341
342impl<T: ?Sized> Encode for &T
343where
344    T: Encode,
345{
346    fn encode_tag<W>(&self, to: W, tag: Tag) -> Result<()>
347    where
348        W: Write,
349    {
350        (**self).encode_tag(to, tag)
351    }
352
353    fn encode_element_header<W>(&self, to: W, de: DataElementHeader) -> Result<usize>
354    where
355        W: Write,
356    {
357        (**self).encode_element_header(to, de)
358    }
359
360    fn encode_item_header<W>(&self, to: W, len: u32) -> Result<()>
361    where
362        W: Write,
363    {
364        (**self).encode_item_header(to, len)
365    }
366
367    fn encode_item_delimiter<W>(&self, to: W) -> Result<()>
368    where
369        W: Write,
370    {
371        (**self).encode_item_delimiter(to)
372    }
373
374    fn encode_sequence_delimiter<W>(&self, to: W) -> Result<()>
375    where
376        W: Write,
377    {
378        (**self).encode_sequence_delimiter(to)
379    }
380
381    fn encode_primitive<W>(&self, to: W, value: &PrimitiveValue) -> Result<usize>
382    where
383        W: Write,
384    {
385        (**self).encode_primitive(to, value)
386    }
387
388    fn encode_offset_table<W>(&self, to: W, offset_table: &[u32]) -> Result<usize>
389    where
390        W: Write,
391    {
392        (**self).encode_offset_table(to, offset_table)
393    }
394}
395
396impl<T: ?Sized> Encode for Box<T>
397where
398    T: Encode,
399{
400    fn encode_tag<W>(&self, to: W, tag: Tag) -> Result<()>
401    where
402        W: Write,
403    {
404        (**self).encode_tag(to, tag)
405    }
406
407    fn encode_element_header<W>(&self, to: W, de: DataElementHeader) -> Result<usize>
408    where
409        W: Write,
410    {
411        (**self).encode_element_header(to, de)
412    }
413
414    fn encode_item_header<W>(&self, to: W, len: u32) -> Result<()>
415    where
416        W: Write,
417    {
418        (**self).encode_item_header(to, len)
419    }
420
421    fn encode_item_delimiter<W>(&self, to: W) -> Result<()>
422    where
423        W: Write,
424    {
425        (**self).encode_item_delimiter(to)
426    }
427
428    fn encode_sequence_delimiter<W>(&self, to: W) -> Result<()>
429    where
430        W: Write,
431    {
432        (**self).encode_sequence_delimiter(to)
433    }
434
435    fn encode_primitive<W>(&self, to: W, value: &PrimitiveValue) -> Result<usize>
436    where
437        W: Write,
438    {
439        (**self).encode_primitive(to, value)
440    }
441
442    fn encode_offset_table<W>(&self, to: W, offset_table: &[u32]) -> Result<usize>
443    where
444        W: Write,
445    {
446        (**self).encode_offset_table(to, offset_table)
447    }
448}
449
450/// Type trait for a data element encoder to a single known writer type `W`.
451pub trait EncodeTo<W: ?Sized> {
452    /// Encode and write an element tag.
453    fn encode_tag(&self, to: &mut W, tag: Tag) -> Result<()>
454    where
455        W: Write;
456
457    /// Encode and write a data element header to the given destination.
458    /// Returns the number of bytes effectively written on success.
459    ///
460    /// Note that data element header should be encoded as is,
461    /// regardless of the given value length.
462    /// Any eventual padding logic should be done at a higher level.
463    fn encode_element_header(&self, to: &mut W, de: DataElementHeader) -> Result<usize>
464    where
465        W: Write;
466
467    /// Encode and write a DICOM sequence item header to the given destination.
468    /* Although item element headers are always a tag and length sequence regardless of TS,
469    the encoding of the length is unknown at this level. So no default impl. */
470    fn encode_item_header(&self, to: &mut W, len: u32) -> Result<()>
471    where
472        W: Write;
473
474    /// Encode and write a DICOM sequence item delimiter to the given destination.
475    fn encode_item_delimiter(&self, to: &mut W) -> Result<()>
476    where
477        W: Write;
478
479    /// Encode and write a DICOM sequence delimiter to the given destination.
480    fn encode_sequence_delimiter(&self, to: &mut W) -> Result<()>
481    where
482        W: Write;
483
484    /// Encode and write a primitive DICOM value to the given destination.
485    fn encode_primitive(&self, to: &mut W, value: &PrimitiveValue) -> Result<usize>
486    where
487        W: Write;
488
489    /// Encode and write a DICOM pixel data offset table
490    /// to the given destination.
491    ///
492    /// For convenience, returns the number of bytes written on success,
493    /// equivalent to `offset_table.len() * 4`.
494    // Note that offset tables might not apply to all forms of encoding,
495    // but this method needs to exist nevertheless.
496    fn encode_offset_table(&self, to: &mut W, offset_table: &[u32]) -> Result<usize>
497    where
498        W: Write;
499}
500
501impl<T, W: ?Sized> EncodeTo<W> for &T
502where
503    T: EncodeTo<W>,
504{
505    fn encode_tag(&self, to: &mut W, tag: Tag) -> Result<()>
506    where
507        W: Write,
508    {
509        (**self).encode_tag(to, tag)
510    }
511
512    fn encode_element_header(&self, to: &mut W, de: DataElementHeader) -> Result<usize>
513    where
514        W: Write,
515    {
516        (**self).encode_element_header(to, de)
517    }
518
519    fn encode_item_header(&self, to: &mut W, len: u32) -> Result<()>
520    where
521        W: Write,
522    {
523        (**self).encode_item_header(to, len)
524    }
525
526    fn encode_item_delimiter(&self, to: &mut W) -> Result<()>
527    where
528        W: Write,
529    {
530        (**self).encode_item_delimiter(to)
531    }
532
533    fn encode_sequence_delimiter(&self, to: &mut W) -> Result<()>
534    where
535        W: Write,
536    {
537        (**self).encode_sequence_delimiter(to)
538    }
539
540    /// Encode and write a primitive DICOM value to the given destination.
541    fn encode_primitive(&self, to: &mut W, value: &PrimitiveValue) -> Result<usize>
542    where
543        W: Write,
544    {
545        (**self).encode_primitive(to, value)
546    }
547
548    fn encode_offset_table(&self, to: &mut W, offset_table: &[u32]) -> Result<usize>
549    where
550        W: Write,
551    {
552        (**self).encode_offset_table(to, offset_table)
553    }
554}
555
556impl<T: ?Sized, W: ?Sized> EncodeTo<W> for Box<T>
557where
558    T: EncodeTo<W>,
559{
560    fn encode_tag(&self, to: &mut W, tag: Tag) -> Result<()>
561    where
562        W: Write,
563    {
564        (**self).encode_tag(to, tag)
565    }
566
567    fn encode_element_header(&self, to: &mut W, de: DataElementHeader) -> Result<usize>
568    where
569        W: Write,
570    {
571        (**self).encode_element_header(to, de)
572    }
573
574    fn encode_item_header(&self, to: &mut W, len: u32) -> Result<()>
575    where
576        W: Write,
577    {
578        (**self).encode_item_header(to, len)
579    }
580
581    fn encode_item_delimiter(&self, to: &mut W) -> Result<()>
582    where
583        W: Write,
584    {
585        (**self).encode_item_delimiter(to)
586    }
587
588    fn encode_sequence_delimiter(&self, to: &mut W) -> Result<()>
589    where
590        W: Write,
591    {
592        (**self).encode_sequence_delimiter(to)
593    }
594
595    /// Encode and write a primitive DICOM value to the given destination.
596    fn encode_primitive(&self, to: &mut W, value: &PrimitiveValue) -> Result<usize>
597    where
598        W: Write,
599    {
600        (**self).encode_primitive(to, value)
601    }
602
603    fn encode_offset_table(&self, to: &mut W, offset_table: &[u32]) -> Result<usize>
604    where
605        W: Write,
606    {
607        (**self).encode_offset_table(to, offset_table)
608    }
609}
610
611/// A type binding of an encoder to a target writer.
612pub struct EncoderFor<T, W: ?Sized> {
613    inner: T,
614    phantom: PhantomData<W>,
615}
616
617impl<T, W: ?Sized> EncoderFor<T, W> {
618    /** Using a generic encoder, create a new encoder specifically for the given
619     * writer of type `W`.
620     */
621    pub fn new(encoder: T) -> Self {
622        EncoderFor {
623            inner: encoder,
624            phantom: PhantomData,
625        }
626    }
627}
628
629impl<T: fmt::Debug, W: ?Sized> fmt::Debug for EncoderFor<T, W> {
630    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
631        f.debug_struct("ImplicitVRLittleEndianEncoder")
632            .field("inner", &self.inner)
633            .field("phantom", &self.phantom)
634            .finish()
635    }
636}
637
638impl<T, W: ?Sized> Default for EncoderFor<T, W>
639where
640    T: Default,
641{
642    fn default() -> Self {
643        EncoderFor {
644            inner: T::default(),
645            phantom: PhantomData,
646        }
647    }
648}
649
650impl<T, W: ?Sized> BasicEncode for EncoderFor<T, W>
651where
652    T: BasicEncode,
653    W: Write,
654{
655    fn endianness(&self) -> Endianness {
656        self.inner.endianness()
657    }
658
659    fn encode_us<S>(&self, to: S, value: u16) -> io::Result<()>
660    where
661        S: Write,
662    {
663        self.inner.encode_us(to, value)
664    }
665
666    fn encode_ul<S>(&self, to: S, value: u32) -> io::Result<()>
667    where
668        S: Write,
669    {
670        self.inner.encode_ul(to, value)
671    }
672
673    fn encode_uv<S>(&self, to: S, value: u64) -> io::Result<()>
674    where
675        S: Write,
676    {
677        self.inner.encode_uv(to, value)
678    }
679
680    fn encode_ss<S>(&self, to: S, value: i16) -> io::Result<()>
681    where
682        S: Write,
683    {
684        self.inner.encode_ss(to, value)
685    }
686
687    fn encode_sl<S>(&self, to: S, value: i32) -> io::Result<()>
688    where
689        S: Write,
690    {
691        self.inner.encode_sl(to, value)
692    }
693
694    fn encode_sv<S>(&self, to: S, value: i64) -> io::Result<()>
695    where
696        S: Write,
697    {
698        self.inner.encode_sv(to, value)
699    }
700
701    fn encode_fl<S>(&self, to: S, value: f32) -> io::Result<()>
702    where
703        S: Write,
704    {
705        self.inner.encode_fl(to, value)
706    }
707
708    fn encode_fd<S>(&self, to: S, value: f64) -> io::Result<()>
709    where
710        S: Write,
711    {
712        self.inner.encode_fd(to, value)
713    }
714}
715
716impl<T, W: ?Sized> EncodeTo<W> for EncoderFor<T, W>
717where
718    T: Encode,
719    W: Write,
720{
721    fn encode_tag(&self, to: &mut W, tag: Tag) -> Result<()> {
722        self.inner.encode_tag(to, tag)
723    }
724
725    fn encode_element_header(&self, to: &mut W, de: DataElementHeader) -> Result<usize> {
726        self.inner.encode_element_header(to, de)
727    }
728
729    fn encode_item_header(&self, to: &mut W, len: u32) -> Result<()> {
730        self.inner.encode_item_header(to, len)
731    }
732
733    fn encode_item_delimiter(&self, to: &mut W) -> Result<()> {
734        self.inner.encode_item_delimiter(to)
735    }
736
737    fn encode_sequence_delimiter(&self, to: &mut W) -> Result<()> {
738        self.inner.encode_sequence_delimiter(to)
739    }
740
741    fn encode_primitive(&self, to: &mut W, value: &PrimitiveValue) -> Result<usize> {
742        self.inner.encode_primitive(to, value)
743    }
744
745    fn encode_offset_table(&self, to: &mut W, offset_table: &[u32]) -> Result<usize> {
746        self.inner.encode_offset_table(to, offset_table)
747    }
748}
749
750#[cfg(test)]
751mod tests {
752    use super::*;
753
754    fn is_encode<T: Encode>(_encoder: &T) {}
755    fn is_encode_to<W: ?Sized, T: EncodeTo<W>>(_encoder: &T) {}
756
757    #[allow(unused)]
758    fn boxed_encode_is_encode<T>(encoder: T)
759    where
760        T: Encode,
761        T: Copy,
762    {
763        is_encode(&encoder);
764        is_encode_to::<dyn Write, _>(&EncoderFor::new(encoder));
765        let boxed = Box::new(encoder);
766        is_encode(&boxed);
767        is_encode_to::<dyn Write, _>(&EncoderFor::new(boxed));
768    }
769}