Skip to content

Commit 7586321

Browse files
authored
Merge pull request Enet4#35 from Enet4/imp/stateful
DICOM object writing
2 parents cdcc2b1 + bad24e0 commit 7586321

File tree

20 files changed

+1721
-594
lines changed

20 files changed

+1721
-594
lines changed

core/src/header.rs

Lines changed: 96 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,33 @@
33
//! element header, and element composite types.
44
55
use crate::error::{Error, Result};
6-
use crate::value::{DicomValueType, PrimitiveValue, Value};
6+
use crate::value::{PrimitiveValue, Value};
77
use std::borrow::Cow;
88
use std::cmp::Ordering;
99
use std::fmt;
1010
use std::str::{from_utf8, FromStr};
1111

12+
/// Trait for any DICOM entity (element or item) which may have a length.
13+
pub trait HasLength {
14+
/// Retrieve the value data's length as specified by the data element or
15+
/// item, in bytes.
16+
///
17+
/// It is named `length` to make it distinct from the conventional method
18+
/// signature `len(&self) -> usize` for the number of elements of a
19+
/// collection.
20+
///
21+
/// According to the standard, the concrete value size may be undefined,
22+
/// which can be the case for sequence elements or specific primitive
23+
/// values.
24+
fn length(&self) -> Length;
25+
}
26+
1227
/// A trait for a data type containing a DICOM header.
1328
#[allow(clippy::len_without_is_empty)]
14-
pub trait Header {
29+
pub trait Header: HasLength {
1530
/// Retrieve the element's tag as a `(group, element)` tuple.
1631
fn tag(&self) -> Tag;
1732

18-
/// Retrieve the value data's length as specified by the data element, in bytes.
19-
/// According to the standard, the concrete value size may be undefined,
20-
/// which can be the case for sequence elements or specific primitive values.
21-
fn len(&self) -> Length;
22-
2333
/// Check whether this is the header of an item.
2434
fn is_item(&self) -> bool {
2535
self.tag() == Tag(0xFFFE, 0xE000)
@@ -36,9 +46,23 @@ pub trait Header {
3646
}
3747
}
3848

49+
/// Stub type representing a non-existing DICOM object.
50+
///
51+
/// This type implements `HasLength`, but cannot be instantiated.
52+
/// This makes it so that `Value<EmptyObject>` is sure to be either a primitive
53+
/// value or a sequence with no items.
54+
#[derive(Debug, PartialEq)]
55+
pub enum EmptyObject {}
56+
57+
impl HasLength for EmptyObject {
58+
fn length(&self) -> Length {
59+
unreachable!()
60+
}
61+
}
62+
3963
/// A data type that represents and owns a DICOM data element. Unlike
4064
/// [`PrimitiveDataElement`], this type may contain multiple data elements
41-
/// through the item sequence VR (of type `I`).
65+
/// through the item sequence VR (where each item contains an object of type `I`).
4266
#[derive(Debug, PartialEq, Clone)]
4367
pub struct DataElement<I> {
4468
header: DataElementHeader,
@@ -91,15 +115,24 @@ impl<'a> PrimitiveDataElementRef<'a> {
91115
PrimitiveDataElementRef { header, value }
92116
}
93117
}
118+
impl<I> HasLength for DataElement<I> {
119+
#[inline]
120+
fn length(&self) -> Length {
121+
self.header.length()
122+
}
123+
}
124+
94125
impl<I> Header for DataElement<I> {
95126
#[inline]
96127
fn tag(&self) -> Tag {
97128
self.header.tag()
98129
}
130+
}
99131

132+
impl<I> HasLength for &DataElement<I> {
100133
#[inline]
101-
fn len(&self) -> Length {
102-
self.header.len()
134+
fn length(&self) -> Length {
135+
(**self).length()
103136
}
104137
}
105138

@@ -109,9 +142,12 @@ impl<'a, I> Header for &'a DataElement<I> {
109142
(**self).tag()
110143
}
111144

145+
}
146+
147+
impl<'v, I> HasLength for DataElementRef<'v, I> {
112148
#[inline]
113-
fn len(&self) -> Length {
114-
(**self).len()
149+
fn length(&self) -> Length {
150+
self.header.length()
115151
}
116152
}
117153

@@ -120,17 +156,9 @@ impl<'v, I> Header for DataElementRef<'v, I> {
120156
fn tag(&self) -> Tag {
121157
self.header.tag()
122158
}
123-
124-
#[inline]
125-
fn len(&self) -> Length {
126-
self.header.len()
127-
}
128159
}
129160

130-
impl<I> DataElement<I>
131-
where
132-
I: DicomValueType,
133-
{
161+
impl<I> DataElement<I> {
134162
/// Create an empty data element.
135163
pub fn empty(tag: Tag, vr: VR) -> Self {
136164
DataElement {
@@ -143,24 +171,17 @@ where
143171
}
144172
}
145173

146-
/// Create a primitive data element from the given parts. This method will not check
147-
/// whether the value representation is compatible with the given value.
148-
pub fn new(tag: Tag, vr: VR, value: Value<I>) -> Self {
149-
DataElement {
150-
header: DataElementHeader {
151-
tag,
152-
vr,
153-
len: value.size(),
154-
},
155-
value,
156-
}
157-
}
158-
159174
/// Retrieve the element header.
160175
pub fn header(&self) -> &DataElementHeader {
161176
&self.header
162177
}
163178

179+
/// Retrieve the value representation, which may be unknown or not
180+
/// applicable.
181+
pub fn vr(&self) -> VR {
182+
self.header.vr()
183+
}
184+
164185
/// Retrieve the data value.
165186
pub fn value(&self) -> &Value<I> {
166187
&self.value
@@ -172,11 +193,25 @@ where
172193
pub fn into_value(self) -> Value<I> {
173194
self.value
174195
}
196+
}
175197

176-
/// Retrieve the value representation, which may be unknown or not
177-
/// applicable.
178-
pub fn vr(&self) -> VR {
179-
self.header.vr()
198+
impl<I> DataElement<I>
199+
where
200+
I: HasLength,
201+
{
202+
/// Create a primitive data element from the given parts.
203+
///
204+
/// This method will not check whether the value representation is
205+
/// compatible with the given value.
206+
pub fn new(tag: Tag, vr: VR, value: Value<I>) -> Self {
207+
DataElement {
208+
header: DataElementHeader {
209+
tag,
210+
vr,
211+
len: value.length(),
212+
},
213+
value,
214+
}
180215
}
181216

182217
/// Retrieve the element's value as a single string.
@@ -187,7 +222,7 @@ where
187222

188223
impl<'v, I> DataElementRef<'v, I>
189224
where
190-
I: DicomValueType,
225+
I: HasLength,
191226
{
192227
/// Create a data element from the given parts. This method will not check
193228
/// whether the value representation is compatible with the value. Caution
@@ -197,7 +232,7 @@ where
197232
header: DataElementHeader {
198233
tag,
199234
vr,
200-
len: value.size(),
235+
len: value.length(),
201236
},
202237
value,
203238
}
@@ -226,19 +261,24 @@ pub struct DataElementHeader {
226261
pub len: Length,
227262
}
228263

264+
impl HasLength for DataElementHeader {
265+
#[inline]
266+
fn length(&self) -> Length {
267+
self.len
268+
}
269+
}
270+
229271
impl Header for DataElementHeader {
272+
#[inline]
230273
fn tag(&self) -> Tag {
231274
self.tag
232275
}
233-
234-
fn len(&self) -> Length {
235-
self.len
236-
}
237276
}
238277

239278
impl DataElementHeader {
240279
/// Create a new data element header with the given properties.
241280
/// This is just a trivial constructor.
281+
#[inline]
242282
pub fn new<T: Into<Tag>>(tag: T, vr: VR, len: Length) -> DataElementHeader {
243283
DataElementHeader {
244284
tag: tag.into(),
@@ -248,6 +288,7 @@ impl DataElementHeader {
248288
}
249289

250290
/// Retrieve the element's value representation, which can be unknown.
291+
#[inline]
251292
pub fn vr(&self) -> VR {
252293
self.vr
253294
}
@@ -258,7 +299,7 @@ impl From<SequenceItemHeader> for DataElementHeader {
258299
DataElementHeader {
259300
tag: value.tag(),
260301
vr: VR::UN,
261-
len: value.len(),
302+
len: value.length(),
262303
}
263304
}
264305
}
@@ -309,21 +350,24 @@ impl SequenceItemHeader {
309350
}
310351
}
311352

353+
impl HasLength for SequenceItemHeader {
354+
#[inline]
355+
fn length(&self) -> Length {
356+
match *self {
357+
SequenceItemHeader::Item { len } => len,
358+
SequenceItemHeader::ItemDelimiter | SequenceItemHeader::SequenceDelimiter => Length(0),
359+
}
360+
}
361+
}
312362
impl Header for SequenceItemHeader {
363+
#[inline]
313364
fn tag(&self) -> Tag {
314365
match *self {
315366
SequenceItemHeader::Item { .. } => Tag(0xFFFE, 0xE000),
316367
SequenceItemHeader::ItemDelimiter => Tag(0xFFFE, 0xE00D),
317368
SequenceItemHeader::SequenceDelimiter => Tag(0xFFFE, 0xE0DD),
318369
}
319370
}
320-
321-
fn len(&self) -> Length {
322-
match *self {
323-
SequenceItemHeader::Item { len } => len,
324-
SequenceItemHeader::ItemDelimiter | SequenceItemHeader::SequenceDelimiter => Length(0),
325-
}
326-
}
327371
}
328372

329373
/// An enum type for a DICOM value representation.

0 commit comments

Comments
 (0)