clojusc/protobuf

Schema does not seem to capture oneof relationships

Opened this issue · 2 comments

jvia commented

Using the Photo example, I added a capture_by field which is oneof either a Phone or Camera.

syntax = "proto3";
package protobuf.examples.photo;

import "protobuf/extensions.proto";

option java_package = "examples";
option java_multiple_files = true;

message Photo {
  int32 id  = 1;
  string path = 2;
  repeated Label labels = 3 [(set) = true];
  repeated Attr attrs = 4 [(map) = true];
  repeated Tag tags  = 5;
  bytes image = 6;
  Type type = 7;
  oneof captured_by {
    Camera camera = 8;
    Phone phone = 9;
  }

  enum Type {
    JPEG = 0;
    PNG = 1;
    GIF = 2;
  }

  message Label {
    string item = 1;
    bool exists = 2;
  }

  message Attr {
    string key = 1;
    string val = 2;
  }

  message Tag {
    int32 person_id = 1;
    double x_coord = 2;
    double y_coord = 3;
    int32 width = 4;
    int32 height = 5;
  }

  message Camera {
    string model = 1;
    string make = 2;;
  }

  message Phone {
    string model = 1;
    string make = 2;
  }
}

The schema does not seem to indicate this relationship:

user> (proto/schema Photo)
{:type :struct,
 :name "protobuf.examples.photo.Photo",
 :fields
 {:path {:type :string},
  :tags
  {:type :list,
   :values
   {:type :struct,
    :name "protobuf.examples.photo.Photo.Tag",
    :fields
    {:person-id {:type :int},
     :x-coord {:type :double},
     :y-coord {:type :double},
     :width {:type :int},
     :height {:type :int}}}},
  :labels {:type :set, :values {:type :string}},
  :phone
  {:type :struct,
   :name "protobuf.examples.photo.Photo.Phone",
   :fields {:model {:type :string}, :make {:type :string}}},
  :type {:type :enum, :values #{:png :gif :jpeg}},
  :id {:type :int},
  :camera
  {:type :struct,
   :name "protobuf.examples.photo.Photo.Camera",
   :fields {:model {:type :string}, :make {:type :string}}},
  :attrs
  {:type :map, :keys {:type :string}, :values {:type :string}},
  :image {:type :byte_string}}}

But creating the protobuf does seem to respect this relationship (somewhat):

user> (proto/create Photo {:phone {:model "model" :make "make"} :camera {:model "model" :make "make"}})
{:camera {:model "model", :make "make"}}

Oddly enough it does not seem to retain the captured_by field and instead brings both fields to the top-level of the schema. It does only allow setting one of these fields

I'll take a little longer look at this in a bit, but wanted to point out that you're using proto3, and that's not fully supported yet. There are several tickets related to adding support for proto3 ... sadly, it's not quite straight-forward.

If there's any chance you can use proto2, I'd recommend that. Most of the benefit for proto3 is actually in C, Go, and others; doesn't affect the JVM very much (at all maybe?).

jvia commented

Unfortunately the protos are defined elsewhere and are out of my hand.

I'll peak around those tickets and see if I can help at all.