Skip to content
This repository was archived by the owner on Mar 25, 2024. It is now read-only.
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: dtolnay/serde-yaml
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 0.9.30
Choose a base ref
...
head repository: dtolnay/serde-yaml
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 0.9.31
Choose a head ref
  • 4 commits
  • 4 files changed
  • 1 contributor

Commits on Jan 6, 2024

  1. Work around dead_code warning in tests

        warning: field `0` is never read
          --> tests/test_error.rs:58:11
           |
        58 |         C(C),
           |         - ^
           |         |
           |         field in this variant
           |
           = note: `#[warn(dead_code)]` on by default
        help: consider changing the field to be of unit type to suppress this warning while preserving the field numbering, or remove the field
           |
        58 |         C(()),
           |           ~~
    
        warning: field `0` is never read
           --> tests/test_error.rs:165:11
            |
        165 |         V(usize),
            |         - ^^^^^
            |         |
            |         field in this variant
            |
        help: consider changing the field to be of unit type to suppress this warning while preserving the field numbering, or remove the field
            |
        165 |         V(()),
            |           ~~
    
        warning: field `0` is never read
           --> tests/test_error.rs:217:15
            |
        217 |         Inner(Inner),
            |         ----- ^^^^^
            |         |
            |         field in this variant
            |
        help: consider changing the field to be of unit type to suppress this warning while preserving the field numbering, or remove the field
            |
        217 |         Inner(()),
            |               ~~
    
        warning: field `0` is never read
           --> tests/test_error.rs:221:17
            |
        221 |         Variant(Vec<usize>),
            |         ------- ^^^^^^^^^^
            |         |
            |         field in this variant
            |
        help: consider changing the field to be of unit type to suppress this warning while preserving the field numbering, or remove the field
            |
        221 |         Variant(()),
            |                 ~~
    
        warning: field `0` is never read
           --> tests/test_error.rs:250:11
            |
        250 |         V(usize),
            |         - ^^^^^
            |         |
            |         field in this variant
            |
        help: consider changing the field to be of unit type to suppress this warning while preserving the field numbering, or remove the field
            |
        250 |         V(()),
            |           ~~
    
        warning: fields `0` and `1` are never read
           --> tests/test_error.rs:367:14
            |
        367 |     struct S(usize, Option<Box<S>>);
            |            - ^^^^^  ^^^^^^^^^^^^^^
            |            |
            |            fields in this struct
            |
            = note: `S` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis
        help: consider changing the fields to be of unit type to suppress this warning while preserving the field numbering, or remove the fields
            |
        367 |     struct S((), ());
            |              ~~  ~~
    
        warning: field `0` is never read
           --> tests/test_error.rs:378:14
            |
        378 |     struct S(Option<Box<S>>);
            |            - ^^^^^^^^^^^^^^
            |            |
            |            field in this struct
            |
            = note: `S` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis
        help: consider changing the field to be of unit type to suppress this warning while preserving the field numbering, or remove the field
            |
        378 |     struct S(());
            |              ~~
    
        warning: fields `0` and `1` are never read
           --> tests/test_error.rs:403:14
            |
        403 |     struct S(usize, Option<Box<S>>);
            |            - ^^^^^  ^^^^^^^^^^^^^^
            |            |
            |            fields in this struct
            |
            = note: `S` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis
        help: consider changing the fields to be of unit type to suppress this warning while preserving the field numbering, or remove the fields
            |
        403 |     struct S((), ());
            |              ~~  ~~
    dtolnay committed Jan 6, 2024

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    8b26413 View commit details

Commits on Jan 29, 2024

  1. Copy the full SHA
    f8a99a4 View commit details
  2. Merge pull request #408 from dtolnay/remove

    Add swap_remove and shift_remove methods on Mapping
    dtolnay authored Jan 29, 2024
    Copy the full SHA
    d8d1a83 View commit details
  3. Release 0.9.31

    dtolnay committed Jan 29, 2024
    Copy the full SHA
    2a77483 View commit details
Showing with 133 additions and 62 deletions.
  1. +4 −4 Cargo.toml
  2. +1 −1 src/lib.rs
  3. +100 −20 src/mapping.rs
  4. +28 −37 tests/test_error.rs
