1// Copyright 2019 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package main 6 7import ( 8 "text/template" 9) 10 11func generateImplCodec() string { 12 return mustExecute(implCodecTemplate, ProtoKinds) 13} 14 15var implCodecTemplate = template.Must(template.New("").Parse(` 16{{- /* 17 IsZero is an expression testing if 'v' is the zero value. 18*/ -}} 19{{- define "IsZero" -}} 20{{if eq .WireType "Bytes" -}} 21len(v) == 0 22{{- else if or (eq .Name "Double") (eq .Name "Float") -}} 23v == 0 && !math.Signbit(float64(v)) 24{{- else -}} 25v == {{.GoType.Zero}} 26{{- end -}} 27{{- end -}} 28 29{{- /* 30 Size is an expression computing the size of 'v'. 31*/ -}} 32{{- define "Size" -}} 33{{- if .WireType.ConstSize -}} 34protowire.Size{{.WireType}}() 35{{- else if eq .WireType "Bytes" -}} 36protowire.SizeBytes(len({{.FromGoType}})) 37{{- else -}} 38protowire.Size{{.WireType}}({{.FromGoType}}) 39{{- end -}} 40{{- end -}} 41 42{{- define "SizeValue" -}} 43{{- if .WireType.ConstSize -}} 44protowire.Size{{.WireType}}() 45{{- else if eq .WireType "Bytes" -}} 46protowire.SizeBytes(len({{.FromValue}})) 47{{- else -}} 48protowire.Size{{.WireType}}({{.FromValue}}) 49{{- end -}} 50{{- end -}} 51 52{{- /* 53 Append is a set of statements appending 'v' to 'b'. 54*/ -}} 55{{- define "Append" -}} 56{{- if eq .Name "String" -}} 57b = protowire.AppendString(b, {{.FromGoType}}) 58{{- else -}} 59b = protowire.Append{{.WireType}}(b, {{.FromGoType}}) 60{{- end -}} 61{{- end -}} 62 63{{- define "AppendValue" -}} 64{{- if eq .Name "String" -}} 65b = protowire.AppendString(b, {{.FromValue}}) 66{{- else -}} 67b = protowire.Append{{.WireType}}(b, {{.FromValue}}) 68{{- end -}} 69{{- end -}} 70 71{{- define "Consume" -}} 72{{- if eq .WireType "Varint" -}} 73var v uint64 74var n int 75if len(b) >= 1 && b[0] < 0x80 { 76 v = uint64(b[0]) 77 n = 1 78} else if len(b) >= 2 && b[1] < 128 { 79 v = uint64(b[0]&0x7f) + uint64(b[1])<<7 80 n = 2 81} else { 82 v, n = protowire.ConsumeVarint(b) 83} 84{{- else -}} 85v, n := protowire.Consume{{.WireType}}(b) 86{{- end -}} 87{{- end -}} 88 89{{- range .}} 90 91{{- if .FromGoType }} 92// size{{.Name}} returns the size of wire encoding a {{.GoType}} pointer as a {{.Name}}. 93func size{{.Name}}(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { 94 {{if not .WireType.ConstSize -}} 95 v := *p.{{.GoType.PointerMethod}}() 96 {{- end}} 97 return f.tagsize + {{template "Size" .}} 98} 99 100// append{{.Name}} wire encodes a {{.GoType}} pointer as a {{.Name}}. 101func append{{.Name}}(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { 102 v := *p.{{.GoType.PointerMethod}}() 103 b = protowire.AppendVarint(b, f.wiretag) 104 {{template "Append" .}} 105 return b, nil 106} 107 108// consume{{.Name}} wire decodes a {{.GoType}} pointer as a {{.Name}}. 109func consume{{.Name}}(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { 110 if wtyp != {{.WireType.Expr}} { 111 return out, errUnknown 112 } 113 {{template "Consume" .}} 114 if n < 0 { 115 return out, errDecode 116 } 117 *p.{{.GoType.PointerMethod}}() = {{.ToGoType}} 118 out.n = n 119 return out, nil 120} 121 122var coder{{.Name}} = pointerCoderFuncs{ 123 size: size{{.Name}}, 124 marshal: append{{.Name}}, 125 unmarshal: consume{{.Name}}, 126 merge: merge{{.GoType.PointerMethod}}, 127} 128 129{{if or (eq .Name "Bytes") (eq .Name "String")}} 130// append{{.Name}}ValidateUTF8 wire encodes a {{.GoType}} pointer as a {{.Name}}. 131func append{{.Name}}ValidateUTF8(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { 132 v := *p.{{.GoType.PointerMethod}}() 133 b = protowire.AppendVarint(b, f.wiretag) 134 {{template "Append" .}} 135 if !utf8.Valid{{if eq .Name "String"}}String{{end}}(v) { 136 return b, errInvalidUTF8{} 137 } 138 return b, nil 139} 140 141// consume{{.Name}}ValidateUTF8 wire decodes a {{.GoType}} pointer as a {{.Name}}. 142func consume{{.Name}}ValidateUTF8(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { 143 if wtyp != {{.WireType.Expr}} { 144 return out, errUnknown 145 } 146 {{template "Consume" .}} 147 if n < 0 { 148 return out, errDecode 149 } 150 if !utf8.Valid(v) { 151 return out, errInvalidUTF8{} 152 } 153 *p.{{.GoType.PointerMethod}}() = {{.ToGoType}} 154 out.n = n 155 return out, nil 156} 157 158var coder{{.Name}}ValidateUTF8 = pointerCoderFuncs{ 159 size: size{{.Name}}, 160 marshal: append{{.Name}}ValidateUTF8, 161 unmarshal: consume{{.Name}}ValidateUTF8, 162 merge: merge{{.GoType.PointerMethod}}, 163} 164{{end}} 165 166// size{{.Name}}NoZero returns the size of wire encoding a {{.GoType}} pointer as a {{.Name}}. 167// The zero value is not encoded. 168func size{{.Name}}NoZero(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { 169 v := *p.{{.GoType.PointerMethod}}() 170 if {{template "IsZero" .}} { 171 return 0 172 } 173 return f.tagsize + {{template "Size" .}} 174} 175 176// append{{.Name}}NoZero wire encodes a {{.GoType}} pointer as a {{.Name}}. 177// The zero value is not encoded. 178func append{{.Name}}NoZero(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { 179 v := *p.{{.GoType.PointerMethod}}() 180 if {{template "IsZero" .}} { 181 return b, nil 182 } 183 b = protowire.AppendVarint(b, f.wiretag) 184 {{template "Append" .}} 185 return b, nil 186} 187 188{{if .ToGoTypeNoZero}} 189// consume{{.Name}}NoZero wire decodes a {{.GoType}} pointer as a {{.Name}}. 190// The zero value is not decoded. 191func consume{{.Name}}NoZero(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { 192 if wtyp != {{.WireType.Expr}} { 193 return out, errUnknown 194 } 195 {{template "Consume" .}} 196 if n < 0 { 197 return out, errDecode 198 } 199 *p.{{.GoType.PointerMethod}}() = {{.ToGoTypeNoZero}} 200 out.n = n 201 return out, nil 202} 203{{end}} 204 205var coder{{.Name}}NoZero = pointerCoderFuncs{ 206 size: size{{.Name}}NoZero, 207 marshal: append{{.Name}}NoZero, 208 unmarshal: consume{{.Name}}{{if .ToGoTypeNoZero}}NoZero{{end}}, 209 merge: merge{{.GoType.PointerMethod}}NoZero, 210} 211 212{{if or (eq .Name "Bytes") (eq .Name "String")}} 213// append{{.Name}}NoZeroValidateUTF8 wire encodes a {{.GoType}} pointer as a {{.Name}}. 214// The zero value is not encoded. 215func append{{.Name}}NoZeroValidateUTF8(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { 216 v := *p.{{.GoType.PointerMethod}}() 217 if {{template "IsZero" .}} { 218 return b, nil 219 } 220 b = protowire.AppendVarint(b, f.wiretag) 221 {{template "Append" .}} 222 if !utf8.Valid{{if eq .Name "String"}}String{{end}}(v) { 223 return b, errInvalidUTF8{} 224 } 225 return b, nil 226} 227 228{{if .ToGoTypeNoZero}} 229// consume{{.Name}}NoZeroValidateUTF8 wire decodes a {{.GoType}} pointer as a {{.Name}}. 230func consume{{.Name}}NoZeroValidateUTF8(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { 231 if wtyp != {{.WireType.Expr}} { 232 return out, errUnknown 233 } 234 {{template "Consume" .}} 235 if n < 0 { 236 return out, errDecode 237 } 238 if !utf8.Valid(v) { 239 return out, errInvalidUTF8{} 240 } 241 *p.{{.GoType.PointerMethod}}() = {{.ToGoTypeNoZero}} 242 out.n = n 243 return out, nil 244} 245{{end}} 246 247var coder{{.Name}}NoZeroValidateUTF8 = pointerCoderFuncs{ 248 size: size{{.Name}}NoZero, 249 marshal: append{{.Name}}NoZeroValidateUTF8, 250 unmarshal: consume{{.Name}}{{if .ToGoTypeNoZero}}NoZero{{end}}ValidateUTF8, 251 merge: merge{{.GoType.PointerMethod}}NoZero, 252} 253{{end}} 254 255{{- if not .NoPointer}} 256// size{{.Name}}Ptr returns the size of wire encoding a *{{.GoType}} pointer as a {{.Name}}. 257// It panics if the pointer is nil. 258func size{{.Name}}Ptr(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { 259 {{if not .WireType.ConstSize -}} 260 v := **p.{{.GoType.PointerMethod}}Ptr() 261 {{end -}} 262 return f.tagsize + {{template "Size" .}} 263} 264 265// append{{.Name}}Ptr wire encodes a *{{.GoType}} pointer as a {{.Name}}. 266// It panics if the pointer is nil. 267func append{{.Name}}Ptr(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { 268 v := **p.{{.GoType.PointerMethod}}Ptr() 269 b = protowire.AppendVarint(b, f.wiretag) 270 {{template "Append" .}} 271 return b, nil 272} 273 274// consume{{.Name}}Ptr wire decodes a *{{.GoType}} pointer as a {{.Name}}. 275func consume{{.Name}}Ptr(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { 276 if wtyp != {{.WireType.Expr}} { 277 return out, errUnknown 278 } 279 {{template "Consume" .}} 280 if n < 0 { 281 return out, errDecode 282 } 283 vp := p.{{.GoType.PointerMethod}}Ptr() 284 if *vp == nil { 285 *vp = new({{.GoType}}) 286 } 287 **vp = {{.ToGoType}} 288 out.n = n 289 return out, nil 290} 291 292var coder{{.Name}}Ptr = pointerCoderFuncs{ 293 size: size{{.Name}}Ptr, 294 marshal: append{{.Name}}Ptr, 295 unmarshal: consume{{.Name}}Ptr, 296 merge: merge{{.GoType.PointerMethod}}Ptr, 297} 298{{end}} 299 300{{if (eq .Name "String")}} 301// append{{.Name}}PtrValidateUTF8 wire encodes a *{{.GoType}} pointer as a {{.Name}}. 302// It panics if the pointer is nil. 303func append{{.Name}}PtrValidateUTF8(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { 304 v := **p.{{.GoType.PointerMethod}}Ptr() 305 b = protowire.AppendVarint(b, f.wiretag) 306 {{template "Append" .}} 307 if !utf8.Valid{{if eq .Name "String"}}String{{end}}(v) { 308 return b, errInvalidUTF8{} 309 } 310 return b, nil 311} 312 313// consume{{.Name}}PtrValidateUTF8 wire decodes a *{{.GoType}} pointer as a {{.Name}}. 314func consume{{.Name}}PtrValidateUTF8(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { 315 if wtyp != {{.WireType.Expr}} { 316 return out, errUnknown 317 } 318 {{template "Consume" .}} 319 if n < 0 { 320 return out, errDecode 321 } 322 if !utf8.Valid(v) { 323 return out, errInvalidUTF8{} 324 } 325 vp := p.{{.GoType.PointerMethod}}Ptr() 326 if *vp == nil { 327 *vp = new({{.GoType}}) 328 } 329 **vp = {{.ToGoType}} 330 out.n = n 331 return out, nil 332} 333 334var coder{{.Name}}PtrValidateUTF8 = pointerCoderFuncs{ 335 size: size{{.Name}}Ptr, 336 marshal: append{{.Name}}PtrValidateUTF8, 337 unmarshal: consume{{.Name}}PtrValidateUTF8, 338 merge: merge{{.GoType.PointerMethod}}Ptr, 339} 340{{end}} 341 342// size{{.Name}}Slice returns the size of wire encoding a []{{.GoType}} pointer as a repeated {{.Name}}. 343func size{{.Name}}Slice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { 344 s := *p.{{.GoType.PointerMethod}}Slice() 345 {{if .WireType.ConstSize -}} 346 size = len(s) * (f.tagsize + {{template "Size" .}}) 347 {{- else -}} 348 for _, v := range s { 349 size += f.tagsize + {{template "Size" .}} 350 } 351 {{- end}} 352 return size 353} 354 355// append{{.Name}}Slice encodes a []{{.GoType}} pointer as a repeated {{.Name}}. 356func append{{.Name}}Slice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { 357 s := *p.{{.GoType.PointerMethod}}Slice() 358 for _, v := range s { 359 b = protowire.AppendVarint(b, f.wiretag) 360 {{template "Append" .}} 361 } 362 return b, nil 363} 364 365// consume{{.Name}}Slice wire decodes a []{{.GoType}} pointer as a repeated {{.Name}}. 366func consume{{.Name}}Slice(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { 367 sp := p.{{.GoType.PointerMethod}}Slice() 368 {{- if .WireType.Packable}} 369 if wtyp == protowire.BytesType { 370 s := *sp 371 b, n := protowire.ConsumeBytes(b) 372 if n < 0 { 373 return out, errDecode 374 } 375 for len(b) > 0 { 376 {{template "Consume" .}} 377 if n < 0 { 378 return out, errDecode 379 } 380 s = append(s, {{.ToGoType}}) 381 b = b[n:] 382 } 383 *sp = s 384 out.n = n 385 return out, nil 386 } 387 {{- end}} 388 if wtyp != {{.WireType.Expr}} { 389 return out, errUnknown 390 } 391 {{template "Consume" .}} 392 if n < 0 { 393 return out, errDecode 394 } 395 *sp = append(*sp, {{.ToGoType}}) 396 out.n = n 397 return out, nil 398} 399 400var coder{{.Name}}Slice = pointerCoderFuncs{ 401 size: size{{.Name}}Slice, 402 marshal: append{{.Name}}Slice, 403 unmarshal: consume{{.Name}}Slice, 404 merge: merge{{.GoType.PointerMethod}}Slice, 405} 406 407{{if or (eq .Name "Bytes") (eq .Name "String")}} 408// append{{.Name}}SliceValidateUTF8 encodes a []{{.GoType}} pointer as a repeated {{.Name}}. 409func append{{.Name}}SliceValidateUTF8(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { 410 s := *p.{{.GoType.PointerMethod}}Slice() 411 for _, v := range s { 412 b = protowire.AppendVarint(b, f.wiretag) 413 {{template "Append" .}} 414 if !utf8.Valid{{if eq .Name "String"}}String{{end}}(v) { 415 return b, errInvalidUTF8{} 416 } 417 } 418 return b, nil 419} 420 421// consume{{.Name}}SliceValidateUTF8 wire decodes a []{{.GoType}} pointer as a repeated {{.Name}}. 422func consume{{.Name}}SliceValidateUTF8(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { 423 if wtyp != {{.WireType.Expr}} { 424 return out, errUnknown 425 } 426 {{template "Consume" .}} 427 if n < 0 { 428 return out, errDecode 429 } 430 if !utf8.Valid(v) { 431 return out, errInvalidUTF8{} 432 } 433 sp := p.{{.GoType.PointerMethod}}Slice() 434 *sp = append(*sp, {{.ToGoType}}) 435 out.n = n 436 return out, nil 437} 438 439var coder{{.Name}}SliceValidateUTF8 = pointerCoderFuncs{ 440 size: size{{.Name}}Slice, 441 marshal: append{{.Name}}SliceValidateUTF8, 442 unmarshal: consume{{.Name}}SliceValidateUTF8, 443 merge: merge{{.GoType.PointerMethod}}Slice, 444} 445{{end}} 446 447{{if or (eq .WireType "Varint") (eq .WireType "Fixed32") (eq .WireType "Fixed64")}} 448// size{{.Name}}PackedSlice returns the size of wire encoding a []{{.GoType}} pointer as a packed repeated {{.Name}}. 449func size{{.Name}}PackedSlice(p pointer, f *coderFieldInfo, opts marshalOptions) (size int) { 450 s := *p.{{.GoType.PointerMethod}}Slice() 451 if len(s) == 0 { 452 return 0 453 } 454 {{if .WireType.ConstSize -}} 455 n := len(s) * {{template "Size" .}} 456 {{- else -}} 457 n := 0 458 for _, v := range s { 459 n += {{template "Size" .}} 460 } 461 {{- end}} 462 return f.tagsize + protowire.SizeBytes(n) 463} 464 465// append{{.Name}}PackedSlice encodes a []{{.GoType}} pointer as a packed repeated {{.Name}}. 466func append{{.Name}}PackedSlice(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { 467 s := *p.{{.GoType.PointerMethod}}Slice() 468 if len(s) == 0 { 469 return b, nil 470 } 471 b = protowire.AppendVarint(b, f.wiretag) 472 {{if .WireType.ConstSize -}} 473 n := len(s) * {{template "Size" .}} 474 {{- else -}} 475 n := 0 476 for _, v := range s { 477 n += {{template "Size" .}} 478 } 479 {{- end}} 480 b = protowire.AppendVarint(b, uint64(n)) 481 for _, v := range s { 482 {{template "Append" .}} 483 } 484 return b, nil 485} 486 487var coder{{.Name}}PackedSlice = pointerCoderFuncs{ 488 size: size{{.Name}}PackedSlice, 489 marshal: append{{.Name}}PackedSlice, 490 unmarshal: consume{{.Name}}Slice, 491 merge: merge{{.GoType.PointerMethod}}Slice, 492} 493{{end}} 494 495{{end -}} 496 497{{- if not .NoValueCodec}} 498// size{{.Name}}Value returns the size of wire encoding a {{.GoType}} value as a {{.Name}}. 499func size{{.Name}}Value(v protoreflect.Value, tagsize int, opts marshalOptions) int { 500 return tagsize + {{template "SizeValue" .}} 501} 502 503// append{{.Name}}Value encodes a {{.GoType}} value as a {{.Name}}. 504func append{{.Name}}Value(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { 505 b = protowire.AppendVarint(b, wiretag) 506 {{template "AppendValue" .}} 507 return b, nil 508} 509 510// consume{{.Name}}Value decodes a {{.GoType}} value as a {{.Name}}. 511func consume{{.Name}}Value(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { 512 if wtyp != {{.WireType.Expr}} { 513 return protoreflect.Value{}, out, errUnknown 514 } 515 {{template "Consume" .}} 516 if n < 0 { 517 return protoreflect.Value{}, out, errDecode 518 } 519 out.n = n 520 return {{.ToValue}}, out, nil 521} 522 523var coder{{.Name}}Value = valueCoderFuncs{ 524 size: size{{.Name}}Value, 525 marshal: append{{.Name}}Value, 526 unmarshal: consume{{.Name}}Value, 527{{- if (eq .Name "Bytes")}} 528 merge: mergeBytesValue, 529{{- else}} 530 merge: mergeScalarValue, 531{{- end}} 532} 533 534{{if (eq .Name "String")}} 535// append{{.Name}}ValueValidateUTF8 encodes a {{.GoType}} value as a {{.Name}}. 536func append{{.Name}}ValueValidateUTF8(b []byte, v protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { 537 b = protowire.AppendVarint(b, wiretag) 538 {{template "AppendValue" .}} 539 if !utf8.ValidString({{.FromValue}}) { 540 return b, errInvalidUTF8{} 541 } 542 return b, nil 543} 544 545// consume{{.Name}}ValueValidateUTF8 decodes a {{.GoType}} value as a {{.Name}}. 546func consume{{.Name}}ValueValidateUTF8(b []byte, _ protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { 547 if wtyp != {{.WireType.Expr}} { 548 return protoreflect.Value{}, out, errUnknown 549 } 550 {{template "Consume" .}} 551 if n < 0 { 552 return protoreflect.Value{}, out, errDecode 553 } 554 if !utf8.Valid(v) { 555 return protoreflect.Value{}, out, errInvalidUTF8{} 556 } 557 out.n = n 558 return {{.ToValue}}, out, nil 559} 560 561var coder{{.Name}}ValueValidateUTF8 = valueCoderFuncs{ 562 size: size{{.Name}}Value, 563 marshal: append{{.Name}}ValueValidateUTF8, 564 unmarshal: consume{{.Name}}ValueValidateUTF8, 565 merge: mergeScalarValue, 566} 567{{end}} 568 569// size{{.Name}}SliceValue returns the size of wire encoding a []{{.GoType}} value as a repeated {{.Name}}. 570func size{{.Name}}SliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { 571 list := listv.List() 572 {{if .WireType.ConstSize -}} 573 size = list.Len() * (tagsize + {{template "SizeValue" .}}) 574 {{- else -}} 575 for i, llen := 0, list.Len(); i < llen; i++ { 576 v := list.Get(i) 577 size += tagsize + {{template "SizeValue" .}} 578 } 579 {{- end}} 580 return size 581} 582 583// append{{.Name}}SliceValue encodes a []{{.GoType}} value as a repeated {{.Name}}. 584func append{{.Name}}SliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { 585 list := listv.List() 586 for i, llen := 0, list.Len(); i < llen; i++ { 587 v := list.Get(i) 588 b = protowire.AppendVarint(b, wiretag) 589 {{template "AppendValue" .}} 590 } 591 return b, nil 592} 593 594// consume{{.Name}}SliceValue wire decodes a []{{.GoType}} value as a repeated {{.Name}}. 595func consume{{.Name}}SliceValue(b []byte, listv protoreflect.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ protoreflect.Value, out unmarshalOutput, err error) { 596 list := listv.List() 597 {{- if .WireType.Packable}} 598 if wtyp == protowire.BytesType { 599 b, n := protowire.ConsumeBytes(b) 600 if n < 0 { 601 return protoreflect.Value{}, out, errDecode 602 } 603 for len(b) > 0 { 604 {{template "Consume" .}} 605 if n < 0 { 606 return protoreflect.Value{}, out, errDecode 607 } 608 list.Append({{.ToValue}}) 609 b = b[n:] 610 } 611 out.n = n 612 return listv, out, nil 613 } 614 {{- end}} 615 if wtyp != {{.WireType.Expr}} { 616 return protoreflect.Value{}, out, errUnknown 617 } 618 {{template "Consume" .}} 619 if n < 0 { 620 return protoreflect.Value{}, out, errDecode 621 } 622 list.Append({{.ToValue}}) 623 out.n = n 624 return listv, out, nil 625} 626 627var coder{{.Name}}SliceValue = valueCoderFuncs{ 628 size: size{{.Name}}SliceValue, 629 marshal: append{{.Name}}SliceValue, 630 unmarshal: consume{{.Name}}SliceValue, 631{{- if (eq .Name "Bytes")}} 632 merge: mergeBytesListValue, 633{{- else}} 634 merge: mergeListValue, 635{{- end}} 636} 637 638{{if or (eq .WireType "Varint") (eq .WireType "Fixed32") (eq .WireType "Fixed64")}} 639// size{{.Name}}PackedSliceValue returns the size of wire encoding a []{{.GoType}} value as a packed repeated {{.Name}}. 640func size{{.Name}}PackedSliceValue(listv protoreflect.Value, tagsize int, opts marshalOptions) (size int) { 641 list := listv.List() 642 llen := list.Len() 643 if llen == 0 { 644 return 0 645 } 646 {{if .WireType.ConstSize -}} 647 n := llen * {{template "SizeValue" .}} 648 {{- else -}} 649 n := 0 650 for i, llen := 0, llen; i < llen; i++ { 651 v := list.Get(i) 652 n += {{template "SizeValue" .}} 653 } 654 {{- end}} 655 return tagsize + protowire.SizeBytes(n) 656} 657 658// append{{.Name}}PackedSliceValue encodes a []{{.GoType}} value as a packed repeated {{.Name}}. 659func append{{.Name}}PackedSliceValue(b []byte, listv protoreflect.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { 660 list := listv.List() 661 llen := list.Len() 662 if llen == 0 { 663 return b, nil 664 } 665 b = protowire.AppendVarint(b, wiretag) 666 {{if .WireType.ConstSize -}} 667 n := llen * {{template "SizeValue" .}} 668 {{- else -}} 669 n := 0 670 for i := 0; i < llen; i++ { 671 v := list.Get(i) 672 n += {{template "SizeValue" .}} 673 } 674 {{- end}} 675 b = protowire.AppendVarint(b, uint64(n)) 676 for i := 0; i < llen; i++ { 677 v := list.Get(i) 678 {{template "AppendValue" .}} 679 } 680 return b, nil 681} 682 683var coder{{.Name}}PackedSliceValue = valueCoderFuncs{ 684 size: size{{.Name}}PackedSliceValue, 685 marshal: append{{.Name}}PackedSliceValue, 686 unmarshal: consume{{.Name}}SliceValue, 687 merge: mergeListValue, 688} 689{{end}} 690 691{{- end}}{{/* if not .NoValueCodec */}} 692 693{{end -}} 694 695// We append to an empty array rather than a nil []byte to get non-nil zero-length byte slices. 696var emptyBuf [0]byte 697 698var wireTypes = map[protoreflect.Kind]protowire.Type{ 699{{range . -}} 700 protoreflect.{{.Name}}Kind: {{.WireType.Expr}}, 701{{end}} 702} 703`)) 704 705func generateImplMessage() string { 706 return mustExecute(implMessageTemplate, []string{"messageState", "messageReflectWrapper"}) 707} 708 709var implMessageTemplate = template.Must(template.New("").Parse(` 710{{range . -}} 711func (m *{{.}}) Descriptor() protoreflect.MessageDescriptor { 712 return m.messageInfo().Desc 713} 714func (m *{{.}}) Type() protoreflect.MessageType { 715 return m.messageInfo() 716} 717func (m *{{.}}) New() protoreflect.Message { 718 return m.messageInfo().New() 719} 720func (m *{{.}}) Interface() protoreflect.ProtoMessage { 721 {{if eq . "messageState" -}} 722 return m.protoUnwrap().(protoreflect.ProtoMessage) 723 {{- else -}} 724 if m, ok := m.protoUnwrap().(protoreflect.ProtoMessage); ok { 725 return m 726 } 727 return (*messageIfaceWrapper)(m) 728 {{- end -}} 729} 730func (m *{{.}}) protoUnwrap() interface{} { 731 return m.pointer().AsIfaceOf(m.messageInfo().GoReflectType.Elem()) 732} 733func (m *{{.}}) ProtoMethods() *protoiface.Methods { 734 m.messageInfo().init() 735 return &m.messageInfo().methods 736} 737 738// ProtoMessageInfo is a pseudo-internal API for allowing the v1 code 739// to be able to retrieve a v2 MessageInfo struct. 740// 741// WARNING: This method is exempt from the compatibility promise and 742// may be removed in the future without warning. 743func (m *{{.}}) ProtoMessageInfo() *MessageInfo { 744 return m.messageInfo() 745} 746 747func (m *{{.}}) Range(f func(protoreflect.FieldDescriptor, protoreflect.Value) bool) { 748 m.messageInfo().init() 749 for _, ri := range m.messageInfo().rangeInfos { 750 switch ri := ri.(type) { 751 case *fieldInfo: 752 if ri.has(m.pointer()) { 753 if !f(ri.fieldDesc, ri.get(m.pointer())) { 754 return 755 } 756 } 757 case *oneofInfo: 758 if n := ri.which(m.pointer()); n > 0 { 759 fi := m.messageInfo().fields[n] 760 if !f(fi.fieldDesc, fi.get(m.pointer())) { 761 return 762 } 763 } 764 } 765 } 766 m.messageInfo().extensionMap(m.pointer()).Range(f) 767} 768func (m *{{.}}) Has(fd protoreflect.FieldDescriptor) bool { 769 m.messageInfo().init() 770 if fi, xt := m.messageInfo().checkField(fd); fi != nil { 771 return fi.has(m.pointer()) 772 } else { 773 return m.messageInfo().extensionMap(m.pointer()).Has(xt) 774 } 775} 776func (m *{{.}}) Clear(fd protoreflect.FieldDescriptor) { 777 m.messageInfo().init() 778 if fi, xt := m.messageInfo().checkField(fd); fi != nil { 779 fi.clear(m.pointer()) 780 } else { 781 m.messageInfo().extensionMap(m.pointer()).Clear(xt) 782 } 783} 784func (m *{{.}}) Get(fd protoreflect.FieldDescriptor) protoreflect.Value { 785 m.messageInfo().init() 786 if fi, xt := m.messageInfo().checkField(fd); fi != nil { 787 return fi.get(m.pointer()) 788 } else { 789 return m.messageInfo().extensionMap(m.pointer()).Get(xt) 790 } 791} 792func (m *{{.}}) Set(fd protoreflect.FieldDescriptor, v protoreflect.Value) { 793 m.messageInfo().init() 794 if fi, xt := m.messageInfo().checkField(fd); fi != nil { 795 fi.set(m.pointer(), v) 796 } else { 797 m.messageInfo().extensionMap(m.pointer()).Set(xt, v) 798 } 799} 800func (m *{{.}}) Mutable(fd protoreflect.FieldDescriptor) protoreflect.Value { 801 m.messageInfo().init() 802 if fi, xt := m.messageInfo().checkField(fd); fi != nil { 803 return fi.mutable(m.pointer()) 804 } else { 805 return m.messageInfo().extensionMap(m.pointer()).Mutable(xt) 806 } 807} 808func (m *{{.}}) NewField(fd protoreflect.FieldDescriptor) protoreflect.Value { 809 m.messageInfo().init() 810 if fi, xt := m.messageInfo().checkField(fd); fi != nil { 811 return fi.newField() 812 } else { 813 return xt.New() 814 } 815} 816func (m *{{.}}) WhichOneof(od protoreflect.OneofDescriptor) protoreflect.FieldDescriptor { 817 m.messageInfo().init() 818 if oi := m.messageInfo().oneofs[od.Name()]; oi != nil && oi.oneofDesc == od { 819 return od.Fields().ByNumber(oi.which(m.pointer())) 820 } 821 panic("invalid oneof descriptor " + string(od.FullName()) + " for message " + string(m.Descriptor().FullName())) 822} 823func (m *{{.}}) GetUnknown() protoreflect.RawFields { 824 m.messageInfo().init() 825 return m.messageInfo().getUnknown(m.pointer()) 826} 827func (m *{{.}}) SetUnknown(b protoreflect.RawFields) { 828 m.messageInfo().init() 829 m.messageInfo().setUnknown(m.pointer(), b) 830} 831func (m *{{.}}) IsValid() bool { 832 return !m.pointer().IsNil() 833} 834 835{{end}} 836`)) 837 838func generateImplMerge() string { 839 return mustExecute(implMergeTemplate, GoTypes) 840} 841 842var implMergeTemplate = template.Must(template.New("").Parse(` 843{{range .}} 844{{if ne . "[]byte"}} 845func merge{{.PointerMethod}}(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { 846 *dst.{{.PointerMethod}}() = *src.{{.PointerMethod}}() 847} 848 849func merge{{.PointerMethod}}NoZero(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { 850 v := *src.{{.PointerMethod}}() 851 if v != {{.Zero}} { 852 *dst.{{.PointerMethod}}() = v 853 } 854} 855 856func merge{{.PointerMethod}}Ptr(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { 857 p := *src.{{.PointerMethod}}Ptr() 858 if p != nil { 859 v := *p 860 *dst.{{.PointerMethod}}Ptr() = &v 861 } 862} 863 864func merge{{.PointerMethod}}Slice(dst, src pointer, _ *coderFieldInfo, _ mergeOptions) { 865 ds := dst.{{.PointerMethod}}Slice() 866 ss := src.{{.PointerMethod}}Slice() 867 *ds = append(*ds, *ss...) 868} 869 870{{end}} 871{{end}} 872`)) 873