use serde::{Deserialize, Serialize};
use crate::codec;
use crate::{PhiFValue, StmResult};
use super::RegisterError;
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
pub struct Parameters {
pub m: u64,
pub k: u64,
pub phi_f: PhiFValue,
}
impl Parameters {
pub fn to_bytes(&self) -> StmResult<Vec<u8>> {
codec::to_cbor_bytes(self)
}
pub fn from_bytes(bytes: &[u8]) -> StmResult<Self> {
codec::from_versioned_bytes(bytes, Self::from_bytes_legacy)
}
fn from_bytes_legacy(bytes: &[u8]) -> StmResult<Self> {
let mut u64_bytes = [0u8; 8];
u64_bytes.copy_from_slice(bytes.get(..8).ok_or(RegisterError::SerializationError)?);
let m = u64::from_be_bytes(u64_bytes);
u64_bytes.copy_from_slice(bytes.get(8..16).ok_or(RegisterError::SerializationError)?);
let k = u64::from_be_bytes(u64_bytes);
u64_bytes.copy_from_slice(bytes.get(16..24).ok_or(RegisterError::SerializationError)?);
let phi_f = f64::from_be_bytes(u64_bytes);
Ok(Self { m, k, phi_f })
}
}
#[cfg(test)]
mod tests {
use super::*;
mod golden {
use super::*;
const GOLDEN_JSON: &str = r#"
{
"m": 20973,
"k": 2422,
"phi_f": 0.2
}
"#;
fn golden_value() -> Parameters {
Parameters {
m: 20973,
k: 2422,
phi_f: 0.2,
}
}
#[test]
fn golden_conversions() {
let value = serde_json::from_str(GOLDEN_JSON)
.expect("This JSON deserialization should not fail");
assert_eq!(golden_value(), value);
let serialized =
serde_json::to_string(&value).expect("This JSON serialization should not fail");
let golden_serialized = serde_json::to_string(&golden_value())
.expect("This JSON serialization should not fail");
assert_eq!(golden_serialized, serialized);
}
}
mod cbor {
use super::*;
const LEGACY_BYTES: &[u8; 24] = &[
0, 0, 0, 0, 0, 0, 81, 237, 0, 0, 0, 0, 0, 0, 9, 118, 63, 201, 153, 153, 153, 153, 153,
154,
];
fn test_value() -> Parameters {
Parameters {
m: 20973,
k: 2422,
phi_f: 0.2,
}
}
#[test]
fn cbor_roundtrip() {
let value = test_value();
let bytes = value.to_bytes().expect("CBOR serialization should not fail");
let decoded =
Parameters::from_bytes(&bytes).expect("CBOR deserialization should not fail");
assert_eq!(value, decoded);
}
#[test]
fn legacy_bytes_can_still_be_decoded() {
let decoded = Parameters::from_bytes(LEGACY_BYTES)
.expect("Legacy deserialization should not fail");
assert_eq!(test_value(), decoded);
}
const GOLDEN_CBOR_BYTES: &[u8; 27] = &[
1, 163, 97, 109, 25, 81, 237, 97, 107, 25, 9, 118, 101, 112, 104, 105, 95, 102, 251,
63, 201, 153, 153, 153, 153, 153, 154,
];
#[test]
fn cbor_golden_bytes_can_be_decoded() {
let decoded = Parameters::from_bytes(GOLDEN_CBOR_BYTES)
.expect("CBOR golden bytes deserialization should not fail");
assert_eq!(test_value(), decoded);
}
#[test]
fn cbor_encoding_is_stable() {
let bytes = test_value().to_bytes().expect("CBOR serialization should not fail");
assert_eq!(GOLDEN_CBOR_BYTES.as_slice(), bytes.as_slice());
}
}
}