use dicom_toolkit_core::error::DcmResult;
use dicom_toolkit_data::DataSet;
use dicom_toolkit_dict::tags;
use crate::association::Association;
#[derive(Debug, Clone)]
pub struct StoreRequest {
pub sop_class_uid: String,
pub sop_instance_uid: String,
pub priority: u16,
pub dataset_bytes: Vec<u8>,
pub context_id: u8,
}
#[derive(Debug, Clone)]
pub struct StoreResponse {
pub status: u16,
pub message_id: u16,
}
pub async fn c_store(assoc: &mut Association, req: StoreRequest) -> DcmResult<StoreResponse> {
let msg_id = next_message_id();
let mut cmd = DataSet::new();
cmd.set_uid(tags::AFFECTED_SOP_CLASS_UID, &req.sop_class_uid);
cmd.set_u16(tags::COMMAND_FIELD, 0x0001); cmd.set_u16(tags::MESSAGE_ID, msg_id);
cmd.set_u16(tags::PRIORITY, req.priority);
cmd.set_u16(tags::COMMAND_DATA_SET_TYPE, 0x0000); cmd.set_uid(tags::AFFECTED_SOP_INSTANCE_UID, &req.sop_instance_uid);
assoc.send_dimse_command(req.context_id, &cmd).await?;
assoc
.send_dimse_data(req.context_id, &req.dataset_bytes)
.await?;
let (_ctx, rsp) = assoc.recv_dimse_command().await?;
let status = rsp.get_u16(tags::STATUS).unwrap_or(0xFFFF);
Ok(StoreResponse {
status,
message_id: msg_id,
})
}
fn next_message_id() -> u16 {
use std::sync::atomic::{AtomicU16, Ordering};
static ID: AtomicU16 = AtomicU16::new(1);
ID.fetch_add(1, Ordering::Relaxed)
}
#[cfg(test)]
mod tests {
use crate::dimse;
use dicom_toolkit_data::DataSet;
use dicom_toolkit_dict::tags;
#[test]
fn c_store_rq_command_build() {
let mut cmd = DataSet::new();
cmd.set_uid(tags::AFFECTED_SOP_CLASS_UID, "1.2.840.10008.5.1.4.1.1.2");
cmd.set_u16(tags::COMMAND_FIELD, 0x0001);
cmd.set_u16(tags::MESSAGE_ID, 7);
cmd.set_u16(tags::PRIORITY, 0);
cmd.set_u16(tags::COMMAND_DATA_SET_TYPE, 0x0000);
cmd.set_uid(tags::AFFECTED_SOP_INSTANCE_UID, "1.2.3.4.5.6.7");
let bytes = dimse::encode_command_dataset(&cmd);
let decoded = dimse::decode_command_dataset(&bytes).unwrap();
assert_eq!(decoded.get_u16(tags::COMMAND_FIELD), Some(0x0001));
assert_eq!(decoded.get_u16(tags::MESSAGE_ID), Some(7));
assert_eq!(decoded.get_u16(tags::PRIORITY), Some(0));
assert_eq!(decoded.get_u16(tags::COMMAND_DATA_SET_TYPE), Some(0x0000));
assert_eq!(
decoded.get_string(tags::AFFECTED_SOP_INSTANCE_UID),
Some("1.2.3.4.5.6.7")
);
}
#[test]
fn c_store_rsp_success_status() {
let mut rsp = DataSet::new();
rsp.set_uid(tags::AFFECTED_SOP_CLASS_UID, "1.2.840.10008.5.1.4.1.1.2");
rsp.set_u16(tags::COMMAND_FIELD, 0x8001); rsp.set_u16(tags::MESSAGE_ID_BEING_RESPONDED_TO, 7);
rsp.set_u16(tags::COMMAND_DATA_SET_TYPE, 0x0101);
rsp.set_u16(tags::STATUS, 0x0000);
let bytes = dimse::encode_command_dataset(&rsp);
let decoded = dimse::decode_command_dataset(&bytes).unwrap();
assert_eq!(decoded.get_u16(tags::STATUS), Some(0x0000));
assert_eq!(decoded.get_u16(tags::COMMAND_FIELD), Some(0x8001));
}
}