use crate::value::{
CastValueError, ConvertValueError, DataSetSequence, DicomDate, DicomDateTime, DicomTime,
InMemFragment, PrimitiveValue, Value, C,
};
use num_traits::NumCast;
use snafu::{ensure, Backtrace, Snafu};
use std::borrow::Cow;
use std::cmp::Ordering;
use std::fmt;
use std::str::{from_utf8, FromStr};
#[derive(Debug, Snafu)]
#[non_exhaustive]
pub enum SequenceItemHeaderError {
#[snafu(display("Unexpected tag {}", tag))]
UnexpectedTag { tag: Tag, backtrace: Backtrace },
#[snafu(display("Unexpected delimiter length {}", len))]
UnexpectedDelimiterLength { len: Length, backtrace: Backtrace },
}
type Result<T, E = SequenceItemHeaderError> = std::result::Result<T, E>;
pub trait HasLength {
fn length(&self) -> Length;
fn is_empty(&self) -> bool {
self.length() == Length(0)
}
}
#[allow(clippy::len_without_is_empty)]
pub trait Header: HasLength {
fn tag(&self) -> Tag;
fn is_item(&self) -> bool {
self.tag() == Tag(0xFFFE, 0xE000)
}
fn is_item_delimiter(&self) -> bool {
self.tag() == Tag(0xFFFE, 0xE00D)
}
fn is_sequence_delimiter(&self) -> bool {
self.tag() == Tag(0xFFFE, 0xE0DD)
}
fn is_encapsulated_pixeldata(&self) -> bool {
self.tag() == Tag(0x7FE0, 0x0010) && self.length().is_undefined()
}
}
#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq, Ord, PartialOrd)]
pub enum EmptyObject {}
impl HasLength for EmptyObject {
fn length(&self) -> Length {
unreachable!()
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct DataElement<I = EmptyObject, P = InMemFragment> {
header: DataElementHeader,
value: Value<I, P>,
}
#[derive(Debug, PartialEq, Clone)]
pub struct PrimitiveDataElement {
header: DataElementHeader,
value: PrimitiveValue,
}
impl PrimitiveDataElement {
pub fn new(header: DataElementHeader, value: PrimitiveValue) -> Self {
PrimitiveDataElement { header, value }
}
}
impl<I, P> From<PrimitiveDataElement> for DataElement<I, P> {
fn from(o: PrimitiveDataElement) -> Self {
DataElement {
header: o.header,
value: o.value.into(),
}
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct DataElementRef<'v, I: 'v, P: 'v> {
header: DataElementHeader,
value: &'v Value<I, P>,
}
#[derive(Debug, PartialEq, Clone)]
pub struct PrimitiveDataElementRef<'v> {
header: DataElementHeader,
value: &'v PrimitiveValue,
}
impl<'a> PrimitiveDataElementRef<'a> {
pub fn new(header: DataElementHeader, value: &'a PrimitiveValue) -> Self {
PrimitiveDataElementRef { header, value }
}
}
impl<I, P> HasLength for DataElement<I, P> {
#[inline]
fn length(&self) -> Length {
self.header.length()
}
}
impl<I, P> Header for DataElement<I, P> {
#[inline]
fn tag(&self) -> Tag {
self.header.tag()
}
}
impl<I, P> HasLength for &DataElement<I, P> {
#[inline]
fn length(&self) -> Length {
(**self).length()
}
}
impl<I, P> Header for &'_ DataElement<I, P> {
#[inline]
fn tag(&self) -> Tag {
(**self).tag()
}
}
impl<I, P> HasLength for DataElementRef<'_, I, P> {
#[inline]
fn length(&self) -> Length {
self.header.length()
}
}
impl<I, P> Header for DataElementRef<'_, I, P> {
#[inline]
fn tag(&self) -> Tag {
self.header.tag()
}
}
impl<I, P> DataElement<I, P> {
pub fn empty(tag: Tag, vr: VR) -> Self {
DataElement {
header: DataElementHeader {
tag,
vr,
len: Length(0),
},
value: if vr == VR::SQ {
DataSetSequence::empty().into()
} else {
PrimitiveValue::Empty.into()
},
}
}
pub fn header(&self) -> &DataElementHeader {
&self.header
}
pub fn vr(&self) -> VR {
self.header.vr()
}
pub fn value(&self) -> &Value<I, P> {
&self.value
}
pub fn into_value(self) -> Value<I, P> {
self.value
}
pub fn into_parts(self) -> (DataElementHeader, Value<I, P>) {
(self.header, self.value)
}
pub fn update_value(&mut self, mut f: impl FnMut(&mut Value<I, P>)) {
f(&mut self.value);
match &mut self.value {
Value::Primitive(v) => {
let byte_len = v.calculate_byte_len();
self.header.len = Length(byte_len as u32);
}
Value::Sequence(_) => {
self.header.vr = VR::SQ;
self.header.len = Length::UNDEFINED;
}
Value::PixelSequence(_) => {
self.header.vr = VR::OB;
self.header.len = Length::UNDEFINED;
}
}
}
}
impl<I, P> DataElement<I, P>
where
I: HasLength,
{
pub fn new<T>(tag: Tag, vr: VR, value: T) -> Self
where
T: Into<Value<I, P>>,
{
let value = value.into();
DataElement {
header: DataElementHeader {
tag,
vr,
len: value.length(),
},
value,
}
}
pub fn new_with_len<T>(tag: Tag, vr: VR, length: Length, value: T) -> Self
where
T: Into<Value<I, P>>,
{
let value = value.into();
DataElement {
header: DataElementHeader {
tag,
vr,
len: length,
},
value,
}
}
pub fn to_str(&self) -> Result<Cow<'_, str>, ConvertValueError> {
self.value.to_str()
}
pub fn to_raw_str(&self) -> Result<Cow<'_, str>, ConvertValueError> {
self.value.to_raw_str()
}
pub fn to_bytes(&self) -> Result<Cow<'_, [u8]>, ConvertValueError> {
self.value.to_bytes()
}
pub fn to_multi_str(&self) -> Result<Cow<'_, [String]>, CastValueError> {
self.value().to_multi_str()
}
pub fn to_int<T>(&self) -> Result<T, ConvertValueError>
where
T: Clone,
T: NumCast,
T: FromStr<Err = std::num::ParseIntError>,
{
self.value().to_int()
}
pub fn to_multi_int<T>(&self) -> Result<Vec<T>, ConvertValueError>
where
T: Clone,
T: NumCast,
T: FromStr<Err = std::num::ParseIntError>,
{
self.value().to_multi_int()
}
pub fn to_float32(&self) -> Result<f32, ConvertValueError> {
self.value().to_float32()
}
pub fn to_multi_float32(&self) -> Result<Vec<f32>, ConvertValueError> {
self.value().to_multi_float32()
}
pub fn to_float64(&self) -> Result<f64, ConvertValueError> {
self.value().to_float64()
}
pub fn to_multi_float64(&self) -> Result<Vec<f64>, ConvertValueError> {
self.value().to_multi_float64()
}
pub fn to_date(&self) -> Result<DicomDate, ConvertValueError> {
self.value().to_date()
}
pub fn to_multi_date(&self) -> Result<Vec<DicomDate>, ConvertValueError> {
self.value().to_multi_date()
}
pub fn to_time(&self) -> Result<DicomTime, ConvertValueError> {
self.value().to_time()
}
pub fn to_multi_time(&self) -> Result<Vec<DicomTime>, ConvertValueError> {
self.value().to_multi_time()
}
pub fn to_datetime(&self) -> Result<DicomDateTime, ConvertValueError> {
self.value().to_datetime()
}
pub fn to_multi_datetime(&self) -> Result<Vec<DicomDateTime>, ConvertValueError> {
self.value().to_multi_datetime()
}
pub fn items(&self) -> Option<&[I]> {
self.value().items()
}
pub fn items_mut(&mut self) -> Option<&mut C<I>> {
self.header.len = Length::UNDEFINED;
self.value.items_mut()
}
pub fn fragments(&self) -> Option<&[P]> {
self.value().fragments()
}
pub fn fragments_mut(&mut self) -> Option<&mut C<P>> {
self.header.len = Length::UNDEFINED;
self.value.fragments_mut()
}
pub fn offset_table(&self) -> Option<&[u32]> {
self.value().offset_table()
}
}
impl<'v, I, P> DataElementRef<'v, I, P>
where
I: HasLength,
{
pub fn new(tag: Tag, vr: VR, value: &'v Value<I, P>) -> Self {
DataElementRef {
header: DataElementHeader {
tag,
vr,
len: value.length(),
},
value,
}
}
pub fn vr(&self) -> VR {
self.header.vr()
}
pub fn value(&self) -> &Value<I, P> {
self.value
}
}
macro_rules! impl_primitive_getters {
($name_single: ident, $name_multi: ident, $variant: ident, $ret: ty) => {
pub fn $name_single(&self) -> Result<$ret, CastValueError> {
self.value().$name_single()
}
pub fn $name_multi(&self) -> Result<&[$ret], CastValueError> {
self.value().$name_multi()
}
};
}
impl<I, P> DataElement<I, P> {
pub fn string(&self) -> Result<&str, CastValueError> {
self.value().string()
}
pub fn strings(&self) -> Result<&[String], CastValueError> {
self.value().strings()
}
impl_primitive_getters!(date, dates, Date, DicomDate);
impl_primitive_getters!(time, times, Time, DicomTime);
impl_primitive_getters!(datetime, datetimes, DateTime, DicomDateTime);
impl_primitive_getters!(uint8, uint8_slice, U8, u8);
impl_primitive_getters!(uint16, uint16_slice, U16, u16);
impl_primitive_getters!(int16, int16_slice, I16, i16);
impl_primitive_getters!(uint32, uint32_slice, U32, u32);
impl_primitive_getters!(int32, int32_slice, I32, i32);
impl_primitive_getters!(int64, int64_slice, I64, i64);
impl_primitive_getters!(uint64, uint64_slice, U64, u64);
impl_primitive_getters!(float32, float32_slice, F32, f32);
impl_primitive_getters!(float64, float64_slice, F64, f64);
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub struct DataElementHeader {
pub tag: Tag,
pub vr: VR,
pub len: Length,
}
impl HasLength for DataElementHeader {
#[inline]
fn length(&self) -> Length {
self.len
}
}
impl Header for DataElementHeader {
#[inline]
fn tag(&self) -> Tag {
self.tag
}
}
impl DataElementHeader {
#[inline]
pub fn new<T: Into<Tag>>(tag: T, vr: VR, len: Length) -> DataElementHeader {
DataElementHeader {
tag: tag.into(),
vr,
len,
}
}
#[inline]
pub fn vr(&self) -> VR {
self.vr
}
#[inline]
pub fn is_non_primitive(&self) -> bool {
self.vr == VR::SQ || self.length().is_undefined()
}
}
impl From<SequenceItemHeader> for DataElementHeader {
fn from(value: SequenceItemHeader) -> DataElementHeader {
DataElementHeader {
tag: value.tag(),
vr: VR::UN,
len: value.length(),
}
}
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum SequenceItemHeader {
Item {
len: Length,
},
ItemDelimiter,
SequenceDelimiter,
}
impl SequenceItemHeader {
pub fn new<T: Into<Tag>>(tag: T, len: Length) -> Result<SequenceItemHeader> {
match tag.into() {
Tag(0xFFFE, 0xE000) => {
Ok(SequenceItemHeader::Item { len })
}
Tag(0xFFFE, 0xE00D) => {
if len != Length(0) {
UnexpectedDelimiterLengthSnafu { len }.fail()
} else {
Ok(SequenceItemHeader::ItemDelimiter)
}
}
Tag(0xFFFE, 0xE0DD) => {
Ok(SequenceItemHeader::SequenceDelimiter)
}
tag => UnexpectedTagSnafu { tag }.fail(),
}
}
}
impl HasLength for SequenceItemHeader {
#[inline]
fn length(&self) -> Length {
match *self {
SequenceItemHeader::Item { len } => len,
SequenceItemHeader::ItemDelimiter | SequenceItemHeader::SequenceDelimiter => Length(0),
}
}
}
impl Header for SequenceItemHeader {
#[inline]
fn tag(&self) -> Tag {
match *self {
SequenceItemHeader::Item { .. } => Tag(0xFFFE, 0xE000),
SequenceItemHeader::ItemDelimiter => Tag(0xFFFE, 0xE00D),
SequenceItemHeader::SequenceDelimiter => Tag(0xFFFE, 0xE0DD),
}
}
}
#[derive(Debug, Eq, PartialEq, Hash, Copy, Clone, Ord, PartialOrd)]
pub enum VR {
AE,
AS,
AT,
CS,
DA,
DS,
DT,
FL,
FD,
IS,
LO,
LT,
OB,
OD,
OF,
OL,
OV,
OW,
PN,
SH,
SL,
SQ,
SS,
ST,
SV,
TM,
UC,
UI,
UL,
UN,
UR,
US,
UT,
UV,
}
impl VR {
pub fn from_binary(chars: [u8; 2]) -> Option<Self> {
from_utf8(chars.as_ref())
.ok()
.and_then(|s| VR::from_str(s).ok())
}
pub fn to_string(self) -> &'static str {
use VR::*;
match self {
AE => "AE",
AS => "AS",
AT => "AT",
CS => "CS",
DA => "DA",
DS => "DS",
DT => "DT",
FL => "FL",
FD => "FD",
IS => "IS",
LO => "LO",
LT => "LT",
OB => "OB",
OD => "OD",
OF => "OF",
OL => "OL",
OV => "OV",
OW => "OW",
PN => "PN",
SH => "SH",
SL => "SL",
SQ => "SQ",
SS => "SS",
ST => "ST",
SV => "SV",
TM => "TM",
UC => "UC",
UI => "UI",
UL => "UL",
UN => "UN",
UR => "UR",
US => "US",
UT => "UT",
UV => "UV",
}
}
pub fn to_bytes(self) -> [u8; 2] {
let bytes = self.to_string().as_bytes();
[bytes[0], bytes[1]]
}
}
impl FromStr for VR {
type Err = &'static str;
fn from_str(string: &str) -> std::result::Result<Self, Self::Err> {
use VR::*;
match string {
"AE" => Ok(AE),
"AS" => Ok(AS),
"AT" => Ok(AT),
"CS" => Ok(CS),
"DA" => Ok(DA),
"DS" => Ok(DS),
"DT" => Ok(DT),
"FL" => Ok(FL),
"FD" => Ok(FD),
"IS" => Ok(IS),
"LO" => Ok(LO),
"LT" => Ok(LT),
"OB" => Ok(OB),
"OD" => Ok(OD),
"OF" => Ok(OF),
"OL" => Ok(OL),
"OV" => Ok(OV),
"OW" => Ok(OW),
"PN" => Ok(PN),
"SH" => Ok(SH),
"SL" => Ok(SL),
"SQ" => Ok(SQ),
"SS" => Ok(SS),
"ST" => Ok(ST),
"SV" => Ok(SV),
"TM" => Ok(TM),
"UC" => Ok(UC),
"UI" => Ok(UI),
"UL" => Ok(UL),
"UN" => Ok(UN),
"UR" => Ok(UR),
"US" => Ok(US),
"UT" => Ok(UT),
"UV" => Ok(UV),
_ => Err("no such value representation"),
}
}
}
impl fmt::Display for VR {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(VR::to_string(*self))
}
}
pub type GroupNumber = u16;
pub type ElementNumber = u16;
#[derive(PartialEq, Eq, Hash, PartialOrd, Ord, Clone, Copy)]
pub struct Tag(pub GroupNumber, pub ElementNumber);
impl Tag {
#[inline]
pub fn group(self) -> GroupNumber {
self.0
}
#[inline]
pub fn element(self) -> ElementNumber {
self.1
}
}
impl fmt::Debug for Tag {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Tag({:#06X?}, {:#06X?})", self.0, self.1)
}
}
impl fmt::Display for Tag {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "({:04X},{:04X})", self.0, self.1)
}
}
impl From<(u16, u16)> for Tag {
#[inline]
fn from(value: (u16, u16)) -> Tag {
Tag(value.0, value.1)
}
}
impl From<[u16; 2]> for Tag {
#[inline]
fn from(value: [u16; 2]) -> Tag {
Tag(value[0], value[1])
}
}
#[derive(Debug, Copy, Clone, Eq, Hash, PartialEq, Snafu)]
pub enum ParseTagError {
Start,
Separator,
End,
Length,
Number,
}
impl FromStr for Tag {
type Err = ParseTagError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.len() {
11 => {
ensure!(s.starts_with('('), StartSnafu);
let (num_g, rest) = parse_tag_part(&s[1..])?;
ensure!(rest.starts_with(','), SeparatorSnafu);
let (num_e, rest) = parse_tag_part(&rest[1..])?;
ensure!(rest == ")", EndSnafu);
Ok(Tag(num_g, num_e))
}
9 => {
let (num_g, rest) = parse_tag_part(s)?;
ensure!(rest.starts_with(','), SeparatorSnafu);
let (num_e, _) = parse_tag_part(&rest[1..])?;
Ok(Tag(num_g, num_e))
}
8 => {
let (g, e) = s.split_at(4);
let (num_g, _) = parse_tag_part(g)?;
let (num_e, _) = parse_tag_part(e)?;
Ok(Tag(num_g, num_e))
}
_ => Err(ParseTagError::Length),
}
}
}
fn parse_tag_part(s: &str) -> Result<(u16, &str), ParseTagError> {
ensure!(s.is_char_boundary(4), NumberSnafu);
let (num, rest) = s.split_at(4);
ensure!(num.chars().all(|c| c.is_ascii_hexdigit()), NumberSnafu);
let num = u16::from_str_radix(num, 16).expect("failed to parse tag part");
Ok((num, rest))
}
#[derive(Clone, Copy)]
pub struct Length(pub u32);
const UNDEFINED_LEN: u32 = 0xFFFF_FFFF;
impl Length {
pub const UNDEFINED: Self = Length(UNDEFINED_LEN);
#[inline]
pub fn new(len: u32) -> Self {
Length(len)
}
#[inline]
pub fn defined(len: u32) -> Self {
assert_ne!(len, UNDEFINED_LEN);
Length(len)
}
}
impl From<u32> for Length {
#[inline]
fn from(o: u32) -> Self {
Length(o)
}
}
impl PartialEq<Length> for Length {
fn eq(&self, rhs: &Length) -> bool {
match (self.0, rhs.0) {
(UNDEFINED_LEN, _) | (_, UNDEFINED_LEN) => false,
(l1, l2) => l1 == l2,
}
}
}
impl PartialOrd<Length> for Length {
fn partial_cmp(&self, rhs: &Length) -> Option<Ordering> {
match (self.0, rhs.0) {
(UNDEFINED_LEN, _) | (_, UNDEFINED_LEN) => None,
(l1, l2) => Some(l1.cmp(&l2)),
}
}
}
impl std::ops::Add<Length> for Length {
type Output = Self;
fn add(self, rhs: Length) -> Self::Output {
match (self.0, rhs.0) {
(UNDEFINED_LEN, _) | (_, UNDEFINED_LEN) => Length::UNDEFINED,
(l1, l2) => {
let o = l1 + l2;
debug_assert!(
o != UNDEFINED_LEN,
"integer overflow (0xFFFF_FFFF reserved for undefined length)"
);
Length(o)
}
}
}
}
impl std::ops::Add<i32> for Length {
type Output = Self;
fn add(self, rhs: i32) -> Self::Output {
match self.0 {
UNDEFINED_LEN => Length::UNDEFINED,
len => {
let o = (len as i32 + rhs) as u32;
debug_assert!(
o != UNDEFINED_LEN,
"integer overflow (0xFFFF_FFFF reserved for undefined length)"
);
Length(o)
}
}
}
}
impl std::ops::Sub<Length> for Length {
type Output = Self;
fn sub(self, rhs: Length) -> Self::Output {
let mut o = self;
o -= rhs;
o
}
}
impl std::ops::SubAssign<Length> for Length {
fn sub_assign(&mut self, rhs: Length) {
match (self.0, rhs.0) {
(UNDEFINED_LEN, _) | (_, UNDEFINED_LEN) => (), (_, l2) => {
self.0 -= l2;
debug_assert!(
self.0 != UNDEFINED_LEN,
"integer overflow (0xFFFF_FFFF reserved for undefined length)"
);
}
}
}
}
impl std::ops::Sub<i32> for Length {
type Output = Self;
fn sub(self, rhs: i32) -> Self::Output {
let mut o = self;
o -= rhs;
o
}
}
impl std::ops::SubAssign<i32> for Length {
fn sub_assign(&mut self, rhs: i32) {
match self.0 {
UNDEFINED_LEN => (), len => {
self.0 = (len as i32 - rhs) as u32;
debug_assert!(
self.0 != UNDEFINED_LEN,
"integer overflow (0xFFFF_FFFF reserved for undefined length)"
);
}
}
}
}
impl Length {
#[inline]
pub fn is_undefined(self) -> bool {
self.0 == UNDEFINED_LEN
}
#[inline]
pub fn is_defined(self) -> bool {
!self.is_undefined()
}
#[inline]
pub fn get(self) -> Option<u32> {
match self.0 {
UNDEFINED_LEN => None,
v => Some(v),
}
}
#[inline]
pub fn inner_eq(self, other: Length) -> bool {
self.0 == other.0
}
}
impl fmt::Debug for Length {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.0 {
UNDEFINED_LEN => f.write_str("Length(Undefined)"),
l => f.debug_tuple("Length").field(&l).finish(),
}
}
}
impl fmt::Display for Length {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.0 {
UNDEFINED_LEN => f.write_str("U/L"),
l => write!(f, "{}", &l),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{dicom_value, value::PixelFragmentSequence, DicomValue};
#[test]
fn to_clean_string() {
let p = dicom_value!(U16, [256, 0, 16]);
let val = DicomValue::new(p);
let element = DataElement::new(Tag(0x0028, 0x3002), VR::US, val);
assert_eq!(element.to_str().unwrap(), "256\\0\\16",);
}
#[test]
fn tag_from_u16_pair() {
let t = Tag::from((0x0010u16, 0x0020u16));
assert_eq!(0x0010u16, t.group());
assert_eq!(0x0020u16, t.element());
}
#[test]
fn tag_from_u16_array() {
let t = Tag::from([0x0010u16, 0x0020u16]);
assert_eq!(0x0010u16, t.group());
assert_eq!(0x0020u16, t.element());
}
#[test]
fn tag_ord() {
assert_eq!(
Tag(0x0010, 0x0020).cmp(&Tag(0x0010, 0x0020)),
Ordering::Equal
);
assert_eq!(
Tag(0x0010, 0x0020).cmp(&Tag(0x0010, 0x0024)),
Ordering::Less
);
assert_eq!(
Tag(0x0010, 0x0020).cmp(&Tag(0x0020, 0x0010)),
Ordering::Less
);
assert_eq!(
Tag(0x0010, 0x0020).cmp(&Tag(0x0020, 0x0024)),
Ordering::Less
);
assert_eq!(
Tag(0x0010, 0x0000).cmp(&Tag(0x0320, 0x0010)),
Ordering::Less
);
assert_eq!(
Tag(0x0010, 0x0020).cmp(&Tag(0x0010, 0x0010)),
Ordering::Greater
);
assert_eq!(
Tag(0x0012, 0x0020).cmp(&Tag(0x0010, 0x0024)),
Ordering::Greater
);
assert_eq!(
Tag(0x0012, 0x0020).cmp(&Tag(0x0010, 0x0010)),
Ordering::Greater
);
assert_eq!(
Tag(0x0012, 0x0020).cmp(&Tag(0x0012, 0x0010)),
Ordering::Greater
);
}
#[test]
fn get_date_value() {
let data_element: DataElement<_, _> = DataElement::new(
Tag(0x0010, 0x0030),
VR::DA,
Value::new(PrimitiveValue::from("19941012")),
);
assert_eq!(
data_element.to_date().unwrap(),
DicomDate::from_ymd(1994, 10, 12).unwrap(),
);
}
#[test]
fn create_data_element_from_primitive() {
let data_element: DataElement<EmptyObject, [u8; 0]> = DataElement::new(
Tag(0x0028, 0x3002),
VR::US,
crate::dicom_value!(U16, [256, 0, 16]),
);
assert_eq!(data_element.uint16_slice().unwrap(), &[256, 0, 16]);
}
#[test]
fn parse_tag() {
let tag: Tag = "00280004".parse().unwrap();
assert_eq!(tag, Tag(0x0028, 0x0004));
let tag: Tag = "7fe00001".parse().unwrap();
assert_eq!(tag, Tag(0x7FE0, 0x0001));
let tag: Tag = "7FE00001".parse().unwrap();
assert_eq!(tag, Tag(0x7FE0, 0x0001));
let tag: Tag = "(7fe0,0010)".parse().unwrap();
assert_eq!(tag, Tag(0x7FE0, 0x0010));
let tag: Tag = "(003a,001a)".parse().unwrap();
assert_eq!(tag, Tag(0x003A, 0x001A));
let tag: Tag = "(7FE0,0010)".parse().unwrap();
assert_eq!(tag, Tag(0x7FE0, 0x0010));
let tag: Tag = "(003A,001A)".parse().unwrap();
assert_eq!(tag, Tag(0x003A, 0x001A));
let tag: Tag = "(003a,001A)".parse().unwrap();
assert_eq!(tag, Tag(0x003A, 0x001A));
let tag: Tag = "7fe0,0010".parse().unwrap();
assert_eq!(tag, Tag(0x7FE0, 0x0010));
let tag: Tag = "003a,001a".parse().unwrap();
assert_eq!(tag, Tag(0x003A, 0x001A));
let r: Result<Tag, _> = "+03a,0001".parse();
assert_eq!(r, Err(ParseTagError::Number));
let r: Result<Tag, _> = "[baad,0123)".parse();
assert_eq!(r, Err(ParseTagError::Start));
let r: Result<Tag, _> = "(baad,0123]".parse();
assert_eq!(r, Err(ParseTagError::End));
let r: Result<Tag, _> = "(3a,1a)".parse();
assert_eq!(r, Err(ParseTagError::Length));
let r: Result<Tag, _> = "g00d,baad".parse();
assert_eq!(r, Err(ParseTagError::Number));
let r: Result<Tag, _> = "(baad&0123)".parse();
assert_eq!(r, Err(ParseTagError::Separator));
let r: Result<Tag, _> = "123,45678".parse();
assert_eq!(r, Err(ParseTagError::Number));
let r: Result<Tag, _> = "abcde,f01".parse();
assert_eq!(r, Err(ParseTagError::Separator));
let r: Result<Tag, _> = "1234567,".parse();
assert_eq!(r, Err(ParseTagError::Number));
}
#[test]
fn test_update_value() {
let mut e: DataElement<EmptyObject, InMemFragment> =
DataElement::new(Tag(0x0010, 0x0010), VR::PN, "Doe^John");
assert_eq!(e.length(), Length(8));
e.update_value(|e| {
*e = "Smith^John".into();
});
assert_eq!(e.length(), Length(10));
let mut e: DataElement<EmptyObject, InMemFragment> = DataElement::new_with_len(
Tag(0x7FE0, 0x0010),
VR::OB,
Length(0),
PixelFragmentSequence::new_fragments(vec![]),
);
assert_eq!(e.length(), Length(0));
e.update_value(|v| {
let fragments = v.fragments_mut().unwrap();
fragments.push(vec![0x00; 256]);
fragments.push(vec![0x55; 256]);
fragments.push(vec![0xCC; 256]);
});
assert!(e.length().is_undefined());
assert_eq!(e.fragments().map(|f| f.len()), Some(3));
}
}