Search code examples
pythongenericscapnproto

How to instantiate a generic Cap'n Proto type in pycapnp


I cannot figure out how to instantiate an Option(T) type in pycapnp.

I have tried to instantiate a new message and then set the value of 'some', but it loses type information in doing so.

struct Option(T) {
  union {
    none @0 :Void;
    some @1 :T;
  }
}

struct Something {
  a @0 :Int16;
}
o = Option.new_message()
o.some = Something.new_message(a=5)
o.some.a // throws error

I would expect the option to become typed by virtue of the added struct, but it loses all type information and I cannot access the members of the object placed in the 'some' union value.


Solution

  • Cap'n Proto generics aren't really designed to work that way. They are designed for static type checking (with statically-typed languages in mind, i.e. not Python). An instance of a generic type cannot "become typed" after the fact -- the type must be known statically / at construction.

    If a type parameter isn't specified, then it is assumed to be AnyPointer. I believe that means you need to access some like this:

    o.some.as_struct(Something).a
    

    I think that in Python there is no way to construct a generic type with type parameter specified at runtime. The only way you can really use generics is when the containing type specifies type parameters, like:

    struct ContainingType {
      option @0 :Option(Something);
    }
    

    If you then construct a ContainingType and then access its option field, you'll get an Option object that knows that the type of some is Something, not AnyPointer.