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

Owned [NamedField] for Fields #62

Open
sunng87 opened this issue Jul 20, 2021 · 10 comments
Open

Owned [NamedField] for Fields #62

sunng87 opened this issue Jul 20, 2021 · 10 comments

Comments

@sunng87
Copy link
Contributor

sunng87 commented Jul 20, 2021

The current signature of Fields::Named hold a borrowed slice of NamedField. As far as I can tell, it's designed for 'static definition of rust structs. This makes it difficult to define dynamic Structable for a map like we talked in #53 .

Perhaps we can make it a Cow for the dynamic scenario.

@hawkw
Copy link
Member

hawkw commented Nov 23, 2021

@sunng87 just to clarify here, is it the slice that should be owned, or the NamedFields that should be owned?

@sunng87
Copy link
Contributor Author

sunng87 commented Nov 24, 2021

@hawkw I think I need for both. I'm trying to construct a Structable from a JSON object, which may have dynamic fields that are determined at runtime, in order to get O(1) access to the fields via valuable API.

Type like this works best for my scenario:

pub enum Fields<'a> {
    /// Named fields
    Named(&'a [NamedField<'a>]),

    OwnedNamed(Vec<OwnedNamedField>),  // where OwnedNamedField hold an owned String instead of str

    /// Unnamed (positional) fields or unit
    Unnamed,
}

@hawkw
Copy link
Member

hawkw commented Nov 24, 2021

Right, I'm looking into a possible change like this. But, I'm not totally sure if I understand why this change is necessary. If you have a Vec of field names, can't you just pass a borrowed slice of that Vec into Fields::Named?

@sunng87
Copy link
Contributor Author

sunng87 commented Nov 27, 2021

That sounds reasonable. It has been a while since last time I'm running into this issue. Let me check my feature branch again to refresh my context about this.

@hawkw
Copy link
Member

hawkw commented Nov 30, 2021

@sunng87 let me know if that solution works out for you; I'd like to get this issue figured out soon, because if we do add code to make owned named fields possible, we would probably have to make some breaking changes, and it would be nice to figure out what's necessary here before releasing 0.1.

@sunng87
Copy link
Contributor Author

sunng87 commented Dec 1, 2021

Sorry for late response. I may still have issue with current NamedField vector. My use-case is to implement Structable for serde_json::Value and its internal Map<String, Value>. Because the map has dynamic fields so I use StructDef::Dynamic here.

impl<'a> Structable for Map<String, Json> {
    fn definition(&'a self) -> StructDef<'a> {
        let field_defs: Vec<NamedField<'a>> = Vec::new();
        // add field names

        let fields = Fields::Named(&field_defs);

        let def = StructDef::Dynamic {
            name: "Json",
            fields,
        };

        def
    }
}

There are two issues from this piece of code:

  1. The lifetime 'a from StructDef<'a> should be same as the Map because the field names in StructDef borrows str from the map. But I got error[E0308]: method not compatible with trait with my code above.
  2. The NamedField vector is created within the function so it's impossible to borrow it outside.

OwnedNamed(Vec<OwnedNamedField>) in my previous comment can fix both 1 and 2 issue.

@hawkw
Copy link
Member

hawkw commented Dec 1, 2021

Hmm, I see why you can't borrow the fields here, so you're right that an owned variant might be necessary. Thanks for the example!

@sunng87
Copy link
Contributor Author

sunng87 commented Dec 2, 2021

Another suggestion is to make name of StructDef::Dynamic an Option<String> because the json object is typically anonymous in term of a type.

@carllerche
Copy link
Member

At some point, I'd say that the type isn't a structable but a mappable.

I think it would be fair to add some additional trait fns that make it easier to work w/ json objects. Eg. get(&str) -> Option<Value<'_>> or something like that.

@sunng87
Copy link
Contributor Author

sunng87 commented Dec 4, 2021

The only concern with Mappable is it doesn't seem to have O(1) access to value with given key name.

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

No branches or pull requests

3 participants