Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extracting struct name from Value? #264

Closed
jgarvin opened this issue Aug 4, 2020 · 4 comments · May be fixed by #328
Closed

Extracting struct name from Value? #264

jgarvin opened this issue Aug 4, 2020 · 4 comments · May be fixed by #328

Comments

@jgarvin
Copy link

jgarvin commented Aug 4, 2020

Looking at the docs for Value:

pub enum Value {
    Bool(bool),
    Char(char),
    Map(Map),
    Number(Number),
    Option(Option<Box<Value>>),
    String(String),
    Seq(Vec<Value>),
    Unit,
}

I don't see how to get the name of a struct out, e.g. if I were to call from_str on the contents of example.ron, how would I get the string "Nested" out of it? My use case is the following: I want to have a field that could be one of many different structs. I'd like to parse into a ron Value, check the parsed struct name, then based on that name choose which actual T to pass to into_rust. I couldn't find this in the examples/docs.

@jgarvin
Copy link
Author

jgarvin commented Aug 6, 2020

So I spent some time playing around with adding:

#[derive(Clone, Debug, Default, Deserialize, Serialize, Eq)]
pub struct Structure {
    pub name: String,
    pub fields: Map,
}

impl Hash for Structure {
    fn hash<H: Hasher>(&self, state: &mut H) {
        // TODO: is this any different than #derive'ing Hash?
        self.name.hash(state);
        self.fields.hash(state);
    }
}

impl Ord for Structure {
    fn cmp(&self, other: &Structure) -> Ordering {
        (&self.name, &self.fields).cmp(&(&other.name, &other.fields))
    }
}

/// Note: equality is only given name matches and if both values and order of values match
impl PartialEq for Structure {
    fn eq(&self, other: &Structure) -> bool {
        self.name == other.name && self.fields == other.fields
    }
}

impl PartialOrd for Structure {
    fn partial_cmp(&self, other: &Structure) -> Option<Ordering> {
        (&self.name, &self.fields).partial_cmp(&(&other.name, &other.fields))
    }
}

#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub enum Value {
    Bool(bool),
    Char(char),
    Structure(Structure),
    Map(Map),
    Number(Number),
    Option(Option<Box<Value>>),
    String(String),
    Seq(Vec<Value>),
    Unit,
}

But the problem I'm running into is that serde's data model seems to force losing struct names when combined with the lack of a parser separate from serde. What I see:

  • parse.rs doesn't give a full parser, it appears to be utility functions for implementing one
  • Deserializer actually contains the parser, and uses the parse.rs functions.
  • Deserializer needs you to map the input onto the serde data model.
  • The data model doesn't support struct names, so it's lost.
  • Deserialize translates the serde data model into the data structure, but it's too late, it only sees a map.

I think in order for this to work there has to be a parser independent of any use of serde that can translate text streams into RON Values.

@kvark
Copy link
Collaborator

kvark commented Aug 6, 2020

If that's something Serde lacks, but is needed, would there be an upstream issue about this?

@jgarvin
Copy link
Author

jgarvin commented Aug 6, 2020

I found serde-rs/serde#1345 which suggests wrapping in a struct with one field that is the name of the actual struct. They link to a helper crate that a later commenter says is broken though.

@github-actions
Copy link

Issue has had no activity in the last 180 days and is going to be closed in 7 days if no further activity occurs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants