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
//! The fcode crate delivers a simple binary serialization strategy for the
//! serde framework. Wire format resembles protobufs, but doesn't have field tags. Note that evolution depends
//! on lexical field ordering; you can *never* change the lexical order of fields, and fields must always
//! be added to the end of a struct/enum.
//!
//! The following evolutions are explicitly supported:
//!
//! * Add a field to the back of a struct. Deserialization of a longer struct is always possible, but
//!   in order to allow new code to deserialize an old object, added fields must be marked with
//!   `#[serde(default)]`.
//! * Extend a tuple struct, in the same way, *except* extending from a 1-field tuple (newtype) to something longer.
//! * Extend a struct enum variant or tuple enum variant in the same way.
//! * Change an anonymous tuple into a named tuple with the same field types.
//! * Change a named or anonymous tuple into a struct, as long as fields with the same type appear in the same order.
//! * Change a tuple enum variant into a struct variant, as long as fields with the same type appear in the same order.
//! * Change any value into a newtype struct (`i32` -> `Foo(i32)`).
//! * Change a struct variant or tuple variant into a newtype variant containing a struct/tuple with the same layout
//!   `Foo { x: i32, y: i32 }` -> `Foo(Foo)` (where `struct Foo { x: i32, y: i32 }`)
//! * Change the size of an integer (e.g. `i16` -> `i32`). Overly large values will cause deserialization error.
//! * Change the size of a float (`f32` -> `f64`) -- conversion back from `f64` to `f32` may silently overflow to infinity.
//! * Change a bool to an integer -- false maps to 0, true maps to anything not 0.
//! * Change a unit to bool (maps to false) or an integer (maps to 0).
//! * Change string to bytes. Non-UTF8 bytes will cause error when deserializing to string.
//! * Extend an enum with a new variant. To make this backwards compatible, the "old" code should have a unit variant
//!   marked with
//!   `#[serde(other)]`. It is therefore a good idea to always add such other / fallback variant for enums that
//!   may be extended in the future. The alternative is to always upgrade both sides before actually using the new variant.
//!
//! Explicitly not supported:
//!
//! * Change a newtype struct (`Foo(x)`) to a tuple (`Foo(x,y)`).
//! * Change the signedness of an integer (`i32` -> `u32`).
//! * Conditional skipping of fields (will panic), or skipping fields in serialization only (will cause deserialization badness).
//! * Serialization of sequences with unknown upfront length (e.g. iterators; will panic).
//!
//! Fields can be deprecated by changing them to unit in the receiver first, and then in the sender once all receivers
//! have been upgraded. Unit deserialisation blindly skips a field without actually checking the wire type. A unit field
//! takes a single byte on the wire. Vice versa, a field can be "undeprecated" (re-use of deprecated slot) by changing the
//! sender before the receiver.

mod de;
mod error;
mod ser;
mod wire;

#[cfg(test)]
mod tests;

pub use de::Deserializer;
pub use error::{Error, Result};
pub use ser::Serializer;

use serde::{Deserialize, Serialize};

/// Serialize a value into a new byte vector.
#[inline]
pub fn to_bytes<T>(value: &T) -> Result<Vec<u8>>
where
	T: Serialize + ?Sized,
{
	let mut v = Vec::new();
	to_writer(&mut v, value)?;
	Ok(v)
}

/// Serialize a value to a [`io::Write`](std::io::Write) implementation.
///
/// Use this to extend a `Vec<u8>`, or feed into some compressor.
#[inline]
pub fn to_writer<T, W>(w: &mut W, value: &T) -> Result<()>
where
	T: Serialize + ?Sized,
	W: std::io::Write,
{
	value.serialize(Serializer::new(w))
}

/// Deserialize a value from a byte slice.
pub fn from_bytes<'de, T>(data: &'de [u8]) -> Result<T>
where
	T: Deserialize<'de>,
{
	let mut de = Deserializer::from_bytes(data);
	let value = T::deserialize(&mut de)?;
	if de.remaining_len() > 0 {
		return Err(Error::DataBeyondEnd);
	}
	Ok(value)
}

/// Deserialize a value from a byte slice that may have more data.
///
/// Returns a pair of (value, size_read).
pub fn from_bytes_more_data<'de, T>(data: &'de [u8]) -> Result<(T, usize)>
where
	T: Deserialize<'de>,
{
	let mut de = Deserializer::from_bytes(data);
	let value = T::deserialize(&mut de)?;
	let consumed = data.len() - de.remaining_len();
	Ok((value, consumed))
}