cuelang.org/go@v0.10.1/encoding/protobuf/types.go (about) 1 // Copyright 2019 CUE Authors 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package protobuf 16 17 import ( 18 "fmt" 19 "text/scanner" 20 21 "cuelang.org/go/cue/ast" 22 "cuelang.org/go/cue/parser" 23 "cuelang.org/go/cue/token" 24 "github.com/emicklei/proto" 25 ) 26 27 func protoToCUE(typ string, options []*proto.Option) ast.Expr { 28 t, ok := scalars[typ] 29 if !ok { 30 return nil 31 } 32 return predeclared(t) 33 } 34 35 var scalars = map[string]string{ 36 // Differing 37 "sint32": "int32", 38 "sint64": "int64", 39 "fixed32": "uint32", 40 "fixed64": "uint64", 41 "sfixed32": "int32", 42 "sfixed64": "int64", 43 44 // Identical to CUE 45 "int32": "int32", 46 "int64": "int64", 47 "uint32": "uint32", 48 "uint64": "uint64", 49 50 "double": "float64", 51 "float": "float32", 52 53 "bool": "bool", 54 "string": "string", 55 "bytes": "bytes", 56 } 57 58 func predeclared(s string) ast.Expr { 59 return &ast.Ident{ 60 Name: s, 61 Node: ast.NewIdent("__" + s), 62 } 63 } 64 65 func (p *protoConverter) setBuiltin(from string, to func() ast.Expr, pkg *protoConverter) { 66 p.scope[0][from] = mapping{to, pkg} 67 } 68 69 func (p *protoConverter) setBuiltinParse(from, to string, pkg *protoConverter) { 70 f := func() ast.Expr { 71 expr, err := parser.ParseExpr("", to, parser.ParseComments) 72 if err != nil { 73 panic(fmt.Sprintf("error parsing name %q: %v", to, err)) 74 } 75 return expr 76 } 77 p.scope[0][from] = mapping{f, pkg} 78 } 79 80 var ( 81 pkgTime = &protoConverter{cuePkgPath: "time"} 82 pkgStruct = &protoConverter{cuePkgPath: "struct"} 83 importTime = ast.NewImport(nil, "time") 84 importStruct = ast.NewImport(nil, "struct") 85 ) 86 87 func (p *protoConverter) mapBuiltinPackage(pos scanner.Position, file string, required bool) (generate bool) { 88 // Map some builtin types to their JSON/CUE mappings. 89 switch file { 90 case "gogoproto/gogo.proto": 91 92 case "google/protobuf/struct.proto": 93 p.setBuiltin("google.protobuf.Struct", func() ast.Expr { 94 return ast.NewStruct() 95 }, nil) 96 97 p.setBuiltin("google.protobuf.Value", func() ast.Expr { 98 return ast.NewIdent("_") 99 }, nil) 100 101 p.setBuiltin("google.protobuf.NullValue", func() ast.Expr { 102 return ast.NewNull() 103 }, nil) 104 105 p.setBuiltin("google.protobuf.ListValue", func() ast.Expr { 106 return ast.NewList(&ast.Ellipsis{}) 107 }, nil) 108 109 p.setBuiltin("google.protobuf.StringValue", func() ast.Expr { 110 return predeclared("string") 111 }, nil) 112 113 p.setBuiltin("google.protobuf.BoolValue", func() ast.Expr { 114 return predeclared("bool") 115 }, nil) 116 117 p.setBuiltin("google.protobuf.NumberValue", func() ast.Expr { 118 return predeclared("number") 119 }, nil) 120 121 return false 122 123 case "google/protobuf/empty.proto": 124 f := func() ast.Expr { 125 time := &ast.Ident{Name: "struct", Node: importStruct} 126 return ast.NewCall( 127 ast.NewSel(time, "MaxFields"), 128 ast.NewLit(token.INT, "0"), 129 ) 130 } 131 p.setBuiltin("google.protobuf.Empty", f, pkgStruct) 132 return false 133 134 case "google/protobuf/duration.proto": 135 f := func() ast.Expr { 136 time := &ast.Ident{Name: "time", Node: importTime} 137 return ast.NewSel(time, "Duration") 138 } 139 p.setBuiltin("google.protobuf.Duration", f, pkgTime) 140 return false 141 142 case "google/protobuf/timestamp.proto": 143 f := func() ast.Expr { 144 time := &ast.Ident{Name: "time", Node: importTime} 145 return ast.NewSel(time, "Time") 146 } 147 p.setBuiltin("google.protobuf.Timestamp", f, pkgTime) 148 return false 149 150 case "google/protobuf/any.proto": 151 // TODO: technically, the value should be `_` (anything), but that 152 // will not convert to a valid OpenAPI value. In practice, all 153 // "well-known" types except wrapper types (which will likely not 154 // be used here) are represented as strings. 155 // 156 // In Structural OpenAPI this type cannot be represented. 157 p.setBuiltinParse("google.protobuf.Any", `{ 158 // A URL/resource name that uniquely identifies the type of the serialized protocol buffer message. This string must contain at least one "/" character. The last segment of the URL's path must represent the fully qualified name of the type (as in `+ 159 "`type.googleapis.com/google.protobuf.Duration`"+`). The name should be in a canonical form (e.g., leading "." is not accepted). 160 // The remaining fields of this object correspond to fields of the proto messsage. If the embedded message is well-known and has a custom JSON representation, that representation is assigned to the 'value' field. 161 "@type": string, 162 }`, nil) 163 return false 164 165 case "google/protobuf/wrappers.proto": 166 p.setBuiltinParse("google.protobuf.DoubleValue", `null | float`, nil) 167 p.setBuiltinParse("google.protobuf.FloatValue", `null | float`, nil) 168 p.setBuiltinParse("google.protobuf.Int64Value", `null | int64`, nil) 169 p.setBuiltinParse("google.protobuf.UInt64Value", `null | uint64`, nil) 170 p.setBuiltinParse("google.protobuf.Int32Value", `null | int32`, nil) 171 p.setBuiltinParse("google.protobuf.UInt32Value", `null | uint32`, nil) 172 p.setBuiltinParse("google.protobuf.BoolValue", `null | bool`, nil) 173 p.setBuiltinParse("google.protobuf.StringValue", `null | string`, nil) 174 p.setBuiltinParse("google.protobuf.BytesValue", `null | bytes`, nil) 175 return false 176 177 // case "google/protobuf/field_mask.proto": 178 // p.setBuiltin("google.protobuf.FieldMask", "protobuf.FieldMask", nil) 179 180 // protobuf.Any 181 182 default: 183 if required { 184 failf(pos, "import %q not found", file) 185 } 186 } 187 return true 188 }