1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
//! # Fixed Size Integers
//!
//! In some cases, the use of variably length encoded data may not be
//! preferrable. These modules, for use with `#[serde(with = ...)]`
//! "opt out" of variable length encoding.
//!
//! Support explicitly not provided for `usize` or `isize`, as
//! these types would not be portable between systems of different
//! pointer widths.
//!
//! Although all data in Postcard is typically encoded in little-endian
//! order, these modules provide a choice to the user to encode the data
//! in either little or big endian form, which may be useful for zero-copy
//! applications.
use serde::{Deserialize, Serialize, Serializer};
/// Use with the `#[serde(with = "postcard::fixint::le")]` field attribute.
/// Disables varint serialization/deserialization for the specified integer
/// field. The integer will always be serialized in the same way as a fixed
/// size array, in **Little Endian** order on the wire.
///
/// ```rust
/// # use serde::Serialize;
/// #[derive(Serialize)]
/// pub struct DefinitelyLittleEndian {
/// #[serde(with = "postcard::fixint::le")]
/// x: u16,
/// }
/// ```
pub mod le {
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use super::LE;
/// Serialize the integer value as a little-endian fixed-size array.
pub fn serialize<S, T>(val: &T, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
T: Copy,
LE<T>: Serialize,
{
LE(*val).serialize(serializer)
}
/// Deserialize the integer value from a little-endian fixed-size array.
pub fn deserialize<'de, D, T>(deserializer: D) -> Result<T, D::Error>
where
D: Deserializer<'de>,
LE<T>: Deserialize<'de>,
{
LE::<T>::deserialize(deserializer).map(|x| x.0)
}
}
/// Use with the `#[serde(with = "postcard::fixint::be")]` field attribute.
/// Disables varint serialization/deserialization for the specified integer
/// field. The integer will always be serialized in the same way as a fixed
/// size array, in **Big Endian** order on the wire.
///
/// ```rust
/// # use serde::Serialize;
/// #[derive(Serialize)]
/// pub struct DefinitelyBigEndian {
/// #[serde(with = "postcard::fixint::be")]
/// x: u16,
/// }
/// ```
pub mod be {
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use super::BE;
/// Serialize the integer value as a big-endian fixed-size array.
pub fn serialize<S, T>(val: &T, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
T: Copy,
BE<T>: Serialize,
{
BE(*val).serialize(serializer)
}
/// Deserialize the integer value from a big-endian fixed-size array.
pub fn deserialize<'de, D, T>(deserializer: D) -> Result<T, D::Error>
where
D: Deserializer<'de>,
BE<T>: Deserialize<'de>,
{
BE::<T>::deserialize(deserializer).map(|x| x.0)
}
}
#[doc(hidden)]
pub struct LE<T>(T);
#[doc(hidden)]
pub struct BE<T>(T);
macro_rules! impl_fixint {
($( $int:ty ),*) => {
$(
impl Serialize for LE<$int> {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.0.to_le_bytes().serialize(serializer)
}
}
impl<'de> Deserialize<'de> for LE<$int> {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
<_ as Deserialize>::deserialize(deserializer)
.map(<$int>::from_le_bytes)
.map(Self)
}
}
impl Serialize for BE<$int> {
#[inline]
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.0.to_be_bytes().serialize(serializer)
}
}
impl<'de> Deserialize<'de> for BE<$int> {
#[inline]
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
<_ as Deserialize>::deserialize(deserializer)
.map(<$int>::from_be_bytes)
.map(Self)
}
}
)*
};
}
impl_fixint![i16, i32, i64, i128, u16, u32, u64, u128];
#[cfg(test)]
mod tests {
use serde::{Deserialize, Serialize};
#[test]
fn test_little_endian() {
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
pub struct DefinitelyLE {
#[serde(with = "crate::fixint::le")]
x: u16,
}
let input = DefinitelyLE { x: 0xABCD };
let mut buf = [0; 32];
let serialized = crate::to_slice(&input, &mut buf).unwrap();
assert_eq!(serialized, &[0xCD, 0xAB]);
let deserialized: DefinitelyLE = crate::from_bytes(serialized).unwrap();
assert_eq!(deserialized, input);
}
#[test]
fn test_big_endian() {
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
pub struct DefinitelyBE {
#[serde(with = "crate::fixint::be")]
x: u16,
}
let input = DefinitelyBE { x: 0xABCD };
let mut buf = [0; 32];
let serialized = crate::to_slice(&input, &mut buf).unwrap();
assert_eq!(serialized, &[0xAB, 0xCD]);
let deserialized: DefinitelyBE = crate::from_bytes(serialized).unwrap();
assert_eq!(deserialized, input);
}
}