Skip to content

Commit

Permalink
encoding/protobuf: move to new-style definitions
Browse files Browse the repository at this point in the history
Change-Id: Ic5ce67f8e8258eab16d48b96cec63e424f24007f
Reviewed-on: https://cue-review.googlesource.com/c/cue/+/5943
Reviewed-by: Marcel van Lohuizen <mpvl@google.com>
  • Loading branch information
mpvl committed May 13, 2020
1 parent 435989a commit 2b118fb
Show file tree
Hide file tree
Showing 19 changed files with 313 additions and 287 deletions.
10 changes: 5 additions & 5 deletions cmd/cue/cmd/testdata/script/def_proto.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ package api
import "time"

// Attributes defines attributes.
Attributes :: {
#Attributes: {
// A map of attribute name to its value.
attributes?: {
[string]: AttributeValue
[string]: #AttributeValue
} @protobuf(1,type=map<string,AttributeValue>)

// Specifies one attribute value with different type.
AttributeValue :: {
#AttributeValue: {
// The attribute value.
close({}) | close({
stringValue: string @protobuf(2,name=string_value)
Expand All @@ -31,12 +31,12 @@ Attributes :: {
timestampValue: time.Time @protobuf(7,type=google.protobuf.Timestamp,name=timestamp_value)
}) | close({
// Used for values of type STRING_MAP
stringMapValue: StringMap @protobuf(9,name=string_map_value)
stringMapValue: #StringMap @protobuf(9,name=string_map_value)
})
}

// Defines a string map.
StringMap :: {
#StringMap: {
// Holds a set of name/value pairs.
entries?: {
[string]: string
Expand Down
26 changes: 13 additions & 13 deletions cmd/cue/cmd/testdata/script/import_proto.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ module: "acme.com/api"
-- root/cue.mod/gen/googleapis.com/acme/test/test/test_proto_gen.cue --
package test_test

AnotherTest: {
#AnotherTest: {
test?: int32 @protobuf(1)
}
-- root/mixer/v1/attributes.proto --
Expand Down Expand Up @@ -170,14 +170,14 @@ import (
)

// Attributes defines attributes.
Attributes :: {
#Attributes: {
// A map of attribute name to its value.
attributes?: {
[string]: AttributeValue
[string]: #AttributeValue
} @protobuf(1,type=map<string,AttributeValue>)

// Specifies one attribute value with different type.
AttributeValue :: {
#AttributeValue: {
// The attribute value.
close({}) | close({
stringValue: string @protobuf(2,name=string_value)
Expand All @@ -193,16 +193,16 @@ Attributes :: {
timestampValue: time.Time @protobuf(7,type=google.protobuf.Timestamp,name=timestamp_value)
}) | close({
// Used for values of type STRING_MAP
stringMapValue: StringMap @protobuf(9,name=string_map_value)
stringMapValue: #StringMap @protobuf(9,name=string_map_value)
}) | close({
testValue: test.Test @protobuf(10,type=acme.test.Test,name=test_value)
testValue: test.#Test @protobuf(10,type=acme.test.Test,name=test_value)
}) | close({
testValue: test_test.AnotherTest @protobuf(11,type=acme.test.test.AnotherTest,name=test_value)
testValue: test_test.#AnotherTest @protobuf(11,type=acme.test.test.AnotherTest,name=test_value)
})
}

// Defines a string map.
StringMap :: {
#StringMap: {
// Holds a set of name/value pairs.
entries?: {
[string]: string
Expand All @@ -216,14 +216,14 @@ package client
import "acme.com/api/mixer/v1"

// Defines the per-service client configuration.
ServiceConfig :: {
disableCheckCalls?: bool @protobuf(1,name=disable_check_calls)
disableReportCalls?: bool @protobuf(2,name=disable_report_calls)
mixerAttributes?: v1.Attributes @protobuf(3,type=Attributes,name=mixer_attributes)
#ServiceConfig: {
disableCheckCalls?: bool @protobuf(1,name=disable_check_calls)
disableReportCalls?: bool @protobuf(2,name=disable_report_calls)
mixerAttributes?: v1.#Attributes @protobuf(3,type=Attributes,name=mixer_attributes)
}
-- expect-test_proto_gen.cue --
package test

Test :: {
#Test: {
test?: int32 @protobuf(1)
}
2 changes: 1 addition & 1 deletion encoding/protobuf/examples_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func ExampleExtract() {
// package basic
//
// // This is my type.
// MyType :: {
// #MyType: {
// stringValue?: string @protobuf(1,name=string_value) // just any 'ole string
//
// // A method must start with a capital letter.
Expand Down
70 changes: 48 additions & 22 deletions encoding/protobuf/parse.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,9 +195,10 @@ type protoConverter struct {
}

type mapping struct {
ref string
alias string // alias for the type, if exists.
pkg *protoConverter
ref string
cueName string
alias string // alias for the type, if exists.
pkg *protoConverter
}

func (p *protoConverter) importPath() string {
Expand All @@ -223,12 +224,12 @@ func (p *protoConverter) toCUEPos(pos scanner.Position) token.Pos {
return p.tfile.Pos(pos.Offset, 0)
}

func (p *protoConverter) addRef(pos scanner.Position, name string) {
func (p *protoConverter) addRef(pos scanner.Position, name, cuename string) {
top := p.scope[len(p.scope)-1]
if _, ok := top[name]; ok {
failf(pos, "entity %q already defined", name)
}
top[name] = mapping{ref: name}
top[name] = mapping{ref: name, cueName: cuename}
}

func (p *protoConverter) addNames(elems []proto.Visitee) {
Expand Down Expand Up @@ -260,15 +261,15 @@ func (p *protoConverter) addNames(elems []proto.Visitee) {
}
sym := strings.Join(append(p.path, name), ".")
p.symbols[sym] = true
p.addRef(pos, name)
p.addRef(pos, name, "#"+name)
}
}

func (p *protoConverter) popNames() {
p.scope = p.scope[:len(p.scope)-1]
}

func (p *protoConverter) uniqueTop(name string) string {
func (p *protoConverter) uniqueTop(name string, asIs bool) string {
a := strings.SplitN(name, ".", 2)
for i := len(p.scope) - 1; i > 0; i-- {
if _, ok := p.scope[i][a[0]]; ok {
Expand All @@ -283,34 +284,47 @@ func (p *protoConverter) uniqueTop(name string) string {
})
p.aliases[first] = alias
}
if len(a) > 1 {
alias += "." + a[1]
a[0] = alias
if len(a) > 1 && !asIs {
a[1] = "#" + a[1]
}
return alias
return strings.Join(a, ".")
}
}
return name

if e, ok := p.scope[0][name]; ok {
return e.cueName
}
// TODO: do something more principled.
switch name {
case "time.Time", "time.Duration":
return name
}
if !asIs {
a[len(a)-1] = "#" + a[len(a)-1]
}
return strings.Join(a, ".")
}

func (p *protoConverter) toExpr(pos scanner.Position, name string) (expr ast.Expr) {
expr, err := parser.ParseExpr("", name, parser.ParseComments)
if err != nil {
panic(err)
panic(fmt.Sprintf("error parsing name %q: %v", name, err))
}
ast.SetPos(expr, p.toCUEPos(pos))
return expr
}

func (p *protoConverter) resolve(pos scanner.Position, name string, options []*proto.Option) string {
if s, ok := protoToCUE(name, options); ok {
return p.uniqueTop(s)
return p.uniqueTop(s, true)
}
if strings.HasPrefix(name, ".") {
return p.resolveTopScope(pos, name[1:], options)
}
for i := len(p.scope) - 1; i > 0; i-- {
if m, ok := p.scope[i][name]; ok {
return m.ref
return m.cueName
}
}
return p.resolveTopScope(pos, name, options)
Expand All @@ -324,12 +338,14 @@ func (p *protoConverter) resolveTopScope(pos scanner.Position, name string, opti
i = len(name)
}
if m, ok := p.scope[0][name[:i]]; ok {
isPkg := false
if m.pkg != nil {
p.imported[m.pkg.importPath()] = true
// TODO: do something more principled.
isPkg = true
}
cueName := name[i:]
return p.uniqueTop(m.ref + cueName)
return p.uniqueTop(m.ref+cueName, !isPkg || m.ref == m.cueName)
}
}
failf(pos, "name %q not found", name)
Expand Down Expand Up @@ -385,7 +401,7 @@ func (p *protoConverter) doImport(v *proto.Import) error {
if imp.importPath() == p.importPath() {
pkg = nil
}
p.scope[0][ref] = mapping{prefix + k, "", pkg}
p.scope[0][ref] = mapping{prefix + k, prefix + toCue(k), "", pkg}
}
}
if len(pkgNamespace) == 0 {
Expand All @@ -400,6 +416,15 @@ func (p *protoConverter) doImport(v *proto.Import) error {
return nil
}

// TODO: this doesn't work. Do something more principled.
func toCue(name string) string {
a := strings.Split(name, ".")
for i, s := range a {
a[i] = "#" + s
}
return strings.Join(a, ".")
}

func (p *protoConverter) stringLit(pos scanner.Position, s string) *ast.BasicLit {
return &ast.BasicLit{
ValuePos: p.toCUEPos(pos),
Expand All @@ -412,13 +437,14 @@ func (p *protoConverter) ident(pos scanner.Position, name string) *ast.Ident {
}

func (p *protoConverter) ref(pos scanner.Position) *ast.Ident {
return &ast.Ident{NamePos: p.toCUEPos(pos), Name: p.path[len(p.path)-1]}
name := "#" + p.path[len(p.path)-1]
return &ast.Ident{NamePos: p.toCUEPos(pos), Name: name}
}

func (p *protoConverter) subref(pos scanner.Position, name string) *ast.Ident {
return &ast.Ident{
NamePos: p.toCUEPos(pos),
Name: name,
Name: "#" + name,
}
}

Expand Down Expand Up @@ -485,7 +511,7 @@ func (p *protoConverter) message(v *proto.Message) {
if v.Comment == nil {
ref.NamePos = newSection
}
f := &ast.Field{Label: ref, Token: token.ISA, Value: s}
f := &ast.Field{Label: ref, Value: s}
addComments(f, 1, v.Comment, nil)

p.addDecl(f)
Expand Down Expand Up @@ -607,14 +633,14 @@ func (p *protoConverter) enum(x *proto.Enum) {
}

// Top-level enum entry.
enum := &ast.Field{Label: name, Token: token.ISA}
enum := &ast.Field{Label: name}
addComments(enum, 1, x.Comment, nil)

// Top-level enum values entry.
valueName := ast.NewIdent(name.Name + "_value")
valueName.NamePos = newSection
valueMap := &ast.StructLit{}
d := &ast.Field{Label: valueName, Token: token.ISA, Value: valueMap}
d := &ast.Field{Label: valueName, Value: valueMap}
// addComments(valueMap, 1, x.Comment, nil)

if strings.Contains(name.Name, "google") {
Expand Down Expand Up @@ -727,7 +753,7 @@ func (p *protoConverter) parseField(s *ast.StructLit, i int, x *proto.Field) *as

// body of @protobuf tag: sequence[,type][,name=<name>][,...]
o.tags += fmt.Sprint(x.Sequence)
if x.Type != typ {
if x.Type != strings.TrimLeft(typ, "#") {
o.tags += ",type=" + x.Type
}
if x.Name != name.Name {
Expand Down
22 changes: 11 additions & 11 deletions encoding/protobuf/testdata/attributes.proto.out.cue
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import (
"time"
)

StructWrap :: {
#StructWrap: {
struct?: {} @protobuf(1,type=google.protobuf.Struct)
any?: _ @protobuf(2,type=google.protobuf.Value)
listVal?: [...] @protobuf(3,type=google.protobuf.ListValue)
Expand All @@ -45,14 +45,14 @@ StructWrap :: {
// target.service: example
// ```
//
Attributes :: {
#Attributes: {
// A map of attribute name to its value.
attributes?: {
[string]: AttributeValue
[string]: #AttributeValue
} @protobuf(1,type=map<string,AttributeValue>)

// Specifies one attribute value with different type.
AttributeValue :: {
#AttributeValue: {
// The attribute value.
close({}) | close({
// Used for values of type STRING, DNS_NAME, EMAIL_ADDRESS, and URI
Expand All @@ -77,16 +77,16 @@ Attributes :: {
durationValue: time.Duration @protobuf(8,type=google.protobuf.Duration,name=duration_value)
}) | close({
// Used for values of type STRING_MAP
stringMapValue: StringMap @protobuf(9,name=string_map_value)
stringMapValue: #StringMap @protobuf(9,name=string_map_value)
}) | close({
testValue: test.Test @protobuf(10,type=acme.test.Test,name=test_value)
testValue: test.#Test @protobuf(10,type=acme.test.Test,name=test_value)
}) | close({
testValue: test_test.AnotherTest @protobuf(11,type=acme.test.test.AnotherTest,name=test_value)
testValue: test_test.#AnotherTest @protobuf(11,type=acme.test.test.AnotherTest,name=test_value)
})
}

// Defines a string map.
StringMap :: {
#StringMap: {
// Holds a set of name/value pairs.
entries?: {
[string]: string
Expand All @@ -101,7 +101,7 @@ Attributes :: {
// dictionary instead. The message-level dictionary is carried by the
// `words` field of this message, the deployment-wide dictionary is determined via
// configuration.
CompressedAttributes :: {
#CompressedAttributes: {
// The message-level dictionary.
words?: [...string] @protobuf(1)

Expand Down Expand Up @@ -142,15 +142,15 @@ CompressedAttributes :: {

// Holds attributes of type STRING_MAP
stringMaps?: {
[string]: StringMap
[string]: #StringMap
} @protobuf(9,type=map<sint32,StringMap>,string_maps,"(gogoproto.nullable)=false")
}
let _time_ = time
let _bytes_ = bytes

// A map of string to string. The keys and values in this map are dictionary
// indices (see the [Attributes][istio.mixer.v1.CompressedAttributes] message for an explanation)
StringMap :: {
#StringMap: {
// Holds a set of name/value pairs.
entries?: {
[string]: int32
Expand Down

0 comments on commit 2b118fb

Please sign in to comment.