use std::fmt;
use serde::de::{self, Visitor};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
#[derive(Clone, Default, PartialEq, Eq, Hash)]
pub struct Payload(pub Vec<u8>);
impl Payload {
pub fn new() -> Self {
Self::default()
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn as_slice(&self) -> &[u8] {
&self.0
}
pub fn into_inner(self) -> Vec<u8> {
self.0
}
}
impl From<Vec<u8>> for Payload {
fn from(bytes: Vec<u8>) -> Self {
Self(bytes)
}
}
impl From<Payload> for Vec<u8> {
fn from(payload: Payload) -> Self {
payload.0
}
}
impl AsRef<[u8]> for Payload {
fn as_ref(&self) -> &[u8] {
&self.0
}
}
impl std::ops::Deref for Payload {
type Target = [u8];
fn deref(&self) -> &[u8] {
&self.0
}
}
impl fmt::Debug for Payload {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Payload({} bytes)", self.0.len())
}
}
impl Serialize for Payload {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_bytes(&self.0)
}
}
impl<'de> Deserialize<'de> for Payload {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct Raw;
impl<'de> Visitor<'de> for Raw {
type Value = Vec<u8>;
fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("bytes")
}
fn visit_bytes<E: de::Error>(self, v: &[u8]) -> Result<Vec<u8>, E> {
Ok(v.to_vec())
}
fn visit_byte_buf<E: de::Error>(self, v: Vec<u8>) -> Result<Vec<u8>, E> {
Ok(v)
}
fn visit_seq<A: de::SeqAccess<'de>>(self, mut seq: A) -> Result<Vec<u8>, A::Error> {
let mut out = Vec::with_capacity(seq.size_hint().unwrap_or(0));
while let Some(byte) = seq.next_element::<u8>()? {
out.push(byte);
}
Ok(out)
}
}
deserializer.deserialize_byte_buf(Raw).map(Payload)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[cfg(feature = "msgpack")]
#[test]
fn bytes_cost_a_header_rather_than_a_second_encoding() {
use crate::{MsgPackCodec, WireCodec};
let raw = vec![200u8; 4096];
let as_payload = MsgPackCodec.encode(&Payload::from(raw.clone())).unwrap();
let as_vec = MsgPackCodec.encode(&raw).unwrap();
assert!(as_payload.len() <= raw.len() + 8, "{} for {}", as_payload.len(), raw.len());
assert!(as_vec.len() > raw.len() * 3 / 2, "a Vec<u8> should visibly cost more");
}
#[cfg(feature = "msgpack")]
#[test]
fn it_round_trips() {
use crate::{MsgPackCodec, WireCodec};
let payload = Payload::from((0..=255u8).collect::<Vec<_>>());
let back: Payload = MsgPackCodec.decode(&MsgPackCodec.encode(&payload).unwrap()).unwrap();
assert_eq!(back, payload);
}
#[cfg(feature = "json")]
#[test]
fn a_text_codec_still_round_trips_through_an_array() {
use crate::{JsonCodec, WireCodec};
let payload = Payload::from(vec![1u8, 127, 128, 255]);
let back: Payload = JsonCodec.decode(&JsonCodec.encode(&payload).unwrap()).unwrap();
assert_eq!(back, payload);
}
#[test]
fn debug_prints_the_length_not_the_bytes() {
assert_eq!(format!("{:?}", Payload::from(vec![0u8; 900])), "Payload(900 bytes)");
}
}