dtolnay / serde-yaml

Strongly typed YAML library for Rust
Apache License 2.0
964 stars 164 forks source link

Breaking change in mapping entry order in release 0.8.19 #221

Closed nthuemmel closed 2 years ago

nthuemmel commented 3 years ago

Before release 0.8.19 (replacing LinkedHashMap with IndexMap, commit b450e9808bd4f591a292a99e72342ad713a65a43), iteration order of serde_yaml::Mapping entries was preserved when an entry was .remove()d.

Starting with release 0.8.19, iteration order changes when removing an entry other than the last entry. For my use case, this is a breaking change.

Example code to reproduce:

extern crate serde; // 1.0.130
extern crate serde_yaml; // 0.8.21

use serde::Serialize;

#[derive(Serialize)]
struct Data {
    a: String,
    b: String,
    c: String,
}

fn main() {
    let structure = Data {
        a: "foo".to_string(),
        b: "bar".to_string(),
        c: "baz".to_string(),
    };

    let mut yaml = serde_yaml::to_value(&structure).unwrap();
    let yaml = yaml.as_mapping_mut().unwrap();

    let yaml_str = serde_yaml::to_string(&yaml).unwrap();
    assert_eq!(yaml_str, r#"---
a: foo
b: bar
c: baz
"#);

    yaml.remove(&serde_yaml::Value::String("a".to_string()));

    let yaml_str = serde_yaml::to_string(&yaml).unwrap();
    assert_eq!(yaml_str, r#"---
b: bar
c: baz
"#);

}

Playground link: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=594665a2b82c1887d66e511b72932220

The output is:

thread 'main' panicked at 'assertion failed: `(left == right)`
  left: `"---\nc: baz\nb: bar\n"`,
 right: `"---\nb: bar\nc: baz\n"`', src/main.rs:33:5

Notice how the remaining mapping entries have swapped positions.

dtolnay commented 2 years ago

Closing per https://github.com/dtolnay/serde-yaml/pull/222#pullrequestreview-1033573084 -- I think this is all right as currently implemented.