Skip to content

Commit d31a5e5

Browse files
committed
[WIP] PS3.5 H3.2 compliant
1 parent 31b01d0 commit d31a5e5

File tree

3 files changed

+161
-5
lines changed

3 files changed

+161
-5
lines changed

Cargo.lock

+10
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

parser/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@ dicom-dictionary-std = { path = "../dictionary-std/", version = "0.6.1" }
1818
smallvec = "1.6.1"
1919
snafu = "0.7.3"
2020
tracing = "0.1.34"
21+
encoding_rs = "0.8.33"

parser/src/stateful/decode.rs

+150-5
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,68 @@ where
439439
Ok(PrimitiveValue::Strs(parts?))
440440
}
441441

442+
fn read_value_pn(
443+
&mut self,
444+
header: &DataElementHeader,
445+
specific_char_set: &SpecificCharacterSet,
446+
) -> Result<PrimitiveValue> {
447+
match self.read_value_pns(header, specific_char_set) {
448+
Ok(PrimitiveValue::Strs(parts)) => Ok(PrimitiveValue::Str(parts.join("="))),
449+
Ok(_) => {
450+
panic!("wron impl: read_value_pns should always return Strs")
451+
}
452+
Err(e) => Err(e),
453+
}
454+
}
455+
456+
fn read_value_pns(
457+
&mut self,
458+
header: &DataElementHeader,
459+
specific_char_set: &SpecificCharacterSet,
460+
) -> Result<PrimitiveValue> {
461+
let len = self.require_known_length(header)?;
462+
self.buffer.resize_with(len, Default::default);
463+
self.from
464+
.read_exact(&mut self.buffer)
465+
.context(ReadValueDataSnafu {
466+
position: self.position,
467+
})?;
468+
469+
let equal_positions: Vec<_> = self
470+
.buffer
471+
.iter()
472+
.enumerate()
473+
.filter(|&(_, &b)| b == b'=')
474+
.map(|(i, _)| i)
475+
.collect();
476+
477+
if equal_positions.len() == 0 {
478+
return self.read_value_str(header);
479+
}
480+
481+
let mut binary_data = Vec::new();
482+
let mut equal_position = 0;
483+
for &index in &equal_positions {
484+
binary_data.push(&self.buffer[equal_position..index]);
485+
equal_position = index + 1;
486+
}
487+
binary_data.push(&self.buffer[equal_position..]);
488+
489+
let mut decoded_parts = Vec::new();
490+
for (i, part) in binary_data.iter().enumerate() {
491+
let charset = match i {
492+
0 => specific_char_set,
493+
_ => &SpecificCharacterSet::IsoIr87,
494+
};
495+
let decoded = charset.decode(part).context(DecodeTextSnafu {
496+
position: self.position,
497+
})?;
498+
decoded_parts.push(decoded);
499+
}
500+
501+
Ok(PrimitiveValue::Strs(decoded_parts.into()))
502+
}
503+
442504
fn read_value_str(&mut self, header: &DataElementHeader) -> Result<PrimitiveValue> {
443505
let len = self.require_known_length(header)?;
444506

@@ -920,9 +982,8 @@ where
920982
.fail()
921983
}
922984
VR::AT => self.read_value_tag(header),
923-
VR::AE | VR::AS | VR::PN | VR::SH | VR::LO | VR::UC | VR::UI => {
924-
self.read_value_strs(header)
925-
}
985+
VR::AE | VR::AS | VR::SH | VR::LO | VR::UC | VR::UI => self.read_value_strs(header),
986+
VR::PN => self.read_value_pns(header, &self.text.clone()),
926987
VR::CS => self.read_value_cs(header),
927988
VR::UT | VR::ST | VR::UR | VR::LT => self.read_value_str(header),
928989
VR::UN | VR::OB => self.read_value_ob(header),
@@ -958,7 +1019,6 @@ where
9581019
VR::AT => self.read_value_tag(header),
9591020
VR::AE
9601021
| VR::AS
961-
| VR::PN
9621022
| VR::SH
9631023
| VR::LO
9641024
| VR::UC
@@ -968,6 +1028,7 @@ where
9681028
| VR::DA
9691029
| VR::TM
9701030
| VR::DT => self.read_value_strs(header),
1031+
VR::PN => self.read_value_pn(header, &self.text.clone()),
9711032
VR::CS => self.read_value_cs(header),
9721033
VR::UT | VR::ST | VR::UR | VR::LT => self.read_value_str(header),
9731034
VR::UN | VR::OB => self.read_value_ob(header),
@@ -1065,13 +1126,16 @@ fn trim_trail_empty_bytes(mut x: &[u8]) -> &[u8] {
10651126
mod tests {
10661127
use super::{StatefulDecode, StatefulDecoder};
10671128
use dicom_core::header::{DataElementHeader, HasLength, Header, Length, SequenceItemHeader};
1068-
use dicom_core::{Tag, VR};
1129+
use dicom_core::{PrimitiveValue, Tag, VR};
10691130
use dicom_encoding::decode::basic::LittleEndianBasicDecoder;
10701131
use dicom_encoding::decode::{
10711132
explicit_le::ExplicitVRLittleEndianDecoder, implicit_le::ImplicitVRLittleEndianDecoder,
10721133
};
10731134
use dicom_encoding::text::{SpecificCharacterSet, TextCodec};
1135+
use encoding_rs::{ISO_2022_JP, SHIFT_JIS};
1136+
use smallvec::SmallVec;
10741137
use std::io::{Cursor, Seek, SeekFrom};
1138+
use std::str;
10751139

10761140
// manually crafting some DICOM data elements
10771141
// Tag: (0002,0002) Media Storage SOP Class UID
@@ -1479,4 +1543,85 @@ mod tests {
14791543

14801544
assert_eq!(decoder.position(), 138);
14811545
}
1546+
1547+
#[test]
1548+
fn test_read_value_pn() {
1549+
let yamada_taro_sjis = SHIFT_JIS.encode("ヤマダ^タロウ").0;
1550+
let equal_ascii = b"=";
1551+
let yamada_taro_iso2022jp = ISO_2022_JP.encode("山田^太郎").0;
1552+
let equal_ascii_2 = b"=";
1553+
let yamada_taro_kana_iso2022jp = ISO_2022_JP.encode("ヤマダ^タロウ").0;
1554+
1555+
let mut combined = Vec::new();
1556+
combined.extend_from_slice(&yamada_taro_sjis);
1557+
combined.extend_from_slice(equal_ascii);
1558+
combined.extend_from_slice(&yamada_taro_iso2022jp);
1559+
combined.extend_from_slice(equal_ascii_2);
1560+
combined.extend_from_slice(&yamada_taro_kana_iso2022jp);
1561+
1562+
let mut cursor = Cursor::new(&combined);
1563+
1564+
let mut decoder = StatefulDecoder::new(
1565+
&mut cursor,
1566+
ImplicitVRLittleEndianDecoder::default(),
1567+
LittleEndianBasicDecoder,
1568+
SpecificCharacterSet::IsoIr13,
1569+
);
1570+
1571+
let header =
1572+
DataElementHeader::new(Tag(0x0010, 0x0010), VR::PN, Length(combined.len() as u32));
1573+
1574+
let result = decoder.read_value(&header);
1575+
assert!(result.is_ok());
1576+
1577+
let value = result.unwrap();
1578+
let expected: SmallVec<[&str; 3]> =
1579+
vec!["ヤマタ\u{ff9e}^タロウ", "山田^太郎", "ヤマダ^タロウ"].into();
1580+
match value {
1581+
PrimitiveValue::Strs(s) => {
1582+
assert_eq!(s, expected);
1583+
}
1584+
_ => panic!("Unexpected value type"),
1585+
}
1586+
}
1587+
1588+
#[test]
1589+
fn test_read_value_pns() {
1590+
let yamada_taro_sjis = SHIFT_JIS.encode("ヤマダ^タロウ").0;
1591+
let equal_ascii = b"=";
1592+
let yamada_taro_iso2022jp = ISO_2022_JP.encode("山田^太郎").0;
1593+
let equal_ascii_2 = b"=";
1594+
let yamada_taro_kana_iso2022jp = ISO_2022_JP.encode("ヤマダ^タロウ").0;
1595+
1596+
let mut combined = Vec::new();
1597+
combined.extend_from_slice(&yamada_taro_sjis);
1598+
combined.extend_from_slice(equal_ascii);
1599+
combined.extend_from_slice(&yamada_taro_iso2022jp);
1600+
combined.extend_from_slice(equal_ascii_2);
1601+
combined.extend_from_slice(&yamada_taro_kana_iso2022jp);
1602+
1603+
let mut cursor = Cursor::new(&combined);
1604+
1605+
let mut decoder = StatefulDecoder::new(
1606+
&mut cursor,
1607+
ImplicitVRLittleEndianDecoder::default(),
1608+
LittleEndianBasicDecoder,
1609+
SpecificCharacterSet::IsoIr13,
1610+
);
1611+
1612+
let header =
1613+
DataElementHeader::new(Tag(0x0010, 0x0010), VR::PN, Length(combined.len() as u32));
1614+
1615+
let result = decoder.read_value_preserved(&header);
1616+
assert!(result.is_ok());
1617+
1618+
let value = result.unwrap();
1619+
let expected = "ヤマタ\u{ff9e}^タロウ=山田^太郎=ヤマダ^タロウ";
1620+
match value {
1621+
PrimitiveValue::Str(s) => {
1622+
assert_eq!(s, expected);
1623+
}
1624+
_ => panic!("Unexpected value type"),
1625+
}
1626+
}
14821627
}

0 commit comments

Comments
 (0)