protoc-gen-go-datastore
This is a protoc generator that generates Go code to implement the
datastore.PropertyLoadSaver
interface on protobuf messages.
The use case for this is to allow to send proto messages into Datastore without
storing the internal XXX_
fields, and also managing the ptypes correctly, so
that when a google.protobuf.Timestamp
is pushed to Datastore, it will become
a time.Time
in there, and so that when a time.Time
is retrieved from
Datastore, it is converted into a google.protobuf.Timestamp
.
Project Status
The current status is: You'd be crazy to use this!
Example
From this proto:
enum DataEnum {
DataEnum_UNKNOWN = 0;
TYPEA = 1;
TYPEB = 2;
}
message Data {
string id = 1;
int64 num = 2;
DataEnum type = 3;
enum EmbeddedEnum {
EmbeddedEnum_UNKNOWN = 0;
EEA = 1;
EEB = 2;
}
EmbeddedEnum embeddedEnum = 4;
google.protobuf.Timestamp timestamp = 5;
otherpkg.MoreData moreData = 6;
}
This extra Go will be generated:
func (x *Data) Load(props []datastore.Property) error {
for _, property := range props {
switch property.Name {
case "Id":
x.Id = property.Value.(string)
case "Num":
x.Num = property.Value.(int64)
case "Type":
enumStr := property.Value.(string)
enumNumber, ok := DataEnum_value[enumStr]
if ok {
x.Type = DataEnum(enumNumber)
} else {
x.Type = DataEnum(0)
}
case "EmbeddedEnum":
enumStr := property.Value.(string)
enumNumber, ok := Data_EmbeddedEnum_value[enumStr]
if ok {
x.EmbeddedEnum = Data_EmbeddedEnum(enumNumber)
} else {
x.EmbeddedEnum = Data_EmbeddedEnum(0)
}
case "Timestamp":
t := property.Value.(time.Time)
tProto, err := ptypes.TimestampProto(t)
if err != nil {
return fmt.Errorf("could not convert time.Time to ptypes: %s", err)
}
x.Timestamp = tProto
case "MoreData":
entity := &otherpkg.MoreData{}
entity.Load(property.Value.(*datastore.Entity).Properties)
x.MoreData = entity
}
}
return nil
}
func (x *Data) Save() ([]datastore.Property, error) {
props := []datastore.Property{
datastore.Property{
Name: "Id",
Value: string(x.Id),
NoIndex: false, // TODO: check str and []byte len
},
datastore.Property{
Name: "Num",
Value: int64(x.Num),
NoIndex: false, // TODO: check str and []byte len
},
datastore.Property{
Name: "Type",
Value: x.Type.String(),
NoIndex: false,
},
datastore.Property{
Name: "EmbeddedEnum",
Value: x.EmbeddedEnum.String(),
NoIndex: false,
},
datastore.Property{
Name: "Timestamp",
Value: func() time.Time { t, _ := ptypes.Timestamp(x.Timestamp); return t }(),
NoIndex: false,
},
datastore.Property{
Name: "MoreData",
Value: &datastore.Entity{
Key: nil,
Properties: func() []datastore.Property {
p, err := x.MoreData.Save()
if err != nil {
panic(err)
}
return p
}(),
},
},
}
return props, nil
}
So the resulting struct implements datastore.PropertyLoadSaver
.