8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "serde_yaml"
version = "0.9.30"
version = "0.9.31"
authors = ["David Tolnay <dtolnay@gmail.com>"]
categories = ["encoding", "parser-implementations"]
description = "YAML data format for Serde"
@@ -12,16 +12,16 @@ repository = "https://github.com/dtolnay/serde-yaml"
rust-version = "1.64"

[dependencies]
indexmap = "2"
indexmap = "2.2.1"
itoa = "1.0"
ryu = "1.0"
serde = "1.0.194"
serde = "1.0.195"
unsafe-libyaml = "0.2.10"

[dev-dependencies]
anyhow = "1.0.79"
indoc = "2.0"
serde_derive = "1.0.194"
serde_derive = "1.0.195"

[lib]
doc-scrape-examples = false
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -115,7 +115,7 @@
//! }
//! ```
#![doc(html_root_url = "https://docs.rs/serde_yaml/0.9.30")]
#![doc(html_root_url = "https://docs.rs/serde_yaml/0.9.31")]
#![deny(missing_docs, unsafe_op_in_unsafe_fn)]
// Suppressed clippy_pedantic lints
#![allow(
120 changes: 100 additions & 20 deletions src/mapping.rs
Original file line number Diff line number Diff line change
@@ -87,15 +87,65 @@ impl Mapping {
}

/// Removes and returns the value corresponding to the key from the map.
///
/// This is equivalent to [`.swap_remove(index)`][Self::swap_remove],
/// replacing this entry’s position with the last element. If you need to
/// preserve the relative order of the keys in the map, use
/// [`.shift_remove(key)`][Self::shift_remove] instead.
#[inline]
pub fn remove<I: Index>(&mut self, index: I) -> Option<Value> {
index.remove_from(self)
self.swap_remove(index)
}

/// Remove and return the key-value pair.
///
/// This is equivalent to [`.swap_remove_entry(index)`][Self::swap_remove_entry],
/// replacing this entry’s position with the last element. If you need to
/// preserve the relative order of the keys in the map, use
/// [`.shift_remove_entry(key)`][Self::shift_remove_entry] instead.
#[inline]
pub fn remove_entry<I: Index>(&mut self, index: I) -> Option<(Value, Value)> {
index.remove_entry_from(self)
self.swap_remove_entry(index)
}

/// Removes and returns the value corresponding to the key from the map.
///
/// Like [`Vec::swap_remove`], the entry is removed by swapping it with the
/// last element of the map and popping it off. This perturbs the position
/// of what used to be the last element!
#[inline]
pub fn swap_remove<I: Index>(&mut self, index: I) -> Option<Value> {
index.swap_remove_from(self)
}

/// Remove and return the key-value pair.
///
/// Like [`Vec::swap_remove`], the entry is removed by swapping it with the
/// last element of the map and popping it off. This perturbs the position
/// of what used to be the last element!
#[inline]
pub fn swap_remove_entry<I: Index>(&mut self, index: I) -> Option<(Value, Value)> {
index.swap_remove_entry_from(self)
}

/// Removes and returns the value corresponding to the key from the map.
///
/// Like [`Vec::remove`], the entry is removed by shifting all of the
/// elements that follow it, preserving their relative order. This perturbs
/// the index of all of those elements!
#[inline]
pub fn shift_remove<I: Index>(&mut self, index: I) -> Option<Value> {
index.shift_remove_from(self)
}

/// Remove and return the key-value pair.
///
/// Like [`Vec::remove`], the entry is removed by shifting all of the
/// elements that follow it, preserving their relative order. This perturbs
/// the index of all of those elements!
#[inline]
pub fn shift_remove_entry<I: Index>(&mut self, index: I) -> Option<(Value, Value)> {
index.shift_remove_entry_from(self)
}

/// Scan through each key-value pair in the map and keep those where the
@@ -203,10 +253,16 @@ pub trait Index: private::Sealed {
fn index_into_mut<'a>(&self, v: &'a mut Mapping) -> Option<&'a mut Value>;

#[doc(hidden)]
fn remove_from(&self, v: &mut Mapping) -> Option<Value>;
fn swap_remove_from(&self, v: &mut Mapping) -> Option<Value>;

#[doc(hidden)]
fn swap_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)>;

#[doc(hidden)]
fn shift_remove_from(&self, v: &mut Mapping) -> Option<Value>;

#[doc(hidden)]
fn remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)>;
fn shift_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)>;
}

