///|
/// A decoded DICOM element value.
pub(all) enum Value {
Text(String)
Integer(Int)
Bytes(Bytes)
} derive(Eq, Debug)
///|
/// One DICOM data element.
pub(all) struct DataElement {
tag : Tag
vr : ValueRepresentation
value : Value
} derive(Eq, Debug)
///|
/// Construct a data element.
pub fn data_element(
tag : Tag,
vr : ValueRepresentation,
value : Value,
) -> DataElement {
{ tag, vr, value }
}
///|
/// The ordered elements in a DICOM data set.
pub(all) struct DataSet {
elements : Array[DataElement]
} derive(Eq, Debug)
///|
/// Create an empty data set.
pub fn data_set() -> DataSet {
{ elements: [] }
}
///|
/// Return the number of elements.
pub fn DataSet::length(self : DataSet) -> Int {
self.elements.length()
}
///|
/// Return all elements in file order.
pub fn DataSet::elements(self : DataSet) -> Array[DataElement] {
self.elements.copy()
}
///|
/// Find an element by tag.
pub fn DataSet::get(self : DataSet, tag : Tag) -> DataElement? {
for element in self.elements {
if element.tag == tag {
return Some(element)
}
}
None
}
///|
/// Add or replace an element while preserving its position when replacing.
pub fn DataSet::set(self : DataSet, element : DataElement) -> Unit {
for index, current in self.elements {
if current.tag == element.tag {
self.elements[index] = element
return
}
}
self.elements.push(element)
}
///|
/// Remove an element by tag.
pub fn DataSet::remove(self : DataSet, tag : Tag) -> Bool {
for index, element in self.elements {
if element.tag == tag {
ignore(self.elements.remove(index))
return true
}
}
false
}
///|
/// Return a text value when the element contains text.
pub fn DataSet::get_text(self : DataSet, tag : Tag) -> String? {
match self.get(tag) {
Some({ value: Text(text), .. }) => Some(text)
_ => None
}
}
///|
/// Return an integer value when the element contains an integer.
pub fn DataSet::get_int(self : DataSet, tag : Tag) -> Int? {
match self.get(tag) {
Some({ value: Integer(value), .. }) => Some(value)
_ => None
}
}
///|
/// Return raw bytes when the element contains bytes.
pub fn DataSet::get_bytes(self : DataSet, tag : Tag) -> Bytes? {
match self.get(tag) {
Some({ value: Bytes(value), .. }) => Some(value)
_ => None
}
}
///|
fn trim_dicom_text(bytes : Bytes) -> String {
let text = bytes_to_ascii(bytes)
text.trim(chars=" ").to_owned()
}
///|
fn decode_value(vr : ValueRepresentation, bytes : Bytes) -> Value {
if vr.is_text() {
Text(trim_dicom_text(bytes))
} else {
match vr {
US if bytes.length() >= 2 => {
let low = bytes[0].to_int()
let high = bytes[1].to_int()
Integer(low + high * 256)
}
SS if bytes.length() >= 2 => {
let low = bytes[0].to_int()
let high = bytes[1].to_int()
let raw = low + high * 256
Integer(if raw >= 32768 { raw - 65536 } else { raw })
}
UL if bytes.length() >= 4 => {
let value = bytes[0].to_int() +
bytes[1].to_int() * 256 +
bytes[2].to_int() * 65536 +
bytes[3].to_int() * 16777216
Integer(value)
}
SL if bytes.length() >= 4 => {
let raw = bytes[0].to_int() +
bytes[1].to_int() * 256 +
bytes[2].to_int() * 65536 +
bytes[3].to_int() * 16777216
Integer(
if bytes[3].to_int() >= 128 {
raw - 2147483647 - 1 - 2147483647 - 1
} else {
raw
},
)
}
_ => Bytes(bytes)
}
}
}