gluon-lang / gluon

A static, type inferred and embeddable language written in Rust.
https://gluon-lang.org
MIT License
3.21k stars 145 forks source link

gluon marshalling complex foreign types #626

Open jrpascucci opened 6 years ago

jrpascucci commented 6 years ago

I’m trying to get marshalling a complex foreign type to work on stable (0.8.1).

I’d like to wrap a passed in immutable json::JsonValue and a mutable clone, pass those to gluon, run scripts on it to manipulate the data, then receive the mutated one back. Is there any reason this might not work on 0.8.1? I’m struggling a bit and my life would be easier if rust’s orphan rules were less strict. Q

Details: Taking a cue from the GluonUser example, I’m using a new struct JsonData {inner: JsonValue}, and struggling to get it to work.

Right now, I can’t seem to get the VmType trait on the JsonValue – does this technique only work for something that has a built-in generic?

impl VmType for JsonData where JsonValue: 'static + VmType, {

trait bound json::JsonValue: gluon_vm::api::VmType is not satisfied

impl VmType for JsonData | ^^^^^^ the trait gluon_vm::api::VmType is not implemented for json::JsonValue

Thanks.

Laegluin commented 6 years ago

Since you can't use derive for a foreign type, you need to provide a fitting gluon type definition yourself. There are multiple ways you can do it:

You can also take a look at the tests for the codegen crate, there are quite few simple examples in there.

If this doesn't help, maybe you can post some of the relevant code? :)

Marwes commented 6 years ago

This seems to be about https://docs.rs/json/0.11.13/json/enum.JsonValue.html ? If that is the case then it is correct that you can't use that directly since it is a foreign type and so you won't be able to implement a trait on it.

You can add a wrapper type like you seem to have but you can't add the where JsonValue: 'static + VmType, bound since it is impossible to implement VmType for the remote JsonValue type.

However, if I were to guess a little at what you want in the end I would actually recommend you depend on the git master for now as there are json support add if you enable the serialization feature which provides serialization and deserialization as well as Value type similar to JsonValue. Documentation is not quite up to date but the source is at https://github.com/gluon-lang/gluon/tree/master/std/json

Marwes commented 6 years ago

Unless things go horribly wrong I hope to get 0.9 out during this weekend.

jrpascucci commented 6 years ago

I'm removing the wheres and having other problems with make_type, but maybe this is going to be more of a documentation problem.

@Laegluin I have to say I don't yet know enough to understand your response - but I thank you for it. :)

@Marwes Yes. Okay, will try that. I feel like you're doing more work than I would have thought one would need to do, but maybe json is fundamentally special.

I started looking at how std::io and the like are done, and I don't understand them either, so what do I know. :).

Thank you for your efforts.

jrpascucci commented 6 years ago

Small update wrt master: the #[repr(transparent)] attribute is experimental (see issue #43036)

My colleagues are against relying on stuff that needs nightly.

Thanks.

Marwes commented 6 years ago

Yes. Okay, will try that. I feel like you're doing more work than I would have thought one would need to do, but maybe json is fundamentally special.

It isn't special in any way, if you had https://docs.rs/json/0.11.13/json/enum.JsonValue.html defined in your own crate then you could easily implement VmType, Pushable and Getable for it (even derive it automatically, as long as all the internal values also get an implementation of the traits).

The issue is only that it is awkward to work with remote types (even serde has issues with this, the remote attribute it uses to workaround this is something I might add at some point https://serde.rs/container-attrs.html#serderemote--).

It is things I 100% want to make easier, but it is still a lot of work to get all the way there.

Another that that would work if you dont want to use master is to define an equivalent to https://docs.rs/json/0.11.13/json/enum.JsonValue.html in your own crate and then add a pair of conversion functions to convert between your JsonValue and the one in the json crate. Then you would only need to convert between these types in the Rust gluon layer but could otherwise derive the necessary traits.