#![cfg(feature = "serde")]
use hdf5_pure::mat::{self, Options};
use serde::{Deserialize, Serialize};
fn modern_string_roundtrip<T>(value: &T) -> T
where
T: Serialize + serde::de::DeserializeOwned,
{
let bytes = mat::to_bytes_with_options(value, &Options::with_modern_strings()).expect("ser");
mat::from_bytes(&bytes).expect("de")
}
#[test]
fn scalar_string_field_roundtrips() {
#[derive(Serialize, Deserialize, Debug, PartialEq)]
struct Root {
greeting: String,
}
let root = Root {
greeting: "hello".into(),
};
assert_eq!(modern_string_roundtrip(&root), root);
}
#[test]
fn multiple_string_fields_roundtrip() {
#[derive(Serialize, Deserialize, Debug, PartialEq)]
struct Root {
greeting: String,
name: String,
empty: String,
}
let root = Root {
greeting: "hello".into(),
name: "world!!".into(),
empty: String::new(),
};
assert_eq!(modern_string_roundtrip(&root), root);
}
#[test]
fn string_fields_mixed_with_numbers_roundtrip() {
#[derive(Serialize, Deserialize, Debug, PartialEq)]
struct Root {
label: String,
trial: u32,
samples: Vec<f64>,
note: String,
}
let root = Root {
label: "run-1".into(),
trial: 7,
samples: vec![1.0, 2.0, 3.0],
note: "ok".into(),
};
assert_eq!(modern_string_roundtrip(&root), root);
}
#[test]
fn nested_struct_string_fields_roundtrip() {
#[derive(Serialize, Deserialize, Debug, PartialEq)]
struct Inner {
title: String,
unit: String,
}
#[derive(Serialize, Deserialize, Debug, PartialEq)]
struct Root {
name: String,
inner: Inner,
}
let root = Root {
name: "outer".into(),
inner: Inner {
title: "temperature".into(),
unit: "°C".into(),
},
};
assert_eq!(modern_string_roundtrip(&root), root);
}
#[test]
fn unicode_and_surrogate_pairs_roundtrip() {
#[derive(Serialize, Deserialize, Debug, PartialEq)]
struct Root {
emoji: String,
accents: String,
cjk: String,
}
let root = Root {
emoji: "🌍🚀😂".into(),
accents: "naïve café résumé".into(),
cjk: "日本語テスト".into(),
};
assert_eq!(modern_string_roundtrip(&root), root);
}
#[test]
fn vec_of_strings_roundtrips_as_cell_of_string_objects() {
#[derive(Serialize, Deserialize, Debug, PartialEq)]
struct Root {
words: Vec<String>,
}
let root = Root {
words: vec!["alpha".into(), "beta".into(), "".into(), "δέλτα".into()],
};
assert_eq!(modern_string_roundtrip(&root), root);
}
#[test]
fn unsupported_object_decode_is_refused_by_name() {
use hdf5_pure::mat::MatError;
use hdf5_pure::{AttrValue, FileBuilder};
let mut builder = FileBuilder::new();
builder
.create_dataset("f")
.with_u32_data(&[0, 0, 0, 0])
.with_shape(&[1, 4])
.set_attr("MATLAB_class", AttrValue::String("function_handle".into()))
.set_attr("MATLAB_object_decode", AttrValue::I32(1));
let bytes = builder.finish().unwrap();
#[derive(Deserialize, Debug)]
struct Root {
#[allow(dead_code)]
f: f64,
}
let err = mat::from_bytes::<Root>(&bytes).expect_err("function_handle is not yet supported");
assert!(
matches!(err, MatError::UnsupportedMatlabClass(ref c) if c == "function_handle"),
"expected UnsupportedMatlabClass(\"function_handle\"), got: {err}"
);
}