use std::path::PathBuf;
use crate::dtype::DataType;
use crate::shape::Shape;
#[derive(Clone, Debug, PartialEq)]
pub struct TensorData {
pub name: Option<String>,
pub dtype: DataType,
pub dims: Vec<usize>,
pub data: Vec<u8>,
pub strings: Vec<String>,
}
impl TensorData {
pub fn from_raw(dtype: DataType, dims: Vec<usize>, data: Vec<u8>) -> Self {
Self {
name: None,
dtype,
dims,
data,
strings: Vec::new(),
}
}
pub fn numel(&self) -> usize {
self.dims.iter().product()
}
pub fn expected_bytes(&self) -> usize {
self.dtype.storage_bytes(self.numel())
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct SparseTensorData {
pub values: TensorData,
pub indices: TensorData,
pub dims: Vec<usize>,
}
#[derive(Clone, Debug, PartialEq)]
pub enum TypeProto {
Tensor { dtype: DataType, shape: Shape },
Sequence(Box<TypeProto>),
Optional(Box<TypeProto>),
Map { key: DataType, value: Box<TypeProto> },
SparseTensor { dtype: DataType, shape: Shape },
}
#[derive(Clone, Debug, PartialEq)]
pub enum WeightRef {
Inline(TensorData),
External {
path: PathBuf,
offset: usize,
length: usize,
dtype: DataType,
dims: Vec<usize>,
},
}
impl WeightRef {
pub fn dtype(&self) -> DataType {
match self {
WeightRef::Inline(t) => t.dtype,
WeightRef::External { dtype, .. } => *dtype,
}
}
pub fn dims(&self) -> &[usize] {
match self {
WeightRef::Inline(t) => &t.dims,
WeightRef::External { dims, .. } => dims,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn tensor_numel_and_bytes() {
let t = TensorData::from_raw(DataType::Float32, vec![2, 3], vec![0u8; 24]);
assert_eq!(t.numel(), 6);
assert_eq!(t.expected_bytes(), 24);
}
#[test]
fn sub_byte_expected_bytes() {
let t = TensorData::from_raw(DataType::Int4, vec![3], vec![0u8; 2]);
assert_eq!(t.numel(), 3);
assert_eq!(t.expected_bytes(), 2); }
#[test]
fn weight_ref_accessors() {
let w = WeightRef::External {
path: PathBuf::from("weights.bin"),
offset: 128,
length: 4096,
dtype: DataType::Float16,
dims: vec![64, 32],
};
assert_eq!(w.dtype(), DataType::Float16);
assert_eq!(w.dims(), &[64, 32]);
}
}