serde-ordered-collections 2.0.0

Ordered serialization/deserialization serde functionality
Documentation
use std::collections::BTreeSet;

use serde::Serialize;

pub fn sorted_serialize<S, T, L>(list: L, s: S) -> Result<S::Ok, S::Error>
where
    L: IntoIterator<Item = T>,
    S: serde::Serializer,
    T: Ord + Serialize + Clone,
{
    let ordered_list: BTreeSet<T> = list.into_iter().collect();
    Serialize::serialize(&ordered_list, s)
}

#[cfg(test)]
mod tests {
    #![allow(non_snake_case)]

    use serde_derive::{Deserialize, Serialize};
    use std::collections::HashSet;

    #[derive(Debug, Serialize, Deserialize, Eq, PartialEq)]
    struct SampleData {
        #[serde(serialize_with = "super::sorted_serialize")]
        values: HashSet<String>,
    }

    #[test]
    fn serde_roundtrip__produces_matching_data() {
        // Given
        let data = SampleData {
            values: {
                let mut set = HashSet::new();
                set.insert("foo".into());
                set.insert("abc".into());
                set.insert("123".into());

                set
            },
        };

        // When
        let string = serde_yaml::to_string(&data).unwrap();

        // Then
        let deserialized_data: SampleData = serde_yaml::from_str(&string).unwrap();
        assert_eq!(data, deserialized_data);
    }

    #[test]
    fn yaml_to_string__produces_correctly_sorted_order_consistently() {
        for _i in 0..100 {
            // Given
            let data = SampleData {
                values: {
                    let mut set = HashSet::new();
                    set.insert("d".into());
                    set.insert("a".into());
                    set.insert("e".into());
                    set.insert("c".into());
                    set.insert("b".into());

                    set
                },
            };

            // When
            let string = serde_yaml::to_string(&data).unwrap();

            // Then
            assert_eq!(
                string,
                r###"---
values:
  - a
  - b
  - c
  - d
  - e
"###
            );
        }
    }
}