Repository: toml-rs/toml (language: rust)

Issue:
Cannot serialize with string-like keys
The serialize logic for maps currently requires that keys either be `&str` (or `String`), _or_ be a newtype around such a type, as per

https://github.com/ordian/toml_edit/blob/bf5fb86a7e63f1a919dd507d98cbe082d6eb9614/src/ser/key.rs

any other type will generate an error with `ErrorKind::KeyNotString` kind saying "map key was not a string".

This makes it painful to have keys be "one of a known set", as expressed with a data-less enum, like so:

```rust
use serde::Serialize;
use std::collections::HashMap;

#[derive(Serialize, Hash, PartialEq, Eq)]
enum Foo {
    #[serde(rename = "hello")]
    Hello,
}

fn main() {
    let mut map = HashMap::new();
    map.insert(Foo::Hello, true);
    println!("{}", );
    println!("{}", toml_edit::ser::to_string(&map).unwrap());
}
```

Note that using `Foo` as a key works fine in maps with `serde_json` (`serde_json::to_string(&map).unwrap()`), whose key serialization logic lives here:

https://github.com/serde-rs/json/blob/2683b1aedc80e3b761033c13bd3359b56923253c/src/value/ser.rs#L441

The fix is to allow `serialize_unit_variant` to serialize using the variant name rather than generating `KeyNotString` here:

https://github.com/ordian/toml_edit/blob/bf5fb86a7e63f1a919dd507d98cbe082d6eb9614/src/ser/key.rs#L93-L100

serde_json allows that here:

https://github.com/serde-rs/json/blob/2683b1aedc80e3b761033c13bd3359b56923253c/src/value/ser.rs#L453-L461


Discussion / hints:
FYI this was carried over from `toml-rs`s serialization: https://github.com/alexcrichton/toml-rs/blob/master/src/ser.rs#L1448

Interesting that `serde_json` also serializes integers and chars but not bools or floats.
(PR coming soon btw)

Fix patch:
diff --git a/src/ser/key.rs b/src/ser/key.rs
index fff7a033..0265fb2d 100644
--- a/src/ser/key.rs
+++ b/src/ser/key.rs
@@ -94,9 +94,9 @@ impl serde::ser::Serializer for KeySerializer {
         self,
         _name: &'static str,
         _variant_index: u32,
-        _variant: &'static str,
+        variant: &'static str,
     ) -> Result<InternalString, Self::Error> {
-        Err(ErrorKind::KeyNotString.into())
+        Ok(variant.into())
     }
 
     fn serialize_newtype_struct<T: ?Sized>(


Test patch:
diff --git a/tests/serde.rs b/tests/serde.rs
index 4d1d0d4b..0c4c4a39 100644
--- a/tests/serde.rs
+++ b/tests/serde.rs
@@ -308,6 +308,25 @@ fn parse_enum_string() {
     }
 }
 
+#[test]
+fn map_key_unit_variants() {
+    #[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone, PartialOrd, Ord)]
+    enum Sort {
+        #[serde(rename = "ascending")]
+        Asc,
+        Desc,
+    }
+
+    let mut map = BTreeMap::new();
+    map.insert(Sort::Asc, 1);
+    map.insert(Sort::Desc, 2);
+
+    equivalent! {
+        map,
+        Table(map! { ascending: Integer(1), Desc: Integer(2) }),
+    }
+}
+
 #[test]
 fn empty_arrays() {
     #[derive(Serialize, Deserialize, PartialEq, Debug, Clone)]