-
-
Notifications
You must be signed in to change notification settings - Fork 75
Description
As we know, Proto3 does not support extensions (except for declaring custom options). Extensions are fully supported in proto2 and editions though (link).
For common tasks (such a CRUD) we can create the following definition:
syntax = "proto2"; // proto2 !!!
package proto;
import "google/protobuf/timestamp.proto";
// common model
message Model {
optional string id = 1001;
optional string version = 1002;
optional google.protobuf.Timestamp created_at = 10001;
optional google.protobuf.Timestamp updated_at = 10002;
optional google.protobuf.Timestamp deleted_at = 10003;
extensions 100000 to 999999; // mount points for extensions
}
// define messages
message Person {
required string first_name = 1;
required string last_name = 2;
}
// mount messages to common model
extend Model {
optional Person person = 100001;
}After executing protoc for Golang (protoc-gen-go), I see that the following construction was created for Golang:
var file_experimant_proto_extTypes = []protoimpl.ExtensionInfo{
{
ExtendedType: (*Model)(nil),
ExtensionType: (*Person)(nil),
Field: 100001,
Name: "proto.person",
Tag: "bytes,100001,opt,name=person",
Filename: "experimant.proto",
},
}
// Extension fields to Model.
var (
// optional proto.Person person = 100001;
E_Person = &file_experimant_proto_extTypes[0]
)So, I can register extensions on client-side then extract it on server-side, or vise versa:
import "google.golang.org/protobuf/proto"
// SET EXTENSION
id := "123"
m := &Model{Id: &id}
fn := "First"
ln := "Name"
p := &Person{FirstName: &fn, LastName: &ln}
proto.SetExtension(m, E_Person, p)
// GET EXTENSION
person := proto.GetExtension(m, E_Person)
// or
proto.RangeExtensions(m, func(t protoreflect.ExtensionType, value any) bool {
if t.TypeDescriptor().FullName() == E_Person.TypeDescriptor().FullName() {
person := value.(*Person)
}
return true
})protoc-gen-ts does not generate (and does not registered them in Model class) an object(s) of classes ExtensionFieldInfo and ExtensionFieldBinaryInfo that is equivalent to Golang's protoimpl.ExtensionInfo.
In addition, as I can see from generated code, model serializer will still ignore extension fields even if I bind it manually, because the generated code explicitly loops through known fields, without knowing anything about extensions.