Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions entproto/adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/jhump/protoreflect/desc/builder"
"google.golang.org/protobuf/types/descriptorpb"
_ "google.golang.org/protobuf/types/known/emptypb"
_ "google.golang.org/protobuf/types/known/structpb"
_ "google.golang.org/protobuf/types/known/timestamppb"
_ "google.golang.org/protobuf/types/known/wrapperspb" // needed to load wkt to global proto registry
)
Expand All @@ -53,6 +54,9 @@ var (
"google.protobuf.StringValue": "google/protobuf/wrappers.proto",
"google.protobuf.BoolValue": "google/protobuf/wrappers.proto",
"google.protobuf.BytesValue": "google/protobuf/wrappers.proto",
"google.protobuf.Struct": "google/protobuf/struct.proto",
"google.protobuf.ListValue": "google/protobuf/struct.proto",
"google.protobuf.Value": "google/protobuf/struct.proto",
}
)

Expand Down
9 changes: 9 additions & 0 deletions entproto/cmd/protoc-gen-entgrpc/converter.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@ func (g *serviceGenerator) newConverter(fld *entproto.FieldMappingDescriptor) (*
case "[]string":
case "[]int32", "[]int64", "[]uint32", "[]uint64":
out.ToProtoConversion = ""
case "map[string]interface {}", "[]interface {}":
// Handled by convertPbMessageType for google.protobuf.Struct / google.protobuf.ListValue
// ToProtoConstructor and ToEntConstructor are already set
default:
return nil, fmt.Errorf("entproto: no mapping to ent field type %q", efld.Type.ConstName())
}
Expand Down Expand Up @@ -179,6 +182,12 @@ func convertPbMessageType(md *desc.MessageDescriptor, entField *gen.Field, conv
switch {
case md.GetFullyQualifiedName() == "google.protobuf.Timestamp":
conv.ToProtoConstructor = protogen.GoImportPath("google.golang.org/protobuf/types/known/timestamppb").Ident("New")
case md.GetFullyQualifiedName() == "google.protobuf.Struct":
conv.ToProtoConstructor = protogen.GoImportPath("entgo.io/contrib/entproto/runtime").Ident("NewStruct")
conv.ToEntConstructor = protogen.GoImportPath("entgo.io/contrib/entproto/runtime").Ident("ExtractStruct")
case md.GetFullyQualifiedName() == "google.protobuf.ListValue":
conv.ToProtoConstructor = protogen.GoImportPath("entgo.io/contrib/entproto/runtime").Ident("NewList")
conv.ToEntConstructor = protogen.GoImportPath("entgo.io/contrib/entproto/runtime").Ident("ExtractList")
case isWrapperType(md):
fqn := md.GetFullyQualifiedName()
typ := strings.Split(fqn, ".")[2]
Expand Down
1 change: 1 addition & 0 deletions entproto/cmd/protoc-gen-entgrpc/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"entgo.io/ent/entc"
"entgo.io/ent/entc/gen"
"google.golang.org/protobuf/compiler/protogen"
_ "google.golang.org/protobuf/types/known/structpb" // register google.protobuf.Struct in proto registry
)

var (
Expand Down
45 changes: 45 additions & 0 deletions entproto/runtime/extract.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,55 @@ package runtime
import (
"time"

"google.golang.org/protobuf/types/known/structpb"
"google.golang.org/protobuf/types/known/timestamppb"
)

// ExtractTime returns the time.Time from a proto WKT Timestamp
func ExtractTime(t *timestamppb.Timestamp) time.Time {
return t.AsTime()
}

// NewStruct creates a new *structpb.Struct from a map[string]interface{}.
// Returns nil if the input is nil or conversion fails.
func NewStruct(m map[string]interface{}) *structpb.Struct {
if m == nil {
return nil
}
s, err := structpb.NewStruct(m)
if err != nil {
return nil
}
return s
}

// ExtractStruct converts a *structpb.Struct to map[string]interface{}.
// Returns nil if the input is nil.
func ExtractStruct(s *structpb.Struct) map[string]interface{} {
if s == nil {
return nil
}
return s.AsMap()
}

// NewList creates a new *structpb.ListValue from a []interface{}.
// Returns nil if the input is nil or conversion fails.
func NewList(l []interface{}) *structpb.ListValue {
if l == nil {
return nil
}
lv, err := structpb.NewList(l)
if err != nil {
return nil
}
return lv
}

// ExtractList converts a *structpb.ListValue to []interface{}.
// Returns nil if the input is nil.
func ExtractList(l *structpb.ListValue) []interface{} {
if l == nil {
return nil
}
return l.AsSlice()
}