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 impl 6 7import ( 8 "fmt" 9 "reflect" 10 "sync" 11 12 "google.golang.org/protobuf/encoding/protowire" 13 "google.golang.org/protobuf/proto" 14 pref "google.golang.org/protobuf/reflect/protoreflect" 15 preg "google.golang.org/protobuf/reflect/protoregistry" 16 piface "google.golang.org/protobuf/runtime/protoiface" 17) 18 19type errInvalidUTF8 struct{} 20 21func (errInvalidUTF8) Error() string { return "string field contains invalid UTF-8" } 22func (errInvalidUTF8) InvalidUTF8() bool { return true } 23 24// initOneofFieldCoders initializes the fast-path functions for the fields in a oneof. 25// 26// For size, marshal, and isInit operations, functions are set only on the first field 27// in the oneof. The functions are called when the oneof is non-nil, and will dispatch 28// to the appropriate field-specific function as necessary. 29// 30// The unmarshal function is set on each field individually as usual. 31func (mi *MessageInfo) initOneofFieldCoders(od pref.OneofDescriptor, si structInfo) { 32 fs := si.oneofsByName[od.Name()] 33 ft := fs.Type 34 oneofFields := make(map[reflect.Type]*coderFieldInfo) 35 needIsInit := false 36 fields := od.Fields() 37 for i, lim := 0, fields.Len(); i < lim; i++ { 38 fd := od.Fields().Get(i) 39 num := fd.Number() 40 // Make a copy of the original coderFieldInfo for use in unmarshaling. 41 // 42 // oneofFields[oneofType].funcs.marshal is the field-specific marshal function. 43 // 44 // mi.coderFields[num].marshal is set on only the first field in the oneof, 45 // and dispatches to the field-specific marshaler in oneofFields. 46 cf := *mi.coderFields[num] 47 ot := si.oneofWrappersByNumber[num] 48 cf.ft = ot.Field(0).Type 49 cf.mi, cf.funcs = fieldCoder(fd, cf.ft) 50 oneofFields[ot] = &cf 51 if cf.funcs.isInit != nil { 52 needIsInit = true 53 } 54 mi.coderFields[num].funcs.unmarshal = func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) { 55 var vw reflect.Value // pointer to wrapper type 56 vi := p.AsValueOf(ft).Elem() // oneof field value of interface kind 57 if !vi.IsNil() && !vi.Elem().IsNil() && vi.Elem().Elem().Type() == ot { 58 vw = vi.Elem() 59 } else { 60 vw = reflect.New(ot) 61 } 62 out, err := cf.funcs.unmarshal(b, pointerOfValue(vw).Apply(zeroOffset), wtyp, &cf, opts) 63 if err != nil { 64 return out, err 65 } 66 vi.Set(vw) 67 return out, nil 68 } 69 } 70 getInfo := func(p pointer) (pointer, *coderFieldInfo) { 71 v := p.AsValueOf(ft).Elem() 72 if v.IsNil() { 73 return pointer{}, nil 74 } 75 v = v.Elem() // interface -> *struct 76 if v.IsNil() { 77 return pointer{}, nil 78 } 79 return pointerOfValue(v).Apply(zeroOffset), oneofFields[v.Elem().Type()] 80 } 81 first := mi.coderFields[od.Fields().Get(0).Number()] 82 first.funcs.size = func(p pointer, _ *coderFieldInfo, opts marshalOptions) int { 83 p, info := getInfo(p) 84 if info == nil || info.funcs.size == nil { 85 return 0 86 } 87 return info.funcs.size(p, info, opts) 88 } 89 first.funcs.marshal = func(b []byte, p pointer, _ *coderFieldInfo, opts marshalOptions) ([]byte, error) { 90 p, info := getInfo(p) 91 if info == nil || info.funcs.marshal == nil { 92 return b, nil 93 } 94 return info.funcs.marshal(b, p, info, opts) 95 } 96 first.funcs.merge = func(dst, src pointer, _ *coderFieldInfo, opts mergeOptions) { 97 srcp, srcinfo := getInfo(src) 98 if srcinfo == nil || srcinfo.funcs.merge == nil { 99 return 100 } 101 dstp, dstinfo := getInfo(dst) 102 if dstinfo != srcinfo { 103 dst.AsValueOf(ft).Elem().Set(reflect.New(src.AsValueOf(ft).Elem().Elem().Elem().Type())) 104 dstp = pointerOfValue(dst.AsValueOf(ft).Elem().Elem()).Apply(zeroOffset) 105 } 106 srcinfo.funcs.merge(dstp, srcp, srcinfo, opts) 107 } 108 if needIsInit { 109 first.funcs.isInit = func(p pointer, _ *coderFieldInfo) error { 110 p, info := getInfo(p) 111 if info == nil || info.funcs.isInit == nil { 112 return nil 113 } 114 return info.funcs.isInit(p, info) 115 } 116 } 117} 118 119func makeWeakMessageFieldCoder(fd pref.FieldDescriptor) pointerCoderFuncs { 120 var once sync.Once 121 var messageType pref.MessageType 122 lazyInit := func() { 123 once.Do(func() { 124 messageName := fd.Message().FullName() 125 messageType, _ = preg.GlobalTypes.FindMessageByName(messageName) 126 }) 127 } 128 129 return pointerCoderFuncs{ 130 size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int { 131 m, ok := p.WeakFields().get(f.num) 132 if !ok { 133 return 0 134 } 135 lazyInit() 136 if messageType == nil { 137 panic(fmt.Sprintf("weak message %v is not linked in", fd.Message().FullName())) 138 } 139 return sizeMessage(m, f.tagsize, opts) 140 }, 141 marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { 142 m, ok := p.WeakFields().get(f.num) 143 if !ok { 144 return b, nil 145 } 146 lazyInit() 147 if messageType == nil { 148 panic(fmt.Sprintf("weak message %v is not linked in", fd.Message().FullName())) 149 } 150 return appendMessage(b, m, f.wiretag, opts) 151 }, 152 unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) { 153 fs := p.WeakFields() 154 m, ok := fs.get(f.num) 155 if !ok { 156 lazyInit() 157 if messageType == nil { 158 return unmarshalOutput{}, errUnknown 159 } 160 m = messageType.New().Interface() 161 fs.set(f.num, m) 162 } 163 return consumeMessage(b, m, wtyp, opts) 164 }, 165 isInit: func(p pointer, f *coderFieldInfo) error { 166 m, ok := p.WeakFields().get(f.num) 167 if !ok { 168 return nil 169 } 170 return proto.CheckInitialized(m) 171 }, 172 merge: func(dst, src pointer, f *coderFieldInfo, opts mergeOptions) { 173 sm, ok := src.WeakFields().get(f.num) 174 if !ok { 175 return 176 } 177 dm, ok := dst.WeakFields().get(f.num) 178 if !ok { 179 lazyInit() 180 if messageType == nil { 181 panic(fmt.Sprintf("weak message %v is not linked in", fd.Message().FullName())) 182 } 183 dm = messageType.New().Interface() 184 dst.WeakFields().set(f.num, dm) 185 } 186 opts.Merge(dm, sm) 187 }, 188 } 189} 190 191func makeMessageFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs { 192 if mi := getMessageInfo(ft); mi != nil { 193 funcs := pointerCoderFuncs{ 194 size: sizeMessageInfo, 195 marshal: appendMessageInfo, 196 unmarshal: consumeMessageInfo, 197 merge: mergeMessage, 198 } 199 if needsInitCheck(mi.Desc) { 200 funcs.isInit = isInitMessageInfo 201 } 202 return funcs 203 } else { 204 return pointerCoderFuncs{ 205 size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int { 206 m := asMessage(p.AsValueOf(ft).Elem()) 207 return sizeMessage(m, f.tagsize, opts) 208 }, 209 marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { 210 m := asMessage(p.AsValueOf(ft).Elem()) 211 return appendMessage(b, m, f.wiretag, opts) 212 }, 213 unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) { 214 mp := p.AsValueOf(ft).Elem() 215 if mp.IsNil() { 216 mp.Set(reflect.New(ft.Elem())) 217 } 218 return consumeMessage(b, asMessage(mp), wtyp, opts) 219 }, 220 isInit: func(p pointer, f *coderFieldInfo) error { 221 m := asMessage(p.AsValueOf(ft).Elem()) 222 return proto.CheckInitialized(m) 223 }, 224 merge: mergeMessage, 225 } 226 } 227} 228 229func sizeMessageInfo(p pointer, f *coderFieldInfo, opts marshalOptions) int { 230 return protowire.SizeBytes(f.mi.sizePointer(p.Elem(), opts)) + f.tagsize 231} 232 233func appendMessageInfo(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { 234 b = protowire.AppendVarint(b, f.wiretag) 235 b = protowire.AppendVarint(b, uint64(f.mi.sizePointer(p.Elem(), opts))) 236 return f.mi.marshalAppendPointer(b, p.Elem(), opts) 237} 238 239func consumeMessageInfo(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { 240 if wtyp != protowire.BytesType { 241 return out, errUnknown 242 } 243 v, n := protowire.ConsumeBytes(b) 244 if n < 0 { 245 return out, protowire.ParseError(n) 246 } 247 if p.Elem().IsNil() { 248 p.SetPointer(pointerOfValue(reflect.New(f.mi.GoReflectType.Elem()))) 249 } 250 o, err := f.mi.unmarshalPointer(v, p.Elem(), 0, opts) 251 if err != nil { 252 return out, err 253 } 254 out.n = n 255 out.initialized = o.initialized 256 return out, nil 257} 258 259func isInitMessageInfo(p pointer, f *coderFieldInfo) error { 260 return f.mi.checkInitializedPointer(p.Elem()) 261} 262 263func sizeMessage(m proto.Message, tagsize int, _ marshalOptions) int { 264 return protowire.SizeBytes(proto.Size(m)) + tagsize 265} 266 267func appendMessage(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) { 268 b = protowire.AppendVarint(b, wiretag) 269 b = protowire.AppendVarint(b, uint64(proto.Size(m))) 270 return opts.Options().MarshalAppend(b, m) 271} 272 273func consumeMessage(b []byte, m proto.Message, wtyp protowire.Type, opts unmarshalOptions) (out unmarshalOutput, err error) { 274 if wtyp != protowire.BytesType { 275 return out, errUnknown 276 } 277 v, n := protowire.ConsumeBytes(b) 278 if n < 0 { 279 return out, protowire.ParseError(n) 280 } 281 o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{ 282 Buf: v, 283 Message: m.ProtoReflect(), 284 }) 285 if err != nil { 286 return out, err 287 } 288 out.n = n 289 out.initialized = o.Flags&piface.UnmarshalInitialized != 0 290 return out, nil 291} 292 293func sizeMessageValue(v pref.Value, tagsize int, opts marshalOptions) int { 294 m := v.Message().Interface() 295 return sizeMessage(m, tagsize, opts) 296} 297 298func appendMessageValue(b []byte, v pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { 299 m := v.Message().Interface() 300 return appendMessage(b, m, wiretag, opts) 301} 302 303func consumeMessageValue(b []byte, v pref.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (pref.Value, unmarshalOutput, error) { 304 m := v.Message().Interface() 305 out, err := consumeMessage(b, m, wtyp, opts) 306 return v, out, err 307} 308 309func isInitMessageValue(v pref.Value) error { 310 m := v.Message().Interface() 311 return proto.CheckInitialized(m) 312} 313 314var coderMessageValue = valueCoderFuncs{ 315 size: sizeMessageValue, 316 marshal: appendMessageValue, 317 unmarshal: consumeMessageValue, 318 isInit: isInitMessageValue, 319 merge: mergeMessageValue, 320} 321 322func sizeGroupValue(v pref.Value, tagsize int, opts marshalOptions) int { 323 m := v.Message().Interface() 324 return sizeGroup(m, tagsize, opts) 325} 326 327func appendGroupValue(b []byte, v pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { 328 m := v.Message().Interface() 329 return appendGroup(b, m, wiretag, opts) 330} 331 332func consumeGroupValue(b []byte, v pref.Value, num protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (pref.Value, unmarshalOutput, error) { 333 m := v.Message().Interface() 334 out, err := consumeGroup(b, m, num, wtyp, opts) 335 return v, out, err 336} 337 338var coderGroupValue = valueCoderFuncs{ 339 size: sizeGroupValue, 340 marshal: appendGroupValue, 341 unmarshal: consumeGroupValue, 342 isInit: isInitMessageValue, 343 merge: mergeMessageValue, 344} 345 346func makeGroupFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs { 347 num := fd.Number() 348 if mi := getMessageInfo(ft); mi != nil { 349 funcs := pointerCoderFuncs{ 350 size: sizeGroupType, 351 marshal: appendGroupType, 352 unmarshal: consumeGroupType, 353 merge: mergeMessage, 354 } 355 if needsInitCheck(mi.Desc) { 356 funcs.isInit = isInitMessageInfo 357 } 358 return funcs 359 } else { 360 return pointerCoderFuncs{ 361 size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int { 362 m := asMessage(p.AsValueOf(ft).Elem()) 363 return sizeGroup(m, f.tagsize, opts) 364 }, 365 marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { 366 m := asMessage(p.AsValueOf(ft).Elem()) 367 return appendGroup(b, m, f.wiretag, opts) 368 }, 369 unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) { 370 mp := p.AsValueOf(ft).Elem() 371 if mp.IsNil() { 372 mp.Set(reflect.New(ft.Elem())) 373 } 374 return consumeGroup(b, asMessage(mp), num, wtyp, opts) 375 }, 376 isInit: func(p pointer, f *coderFieldInfo) error { 377 m := asMessage(p.AsValueOf(ft).Elem()) 378 return proto.CheckInitialized(m) 379 }, 380 merge: mergeMessage, 381 } 382 } 383} 384 385func sizeGroupType(p pointer, f *coderFieldInfo, opts marshalOptions) int { 386 return 2*f.tagsize + f.mi.sizePointer(p.Elem(), opts) 387} 388 389func appendGroupType(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { 390 b = protowire.AppendVarint(b, f.wiretag) // start group 391 b, err := f.mi.marshalAppendPointer(b, p.Elem(), opts) 392 b = protowire.AppendVarint(b, f.wiretag+1) // end group 393 return b, err 394} 395 396func consumeGroupType(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { 397 if wtyp != protowire.StartGroupType { 398 return out, errUnknown 399 } 400 if p.Elem().IsNil() { 401 p.SetPointer(pointerOfValue(reflect.New(f.mi.GoReflectType.Elem()))) 402 } 403 return f.mi.unmarshalPointer(b, p.Elem(), f.num, opts) 404} 405 406func sizeGroup(m proto.Message, tagsize int, _ marshalOptions) int { 407 return 2*tagsize + proto.Size(m) 408} 409 410func appendGroup(b []byte, m proto.Message, wiretag uint64, opts marshalOptions) ([]byte, error) { 411 b = protowire.AppendVarint(b, wiretag) // start group 412 b, err := opts.Options().MarshalAppend(b, m) 413 b = protowire.AppendVarint(b, wiretag+1) // end group 414 return b, err 415} 416 417func consumeGroup(b []byte, m proto.Message, num protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (out unmarshalOutput, err error) { 418 if wtyp != protowire.StartGroupType { 419 return out, errUnknown 420 } 421 b, n := protowire.ConsumeGroup(num, b) 422 if n < 0 { 423 return out, protowire.ParseError(n) 424 } 425 o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{ 426 Buf: b, 427 Message: m.ProtoReflect(), 428 }) 429 if err != nil { 430 return out, err 431 } 432 out.n = n 433 out.initialized = o.Flags&piface.UnmarshalInitialized != 0 434 return out, nil 435} 436 437func makeMessageSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs { 438 if mi := getMessageInfo(ft); mi != nil { 439 funcs := pointerCoderFuncs{ 440 size: sizeMessageSliceInfo, 441 marshal: appendMessageSliceInfo, 442 unmarshal: consumeMessageSliceInfo, 443 merge: mergeMessageSlice, 444 } 445 if needsInitCheck(mi.Desc) { 446 funcs.isInit = isInitMessageSliceInfo 447 } 448 return funcs 449 } 450 return pointerCoderFuncs{ 451 size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int { 452 return sizeMessageSlice(p, ft, f.tagsize, opts) 453 }, 454 marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { 455 return appendMessageSlice(b, p, f.wiretag, ft, opts) 456 }, 457 unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) { 458 return consumeMessageSlice(b, p, ft, wtyp, opts) 459 }, 460 isInit: func(p pointer, f *coderFieldInfo) error { 461 return isInitMessageSlice(p, ft) 462 }, 463 merge: mergeMessageSlice, 464 } 465} 466 467func sizeMessageSliceInfo(p pointer, f *coderFieldInfo, opts marshalOptions) int { 468 s := p.PointerSlice() 469 n := 0 470 for _, v := range s { 471 n += protowire.SizeBytes(f.mi.sizePointer(v, opts)) + f.tagsize 472 } 473 return n 474} 475 476func appendMessageSliceInfo(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { 477 s := p.PointerSlice() 478 var err error 479 for _, v := range s { 480 b = protowire.AppendVarint(b, f.wiretag) 481 siz := f.mi.sizePointer(v, opts) 482 b = protowire.AppendVarint(b, uint64(siz)) 483 b, err = f.mi.marshalAppendPointer(b, v, opts) 484 if err != nil { 485 return b, err 486 } 487 } 488 return b, nil 489} 490 491func consumeMessageSliceInfo(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (out unmarshalOutput, err error) { 492 if wtyp != protowire.BytesType { 493 return out, errUnknown 494 } 495 v, n := protowire.ConsumeBytes(b) 496 if n < 0 { 497 return out, protowire.ParseError(n) 498 } 499 m := reflect.New(f.mi.GoReflectType.Elem()).Interface() 500 mp := pointerOfIface(m) 501 o, err := f.mi.unmarshalPointer(v, mp, 0, opts) 502 if err != nil { 503 return out, err 504 } 505 p.AppendPointerSlice(mp) 506 out.n = n 507 out.initialized = o.initialized 508 return out, nil 509} 510 511func isInitMessageSliceInfo(p pointer, f *coderFieldInfo) error { 512 s := p.PointerSlice() 513 for _, v := range s { 514 if err := f.mi.checkInitializedPointer(v); err != nil { 515 return err 516 } 517 } 518 return nil 519} 520 521func sizeMessageSlice(p pointer, goType reflect.Type, tagsize int, _ marshalOptions) int { 522 s := p.PointerSlice() 523 n := 0 524 for _, v := range s { 525 m := asMessage(v.AsValueOf(goType.Elem())) 526 n += protowire.SizeBytes(proto.Size(m)) + tagsize 527 } 528 return n 529} 530 531func appendMessageSlice(b []byte, p pointer, wiretag uint64, goType reflect.Type, opts marshalOptions) ([]byte, error) { 532 s := p.PointerSlice() 533 var err error 534 for _, v := range s { 535 m := asMessage(v.AsValueOf(goType.Elem())) 536 b = protowire.AppendVarint(b, wiretag) 537 siz := proto.Size(m) 538 b = protowire.AppendVarint(b, uint64(siz)) 539 b, err = opts.Options().MarshalAppend(b, m) 540 if err != nil { 541 return b, err 542 } 543 } 544 return b, nil 545} 546 547func consumeMessageSlice(b []byte, p pointer, goType reflect.Type, wtyp protowire.Type, opts unmarshalOptions) (out unmarshalOutput, err error) { 548 if wtyp != protowire.BytesType { 549 return out, errUnknown 550 } 551 v, n := protowire.ConsumeBytes(b) 552 if n < 0 { 553 return out, protowire.ParseError(n) 554 } 555 mp := reflect.New(goType.Elem()) 556 o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{ 557 Buf: v, 558 Message: asMessage(mp).ProtoReflect(), 559 }) 560 if err != nil { 561 return out, err 562 } 563 p.AppendPointerSlice(pointerOfValue(mp)) 564 out.n = n 565 out.initialized = o.Flags&piface.UnmarshalInitialized != 0 566 return out, nil 567} 568 569func isInitMessageSlice(p pointer, goType reflect.Type) error { 570 s := p.PointerSlice() 571 for _, v := range s { 572 m := asMessage(v.AsValueOf(goType.Elem())) 573 if err := proto.CheckInitialized(m); err != nil { 574 return err 575 } 576 } 577 return nil 578} 579 580// Slices of messages 581 582func sizeMessageSliceValue(listv pref.Value, tagsize int, opts marshalOptions) int { 583 list := listv.List() 584 n := 0 585 for i, llen := 0, list.Len(); i < llen; i++ { 586 m := list.Get(i).Message().Interface() 587 n += protowire.SizeBytes(proto.Size(m)) + tagsize 588 } 589 return n 590} 591 592func appendMessageSliceValue(b []byte, listv pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { 593 list := listv.List() 594 mopts := opts.Options() 595 for i, llen := 0, list.Len(); i < llen; i++ { 596 m := list.Get(i).Message().Interface() 597 b = protowire.AppendVarint(b, wiretag) 598 siz := proto.Size(m) 599 b = protowire.AppendVarint(b, uint64(siz)) 600 var err error 601 b, err = mopts.MarshalAppend(b, m) 602 if err != nil { 603 return b, err 604 } 605 } 606 return b, nil 607} 608 609func consumeMessageSliceValue(b []byte, listv pref.Value, _ protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ pref.Value, out unmarshalOutput, err error) { 610 list := listv.List() 611 if wtyp != protowire.BytesType { 612 return pref.Value{}, out, errUnknown 613 } 614 v, n := protowire.ConsumeBytes(b) 615 if n < 0 { 616 return pref.Value{}, out, protowire.ParseError(n) 617 } 618 m := list.NewElement() 619 o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{ 620 Buf: v, 621 Message: m.Message(), 622 }) 623 if err != nil { 624 return pref.Value{}, out, err 625 } 626 list.Append(m) 627 out.n = n 628 out.initialized = o.Flags&piface.UnmarshalInitialized != 0 629 return listv, out, nil 630} 631 632func isInitMessageSliceValue(listv pref.Value) error { 633 list := listv.List() 634 for i, llen := 0, list.Len(); i < llen; i++ { 635 m := list.Get(i).Message().Interface() 636 if err := proto.CheckInitialized(m); err != nil { 637 return err 638 } 639 } 640 return nil 641} 642 643var coderMessageSliceValue = valueCoderFuncs{ 644 size: sizeMessageSliceValue, 645 marshal: appendMessageSliceValue, 646 unmarshal: consumeMessageSliceValue, 647 isInit: isInitMessageSliceValue, 648 merge: mergeMessageListValue, 649} 650 651func sizeGroupSliceValue(listv pref.Value, tagsize int, opts marshalOptions) int { 652 list := listv.List() 653 n := 0 654 for i, llen := 0, list.Len(); i < llen; i++ { 655 m := list.Get(i).Message().Interface() 656 n += 2*tagsize + proto.Size(m) 657 } 658 return n 659} 660 661func appendGroupSliceValue(b []byte, listv pref.Value, wiretag uint64, opts marshalOptions) ([]byte, error) { 662 list := listv.List() 663 mopts := opts.Options() 664 for i, llen := 0, list.Len(); i < llen; i++ { 665 m := list.Get(i).Message().Interface() 666 b = protowire.AppendVarint(b, wiretag) // start group 667 var err error 668 b, err = mopts.MarshalAppend(b, m) 669 if err != nil { 670 return b, err 671 } 672 b = protowire.AppendVarint(b, wiretag+1) // end group 673 } 674 return b, nil 675} 676 677func consumeGroupSliceValue(b []byte, listv pref.Value, num protowire.Number, wtyp protowire.Type, opts unmarshalOptions) (_ pref.Value, out unmarshalOutput, err error) { 678 list := listv.List() 679 if wtyp != protowire.StartGroupType { 680 return pref.Value{}, out, errUnknown 681 } 682 b, n := protowire.ConsumeGroup(num, b) 683 if n < 0 { 684 return pref.Value{}, out, protowire.ParseError(n) 685 } 686 m := list.NewElement() 687 o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{ 688 Buf: b, 689 Message: m.Message(), 690 }) 691 if err != nil { 692 return pref.Value{}, out, err 693 } 694 list.Append(m) 695 out.n = n 696 out.initialized = o.Flags&piface.UnmarshalInitialized != 0 697 return listv, out, nil 698} 699 700var coderGroupSliceValue = valueCoderFuncs{ 701 size: sizeGroupSliceValue, 702 marshal: appendGroupSliceValue, 703 unmarshal: consumeGroupSliceValue, 704 isInit: isInitMessageSliceValue, 705 merge: mergeMessageListValue, 706} 707 708func makeGroupSliceFieldCoder(fd pref.FieldDescriptor, ft reflect.Type) pointerCoderFuncs { 709 num := fd.Number() 710 if mi := getMessageInfo(ft); mi != nil { 711 funcs := pointerCoderFuncs{ 712 size: sizeGroupSliceInfo, 713 marshal: appendGroupSliceInfo, 714 unmarshal: consumeGroupSliceInfo, 715 merge: mergeMessageSlice, 716 } 717 if needsInitCheck(mi.Desc) { 718 funcs.isInit = isInitMessageSliceInfo 719 } 720 return funcs 721 } 722 return pointerCoderFuncs{ 723 size: func(p pointer, f *coderFieldInfo, opts marshalOptions) int { 724 return sizeGroupSlice(p, ft, f.tagsize, opts) 725 }, 726 marshal: func(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { 727 return appendGroupSlice(b, p, f.wiretag, ft, opts) 728 }, 729 unmarshal: func(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) { 730 return consumeGroupSlice(b, p, num, wtyp, ft, opts) 731 }, 732 isInit: func(p pointer, f *coderFieldInfo) error { 733 return isInitMessageSlice(p, ft) 734 }, 735 merge: mergeMessageSlice, 736 } 737} 738 739func sizeGroupSlice(p pointer, messageType reflect.Type, tagsize int, _ marshalOptions) int { 740 s := p.PointerSlice() 741 n := 0 742 for _, v := range s { 743 m := asMessage(v.AsValueOf(messageType.Elem())) 744 n += 2*tagsize + proto.Size(m) 745 } 746 return n 747} 748 749func appendGroupSlice(b []byte, p pointer, wiretag uint64, messageType reflect.Type, opts marshalOptions) ([]byte, error) { 750 s := p.PointerSlice() 751 var err error 752 for _, v := range s { 753 m := asMessage(v.AsValueOf(messageType.Elem())) 754 b = protowire.AppendVarint(b, wiretag) // start group 755 b, err = opts.Options().MarshalAppend(b, m) 756 if err != nil { 757 return b, err 758 } 759 b = protowire.AppendVarint(b, wiretag+1) // end group 760 } 761 return b, nil 762} 763 764func consumeGroupSlice(b []byte, p pointer, num protowire.Number, wtyp protowire.Type, goType reflect.Type, opts unmarshalOptions) (out unmarshalOutput, err error) { 765 if wtyp != protowire.StartGroupType { 766 return out, errUnknown 767 } 768 b, n := protowire.ConsumeGroup(num, b) 769 if n < 0 { 770 return out, protowire.ParseError(n) 771 } 772 mp := reflect.New(goType.Elem()) 773 o, err := opts.Options().UnmarshalState(piface.UnmarshalInput{ 774 Buf: b, 775 Message: asMessage(mp).ProtoReflect(), 776 }) 777 if err != nil { 778 return out, err 779 } 780 p.AppendPointerSlice(pointerOfValue(mp)) 781 out.n = n 782 out.initialized = o.Flags&piface.UnmarshalInitialized != 0 783 return out, nil 784} 785 786func sizeGroupSliceInfo(p pointer, f *coderFieldInfo, opts marshalOptions) int { 787 s := p.PointerSlice() 788 n := 0 789 for _, v := range s { 790 n += 2*f.tagsize + f.mi.sizePointer(v, opts) 791 } 792 return n 793} 794 795func appendGroupSliceInfo(b []byte, p pointer, f *coderFieldInfo, opts marshalOptions) ([]byte, error) { 796 s := p.PointerSlice() 797 var err error 798 for _, v := range s { 799 b = protowire.AppendVarint(b, f.wiretag) // start group 800 b, err = f.mi.marshalAppendPointer(b, v, opts) 801 if err != nil { 802 return b, err 803 } 804 b = protowire.AppendVarint(b, f.wiretag+1) // end group 805 } 806 return b, nil 807} 808 809func consumeGroupSliceInfo(b []byte, p pointer, wtyp protowire.Type, f *coderFieldInfo, opts unmarshalOptions) (unmarshalOutput, error) { 810 if wtyp != protowire.StartGroupType { 811 return unmarshalOutput{}, errUnknown 812 } 813 m := reflect.New(f.mi.GoReflectType.Elem()).Interface() 814 mp := pointerOfIface(m) 815 out, err := f.mi.unmarshalPointer(b, mp, f.num, opts) 816 if err != nil { 817 return out, err 818 } 819 p.AppendPointerSlice(mp) 820 return out, nil 821} 822 823func asMessage(v reflect.Value) pref.ProtoMessage { 824 if m, ok := v.Interface().(pref.ProtoMessage); ok { 825 return m 826 } 827 return legacyWrapMessage(v).Interface() 828} 829