use serde::de::{self, Deserializer, SeqAccess, Visitor};
use serde::ser::Serializer;
use std::fmt;
pub mod u128_bytes {
use super::*;
pub fn serialize<S: Serializer>(val: &u128, ser: S) -> Result<S::Ok, S::Error> {
ser.serialize_bytes(&val.to_be_bytes())
}
pub fn deserialize<'de, D: Deserializer<'de>>(de: D) -> Result<u128, D::Error> {
de.deserialize_bytes(U128Visitor)
}
pub(super) struct U128Visitor;
impl<'de> Visitor<'de> for U128Visitor {
type Value = u128;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("16 bytes for u128")
}
fn visit_bytes<E: de::Error>(self, v: &[u8]) -> Result<u128, E> {
let arr: [u8; 16] = v
.try_into()
.map_err(|_| E::invalid_length(v.len(), &"16 bytes"))?;
Ok(u128::from_be_bytes(arr))
}
fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<u128, A::Error> {
let mut bytes = [0u8; 16];
for (i, byte) in bytes.iter_mut().enumerate() {
*byte = seq
.next_element()?
.ok_or_else(|| de::Error::invalid_length(i, &"16 bytes"))?;
}
Ok(u128::from_be_bytes(bytes))
}
}
}
pub mod option_u128_bytes {
use super::*;
pub fn serialize<S: Serializer>(val: &Option<u128>, ser: S) -> Result<S::Ok, S::Error> {
match val {
Some(v) => ser.serialize_bytes(&v.to_be_bytes()),
None => ser.serialize_none(),
}
}
pub fn deserialize<'de, D: Deserializer<'de>>(de: D) -> Result<Option<u128>, D::Error> {
de.deserialize_option(OptU128Visitor)
}
pub(super) struct OptU128Visitor;
impl<'de> Visitor<'de> for OptU128Visitor {
type Value = Option<u128>;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("null or 16 bytes for u128")
}
fn visit_none<E: de::Error>(self) -> Result<Option<u128>, E> {
Ok(None)
}
fn visit_some<D2: Deserializer<'de>>(self, de: D2) -> Result<Option<u128>, D2::Error> {
super::u128_bytes::deserialize(de).map(Some)
}
fn visit_bytes<E: de::Error>(self, v: &[u8]) -> Result<Option<u128>, E> {
let arr: [u8; 16] = v
.try_into()
.map_err(|_| E::invalid_length(v.len(), &"16 bytes"))?;
Ok(Some(u128::from_be_bytes(arr)))
}
}
}
pub mod vec_u128_bytes {
use super::*;
pub fn serialize<S: Serializer>(val: &[u128], ser: S) -> Result<S::Ok, S::Error> {
use serde::ser::SerializeSeq;
let mut seq = ser.serialize_seq(Some(val.len()))?;
for v in val {
seq.serialize_element(&v.to_be_bytes())?; }
seq.end()
}
pub fn deserialize<'de, D: Deserializer<'de>>(de: D) -> Result<Vec<u128>, D::Error> {
de.deserialize_seq(VecU128Visitor)
}
pub(super) struct VecU128Visitor;
impl<'de> Visitor<'de> for VecU128Visitor {
type Value = Vec<u128>;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("sequence of 16-byte u128 values")
}
fn visit_seq<A: SeqAccess<'de>>(self, mut seq: A) -> Result<Vec<u128>, A::Error> {
let mut out = Vec::with_capacity(seq.size_hint().unwrap_or(0));
while let Some(arr) = seq.next_element::<[u8; 16]>()? {
out.push(u128::from_be_bytes(arr));
}
Ok(out)
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use serde::de::Visitor;
#[derive(Debug)]
struct StubError(String);
impl std::fmt::Display for StubError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.0)
}
}
impl std::error::Error for StubError {}
impl de::Error for StubError {
fn custom<T: std::fmt::Display>(msg: T) -> Self {
StubError(msg.to_string())
}
}
#[test]
fn u128_visitor_expecting_writes_specific_message() {
let mut buf = String::new();
std::fmt::write(
&mut buf,
format_args!("{}", ExpectingDisplay(&u128_bytes::U128Visitor)),
)
.expect("write");
assert_eq!(
buf, "16 bytes for u128",
"PROPERTY: U128Visitor::expecting must produce the canonical message. \
A mutation that replaces the body with `Ok(Default::default())` \
would produce an empty string and break this assertion."
);
}
#[test]
fn u128_visitor_visit_bytes_round_trips_known_value() {
let value: u128 = 0x0102_0304_0506_0708_090a_0b0c_0d0e_0f10;
let bytes = value.to_be_bytes();
let result: Result<u128, StubError> = u128_bytes::U128Visitor.visit_bytes(&bytes);
assert_eq!(
result.expect("16-byte input must decode"),
value,
"PROPERTY: U128Visitor::visit_bytes must round-trip a known 16-byte big-endian \
encoding back to the original u128. Mutations that hard-code 0 or default would \
fail this assertion."
);
}
#[test]
fn u128_visitor_visit_bytes_rejects_wrong_length() {
let result: Result<u128, StubError> = u128_bytes::U128Visitor.visit_bytes(&[0u8; 8]);
assert!(
result.is_err(),
"PROPERTY: U128Visitor::visit_bytes must reject inputs that are not exactly 16 bytes."
);
}
#[test]
fn opt_u128_visitor_expecting_writes_specific_message() {
let mut buf = String::new();
std::fmt::write(
&mut buf,
format_args!("{}", ExpectingDisplay(&option_u128_bytes::OptU128Visitor)),
)
.expect("write");
assert_eq!(
buf, "null or 16 bytes for u128",
"PROPERTY: OptU128Visitor::expecting must produce the canonical message."
);
}
#[test]
fn opt_u128_visitor_visit_bytes_returns_some_known_value() {
let value: u128 = 0xDEAD_BEEF_CAFE_F00D_FEED_FACE_BAAD_F00D;
let bytes = value.to_be_bytes();
let result: Result<Option<u128>, StubError> =
option_u128_bytes::OptU128Visitor.visit_bytes(&bytes);
assert_eq!(
result.expect("16-byte input must decode"),
Some(value),
"PROPERTY: OptU128Visitor::visit_bytes must round-trip a known 16-byte big-endian \
encoding back to Some(u128). Mutations that return Ok(None), Ok(Some(0)), or \
Ok(Some(1)) would all fail this assertion."
);
}
#[test]
fn opt_u128_visitor_visit_bytes_rejects_wrong_length() {
let result: Result<Option<u128>, StubError> =
option_u128_bytes::OptU128Visitor.visit_bytes(&[0u8; 4]);
assert!(
result.is_err(),
"PROPERTY: OptU128Visitor::visit_bytes must reject inputs that are not exactly 16 bytes."
);
}
#[test]
fn opt_u128_visitor_visit_none_returns_none() {
let result: Result<Option<u128>, StubError> =
option_u128_bytes::OptU128Visitor.visit_none();
assert_eq!(
result.expect("visit_none never errors"),
None,
"PROPERTY: OptU128Visitor::visit_none must return Ok(None)."
);
}
#[test]
fn vec_u128_visitor_expecting_writes_specific_message() {
let mut buf = String::new();
std::fmt::write(
&mut buf,
format_args!("{}", ExpectingDisplay(&vec_u128_bytes::VecU128Visitor)),
)
.expect("write");
assert_eq!(
buf, "sequence of 16-byte u128 values",
"PROPERTY: VecU128Visitor::expecting must produce the canonical message."
);
}
struct ExpectingDisplay<'a, V: ?Sized>(&'a V);
impl<'a, V: for<'de> serde::de::Visitor<'de>> std::fmt::Display for ExpectingDisplay<'a, V> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.0.expecting(f)
}
}
}