Dynamic mapping


#1

I have been looking at Rust for a while, and I really like the idea of a strict and a rich type system and save memory allocation (no more mark sweep :smile: ). I have been using C++ for many years, so Rust is a refreshing approach.

But what I can’t find a way in Rust to make dynamic mapping of values like mapping things from a JSON structure to a Rust type, or how to pack arguments from dynamic values and then call a function using this values. (as it now is possible to do using C++ templates).

In languages like Go, this can be done using reflection, and they have a very nice JSON mapping, where the type info (and meta hints) in Go can be used to validate dynamic values.

I have seen some writing about reflection in Rust, but it seems like this is not a part of the language that have matured, and it have no standard library to support this.

So … how can I make a JSON object to a Rust type, and how can I find a function by its name, and pack dynamic values to a function call ? I could, of cause, make some IDL compiler but I like the idea of using the type system in the language and not maintain to definitions.


#2

It think “serde” is the library you are looking for JSON stuff. On nightly, it derives the info statically and never at runtime.

With regards to packing arguments to a function, I’m not sure how this is useful and couldn’t be better implemented using other techniques like traits?

When it comes to runtime reflection, Rust has the behavior of a vampire.


#3

Thanks for your swift answer :slight_smile:

Ok, “serde” looks really nice, it seems like i god starting point.

Then there is the reflection part and if I can make dynamic call’s using traits (they look a bit like Go interfaces or C++ abstract classes) it is ok with me, the problem is packing arguments, finding function names and making a call to this function using the dynamically packed arguments (unsafe call).

My goal is JsonRPC but I like to be able to only define methods in pure Rust, too keep all things simple and understandable.

I know how to do this i Go, but … i really like to be able to do this in Rust instead.

What is the future of this “Rust vampire”, any plans for feeding it with garlic or silver crosses ?


#4

Rust takes the approach of generating code at compile time for those kinds of tasks rather than the approach taken in Go, Java, etc of reflecting over values and types at runtime. You could make a syntax extension (which are limited to use with nightly compilers at the moment, unfortunately) to generate the logic you need to route function calls appropriately.


#5

You can do it with just traits and regular (stable) macros:

Playground link

you do have to manually add each function you want to expose to a map, though.

It would be possible to could do it with just the type system if there were a ‘non-generic function’ trait that had inputs and outputs as associated types, but there isn’t; I originally tried an impl like

impl<I1: FromToDyn, I2: FromToDyn, O: FromToDyn, F: Fn(I1, I2) -> O> DynCall for F { ... }

but of course it didn’t work because it can’t rule out F being generic (or otherwise having multiple Fn implementations with different types), in which case it wouldn’t know which version to call.


#6

I did not expect Rust to have a dynamic type system at run time (that is the beauty of Rust and C), but something like C++ variadic template system, where all type mapping are done at compile time, but using a more rich type system than C++.

But syntax extension sounds promising, where can I find more info on this subject, and when is it expected to be in stable ?


#7

Thanks for you example.

I use this kind of approach in C++ at the moment (I have a dynamic value inside a static language), and this is the default method for RPC in Go too. In large code bases this can become hard to maintain as we are not able to use the static type checker of the compiler.

But I like to use the static definition already given by the language to build up the info about the mapping, and was hoping that this info could be found somewhere, like in the C++ variadic template system.

But I am also new to Rust, so it is nice to see what is possible. I have also looked at Go for a while, but I much rather invest my time in Rust, but I really need to find a solution to this mapping problem, or I am a little stuck to Go :slight_smile: