1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
//! This module contains all DICOM data element encoding logic.
use crate::error::Result;
use byteordered::Endianness;
use dicom_core::{DataElementHeader, Tag};
use std::io::Write;

pub mod basic;

/// Type trait for an encoder of basic data properties.
/// Unlike `Encode` (and similar to `BasicDecode`), this trait is not object
/// safe because it's better to just provide a dynamic implementation.
pub trait BasicEncode {
    /// Retrieve the encoder's endianness.
    fn endianness(&self) -> Endianness;

    /// Encode an unsigned short value to the given writer.
    fn encode_us<S>(&self, to: S, value: u16) -> Result<()>
    where
        S: Write;

    /// Encode an unsigned long value to the given writer.
    fn encode_ul<S>(&self, to: S, value: u32) -> Result<()>
    where
        S: Write;

    /// Encode a signed short value to the given writer.
    fn encode_ss<S>(&self, to: S, value: i16) -> Result<()>
    where
        S: Write;

    /// Encode a signed long value to the given writer.
    fn encode_sl<S>(&self, to: S, value: i32) -> Result<()>
    where
        S: Write;

    /// Encode a single precision float value to the given writer.
    fn encode_fl<S>(&self, to: S, value: f32) -> Result<()>
    where
        S: Write;

    /// Encode a double precision float value to the given writer.
    fn encode_fd<S>(&self, to: S, value: f64) -> Result<()>
    where
        S: Write;

    /// Perform
    #[inline]
    fn with_encoder<T, F1, F2>(&self, f_le: F1, f_be: F2) -> T
    where
        F1: FnOnce(self::basic::LittleEndianBasicEncoder) -> T,
        F2: FnOnce(self::basic::BigEndianBasicEncoder) -> T,
    {
        match self.endianness() {
            Endianness::Little => f_le(self::basic::LittleEndianBasicEncoder),
            Endianness::Big => f_be(self::basic::BigEndianBasicEncoder),
        }
    }
}

/// Type trait for a data element encoder.
pub trait Encode {
    /// The target of the encoded data.
    type Writer: ?Sized + Write;

    /// Encode and write an element tag.
    fn encode_tag(&self, to: &mut Self::Writer, tag: Tag) -> Result<()>;

    /// Encode and write a data element header to the given destination.
    /// Returns the number of bytes effectively written on success.
    fn encode_element_header(&self, to: &mut Self::Writer, de: DataElementHeader) -> Result<usize>;

    /// Encode and write a DICOM sequence item header to the given destination.
    /* Although item element headers are always a tag and length sequence regardless of TS,
    the encoding of the length is unknown at this level. So no default impl. */
    fn encode_item_header(&self, to: &mut Self::Writer, len: u32) -> Result<()>;

    /// Encode and write a DICOM sequence item delimiter to the given destination.
    fn encode_item_delimiter(&self, to: &mut Self::Writer) -> Result<()> {
        self.encode_tag(to, Tag(0xFFFE, 0xE00D))?;
        to.write_all(&[0u8; 4])?;
        Ok(())
    }

    /// Encode and write a DICOM sequence delimiter to the given destination.
    fn encode_sequence_delimiter(&self, to: &mut Self::Writer) -> Result<()> {
        self.encode_tag(to, Tag(0xFFFE, 0xE0DD))?;
        to.write_all(&[0u8; 4])?;
        Ok(())
    }
}