Help implementing a function similar to this Python one


I’ve been looking over the source code of the Python driver for RethinkDB at

There is a function which essentially receives any type as its argument and returns an instance of a subclass of the RqlQuery class.

Supposing I had a trait RqlQuery in Rust, how could I achieve a similar result to the below Python function (edited for brevity)?

def expr(val, nesting_depth=20):  # Returns an instance of a RqlQuery subclass
        Convert a Python primitive into a RQL primitive value
    if isinstance(val, RqlQuery):
        return val
    elif isinstance(val, collections.Callable):
        return Func(val)
    elif isinstance(val, (datetime.datetime,
        return ISO8601(val.isoformat())
    elif isinstance(val, (str, unicode)):
        return Datum(val)
    elif isinstance(val, bytes):
        return Binary(val)
    elif isinstance(val, collections.Mapping):
        obj = {}
        for k, v in dict_items(val):
            obj[k] = expr(v, nesting_depth - 1)
        return MakeObj(obj)
    elif isinstance(val, collections.Iterable):
        val = [expr(v, nesting_depth - 1) for v in val]
        return MakeArray(*val)
        return Datum(val)


isinstance(val, collections.Mapping) and isinstance(val, collections.Iterable) are problematic. There’s no way to ask “does x implement trait y” at runtime (you can only as “is x type y” using the Any trait).

This may be doable with specialization but that will only let you ask “does type x implement trait y” at compile time, not “does some unknown object x implement trait y” at runtime.

However, if you use concrete types instead of Mapping and Iterable, this is totally doable (although I recommend using an enum instead of traits.


The typical way would be to have an enum instead of a trait, listing the various possibilities. There could then be a trait that converts into that enum, e.g.

enum Rql {
    // ...

trait ToRql {
    fn to_rql(self) -> Rql;

impl ToRql for String {
    fn to_rql(self) -> Rql { Rql::Datum(self) }
impl<T: ToRql> for Vec<T> {
    fn to_rql(self) -> Rql {
        Rql::Array(self.into_iter().map(|x| x.to_rql()).collect())

// ...


Thanks for pointing me on the right path. I’ll have a look at using an enum. Cheers.


Thanks. Looks like an enum is the way to go.