dicom_toolkit_data/
meta_info.rs1use crate::dataset::DataSet;
6use crate::element::Element;
7use dicom_toolkit_core::error::{DcmError, DcmResult};
8use dicom_toolkit_dict::{tags, Vr};
9
10pub const META_VERSION: [u8; 2] = [0x00, 0x01];
14
15pub const IMPL_CLASS_UID: &str = "1.2.276.0.7230010.3.1.9999.1";
17
18pub const IMPL_VERSION_NAME: &str = "DCMTK-RS-0.1";
20
21#[derive(Debug, Clone, PartialEq)]
28pub struct FileMetaInformation {
29 pub media_storage_sop_class_uid: String,
30 pub media_storage_sop_instance_uid: String,
31 pub transfer_syntax_uid: String,
32 pub implementation_class_uid: String,
33 pub implementation_version_name: String,
34}
35
36impl FileMetaInformation {
37 pub fn new(sop_class_uid: &str, sop_instance_uid: &str, ts_uid: &str) -> Self {
39 Self {
40 media_storage_sop_class_uid: sop_class_uid.to_string(),
41 media_storage_sop_instance_uid: sop_instance_uid.to_string(),
42 transfer_syntax_uid: ts_uid.to_string(),
43 implementation_class_uid: IMPL_CLASS_UID.to_string(),
44 implementation_version_name: IMPL_VERSION_NAME.to_string(),
45 }
46 }
47
48 pub fn to_dataset(&self) -> DataSet {
52 let mut ds = DataSet::new();
53
54 ds.insert(Element::bytes(
55 tags::FILE_META_INFORMATION_VERSION,
56 Vr::OB,
57 META_VERSION.to_vec(),
58 ));
59 ds.insert(Element::uid(
60 tags::MEDIA_STORAGE_SOP_CLASS_UID,
61 &self.media_storage_sop_class_uid,
62 ));
63 ds.insert(Element::uid(
64 tags::MEDIA_STORAGE_SOP_INSTANCE_UID,
65 &self.media_storage_sop_instance_uid,
66 ));
67 ds.insert(Element::uid(
68 tags::TRANSFER_SYNTAX_UID,
69 &self.transfer_syntax_uid,
70 ));
71 ds.insert(Element::uid(
72 tags::IMPLEMENTATION_CLASS_UID,
73 &self.implementation_class_uid,
74 ));
75 ds.insert(Element::string(
76 tags::IMPLEMENTATION_VERSION_NAME,
77 Vr::SH,
78 &self.implementation_version_name,
79 ));
80
81 ds
82 }
83
84 pub fn from_dataset(ds: &DataSet) -> DcmResult<Self> {
86 let transfer_syntax_uid = ds
87 .get_string(tags::TRANSFER_SYNTAX_UID)
88 .ok_or_else(|| DcmError::InvalidFile {
89 reason: "missing Transfer Syntax UID (0002,0010)".into(),
90 })?
91 .trim_end_matches('\0')
92 .to_string();
93
94 let media_storage_sop_class_uid = ds
95 .get_string(tags::MEDIA_STORAGE_SOP_CLASS_UID)
96 .unwrap_or("")
97 .trim_end_matches('\0')
98 .to_string();
99
100 let media_storage_sop_instance_uid = ds
101 .get_string(tags::MEDIA_STORAGE_SOP_INSTANCE_UID)
102 .unwrap_or("")
103 .trim_end_matches('\0')
104 .to_string();
105
106 let implementation_class_uid = ds
107 .get_string(tags::IMPLEMENTATION_CLASS_UID)
108 .unwrap_or(IMPL_CLASS_UID)
109 .trim_end_matches('\0')
110 .to_string();
111
112 let implementation_version_name = ds
113 .get_string(tags::IMPLEMENTATION_VERSION_NAME)
114 .unwrap_or(IMPL_VERSION_NAME)
115 .trim_end_matches('\0')
116 .to_string();
117
118 Ok(Self {
119 media_storage_sop_class_uid,
120 media_storage_sop_instance_uid,
121 transfer_syntax_uid,
122 implementation_class_uid,
123 implementation_version_name,
124 })
125 }
126}
127
128#[cfg(test)]
131mod tests {
132 use super::*;
133
134 #[test]
135 fn meta_roundtrip_to_from_dataset() {
136 let meta = FileMetaInformation::new(
137 "1.2.840.10008.5.1.4.1.1.2",
138 "1.2.3.4.5.6.7",
139 "1.2.840.10008.1.2.1",
140 );
141 let ds = meta.to_dataset();
142 let back = FileMetaInformation::from_dataset(&ds).unwrap();
143 assert_eq!(meta.transfer_syntax_uid, back.transfer_syntax_uid);
144 assert_eq!(
145 meta.media_storage_sop_class_uid,
146 back.media_storage_sop_class_uid
147 );
148 assert_eq!(
149 meta.media_storage_sop_instance_uid,
150 back.media_storage_sop_instance_uid
151 );
152 }
153
154 #[test]
155 fn meta_from_dataset_missing_ts_uid_errors() {
156 let ds = DataSet::new();
157 assert!(FileMetaInformation::from_dataset(&ds).is_err());
158 }
159
160 #[test]
161 fn meta_to_dataset_has_version() {
162 let meta = FileMetaInformation::new("", "", "1.2.840.10008.1.2.1");
163 let ds = meta.to_dataset();
164 let ver = ds.get_bytes(tags::FILE_META_INFORMATION_VERSION).unwrap();
165 assert_eq!(ver, &[0x00, 0x01]);
166 }
167}