mod error;
mod map;
mod num;
mod seq;
pub use num::{AggressiveMinimize, Exact, LosslessMinimize, NumEncoder};
use core::marker::PhantomData;
pub use error::Error;
use messagepack_core::{
Encode,
encode::{BinaryEncoder, MapFormatEncoder, NilEncoder},
io::{IoWrite, SliceWriter, WError},
};
use serde::ser;
pub fn to_core_writer_with_config<T, W, C>(
value: &T,
writer: &mut W,
config: C,
) -> Result<usize, Error<W::Error>>
where
T: ser::Serialize + ?Sized,
W: IoWrite,
C: NumEncoder<W>,
{
let mut ser = Serializer::new(writer, config);
value.serialize(&mut ser)?;
Ok(ser.current_length)
}
#[inline]
pub fn to_core_writer<T, W>(value: &T, writer: &mut W) -> Result<usize, Error<W::Error>>
where
T: ser::Serialize + ?Sized,
W: IoWrite,
{
to_core_writer_with_config(value, writer, num::LosslessMinimize)
}
#[inline]
pub fn to_slice_with_config<'a, T, C>(
value: &T,
buf: &'a mut [u8],
config: C,
) -> Result<usize, Error<WError>>
where
T: ser::Serialize + ?Sized,
C: NumEncoder<SliceWriter<'a>>,
{
let mut writer = SliceWriter::new(buf);
to_core_writer_with_config(value, &mut writer, config)
}
#[inline]
pub fn to_slice<T>(value: &T, buf: &mut [u8]) -> Result<usize, Error<WError>>
where
T: ser::Serialize + ?Sized,
{
to_slice_with_config(value, buf, num::LosslessMinimize)
}
#[cfg(feature = "alloc")]
#[inline]
pub fn to_vec_with_config<T, C>(
value: &T,
config: C,
) -> Result<alloc::vec::Vec<u8>, Error<core::convert::Infallible>>
where
T: ser::Serialize + ?Sized,
C: for<'a> NumEncoder<messagepack_core::io::VecRefWriter<'a>>,
{
let mut buf = alloc::vec::Vec::new();
let mut writer = messagepack_core::io::VecRefWriter::new(&mut buf);
to_core_writer_with_config(value, &mut writer, config)?;
Ok(buf)
}
#[cfg(feature = "alloc")]
#[inline]
pub fn to_vec<T>(value: &T) -> Result<alloc::vec::Vec<u8>, Error<core::convert::Infallible>>
where
T: ser::Serialize + ?Sized,
{
to_vec_with_config(value, num::LosslessMinimize)
}
#[cfg(feature = "std")]
#[inline]
pub fn to_writer_with_config<T, W, C>(
value: &T,
writer: &mut W,
config: C,
) -> Result<usize, Error<std::io::Error>>
where
T: ser::Serialize + ?Sized,
W: std::io::Write,
C: NumEncoder<W>,
{
to_core_writer_with_config(value, writer, config)
}
#[cfg(feature = "std")]
#[inline]
pub fn to_writer<T, W>(value: &T, writer: &mut W) -> Result<usize, Error<std::io::Error>>
where
T: ser::Serialize + ?Sized,
W: std::io::Write,
{
to_writer_with_config(value, writer, num::LosslessMinimize)
}
#[derive(Debug, PartialOrd, Ord, PartialEq, Eq)]
struct Serializer<'a, W, Num> {
writer: &'a mut W,
current_length: usize,
num_encoder: PhantomData<Num>,
}
impl<'a, W, Num> Serializer<'a, W, Num>
where
W: IoWrite,
Num: num::NumEncoder<W>,
{
pub fn new(writer: &'a mut W, _num_encoder: Num) -> Self {
Self {
writer,
current_length: 0,
num_encoder: PhantomData,
}
}
}
impl<W, Num> AsMut<Self> for Serializer<'_, W, Num> {
fn as_mut(&mut self) -> &mut Self {
self
}
}
impl<'a, 'b: 'a, W, Num> ser::Serializer for &'a mut Serializer<'b, W, Num>
where
W: IoWrite,
Num: NumEncoder<W>,
{
type Ok = ();
type Error = Error<W::Error>;
type SerializeSeq = seq::SerializeSeq<'a, 'b, W, Num>;
type SerializeTuple = seq::SerializeSeq<'a, 'b, W, Num>;
type SerializeTupleStruct = seq::SerializeSeq<'a, 'b, W, Num>;
type SerializeTupleVariant = seq::SerializeSeq<'a, 'b, W, Num>;
type SerializeMap = map::SerializeMap<'a, 'b, W, Num>;
type SerializeStruct = map::SerializeMap<'a, 'b, W, Num>;
type SerializeStructVariant = map::SerializeMap<'a, 'b, W, Num>;
fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error> {
self.current_length += v.encode(self.writer)?;
Ok(())
}
fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error> {
self.current_length += Num::encode_i8(v, self.writer)?;
Ok(())
}
fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error> {
self.current_length += Num::encode_i16(v, self.writer)?;
Ok(())
}
fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error> {
self.current_length += Num::encode_i32(v, self.writer)?;
Ok(())
}
fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> {
self.current_length += Num::encode_i64(v, self.writer)?;
Ok(())
}
fn serialize_i128(self, v: i128) -> Result<Self::Ok, Self::Error> {
self.current_length += Num::encode_i128(v, self.writer)?;
Ok(())
}
fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error> {
self.current_length += Num::encode_u8(v, self.writer)?;
Ok(())
}
fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error> {
self.current_length += Num::encode_u16(v, self.writer)?;
Ok(())
}
fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error> {
self.current_length += Num::encode_u32(v, self.writer)?;
Ok(())
}
fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error> {
self.current_length += Num::encode_u64(v, self.writer)?;
Ok(())
}
fn serialize_u128(self, v: u128) -> Result<Self::Ok, Self::Error> {
self.current_length += Num::encode_u128(v, self.writer)?;
Ok(())
}
fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error> {
self.current_length += Num::encode_f32(v, self.writer)?;
Ok(())
}
fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error> {
self.current_length += Num::encode_f64(v, self.writer)?;
Ok(())
}
fn serialize_char(self, v: char) -> Result<Self::Ok, Self::Error> {
let mut buf = [0u8; 4];
let s = v.encode_utf8(&mut buf);
self.serialize_str(s)
}
fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
self.current_length += v.encode(self.writer)?;
Ok(())
}
fn serialize_bytes(self, v: &[u8]) -> Result<Self::Ok, Self::Error> {
self.current_length += BinaryEncoder(v).encode(self.writer)?;
Ok(())
}
fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
self.current_length += NilEncoder.encode(self.writer)?;
Ok(())
}
fn serialize_some<T>(self, value: &T) -> Result<Self::Ok, Self::Error>
where
T: ?Sized + ser::Serialize,
{
value.serialize(self)
}
fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
self.serialize_none()
}
fn serialize_unit_struct(self, _name: &'static str) -> Result<Self::Ok, Self::Error> {
self.serialize_unit()
}
fn serialize_unit_variant(
self,
_name: &'static str,
_variant_index: u32,
variant: &'static str,
) -> Result<Self::Ok, Self::Error> {
self.serialize_str(variant)
}
fn serialize_newtype_struct<T>(
self,
name: &'static str,
value: &T,
) -> Result<Self::Ok, Self::Error>
where
T: ?Sized + ser::Serialize,
{
match name {
crate::extension::EXTENSION_STRUCT_NAME => {
let mut ser = crate::extension::ser::SerializeExt::new(self.writer);
value.serialize(&mut ser)?;
self.current_length += ser.length();
Ok(())
}
_ => value.serialize(self.as_mut()),
}
}
fn serialize_newtype_variant<T>(
self,
_name: &'static str,
_variant_index: u32,
variant: &'static str,
value: &T,
) -> Result<Self::Ok, Self::Error>
where
T: ?Sized + ser::Serialize,
{
self.current_length += MapFormatEncoder::new(1).encode(self.writer)?;
self.serialize_str(variant)?;
value.serialize(self.as_mut())
}
fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
let seq = seq::SerializeSeq::new(self, len)?;
Ok(seq)
}
fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> {
self.serialize_seq(Some(len))
}
fn serialize_tuple_struct(
self,
_name: &'static str,
len: usize,
) -> Result<Self::SerializeTupleStruct, Self::Error> {
self.serialize_seq(Some(len))
}
fn serialize_tuple_variant(
self,
_name: &'static str,
_variant_index: u32,
variant: &'static str,
len: usize,
) -> Result<Self::SerializeTupleVariant, Self::Error> {
self.current_length += MapFormatEncoder::new(1).encode(self.writer)?;
self.serialize_str(variant)?;
self.serialize_seq(Some(len))
}
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
map::SerializeMap::new(self, len)
}
fn serialize_struct(
self,
_name: &'static str,
len: usize,
) -> Result<Self::SerializeStruct, Self::Error> {
self.serialize_map(Some(len))
}
fn serialize_struct_variant(
self,
name: &'static str,
_variant_index: u32,
variant: &'static str,
len: usize,
) -> Result<Self::SerializeStructVariant, Self::Error> {
self.current_length += MapFormatEncoder::new(1).encode(self.writer)?;
self.serialize_str(variant)?;
self.serialize_struct(name, len)
}
#[cfg(not(any(feature = "alloc", feature = "std")))]
fn collect_str<T>(self, _value: &T) -> Result<Self::Ok, Self::Error>
where
T: ?Sized + core::fmt::Display,
{
Err(ser::Error::custom("`collect_str` is not supported"))
}
fn is_human_readable(&self) -> bool {
false
}
}
#[cfg(test)]
mod tests {
use serde::Serialize;
use super::*;
#[test]
fn encode_nil() {
let v: Option<()> = None;
let buf = &mut [0u8; 128];
let len = to_slice(&v, buf).unwrap();
assert_eq!(buf[..len], [0xc0]);
}
#[test]
fn encode_unit() {
let buf = &mut [0u8; 128];
let len = to_slice(&(), buf).unwrap();
assert_eq!(buf[..len], [0xc0]);
}
#[test]
fn encode_unit_struct() {
#[derive(Serialize)]
struct Unit;
let buf = &mut [0u8; 128];
let len = to_slice(&Unit, buf).unwrap();
assert_eq!(buf[..len], [0xc0]);
}
#[test]
fn encode_false() {
let v = false;
let buf = &mut [0u8; 128];
let len = to_slice(&v, buf).unwrap();
assert_eq!(buf[..len], [0xc2]);
}
#[test]
fn encode_true() {
let v = true;
let buf = &mut [0u8; 128];
let len = to_slice(&v, buf).unwrap();
assert_eq!(buf[..len], [0xc3]);
}
#[test]
fn encode_bytes() {
let v = serde_bytes::Bytes::new(&[5, 4, 3, 2, 1, 0]);
let buf = &mut [0u8; 128];
let len = to_slice(&v, buf).unwrap();
assert_eq!(buf[..len], [0xc4, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00]);
}
#[test]
fn encode_enum() {
#[derive(Serialize)]
enum Type {
Bool,
Int,
Float,
}
let buf = &mut [0u8; 128];
{
let len = to_slice(&Type::Bool, buf).unwrap();
assert_eq!(buf[..len], [0xa4, b'B', b'o', b'o', b'l'])
}
{
let len = to_slice(&Type::Int, buf).unwrap();
assert_eq!(buf[..len], [0xa3, b'I', b'n', b't'])
}
{
let len = to_slice(&Type::Float, buf).unwrap();
assert_eq!(buf[..len], [0xa5, b'F', b'l', b'o', b'a', b't'])
}
}
#[test]
fn encode_newtype_struct() {
#[derive(Serialize)]
struct B(#[serde(with = "serde_bytes")] [u8; 5]);
let buf = &mut [0u8; 128];
let len = to_slice(&B([5, 4, 3, 2, 1]), buf).unwrap();
assert_eq!(buf[..len], [0xc4, 0x05, 0x05, 0x04, 0x03, 0x02, 0x01])
}
#[test]
fn encode_newtype_variant() {
#[derive(Serialize)]
enum Type {
Bool(bool),
Int(u8),
Float(f32),
}
let buf = &mut [0u8; 128];
{
let len = to_slice(&Type::Bool(true), buf).unwrap();
assert_eq!(
buf[..len],
[
0x81, 0xa4, b'B', b'o', b'o', b'l', 0xc3 ]
)
}
{
let len = to_slice(&Type::Int(128), buf).unwrap();
assert_eq!(
buf[..len],
[
0x81, 0xa3, b'I', b'n', b't', 0xcc, 0x80 ]
)
}
{
let len = to_slice(&Type::Float(12.34), buf).unwrap();
assert_eq!(
buf[..len],
[
0x81, 0xa5, b'F', b'l', b'o', b'a', b't', 0xca, 0x41, 0x45, 0x70, 0xa4 ]
)
}
}
#[test]
fn encode_struct_variant() {
#[derive(Serialize)]
enum Type {
Bool { flag: bool, msg: &'static str },
}
let buf = &mut [0u8; 128];
{
let len = to_slice(
&Type::Bool {
flag: false,
msg: "hi",
},
buf,
)
.unwrap();
assert_eq!(
buf[..len],
[
0x81, 0xa4, b'B', b'o', b'o', b'l', 0x82, 0xa4, b'f', b'l', b'a', b'g', 0xc2, 0xa3, b'm', b's', b'g', 0xa2, b'h', b'i',
]
)
}
}
#[test]
fn encode_tuple_struct() {
#[derive(Serialize)]
struct V(i16, u32, i32);
let buf = &mut [0u8; 128];
let len = to_slice(&V(1, 2, 3), buf).unwrap();
assert_eq!(
buf[..len],
[
0x93, 0x01, 0x02, 0x03, ]
);
}
#[test]
fn encode_pos_fix_int() {
let v = 127_u8;
let buf = &mut [0u8; 128];
let len = to_slice(&v, buf).unwrap();
assert_eq!(buf[..len], [0x7f]);
}
#[test]
fn encode_neg_fix_int() {
let v = -32_i8;
let buf = &mut [0u8; 128];
let len = to_slice(&v, buf).unwrap();
assert_eq!(buf[..len], [0xe0]);
}
#[test]
#[cfg(not(feature = "alloc"))]
fn encode_flatten_struct() {
#[derive(Serialize)]
struct Inner {
b: u8,
c: u8,
}
#[derive(Serialize)]
struct Outer {
a: u8,
#[serde(flatten)]
extra: Inner,
}
let mut buf = [0u8; 128];
let v = Outer {
a: 1,
extra: Inner { b: 2, c: 3 },
};
let res = to_slice(&v, &mut buf);
assert!(matches!(res, Err(Error::SeqLenNone)));
}
#[test]
#[cfg(feature = "alloc")]
fn encode_flatten_struct() {
#[derive(Serialize)]
struct Inner {
b: u8,
c: u8,
}
#[derive(Serialize)]
struct Outer {
a: u8,
#[serde(flatten)]
extra: Inner,
}
let mut buf = [0u8; 128];
let v = Outer {
a: 1,
extra: Inner { b: 2, c: 3 },
};
let len = to_slice(&v, &mut buf).unwrap();
assert_eq!(
buf[..len],
[
0x83, 0xa1, b'a', 0x01, 0xa1, b'b', 0x02, 0xa1, b'c', 0x03, ]
);
}
#[cfg(feature = "std")]
#[test]
fn encode_with_writer() {
#[derive(Serialize)]
struct V(i16, u32, i32);
let mut buf = vec![];
let len = to_writer(&V(1, 2, 3), &mut buf).unwrap();
assert_eq!(
buf[..len],
[
0x93, 0x01, 0x02, 0x03 ]
);
}
}