toml icon indicating copy to clipboard operation
toml copied to clipboard

How to use `Spanned`

Open yannham opened this issue 8 months ago • 0 comments

Hello,

I'm sorry if this question has been answered already, but I couldn't find enough information both in the documentation of toml::Spanned or looking through the opened and closed issues to understand how to use toml::Spanned properly.

I'm trying to serialize a TOML value with all position information, recursively. Think of toml::Value but with span information at every node.

My naive attempt is the following:

use toml::Spanned;

/// A TOML value with span information. Similar to `toml::Spanned<toml::Value>`, but where
/// atoms use Nickel types instead (`NickelString`, `Number`, etc)
#[derive(serde::Deserialize, Debug, Clone)]
#[serde(untagged)]
pub enum SpannedValueData {
    String(NickelString),
    #[serde(deserialize_with = "crate::serialize::deserialize_num")]
    Number(Number),
    Boolean(bool),
    Array(Vec<SpannedValue>),
    Map(IndexMap<String, SpannedValue>),
}

impl SpannedValue {
    /// Take the id of the current file and convert a spanned value to a Nickel term with
    /// position information properly set.
    pub fn into_term(self, ...) -> RichTerm {
        // not relevant to the issue here: embed this spanned value into an other representation
    }
}

#[derive(serde::Deserialize, Debug, Clone)]
#[serde(transparent)]
pub struct SpannedValue(Spanned<SpannedValueData>);

/// Deserialize a Nickel term with position information from a TOML source provided as
/// a string and the file id of this source.
pub fn from_str(s: &str, ...) -> Result<RichTerm, toml::de::Error> {
    let spanned: SpannedValue = toml::from_str(s)?;
    Ok(spanned.into_term(...))
}

I tried to hide the part not relevant to the issue at hand here, but mostly NickelString and Number are straightforward wrappers around string and numbers with proper Serialize and Deserialize implementations.

Now, if I try to deserialize a very simple TOML document:

[package]
name = "hello"
version = "0.1"

I get the following error:

data did not match any variant of untagged enum SpannedValueData

However, if I remove the Spanned<...> around SpannedValueData, then it works. So clearly there's something wrong about deserializing spanned values, but I'm not sure to understand what it is. I would expect that trying to deserialize Spanned<T> when T is deserializable would work out of the box.

yannham avatar Jun 05 '24 16:06 yannham