mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-08-07 05:25:44 +00:00
Merge pull request #1044 from Marwes/human_readable
Serialize to binary if the serde format is not human readable
This commit is contained in:
+181
-74
@@ -869,37 +869,204 @@ map_impl!(
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
macro_rules! parse_impl {
|
||||
($ty:ty) => {
|
||||
macro_rules! parse_ip_impl {
|
||||
($ty:ty; $size: expr) => {
|
||||
impl<'de> Deserialize<'de> for $ty {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
let s = try!(String::deserialize(deserializer));
|
||||
s.parse().map_err(Error::custom)
|
||||
if deserializer.is_human_readable() {
|
||||
let s = try!(String::deserialize(deserializer));
|
||||
s.parse().map_err(Error::custom)
|
||||
} else {
|
||||
<[u8; $size]>::deserialize(deserializer).map(<$ty>::from)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! variant_identifier {
|
||||
(
|
||||
$name_kind: ident ( $($variant: ident; $bytes: expr; $index: expr),* )
|
||||
$expecting_message: expr,
|
||||
$variants_name: ident
|
||||
) => {
|
||||
enum $name_kind {
|
||||
$( $variant ),*
|
||||
}
|
||||
|
||||
static $variants_name: &'static [&'static str] = &[ $( stringify!($variant) ),*];
|
||||
|
||||
impl<'de> Deserialize<'de> for $name_kind {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct KindVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for KindVisitor {
|
||||
type Value = $name_kind;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str($expecting_message)
|
||||
}
|
||||
|
||||
fn visit_u32<E>(self, value: u32) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
match value {
|
||||
$(
|
||||
$index => Ok($name_kind :: $variant),
|
||||
)*
|
||||
_ => Err(Error::invalid_value(Unexpected::Unsigned(value as u64), &self),),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
match value {
|
||||
$(
|
||||
stringify!($variant) => Ok($name_kind :: $variant),
|
||||
)*
|
||||
_ => Err(Error::unknown_variant(value, $variants_name)),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_bytes<E>(self, value: &[u8]) -> Result<Self::Value, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
match value {
|
||||
$(
|
||||
$bytes => Ok($name_kind :: $variant),
|
||||
)*
|
||||
_ => {
|
||||
match str::from_utf8(value) {
|
||||
Ok(value) => Err(Error::unknown_variant(value, $variants_name)),
|
||||
Err(_) => Err(Error::invalid_value(Unexpected::Bytes(value), &self)),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_identifier(KindVisitor)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! deserialize_enum {
|
||||
(
|
||||
$name: ident $name_kind: ident ( $($variant: ident; $bytes: expr; $index: expr),* )
|
||||
$expecting_message: expr,
|
||||
$deserializer: expr
|
||||
) => {
|
||||
variant_identifier!{
|
||||
$name_kind ( $($variant; $bytes; $index),* )
|
||||
$expecting_message,
|
||||
VARIANTS
|
||||
}
|
||||
|
||||
struct EnumVisitor;
|
||||
impl<'de> Visitor<'de> for EnumVisitor {
|
||||
type Value = $name;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str(concat!("a ", stringify!($name)))
|
||||
}
|
||||
|
||||
|
||||
fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: EnumAccess<'de>,
|
||||
{
|
||||
match try!(data.variant()) {
|
||||
$(
|
||||
($name_kind :: $variant, v) => v.newtype_variant().map($name :: $variant),
|
||||
)*
|
||||
}
|
||||
}
|
||||
}
|
||||
$deserializer.deserialize_enum(stringify!($name), VARIANTS, EnumVisitor)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl<'de> Deserialize<'de> for net::IpAddr {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
if deserializer.is_human_readable() {
|
||||
let s = try!(String::deserialize(deserializer));
|
||||
s.parse().map_err(Error::custom)
|
||||
} else {
|
||||
use lib::net::IpAddr;
|
||||
deserialize_enum!{
|
||||
IpAddr IpAddrKind (V4; b"V4"; 0, V6; b"V6"; 1)
|
||||
"`V4` or `V6`",
|
||||
deserializer
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
parse_impl!(net::IpAddr);
|
||||
parse_ip_impl!(net::Ipv4Addr; 4);
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
parse_impl!(net::Ipv4Addr);
|
||||
parse_ip_impl!(net::Ipv6Addr; 16);
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
parse_impl!(net::Ipv6Addr);
|
||||
macro_rules! parse_socket_impl {
|
||||
($ty:ty, $new: expr) => {
|
||||
impl<'de> Deserialize<'de> for $ty {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
if deserializer.is_human_readable() {
|
||||
let s = try!(String::deserialize(deserializer));
|
||||
s.parse().map_err(Error::custom)
|
||||
} else {
|
||||
<(_, u16)>::deserialize(deserializer).map(|(ip, port)| $new(ip, port))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
parse_impl!(net::SocketAddr);
|
||||
impl<'de> Deserialize<'de> for net::SocketAddr {
|
||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
if deserializer.is_human_readable() {
|
||||
let s = try!(String::deserialize(deserializer));
|
||||
s.parse().map_err(Error::custom)
|
||||
} else {
|
||||
use lib::net::SocketAddr;
|
||||
deserialize_enum!{
|
||||
SocketAddr SocketAddrKind (V4; b"V4"; 0, V6; b"V6"; 1)
|
||||
"`V4` or `V6`",
|
||||
deserializer
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
parse_impl!(net::SocketAddrV4);
|
||||
parse_socket_impl!(net::SocketAddrV4, net::SocketAddrV4::new);
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
parse_impl!(net::SocketAddrV6);
|
||||
parse_socket_impl!(net::SocketAddrV6, |ip, port| net::SocketAddrV6::new(ip, port, 0, 0));
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -984,70 +1151,10 @@ impl<'de> Deserialize<'de> for PathBuf {
|
||||
// #[derive(Deserialize)]
|
||||
// #[serde(variant_identifier)]
|
||||
#[cfg(all(feature = "std", any(unix, windows)))]
|
||||
enum OsStringKind {
|
||||
Unix,
|
||||
Windows,
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "std", any(unix, windows)))]
|
||||
static OSSTR_VARIANTS: &'static [&'static str] = &["Unix", "Windows"];
|
||||
|
||||
#[cfg(all(feature = "std", any(unix, windows)))]
|
||||
impl<'de> Deserialize<'de> for OsStringKind {
|
||||
fn deserialize<D>(deserializer: D) -> Result<OsStringKind, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct KindVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for KindVisitor {
|
||||
type Value = OsStringKind;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("`Unix` or `Windows`")
|
||||
}
|
||||
|
||||
fn visit_u32<E>(self, value: u32) -> Result<OsStringKind, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
match value {
|
||||
0 => Ok(OsStringKind::Unix),
|
||||
1 => Ok(OsStringKind::Windows),
|
||||
_ => Err(Error::invalid_value(Unexpected::Unsigned(value as u64), &self),),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, value: &str) -> Result<OsStringKind, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
match value {
|
||||
"Unix" => Ok(OsStringKind::Unix),
|
||||
"Windows" => Ok(OsStringKind::Windows),
|
||||
_ => Err(Error::unknown_variant(value, OSSTR_VARIANTS)),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_bytes<E>(self, value: &[u8]) -> Result<OsStringKind, E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
match value {
|
||||
b"Unix" => Ok(OsStringKind::Unix),
|
||||
b"Windows" => Ok(OsStringKind::Windows),
|
||||
_ => {
|
||||
match str::from_utf8(value) {
|
||||
Ok(value) => Err(Error::unknown_variant(value, OSSTR_VARIANTS)),
|
||||
Err(_) => Err(Error::invalid_value(Unexpected::Bytes(value), &self)),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_identifier(KindVisitor)
|
||||
}
|
||||
variant_identifier!{
|
||||
OsStringKind (Unix; b"Unix"; 0, Windows; b"Windows"; 1)
|
||||
"`Unix` or `Windows`",
|
||||
OSSTR_VARIANTS
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "std", any(unix, windows)))]
|
||||
|
||||
@@ -1011,6 +1011,15 @@ pub trait Deserializer<'de>: Sized {
|
||||
fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: Visitor<'de>;
|
||||
|
||||
/// Returns whether the serialized data is human readable or not.
|
||||
///
|
||||
/// Some formats are not intended to be human readable. For these formats
|
||||
/// a type being serialized may opt to serialize into a more compact form.
|
||||
///
|
||||
/// NOTE: Implementing this method and returning `false` is considered a breaking
|
||||
/// change as it may alter how any given type tries to deserialize itself.
|
||||
fn is_human_readable(&self) -> bool { true }
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
+52
-18
@@ -506,9 +506,18 @@ impl Serialize for net::IpAddr {
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
match *self {
|
||||
net::IpAddr::V4(ref a) => a.serialize(serializer),
|
||||
net::IpAddr::V6(ref a) => a.serialize(serializer),
|
||||
if serializer.is_human_readable() {
|
||||
match *self {
|
||||
net::IpAddr::V4(ref a) => a.serialize(serializer),
|
||||
net::IpAddr::V6(ref a) => a.serialize(serializer),
|
||||
}
|
||||
} else {
|
||||
match *self {
|
||||
net::IpAddr::V4(ref a) =>
|
||||
serializer.serialize_newtype_variant("IpAddr", 0, "V4", a),
|
||||
net::IpAddr::V6(ref a) =>
|
||||
serializer.serialize_newtype_variant("IpAddr", 1, "V6", a),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -519,9 +528,13 @@ impl Serialize for net::Ipv4Addr {
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
/// "101.102.103.104".len()
|
||||
const MAX_LEN: usize = 15;
|
||||
serialize_display_bounded_length!(self, MAX_LEN, serializer)
|
||||
if serializer.is_human_readable() {
|
||||
/// "101.102.103.104".len()
|
||||
const MAX_LEN: usize = 15;
|
||||
serialize_display_bounded_length!(self, MAX_LEN, serializer)
|
||||
} else {
|
||||
self.octets().serialize(serializer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -531,9 +544,13 @@ impl Serialize for net::Ipv6Addr {
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
/// "1000:1002:1003:1004:1005:1006:1007:1008".len()
|
||||
const MAX_LEN: usize = 39;
|
||||
serialize_display_bounded_length!(self, MAX_LEN, serializer)
|
||||
if serializer.is_human_readable() {
|
||||
/// "1000:1002:1003:1004:1005:1006:1007:1008".len()
|
||||
const MAX_LEN: usize = 39;
|
||||
serialize_display_bounded_length!(self, MAX_LEN, serializer)
|
||||
} else {
|
||||
self.octets().serialize(serializer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -543,9 +560,18 @@ impl Serialize for net::SocketAddr {
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
match *self {
|
||||
net::SocketAddr::V4(ref addr) => addr.serialize(serializer),
|
||||
net::SocketAddr::V6(ref addr) => addr.serialize(serializer),
|
||||
if serializer.is_human_readable() {
|
||||
match *self {
|
||||
net::SocketAddr::V4(ref addr) => addr.serialize(serializer),
|
||||
net::SocketAddr::V6(ref addr) => addr.serialize(serializer),
|
||||
}
|
||||
} else {
|
||||
match *self {
|
||||
net::SocketAddr::V4(ref addr) =>
|
||||
serializer.serialize_newtype_variant("SocketAddr", 0, "V4", addr),
|
||||
net::SocketAddr::V6(ref addr) =>
|
||||
serializer.serialize_newtype_variant("SocketAddr", 1, "V6", addr),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -556,9 +582,13 @@ impl Serialize for net::SocketAddrV4 {
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
/// "101.102.103.104:65000".len()
|
||||
const MAX_LEN: usize = 21;
|
||||
serialize_display_bounded_length!(self, MAX_LEN, serializer)
|
||||
if serializer.is_human_readable() {
|
||||
/// "101.102.103.104:65000".len()
|
||||
const MAX_LEN: usize = 21;
|
||||
serialize_display_bounded_length!(self, MAX_LEN, serializer)
|
||||
} else {
|
||||
(self.ip(), self.port()).serialize(serializer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -568,9 +598,13 @@ impl Serialize for net::SocketAddrV6 {
|
||||
where
|
||||
S: Serializer,
|
||||
{
|
||||
/// "[1000:1002:1003:1004:1005:1006:1007:1008]:65000".len()
|
||||
const MAX_LEN: usize = 47;
|
||||
serialize_display_bounded_length!(self, MAX_LEN, serializer)
|
||||
if serializer.is_human_readable() {
|
||||
/// "[1000:1002:1003:1004:1005:1006:1007:1008]:65000".len()
|
||||
const MAX_LEN: usize = 47;
|
||||
serialize_display_bounded_length!(self, MAX_LEN, serializer)
|
||||
} else {
|
||||
(self.ip(), self.port()).serialize(serializer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1363,6 +1363,15 @@ pub trait Serializer: Sized {
|
||||
fn collect_str<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
|
||||
where
|
||||
T: Display;
|
||||
|
||||
/// Returns wheter the data format is human readable or not.
|
||||
///
|
||||
/// Some formats are not intended to be human readable. For these formats
|
||||
/// a type being serialized may opt to serialize into a more compact form.
|
||||
///
|
||||
/// NOTE: Implementing this method and returning `false` is considered a breaking
|
||||
/// change as it may alter how any given type tries to serialize itself.
|
||||
fn is_human_readable(&self) -> bool { true }
|
||||
}
|
||||
|
||||
/// Returned from `Serializer::serialize_seq`.
|
||||
|
||||
Reference in New Issue
Block a user