1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970
|
// Copyright 2020 The gVisor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package wire contains a few basic types that can be composed to serialize
// graph information for the state package. This package defines the wire
// protocol.
//
// Note that these types are careful about how they implement the relevant
// interfaces (either value receiver or pointer receiver), so that native-sized
// types, such as integers and simple pointers, can fit inside the interface
// object.
//
// This package also uses panic as control flow, so called should be careful to
// wrap calls in appropriate handlers.
//
// Testing for this package is driven by the state test package.
package wire
import (
"fmt"
"io"
"math"
"gvisor.dev/gvisor/pkg/gohacks"
)
// Reader is the required reader interface.
type Reader interface {
io.Reader
ReadByte() (byte, error)
}
// Writer is the required writer interface.
type Writer interface {
io.Writer
WriteByte(byte) error
}
// readFull is a utility. The equivalent is not needed for Write, but the API
// contract dictates that it must always complete all bytes given or return an
// error.
func readFull(r io.Reader, p []byte) {
for done := 0; done < len(p); {
n, err := r.Read(p[done:])
done += n
if n == 0 && err != nil {
panic(err)
}
}
}
// Object is a generic object.
type Object interface {
// save saves the given object.
//
// Panic is used for error control flow.
save(Writer)
// load loads a new object of the given type.
//
// Panic is used for error control flow.
load(Reader) Object
}
// Bool is a boolean.
type Bool bool
// loadBool loads an object of type Bool.
func loadBool(r Reader) Bool {
b := loadUint(r)
return Bool(b == 1)
}
// save implements Object.save.
func (b Bool) save(w Writer) {
var v Uint
if b {
v = 1
} else {
v = 0
}
v.save(w)
}
// load implements Object.load.
func (Bool) load(r Reader) Object { return loadBool(r) }
// Int is a signed integer.
//
// This uses varint encoding.
type Int int64
// loadInt loads an object of type Int.
func loadInt(r Reader) Int {
u := loadUint(r)
x := Int(u >> 1)
if u&1 != 0 {
x = ^x
}
return x
}
// save implements Object.save.
func (i Int) save(w Writer) {
u := Uint(i) << 1
if i < 0 {
u = ^u
}
u.save(w)
}
// load implements Object.load.
func (Int) load(r Reader) Object { return loadInt(r) }
// Uint is an unsigned integer.
type Uint uint64
// loadUint loads an object of type Uint.
func loadUint(r Reader) Uint {
var (
u Uint
s uint
)
for i := 0; i <= 9; i++ {
b, err := r.ReadByte()
if err != nil {
panic(err)
}
if b < 0x80 {
if i == 9 && b > 1 {
panic("overflow")
}
u |= Uint(b) << s
return u
}
u |= Uint(b&0x7f) << s
s += 7
}
panic("unreachable")
}
// save implements Object.save.
func (u Uint) save(w Writer) {
for u >= 0x80 {
if err := w.WriteByte(byte(u) | 0x80); err != nil {
panic(err)
}
u >>= 7
}
if err := w.WriteByte(byte(u)); err != nil {
panic(err)
}
}
// load implements Object.load.
func (Uint) load(r Reader) Object { return loadUint(r) }
// Float32 is a 32-bit floating point number.
type Float32 float32
// loadFloat32 loads an object of type Float32.
func loadFloat32(r Reader) Float32 {
n := loadUint(r)
return Float32(math.Float32frombits(uint32(n)))
}
// save implements Object.save.
func (f Float32) save(w Writer) {
n := Uint(math.Float32bits(float32(f)))
n.save(w)
}
// load implements Object.load.
func (Float32) load(r Reader) Object { return loadFloat32(r) }
// Float64 is a 64-bit floating point number.
type Float64 float64
// loadFloat64 loads an object of type Float64.
func loadFloat64(r Reader) Float64 {
n := loadUint(r)
return Float64(math.Float64frombits(uint64(n)))
}
// save implements Object.save.
func (f Float64) save(w Writer) {
n := Uint(math.Float64bits(float64(f)))
n.save(w)
}
// load implements Object.load.
func (Float64) load(r Reader) Object { return loadFloat64(r) }
// Complex64 is a 64-bit complex number.
type Complex64 complex128
// loadComplex64 loads an object of type Complex64.
func loadComplex64(r Reader) Complex64 {
re := loadFloat32(r)
im := loadFloat32(r)
return Complex64(complex(float32(re), float32(im)))
}
// save implements Object.save.
func (c *Complex64) save(w Writer) {
re := Float32(real(*c))
im := Float32(imag(*c))
re.save(w)
im.save(w)
}
// load implements Object.load.
func (*Complex64) load(r Reader) Object {
c := loadComplex64(r)
return &c
}
// Complex128 is a 128-bit complex number.
type Complex128 complex128
// loadComplex128 loads an object of type Complex128.
func loadComplex128(r Reader) Complex128 {
re := loadFloat64(r)
im := loadFloat64(r)
return Complex128(complex(float64(re), float64(im)))
}
// save implements Object.save.
func (c *Complex128) save(w Writer) {
re := Float64(real(*c))
im := Float64(imag(*c))
re.save(w)
im.save(w)
}
// load implements Object.load.
func (*Complex128) load(r Reader) Object {
c := loadComplex128(r)
return &c
}
// String is a string.
type String string
// loadString loads an object of type String.
func loadString(r Reader) String {
l := loadUint(r)
p := make([]byte, l)
readFull(r, p)
return String(gohacks.StringFromImmutableBytes(p))
}
// save implements Object.save.
func (s *String) save(w Writer) {
l := Uint(len(*s))
l.save(w)
p := gohacks.ImmutableBytesFromString(string(*s))
_, err := w.Write(p) // Must write all bytes.
if err != nil {
panic(err)
}
}
// load implements Object.load.
func (*String) load(r Reader) Object {
s := loadString(r)
return &s
}
// Dot is a kind of reference: one of Index and FieldName.
type Dot interface {
isDot()
}
// Index is a reference resolution.
type Index uint32
func (Index) isDot() {}
// FieldName is a reference resolution.
type FieldName string
func (*FieldName) isDot() {}
// Ref is a reference to an object.
type Ref struct {
// Root is the root object.
Root Uint
// Dots is the set of traversals required from the Root object above.
// Note that this will be stored in reverse order for efficiency.
Dots []Dot
// Type is the base type for the root object. This is non-nil iff Dots
// is non-zero length (that is, this is a complex reference). This is
// not *strictly* necessary, but can be used to simplify decoding.
Type TypeSpec
}
// loadRef loads an object of type Ref (abstract).
func loadRef(r Reader) Ref {
ref := Ref{
Root: loadUint(r),
}
l := loadUint(r)
ref.Dots = make([]Dot, l)
for i := 0; i < int(l); i++ {
// Disambiguate between an Index (non-negative) and a field
// name (negative). This does some space and avoids a dedicate
// loadDot function. See Ref.save for the other side.
d := loadInt(r)
if d >= 0 {
ref.Dots[i] = Index(d)
continue
}
p := make([]byte, -d)
readFull(r, p)
fieldName := FieldName(gohacks.StringFromImmutableBytes(p))
ref.Dots[i] = &fieldName
}
if l != 0 {
// Only if dots is non-zero.
ref.Type = loadTypeSpec(r)
}
return ref
}
// save implements Object.save.
func (r *Ref) save(w Writer) {
r.Root.save(w)
l := Uint(len(r.Dots))
l.save(w)
for _, d := range r.Dots {
// See LoadRef. We use non-negative numbers to encode Index
// objects and negative numbers to encode field lengths.
switch x := d.(type) {
case Index:
i := Int(x)
i.save(w)
case *FieldName:
d := Int(-len(*x))
d.save(w)
p := gohacks.ImmutableBytesFromString(string(*x))
if _, err := w.Write(p); err != nil {
panic(err)
}
default:
panic("unknown dot implementation")
}
}
if l != 0 {
// See above.
saveTypeSpec(w, r.Type)
}
}
// load implements Object.load.
func (*Ref) load(r Reader) Object {
ref := loadRef(r)
return &ref
}
// Nil is a primitive zero value of any type.
type Nil struct{}
// loadNil loads an object of type Nil.
func loadNil(r Reader) Nil {
return Nil{}
}
// save implements Object.save.
func (Nil) save(w Writer) {}
// load implements Object.load.
func (Nil) load(r Reader) Object { return loadNil(r) }
// Slice is a slice value.
type Slice struct {
Length Uint
Capacity Uint
Ref Ref
}
// loadSlice loads an object of type Slice.
func loadSlice(r Reader) Slice {
return Slice{
Length: loadUint(r),
Capacity: loadUint(r),
Ref: loadRef(r),
}
}
// save implements Object.save.
func (s *Slice) save(w Writer) {
s.Length.save(w)
s.Capacity.save(w)
s.Ref.save(w)
}
// load implements Object.load.
func (*Slice) load(r Reader) Object {
s := loadSlice(r)
return &s
}
// Array is an array value.
type Array struct {
Contents []Object
}
// loadArray loads an object of type Array.
func loadArray(r Reader) Array {
l := loadUint(r)
if l == 0 {
// Note that there isn't a single object available to encode
// the type of, so we need this additional branch.
return Array{}
}
// All the objects here have the same type, so use dynamic dispatch
// only once. All other objects will automatically take the same type
// as the first object.
contents := make([]Object, l)
v := Load(r)
contents[0] = v
for i := 1; i < int(l); i++ {
contents[i] = v.load(r)
}
return Array{
Contents: contents,
}
}
// save implements Object.save.
func (a *Array) save(w Writer) {
l := Uint(len(a.Contents))
l.save(w)
if l == 0 {
// See LoadArray.
return
}
// See above.
Save(w, a.Contents[0])
for i := 1; i < int(l); i++ {
a.Contents[i].save(w)
}
}
// load implements Object.load.
func (*Array) load(r Reader) Object {
a := loadArray(r)
return &a
}
// Map is a map value.
type Map struct {
Keys []Object
Values []Object
}
// loadMap loads an object of type Map.
func loadMap(r Reader) Map {
l := loadUint(r)
if l == 0 {
// See LoadArray.
return Map{}
}
// See type dispatch notes in Array.
keys := make([]Object, l)
values := make([]Object, l)
k := Load(r)
v := Load(r)
keys[0] = k
values[0] = v
for i := 1; i < int(l); i++ {
keys[i] = k.load(r)
values[i] = v.load(r)
}
return Map{
Keys: keys,
Values: values,
}
}
// save implements Object.save.
func (m *Map) save(w Writer) {
l := Uint(len(m.Keys))
if int(l) != len(m.Values) {
panic(fmt.Sprintf("mismatched keys (%d) Aand values (%d)", len(m.Keys), len(m.Values)))
}
l.save(w)
if l == 0 {
// See LoadArray.
return
}
// See above.
Save(w, m.Keys[0])
Save(w, m.Values[0])
for i := 1; i < int(l); i++ {
m.Keys[i].save(w)
m.Values[i].save(w)
}
}
// load implements Object.load.
func (*Map) load(r Reader) Object {
m := loadMap(r)
return &m
}
// TypeSpec is a type dereference.
type TypeSpec interface {
isTypeSpec()
}
// TypeID is a concrete type ID.
type TypeID Uint
func (TypeID) isTypeSpec() {}
// TypeSpecPointer is a pointer type.
type TypeSpecPointer struct {
Type TypeSpec
}
func (*TypeSpecPointer) isTypeSpec() {}
// TypeSpecArray is an array type.
type TypeSpecArray struct {
Count Uint
Type TypeSpec
}
func (*TypeSpecArray) isTypeSpec() {}
// TypeSpecSlice is a slice type.
type TypeSpecSlice struct {
Type TypeSpec
}
func (*TypeSpecSlice) isTypeSpec() {}
// TypeSpecMap is a map type.
type TypeSpecMap struct {
Key TypeSpec
Value TypeSpec
}
func (*TypeSpecMap) isTypeSpec() {}
// TypeSpecNil is an empty type.
type TypeSpecNil struct{}
func (TypeSpecNil) isTypeSpec() {}
// TypeSpec types.
//
// These use a distinct encoding on the wire, as they are used only in the
// interface object. They are decoded through the dedicated loadTypeSpec and
// saveTypeSpec functions.
const (
typeSpecTypeID Uint = iota
typeSpecPointer
typeSpecArray
typeSpecSlice
typeSpecMap
typeSpecNil
)
// loadTypeSpec loads TypeSpec values.
func loadTypeSpec(r Reader) TypeSpec {
switch hdr := loadUint(r); hdr {
case typeSpecTypeID:
return TypeID(loadUint(r))
case typeSpecPointer:
return &TypeSpecPointer{
Type: loadTypeSpec(r),
}
case typeSpecArray:
return &TypeSpecArray{
Count: loadUint(r),
Type: loadTypeSpec(r),
}
case typeSpecSlice:
return &TypeSpecSlice{
Type: loadTypeSpec(r),
}
case typeSpecMap:
return &TypeSpecMap{
Key: loadTypeSpec(r),
Value: loadTypeSpec(r),
}
case typeSpecNil:
return TypeSpecNil{}
default:
// This is not a valid stream?
panic(fmt.Errorf("unknown header: %d", hdr))
}
}
// saveTypeSpec saves TypeSpec values.
func saveTypeSpec(w Writer, t TypeSpec) {
switch x := t.(type) {
case TypeID:
typeSpecTypeID.save(w)
Uint(x).save(w)
case *TypeSpecPointer:
typeSpecPointer.save(w)
saveTypeSpec(w, x.Type)
case *TypeSpecArray:
typeSpecArray.save(w)
x.Count.save(w)
saveTypeSpec(w, x.Type)
case *TypeSpecSlice:
typeSpecSlice.save(w)
saveTypeSpec(w, x.Type)
case *TypeSpecMap:
typeSpecMap.save(w)
saveTypeSpec(w, x.Key)
saveTypeSpec(w, x.Value)
case TypeSpecNil:
typeSpecNil.save(w)
default:
// This should not happen?
panic(fmt.Errorf("unknown type %T", t))
}
}
// Interface is an interface value.
type Interface struct {
Type TypeSpec
Value Object
}
// loadInterface loads an object of type Interface.
func loadInterface(r Reader) Interface {
return Interface{
Type: loadTypeSpec(r),
Value: Load(r),
}
}
// save implements Object.save.
func (i *Interface) save(w Writer) {
saveTypeSpec(w, i.Type)
Save(w, i.Value)
}
// load implements Object.load.
func (*Interface) load(r Reader) Object {
i := loadInterface(r)
return &i
}
// Type is type information.
type Type struct {
Name string
Fields []string
}
// loadType loads an object of type Type.
func loadType(r Reader) Type {
name := string(loadString(r))
l := loadUint(r)
fields := make([]string, l)
for i := 0; i < int(l); i++ {
fields[i] = string(loadString(r))
}
return Type{
Name: name,
Fields: fields,
}
}
// save implements Object.save.
func (t *Type) save(w Writer) {
s := String(t.Name)
s.save(w)
l := Uint(len(t.Fields))
l.save(w)
for i := 0; i < int(l); i++ {
s := String(t.Fields[i])
s.save(w)
}
}
// load implements Object.load.
func (*Type) load(r Reader) Object {
t := loadType(r)
return &t
}
// multipleObjects is a special type for serializing multiple objects.
type multipleObjects []Object
// loadMultipleObjects loads a series of objects.
func loadMultipleObjects(r Reader) multipleObjects {
l := loadUint(r)
m := make(multipleObjects, l)
for i := 0; i < int(l); i++ {
m[i] = Load(r)
}
return m
}
// save implements Object.save.
func (m *multipleObjects) save(w Writer) {
l := Uint(len(*m))
l.save(w)
for i := 0; i < int(l); i++ {
Save(w, (*m)[i])
}
}
// load implements Object.load.
func (*multipleObjects) load(r Reader) Object {
m := loadMultipleObjects(r)
return &m
}
// noObjects represents no objects.
type noObjects struct{}
// loadNoObjects loads a sentinel.
func loadNoObjects(r Reader) noObjects { return noObjects{} }
// save implements Object.save.
func (noObjects) save(w Writer) {}
// load implements Object.load.
func (noObjects) load(r Reader) Object { return loadNoObjects(r) }
// Struct is a basic composite value.
type Struct struct {
TypeID TypeID
fields Object // Optionally noObjects or *multipleObjects.
}
// Field returns a pointer to the given field slot.
//
// This must be called after Alloc.
func (s *Struct) Field(i int) *Object {
if fields, ok := s.fields.(*multipleObjects); ok {
return &((*fields)[i])
}
if _, ok := s.fields.(noObjects); ok {
// Alloc may be optionally called; can't call twice.
panic("Field called inappropriately, wrong Alloc?")
}
return &s.fields
}
// Alloc allocates the given number of fields.
//
// This must be called before Add and Save.
//
// Precondition: slots must be positive.
func (s *Struct) Alloc(slots int) {
switch {
case slots == 0:
s.fields = noObjects{}
case slots == 1:
// Leave it alone.
case slots > 1:
fields := make(multipleObjects, slots)
s.fields = &fields
default:
// Violates precondition.
panic(fmt.Sprintf("Alloc called with negative slots %d?", slots))
}
}
// Fields returns the number of fields.
func (s *Struct) Fields() int {
switch x := s.fields.(type) {
case *multipleObjects:
return len(*x)
case noObjects:
return 0
default:
return 1
}
}
// loadStruct loads an object of type Struct.
func loadStruct(r Reader) Struct {
return Struct{
TypeID: TypeID(loadUint(r)),
fields: Load(r),
}
}
// save implements Object.save.
//
// Precondition: Alloc must have been called, and the fields all filled in
// appropriately. See Alloc and Add for more details.
func (s *Struct) save(w Writer) {
Uint(s.TypeID).save(w)
Save(w, s.fields)
}
// load implements Object.load.
func (*Struct) load(r Reader) Object {
s := loadStruct(r)
return &s
}
// Object types.
//
// N.B. Be careful about changing the order or introducing new elements in the
// middle here. This is part of the wire format and shouldn't change.
const (
typeBool Uint = iota
typeInt
typeUint
typeFloat32
typeFloat64
typeNil
typeRef
typeString
typeSlice
typeArray
typeMap
typeStruct
typeNoObjects
typeMultipleObjects
typeInterface
typeComplex64
typeComplex128
typeType
)
// Save saves the given object.
//
// +checkescape all
//
// N.B. This function will panic on error.
func Save(w Writer, obj Object) {
switch x := obj.(type) {
case Bool:
typeBool.save(w)
x.save(w)
case Int:
typeInt.save(w)
x.save(w)
case Uint:
typeUint.save(w)
x.save(w)
case Float32:
typeFloat32.save(w)
x.save(w)
case Float64:
typeFloat64.save(w)
x.save(w)
case Nil:
typeNil.save(w)
x.save(w)
case *Ref:
typeRef.save(w)
x.save(w)
case *String:
typeString.save(w)
x.save(w)
case *Slice:
typeSlice.save(w)
x.save(w)
case *Array:
typeArray.save(w)
x.save(w)
case *Map:
typeMap.save(w)
x.save(w)
case *Struct:
typeStruct.save(w)
x.save(w)
case noObjects:
typeNoObjects.save(w)
x.save(w)
case *multipleObjects:
typeMultipleObjects.save(w)
x.save(w)
case *Interface:
typeInterface.save(w)
x.save(w)
case *Type:
typeType.save(w)
x.save(w)
case *Complex64:
typeComplex64.save(w)
x.save(w)
case *Complex128:
typeComplex128.save(w)
x.save(w)
default:
panic(fmt.Errorf("unknown type: %#v", obj))
}
}
// Load loads a new object.
//
// +checkescape all
//
// N.B. This function will panic on error.
func Load(r Reader) Object {
switch hdr := loadUint(r); hdr {
case typeBool:
return loadBool(r)
case typeInt:
return loadInt(r)
case typeUint:
return loadUint(r)
case typeFloat32:
return loadFloat32(r)
case typeFloat64:
return loadFloat64(r)
case typeNil:
return loadNil(r)
case typeRef:
return ((*Ref)(nil)).load(r) // Escapes.
case typeString:
return ((*String)(nil)).load(r) // Escapes.
case typeSlice:
return ((*Slice)(nil)).load(r) // Escapes.
case typeArray:
return ((*Array)(nil)).load(r) // Escapes.
case typeMap:
return ((*Map)(nil)).load(r) // Escapes.
case typeStruct:
return ((*Struct)(nil)).load(r) // Escapes.
case typeNoObjects: // Special for struct.
return loadNoObjects(r)
case typeMultipleObjects: // Special for struct.
return ((*multipleObjects)(nil)).load(r) // Escapes.
case typeInterface:
return ((*Interface)(nil)).load(r) // Escapes.
case typeComplex64:
return ((*Complex64)(nil)).load(r) // Escapes.
case typeComplex128:
return ((*Complex128)(nil)).load(r) // Escapes.
case typeType:
return ((*Type)(nil)).load(r) // Escapes.
default:
// This is not a valid stream?
panic(fmt.Errorf("unknown header: %d", hdr))
}
}
// LoadUint loads a single unsigned integer.
//
// N.B. This function will panic on error.
func LoadUint(r Reader) uint64 {
return uint64(loadUint(r))
}
// SaveUint saves a single unsigned integer.
//
// N.B. This function will panic on error.
func SaveUint(w Writer, v uint64) {
Uint(v).save(w)
}
|