Skip to main content

matten/
ser.rs

1//! Serde integration for [`Tensor`](crate::Tensor) (RFC-009, `serde` feature).
2//!
3//! The canonical on-wire representation is a JSON object with two fields:
4//!
5//! ```json
6//! { "shape": [2, 2], "data": [1.0, 2.0, 3.0, 4.0] }
7//! ```
8//!
9//! This form is unambiguous for any rank, avoids deeply nested JSON for higher-
10//! rank tensors, and maps 1:1 to the internal flat row-major storage.
11//!
12//! Deserialization validates shape consistency with `Tensor::try_new`, so a
13//! malformed payload (shape/data length mismatch, zero-sized dim, overflow,
14//! rank too large) yields a serde error rather than a panic.
15
16#[cfg(feature = "serde")]
17use crate::Tensor;
18#[cfg(feature = "serde")]
19use serde::{Deserialize, Deserializer, Serialize, Serializer};
20/// Private mirror used for serde round-trips.
21#[cfg(feature = "serde")]
22#[derive(Serialize, Deserialize)]
23struct TensorSerde {
24    shape: Vec<usize>,
25    data: Vec<f64>,
26}
27
28#[cfg(feature = "serde")]
29impl Serialize for Tensor {
30    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
31        #[cfg(feature = "dynamic")]
32        if self.is_dynamic() {
33            return Err(serde::ser::Error::custom(
34                "matten: dynamic tensors cannot be serialized with the default serde \
35                 implementation; call try_numeric() first to convert to a numeric \
36                 tensor, or use to_elements() to handle Element values manually",
37            ));
38        }
39        TensorSerde {
40            shape: self.shape().to_vec(),
41            data: self.to_vec(),
42        }
43        .serialize(serializer)
44    }
45}
46
47#[cfg(feature = "serde")]
48impl<'de> Deserialize<'de> for Tensor {
49    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
50        let ts = TensorSerde::deserialize(deserializer)?;
51        Tensor::try_new(ts.data, &ts.shape).map_err(serde::de::Error::custom)
52    }
53}