mirror of
https://github.com/pezkuwichain/serde.git
synced 2026-04-23 10:38:02 +00:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e9270e59f0 | |||
| 72060b779a | |||
| 1bb23ad9d1 | |||
| 9be4c9654a | |||
| 4114e90bac | |||
| 8bb07b0743 | |||
| ba8c1d63c8 | |||
| 857a805993 | |||
| 5a8dcac2ed | |||
| 697b082e90 | |||
| d91075c8d5 | |||
| 4118cec731 | |||
| c261015325 | |||
| 6b5e5a83d0 | |||
| bc6b2b1dee | |||
| beb21cb640 | |||
| 7cfebbcd72 | |||
| b60c03ec3f | |||
| 3257851192 | |||
| 9a84622c56 | |||
| de8ac1c0be |
+2
-2
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "serde"
|
||||
version = "1.0.123" # remember to update html_root_url and serde_derive dependency
|
||||
version = "1.0.125" # remember to update html_root_url and serde_derive dependency
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
description = "A generic serialization/deserialization framework"
|
||||
@@ -14,7 +14,7 @@ include = ["build.rs", "src/**/*.rs", "crates-io.md", "README.md", "LICENSE-APAC
|
||||
build = "build.rs"
|
||||
|
||||
[dependencies]
|
||||
serde_derive = { version = "=1.0.123", optional = true, path = "../serde_derive" }
|
||||
serde_derive = { version = "=1.0.125", optional = true, path = "../serde_derive" }
|
||||
|
||||
[dev-dependencies]
|
||||
serde_derive = { version = "1.0", path = "../serde_derive" }
|
||||
|
||||
+3
-1
@@ -76,12 +76,14 @@ fn main() {
|
||||
println!("cargo:rustc-cfg=serde_derive");
|
||||
}
|
||||
|
||||
// TryFrom, Atomic types, and non-zero signed integers stabilized in Rust 1.34:
|
||||
// TryFrom, Atomic types, non-zero signed integers, and SystemTime::checked_add
|
||||
// stabilized in Rust 1.34:
|
||||
// https://blog.rust-lang.org/2019/04/11/Rust-1.34.0.html#tryfrom-and-tryinto
|
||||
// https://blog.rust-lang.org/2019/04/11/Rust-1.34.0.html#library-stabilizations
|
||||
if minor >= 34 {
|
||||
println!("cargo:rustc-cfg=core_try_from");
|
||||
println!("cargo:rustc-cfg=num_nonzero_signed");
|
||||
println!("cargo:rustc-cfg=systemtime_checked_add");
|
||||
|
||||
// Whitelist of archs that support std::sync::atomic module. Ideally we
|
||||
// would use #[cfg(target_has_atomic = "...")] but it is not stable yet.
|
||||
|
||||
+20
-1
@@ -2046,6 +2046,17 @@ impl<'de> Deserialize<'de> for SystemTime {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_overflow<E>(secs: u64, nanos: u32) -> Result<(), E>
|
||||
where
|
||||
E: Error,
|
||||
{
|
||||
static NANOS_PER_SEC: u32 = 1_000_000_000;
|
||||
match secs.checked_add((nanos / NANOS_PER_SEC) as u64) {
|
||||
Some(_) => Ok(()),
|
||||
None => Err(E::custom("overflow deserializing SystemTime epoch offset")),
|
||||
}
|
||||
}
|
||||
|
||||
struct DurationVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for DurationVisitor {
|
||||
@@ -2071,6 +2082,7 @@ impl<'de> Deserialize<'de> for SystemTime {
|
||||
return Err(Error::invalid_length(1, &self));
|
||||
}
|
||||
};
|
||||
try!(check_overflow(secs, nanos));
|
||||
Ok(Duration::new(secs, nanos))
|
||||
}
|
||||
|
||||
@@ -2108,13 +2120,20 @@ impl<'de> Deserialize<'de> for SystemTime {
|
||||
Some(nanos) => nanos,
|
||||
None => return Err(<A::Error as Error>::missing_field("nanos_since_epoch")),
|
||||
};
|
||||
try!(check_overflow(secs, nanos));
|
||||
Ok(Duration::new(secs, nanos))
|
||||
}
|
||||
}
|
||||
|
||||
const FIELDS: &'static [&'static str] = &["secs_since_epoch", "nanos_since_epoch"];
|
||||
let duration = try!(deserializer.deserialize_struct("SystemTime", FIELDS, DurationVisitor));
|
||||
Ok(UNIX_EPOCH + duration)
|
||||
#[cfg(systemtime_checked_add)]
|
||||
let ret = UNIX_EPOCH
|
||||
.checked_add(duration)
|
||||
.ok_or_else(|| D::Error::custom("overflow deserializing SystemTime"));
|
||||
#[cfg(not(systemtime_checked_add))]
|
||||
let ret = Ok(UNIX_EPOCH + duration);
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -44,7 +44,7 @@
|
||||
//! - [BSON], the data storage and network transfer format used by MongoDB.
|
||||
//! - [Avro], a binary format used within Apache Hadoop, with support for schema
|
||||
//! definition.
|
||||
//! - [JSON5], A superset of JSON including some productions from ES5.
|
||||
//! - [JSON5], a superset of JSON including some productions from ES5.
|
||||
//! - [Postcard], a no\_std and embedded-systems friendly compact binary format.
|
||||
//! - [URL] query strings, in the x-www-form-urlencoded format.
|
||||
//! - [Envy], a way to deserialize environment variables into Rust structs.
|
||||
@@ -84,7 +84,7 @@
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Serde types in rustdoc of other crates get linked to here.
|
||||
#![doc(html_root_url = "https://docs.rs/serde/1.0.123")]
|
||||
#![doc(html_root_url = "https://docs.rs/serde/1.0.125")]
|
||||
// Support using Serde without the standard library!
|
||||
#![cfg_attr(not(feature = "std"), no_std)]
|
||||
// Unstable functionality only if the user asks for it. For tracking and
|
||||
@@ -120,6 +120,7 @@
|
||||
zero_prefixed_literal,
|
||||
// correctly used
|
||||
enum_glob_use,
|
||||
let_underscore_drop,
|
||||
map_err_ignore,
|
||||
result_unit_err,
|
||||
wildcard_imports,
|
||||
@@ -138,7 +139,6 @@
|
||||
)
|
||||
)]
|
||||
// Rustc lints.
|
||||
#![forbid(unsafe_code)]
|
||||
#![deny(missing_docs, unused_imports)]
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
+23
-14
@@ -1287,8 +1287,9 @@ mod content {
|
||||
// }
|
||||
//
|
||||
// We want {"topic":"Info"} to deserialize even though
|
||||
// ordinarily unit structs do not deserialize from empty map.
|
||||
// ordinarily unit structs do not deserialize from empty map/seq.
|
||||
Content::Map(ref v) if v.is_empty() => visitor.visit_unit(),
|
||||
Content::Seq(ref v) if v.is_empty() => visitor.visit_unit(),
|
||||
_ => self.deserialize_any(visitor),
|
||||
}
|
||||
}
|
||||
@@ -1741,6 +1742,25 @@ mod content {
|
||||
_ => Err(self.invalid_type(&visitor)),
|
||||
}
|
||||
}
|
||||
|
||||
fn deserialize_float<V>(self, visitor: V) -> Result<V::Value, E>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
match *self.content {
|
||||
Content::F32(v) => visitor.visit_f32(v),
|
||||
Content::F64(v) => visitor.visit_f64(v),
|
||||
Content::U8(v) => visitor.visit_u8(v),
|
||||
Content::U16(v) => visitor.visit_u16(v),
|
||||
Content::U32(v) => visitor.visit_u32(v),
|
||||
Content::U64(v) => visitor.visit_u64(v),
|
||||
Content::I8(v) => visitor.visit_i8(v),
|
||||
Content::I16(v) => visitor.visit_i16(v),
|
||||
Content::I32(v) => visitor.visit_i32(v),
|
||||
Content::I64(v) => visitor.visit_i64(v),
|
||||
_ => Err(self.invalid_type(&visitor)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_content_seq_ref<'a, 'de, V, E>(
|
||||
@@ -1888,25 +1908,14 @@ mod content {
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
match *self.content {
|
||||
Content::F32(v) => visitor.visit_f32(v),
|
||||
Content::F64(v) => visitor.visit_f64(v),
|
||||
Content::U64(v) => visitor.visit_u64(v),
|
||||
Content::I64(v) => visitor.visit_i64(v),
|
||||
_ => Err(self.invalid_type(&visitor)),
|
||||
}
|
||||
self.deserialize_float(visitor)
|
||||
}
|
||||
|
||||
fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
where
|
||||
V: Visitor<'de>,
|
||||
{
|
||||
match *self.content {
|
||||
Content::F64(v) => visitor.visit_f64(v),
|
||||
Content::U64(v) => visitor.visit_u64(v),
|
||||
Content::I64(v) => visitor.visit_i64(v),
|
||||
_ => Err(self.invalid_type(&visitor)),
|
||||
}
|
||||
self.deserialize_float(visitor)
|
||||
}
|
||||
|
||||
fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||
|
||||
+54
-1
@@ -674,6 +674,52 @@ impl Serialize for net::IpAddr {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
const DEC_DIGITS_LUT: &'static [u8] = b"\
|
||||
0001020304050607080910111213141516171819\
|
||||
2021222324252627282930313233343536373839\
|
||||
4041424344454647484950515253545556575859\
|
||||
6061626364656667686970717273747576777879\
|
||||
8081828384858687888990919293949596979899";
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[inline]
|
||||
fn format_u8(mut n: u8, out: &mut [u8]) -> usize {
|
||||
if n >= 100 {
|
||||
let d1 = ((n % 100) << 1) as usize;
|
||||
n /= 100;
|
||||
out[0] = b'0' + n;
|
||||
out[1] = DEC_DIGITS_LUT[d1];
|
||||
out[2] = DEC_DIGITS_LUT[d1 + 1];
|
||||
3
|
||||
} else if n >= 10 {
|
||||
let d1 = (n << 1) as usize;
|
||||
out[0] = DEC_DIGITS_LUT[d1];
|
||||
out[1] = DEC_DIGITS_LUT[d1 + 1];
|
||||
2
|
||||
} else {
|
||||
out[0] = b'0' + n;
|
||||
1
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
#[test]
|
||||
fn test_format_u8() {
|
||||
let mut i = 0u8;
|
||||
|
||||
loop {
|
||||
let mut buf = [0u8; 3];
|
||||
let written = format_u8(i, &mut buf);
|
||||
assert_eq!(i.to_string().as_bytes(), &buf[..written]);
|
||||
|
||||
match i.checked_add(1) {
|
||||
Some(next) => i = next,
|
||||
None => break,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl Serialize for net::Ipv4Addr {
|
||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
@@ -683,7 +729,14 @@ impl Serialize for net::Ipv4Addr {
|
||||
if serializer.is_human_readable() {
|
||||
const MAX_LEN: usize = 15;
|
||||
debug_assert_eq!(MAX_LEN, "101.102.103.104".len());
|
||||
serialize_display_bounded_length!(self, MAX_LEN, serializer)
|
||||
let mut buf = [b'.'; MAX_LEN];
|
||||
let mut written = format_u8(self.octets()[0], &mut buf);
|
||||
for oct in &self.octets()[1..] {
|
||||
// Skip over delimiters that we initialized buf with
|
||||
written += format_u8(*oct, &mut buf[written + 1..]) + 1;
|
||||
}
|
||||
// We've only written ASCII bytes to the buffer, so it is valid UTF-8
|
||||
serializer.serialize_str(unsafe { str::from_utf8_unchecked(&buf[..written]) })
|
||||
} else {
|
||||
self.octets().serialize(serializer)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "serde_derive"
|
||||
version = "1.0.123" # remember to update html_root_url
|
||||
version = "1.0.125" # remember to update html_root_url
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
description = "Macros 1.1 implementation of #[derive(Serialize, Deserialize)]"
|
||||
|
||||
@@ -13,13 +13,15 @@
|
||||
//!
|
||||
//! [https://serde.rs/derive.html]: https://serde.rs/derive.html
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.123")]
|
||||
#![doc(html_root_url = "https://docs.rs/serde_derive/1.0.125")]
|
||||
#![allow(unknown_lints, bare_trait_objects)]
|
||||
#![deny(clippy::all, clippy::pedantic)]
|
||||
// Ignored clippy lints
|
||||
#![allow(
|
||||
clippy::cognitive_complexity,
|
||||
clippy::enum_variant_names,
|
||||
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/6797
|
||||
clippy::manual_map,
|
||||
clippy::match_like_matches_macro,
|
||||
clippy::needless_pass_by_value,
|
||||
clippy::too_many_arguments,
|
||||
@@ -38,6 +40,7 @@
|
||||
clippy::filter_map,
|
||||
clippy::indexing_slicing,
|
||||
clippy::items_after_statements,
|
||||
clippy::let_underscore_drop,
|
||||
clippy::map_err_ignore,
|
||||
clippy::match_same_arms,
|
||||
clippy::module_name_repetitions,
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
// Ignored clippy lints
|
||||
#![allow(
|
||||
clippy::cognitive_complexity,
|
||||
// clippy bug: https://github.com/rust-lang/rust-clippy/issues/6797
|
||||
clippy::manual_map,
|
||||
clippy::missing_panics_doc,
|
||||
clippy::redundant_field_names,
|
||||
clippy::result_unit_err,
|
||||
clippy::should_implement_trait,
|
||||
@@ -17,6 +20,7 @@
|
||||
clippy::doc_markdown,
|
||||
clippy::enum_glob_use,
|
||||
clippy::items_after_statements,
|
||||
clippy::let_underscore_drop,
|
||||
clippy::match_same_arms,
|
||||
clippy::missing_errors_doc,
|
||||
clippy::module_name_repetitions,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "serde_test"
|
||||
version = "1.0.123" # remember to update html_root_url
|
||||
version = "1.0.125" # remember to update html_root_url
|
||||
authors = ["Erick Tryzelaar <erick.tryzelaar@gmail.com>", "David Tolnay <dtolnay@gmail.com>"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
description = "Token De/Serializer for testing De/Serialize implementations"
|
||||
|
||||
@@ -144,7 +144,7 @@
|
||||
//! # }
|
||||
//! ```
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.123")]
|
||||
#![doc(html_root_url = "https://docs.rs/serde_test/1.0.125")]
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
|
||||
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
|
||||
// Ignored clippy lints
|
||||
@@ -155,6 +155,7 @@
|
||||
allow(
|
||||
empty_line_after_outer_attr,
|
||||
missing_docs_in_private_items,
|
||||
missing_panics_doc,
|
||||
module_name_repetitions,
|
||||
must_use_candidate,
|
||||
redundant_field_names,
|
||||
|
||||
@@ -15,7 +15,7 @@ use std::sync::atomic::{
|
||||
AtomicUsize, Ordering,
|
||||
};
|
||||
use std::sync::{Arc, Weak as ArcWeak};
|
||||
use std::time::{Duration, UNIX_EPOCH};
|
||||
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use std::sync::atomic::{AtomicI64, AtomicU64};
|
||||
@@ -192,8 +192,12 @@ macro_rules! declare_tests {
|
||||
}
|
||||
|
||||
macro_rules! declare_error_tests {
|
||||
($($name:ident<$target:ty> { $tokens:expr, $expected:expr, })+) => {
|
||||
($(
|
||||
$(#[$cfg:meta])*
|
||||
$name:ident<$target:ty> { $tokens:expr, $expected:expr, }
|
||||
)+) => {
|
||||
$(
|
||||
$(#[$cfg])*
|
||||
#[test]
|
||||
fn $name() {
|
||||
assert_de_tokens_error::<$target>($tokens, $expected);
|
||||
@@ -1614,4 +1618,35 @@ declare_error_tests! {
|
||||
],
|
||||
"overflow deserializing Duration",
|
||||
}
|
||||
test_systemtime_overflow_seq<SystemTime> {
|
||||
&[
|
||||
Token::Seq { len: Some(2) },
|
||||
Token::U64(u64::max_value()),
|
||||
Token::U32(1_000_000_000),
|
||||
Token::SeqEnd,
|
||||
],
|
||||
"overflow deserializing SystemTime epoch offset",
|
||||
}
|
||||
test_systemtime_overflow_struct<SystemTime> {
|
||||
&[
|
||||
Token::Struct { name: "SystemTime", len: 2 },
|
||||
Token::Str("secs_since_epoch"),
|
||||
Token::U64(u64::max_value()),
|
||||
|
||||
Token::Str("nanos_since_epoch"),
|
||||
Token::U32(1_000_000_000),
|
||||
Token::StructEnd,
|
||||
],
|
||||
"overflow deserializing SystemTime epoch offset",
|
||||
}
|
||||
#[cfg(systemtime_checked_add)]
|
||||
test_systemtime_overflow<SystemTime> {
|
||||
&[
|
||||
Token::Seq { len: Some(2) },
|
||||
Token::U64(u64::max_value()),
|
||||
Token::U32(0),
|
||||
Token::SeqEnd,
|
||||
],
|
||||
"overflow deserializing SystemTime",
|
||||
}
|
||||
}
|
||||
|
||||
@@ -994,6 +994,28 @@ fn test_internally_tagged_struct_variant_containing_unit_variant() {
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_de_tokens(
|
||||
&Message::Log { level: Level::Info },
|
||||
&[
|
||||
Token::Map { len: Some(2) },
|
||||
Token::Str("action"),
|
||||
Token::Str("Log"),
|
||||
Token::Str("level"),
|
||||
Token::BorrowedStr("Info"),
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_de_tokens(
|
||||
&Message::Log { level: Level::Info },
|
||||
&[
|
||||
Token::Seq { len: Some(2) },
|
||||
Token::Str("Log"),
|
||||
Token::BorrowedStr("Info"),
|
||||
Token::SeqEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1877,6 +1899,28 @@ fn test_internally_tagged_newtype_variant_containing_unit_struct() {
|
||||
Token::MapEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_de_tokens(
|
||||
&Message::Info(Info),
|
||||
&[
|
||||
Token::Struct {
|
||||
name: "Message",
|
||||
len: 1,
|
||||
},
|
||||
Token::Str("topic"),
|
||||
Token::Str("Info"),
|
||||
Token::StructEnd,
|
||||
],
|
||||
);
|
||||
|
||||
assert_de_tokens(
|
||||
&Message::Info(Info),
|
||||
&[
|
||||
Token::Seq { len: Some(1) },
|
||||
Token::Str("Info"),
|
||||
Token::SeqEnd,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
#[deny(safe_packed_borrows)]
|
||||
|
||||
Reference in New Issue
Block a user