Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ENH: Add lookup and putting of private elements #508

Merged
merged 11 commits into from
Apr 25, 2024
8 changes: 4 additions & 4 deletions object/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,12 +290,12 @@ pub enum WriteError {
#[derive(Debug, Snafu)]
#[non_exhaustive]
pub enum PrivateElementError {
#[snafu(display("Group number must be odd, found {}", group))]
#[snafu(display("Group number must be odd, found {:#06x}", group))]
InvalidGroup { group: GroupNumber },
#[snafu(display("Private creator {} not found in group {}", creator, group))]
#[snafu(display("Private creator {} not found in group {:#06x}", creator, group))]
PrivateCreatorNotFound { creator: String, group: GroupNumber },
#[snafu(display(
"Private Creator {} found in group {}, but elem {} not found",
"Private Creator {} found in group {:#06x}, but elem {:#06x} not found",
creator,
group,
elem
Expand All @@ -305,7 +305,7 @@ pub enum PrivateElementError {
group: GroupNumber,
elem: u8,
},
#[snafu(display("No space available in group {}", group))]
#[snafu(display("No space available in group {:#06x}", group))]
NoSpace { group: GroupNumber },
}

Expand Down
96 changes: 96 additions & 0 deletions object/src/mem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -715,6 +715,33 @@ where
None
}

/// Get a private element from the dataset using the group number, creator and element number.
///
/// For more info, see the [DICOM standard section on private elements](https://dicom.nema.org/medical/dicom/2024a/output/chtml/part05/sect_7.8.html)
///
/// ## Example
///
/// ```
/// # use dicom_core::{VR, PrimitiveValue, Tag, DataElement};
/// # use dicom_object::InMemDicomObject;
///
/// let mut ds = InMemDicomObject::from_element_iter(vec![
/// DataElement::new(
/// Tag(0x0009, 0x0010),
/// VR::LO,
/// PrimitiveValue::from("CREATOR 1"),
/// ),
/// DataElement::new(Tag(0x0009, 0x01001), VR::DS, PrimitiveValue::from("1.0")),
/// ]);
/// assert_eq!(
/// ds.private_element(0x0009, "CREATOR 1", 0x01)
/// .unwrap()
/// .value()
/// .to_str()
/// .unwrap(),
/// "1.0"
/// );
/// ```
pub fn private_element(
naterichman marked this conversation as resolved.
Show resolved Hide resolved
&self,
group: GroupNumber,
Expand Down Expand Up @@ -758,6 +785,45 @@ where
self.entries.insert(elt.tag(), elt)
}

/// Insert a private element into the dataset, replacing (and returning) any
/// previous element of the same attribute.
///
/// This function will find the next available private element block in the given
/// group. If the creator already exists, the element will be added to the block
/// already reserved for that creator. If it does not exist, then a new block
/// will be reserved for the creator in the specified group.
///
/// For more info, see the [DICOM standard section on private elements](https://dicom.nema.org/medical/dicom/2024a/output/chtml/part05/sect_7.8.html)
///
/// ## Example
/// ```
/// # use dicom_core::{VR, PrimitiveValue, Tag, DataElement, header::Header};
/// # use dicom_object::InMemDicomObject;
/// let mut ds = InMemDicomObject::new_empty();
/// ds.put_private_element(
/// 0x0009,
/// "CREATOR 1",
/// 0x02,
/// VR::DS,
/// PrimitiveValue::Str("1.0".to_string()),
/// )
/// .unwrap();
/// assert_eq!(
/// ds.private_element(0x0009, "CREATOR 1", 0x02)
/// .unwrap()
Enet4 marked this conversation as resolved.
Show resolved Hide resolved
/// .value()
/// .to_str()
/// .unwrap(),
/// "1.0"
/// );
/// assert_eq!(
/// ds.private_element(0x0009, "CREATOR 1", 0x02)
/// .unwrap()
/// .header()
/// .tag(),
/// Tag(0x0009, 0x0102)
/// );
/// ```
pub fn put_private_element(
&mut self,
group: GroupNumber,
Expand Down Expand Up @@ -3731,6 +3797,19 @@ mod tests {
PrimitiveValue::Str("1.0".to_string()),
)
.unwrap();

let res = ds.put_private_element(
0x0012,
"CREATOR 4",
0x02,
VR::DS,
PrimitiveValue::Str("1.0".to_string()),
);
assert_eq!(
&res.err().unwrap().to_string(),
"Group number must be odd, found 0x0012"
);

assert_eq!(
ds.private_element(0x0009, "CREATOR 1", 0x01)
.unwrap()
Expand All @@ -3755,4 +3834,21 @@ mod tests {
Tag(0x0009, 0x1202)
);
}

#[test]
fn private_element_group_full() {
let mut ds = InMemDicomObject::from_element_iter(
(0..=0x00FFu16)
.into_iter()
.map(|i| {
DataElement::new(Tag(0x0009, i), VR::LO, PrimitiveValue::from("CREATOR 1"))
})
.collect::<Vec<DataElement<_>>>(),
);
let res = ds.put_private_element(0x0009, "TEST", 0x01, VR::DS, PrimitiveValue::from("1.0"));
assert_eq!(
res.err().unwrap().to_string(),
"No space available in group 0x0009"
);
}
}