pub mod option_unit_as_null_or_true {
use serde::{de, ser, Deserialize, Serialize};
#[doc(hidden)]
pub fn serialize<S>(value: &Option<()>, ser: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
match value {
None => ().serialize(ser),
Some(()) => true.serialize(ser),
}
}
#[doc(hidden)]
pub fn deserialize<'de, D>(de: D) -> Result<Option<()>, D::Error>
where
D: de::Deserializer<'de>,
{
match OptionAsNullOrTrue::deserialize(de)? {
OptionAsNullOrTrue::Null(()) => Ok(None),
OptionAsNullOrTrue::True(true) => Ok(Some(())),
_ => Err(de::Error::invalid_value(
de::Unexpected::Bool(false),
&"null or true",
)),
}
}
#[derive(Deserialize)]
#[serde(untagged)]
enum OptionAsNullOrTrue {
Null(()),
True(bool),
}
}
pub mod option_unit_as_bool {
use serde::{de, ser, Deserialize, Serialize};
#[doc(hidden)]
pub fn serialize<S>(value: &Option<()>, ser: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
value.is_some().serialize(ser)
}
#[doc(hidden)]
pub fn deserialize<'de, D>(de: D) -> Result<Option<()>, D::Error>
where
D: de::Deserializer<'de>,
{
Ok(if bool::deserialize(de)? {
Some(())
} else {
None
})
}
}
pub mod option_unit_as_list {
use serde::{de, ser, Deserialize, Serialize};
#[doc(hidden)]
pub fn serialize<S>(value: &Option<()>, ser: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
OptionAsList { unit: *value }.serialize(ser)
}
#[doc(hidden)]
pub fn deserialize<'de, D>(de: D) -> Result<Option<()>, D::Error>
where
D: de::Deserializer<'de>,
{
let o = OptionAsList::deserialize(de)?;
Ok(o.unit)
}
#[derive(Serialize, Deserialize)]
struct OptionAsList {
#[serde(default)]
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(deserialize_with = "deserialize_prefer_some")]
unit: Option<()>,
}
fn deserialize_prefer_some<'de, D>(de: D) -> Result<Option<()>, D::Error>
where
D: de::Deserializer<'de>,
{
let _ = <()>::deserialize(de)?;
Ok(Some(()))
}
}
pub mod u64_as_i64 {
use serde::{de, ser, Deserialize, Serialize};
#[doc(hidden)]
pub fn serialize<S>(value: &u64, ser: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
i64::from_be_bytes(value.to_be_bytes()).serialize(ser)
}
#[doc(hidden)]
pub fn deserialize<'de, D>(de: D) -> Result<u64, D::Error>
where
D: de::Deserializer<'de>,
{
let value = i64::deserialize(de)?;
Ok(u64::from_be_bytes(value.to_be_bytes()))
}
}
pub mod u64_as_bytes {
use super::array_as_bytes::ByteArrayVisitor;
use serde::{de, ser};
#[doc(hidden)]
pub fn serialize<S>(value: &u64, ser: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
ser.serialize_bytes(&value.to_be_bytes())
}
#[doc(hidden)]
pub fn deserialize<'de, D>(de: D) -> Result<u64, D::Error>
where
D: de::Deserializer<'de>,
{
let bytes = de.deserialize_bytes(ByteArrayVisitor::default())?;
Ok(u64::from_be_bytes(bytes))
}
}
pub mod u64_as_i64_or_bytes {
use serde::{de, ser, Deserialize};
#[doc(hidden)]
pub fn serialize<S>(value: &u64, ser: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
if *value > i64::MAX as u64 {
super::u64_as_bytes::serialize(value, ser)
} else {
super::u64_as_i64::serialize(value, ser)
}
}
#[doc(hidden)]
pub fn deserialize<'de, D>(de: D) -> Result<u64, D::Error>
where
D: de::Deserializer<'de>,
{
match U64AsI64OrRaw::deserialize(de)? {
U64AsI64OrRaw::I64(value) if value <= i64::MAX as u64 => Ok(value as u64),
U64AsI64OrRaw::Raw(value) if value > i64::MAX as u64 => Ok(value),
_ => Err(de::Error::invalid_value(
de::Unexpected::Other("out-of-bounds i64 or raw"),
&"i64 >= 0 or raw <= i64::MAX",
)),
}
}
#[derive(Deserialize)]
#[serde(untagged)]
enum U64AsI64OrRaw {
I64(u64),
#[serde(with = "super::u64_as_bytes")]
Raw(u64),
}
}
pub mod array_as_bytes {
use serde::{de, ser};
use std::{fmt, marker::PhantomData};
#[doc(hidden)]
pub trait CopyFromSlice: Default {
const LENGTH: usize;
fn copy_from_slice(&mut self, slice: &[u8]);
}
macro_rules! copy_from_slice_array_impl {
($n:literal) => {
impl CopyFromSlice for [u8; $n] {
const LENGTH: usize = $n;
fn copy_from_slice(&mut self, slice: &[u8]) {
<[u8]>::copy_from_slice(self, slice)
}
}
};
}
copy_from_slice_array_impl!(0);
copy_from_slice_array_impl!(1);
copy_from_slice_array_impl!(2);
copy_from_slice_array_impl!(3);
copy_from_slice_array_impl!(4);
copy_from_slice_array_impl!(5);
copy_from_slice_array_impl!(6);
copy_from_slice_array_impl!(7);
copy_from_slice_array_impl!(8);
copy_from_slice_array_impl!(9);
copy_from_slice_array_impl!(10);
copy_from_slice_array_impl!(11);
copy_from_slice_array_impl!(12);
copy_from_slice_array_impl!(13);
copy_from_slice_array_impl!(14);
copy_from_slice_array_impl!(15);
copy_from_slice_array_impl!(16);
copy_from_slice_array_impl!(17);
copy_from_slice_array_impl!(18);
copy_from_slice_array_impl!(19);
copy_from_slice_array_impl!(20);
copy_from_slice_array_impl!(21);
copy_from_slice_array_impl!(22);
copy_from_slice_array_impl!(23);
copy_from_slice_array_impl!(24);
copy_from_slice_array_impl!(25);
copy_from_slice_array_impl!(26);
copy_from_slice_array_impl!(27);
copy_from_slice_array_impl!(28);
copy_from_slice_array_impl!(29);
copy_from_slice_array_impl!(30);
copy_from_slice_array_impl!(31);
copy_from_slice_array_impl!(32);
#[derive(Default)]
pub(crate) struct ByteArrayVisitor<T>
where
T: CopyFromSlice,
{
array: PhantomData<T>,
}
impl<'de, T> de::Visitor<'de> for ByteArrayVisitor<T>
where
T: CopyFromSlice,
{
type Value = T;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("byte array")
}
fn visit_bytes<E>(self, bytes: &[u8]) -> Result<T, E>
where
E: de::Error,
{
if bytes.len() != T::LENGTH {
return Err(de::Error::invalid_length(bytes.len(), &"array size"));
}
let mut buf = T::default();
buf.copy_from_slice(bytes);
Ok(buf)
}
fn visit_byte_buf<E>(self, bytes: Vec<u8>) -> Result<T, E>
where
E: de::Error,
{
self.visit_bytes(&bytes)
}
}
#[doc(hidden)]
pub fn serialize<S, T>(value: &T, ser: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
T: AsRef<[u8]>,
{
ser.serialize_bytes(value.as_ref())
}
#[doc(hidden)]
pub fn deserialize<'de, D, T>(de: D) -> Result<T, D::Error>
where
D: de::Deserializer<'de>,
T: CopyFromSlice,
{
de.deserialize_bytes(ByteArrayVisitor::default())
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::from_slice;
use crate::to_vec;
use hex_literal::hex;
use serde::{Deserialize, Serialize};
#[test]
fn customize_option_unit() {
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
struct Test {
#[serde(with = "option_unit_as_null_or_true")]
a0: Option<()>,
#[serde(with = "option_unit_as_null_or_true")]
a1: Option<()>,
#[serde(with = "option_unit_as_bool")]
b0: Option<()>,
#[serde(with = "option_unit_as_bool")]
b1: Option<()>,
#[serde(with = "option_unit_as_list")]
c0: Option<()>,
#[serde(with = "option_unit_as_list")]
c1: Option<()>,
}
let input = Test {
a0: None,
a1: Some(()),
b0: None,
b1: Some(()),
c0: None,
c1: Some(()),
};
let buf = to_vec(&input).unwrap();
assert_eq!(
hex!("60 00 11 10 11 60 80 60 00 80 80").as_ref(),
buf.as_slice()
);
let output = from_slice(&buf).unwrap();
assert_eq!(input, output);
}
#[test]
fn customize_u64() {
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
struct Test {
#[serde(with = "u64_as_i64")]
a0: u64,
#[serde(with = "u64_as_i64")]
a1: u64,
#[serde(with = "u64_as_bytes")]
b0: u64,
#[serde(with = "u64_as_bytes")]
b1: u64,
#[serde(with = "u64_as_i64_or_bytes")]
c0: u64,
#[serde(with = "u64_as_i64_or_bytes")]
c1: u64,
}
let input = Test {
a0: 17,
a1: 0x8765432101234567,
b0: 17,
b1: 0x8765432101234567,
c0: 17,
c1: 0x8765432101234567,
};
let buf = to_vec(&input).unwrap();
assert_eq!(
hex!("60 2111 288765432101234567 51080000000000000011 51088765432101234567 2111 51088765432101234567 80").as_ref(),
buf.as_slice()
);
let output = from_slice(&buf).unwrap();
assert_eq!(input, output);
}
}