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

Issue:
`SpannedVisitor` field order
I'm attempting to implement span support for serde_yaml in a way compatible to serde_spanned. Specifically, I'd like to handle the magic struct in [`deserialize_struct`](https://github.com/shouya/serde-yaml-ng/blob/4162b22dac196f300982f93df3e29b829bde1aea/src/de.rs#L1713) from the [`DeserializerFromEvents`](https://github.com/shouya/serde-yaml-ng/blob/4162b22dac196f300982f93df3e29b829bde1aea/src/de.rs#L434) deserializer.

`DeserializerFromEvents` has a [`pos` ](https://github.com/shouya/serde-yaml-ng/blob/4162b22dac196f300982f93df3e29b829bde1aea/src/de.rs#L111) field that appear relevant, I'm trying detect the span based on this position cursor. However, due to the way `DeserializerFromEvents` works, it's impossible to extract `end` of the span the before parsing the value.

I thought about implementing [`SpannedDeserializer`](https://github.com/shouya/serde-yaml-ng/blob/4162b22dac196f300982f93df3e29b829bde1aea/src/de.rs#L1724C16-L1724C35) in a way that just wraps around `self: &mut DeserializerFromEvents<'de, 'document>`, so it can first spit out the starting `pos`, then the `value`, then the ending `pos`.

However, based on how [`SpannedVisitor`](https://github.com/toml-rs/toml/blob/091a0047931e997fe129f3c8fac2788af8091604/crates/serde_spanned/src/spanned.rs#L181) is implemented, it expect a strict order of keys to emit from my deserializer, which makes my plan unfeasible.

Based on my understanding of how serde_spanned works, making `SpannedVisitor` consume the keys in order of `start` > `value` > `end` (or `value`  > `start` > `end`) should make it flexible for use cases like mine. Or, for backward compatibility's sake, maybe it's better to allow `SpannedVisitor` consume the keys in arbitrary order. Or perhaps I'm doing it wrong and there is a better way to do it?


Discussion / hints:

Fix patch:
diff --git a/crates/serde_spanned/src/spanned.rs b/crates/serde_spanned/src/spanned.rs
index 7db9bced..9dfc3d37 100644
--- a/crates/serde_spanned/src/spanned.rs
+++ b/crates/serde_spanned/src/spanned.rs
@@ -182,25 +182,46 @@ where
             where
                 V: serde::de::MapAccess<'de>,
             {
-                if visitor.next_key()? != Some(START_FIELD) {
-                    return Err(serde::de::Error::custom("spanned start key not found"));
+                let mut start: Option<usize> = None;
+                let mut end: Option<usize> = None;
+                let mut value: Option<T> = None;
+                while let Some(key) = visitor.next_key()? {
+                    match key {
+                        START_FIELD => {
+                            if start.is_some() {
+                                return Err(serde::de::Error::duplicate_field(START_FIELD));
+                            }
+                            start = Some(visitor.next_value()?);
+                        }
+                        END_FIELD => {
+                            if end.is_some() {
+                                return Err(serde::de::Error::duplicate_field(END_FIELD));
+                            }
+                            end = Some(visitor.next_value()?);
+                        }
+                        VALUE_FIELD => {
+                            if value.is_some() {
+                                return Err(serde::de::Error::duplicate_field(VALUE_FIELD));
+                            }
+                            value = Some(visitor.next_value()?);
+                        }
+                        field => {
+                            return Err(serde::de::Error::unknown_field(
+                                field,
+                                &[START_FIELD, END_FIELD, VALUE_FIELD],
+                            ));
+                        }
+                    }
                 }
-                let start: usize = visitor.next_value()?;
-
-                if visitor.next_key()? != Some(END_FIELD) {
-                    return Err(serde::de::Error::custom("spanned end key not found"));
-                }
-                let end: usize = visitor.next_value()?;
-
-                if visitor.next_key()? != Some(VALUE_FIELD) {
-                    return Err(serde::de::Error::custom("spanned value key not found"));
+                match (start, end, value) {
+                    (Some(start), Some(end), Some(value)) => Ok(Spanned {
+                        span: start..end,
+                        value,
+                    }),
+                    (None, _, _) => Err(serde::de::Error::missing_field(START_FIELD)),
+                    (_, None, _) => Err(serde::de::Error::missing_field(END_FIELD)),
+                    (_, _, None) => Err(serde::de::Error::missing_field(VALUE_FIELD)),
                 }
-                let value: T = visitor.next_value()?;
-
-                Ok(Spanned {
-                    span: start..end,
-                    value,
-                })
             }
         }
 


Test patch: