use dicom_core::PrimitiveValue;
use serde::ser::SerializeSeq;
use serde::Serialize;
use crate::{INFINITY, NAN, NEG_INFINITY};
#[derive(Debug, Clone)]
pub struct AsStrings<'a>(&'a PrimitiveValue);
impl<'a> From<&'a PrimitiveValue> for AsStrings<'a> {
fn from(value: &'a PrimitiveValue) -> Self {
AsStrings(value)
}
}
impl Serialize for AsStrings<'_> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let strings = self.0.to_multi_str();
serializer.collect_seq(&*strings)
}
}
#[derive(Debug, Clone)]
pub struct AsNumbers<'a>(&'a PrimitiveValue);
impl<'a> From<&'a PrimitiveValue> for AsNumbers<'a> {
fn from(value: &'a PrimitiveValue) -> Self {
AsNumbers(value)
}
}
impl Serialize for AsNumbers<'_> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
match self.0 {
PrimitiveValue::Empty => serializer.serialize_seq(Some(0))?.end(),
PrimitiveValue::Date(_) => panic!("wrong impl: cannot encode Date as numbers"),
PrimitiveValue::DateTime(_) => panic!("wrong impl: cannot encode DateTime as numbers"),
PrimitiveValue::Time(_) => panic!("wrong impl: cannot encode Time as numbers"),
PrimitiveValue::Tags(_) => panic!("wrong impl: cannot encode Tags as numbers"),
PrimitiveValue::Strs(strings) => serializer.collect_seq(strings),
PrimitiveValue::Str(string) => serializer.collect_seq([string]),
PrimitiveValue::U8(numbers) => serializer.collect_seq(numbers),
PrimitiveValue::I16(numbers) => serializer.collect_seq(numbers),
PrimitiveValue::U16(numbers) => serializer.collect_seq(numbers),
PrimitiveValue::I32(numbers) => serializer.collect_seq(numbers),
PrimitiveValue::U32(numbers) => serializer.collect_seq(numbers),
PrimitiveValue::I64(numbers) => {
let mut ser = serializer.serialize_seq(None)?;
for number in numbers {
let narrowed: Option<i32> = num_traits::NumCast::from(*number);
if let Some(narrowed) = narrowed {
ser.serialize_element(&narrowed)?;
} else {
ser.serialize_element(&number.to_string())?;
}
}
ser.end()
}
PrimitiveValue::U64(numbers) => {
let mut ser = serializer.serialize_seq(None)?;
for number in numbers {
let narrowed: Option<i32> = num_traits::NumCast::from(*number);
if let Some(narrowed) = narrowed {
ser.serialize_element(&narrowed)?;
} else {
ser.serialize_element(&number.to_string())?;
}
}
ser.end()
}
PrimitiveValue::F32(numbers) => {
let mut ser = serializer.serialize_seq(None)?;
for number in numbers {
if number.is_finite() {
ser.serialize_element(&number)?;
} else if number.is_nan() {
ser.serialize_element(NAN)?;
} else if number.is_infinite() && number.is_sign_positive() {
ser.serialize_element(INFINITY)?;
} else if number.is_infinite() && number.is_sign_negative() {
ser.serialize_element(NEG_INFINITY)?;
} else {
ser.serialize_element(&Option::<()>::None)?;
}
}
ser.end()
}
PrimitiveValue::F64(numbers) => {
let mut ser = serializer.serialize_seq(None)?;
for number in numbers {
if number.is_finite() {
ser.serialize_element(&number)?;
} else if number.is_nan() {
ser.serialize_element(NAN)?;
} else if number.is_infinite() && number.is_sign_positive() {
ser.serialize_element(INFINITY)?;
} else if number.is_infinite() && number.is_sign_negative() {
ser.serialize_element(NEG_INFINITY)?;
} else {
ser.serialize_element(&Option::<()>::None)?;
}
}
ser.end()
}
}
}
}
#[derive(Debug, Clone)]
pub struct InlineBinary<'a>(&'a PrimitiveValue);
impl<'a> From<&'a PrimitiveValue> for InlineBinary<'a> {
fn from(value: &'a PrimitiveValue) -> Self {
InlineBinary(value)
}
}
impl Serialize for InlineBinary<'_> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let value = self.0.to_bytes();
use base64::Engine;
let str = base64::engine::general_purpose::STANDARD.encode(value);
serializer.serialize_str(&str)
}
}
#[derive(Debug, Clone)]
pub struct AsPersonNames<'a>(&'a PrimitiveValue);
impl<'a> From<&'a PrimitiveValue> for AsPersonNames<'a> {
fn from(value: &'a PrimitiveValue) -> Self {
AsPersonNames(value)
}
}
impl Serialize for AsPersonNames<'_> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let strings = self.0.to_multi_str();
serializer.collect_seq(strings.iter().map(|p| PersonNameDef::from(p.as_str())))
}
}
#[derive(Debug, Clone, Serialize)]
pub struct PersonNameDef<'a> {
#[serde(rename = "Alphabetic")]
alphabetic: &'a str,
}
impl<'a> From<&'a str> for PersonNameDef<'a> {
fn from(value: &'a str) -> Self {
PersonNameDef { alphabetic: value }
}
}
#[cfg(test)]
mod tests {
use dicom_core::dicom_value;
use dicom_core::value::DicomDate;
use pretty_assertions::assert_eq;
use serde_json::json;
use serde_json::Value;
use super::*;
#[test]
fn serialize_primitive_value_as_strings() {
let v = PrimitiveValue::from("Test Hospital");
let json = serde_json::to_value(AsStrings(&v)).unwrap();
assert_eq!(
json,
Value::Array(vec![Value::String("Test Hospital".to_string())]),
);
let v = PrimitiveValue::Empty;
let json = serde_json::to_value(AsStrings(&v)).unwrap();
assert_eq!(json, json!([]));
let v = dicom_value!(U16, [20, 40, 60]);
let json = serde_json::to_value(AsStrings(&v)).unwrap();
assert_eq!(
json,
Value::Array(vec![
Value::from("20"),
Value::from("40"),
Value::from("60"),
]),
);
let v = dicom_value!(Date, [DicomDate::from_ymd(2023, 6, 13).unwrap()]);
let json = serde_json::to_value(AsStrings(&v)).unwrap();
assert_eq!(json, Value::Array(vec![Value::from("20230613")]));
}
#[test]
fn serialize_primitive_value_as_numbers() {
let v = PrimitiveValue::from(23.5_f64);
let json = serde_json::to_value(AsNumbers(&v)).unwrap();
assert_eq!(json, json!([23.5]),);
let v = PrimitiveValue::from([f64::NAN, f64::INFINITY, f64::NEG_INFINITY]);
let json = serde_json::to_value(AsNumbers(&v)).unwrap();
assert_eq!(json, json!(["NaN", "inf", "-inf"]),);
let v = PrimitiveValue::from([f32::NAN, f32::INFINITY, f32::NEG_INFINITY]);
let json = serde_json::to_value(AsNumbers(&v)).unwrap();
assert_eq!(json, json!(["NaN", "inf", "-inf"]),);
let v = PrimitiveValue::Empty;
let json = serde_json::to_value(AsNumbers(&v)).unwrap();
assert_eq!(json, json!([]));
let v = PrimitiveValue::from("5");
let json = serde_json::to_value(AsNumbers(&v)).unwrap();
assert_eq!(json, json!(["5"]),);
let v = dicom_value!(U16, [20, 40, 60]);
let json = serde_json::to_value(AsNumbers(&v)).unwrap();
assert_eq!(json, json!([20, 40, 60]));
let v = dicom_value!(U64, [876543245678]);
let json = serde_json::to_value(AsNumbers(&v)).unwrap();
assert_eq!(json, json!(["876543245678"]),);
}
}