1use crate::dataset::DataSet;
6use crate::element::Element;
7use crate::file_format::FileFormat;
8use crate::io::transfer::{implicit_vr_for_tag, TransferSyntaxProperties};
9use crate::meta_info::FileMetaInformation;
10use crate::value::{DicomDate, DicomDateTime, DicomTime, PersonName, PixelData, Value};
11use dicom_toolkit_core::charset::DicomCharsetDecoder;
12use dicom_toolkit_core::error::{DcmError, DcmResult};
13use dicom_toolkit_dict::{tags, Tag, Vr};
14use std::io::Read;
15
16pub struct DicomReader<R: Read> {
18 reader: R,
19}
20
21impl<R: Read> DicomReader<R> {
22 pub fn new(reader: R) -> Self {
23 Self { reader }
24 }
25
26 pub fn read_file(&mut self) -> DcmResult<FileFormat> {
28 let mut data = Vec::new();
29 self.reader.read_to_end(&mut data)?;
30 parse_file(&data)
31 }
32
33 pub fn read_dataset(&mut self, ts_uid: &str) -> DcmResult<DataSet> {
35 let mut data = Vec::new();
36 self.reader.read_to_end(&mut data)?;
37 let props = TransferSyntaxProperties::from_uid(ts_uid);
38 let actual: std::borrow::Cow<[u8]> = if props.is_deflated {
39 std::borrow::Cow::Owned(decompress_deflated(&data)?)
40 } else {
41 std::borrow::Cow::Borrowed(&data)
42 };
43 let mut cursor = DicomCursor::new(&actual);
44 cursor.read_dataset_impl(
45 props.is_explicit_vr(),
46 props.is_little_endian(),
47 actual.len(),
48 )
49 }
50}
51
52pub(crate) fn parse_file(data: &[u8]) -> DcmResult<FileFormat> {
55 if data.len() < 132 {
57 let mut cursor = DicomCursor::new(data);
58 let ds = cursor.read_dataset_impl(false, true, data.len())?;
59 let meta = FileMetaInformation::new("", "", "1.2.840.10008.1.2");
60 return Ok(FileFormat::new(meta, ds));
61 }
62
63 let has_dicm = &data[128..132] == b"DICM";
64
65 if !has_dicm {
66 let mut cursor = DicomCursor::new(data);
68 let ds = cursor.read_dataset_impl(false, true, data.len())?;
69 let meta = FileMetaInformation::new("", "", "1.2.840.10008.1.2");
70 return Ok(FileFormat::new(meta, ds));
71 }
72
73 let mut cursor = DicomCursor::new(data);
74 cursor.pos = 132; let meta_ds = cursor.read_meta()?;
78 let meta = FileMetaInformation::from_dataset(&meta_ds)?;
79 let ts_uid = meta.transfer_syntax_uid.clone();
80 let props = TransferSyntaxProperties::from_uid(&ts_uid);
81
82 let dataset = if props.is_deflated {
83 let remaining = &data[cursor.pos..];
84 let decompressed = decompress_deflated(remaining)?;
85 let mut dc = DicomCursor::new(&decompressed);
86 dc.read_dataset_impl(true, true, decompressed.len())?
87 } else {
88 cursor.read_dataset_impl(props.is_explicit_vr(), props.is_little_endian(), data.len())?
89 };
90
91 Ok(FileFormat::new(meta, dataset))
92}
93
94fn decompress_deflated(data: &[u8]) -> DcmResult<Vec<u8>> {
95 use flate2::read::DeflateDecoder;
96 let mut decoder = DeflateDecoder::new(data);
97 let mut out = Vec::new();
98 decoder.read_to_end(&mut out).map_err(DcmError::Io)?;
99 Ok(out)
100}
101
102struct DicomCursor<'a> {
105 data: &'a [u8],
106 pos: usize,
107 charset: DicomCharsetDecoder,
109}
110
111impl<'a> DicomCursor<'a> {
112 fn new(data: &'a [u8]) -> Self {
113 Self {
114 data,
115 pos: 0,
116 charset: DicomCharsetDecoder::default_ascii(),
117 }
118 }
119
120 fn read_u8(&mut self) -> DcmResult<u8> {
123 if self.pos >= self.data.len() {
124 return Err(DcmError::UnexpectedEof {
125 offset: self.pos as u64,
126 });
127 }
128 let b = self.data[self.pos];
129 self.pos += 1;
130 Ok(b)
131 }
132
133 fn read_u16(&mut self, le: bool) -> DcmResult<u16> {
134 let a = self.read_u8()?;
135 let b = self.read_u8()?;
136 Ok(if le {
137 u16::from_le_bytes([a, b])
138 } else {
139 u16::from_be_bytes([a, b])
140 })
141 }
142
143 fn read_u32(&mut self, le: bool) -> DcmResult<u32> {
144 let a = self.read_u8()?;
145 let b = self.read_u8()?;
146 let c = self.read_u8()?;
147 let d = self.read_u8()?;
148 Ok(if le {
149 u32::from_le_bytes([a, b, c, d])
150 } else {
151 u32::from_be_bytes([a, b, c, d])
152 })
153 }
154
155 fn read_bytes(&mut self, n: usize) -> DcmResult<&'a [u8]> {
156 if self.pos + n > self.data.len() {
157 return Err(DcmError::UnexpectedEof {
158 offset: self.pos as u64,
159 });
160 }
161 let slice = &self.data[self.pos..self.pos + n];
162 self.pos += n;
163 Ok(slice)
164 }
165
166 fn peek_tag(&self, le: bool) -> DcmResult<Tag> {
167 if self.pos + 4 > self.data.len() {
168 return Err(DcmError::UnexpectedEof {
169 offset: self.pos as u64,
170 });
171 }
172 let g0 = self.data[self.pos];
173 let g1 = self.data[self.pos + 1];
174 let e0 = self.data[self.pos + 2];
175 let e1 = self.data[self.pos + 3];
176 let group = if le {
177 u16::from_le_bytes([g0, g1])
178 } else {
179 u16::from_be_bytes([g0, g1])
180 };
181 let element = if le {
182 u16::from_le_bytes([e0, e1])
183 } else {
184 u16::from_be_bytes([e0, e1])
185 };
186 Ok(Tag::new(group, element))
187 }
188
189 fn read_tag(&mut self, le: bool) -> DcmResult<Tag> {
190 let tag = self.peek_tag(le)?;
191 self.pos += 4;
192 Ok(tag)
193 }
194
195 fn read_meta(&mut self) -> DcmResult<DataSet> {
199 let mut meta = DataSet::new();
200 while self.pos + 4 <= self.data.len() {
201 let group = u16::from_le_bytes([self.data[self.pos], self.data[self.pos + 1]]);
202 if group != 0x0002 {
203 break;
204 }
205 let elem = self.read_element(true, true)?;
206 if !elem.tag.is_group_length() {
208 meta.insert(elem);
209 }
210 }
211 Ok(meta)
212 }
213
214 fn read_dataset_impl(&mut self, explicit: bool, le: bool, end: usize) -> DcmResult<DataSet> {
217 let mut ds = DataSet::new();
218 while self.pos < end && self.pos + 4 <= self.data.len() {
219 let tag = self.peek_tag(le)?;
220
221 if tag.is_sequence_delimitation() || tag.is_item_delimitation() {
223 self.pos += 4;
224 let _ = self.read_u32(true); break;
226 }
227
228 if tag.is_item() {
230 break;
231 }
232
233 let elem = self.read_element(explicit, le)?;
234
235 if elem.tag == tags::SPECIFIC_CHARACTER_SET {
237 if let Value::Strings(ref terms) = elem.value {
238 let charset_value = terms.join("\\");
239 if let Ok(decoder) = DicomCharsetDecoder::new(&charset_value) {
240 self.charset = decoder;
241 }
242 }
243 }
244
245 ds.insert(elem);
246 }
247 Ok(ds)
248 }
249
250 fn read_element(&mut self, explicit: bool, le: bool) -> DcmResult<Element> {
253 let tag = self.read_tag(le)?;
254
255 let (vr, len, undef_len) = if tag.is_delimiter() {
256 let len = self.read_u32(true)?;
257 (Vr::UN, len, false)
258 } else if explicit {
259 let vr_b0 = self.read_u8()?;
260 let vr_b1 = self.read_u8()?;
261 let vr = Vr::from_bytes([vr_b0, vr_b1]).unwrap_or(Vr::UN);
262 if vr.has_long_explicit_length() {
263 let _reserved = self.read_u16(le)?;
264 let len = self.read_u32(le)?;
265 (vr, len, len == 0xFFFF_FFFF)
266 } else {
267 let len = self.read_u16(le)? as u32;
268 (vr, len, false)
269 }
270 } else {
271 let len = self.read_u32(le)?;
272 let vr = implicit_vr_for_tag(tag);
273 (vr, len, len == 0xFFFF_FFFF)
274 };
275
276 let value = self.read_value(tag, vr, len, undef_len, explicit, le)?;
277 Ok(Element::new(tag, vr, value))
278 }
279
280 fn read_value(
283 &mut self,
284 tag: Tag,
285 vr: Vr,
286 len: u32,
287 undef_len: bool,
288 explicit: bool,
289 le: bool,
290 ) -> DcmResult<Value> {
291 match vr {
292 Vr::SQ => {
293 let items = self.read_sequence(len, undef_len, explicit, le)?;
294 Ok(Value::Sequence(items))
295 }
296 _ if tag == tags::PIXEL_DATA => self.read_pixel_data(len, undef_len, le),
297 _ => {
298 if undef_len {
299 return Err(DcmError::InvalidLength {
300 group: tag.group,
301 element: tag.element,
302 length: 0xFFFF_FFFF,
303 });
304 }
305 let bytes = self.read_bytes(len as usize)?;
306 parse_value_bytes(vr, bytes, le, &self.charset)
307 }
308 }
309 }
310
311 fn read_sequence(
314 &mut self,
315 len: u32,
316 undef_len: bool,
317 explicit: bool,
318 le: bool,
319 ) -> DcmResult<Vec<DataSet>> {
320 let end = if undef_len {
321 usize::MAX
322 } else {
323 self.pos.saturating_add(len as usize)
324 };
325
326 let mut items = Vec::new();
327
328 while self.pos < end && self.pos + 4 <= self.data.len() {
329 let tag = self.peek_tag(le)?;
330
331 if tag.is_sequence_delimitation() {
332 self.pos += 4;
333 let _ = self.read_u32(true);
334 break;
335 }
336
337 if tag.is_item() {
338 self.pos += 4; let item_len = self.read_u32(le)?;
340 let item_undef = item_len == 0xFFFF_FFFF;
341 let item_end = if item_undef {
342 usize::MAX
343 } else {
344 self.pos.saturating_add(item_len as usize)
345 };
346 let item_ds = self.read_dataset_impl(explicit, le, item_end)?;
347 items.push(item_ds);
348 } else {
349 break;
350 }
351 }
352
353 Ok(items)
354 }
355
356 fn read_pixel_data(&mut self, len: u32, undef_len: bool, le: bool) -> DcmResult<Value> {
359 if !undef_len {
360 let bytes = self.read_bytes(len as usize)?.to_vec();
361 return Ok(Value::PixelData(PixelData::Native { bytes }));
362 }
363
364 let mut offset_table: Vec<u32> = Vec::new();
366 let mut fragments: Vec<Vec<u8>> = Vec::new();
367 let mut first_item = true;
368
369 loop {
370 if self.pos + 4 > self.data.len() {
371 break;
372 }
373 let tag = self.peek_tag(le)?;
374
375 if tag.is_sequence_delimitation() {
376 self.pos += 4;
377 let _ = self.read_u32(true);
378 break;
379 }
380
381 if tag.is_item() {
382 self.pos += 4;
383 let item_len = self.read_u32(le)?;
384 let item_bytes = self.read_bytes(item_len as usize)?.to_vec();
385
386 if first_item {
387 let n = item_bytes.len() / 4;
389 for i in 0..n {
390 let b = &item_bytes[i * 4..i * 4 + 4];
391 offset_table.push(u32::from_le_bytes([b[0], b[1], b[2], b[3]]));
392 }
393 first_item = false;
394 } else {
395 fragments.push(item_bytes);
396 }
397 } else {
398 break;
399 }
400 }
401
402 Ok(Value::PixelData(PixelData::Encapsulated {
403 offset_table,
404 fragments,
405 }))
406 }
407}
408
409fn parse_value_bytes(
412 vr: Vr,
413 bytes: &[u8],
414 le: bool,
415 charset: &DicomCharsetDecoder,
416) -> DcmResult<Value> {
417 if bytes.is_empty() {
418 return Ok(Value::Empty);
419 }
420
421 match vr {
422 Vr::UI => {
423 let s = std::str::from_utf8(bytes)
425 .unwrap_or("")
426 .trim_end_matches('\0');
427 Ok(Value::Uid(s.to_string()))
428 }
429
430 Vr::AE | Vr::AS | Vr::CS | Vr::LO | Vr::SH => {
434 let s = decode_string_with_charset(bytes, charset);
435 let s = s.trim_end_matches('\0').trim_end_matches(' ');
436 let parts: Vec<String> = s.split('\\').map(str::to_string).collect();
437 Ok(Value::Strings(parts))
438 }
439 Vr::LT | Vr::ST | Vr::UT | Vr::UC | Vr::UR => {
440 let s = decode_string_with_charset(bytes, charset);
441 let s = s.trim_end_matches('\0').trim_end_matches(' ').to_string();
442 Ok(Value::Strings(vec![s]))
443 }
444 Vr::PN => {
445 let s = decode_string_with_charset(bytes, charset);
446 let s = s.trim_end_matches('\0').trim_end_matches(' ');
447 if s.is_empty() {
448 return Ok(Value::Empty);
449 }
450 let names: Vec<PersonName> = s.split('\\').map(PersonName::parse).collect();
451 Ok(Value::PersonNames(names))
452 }
453
454 Vr::DA => {
457 let s = decode_ascii_string(bytes);
458 if s.is_empty() {
459 return Ok(Value::Empty);
460 }
461 let res: Result<Vec<_>, _> = s
462 .split('\\')
463 .map(|p| DicomDate::from_da_str(p.trim()))
464 .collect();
465 res.map(Value::Date)
466 .map_err(|_| DcmError::Other("invalid DA value".into()))
467 }
468 Vr::TM => {
469 let s = decode_ascii_string(bytes);
470 if s.is_empty() {
471 return Ok(Value::Empty);
472 }
473 let res: Result<Vec<_>, _> =
474 s.split('\\').map(|p| DicomTime::parse(p.trim())).collect();
475 res.map(Value::Time)
476 .map_err(|_| DcmError::Other("invalid TM value".into()))
477 }
478 Vr::DT => {
479 let s = decode_ascii_string(bytes);
480 if s.is_empty() {
481 return Ok(Value::Empty);
482 }
483 let res: Result<Vec<_>, _> = s
484 .split('\\')
485 .map(|p| DicomDateTime::parse(p.trim()))
486 .collect();
487 res.map(Value::DateTime)
488 .map_err(|_| DcmError::Other("invalid DT value".into()))
489 }
490 Vr::IS => {
491 let s = decode_ascii_string(bytes);
492 if s.is_empty() {
493 return Ok(Value::Empty);
494 }
495 let res: Result<Vec<i64>, _> = s
496 .split('\\')
497 .map(|p| {
498 p.trim()
499 .parse::<i64>()
500 .map_err(|_| DcmError::Other(format!("invalid IS: {p}")))
501 })
502 .collect();
503 res.map(Value::Ints)
504 }
505 Vr::DS => {
506 let s = decode_ascii_string(bytes);
507 if s.is_empty() {
508 return Ok(Value::Empty);
509 }
510 let res: Result<Vec<f64>, _> = s
511 .split('\\')
512 .map(|p| {
513 p.trim()
514 .parse::<f64>()
515 .map_err(|_| DcmError::Other(format!("invalid DS: {p}")))
516 })
517 .collect();
518 res.map(Value::Decimals)
519 }
520
521 Vr::US | Vr::OW => {
522 if bytes.len() % 2 != 0 {
523 return Err(DcmError::Other(format!(
524 "{} value has odd byte length",
525 vr.code()
526 )));
527 }
528 let vals: Vec<u16> = bytes
529 .chunks_exact(2)
530 .map(|c| {
531 if le {
532 u16::from_le_bytes([c[0], c[1]])
533 } else {
534 u16::from_be_bytes([c[0], c[1]])
535 }
536 })
537 .collect();
538 Ok(Value::U16(vals))
539 }
540 Vr::SS => {
541 if bytes.len() % 2 != 0 {
542 return Err(DcmError::Other("SS value has odd byte length".into()));
543 }
544 let vals: Vec<i16> = bytes
545 .chunks_exact(2)
546 .map(|c| {
547 if le {
548 i16::from_le_bytes([c[0], c[1]])
549 } else {
550 i16::from_be_bytes([c[0], c[1]])
551 }
552 })
553 .collect();
554 Ok(Value::I16(vals))
555 }
556 Vr::UL | Vr::OL => {
557 if bytes.len() % 4 != 0 {
558 return Err(DcmError::Other(format!(
559 "{} value length not multiple of 4",
560 vr.code()
561 )));
562 }
563 let vals: Vec<u32> = bytes
564 .chunks_exact(4)
565 .map(|c| {
566 if le {
567 u32::from_le_bytes([c[0], c[1], c[2], c[3]])
568 } else {
569 u32::from_be_bytes([c[0], c[1], c[2], c[3]])
570 }
571 })
572 .collect();
573 Ok(Value::U32(vals))
574 }
575 Vr::SL => {
576 if bytes.len() % 4 != 0 {
577 return Err(DcmError::Other("SL value length not multiple of 4".into()));
578 }
579 let vals: Vec<i32> = bytes
580 .chunks_exact(4)
581 .map(|c| {
582 if le {
583 i32::from_le_bytes([c[0], c[1], c[2], c[3]])
584 } else {
585 i32::from_be_bytes([c[0], c[1], c[2], c[3]])
586 }
587 })
588 .collect();
589 Ok(Value::I32(vals))
590 }
591 Vr::FL | Vr::OF => {
592 if bytes.len() % 4 != 0 {
593 return Err(DcmError::Other(format!(
594 "{} value length not multiple of 4",
595 vr.code()
596 )));
597 }
598 let vals: Vec<f32> = bytes
599 .chunks_exact(4)
600 .map(|c| {
601 if le {
602 f32::from_le_bytes([c[0], c[1], c[2], c[3]])
603 } else {
604 f32::from_be_bytes([c[0], c[1], c[2], c[3]])
605 }
606 })
607 .collect();
608 Ok(Value::F32(vals))
609 }
610 Vr::FD | Vr::OD => {
611 if bytes.len() % 8 != 0 {
612 return Err(DcmError::Other(format!(
613 "{} value length not multiple of 8",
614 vr.code()
615 )));
616 }
617 let vals: Vec<f64> = bytes
618 .chunks_exact(8)
619 .map(|c| {
620 if le {
621 f64::from_le_bytes([c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]])
622 } else {
623 f64::from_be_bytes([c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]])
624 }
625 })
626 .collect();
627 Ok(Value::F64(vals))
628 }
629 Vr::SV => {
630 if bytes.len() % 8 != 0 {
631 return Err(DcmError::Other("SV value length not multiple of 8".into()));
632 }
633 let vals: Vec<i64> = bytes
634 .chunks_exact(8)
635 .map(|c| {
636 if le {
637 i64::from_le_bytes([c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]])
638 } else {
639 i64::from_be_bytes([c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]])
640 }
641 })
642 .collect();
643 Ok(Value::I64(vals))
644 }
645 Vr::UV | Vr::OV => {
646 if bytes.len() % 8 != 0 {
647 return Err(DcmError::Other(format!(
648 "{} value length not multiple of 8",
649 vr.code()
650 )));
651 }
652 let vals: Vec<u64> = bytes
653 .chunks_exact(8)
654 .map(|c| {
655 if le {
656 u64::from_le_bytes([c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]])
657 } else {
658 u64::from_be_bytes([c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7]])
659 }
660 })
661 .collect();
662 Ok(Value::U64(vals))
663 }
664 Vr::AT => {
665 if bytes.len() % 4 != 0 {
666 return Err(DcmError::Other("AT value length not multiple of 4".into()));
667 }
668 let tags: Vec<Tag> = bytes
669 .chunks_exact(4)
670 .map(|c| {
671 let g = if le {
672 u16::from_le_bytes([c[0], c[1]])
673 } else {
674 u16::from_be_bytes([c[0], c[1]])
675 };
676 let e = if le {
677 u16::from_le_bytes([c[2], c[3]])
678 } else {
679 u16::from_be_bytes([c[2], c[3]])
680 };
681 Tag::new(g, e)
682 })
683 .collect();
684 Ok(Value::Tags(tags))
685 }
686 Vr::OB | Vr::UN => Ok(Value::U8(bytes.to_vec())),
687 Vr::SQ => Err(DcmError::Other("parse_value_bytes called for SQ".into())),
688 }
689}
690
691fn decode_string_with_charset(bytes: &[u8], charset: &DicomCharsetDecoder) -> String {
693 charset
694 .decode(bytes)
695 .unwrap_or_else(|_| String::from_utf8_lossy(bytes).into_owned())
696}
697
698fn decode_ascii_string(bytes: &[u8]) -> String {
700 String::from_utf8_lossy(bytes)
701 .trim_end_matches('\0')
702 .trim_end_matches(' ')
703 .to_string()
704}
705
706#[cfg(test)]
709mod tests {
710 use super::*;
711 use crate::value::Value;
712 use dicom_toolkit_dict::Vr;
713
714 fn ascii() -> DicomCharsetDecoder {
715 DicomCharsetDecoder::default_ascii()
716 }
717
718 #[test]
719 fn parse_us_bytes() {
720 let bytes = 512u16.to_le_bytes();
721 let v = parse_value_bytes(Vr::US, &bytes, true, &ascii()).unwrap();
722 assert_eq!(v.as_u16(), Some(512));
723 }
724
725 #[test]
726 fn parse_ui_bytes() {
727 let uid = b"1.2.840.10008.1.2.1";
728 let v = parse_value_bytes(Vr::UI, uid, true, &ascii()).unwrap();
729 assert_eq!(v.as_string(), Some("1.2.840.10008.1.2.1"));
730 }
731
732 #[test]
733 fn parse_lo_bytes_backslash() {
734 let s = b"foo\\bar";
735 let v = parse_value_bytes(Vr::LO, s, true, &ascii()).unwrap();
736 match v {
737 Value::Strings(ss) => assert_eq!(ss, &["foo", "bar"]),
738 other => panic!("unexpected: {:?}", other),
739 }
740 }
741
742 #[test]
743 fn parse_ds_bytes() {
744 let s = b"2.78";
745 let v = parse_value_bytes(Vr::DS, s, true, &ascii()).unwrap();
746 match v {
747 Value::Decimals(ds) => assert!((ds[0] - 2.78).abs() < 1e-9),
748 other => panic!("unexpected: {:?}", other),
749 }
750 }
751
752 #[test]
753 fn parse_is_bytes() {
754 let s = b"-42";
755 let v = parse_value_bytes(Vr::IS, s, true, &ascii()).unwrap();
756 match v {
757 Value::Ints(is) => assert_eq!(is[0], -42),
758 other => panic!("unexpected: {:?}", other),
759 }
760 }
761
762 #[test]
763 fn parse_ob_bytes() {
764 let bytes = vec![0xDE, 0xAD, 0xBE, 0xEF];
765 let v = parse_value_bytes(Vr::OB, &bytes, true, &ascii()).unwrap();
766 assert_eq!(v.as_bytes(), Some(bytes.as_slice()));
767 }
768
769 #[test]
770 fn parse_lo_latin1() {
771 let bytes = vec![b'M', 0xFC, b'l', b'l', b'e', b'r'];
773 let latin1 = DicomCharsetDecoder::new("ISO_IR 100").unwrap();
774 let v = parse_value_bytes(Vr::LO, &bytes, true, &latin1).unwrap();
775 match v {
776 Value::Strings(ss) => assert_eq!(ss, &["Müller"]),
777 other => panic!("unexpected: {:?}", other),
778 }
779 }
780
781 #[test]
782 fn parse_pn_utf8() {
783 let name = "田中^太郎";
784 let utf8 = DicomCharsetDecoder::new("ISO_IR 192").unwrap();
785 let v = parse_value_bytes(Vr::PN, name.as_bytes(), true, &utf8).unwrap();
786 match v {
787 Value::PersonNames(names) => assert_eq!(names[0].to_string(), "田中^太郎"),
788 other => panic!("unexpected: {:?}", other),
789 }
790 }
791}