struct HashLikeValue<'a>(&'a str);
@@ -239,11 +295,17 @@ impl Index for Value {
fn index_into_mut<'a>(&self, v: &'a mut Mapping) -> Option<&'a mut Value> {
v.map.get_mut(self)
}
fn remove_from(&self, v: &mut Mapping) -> Option<Value> {
v.map.remove(self)
fn swap_remove_from(&self, v: &mut Mapping) -> Option<Value> {
v.map.swap_remove(self)
}
fn remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> {
v.map.remove_entry(self)
fn swap_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> {
v.map.swap_remove_entry(self)
}
fn shift_remove_from(&self, v: &mut Mapping) -> Option<Value> {
v.map.shift_remove(self)
}
fn shift_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> {
v.map.shift_remove_entry(self)
}
}

@@ -257,11 +319,17 @@ impl Index for str {
fn index_into_mut<'a>(&self, v: &'a mut Mapping) -> Option<&'a mut Value> {
v.map.get_mut(&HashLikeValue(self))
}
fn remove_from(&self, v: &mut Mapping) -> Option<Value> {
v.map.remove(&HashLikeValue(self))
fn swap_remove_from(&self, v: &mut Mapping) -> Option<Value> {
v.map.swap_remove(&HashLikeValue(self))
}
fn swap_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> {
v.map.swap_remove_entry(&HashLikeValue(self))
}
fn shift_remove_from(&self, v: &mut Mapping) -> Option<Value> {
v.map.shift_remove(&HashLikeValue(self))
}
fn remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> {
v.map.remove_entry(&HashLikeValue(self))
fn shift_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> {
v.map.shift_remove_entry(&HashLikeValue(self))
}
}

@@ -275,11 +343,17 @@ impl Index for String {
fn index_into_mut<'a>(&self, v: &'a mut Mapping) -> Option<&'a mut Value> {
self.as_str().index_into_mut(v)
}
fn remove_from(&self, v: &mut Mapping) -> Option<Value> {
self.as_str().remove_from(v)
fn swap_remove_from(&self, v: &mut Mapping) -> Option<Value> {
self.as_str().swap_remove_from(v)
}
fn remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> {
self.as_str().remove_entry_from(v)
fn swap_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> {
self.as_str().swap_remove_entry_from(v)
}
fn shift_remove_from(&self, v: &mut Mapping) -> Option<Value> {
self.as_str().shift_remove_from(v)
}
fn shift_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> {
self.as_str().shift_remove_entry_from(v)
}
}

@@ -296,11 +370,17 @@ where
fn index_into_mut<'a>(&self, v: &'a mut Mapping) -> Option<&'a mut Value> {
(**self).index_into_mut(v)
}
fn remove_from(&self, v: &mut Mapping) -> Option<Value> {
(**self).remove_from(v)
fn swap_remove_from(&self, v: &mut Mapping) -> Option<Value> {
(**self).swap_remove_from(v)
}
fn swap_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> {
(**self).swap_remove_entry_from(v)
}
fn shift_remove_from(&self, v: &mut Mapping) -> Option<Value> {
(**self).shift_remove_from(v)
}
fn remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> {
(**self).remove_entry_from(v)
fn shift_remove_entry_from(&self, v: &mut Mapping) -> Option<(Value, Value)> {
(**self).shift_remove_entry_from(v)
}
}

65 changes: 28 additions & 37 deletions tests/test_error.rs
Original file line number Diff line number Diff line change
@@ -49,18 +49,16 @@ fn test_incorrect_type() {
#[test]
fn test_incorrect_nested_type() {
#[derive(Deserialize, Debug)]
struct A {
#[allow(dead_code)]
b: Vec<B>,
pub struct A {
pub b: Vec<B>,
}
#[derive(Deserialize, Debug)]
enum B {
pub enum B {
C(C),
}
#[derive(Deserialize, Debug)]
struct C {
#[allow(dead_code)]
d: bool,
pub struct C {
pub d: bool,
}
let yaml = indoc! {"
b:
@@ -80,11 +78,9 @@ fn test_empty() {
#[test]
fn test_missing_field() {
#[derive(Deserialize, Debug)]
struct Basic {
#[allow(dead_code)]
v: bool,
#[allow(dead_code)]
w: bool,
pub struct Basic {
pub v: bool,
pub w: bool,
}
let yaml = indoc! {"
---
@@ -107,9 +103,8 @@ fn test_unknown_anchor() {
#[test]
fn test_ignored_unknown_anchor() {
#[derive(Deserialize, Debug)]
struct Wrapper {
#[allow(dead_code)]
c: (),
pub struct Wrapper {
pub c: (),
}
let yaml = indoc! {"
b: [*a]
@@ -161,7 +156,7 @@ fn test_second_document_syntax_error() {
#[test]
fn test_missing_enum_tag() {
#[derive(Deserialize, Debug)]
enum E {
pub enum E {
V(usize),
}
let yaml = indoc! {r#"
@@ -175,11 +170,11 @@ fn test_missing_enum_tag() {
#[test]
fn test_serialize_nested_enum() {
#[derive(Serialize, Debug)]
enum Outer {
pub enum Outer {
Inner(Inner),
}
#[derive(Serialize, Debug)]
enum Inner {
pub enum Inner {
Newtype(usize),
Tuple(usize, usize),
Struct { x: usize },
@@ -213,11 +208,11 @@ fn test_serialize_nested_enum() {
#[test]
fn test_deserialize_nested_enum() {
#[derive(Deserialize, Debug)]
enum Outer {
pub enum Outer {
Inner(Inner),
}
#[derive(Deserialize, Debug)]
enum Inner {
pub enum Inner {
Variant(Vec<usize>),
}

@@ -246,7 +241,7 @@ fn test_deserialize_nested_enum() {
#[test]
fn test_variant_not_a_seq() {
#[derive(Deserialize, Debug)]
enum E {
pub enum E {
V(usize),
}
let yaml = indoc! {"
@@ -260,11 +255,10 @@ fn test_variant_not_a_seq() {

#[test]
fn test_struct_from_sequence() {
#[allow(dead_code)]
#[derive(Deserialize, Debug)]
struct Struct {
x: usize,
y: usize,
pub struct Struct {
pub x: usize,
pub y: usize,
}
let yaml = indoc! {"
[0, 0]
@@ -336,9 +330,8 @@ fn test_long_tuple() {
#[test]
fn test_invalid_scalar_type() {
#[derive(Deserialize, Debug)]
struct S {
#[allow(dead_code)]
x: [i32; 1],
pub struct S {
pub x: [i32; 1],
}

let yaml = "x: ''\n";
@@ -350,9 +343,8 @@ fn test_invalid_scalar_type() {
#[test]
fn test_infinite_recursion_objects() {
#[derive(Deserialize, Debug)]
struct S {
#[allow(dead_code)]
x: Option<Box<S>>,
pub struct S {
pub x: Option<Box<S>>,
}

let yaml = "&a {'x': *a}";
@@ -364,7 +356,7 @@ fn test_infinite_recursion_objects() {
#[test]
fn test_infinite_recursion_arrays() {
#[derive(Deserialize, Debug)]
struct S(usize, Option<Box<S>>);
pub struct S(pub usize, pub Option<Box<S>>);

let yaml = "&a [0, *a]";
let expected = "recursion limit exceeded";
@@ -375,7 +367,7 @@ fn test_infinite_recursion_arrays() {
#[test]
fn test_infinite_recursion_newtype() {
#[derive(Deserialize, Debug)]
struct S(Option<Box<S>>);
pub struct S(pub Option<Box<S>>);

let yaml = "&a [*a]";
let expected = "recursion limit exceeded";
@@ -386,9 +378,8 @@ fn test_infinite_recursion_newtype() {
#[test]
fn test_finite_recursion_objects() {
#[derive(Deserialize, Debug)]
struct S {
#[allow(dead_code)]
x: Option<Box<S>>,
pub struct S {
pub x: Option<Box<S>>,
}

let yaml = "{'x':".repeat(1_000) + &"}".repeat(1_000);
@@ -400,7 +391,7 @@ fn test_finite_recursion_objects() {
#[test]
fn test_finite_recursion_arrays() {
#[derive(Deserialize, Debug)]
struct S(usize, Option<Box<S>>);
pub struct S(pub usize, pub Option<Box<S>>);

let yaml = "[0, ".repeat(1_000) + &"]".repeat(1_000);
let expected = "recursion limit exceeded at line 1 column 513";