use std::path::PathBuf;
use ztensor::{DType, Error, Source, Writer};
use ztensor_compat::csr;
fn tmp(name: &str) -> PathBuf {
PathBuf::from(env!("CARGO_TARGET_TMPDIR")).join(name)
}
fn le_u64s(vals: &[u64]) -> Vec<u8> {
vals.iter().flat_map(|v| v.to_le_bytes()).collect()
}
fn f32s(vals: &[f32]) -> Vec<u8> {
vals.iter().flat_map(|v| v.to_le_bytes()).collect()
}
#[test]
fn csr_roundtrip() {
let path = tmp("csr.zt");
let values = f32s(&[1.0, 2.0, 3.0]);
let indices = le_u64s(&[0, 2, 1]);
let indptr = le_u64s(&[0, 2, 3]);
let mut w = Writer::create(&path).unwrap();
w.object("m", |o| {
o.shape([2u64, 3])
.layout("zt.sparse_csr/1")
.part("values", |p| p.dtype(DType::F32).bytes(&values))
.part("indices", |p| p.dtype(DType::U64).bytes(&indices))
.part("indptr", |p| p.dtype(DType::U64).bytes(&indptr))
})
.unwrap();
w.finish().unwrap();
let src = Source::open(&path).unwrap();
let tensor = src.tensor("m").unwrap();
let csr = csr::read(&tensor).unwrap();
assert_eq!((csr.rows, csr.cols), (2, 3));
assert_eq!(csr.indices, vec![0, 2, 1]);
assert_eq!(csr.indptr, vec![0, 2, 3]);
assert_eq!(csr.values, values);
assert_eq!(csr.dtype, DType::F32);
assert_eq!(tensor.part("values").unwrap().map().unwrap(), &values[..]);
}
#[test]
fn a_foreign_layout_is_not_assembled_as_csr() {
let path = tmp("csr-not.zt");
let mut w = Writer::create(&path).unwrap();
w.object("q", |o| {
o.shape([64u64])
.layout("pie.custom/1")
.part("scales", |p| p.dtype(DType::U8).bytes(&[1u8; 64]))
.part("weights", |p| p.dtype(DType::U8).bytes(&[2u8; 32]))
})
.unwrap();
w.finish().unwrap();
let src = Source::open(&path).unwrap();
let tensor = src.tensor("q").unwrap();
assert!(matches!(csr::read(&tensor), Err(Error::Unsupported(_))));
}