#[derive(
PartialEq,
Eq,
Clone,
Debug,
openmls_serialization_helpers::Serialize,
openmls_serialization_helpers::Deserialize,
)]
enum TestEnum {
#[storage_tag = 0]
Unit,
#[storage_tag = 3]
Unit2,
#[storage_tag = 2000]
Value(u64),
#[storage_tag = 2]
Data([u8; 3]),
#[storage_tag = 500]
Data2(u64, [u8; 3]),
#[storage_tag = 4]
Unit3,
}
struct TestCase {
data: TestEnum,
expected_tag: u32,
}
#[test]
fn test_serialization_deserialization_postcard() {
for TestCase {
data,
expected_tag: expected_discriminant,
} in TEST_CASES
{
let serialized = &postcard::to_allocvec(&data).expect("serialization failed");
let serialized_discriminant = &postcard::to_allocvec(expected_discriminant).unwrap();
assert!(serialized.starts_with(serialized_discriminant));
let deserialized: TestEnum =
postcard::from_bytes(serialized).expect("deserialization failed");
assert_eq!(data, &deserialized);
}
}
#[derive(serde::Serialize)]
enum TestEnumCompare {
Unit,
Unit2,
Value(u64),
Data([u8; 3]),
Data2(u64, [u8; 3]),
Unit3,
}
impl From<&TestEnum> for TestEnumCompare {
fn from(orig: &TestEnum) -> Self {
match orig {
TestEnum::Unit => Self::Unit,
TestEnum::Unit2 => Self::Unit2,
TestEnum::Value(value) => Self::Value(*value),
TestEnum::Data(data) => Self::Data(*data),
TestEnum::Data2(value, data) => Self::Data2(*value, *data),
TestEnum::Unit3 => Self::Unit3,
}
}
}
#[test]
fn test_serialization_deserialization_serde_json() {
for TestCase { data, .. } in TEST_CASES {
let serialized = serde_json::to_string(&data).expect("serialization failed");
let serialized_compare = serde_json::to_string(&TestEnumCompare::from(data)).unwrap();
assert_eq!(serialized, serialized_compare);
let deserialized: TestEnum =
serde_json::from_str(&serialized).expect("deserialization failed");
assert_eq!(data, &deserialized);
}
}
#[test]
fn test_serialization_deserialization_ciborium() {
for TestCase { data, .. } in TEST_CASES {
let mut serialized = Vec::new();
ciborium::into_writer(&data, &mut serialized).expect("serialization failed");
let deserialized: TestEnum =
ciborium::from_reader(serialized.as_slice()).expect("deserialization failed");
assert_eq!(data, &deserialized);
}
}
const TEST_CASES: &[TestCase] = &[
TestCase {
data: TestEnum::Unit,
expected_tag: 0,
},
TestCase {
data: TestEnum::Unit2,
expected_tag: 3,
},
TestCase {
data: TestEnum::Data([1, 2, 3]),
expected_tag: 2,
},
TestCase {
data: TestEnum::Data2(0, [1, 2, 3]),
expected_tag: 500,
},
TestCase {
data: TestEnum::Value(0),
expected_tag: 2000,
},
TestCase {
data: TestEnum::Value(60),
expected_tag: 2000,
},
TestCase {
data: TestEnum::Unit3,
expected_tag: 4,
},
];
#[test]
fn deserialize_invalid_storage_tag_non_self_describing() {
#[derive(Debug, openmls_serialization_helpers::Serialize)]
enum Serialized {
#[storage_tag = 1]
Unit,
}
#[derive(Debug, openmls_serialization_helpers::Deserialize)]
enum Deserialized {
#[storage_tag = 2]
Unit,
}
let serialized = &postcard::to_allocvec(&Serialized::Unit).expect("serialization failed");
let err =
postcard::from_bytes::<Deserialized>(serialized).expect_err("deserialization should fail");
assert!(matches!(err, postcard::Error::SerdeDeCustom));
}
#[test]
fn deserialize_invalid_variant_name_self_describing() {
#[derive(Debug, openmls_serialization_helpers::Serialize)]
enum Serialized {
#[storage_tag = 1]
Unit,
}
#[derive(Debug, openmls_serialization_helpers::Deserialize)]
enum Deserialized {
#[storage_tag = 1]
Unit2,
}
let serialized = &serde_json::to_string(&Serialized::Unit).expect("serialization failed");
let err =
serde_json::from_str::<Deserialized>(serialized).expect_err("deserialization should fail");
assert_eq!(err.to_string(), "unexpected variant name \"Unit\"");
}
#[test]
fn test_tuple_deserialization_fails_with_too_few_fields_self_describing() {
#[derive(Debug, openmls_serialization_helpers::Serialize)]
enum Serialized {
#[storage_tag = 1]
Data(u16),
}
#[allow(dead_code)]
#[derive(Debug, openmls_serialization_helpers::Deserialize)]
enum Deserialized {
#[storage_tag = 1]
Data(u16, u16),
}
let data = Serialized::Data(1);
let serialized = &serde_json::to_string(&data).expect("serialization failed");
let err =
serde_json::from_str::<Deserialized>(serialized).expect_err("deserialization should fail");
assert!(err.to_string().contains("expected a tuple of two elements"));
}
#[test]
fn test_with_feature_flag() {
#[derive(
PartialEq,
Eq,
Clone,
Debug,
openmls_serialization_helpers::Serialize,
openmls_serialization_helpers::Deserialize,
)]
enum TestEnumWithFeatureFlags {
#[storage_tag = 0]
Unit1,
#[cfg(feature = "test-feature")]
#[storage_tag = 1]
Data(usize, usize),
#[storage_tag = 2]
Unit2,
}
let data = TestEnumWithFeatureFlags::Unit2;
let serialized = &serde_json::to_string(&data).expect("serialization failed");
let deserialized = serde_json::from_str::<TestEnumWithFeatureFlags>(serialized)
.expect("deserialization failed");
assert_eq!(data, deserialized);
}