1use crate::element::Element;
7use crate::value::Value;
8use dicom_toolkit_core::error::{DcmError, DcmResult};
9use dicom_toolkit_dict::{Tag, Vr};
10use indexmap::IndexMap;
11
12#[derive(Debug, Clone, Default, PartialEq)]
16pub struct DataSet {
17 elements: IndexMap<Tag, Element>,
18}
19
20impl DataSet {
21 pub fn new() -> Self {
22 Self {
23 elements: IndexMap::new(),
24 }
25 }
26
27 pub fn insert(&mut self, element: Element) {
31 self.elements.insert(element.tag, element);
32 self.elements.sort_unstable_keys();
33 }
34
35 pub fn get(&self, tag: Tag) -> Option<&Element> {
36 self.elements.get(&tag)
37 }
38
39 pub fn get_mut(&mut self, tag: Tag) -> Option<&mut Element> {
40 self.elements.get_mut(&tag)
41 }
42
43 pub fn remove(&mut self, tag: Tag) -> Option<Element> {
44 self.elements.swap_remove(&tag)
45 }
46
47 pub fn contains(&self, tag: Tag) -> bool {
48 self.elements.contains_key(&tag)
49 }
50
51 pub fn len(&self) -> usize {
52 self.elements.len()
53 }
54
55 pub fn is_empty(&self) -> bool {
56 self.elements.is_empty()
57 }
58
59 pub fn iter(&self) -> impl Iterator<Item = (&Tag, &Element)> {
60 self.elements.iter()
61 }
62
63 pub fn tags(&self) -> impl Iterator<Item = Tag> + '_ {
64 self.elements.keys().copied()
65 }
66
67 pub fn find_element(&self, tag: Tag) -> DcmResult<&Element> {
69 self.elements.get(&tag).ok_or(DcmError::UnknownTag {
70 group: tag.group,
71 element: tag.element,
72 })
73 }
74
75 pub fn get_string(&self, tag: Tag) -> Option<&str> {
78 self.get(tag)?.string_value()
79 }
80
81 pub fn get_strings(&self, tag: Tag) -> Option<&[String]> {
82 self.get(tag)?.strings_value()
83 }
84
85 pub fn get_u16(&self, tag: Tag) -> Option<u16> {
86 self.get(tag)?.u16_value()
87 }
88
89 pub fn get_u32(&self, tag: Tag) -> Option<u32> {
90 self.get(tag)?.u32_value()
91 }
92
93 pub fn get_i32(&self, tag: Tag) -> Option<i32> {
94 self.get(tag)?.i32_value()
95 }
96
97 pub fn get_f64(&self, tag: Tag) -> Option<f64> {
98 self.get(tag)?.f64_value()
99 }
100
101 pub fn get_bytes(&self, tag: Tag) -> Option<&[u8]> {
102 self.get(tag)?.bytes_value()
103 }
104
105 pub fn get_items(&self, tag: Tag) -> Option<&[DataSet]> {
106 self.get(tag)?.items()
107 }
108
109 pub fn set_string(&mut self, tag: Tag, vr: Vr, value: &str) {
112 self.insert(Element::string(tag, vr, value));
113 }
114
115 pub fn set_strings(&mut self, tag: Tag, vr: Vr, values: Vec<String>) {
116 self.insert(Element::new(tag, vr, Value::Strings(values)));
117 }
118
119 pub fn set_u16(&mut self, tag: Tag, value: u16) {
120 self.insert(Element::u16(tag, value));
121 }
122
123 pub fn set_u32(&mut self, tag: Tag, value: u32) {
124 self.insert(Element::u32(tag, value));
125 }
126
127 pub fn set_i32(&mut self, tag: Tag, value: i32) {
128 self.insert(Element::i32(tag, value));
129 }
130
131 pub fn set_f64(&mut self, tag: Tag, value: f64) {
132 self.insert(Element::f64(tag, value));
133 }
134
135 pub fn set_bytes(&mut self, tag: Tag, vr: Vr, data: Vec<u8>) {
136 self.insert(Element::bytes(tag, vr, data));
137 }
138
139 pub fn set_sequence(&mut self, tag: Tag, items: Vec<DataSet>) {
140 self.insert(Element::sequence(tag, items));
141 }
142
143 pub fn set_uid(&mut self, tag: Tag, uid: &str) {
144 self.insert(Element::uid(tag, uid));
145 }
146}
147
148#[cfg(test)]
151mod tests {
152 use super::*;
153 use dicom_toolkit_dict::tags;
154
155 #[test]
156 fn dataset_insert_and_get() {
157 let mut ds = DataSet::new();
158 ds.set_u16(tags::ROWS, 512);
159 assert_eq!(ds.get_u16(tags::ROWS), Some(512));
160 }
161
162 #[test]
163 fn dataset_contains_remove() {
164 let mut ds = DataSet::new();
165 ds.set_string(tags::PATIENT_NAME, Vr::PN, "Smith^John");
166 assert!(ds.contains(tags::PATIENT_NAME));
167 let removed = ds.remove(tags::PATIENT_NAME).unwrap();
168 assert_eq!(removed.string_value(), Some("Smith^John"));
169 assert!(!ds.contains(tags::PATIENT_NAME));
170 }
171
172 #[test]
173 fn dataset_len_is_empty() {
174 let mut ds = DataSet::new();
175 assert!(ds.is_empty());
176 assert_eq!(ds.len(), 0);
177 ds.set_u16(tags::ROWS, 1);
178 assert!(!ds.is_empty());
179 assert_eq!(ds.len(), 1);
180 }
181
182 #[test]
183 fn dataset_tag_order_ascending() {
184 let mut ds = DataSet::new();
186 ds.set_u16(tags::COLUMNS, 256); ds.set_u16(tags::ROWS, 512); ds.set_string(tags::PATIENT_NAME, Vr::PN, "Doe^Jane"); let tags: Vec<Tag> = ds.tags().collect();
191 assert!(
192 tags.windows(2).all(|w| w[0] < w[1]),
193 "tags not in order: {:?}",
194 tags
195 );
196 }
197
198 #[test]
199 fn dataset_convenience_getters() {
200 let mut ds = DataSet::new();
201 ds.set_string(tags::PATIENT_ID, Vr::LO, "PID001");
202 ds.set_strings(
203 tags::IMAGE_TYPE,
204 Vr::CS,
205 vec!["ORIGINAL".into(), "PRIMARY".into()],
206 );
207 ds.set_u16(tags::ROWS, 512);
208 ds.set_u32(Tag::new(0x0028, 0x0000), 42);
209 ds.set_i32(Tag::new(0x0020, 0x0013), -1);
210 ds.set_f64(Tag::new(0x0028, 0x1050), 1024.0);
211 ds.set_uid(tags::SOP_CLASS_UID, "1.2.840.10008.1.1");
212
213 assert_eq!(ds.get_string(tags::PATIENT_ID), Some("PID001"));
214 assert_eq!(ds.get_strings(tags::IMAGE_TYPE).unwrap().len(), 2);
215 assert_eq!(ds.get_u16(tags::ROWS), Some(512));
216 assert_eq!(ds.get_u32(Tag::new(0x0028, 0x0000)), Some(42));
217 assert_eq!(ds.get_i32(Tag::new(0x0020, 0x0013)), Some(-1));
218 assert!((ds.get_f64(Tag::new(0x0028, 0x1050)).unwrap() - 1024.0).abs() < 1e-9);
219 assert_eq!(
220 ds.get_string(tags::SOP_CLASS_UID),
221 Some("1.2.840.10008.1.1")
222 );
223 }
224
225 #[test]
226 fn dataset_set_bytes() {
227 let mut ds = DataSet::new();
228 let data = vec![0u8, 1, 2, 3];
229 ds.set_bytes(Tag::new(0x0042, 0x0011), Vr::OB, data.clone());
230 assert_eq!(
231 ds.get_bytes(Tag::new(0x0042, 0x0011)),
232 Some(data.as_slice())
233 );
234 }
235
236 #[test]
237 fn dataset_nested_sequence() {
238 let mut item = DataSet::new();
239 item.set_string(tags::PATIENT_NAME, Vr::PN, "Jones^Bob");
240
241 let mut ds = DataSet::new();
242 ds.set_sequence(Tag::new(0x0008, 0x1115), vec![item]);
243
244 let items = ds.get_items(Tag::new(0x0008, 0x1115)).unwrap();
245 assert_eq!(items.len(), 1);
246 assert_eq!(items[0].get_string(tags::PATIENT_NAME), Some("Jones^Bob"));
247 }
248
249 #[test]
250 fn dataset_find_element_ok() {
251 let mut ds = DataSet::new();
252 ds.set_u16(tags::ROWS, 512);
253 assert!(ds.find_element(tags::ROWS).is_ok());
254 }
255
256 #[test]
257 fn dataset_find_element_not_found() {
258 let ds = DataSet::new();
259 let err = ds.find_element(tags::ROWS).unwrap_err();
260 assert!(matches!(err, DcmError::UnknownTag { .. }));
262 }
263
264 #[test]
265 fn dataset_iter() {
266 let mut ds = DataSet::new();
267 ds.set_u16(tags::ROWS, 512);
268 ds.set_u16(tags::COLUMNS, 256);
269 let count = ds.iter().count();
270 assert_eq!(count, 2);
271 }
272
273 #[test]
274 fn dataset_overwrite() {
275 let mut ds = DataSet::new();
276 ds.set_u16(tags::ROWS, 512);
277 ds.set_u16(tags::ROWS, 1024);
278 assert_eq!(ds.len(), 1);
279 assert_eq!(ds.get_u16(tags::ROWS), Some(1024));
280 }
281}