Skip to content

Commit 5bff536

Browse files
committed
Manually implement Serialize and Deserialize for VecStorage
1 parent 58bea21 commit 5bff536

File tree

2 files changed

+76
-3
lines changed

2 files changed

+76
-3
lines changed

src/base/vec_storage.rs

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ use crate::base::storage::{
1313
};
1414
use crate::base::{Scalar, Vector};
1515

16+
#[cfg(feature = "serde-serialize-no-std")]
17+
use serde::{
18+
de::{Deserialize, Deserializer, Error},
19+
ser::{Serialize, Serializer},
20+
};
21+
1622
#[cfg(feature = "abomonation-serialize")]
1723
use abomonation::Abomonation;
1824

@@ -24,13 +30,54 @@ use abomonation::Abomonation;
2430
/// A Vec-based matrix data storage. It may be dynamically-sized.
2531
#[repr(C)]
2632
#[derive(Eq, Debug, Clone, PartialEq)]
27-
#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
2833
pub struct VecStorage<T, R: Dim, C: Dim> {
2934
data: Vec<T>,
3035
nrows: R,
3136
ncols: C,
3237
}
3338

39+
#[cfg(feature = "serde-serialize")]
40+
impl<T, R: Dim, C: Dim> Serialize for VecStorage<T, R, C>
41+
where
42+
T: Serialize,
43+
R: Serialize,
44+
C: Serialize,
45+
{
46+
fn serialize<Ser>(&self, serializer: Ser) -> Result<Ser::Ok, Ser::Error>
47+
where
48+
Ser: Serializer,
49+
{
50+
(&self.data, &self.nrows, &self.ncols).serialize(serializer)
51+
}
52+
}
53+
54+
#[cfg(feature = "serde-serialize")]
55+
impl<'a, T, R: Dim, C: Dim> Deserialize<'a> for VecStorage<T, R, C>
56+
where
57+
T: Deserialize<'a>,
58+
R: Deserialize<'a>,
59+
C: Deserialize<'a>,
60+
{
61+
fn deserialize<Des>(deserializer: Des) -> Result<Self, Des::Error>
62+
where
63+
Des: Deserializer<'a>,
64+
{
65+
let (data, nrows, ncols): (Vec<T>, R, C) = Deserialize::deserialize(deserializer)?;
66+
67+
// SAFETY: make sure the data we deserialize have the
68+
// correct number of elements.
69+
if nrows.value() * ncols.value() != data.len() {
70+
return Err(Des::Error::custom(format!(
71+
"Expected {} components, found {}",
72+
nrows.value() * ncols.value(),
73+
data.len()
74+
)));
75+
}
76+
77+
Ok(Self { data, nrows, ncols })
78+
}
79+
}
80+
3481
#[deprecated(note = "renamed to `VecStorage`")]
3582
/// Renamed to [VecStorage].
3683
pub type MatrixVec<T, R, C> = VecStorage<T, R, C>;

tests/core/serde.rs

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#![cfg(feature = "serde-serialize")]
22

33
use na::{
4-
DMatrix, Isometry2, Isometry3, IsometryMatrix2, IsometryMatrix3, Matrix3x4, Point2, Point3,
5-
Quaternion, Rotation2, Rotation3, Similarity2, Similarity3, SimilarityMatrix2,
4+
DMatrix, Isometry2, Isometry3, IsometryMatrix2, IsometryMatrix3, Matrix2x3, Matrix3x4, Point2,
5+
Point3, Quaternion, Rotation2, Rotation3, Similarity2, Similarity3, SimilarityMatrix2,
66
SimilarityMatrix3, Translation2, Translation3, Unit, Vector2,
77
};
88
use rand;
@@ -27,6 +27,32 @@ fn serde_dmatrix() {
2727
let serialized = serde_json::to_string(&v).unwrap();
2828
let deserialized: DMatrix<f32> = serde_json::from_str(&serialized).unwrap();
2929
assert_eq!(v, deserialized);
30+
31+
let m = DMatrix::from_column_slice(2, 3, &[1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
32+
let mat_str = "[[1.0, 2.0, 3.0, 4.0, 5.0, 6.0],2,3]";
33+
let deserialized: DMatrix<f32> = serde_json::from_str(&mat_str).unwrap();
34+
assert_eq!(m, deserialized);
35+
36+
let m = Matrix2x3::from_column_slice(&[1.0, 2.0, 3.0, 4.0, 5.0, 6.0]);
37+
let mat_str = "[1.0, 2.0, 3.0, 4.0, 5.0, 6.0]";
38+
let deserialized: Matrix2x3<f32> = serde_json::from_str(&mat_str).unwrap();
39+
assert_eq!(m, deserialized);
40+
}
41+
42+
#[test]
43+
#[should_panic]
44+
fn serde_dmatrix_invalid_len() {
45+
// This must fail: we attempt to deserialize a 2x3 with only 5 elements.
46+
let mat_str = "[[1.0, 2.0, 3.0, 4.0, 5.0],2,3]";
47+
let _: DMatrix<f32> = serde_json::from_str(&mat_str).unwrap();
48+
}
49+
50+
#[test]
51+
#[should_panic]
52+
fn serde_smatrix_invalid_len() {
53+
// This must fail: we attempt to deserialize a 2x3 with only 5 elements.
54+
let mat_str = "[1.0, 2.0, 3.0, 4.0, 5.0]";
55+
let _: Matrix2x3<f32> = serde_json::from_str(&mat_str).unwrap();
3056
}
3157

3258
test_serde!(

0 commit comments

Comments
 (0)