dicomweb_util/
lib.rs
1use bytes::{Buf, Bytes};
2use dicom::object::mem::InMemElement;
3use dicom::object::{
4 DefaultDicomObject, FileMetaTable, FileMetaTableBuilder, InMemDicomObject,
5 StandardDataDictionary,
6};
7use enum_as_inner::EnumAsInner;
8use log::{debug, error, info, log_enabled, trace, warn, Level};
9use serde::Deserialize;
10use serde_json::Value;
11use std::{borrow::Borrow, io::BufRead};
12use std::{
13 collections::HashMap,
14 io::{self, Cursor, Read},
15};
16use thiserror::Error;
17
18#[derive(Error, Debug)]
19pub enum Error {
20 #[error("{0}")]
21 Io(#[from] std::io::Error),
22 #[error("{0}")]
23 Serde(#[from] serde_json::Error),
24 #[error("{0}")]
25 Dicom(#[from] dicom::object::Error),
26 #[error("{0}")]
27 DicomCastValue(#[from] dicom::core::value::CastValueError),
28 #[error("{0}")]
29 Custom(String),
30}
31pub type Result<T> = std::result::Result<T, Error>;
32
33pub mod decode;
34pub mod encode;
35
36#[derive(Debug)]
37enum MultipartParserStates {
38 NextPart,
39 InHeader,
40 InBinary,
41}
42
43pub fn parse_multipart_body(body: Bytes, boundary: &str) -> Result<Vec<Vec<u8>>> {
44 let mut reader = Cursor::new(body).reader();
45 let mut line = String::new();
46
47 let mut result = vec![];
48
49 let mut state = MultipartParserStates::NextPart;
50 let mut content_length: usize = 0;
51
52 loop {
53 match reader.read_line(&mut line) {
54 Ok(bytes_read) => {
55 if bytes_read == 0 {
56 break;
57 }
58 trace!("{:?}", state);
59 trace!("{:?}", line);
60 match state {
61 MultipartParserStates::NextPart => {
62 if line.trim().ends_with(boundary) {
63 debug!("found start of part in multipart body");
64 state = MultipartParserStates::InHeader;
65 }
66 }
67 MultipartParserStates::InHeader => {
68 if line.starts_with("Content-Length") {
69 content_length =
70 usize::from_str_radix(line.split_whitespace().last().unwrap(), 10)
71 .unwrap();
72 debug!("content length:{}", content_length);
73 } else if line.trim() == "" {
74 state = MultipartParserStates::InBinary;
75 }
76 }
77 _ => {
78 return Err(Error::Custom(
79 "in wrong state when reading multipart header".to_string(),
80 ));
81 }
82 }
83
84 line.clear();
85 }
86 Err(err) => {
87 error!("{}", err);
88 break;
89 }
90 };
91 match state {
92 MultipartParserStates::InBinary => {
93 if content_length > 0 {
94 let mut buffer = vec![0u8; content_length];
95 reader.read_exact(&mut buffer)?;
96 result.push(buffer);
97 } else {
98 let mut buffer = Vec::new();
100 reader.read_to_end(&mut buffer)?;
101 let len = buffer.len() - boundary.len() - 6;
102 result.push(buffer[..len].into());
103 }
104 state = MultipartParserStates::NextPart
105 }
106 _ => {}
107 }
108 }
109 Ok(result)
110}
111
112pub fn dicom_from_reader<R: Read>(mut file: R) -> Result<DefaultDicomObject> {
113 {
115 let mut buf = [0u8; 128];
116 file.read_exact(&mut buf)?;
118 }
119 let result = DefaultDicomObject::from_reader(file)?;
120 Ok(result)
121}
122
123#[derive(Debug, Deserialize, EnumAsInner)]
124#[serde(untagged)]
125pub enum DICOMJsonTagValue {
126 Str(String),
127 Int(i32),
128 DICOMJson(DICOMJson),
129 Value(Value),
130}
131
132#[derive(Debug, Deserialize)]
133pub struct DICOMJsonTag {
134 pub vr: String,
135 pub Value: Vec<DICOMJsonTagValue>,
136}
137
138pub type DICOMJson = Vec<HashMap<String, DICOMJsonTag>>;
139pub type DicomResponse = InMemDicomObject<StandardDataDictionary>;
140
141pub fn json2dicom(parsed: &Vec<Value>) -> Result<Vec<DicomResponse>> {
142 println!("{:?}", parsed);
144
145 let ds = parsed.iter().map(decode::decode_response_item).collect();
146 Ok(ds)
147}
148
149#[cfg(test)]
150mod tests {
151 #[test]
152 fn it_works() {
153 assert_eq!(2 + 2, 4);
154 }
155}